vj_sim/driver_counts.rs
1//! `$countdrivers` data (IEEE 1800-2023 D.2, Table D.1): per net bit, how
2//! many drivers are at 0, 1 and x (a driver at `z` is not counted). A net
3//! resolver records them next to its `%v` strengths (`vj_exec::nets`)
4//! under the net's strength key; a net no resolver runs for has at most one
5//! driver, so `sv_rt_net_drivers` reads its count off the net itself.
6
7use std::cell::RefCell;
8use std::collections::HashMap;
9
10/// A bit's driver counts: at 0, at 1, at x.
11pub type BitCounts = [u32; 3];
12
13/// The counts a net no `$countdrivers` meaning exists for records (a net in
14/// a bidirectional switch network): the call stops the run by name.
15pub const UNCOUNTED: BitCounts = [u32::MAX; 3];
16
17thread_local! {
18 /// Each net's per-bit counts (bit 0 first), by strength key. Per thread
19 /// like the runtime's other run state; emptied by
20 /// [`reset_driver_counts_for_new_run`].
21 static COUNTS: RefCell<HashMap<u64, Vec<BitCounts>>> = RefCell::default();
22 /// Each dumped port's per-bit fixture/DUT split, by side key.
23 static SIDES: RefCell<HashMap<u64, Vec<SideBit>>> = RefCell::default();
24}
25
26/// One bit of a net as the test fixture's drivers and the DUT's own drivers
27/// resolve it separately (`$dumpports`, LRM 21.7.4.3.2). Index 0 is the
28/// fixture side (drivers outside the dumped instance), index 1 the DUT side.
29#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
30pub struct SideBit {
31 /// The side's resolved possible states in the resolver's `Points`
32 /// encoding: bit 0 is `z`, bit `l` (1..=7) is 0 at strength level `l`,
33 /// bit `8 + l` is 1 at level `l`.
34 pub points: [u16; 2],
35 /// How many of the side's drivers are not at `z` on this bit.
36 pub active: [u8; 2],
37 /// Whether the side has any driver at all (connected).
38 pub present: [bool; 2],
39}
40
41/// Forgets every net's counts (the start of a run).
42pub fn reset_driver_counts_for_new_run() {
43 COUNTS.with(|c| c.borrow_mut().clear());
44 SIDES.with(|c| c.borrow_mut().clear());
45}
46
47/// Records the counts of net `key`.
48pub fn set_driver_counts(key: u64, counts: &[BitCounts]) {
49 COUNTS.with(|c| {
50 let mut m = c.borrow_mut();
51 match m.get_mut(&key) {
52 Some(v) if v.as_slice() == counts => {}
53 Some(v) => *v = counts.to_vec(),
54 None => {
55 m.insert(key, counts.to_vec());
56 }
57 }
58 });
59}
60
61/// The recorded counts of bit `bit` of net `key`.
62pub fn driver_counts_of(key: u64, bit: u32) -> Option<BitCounts> {
63 COUNTS.with(|c| {
64 c.borrow()
65 .get(&key)
66 .and_then(|v| v.get(bit as usize).copied())
67 })
68}
69
70/// Records the fixture/DUT split of the port whose side key is `key`.
71pub fn set_sides(key: u64, bits: &[SideBit]) {
72 SIDES.with(|c| {
73 c.borrow_mut().insert(key, bits.to_vec());
74 });
75}
76
77/// The recorded split of bit `bit` of the port with side key `key`.
78pub fn sides_of(key: u64, bit: u32) -> Option<SideBit> {
79 SIDES.with(|c| {
80 c.borrow()
81 .get(&key)
82 .and_then(|v| v.get(bit as usize).copied())
83 })
84}