Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
26a3c5a
Fix output ports to not have _oe signals
robtaylor Mar 18, 2025
6583f69
Add comprehensive test suite for improved code coverage
robtaylor Mar 16, 2025
184953f
Add comprehensive test suite for steps and software components
robtaylor Mar 16, 2025
c789ef3
Add comprehensive tests for pin_lock.py utilities
robtaylor Mar 16, 2025
684678a
Fix SiliconPlatformPort class and add comprehensive tests
robtaylor Mar 16, 2025
65b4de5
Fix warnings in test_instantiate_ports test
robtaylor Mar 16, 2025
0cfcd61
Fix test_instantiate_ports_missing_clock to eliminate warnings
robtaylor Mar 16, 2025
b6566e0
Fix remaining warnings in test suite
robtaylor Mar 16, 2025
974edd6
Fix all warnings in test suite
robtaylor Mar 16, 2025
09e6177
Add specific test commands for silicon.py coverage
robtaylor Mar 16, 2025
3706346
Add test for instantiate_ports with clocks and resets
robtaylor Mar 16, 2025
ce78785
Fix output ports to not have output enable signals (_oe)
robtaylor Mar 18, 2025
3fef143
Rewrite skipped tests in test_pin_lock_complete.py for Pydantic models
robtaylor Mar 19, 2025
77de7f8
Fix skipped test in test_pin_lock_complete.py using real Pydantic obj…
robtaylor Mar 19, 2025
30dc546
Fix test_pin_lock_advanced.py to use correct Pydantic models
robtaylor Mar 19, 2025
f081653
Update tests to improve Pydantic compatibility
robtaylor Mar 19, 2025
ba133a2
Fix lint issues in test files
robtaylor Mar 19, 2025
16b80e0
Fix lint issues in test_pin_lock_complete.py
robtaylor Mar 19, 2025
592d51e
Fix lint issues in amaranth test files
robtaylor Mar 19, 2025
73c3689
Fix lint issues in additional test files
robtaylor Mar 19, 2025
f53a43e
Refactor test_pin_lock.py to use Pydantic objects instead of mocks
robtaylor Mar 19, 2025
b77406b
Fix test_pin_lock.py by removing non-existent function import
robtaylor Mar 19, 2025
b8175d2
Fix test_pin_lock.py to use actual _QuadPackageDef instead of mock
robtaylor Mar 19, 2025
dc7687f
Add test for config.json content generated by SiliconStep.submit
robtaylor Mar 20, 2025
ca1d660
Update Process enum __str__ method to return the enum value instead o…
robtaylor Mar 20, 2025
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
67 changes: 13 additions & 54 deletions chipflow_lib/platforms/silicon.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,11 @@
import os
import subprocess

from dataclasses import dataclass

from amaranth import Module, Signal, Cat, ClockDomain, ClockSignal, ResetSignal

from amaranth.lib import wiring, io
from amaranth.lib import io
from amaranth.lib.cdc import FFSynchronizer
from amaranth.lib.wiring import Component, In, PureInterface
from amaranth.lib.wiring import PureInterface

from amaranth.back import rtlil
from amaranth.hdl import Fragment
Expand All @@ -25,44 +23,6 @@
logger = logging.getLogger(__name__)


def make_hashable(cls):
def __hash__(self):
return hash(id(self))

def __eq__(self, obj):
return id(self) == id(obj)

cls.__hash__ = __hash__
cls.__eq__ = __eq__
return cls


HeartbeatSignature = wiring.Signature({"heartbeat_i": In(1)})


@make_hashable
@dataclass
class Heartbeat(Component):
clock_domain: str = "sync"
counter_size: int = 23
name: str = "heartbeat"

def __init__(self, ports):
super().__init__(HeartbeatSignature)
self.ports = ports

def elaborate(self, platform):
m = Module()
# Heartbeat LED (to confirm clock/reset alive)
heartbeat_ctr = Signal(self.counter_size)
getattr(m.d, self.clock_domain).__iadd__(heartbeat_ctr.eq(heartbeat_ctr + 1))

heartbeat_buffer = io.Buffer("o", self.ports.heartbeat)
m.submodules.heartbeat_buffer = heartbeat_buffer
m.d.comb += heartbeat_buffer.o.eq(heartbeat_ctr[-1])
return m


