From 741825a07d8a0f283f40324044ca970c4bdd5e1f Mon Sep 17 00:00:00 2001 From: Amaury Pouly Date: Wed, 12 Jun 2024 09:38:54 +0000 Subject: [PATCH] [otlib,gpio_mon] Decouple GpionMon and Waves more Signed-off-by: Amaury Pouly --- .../src/test_utils/gpio_monitor.rs | 96 ++++++++++++++----- .../chip/sysrst_ctrl/sysrst_ctrl_ec_rst_l.rs | 4 +- 2 files changed, 76 insertions(+), 24 deletions(-) diff --git a/sw/host/opentitanlib/src/test_utils/gpio_monitor.rs b/sw/host/opentitanlib/src/test_utils/gpio_monitor.rs index 8a43f3c210c80..bb3fe5148461b 100644 --- a/sw/host/opentitanlib/src/test_utils/gpio_monitor.rs +++ b/sw/host/opentitanlib/src/test_utils/gpio_monitor.rs @@ -35,6 +35,8 @@ pub struct Waves { initial_levels: Vec, // Initial timestamp. initial_timestamp: u64, + // Final timestamp. + final_timestamp: u64, // Clock resolution. resolution: u64, // Complete trace since the beginning. @@ -84,24 +86,20 @@ impl<'a> GpioMon<'a> { }) } - pub fn timestamp_ns(&self, timestamp: u64) -> u64 { - timestamp * 1000000000u64 / self.waves.resolution + pub fn timestamp_to_ns(&self, timestamp: u64) -> u64 { + self.waves.timestamp_to_ns(timestamp) } pub fn signal_index(&self, name: &str) -> Option { - self.waves.pin_names.iter().position(|x| x == name) + self.waves.signal_index(name) } pub fn initial_levels(&self) -> Vec { - self.waves.initial_levels.clone() - } - - pub fn all_events(&self) -> Vec { - self.waves.events.clone() + self.waves.initial_levels() } - pub fn timestamp_to_ns(&self, timestamp: u64) -> u64 { - (timestamp - self.waves.initial_timestamp) * 1000000000u64 / self.waves.resolution + pub fn all_events(&self) -> impl Iterator { + self.waves.all_events() } pub fn read(&mut self, continue_monitoring: bool) -> Result> { @@ -111,12 +109,13 @@ impl<'a> GpioMon<'a> { ); let gpio_pins = self.transport.gpio_pins(&self.pins)?; let gpios_pins = &gpio_pins.iter().map(Rc::borrow).collect::>(); - let events = self + let resp = self .monitor .monitoring_read(gpios_pins, continue_monitoring)?; self.still_monitoring = continue_monitoring; - self.waves.add_events(&events.events); - Ok(events.events) + self.waves.add_events(&resp.events); + self.waves.final_timestamp = resp.timestamp; + Ok(resp.events) } pub fn dump_on_drop(&mut self, dump_on_drop: bool) { @@ -128,6 +127,25 @@ impl<'a> GpioMon<'a> { } } +/// Consume a GpioMon and return a copy of the waves. If the monitor +/// is still active, this function will try to stop it (and return an +/// error if this is not possible). +impl TryFrom> for Waves { + type Error = anyhow::Error; + + fn try_from(mut gpio_mon: GpioMon<'_>) -> Result { + if gpio_mon.still_monitoring { + let _ = gpio_mon.read(false)?; + } + gpio_mon.dump_on_drop = false; + let waves = std::mem::replace( + &mut gpio_mon.waves, + Waves::new(Vec::new(), Vec::new(), 0, 1), + ); + Ok(waves) + } +} + impl Waves { pub fn new( pin_names: Vec, @@ -139,11 +157,19 @@ impl Waves { pin_names, initial_levels, initial_timestamp, + final_timestamp: initial_timestamp, resolution, events: vec![], } } + // Returns the index of the signal created. + pub fn add_signal(&mut self, name: String, initial_level: bool) -> usize { + self.pin_names.push(name); + self.initial_levels.push(initial_level); + self.pin_names.len() - 1 + } + pub fn add_event(&mut self, event: MonitoringEvent) { self.events.push(event) } @@ -152,6 +178,35 @@ impl Waves { self.events.extend_from_slice(event) } + pub fn signal_index(&self, name: &str) -> Option { + self.pin_names.iter().position(|x| x == name) + } + + pub fn initial_levels(&self) -> Vec { + self.initial_levels.clone() + } + + pub fn set_final_timestamp(&mut self, ts: u64) { + self.final_timestamp = ts; + } + + pub fn timestamp_to_ns(&self, timestamp: u64) -> u64 { + (timestamp - self.initial_timestamp) * 1000000000u64 / self.resolution + } + + pub fn ns_to_timestamp(&self, ns: u64) -> u64 { + self.initial_timestamp + self.resolution * ns / 1000000000u64 + } + + pub fn all_events(&self) -> impl Iterator { + self.events.iter() + } + + pub fn sort_events(&mut self) { + self.events.sort_by(|a, b| a.timestamp.cmp(&b.timestamp)); + } + + // This function assumes that the events are sorted. pub fn dump_vcd(&self) -> String { const SYMBOLS: &[char] = &['!', '#', '$', '%', '&', '(', ')']; assert!(self.pin_names.len() < SYMBOLS.len()); @@ -171,19 +226,16 @@ impl Waves { vcd.push('\n'); for event in &self.events { - let ns = (event.timestamp - self.initial_timestamp) * 1000000000u64 / self.resolution; + let ns = self.timestamp_to_ns(event.timestamp); + let val = event.edge == Edge::Rising; vcd.push_str(&format!( "#{ns} {}{}\n", - if event.edge == Edge::Rising { 1 } else { 0 }, - SYMBOLS[event.signal_index as usize] + val as u8, SYMBOLS[event.signal_index as usize] )); } - // Add a final time to make sure that the last edge is visible. - vcd.push_str(&format!( - "#{}", - 1000 + (self.events.last().unwrap().timestamp - self.initial_timestamp) * 1000000000u64 - / self.resolution - )); + // Make sure that the final timestamp is after the last event. + let final_ts = std::cmp::max(self.events.last().unwrap().timestamp, self.final_timestamp); + vcd.push_str(&format!("#{}", self.timestamp_to_ns(final_ts),)); vcd } diff --git a/sw/host/tests/chip/sysrst_ctrl/sysrst_ctrl_ec_rst_l.rs b/sw/host/tests/chip/sysrst_ctrl/sysrst_ctrl_ec_rst_l.rs index 4bade1f027210..bbb287c24c48b 100644 --- a/sw/host/tests/chip/sysrst_ctrl/sysrst_ctrl_ec_rst_l.rs +++ b/sw/host/tests/chip/sysrst_ctrl/sysrst_ctrl_ec_rst_l.rs @@ -200,8 +200,8 @@ fn chip_sw_sysrst_ctrl_input(params: &Params) -> Result<()> { ensure!(first_index == gpio_mon.signal_index("ec_rst_l").unwrap() as u8); ensure!(second_index == gpio_mon.signal_index("ec_rst_l").unwrap() as u8); // Make sure the pulse width matches what we expect. - let pulse_width_us = (gpio_mon.timestamp_ns(rise_timestamp) - - gpio_mon.timestamp_ns(fall_timestamp)) + let pulse_width_us = (gpio_mon.timestamp_to_ns(rise_timestamp) + - gpio_mon.timestamp_to_ns(fall_timestamp)) / 1000; let delta = EC_RST_STRETCH_PULSE_WIDTH_USEC.abs_diff(pulse_width_us); log::info!("reset pulse width = {pulse_width_us} us, delta = {delta} us");