Architecture ============ System Architecture ------------------- The Zuspec HDLSim backend implements a dual-domain architecture that partitions verification logic between SystemVerilog (for hardware simulation) and Python (for test orchestration). .. mermaid:: graph TB subgraph Python["Python Domain (pytest via PyHDL-IF)"] PY1["• Test Orchestration"] PY2["• Top-level Component"] PY3["• Python-only Components"] PY4["• Test Sequences & Scenarios"] end subgraph SV["SystemVerilog Domain (HDL Simulator)"] SV1["• Generated Testbench Module"] SV2["• Generated Transactors (XtorComponent)"] SV3["• Extern Components (existing HDL)"] SV4["• Signal-level Connectivity"] SV5["• DUT (Design Under Test)"] end Python <-->|"PyHDL-IF Bridge
(TLM/API calls)"| SV style Python fill:#e1f5ff style SV fill:#ffe1f5 Component Classification ------------------------ The backend classifies components into three categories that determine their implementation domain: Extern Components ^^^^^^^^^^^^^^^^^ **Purpose**: Wrap existing SystemVerilog modules for use in Zuspec testbenches **Implementation**: SystemVerilog only (pre-existing or provided by user) **Characteristics**: * Inherit from ``Extern`` protocol * Reference existing HDL modules * Provide SystemVerilog source filesets via ``@annotation_fileset`` * Connect to other SV components via signals/interfaces **Example**: .. code-block:: python @zdc.dataclass class DutWrapper(zdc.Component, Extern): """Wrapper for existing DUT module.""" @annotation_fileset(sources=["dut.sv"]) def __post_init__(self): pass XtorComponent Transactors ^^^^^^^^^^^^^^^^^^^^^^^^^^ **Purpose**: Define transactors that generate both SystemVerilog and Python APIs **Implementation**: SystemVerilog (generated) + Python proxy (runtime) **Characteristics**: * Inherit from ``XtorComponent[Protocol]`` * Protocol defines the transaction API * SV code generated by zuspec-be-sv * Python API wrapper generated via `PyHDL-IF `_ * Connect via ``xtor_if`` interface **Example**: .. code-block:: python @zdc.dataclass class ClkGenXtor(XtorComponent[ClkGenIf]): """Clock generator transactor.""" clock: Signal = zdc.output() async def start(self, freq_mhz: int): """Start clock generation.""" ... Python Components ^^^^^^^^^^^^^^^^^ **Purpose**: Pure Python verification components **Implementation**: Python only **Characteristics**: * Standard Zuspec components * No signal-level connectivity to SV domain * Communicate via TLM/method calls * Run in pytest environment Domain Separation Rules ----------------------- The HDLTestbench profile enforces strict domain separation: 1. **No Signal-Level Crossing**: Python components cannot connect directly to signals in the SV domain 2. **TLM Boundary**: Communication between domains uses transaction-level modeling (method calls on xtor_if) 3. **Extern Isolation**: Extern components can only connect to other SV components (Extern or XtorComponent) Generation Flow --------------- Build Time (GenTB Task) ^^^^^^^^^^^^^^^^^^^^^^^^ .. mermaid:: flowchart TD Start[Zuspec Component Class] --> Check[Profile Checking] Check --> |Valid| SVGen[SV Generation] Check --> |Errors| Fail[Report Errors] SVGen --> Trans[Generate Transactor Modules
via zuspec-be-sv] SVGen --> TBMod[Generate Testbench Wrapper Module] SVGen --> API[Generate PyHDL-IF API Definitions JSON] Trans --> APIGen[PyHDL-IF API Generation] API --> APIGen APIGen --> Glue[Generate SV/Python API Glue Code] TBMod --> Fileset[Produce Ordered Compilation Fileset] Glue --> Fileset Fileset --> Done[Ready for Compilation] style Check fill:#ffffcc style SVGen fill:#ccffcc style APIGen fill:#ccccff style Done fill:#ccffcc Runtime (Simulation) ^^^^^^^^^^^^^^^^^^^^ .. mermaid:: sequenceDiagram participant Sim as HDL Simulator participant TB as Testbench Module participant PyHDL as PyHDL-IF participant Runtime as HDLSimRuntime participant Pytest as pytest Sim->>TB: Load & Initialize TB->>PyHDL: Register Transactor APIs TB->>Runtime: configure_objfactory("MyTB") Runtime->>Runtime: Patch MyTB.__init__ TB->>Pytest: pyhdl_pytest() Pytest->>Runtime: Create MyTB instance Runtime->>PyHDL: Lookup registered components PyHDL-->>Runtime: Return SV proxies Runtime-->>Pytest: Return TestbenchProxy Pytest->>Runtime: Call test methods Runtime->>PyHDL: Forward to SV APIs PyHDL->>TB: Execute in simulator TB-->>PyHDL: Return results PyHDL-->>Runtime: Return to Python Runtime-->>Pytest: Complete test Pytest->>Sim: $finish Code Generation Details ----------------------- Testbench Module Structure ^^^^^^^^^^^^^^^^^^^^^^^^^^^ The generated top-level testbench module has this structure: .. code-block:: systemverilog module MyTB_tb; import pyhdl_if::*; import RVXtor::*; // Instance HDL components MyTB_hdl u_hdl(); initial begin // Register transactors with PyHDL-IF // ... registration code ... // Configure Python ObjFactory pyhdl_configure_objfactory("mypackage.MyTB"); // Launch pytest pyhdl_pytest(); $finish; end endmodule HDL Module Structure ^^^^^^^^^^^^^^^^^^^^ The ``_hdl`` module contains the hardware components: .. code-block:: systemverilog module MyTB_hdl; // Extern component instances dut u_dut(...); // Generated transactor instances RVXtor u_xtor(...); // Signal bindings from __bind__ assign u_dut.rv_if = u_xtor.xtor_if; endmodule Python Runtime Factory ^^^^^^^^^^^^^^^^^^^^^^ At runtime, the ``PyTestbenchFactory`` creates proxy objects: .. code-block:: python class TestbenchProxy: def __init__(self): # Look up registered SV components via PyHDL-IF self.xtor = HdlObjRgy.inst().find("top.xtor") self.dut = None # Extern, no Python API Key Classes ----------- * ``SVTestbenchGenerator``: Generates SystemVerilog testbench modules * ``PyTestbenchFactory``: Creates runtime proxy objects for Python tests * ``HDLTestbenchChecker``: Validates profile rules * ``TransactorJsonApiGenerator``: Generates PyHDL-IF API definitions * ``GenTB``: `DFM `_ task for testbench generation See :doc:`api_reference` for detailed API documentation.