[opentitantool] Make the verilator startup time configurable
1. Add a `--verilator_timeout` parameter to control how long to wait
for the verilator subprocess to start. Set the default value to
60 seconds.
Signed-off-by: Chris Frantz <cfrantz@google.com>
diff --git a/sw/host/opentitanlib/src/backend/verilator.rs b/sw/host/opentitanlib/src/backend/verilator.rs
index 9f74395..cb72dc5 100644
--- a/sw/host/opentitanlib/src/backend/verilator.rs
+++ b/sw/host/opentitanlib/src/backend/verilator.rs
@@ -2,10 +2,13 @@
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
+use anyhow::Result;
+use humantime::parse_duration;
+use std::time::Duration;
+use structopt::StructOpt;
+
use crate::transport::verilator::{Options, Verilator};
use crate::transport::Transport;
-use anyhow::Result;
-use structopt::StructOpt;
#[derive(Debug, StructOpt)]
pub struct VerilatorOpts {
@@ -21,6 +24,9 @@
#[structopt(long, required = false)]
verilator_args: Vec<String>,
+
+ #[structopt(long, parse(try_from_str=parse_duration), default_value="60s", help = "Verilator startup timeout")]
+ verilator_timeout: Duration,
}
pub fn create(args: &VerilatorOpts) -> Result<Box<dyn Transport>> {
@@ -30,6 +36,7 @@
flash_image: args.verilator_flash.clone(),
otp_image: args.verilator_otp.clone(),
extra_args: args.verilator_args.clone(),
+ timeout: args.verilator_timeout.clone(),
};
Ok(Box::new(Verilator::from_options(options)?))
}
diff --git a/sw/host/opentitanlib/src/transport/verilator/subprocess.rs b/sw/host/opentitanlib/src/transport/verilator/subprocess.rs
index ae5ddfa..297988c 100644
--- a/sw/host/opentitanlib/src/transport/verilator/subprocess.rs
+++ b/sw/host/opentitanlib/src/transport/verilator/subprocess.rs
@@ -23,6 +23,8 @@
pub otp_image: String,
/// Any extra arguments to verilator.
pub extra_args: Vec<String>,
+ /// Timeout for starting verilator.
+ pub timeout: Duration,
}
pub struct Subprocess {
@@ -68,13 +70,12 @@
/// Finds a string within the verilator output.
/// It is assumed that the [`Regex`] `re` has exactly one capture group.
- pub fn find(&mut self, re: &Regex, timeout: Duration) -> Result<String> {
+ pub fn find(&mut self, re: &Regex, deadline: Instant) -> Result<String> {
// Regex captures_len: Capture group 0 is the full match. Subsequent
// capture groups are the individual capture groups in the regex.
// We expect only one user-specified capture group in the regex,
// and thus expect a capture length of two.
assert_eq!(re.captures_len(), 2);
- let deadline = Instant::now() + timeout;
while deadline > Instant::now() {
{
let a = self.accumulated_output.lock().unwrap();
@@ -108,6 +109,7 @@
flash_image: "".to_owned(),
otp_image: "".to_owned(),
extra_args: vec!["abc 123 def 456".to_owned()],
+ timeout: Duration::from_secs(5),
};
Subprocess::from_options(options)
}
@@ -116,7 +118,8 @@
fn test_find_regex() -> Result<()> {
let mut subprocess = echo_subprocess()?;
let regex = Regex::new("abc (.*) def")?;
- let found = subprocess.find(®ex, Duration::from_millis(5000))?;
+ let deadline = Instant::now() + Duration::from_secs(5);
+ let found = subprocess.find(®ex, deadline)?;
assert_eq!(found, "123");
Ok(())
}
diff --git a/sw/host/opentitanlib/src/transport/verilator/transport.rs b/sw/host/opentitanlib/src/transport/verilator/transport.rs
index e995da0..0ca0137 100644
--- a/sw/host/opentitanlib/src/transport/verilator/transport.rs
+++ b/sw/host/opentitanlib/src/transport/verilator/transport.rs
@@ -4,11 +4,10 @@
use anyhow::{ensure, Result};
use lazy_static::lazy_static;
-use log::info;
use regex::Regex;
use std::cell::RefCell;
use std::rc::Rc;
-use std::time::Duration;
+use std::time::Instant;
use crate::io::uart::Uart;
use crate::transport::verilator::subprocess::{Options, Subprocess};
@@ -45,17 +44,18 @@
Regex::new(r#"GPIO: FIFO pipes created at [^ ]+ \(read\) and ([^ ]+) \(write\) for 32-bit wide GPIO."#).unwrap();
}
+ let deadline = Instant::now() + options.timeout;
let mut subprocess = Subprocess::from_options(options)?;
- let gpio_rd = subprocess.find(&GPIO_RD, Duration::from_secs(5))?;
- let gpio_wr = subprocess.find(&GPIO_WR, Duration::from_secs(5))?;
- let uart = subprocess.find(&UART, Duration::from_secs(5))?;
- let spi = subprocess.find(&SPI, Duration::from_secs(5))?;
+ let gpio_rd = subprocess.find(&GPIO_RD, deadline)?;
+ let gpio_wr = subprocess.find(&GPIO_WR, deadline)?;
+ let uart = subprocess.find(&UART, deadline)?;
+ let spi = subprocess.find(&SPI, deadline)?;
- info!("Verilator started with the following interaces:");
- info!("gpio_read = {}", gpio_rd);
- info!("gpio_write = {}", gpio_wr);
- info!("uart = {}", uart);
- info!("spi = {}", spi);
+ log::info!("Verilator started with the following interaces:");
+ log::info!("gpio_read = {}", gpio_rd);
+ log::info!("gpio_write = {}", gpio_wr);
+ log::info!("uart = {}", uart);
+ log::info!("spi = {}", spi);
Ok(Verilator {
subprocess: Some(subprocess),
uart_file: uart,