Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,25 @@ jobs:
python3 -m pip install -e .[test]
pytest -m "switchboard" -x --verbose --durations=0

cocotb_ci:
name: "Cocotb CI"
runs-on: ubuntu-latest
container:
image: ghcr.io/siliconcompiler/sc_runner:latest
timeout-minutes: 45

steps:
- name: Checkout repository
uses: actions/checkout@v6

- name: pytest
run: |
python3 -m venv venv
. venv/bin/activate
python3 -m pip install --upgrade pip
python3 -m pip install -e .[test]
pytest -m "cocotb" -x --verbose --durations=0

python_ci:
name: "Python + Tools CI"
runs-on: ubuntu-latest
Expand Down
10 changes: 7 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ urls = {Homepage = "https://github.com/zeroasiccorp/umi"}
requires-python = ">= 3.9"
license = {file = "LICENSE"}
dependencies = [
"siliconcompiler >= 0.35.0",
"siliconcompiler >= 0.36.5",
"lambdalib >= 0.4.0, < 0.11.0"
]
dynamic = ["version"]
Expand All @@ -32,7 +32,10 @@ test = [
"pytest-xdist == 3.8.0",
"pytest-timeout == 2.4.0",
"flake8 == 7.3.0",
"switchboard-hw == 0.3.0"
"switchboard-hw == 0.3.1",
"cocotb==2.0.1",
"cocotb-bus==0.3.0",
"cocotbext-umi==0.0.2"
]

[tool.check-wheel-contents]
Expand All @@ -42,7 +45,8 @@ ignore = [

[tool.pytest.ini_options]
markers = [
"switchboard: this test requires switchboard to run"
"switchboard: this test requires switchboard to run",
"cocotb: this test requires cocotb to run"
]
testpaths = [
"tests",
Expand Down
1 change: 1 addition & 0 deletions tests/sumi/umi_stream/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
!icarus_cmd_file.f
1 change: 1 addition & 0 deletions tests/sumi/umi_stream/icarus_cmd_file.f
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
+timescale+1ns/1ps
140 changes: 140 additions & 0 deletions tests/sumi/umi_stream/run_cocotb_sim.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
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("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("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}")
Loading