[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(&regex, Duration::from_millis(5000))?;
+        let deadline = Instant::now() + Duration::from_secs(5);
+        let found = subprocess.find(&regex, 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,