class SiliconPlatformPort(io.PortLike):
def __init__(self,
component: str,
Expand Down Expand Up @@ -90,40 +50,37 @@ def __init__(self,
self._oe = Signal(port.width, name=f"{component}_{name}__oe", init=-1)
else:
self._oe = Signal(1, name=f"{component}_{name}__oe", init=-1)
elif self._direction is io.Direction.Output:
# Always create an _oe for output ports
self._oe = Signal(1, name=f"{component}_{name}__oe", init=-1)

logger.debug(f"Created SiliconPlatformPort {name}, width={len(port.pins)},dir{self._direction}")

def wire(self, m: Module, interface: PureInterface):
assert self._direction == interface.signature.direction
if hasattr(interface, 'i'):
m.d.comb += interface.i.eq(self.i)
for d in ['o', 'oe']:
if hasattr(interface, d):
m.d.comb += getattr(self, d).eq(getattr(interface, d))
if hasattr(interface, 'o'):
m.d.comb += self.o.eq(interface.o)
if hasattr(interface, 'oe') and self._oe is not None:
m.d.comb += self.oe.eq(interface.oe)

@property

def i(self):
if self._i is None:
raise AttributeError("SiliconPlatformPort with output direction does not have an "
"input signal")
"input signal")
return self._i

@property
def o(self):
if self._o is None:
raise AttributeError("SiliconPlatformPort with input direction does not have an "
"output signal")
"output signal")
return self._o

@property
def oe(self):
if self._oe is None:
raise AttributeError("SiliconPlatformPort with input direction does not have an "
"output enable signal")
raise AttributeError("SiliconPlatformPort with output or input direction does not have an "
"output enable signal")
return self._oe

@property
Expand Down Expand Up @@ -217,7 +174,9 @@ def elaborate(self, platform):
m.d.comb += i_inv.eq(self.port.i)
if self.direction in (io.Direction.Output, io.Direction.Bidir):
m.d.comb += self.port.o.eq(o_inv)
m.d.comb += self.port.oe.eq(self.oe)
# Only set oe for bidirectional ports
if self.direction is io.Direction.Bidir:
m.d.comb += self.port.oe.eq(self.oe)

return m

Expand Down
2 changes: 1 addition & 1 deletion chipflow_lib/platforms/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,7 @@ class Process(enum.Enum):
IHP_SG13G2 = "ihp_sg13g2"

def __str__(self):
return f'{self.name}'
return f'{self.value}'


class LockFile(pydantic.BaseModel):
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ test-docs.cmd = "sphinx-build -b doctest docs/ docs/_build"
lint.cmd = "ruff check"
docs.cmd = "sphinx-build docs/ docs/_build/ -W --keep-going"
test-silicon.cmd = "pytest tests/test_silicon_platform.py tests/test_silicon_platform_additional.py tests/test_silicon_platform_amaranth.py tests/test_silicon_platform_build.py tests/test_silicon_platform_port.py --cov=chipflow_lib.platforms.silicon --cov-report=term"
test-silicon-html.cmd = "pytest tests/test_silicon_platform.py tests/test_silicon_platform_additional.py tests/test_silicon_platform_amaranth.py tests/test_silicon_platform_build.py tests/test_silicon_platform_port.py --cov=chipflow_lib.platforms.silicon --cov-report=html"


[dependency-groups]
Expand Down
21 changes: 21 additions & 0 deletions tests/test_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# SPDX-License-Identifier: BSD-2-Clause
import os
import unittest

from chipflow_lib.config import get_dir_models, get_dir_software


class TestConfig(unittest.TestCase):
def test_get_dir_models(self):
"""Test get_dir_models returns the correct path"""
# Since we can't predict the absolute path, we'll check that it ends correctly
models_dir = get_dir_models()
self.assertTrue(models_dir.endswith("/chipflow_lib/models"))
self.assertTrue(os.path.isdir(models_dir))

def test_get_dir_software(self):
"""Test get_dir_software returns the correct path"""
# Since we can't predict the absolute path, we'll check that it ends correctly
software_dir = get_dir_software()
self.assertTrue(software_dir.endswith("/chipflow_lib/software"))
self.assertTrue(os.path.isdir(software_dir))
21 changes: 21 additions & 0 deletions tests/test_errors.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# SPDX-License-Identifier: BSD-2-Clause
import unittest

from chipflow_lib.errors import ChipFlowError


class TestErrors(unittest.TestCase):
def test_chipflow_error(self):
"""Test that ChipFlowError can be instantiated and raised"""
# Test instantiation
error = ChipFlowError("Test error message")
self.assertEqual(str(error), "Test error message")

# Test raising
with self.assertRaises(ChipFlowError) as cm:
raise ChipFlowError("Test raised error")

self.assertEqual(str(cm.exception), "Test raised error")

# Test inheritance
self.assertTrue(issubclass(ChipFlowError, Exception))
Loading
Loading