diff --git a/pyproject.toml b/pyproject.toml index 03198e41..619c7e4f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -28,7 +28,7 @@ requires-python = ">= 3.9" license = "Apache-2.0" license-files = ["LICENSE"] dependencies = [ - "siliconcompiler >= 0.36.5", + "siliconcompiler >= 0.38.0", "lambdalib >= 0.12.0, <0.14.0" ] dynamic = ["version"] @@ -39,7 +39,7 @@ test = [ "pytest-xdist == 3.8.0", "pytest-timeout == 2.4.0", "flake8 == 7.3.0", - "switchboard-hw==0.3.3", + "switchboard-hw==0.3.4", "cocotb==2.0.1", "cocotb-bus==0.3.0", "cocotbext-axi==0.1.28", diff --git a/tests/adapters/axi2umi/test_axi2umi.py b/tests/adapters/axi2umi/test_axi2umi.py index 6492abf4..137f3d55 100644 --- a/tests/adapters/axi2umi/test_axi2umi.py +++ b/tests/adapters/axi2umi/test_axi2umi.py @@ -3,7 +3,8 @@ import pytest -from siliconcompiler import Design +from siliconcompiler import Sim +from siliconcompiler.targets.dvflow_cocotb import dvflow_cocotb import cocotb from cocotb.clock import Clock @@ -21,6 +22,8 @@ from umi.adapters.axi2umi.axi2umi import AXI2UMI +from cocotb_utils import CocotbSimEnv + class Env: """Reusable test environment for AXI4 Full to UMI adapter tests.""" @@ -346,32 +349,31 @@ async def drop_test(dut, test_n_transactions=10, resp_valid_gen=None): await ClockCycles(dut.clk, 10) -class TbDesign(Design): +class TbDesign(CocotbSimEnv): def __init__(self): - super().__init__() - - # Set the design's name - self.set_name("tb_axi2umi") - - # Establish the root directory for all design-related files - self.set_dataroot("tb_axi2umi", __file__) - - # Configure filesets within the established data root - with self.active_dataroot("tb_axi2umi"): - with self.active_fileset("testbench.cocotb"): - self.set_topmodule("axi2umi") - self.add_file("test_axi2umi.py", filetype="python") - self.add_depfileset(AXI2UMI(), "rtl") + super().__init__( + name="tb_axi2umi", + topmodule="axi2umi", + files=[__file__], + dep=[AXI2UMI()] + ) @pytest.mark.cocotb @pytest.mark.parametrize("simulator", ["icarus", "verilator"]) def test_axi2umi(simulator): - from run_cocotb_sim import load_cocotb_test - load_cocotb_test( - design=TbDesign(), - simulator=simulator, + project = Sim(TbDesign()) + project.add_fileset("testbench.cocotb") + + dvflow_cocotb( + project=project, trace=False, + timescale=("1ns", "1ps"), seed=None ) + + project.set_flow(f"{simulator}cocotbdvflow") + + project.run() + project.summary() diff --git a/tests/adapters/axi2umi/test_axird2umi.py b/tests/adapters/axi2umi/test_axird2umi.py index 8bc17bf2..fce8a9af 100644 --- a/tests/adapters/axi2umi/test_axird2umi.py +++ b/tests/adapters/axi2umi/test_axird2umi.py @@ -3,7 +3,8 @@ import pytest -from siliconcompiler import Design +from siliconcompiler import Sim +from siliconcompiler.targets.dvflow_cocotb import dvflow_cocotb import cocotb from cocotb.clock import Clock @@ -20,6 +21,8 @@ from umi.adapters.axi2umi.axi2umi import AXI2UMI +from cocotb_utils import CocotbSimEnv + class Env: """Reusable test environment for AXI4 Full Read to UMI adapter tests.""" @@ -150,32 +153,31 @@ async def basic_test( await ClockCycles(dut.clk, 10) -class TbDesign(Design): +class TbDesign(CocotbSimEnv): def __init__(self): - super().__init__() - - # Set the design's name - self.set_name("tb_axird2umi") - - # Establish the root directory for all design-related files - self.set_dataroot("tb_axird2umi", __file__) - - # Configure filesets within the established data root - with self.active_dataroot("tb_axird2umi"): - with self.active_fileset("testbench.cocotb"): - self.set_topmodule("axird2umi") - self.add_file("test_axird2umi.py", filetype="python") - self.add_depfileset(AXI2UMI(), "rtl") + super().__init__( + name="tb_axird2umi", + topmodule="axird2umi", + files=[__file__], + dep=[AXI2UMI()] + ) @pytest.mark.cocotb @pytest.mark.parametrize("simulator", ["icarus", "verilator"]) def test_axird2umi(simulator): - from run_cocotb_sim import load_cocotb_test - load_cocotb_test( - design=TbDesign(), - simulator=simulator, + project = Sim(TbDesign()) + project.add_fileset("testbench.cocotb") + + dvflow_cocotb( + project=project, trace=False, + timescale=("1ns", "1ps"), seed=None ) + + project.set_flow(f"{simulator}cocotbdvflow") + + project.run() + project.summary() diff --git a/tests/adapters/axi2umi/test_axiwr2umi.py b/tests/adapters/axi2umi/test_axiwr2umi.py index f2fc27ad..2f5d4929 100644 --- a/tests/adapters/axi2umi/test_axiwr2umi.py +++ b/tests/adapters/axi2umi/test_axiwr2umi.py @@ -4,7 +4,8 @@ import pytest -from siliconcompiler import Design +from siliconcompiler import Sim +from siliconcompiler.targets.dvflow_cocotb import dvflow_cocotb import cocotb from cocotb.clock import Clock @@ -22,6 +23,8 @@ from umi.adapters.axi2umi.axi2umi import AXI2UMI +from cocotb_utils import CocotbSimEnv + class ErrorInjectingUmiMemoryDevice(UmiMemoryDevice): """ @@ -370,32 +373,31 @@ async def error_injection_test( await ClockCycles(dut.clk, 10) -class TbDesign(Design): +class TbDesign(CocotbSimEnv): def __init__(self): - super().__init__() - - # Set the design's name - self.set_name("tb_axiwr2umi") - - # Establish the root directory for all design-related files - self.set_dataroot("tb_axiwr2umi", __file__) - - # Configure filesets within the established data root - with self.active_dataroot("tb_axiwr2umi"): - with self.active_fileset("testbench.cocotb"): - self.set_topmodule("axiwr2umi") - self.add_file("test_axiwr2umi.py", filetype="python") - self.add_depfileset(AXI2UMI(), "rtl") + super().__init__( + name="tb_axiwr2umi", + topmodule="axiwr2umi", + files=[__file__], + dep=[AXI2UMI()] + ) @pytest.mark.cocotb @pytest.mark.parametrize("simulator", ["icarus", "verilator"]) def test_axiwr2umi(simulator): - from run_cocotb_sim import load_cocotb_test - load_cocotb_test( - design=TbDesign(), - simulator=simulator, + project = Sim(TbDesign()) + project.add_fileset("testbench.cocotb") + + dvflow_cocotb( + project=project, trace=False, + timescale=("1ns", "1ps"), seed=None ) + + project.set_flow(f"{simulator}cocotbdvflow") + + project.run() + project.summary() diff --git a/tests/adapters/tl2umi/test_advanced.py b/tests/adapters/tl2umi/test_advanced.py index ab333315..f4bfed43 100644 --- a/tests/adapters/tl2umi/test_advanced.py +++ b/tests/adapters/tl2umi/test_advanced.py @@ -3,8 +3,12 @@ from cocotb.handle import SimHandleBase from cocotb.triggers import ClockCycles -from tl_driver import TLTransaction, TLArithParam, TLLogicParam -from tl2umi_env import TL2UMIEnv, create_expected_write_response, create_expected_read_response +from adapters.tl2umi.tl_driver import TLTransaction, TLArithParam, TLLogicParam +from adapters.tl2umi.tl2umi_env import ( + TL2UMIEnv, + create_expected_write_response, + create_expected_read_response +) @cocotb.test(timeout_time=50, timeout_unit="ms") diff --git a/tests/adapters/tl2umi/test_basic.py b/tests/adapters/tl2umi/test_basic.py index b3271637..6883c46b 100644 --- a/tests/adapters/tl2umi/test_basic.py +++ b/tests/adapters/tl2umi/test_basic.py @@ -2,8 +2,12 @@ from cocotb.handle import SimHandleBase -from tl_driver import TLTransaction -from tl2umi_env import TL2UMIEnv, create_expected_write_response, create_expected_read_response +from adapters.tl2umi.tl_driver import TLTransaction +from adapters.tl2umi.tl2umi_env import ( + TL2UMIEnv, + create_expected_write_response, + create_expected_read_response +) @cocotb.test(timeout_time=50, timeout_unit="ms") diff --git a/tests/adapters/tl2umi/test_tl2umi_run.py b/tests/adapters/tl2umi/test_tl2umi_run.py index 74f7fea6..ae75d661 100644 --- a/tests/adapters/tl2umi/test_tl2umi_run.py +++ b/tests/adapters/tl2umi/test_tl2umi_run.py @@ -2,47 +2,48 @@ import pytest -from siliconcompiler import Design +from siliconcompiler import Sim +from siliconcompiler.targets.dvflow_cocotb import dvflow_cocotb from umi.adapters import TL2UMI +from cocotb_utils import CocotbSimEnv -class TL2UMITestbench(Design): + +class TL2UMITestbench(CocotbSimEnv): """TL2UMI testbench for cocotb testing (UMI memory agent in Python)""" def __init__(self, aw=64, dw=64): - super().__init__() - - self.set_name(f"tb_tl2umi_aw{aw}_dw{dw}") - self.set_dataroot("tl2umi", __file__) - - with self.active_dataroot("tl2umi"): - with self.active_fileset("testbench.cocotb"): - self.set_topmodule("tl2umi") - self.set_param("AW", str(aw)) - self.set_param("DW", str(dw)) - # Add test files - self.add_file("test_basic.py", filetype="python") - self.add_file("test_advanced.py", filetype="python") - # Add helper Python modules (populates PYTHONPATH via DVFlow) - self.add_file("tl2umi_env.py", filetype="python") - self.add_file("tl_driver.py", filetype="python") - self.add_file("tl_monitor.py", filetype="python") - # Add RTL dependency (no Verilog wrapper needed) - self.add_depfileset(TL2UMI(), "rtl") + super().__init__( + name=f"tb_tl2umi_aw{aw}_dw{dw}", + topmodule="tl2umi", + files=[ + "adapters/tl2umi/test_basic.py", + "adapters/tl2umi/test_advanced.py", + ], + dep=[TL2UMI()], + param=[("AW", str(aw)), ("DW", str(dw))] + ) @pytest.mark.cocotb @pytest.mark.parametrize("simulator, aw, dw", list(itertools.product( ["verilator"], - [32, 64], + [64], [64, 128] ))) def test_tl2umi(simulator, aw, dw): - from run_cocotb_sim import load_cocotb_test - load_cocotb_test( - design=TL2UMITestbench(aw=aw, dw=dw), - simulator=simulator, + project = Sim(TL2UMITestbench(aw=aw, dw=dw)) + project.add_fileset("testbench.cocotb") + + dvflow_cocotb( + project=project, trace=False, + timescale=("1ns", "1ps"), seed=None ) + + project.set_flow(f"{simulator}cocotbdvflow") + + project.run() + project.summary() diff --git a/tests/adapters/tl2umi/tl2umi_env.py b/tests/adapters/tl2umi/tl2umi_env.py index 919e3b3b..489493e7 100644 --- a/tests/adapters/tl2umi/tl2umi_env.py +++ b/tests/adapters/tl2umi/tl2umi_env.py @@ -5,7 +5,7 @@ # the Verilog umi_memagent. The DUT is tl2umi directly (no wrapper needed). from cocotb.clock import Clock -from cocotb.triggers import ClockCycles, Timer +from cocotb.triggers import ClockCycles from cocotb_bus.scoreboard import Scoreboard @@ -13,18 +13,10 @@ from cocotbext.umi.monitors.sumi_monitor import SumiMonitor from cocotbext.umi.models.umi_memory_device import UmiMemoryDevice -from tl_driver import TLDriver -from tl_monitor import TLMonitor, TLDResponse, TLDOpcode +from adapters.tl2umi.tl_driver import TLDriver +from adapters.tl2umi.tl_monitor import TLMonitor, TLDResponse, TLDOpcode - -async def do_reset(reset, time_ns, active_level=False): - """Perform an async reset""" - reset.value = not active_level - await Timer(1, unit="step") - reset.value = active_level - await Timer(time_ns, "ns") - reset.value = not active_level - await Timer(1, unit="step") +from cocotb_utils import drive_reset class TL2UMIEnv: @@ -97,7 +89,7 @@ def _build(self): async def start(self): """Start clocks and perform reset""" Clock(self.clk, self.clk_period_ns, unit="ns").start() - await do_reset(self.nreset, self.clk_period_ns) + await drive_reset(self.nreset, self.clk_period_ns) # Initialize DUT configuration signals self.dut.srcaddr.value = 0xAE510000 diff --git a/tests/adapters/umi2apb/env.py b/tests/adapters/umi2apb/env.py index e8c033df..f9cb4477 100644 --- a/tests/adapters/umi2apb/env.py +++ b/tests/adapters/umi2apb/env.py @@ -2,7 +2,7 @@ # and provides common functionality for the tests. from cocotb.clock import Clock -from cocotb.triggers import ClockCycles, Timer +from cocotb.triggers import ClockCycles from cocotb_bus.scoreboard import Scoreboard from cocotbext.apb import ApbBus, ApbSlave, MemoryRegion @@ -11,15 +11,7 @@ from cocotbext.umi.monitors.sumi_monitor import SumiMonitor from cocotbext.umi.sumi import SumiTransaction, SumiCmdType, SumiCmd - -async def do_reset(reset, time_ns: int, active_level: bool = False): - """Drive an asynchronous reset pulse on *reset*.""" - reset.value = not active_level - await Timer(1, unit="step") - reset.value = active_level - await Timer(time_ns, "ns") - reset.value = not active_level - await Timer(1, unit="step") +from cocotb_utils import drive_reset # Creates the umi2apb test environment @@ -77,7 +69,7 @@ def __init__( # Prerequisites for starting tests async def start(self): - await do_reset(self.nreset, self.clk_period_ns) + await drive_reset(self.nreset, self.clk_period_ns) Clock(self.clk, self.clk_period_ns, unit="ns").start() await ClockCycles(self.clk, 10) diff --git a/tests/adapters/umi2apb/test_backpressure.py b/tests/adapters/umi2apb/test_backpressure.py index b0cae26a..2b7159d9 100644 --- a/tests/adapters/umi2apb/test_backpressure.py +++ b/tests/adapters/umi2apb/test_backpressure.py @@ -5,7 +5,7 @@ from cocotb.triggers import ClockCycles from cocotbext.umi.sumi import SumiTransaction, SumiCmdType, SumiCmd -from env import UMI2APBEnv, create_expected_write_response +from adapters.umi2apb.env import UMI2APBEnv, create_expected_write_response @cocotb.test(timeout_time=1, timeout_unit="ms") diff --git a/tests/adapters/umi2apb/test_basic_WR.py b/tests/adapters/umi2apb/test_basic_WR.py index f083897a..89fd8675 100644 --- a/tests/adapters/umi2apb/test_basic_WR.py +++ b/tests/adapters/umi2apb/test_basic_WR.py @@ -7,7 +7,7 @@ from cocotbext.umi.sumi import SumiTransaction, SumiCmdType, SumiCmd from cocotbext.umi.utils.generators import random_toggle_generator -from env import UMI2APBEnv, create_expected_write_response +from adapters.umi2apb.env import UMI2APBEnv, create_expected_write_response @cocotb.test(timeout_time=50, timeout_unit="ms") diff --git a/tests/adapters/umi2apb/test_full_throughput.py b/tests/adapters/umi2apb/test_full_throughput.py index 3823d585..4a8fc5a2 100644 --- a/tests/adapters/umi2apb/test_full_throughput.py +++ b/tests/adapters/umi2apb/test_full_throughput.py @@ -3,7 +3,7 @@ from cocotb.triggers import Event, Combine, ClockCycles -from env import UMI2APBEnv +from adapters.umi2apb.env import UMI2APBEnv from cocotbext.umi.sumi import SumiTransaction, SumiCmdType, SumiCmd diff --git a/tests/adapters/umi2apb/test_posted_write.py b/tests/adapters/umi2apb/test_posted_write.py index 88d550aa..971e3c24 100644 --- a/tests/adapters/umi2apb/test_posted_write.py +++ b/tests/adapters/umi2apb/test_posted_write.py @@ -7,7 +7,7 @@ from cocotbext.umi.sumi import SumiTransaction, SumiCmdType, SumiCmd from cocotbext.umi.utils.generators import random_toggle_generator -from env import UMI2APBEnv +from adapters.umi2apb.env import UMI2APBEnv @cocotb.test(timeout_time=50, timeout_unit="ms") diff --git a/tests/adapters/umi2apb/test_random_stimulus.py b/tests/adapters/umi2apb/test_random_stimulus.py index c219b4e2..997b5017 100644 --- a/tests/adapters/umi2apb/test_random_stimulus.py +++ b/tests/adapters/umi2apb/test_random_stimulus.py @@ -7,7 +7,7 @@ from cocotb_bus.drivers import BitDriver -from env import UMI2APBEnv, create_expected_write_response +from adapters.umi2apb.env import UMI2APBEnv, create_expected_write_response from cocotbext.umi.sumi import SumiTransaction, SumiCmdType, SumiCmd from cocotbext.umi.utils.generators import ( random_toggle_generator, diff --git a/tests/adapters/umi2apb/test_run.py b/tests/adapters/umi2apb/test_run.py index 1e79f62a..cc7af32a 100644 --- a/tests/adapters/umi2apb/test_run.py +++ b/tests/adapters/umi2apb/test_run.py @@ -1,38 +1,44 @@ import pytest -from siliconcompiler import Design +from siliconcompiler import Sim +from siliconcompiler.targets.dvflow_cocotb import dvflow_cocotb from umi.adapters.umi2apb.umi2apb import UMI2APB +from cocotb_utils import CocotbSimEnv -class TbDesign(Design): - def __init__(self): - super().__init__() - - self.set_name("tb_umi2apb") +class TbDesign(CocotbSimEnv): - self.set_dataroot("tb_umi2apb", __file__) - - with self.active_dataroot("tb_umi2apb"): - with self.active_fileset("testbench.cocotb"): - self.set_topmodule("umi2apb") - self.add_file("env.py", filetype="python") - self.add_file("test_basic_WR.py", filetype="python") - self.add_file("test_backpressure.py", filetype="python") - self.add_file("test_full_throughput.py", filetype="python") - self.add_file("test_posted_write.py", filetype="python") - self.add_file("test_random_stimulus.py", filetype="python") - self.add_depfileset(UMI2APB(), "rtl") + def __init__(self): + super().__init__( + name="tb_umi2apb", + topmodule="umi2apb", + files=[ + "adapters/umi2apb/test_basic_WR.py", + "adapters/umi2apb/test_backpressure.py", + "adapters/umi2apb/test_full_throughput.py", + "adapters/umi2apb/test_posted_write.py", + "adapters/umi2apb/test_random_stimulus.py", + ], + dep=[UMI2APB()] + ) @pytest.mark.cocotb @pytest.mark.parametrize("simulator", ["icarus", "verilator"]) def test_umi2apb(simulator, output_wave=False): - from run_cocotb_sim import load_cocotb_test - load_cocotb_test( - design=TbDesign(), - simulator=simulator, + project = Sim(TbDesign()) + project.add_fileset("testbench.cocotb") + + dvflow_cocotb( + project=project, trace=output_wave, + timescale=("1ns", "1ps"), seed=None ) + + project.set_flow(f"{simulator}cocotbdvflow") + + project.run() + project.summary() diff --git a/tests/cocotb_utils.py b/tests/cocotb_utils.py new file mode 100644 index 00000000..48033824 --- /dev/null +++ b/tests/cocotb_utils.py @@ -0,0 +1,66 @@ +from typing import List, Tuple +from siliconcompiler import Design +from cocotb.triggers import Timer + + +class CocotbSimEnv(Design): + + def __init__( + self, + name: str = None, + topmodule: str = None, + files: List[str] = None, + dep: List[Design] = None, + define: List[str] = None, + undefine: List[str] = None, + param: List[Tuple] = None + ): + + if name: + super().__init__(name) + else: + super().__init__(topmodule) + + self.set_dataroot("local", __file__) + + # Taking care of Nones + if files is None: + files = [] + if dep is None: + dep = [] + if define is None: + define = [] + if undefine is None: + undefine = [] + if param is None: + param = [] + + with self.active_dataroot("local"): + with self.active_fileset('testbench.cocotb'): + if topmodule: + self.set_topmodule(topmodule) + for item in files: + self.add_file(item) + for item in dep: + self.add_depfileset(item) + for item in define: + self.add_define(item) + for item in undefine: + self.add_undefine(item) + for item in param: + self.set_param(item[0], item[1]) + self.add_libdir(".") + + +async def drive_reset(reset, time_ns=50, active_level=False): + """Drive an asynchronous reset pulse on *reset*. + + Holds *reset* asserted for *time_ns* nanoseconds. *active_level* selects + the asserted logic level (False for active-low resets, the default). + """ + reset.value = int(not active_level) + await Timer(1, unit="step") + reset.value = int(active_level) + await Timer(time_ns, unit="ns") + reset.value = int(not active_level) + await Timer(1, unit="step") diff --git a/tests/run_cocotb_sim.py b/tests/run_cocotb_sim.py deleted file mode 100644 index 4e6d88d4..00000000 --- a/tests/run_cocotb_sim.py +++ /dev/null @@ -1,140 +0,0 @@ -from siliconcompiler import Design, Sim -from siliconcompiler.flows.dvflow import DVFlow - -from siliconcompiler.tools.icarus.compile import CompileTask as IcarusCompileTask -from siliconcompiler.tools.icarus.cocotb_exec import CocotbExecTask as IcarusCocotbExecTask - -from siliconcompiler.tools.verilator.cocotb_compile import CocotbCompileTask as VerilatorCompileTask -from siliconcompiler.tools.verilator.cocotb_exec import CocotbExecTask as VerilatorCocotbExecTask - - -class IcarusDesign(Design): - def __init__(self, design: Design): - super().__init__() - - self.set_name(f"{design.name}_icarus_sim") - - self.set_dataroot("icarus_tb", __file__) - - with self.active_dataroot("icarus_tb"): - with self.active_fileset("icarus_sim"): - self.add_file("sim_cmd_files/icarus_cmd_file.f", filetype="commandfile") - self.add_depfileset(design, "testbench.cocotb") - self.set_topmodule(design.get_topmodule("testbench.cocotb")) - - -class VerilatorDesign(Design): - def __init__(self, design: Design): - super().__init__() - - self.set_name(f"{design.name}_verilator_sim") - - self.set_dataroot("verilator_tb", __file__) - - with self.active_dataroot("verilator_tb"): - with self.active_fileset("verilator_sim"): - self.add_file("sim_cmd_files/verilator_cmd_file.vc", filetype="commandfile") - self.add_depfileset(design, "testbench.cocotb") - self.set_topmodule(design.get_topmodule("testbench.cocotb")) - - -def load_cocotb_test( - design: Design, - simulator="icarus", - trace=True, - seed=None -): - - if simulator == "icarus": - load_cocotb_icarus_sim(design, trace=trace, seed=seed) - elif simulator == "verilator": - load_cocotb_verilator_sim(design, trace=trace, seed=seed, trace_type="vcd") - - -def load_cocotb_icarus_sim( - design: Design, - trace=True, - seed=None -): - project = Sim() - project.set_design(IcarusDesign(design)) - project.add_fileset("icarus_sim") - project.set_flow(DVFlow(tool="icarus-cocotb")) - - IcarusCompileTask.find_task(project).set_trace_enabled(trace) - - if seed is not None: - IcarusCocotbExecTask.find_task(project).set_cocotb_randomseed(seed) - - project.run() - project.summary() - - results = project.find_result( - step='simulate', - index='0', - directory="outputs", - filename="results.xml" - ) - if results: - print(f"\nCocotb results file: {results}") - - vcd = project.find_result( - step='simulate', - index='0', - directory="reports", - filename="tb_umi_stream.vcd" - ) - if vcd: - print(f"Waveform file: {vcd}") - - -def load_cocotb_verilator_sim( - design: Design, - trace=True, - seed=None, - trace_type="vcd" -): - project = Sim() - project.set_design(VerilatorDesign(design)) - project.add_fileset("verilator_sim") - project.set_flow(DVFlow(tool="verilator-cocotb")) - - # Enable waveform tracing (must be enabled on both compile and simulate tasks) - compile_task = VerilatorCompileTask.find_task(project) - compile_task.set_verilator_trace(trace) - compile_task.set_verilator_tracetype(trace_type) - - cocotb_task = VerilatorCocotbExecTask.find_task(project) - cocotb_task.set_cocotb_trace( - enable=trace, - trace_type=trace_type - ) - - # Optionally set a random seed for reproducibility - if seed is not None: - cocotb_task.set_cocotb_randomseed(seed) - - # Run the simulation - project.run() - project.summary() - - # Find and display the results file - results = project.find_result( - step='simulate', - index='0', - directory="outputs", - filename="results.xml" - ) - if results: - print(f"\nCocotb results file: {results}") - - # Find and display the waveform file - wave_ext = trace_type if trace_type in ("vcd", "fst") else "vcd" - wave = project.find_result( - step='simulate', - index='0', - directory="reports", - filename=f"adder.{wave_ext}" - ) - if wave: - print(f"Waveform file: {wave}") diff --git a/tests/sim_cmd_files/icarus_cmd_file.f b/tests/sim_cmd_files/icarus_cmd_file.f deleted file mode 100644 index 3e26e00a..00000000 --- a/tests/sim_cmd_files/icarus_cmd_file.f +++ /dev/null @@ -1 +0,0 @@ -+timescale+1ns/1ps diff --git a/tests/sim_cmd_files/verilator_cmd_file.vc b/tests/sim_cmd_files/verilator_cmd_file.vc deleted file mode 100644 index 89b77f44..00000000 --- a/tests/sim_cmd_files/verilator_cmd_file.vc +++ /dev/null @@ -1 +0,0 @@ ---timescale 1ns/1ps diff --git a/tests/sumi/umi_buffer/test_umi_buffer.py b/tests/sumi/umi_buffer/test_umi_buffer.py index 88e1995c..d6a7f781 100644 --- a/tests/sumi/umi_buffer/test_umi_buffer.py +++ b/tests/sumi/umi_buffer/test_umi_buffer.py @@ -5,11 +5,12 @@ import pytest -from siliconcompiler import Design +from siliconcompiler import Sim +from siliconcompiler.targets.dvflow_cocotb import dvflow_cocotb import cocotb from cocotb.clock import Clock -from cocotb.triggers import ClockCycles, RisingEdge, Timer +from cocotb.triggers import ClockCycles, RisingEdge from cocotb.types import LogicArray from cocotb.handle import SimHandleBase @@ -24,6 +25,8 @@ from umi.sumi.umi_buffer.umi_buffer import Buffer +from cocotb_utils import drive_reset, CocotbSimEnv + class ValidReadyDriver(ValidatedBusDriver): @@ -112,15 +115,6 @@ def valid_handshake(): self._recv(self.bus.data.value.to_bytes(byteorder="little")) -async def drive_reset(reset, time_ns=50): - reset.value = 1 - await Timer(1, unit="step") - reset.value = 0 - await Timer(time_ns, unit="ns") - reset.value = 1 - await Timer(1, unit="step") - - @cocotb.test() @cocotb.parametrize( input_valid_gen=[None, random_toggle_generator(), wave_generator()], @@ -258,24 +252,16 @@ async def umi_buffer_backpressure_test(dut): raise scoreboard.result -class TbDesign(Design): +class TbDesign(CocotbSimEnv): def __init__(self, mode: int): - super().__init__() - - # Set the design's name - self.set_name(f"tb_umi_buffer_mode_{mode}") - - # Establish the root directory for all design-related files - self.set_dataroot("tb_umi_buffer", __file__) - - # Configure filesets within the established data root - with self.active_dataroot("tb_umi_buffer"): - with self.active_fileset("testbench.cocotb"): - self.set_topmodule("umi_buffer") - self.set_param("MODE", str(mode)) - self.add_file("test_umi_buffer.py", filetype="python") - self.add_depfileset(Buffer(), "rtl") + super().__init__( + name=f"tb_umi_buffer_mode_{mode}", + topmodule="umi_buffer", + files=[__file__], + dep=[Buffer()], + param=[("MODE", str(mode))] + ) @pytest.mark.cocotb @@ -284,10 +270,17 @@ def __init__(self, mode: int): [0, 1] ))) def test_umi_buffer(simulator, mode): - from run_cocotb_sim import load_cocotb_test - load_cocotb_test( - design=TbDesign(mode), - simulator=simulator, + project = Sim(TbDesign(mode)) + project.add_fileset("testbench.cocotb") + + dvflow_cocotb( + project=project, trace=False, + timescale=("1ns", "1ps"), seed=None ) + + project.set_flow(f"{simulator}cocotbdvflow") + + project.run() + project.summary() diff --git a/tests/sumi/umi_mux/test_umi_mux.py b/tests/sumi/umi_mux/test_umi_mux.py index 0c6a9692..4f0fbb9c 100644 --- a/tests/sumi/umi_mux/test_umi_mux.py +++ b/tests/sumi/umi_mux/test_umi_mux.py @@ -3,12 +3,14 @@ import random import pytest -from siliconcompiler import Design +from siliconcompiler import Sim +from siliconcompiler.targets.dvflow_cocotb import dvflow_cocotb + from umi.sumi.umi_mux.umi_mux import Mux import cocotb from cocotb.clock import Clock -from cocotb.triggers import ClockCycles, RisingEdge, Timer +from cocotb.triggers import ClockCycles, RisingEdge from cocotb_bus.drivers import BitDriver from cocotbext.umi.sumi import SumiCmd, SumiCmdType, SumiTransaction @@ -20,14 +22,7 @@ wave_generator ) - -async def drive_reset(reset, time_ns=50): - reset.value = 1 - await Timer(1, unit="step") - reset.value = 0 - await Timer(time_ns, unit="ns") - reset.value = 1 - await Timer(1, unit="step") +from cocotb_utils import drive_reset, CocotbSimEnv @cocotb.test(timeout_time=20, timeout_unit="us") @@ -230,30 +225,34 @@ def rand_transaction() -> SumiTransaction: await ClockCycles(dut.clk, 10) -class TbDesign(Design): +class TbDesign(CocotbSimEnv): def __init__(self): - super().__init__() - - self.set_name("tb_umi_mux") - - self.set_dataroot("local", __file__) - - with self.active_dataroot("local"): - with self.active_fileset("testbench.cocotb"): - self.set_topmodule("tb_umi_mux") - self.add_file("tb_umi_mux.v") - self.add_file("test_umi_mux.py", filetype="python") - self.add_depfileset(Mux(), "rtl") + super().__init__( + name="tb_umi_mux", + topmodule="tb_umi_mux", + files=[ + "sumi/umi_mux/tb_umi_mux.v", + __file__, + ], + dep=[Mux()] + ) @pytest.mark.cocotb @pytest.mark.parametrize("simulator", ["icarus", "verilator"]) def test_umi_mux_cocotb(simulator): - from run_cocotb_sim import load_cocotb_test - load_cocotb_test( - design=TbDesign(), - simulator=simulator, - trace=False, + project = Sim(TbDesign()) + project.add_fileset("testbench.cocotb") + + dvflow_cocotb( + project=project, + trace=True, + timescale=("1ns", "1ps"), seed=None ) + + project.set_flow(f"{simulator}cocotbdvflow") + + project.run() + project.summary() diff --git a/tests/sumi/umi_stream/test_umi_stream.py b/tests/sumi/umi_stream/test_umi_stream.py index 8b7a1398..b1dd41dc 100644 --- a/tests/sumi/umi_stream/test_umi_stream.py +++ b/tests/sumi/umi_stream/test_umi_stream.py @@ -19,12 +19,15 @@ from cocotbext.umi.utils import generators from cocotbext.umi.utils.vrd_transaction import VRDTransaction -from siliconcompiler import Design +from siliconcompiler import Sim +from siliconcompiler.targets.dvflow_cocotb import dvflow_cocotb from umi.sumi.umi_stream.umi_stream import Stream -from valid_ready_driver import ValidReadyDriver -from valid_ready_monitor import ValidReadyMonitor +from sumi.umi_stream.valid_ready_driver import ValidReadyDriver +from sumi.umi_stream.valid_ready_monitor import ValidReadyMonitor + +from cocotb_utils import CocotbSimEnv ###################################################### @@ -408,29 +411,32 @@ async def s2mm_task(): raise env.scoreboard.result -class TbDesign(Design): - +class TbDesign(CocotbSimEnv): def __init__(self): - super().__init__() - - self.set_name("tb_umi_stream") - - self.set_dataroot("tb_umi_stream", __file__) - - with self.active_dataroot("tb_umi_stream"): - with self.active_fileset("testbench.cocotb"): - self.set_topmodule("umi_stream") - self.add_file("test_umi_stream.py", filetype="python") - self.add_depfileset(Stream(), "rtl") + super().__init__( + name="tb_umi_stream", + topmodule="umi_stream", + files=[ + __file__, + ], + dep=[Stream()] + ) @pytest.mark.cocotb @pytest.mark.parametrize("simulator", ["icarus", "verilator"]) def test_umi_stream(simulator): - from run_cocotb_sim import load_cocotb_test - load_cocotb_test( - design=TbDesign(), - simulator=simulator, + project = Sim(TbDesign()) + project.add_fileset("testbench.cocotb") + + dvflow_cocotb( + project=project, trace=False, + timescale=("1ns", "1ps"), seed=None ) + + project.set_flow(f"{simulator}cocotbdvflow") + + project.run() + project.summary()