Skip to main content

rustdv_sim/handle/
hierarchy.rs

1//! Module lookup and typed child access.
2
3use rustdv_gpi as gpi;
4
5use crate::handle::{HandleBase, HandleChildren, HandleError, SimHandle};
6
7/// A module/scope handle: `dut.child("name")?` (OQ-6 dynamic-first lean).
8#[derive(Copy, Clone)]
9pub struct HierarchyHandle {
10    pub(super) raw: gpi::HierarchyHandle,
11}
12
13impl From<gpi::HierarchyHandle> for HierarchyHandle {
14    fn from(raw: gpi::HierarchyHandle) -> Self {
15        HierarchyHandle { raw }
16    }
17}
18
19impl HandleBase for HierarchyHandle {
20    fn name(&self) -> String {
21        self.raw.name()
22    }
23
24    fn full_name(&self) -> String {
25        self.raw.full_name()
26    }
27}
28
29impl HandleChildren for HierarchyHandle {
30    fn child(&self, name: &str) -> Result<SimHandle, HandleError> {
31        Ok(SimHandle::wrap(self.raw.child(name)?))
32    }
33
34    fn children(&self) -> Vec<SimHandle> {
35        self.raw
36            .children()
37            .into_iter()
38            .map(SimHandle::wrap)
39            .collect()
40    }
41}
42
43/// The `RUSTDV_TOP` module, or the first top-level module when it is unset.
44pub fn top_module() -> Result<HierarchyHandle, HandleError> {
45    Ok(HierarchyHandle::from(gpi::top_module()?))
46}
47
48impl std::fmt::Debug for HierarchyHandle {
49    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
50        write!(f, "HierarchyHandle(\"{}\")", self.full_name())
51    }
52}
53
54impl HierarchyHandle {
55    /// A handle to nothing, for unit tests that need a `RustdvCtx` but never
56    /// touch the DUT. Any VPI call through it reaches `rustdv-vpi-stubs`,
57    /// which panics — so a test that *does* touch the DUT fails loudly rather
58    /// than reading garbage, and its author learns it belongs in a `sim-*`
59    /// case instead.
60    pub fn null_for_test() -> HierarchyHandle {
61        HierarchyHandle {
62            raw: gpi::HierarchyHandle::null_for_test(),
63        }
64    }
65}