Skip to main content

rustdv_sim/
handle.rs

1//! Typed DUT handles with scheduled-write semantics and edge methods —
2//! the user-facing layer over rustdv-gpi (design-doc mapping rows 14,
3//! 19–22). `set()` is buffered and applied at the next ReadWrite phase;
4//! `set_now()` is the immediate variant.
5
6use rustdv_gpi as gpi;
7pub use rustdv_gpi::{BigUint, HandleError, Logic, LogicArray, ValueError};
8
9pub mod aggregate;
10pub mod hierarchy;
11pub mod logic;
12pub mod real;
13pub mod string;
14
15pub use aggregate::AggregateHandle;
16pub use hierarchy::{HierarchyHandle, top_module};
17pub use logic::LogicHandle;
18pub use real::RealHandle;
19pub use string::StringHandle;
20
21use crate::triggers::Edge;
22
23#[derive(Copy, Clone)]
24pub enum SimHandle {
25    Hierarchy(HierarchyHandle),
26    Logic(LogicHandle),
27    Real(RealHandle),
28    String(StringHandle),
29    Struct(AggregateHandle),
30    Union(AggregateHandle),
31    Other,
32}
33
34impl SimHandle {
35    fn wrap(h: gpi::AnyHandle) -> SimHandle {
36        match h {
37            gpi::AnyHandle::Hierarchy(raw) => SimHandle::Hierarchy(HierarchyHandle { raw }),
38            gpi::AnyHandle::Logic(raw) => SimHandle::Logic(LogicHandle { raw }),
39            gpi::AnyHandle::Real(raw) => SimHandle::Real(RealHandle { raw }),
40            gpi::AnyHandle::String(raw) => SimHandle::String(StringHandle { raw }),
41            gpi::AnyHandle::Struct(raw) => SimHandle::Struct(AggregateHandle { raw }),
42            gpi::AnyHandle::Union(raw) => SimHandle::Union(AggregateHandle { raw }),
43            gpi::AnyHandle::Other(_) => SimHandle::Other,
44        }
45    }
46
47    fn wrong_kind(self, expected: &'static str) -> HandleError {
48        let (name, actual) = match self {
49            Self::Hierarchy(h) => (h.full_name(), "module"),
50            Self::Logic(h) => (h.full_name(), "signal"),
51            Self::Real(h) => (h.full_name(), "real"),
52            Self::String(h) => (h.full_name(), "string"),
53            Self::Struct(h) => (h.full_name(), "struct"),
54            Self::Union(h) => (h.full_name(), "union"),
55            // Other carries no underlying object metadata.
56            Self::Other => ("<unknown>".into(), "unsupported simulator object"),
57        };
58        HandleError::WrongKind {
59            name,
60            expected,
61            actual: actual.into(),
62        }
63    }
64
65    pub fn as_hierarchy(self) -> Result<HierarchyHandle, HandleError> {
66        match self {
67            SimHandle::Hierarchy(h) => Ok(h),
68            other => Err(other.wrong_kind("module")),
69        }
70    }
71
72    pub fn as_signal(self) -> Result<LogicHandle, HandleError> {
73        match self {
74            SimHandle::Logic(l) => Ok(l),
75            other => Err(other.wrong_kind("signal")),
76        }
77    }
78
79    pub fn as_real(self) -> Result<RealHandle, HandleError> {
80        match self {
81            Self::Real(h) => Ok(h),
82            other => Err(other.wrong_kind("real")),
83        }
84    }
85
86    pub fn as_string(self) -> Result<StringHandle, HandleError> {
87        match self {
88            Self::String(h) => Ok(h),
89            other => Err(other.wrong_kind("string")),
90        }
91    }
92
93    pub fn as_aggregate(self) -> Result<AggregateHandle, HandleError> {
94        match self {
95            Self::Struct(h) | Self::Union(h) => Ok(h),
96            other => Err(other.wrong_kind("struct or union")),
97        }
98    }
99
100    pub fn is_other(self) -> bool {
101        matches!(self, SimHandle::Other)
102    }
103}
104
105/// A trait for the common methods of all handle types
106pub trait HandleBase {
107    /// Get the name of the handle (without hierarchy)
108    fn name(&self) -> String;
109
110    /// Get the full name of the handle (with hierarchy)
111    fn full_name(&self) -> String;
112}
113
114/// A trait for handles that have children (hierarchy, aggregate)
115pub trait HandleChildren {
116    /// Get a child handle by name
117    fn child(&self, name: &str) -> Result<SimHandle, HandleError>;
118
119    /// Get all child handles
120    fn children(&self) -> Vec<SimHandle>;
121
122    /// Get a child handle by name and convert it to logic handle
123    fn signal(&self, name: &str) -> Result<LogicHandle, HandleError> {
124        self.child(name)?.as_signal()
125    }
126
127    /// Get a child handle by name and convert it to real handle
128    fn real(&self, name: &str) -> Result<RealHandle, HandleError> {
129        self.child(name)?.as_real()
130    }
131
132    /// Get a child handle by name and convert it to string handle
133    fn string(&self, name: &str) -> Result<StringHandle, HandleError> {
134        self.child(name)?.as_string()
135    }
136
137    /// Get a child handle by name and convert it to hierarchy handle
138    fn hierarchy(&self, name: &str) -> Result<HierarchyHandle, HandleError> {
139        self.child(name)?.as_hierarchy()
140    }
141
142    /// Get a child handle by name and convert it to aggregate handle
143    fn aggregate(&self, name: &str) -> Result<AggregateHandle, HandleError> {
144        self.child(name)?.as_aggregate()
145    }
146}
147
148/// A trait for handles that have observable events
149pub trait HandleEvent {
150    /// Get the rising edge event for this handle
151    fn rising_edge(&self) -> Edge;
152
153    /// Get the falling edge event for this handle
154    fn falling_edge(&self) -> Edge;
155
156    /// Get the value change event for this handle
157    fn value_change(&self) -> Edge;
158}