Skip to content

Commit e415a26

Browse files
committed
tests: Update tests for pin-lock functionality
1 parent fc9ea00 commit e415a26

File tree

6 files changed

+199
-49
lines changed

6 files changed

+199
-49
lines changed

tests/fixtures/chipflow-flexic.toml

Lines changed: 0 additions & 35 deletions
This file was deleted.

tests/fixtures/mock.toml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
[chipflow]
2+
project_name = "proj-name"
3+
4+
[chipflow.steps]
5+
silicon = "chipflow_lib.steps.silicon:SiliconStep"
6+
7+
[chipflow.silicon]
8+
process = "ihp_sg13g2"
9+
package = "pga144"
10+
11+
[chipflow.clocks]
12+
default = 'sys_clk'
13+
14+
[chipflow.resets]
15+
default = 'sys_rst_n'
16+
17+
[chipflow.silicon.pads]
18+
sys_clk = { type = "clk", loc = "N3" }
19+
sys_rst_n = { type = "i", loc = "N4" }
20+
21+
[chipflow.silicon.power]
22+
vss = { loc = "N1" }
23+
vssio = { loc = "N5" }
24+
vddio = { loc = "N6" }
25+
vdd = { loc = "N7" }

tests/fixtures/mock_top.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# SPDX-License-Identifier: BSD-2-Clause
2+
from amaranth import Module
3+
from amaranth.lib import wiring
4+
from amaranth.lib.wiring import In, Out
5+
6+
from chipflow_lib.platforms import InputPinSignature, OutputPinSignature, BidirPinSignature
7+
8+
__all__ = ["MockTop"]
9+
10+
TestSignature1 = wiring.Signature({
11+
"a": In(InputPinSignature(1)),
12+
"b": In(InputPinSignature(5)),
13+
"c": Out(OutputPinSignature(1)),
14+
"d": Out(OutputPinSignature(10)),
15+
"e": In(BidirPinSignature(1)),
16+
"f": In(BidirPinSignature(7)),
17+
})
18+
19+
TestSignature2 = wiring.Signature({
20+
"a": Out(OutputPinSignature(1)),
21+
"b": Out(OutputPinSignature(5)),
22+
"c": In(InputPinSignature(1)),
23+
"d": In(InputPinSignature(10)),
24+
"e": Out(BidirPinSignature(1)),
25+
"f": Out(BidirPinSignature(7)),
26+
})
27+
28+
29+
# ---------
30+
31+
class MockTop(wiring.Component):
32+
def __init__(self):
33+
# Top level interfaces
34+
35+
interfaces = {
36+
"test1" : Out(TestSignature1),
37+
"test2": Out(TestSignature2)
38+
}
39+
40+
super().__init__(interfaces)
41+
42+
def elaborate(self, platform):
43+
m = Module()
44+
for inpin, outpin in zip(self.test1.members, self.test2.members):
45+
m.d.comb += inpin.eq(outpin)
46+
47+
return m

tests/test_silicon_platform.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@
22
# SPDX-License-Identifier: BSD-2-Clause
33

44
import os
5-
65
import unittest
6+
7+
import tomli
8+
79
from amaranth import *
8-
from amaranth.hdl import Fragment
910
from amaranth.hdl._ir import Design
1011

1112
from chipflow_lib import ChipFlowError
@@ -15,19 +16,23 @@
1516
class SiliconPlatformTestCase(unittest.TestCase):
1617
def setUp(self):
1718
os.environ["CHIPFLOW_ROOT"] = os.path.dirname(os.path.dirname(__file__))
19+
current_dir = os.path.dirname(__file__)
20+
customer_config = f"{current_dir}/fixtures/mock.toml"
21+
with open(customer_config, "rb") as f:
22+
self.config = tomli.load(f)
1823

1924
def test_sync_domain_works(self):
2025
m = Module()
2126
m.domains += ClockDomain("sync")
2227

23-
fragment = SiliconPlatform(pads={})._prepare(m)
28+
fragment = SiliconPlatform(self.config)._prepare(m)
2429
self.assertIsInstance(fragment, Design)
2530

2631
def test_subfragment_works(self):
2732
m = Module()
2833
m.submodules += Module()
2934

30-
fragment = SiliconPlatform(pads={})._prepare(m)
35+
fragment = SiliconPlatform(self.config)._prepare(m)
3136
self.assertIsInstance(fragment, Design)
3237

3338
def test_wrong_clock_domain_name(self):
@@ -37,4 +42,4 @@ def test_wrong_clock_domain_name(self):
3742
with self.assertRaisesRegex(
3843
ChipFlowError,
3944
r"^Only a single clock domain, called 'sync', may be used$"):
40-
SiliconPlatform(pads={}).build(m)
45+
SiliconPlatform(self.config).build(m)

tests/test_silicon_step.py

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
# SPDX-License-Identifier: BSD-2-Clause
2-
32
import io
43
import json
54
import os
65
import tomli
76
import unittest
87
from contextlib import redirect_stdout
8+
from pprint import pformat
99
from unittest.mock import patch
1010

1111
from chipflow_lib.steps.silicon import SiliconStep
@@ -29,7 +29,7 @@ def json(self):
2929
"msg": "msg",
3030
"url": "https://example.com/build-url/",
3131
"name": "name",
32-
"id": 123,
32+
"id": "proj-name",
3333
}, 200)
3434

3535
return MockResponse(None, 404)
@@ -41,9 +41,10 @@ def setUp(self):
4141
os.environ["CHIPFLOW_API_KEY_ID"] = "keyid"
4242
os.environ["CHIPFLOW_API_KEY_SECRET"] = "keysecret"
4343

44+
@patch('dotenv.load_dotenv')
4445
@patch('requests.post', side_effect=mocked_requests_post)
45-
def test_submit_happy_path(self, mock_requests_post):
46-
customer_config = f"{current_dir}/fixtures/chipflow-flexic.toml"
46+
def test_submit_happy_path(self, mock_requests_post, mock_dotenv):
47+
customer_config = f"{current_dir}/fixtures/mock.toml"
4748
with open(customer_config, "rb") as f:
4849
config_dict = tomli.load(f)
4950

@@ -53,7 +54,7 @@ def test_submit_happy_path(self, mock_requests_post):
5354
with redirect_stdout(f):
5455
silicon_step.submit(current_dir + "/fixtures/mock.rtlil")
5556
output = f.getvalue()
56-
assert 'msg (#123: name); https://example.com/build-url/' in output, "The printed output is correct."
57+
assert 'msg (#proj-name: name); https://example.com/build-url/' in output, "The printed output is correct."
5758

5859
args = mock_requests_post.call_args_list[0][0]
5960
kwargs = mock_requests_post.call_args_list[0][1]
@@ -63,7 +64,7 @@ def test_submit_happy_path(self, mock_requests_post):
6364
rtlil = files["rtlil"].read()
6465
assert args[0] == 'https://app.chipflow-infra.com/api/builds'
6566
assert kwargs["auth"] == ("keyid", "keysecret")
66-
assert data["projectId"] == 123
67+
assert data["projectId"] == 'proj-name'
6768
assert isinstance(data["name"], str), "Name is a string"
6869
assert list(config["dependency_versions"]) == [
6970
"python",
@@ -73,10 +74,10 @@ def test_submit_happy_path(self, mock_requests_post):
7374
"amaranth-orchard", "amaranth-vexriscv",
7475
], "We have entries for the the dependency versions"
7576

77+
print(pformat(config))
7678
assert config["silicon"] == {
77-
'process': 'customer1',
78-
'pad_ring':
79-
'cf20',
79+
'process': 'ihp_sg13g2',
80+
'package': 'pga144',
8081
'pads': {},
8182
'power': {
8283
'vss': {'loc': 'N1'},
@@ -86,3 +87,5 @@ def test_submit_happy_path(self, mock_requests_post):
8687
}
8788
}
8889
assert rtlil == b"fake-rtlil", "The RTL file was passed through."
90+
91+
assert mock_dotenv.called

tests/test_utils.py

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
# SPDX-License-Identifier: BSD-2-Clause
2+
import itertools
3+
import logging
4+
import pytest #noqa
5+
6+
from pprint import pformat
7+
8+
from amaranth.lib import io
9+
10+
from chipflow_lib.platforms.utils import PinSignature, OutputPinSignature, InputPinSignature, BidirPinSignature, _PinAnnotation, _PinAnnotationModel
11+
from chipflow_lib.platforms.utils import PinList, _group_consecutive_items,_find_contiguous_sequence, _Side
12+
13+
14+
logger = logging.getLogger(__name__)
15+
16+
17+
def gen_quad_pins(width, height) -> PinList:
18+
return sorted(
19+
[e for e in itertools.product((_Side.N, _Side.S), range(width))] +
20+
[e for e in itertools.product((_Side.W, _Side.E), range(height))]
21+
)
22+
23+
24+
def test_group_consecutive_items_null():
25+
ordering = gen_quad_pins(50,60)
26+
pins = ordering.copy()
27+
groups = _group_consecutive_items(pins,pins)
28+
assert len(groups.keys()) == 1
29+
assert len(ordering) in groups.keys()
30+
31+
def test_group_consecutive_items_nonconsecutive():
32+
ordering = gen_quad_pins(50,60)
33+
pins = ordering[0:6] + ordering[7:70] + ordering[71:180] + ordering[181:]
34+
logger.debug(f"{ordering} {pins}")
35+
groups = _group_consecutive_items(ordering,pins)
36+
logger.debug(f"\n{pformat(groups)}")
37+
assert len(ordering) == 50*2 + 60*2
38+
assert len(groups.keys()) == 4
39+
assert sum(groups.keys()) == len(ordering) - 3
40+
assert 6 in groups.keys()
41+
assert 70 - 7 in groups.keys()
42+
assert 180 - 71 in groups.keys()
43+
assert len(ordering) -181 in groups.keys()
44+
45+
def test_find_contiguous_sequence():
46+
ordering = gen_quad_pins(50,60)
47+
pins = ordering[0:6] + ordering[7:70] + ordering[71:180] + ordering[181:]
48+
seq = _find_contiguous_sequence(ordering, pins, 120)
49+
logger.debug(f"\n{pformat(seq)}")
50+
logger.debug(f"{ordering[71:180] + ordering[181:191]}")
51+
assert len(seq) == 120
52+
assert seq == ordering[71:180] + ordering[181:192]
53+
54+
55+
def test_pin_signature():
56+
sig_bidir = PinSignature(io.Direction.Bidir, width=8)
57+
assert isinstance(sig_bidir, PinSignature)
58+
assert sig_bidir._direction == io.Direction.Bidir
59+
assert sig_bidir._width == 8
60+
assert "o" in sig_bidir.members
61+
assert "oe" in sig_bidir.members
62+
assert "i" in sig_bidir.members
63+
64+
sig_output = OutputPinSignature(width=4)
65+
assert isinstance(sig_output, PinSignature)
66+
assert sig_output._direction == io.Direction.Output
67+
assert sig_output._width == 4
68+
assert "o" in sig_output.members
69+
assert "oe" not in sig_output.members
70+
assert "i" not in sig_output.members
71+
72+
sig_input = InputPinSignature(width=2)
73+
assert isinstance(sig_input, PinSignature)
74+
assert sig_input._direction == io.Direction.Input
75+
assert sig_input._width == 2
76+
assert "o" not in sig_input.members
77+
assert "oe" not in sig_output.members
78+
assert "i" in sig_input.members
79+
80+
sig_bidir_fn = BidirPinSignature(width=1)
81+
assert isinstance(sig_bidir_fn, PinSignature)
82+
assert sig_bidir_fn._direction == io.Direction.Bidir
83+
assert sig_bidir_fn._width == 1
84+
assert "o" in sig_bidir_fn.members
85+
assert "oe" in sig_bidir_fn.members
86+
assert "i" in sig_bidir_fn.members
87+
88+
def test_pin_annotation_model():
89+
model = _PinAnnotationModel(direction=io.Direction.Output, width=32)
90+
assert model.direction == "o"
91+
assert model.width == 32
92+
93+
def test_pin_annotation():
94+
annotation = _PinAnnotation(direction=io.Direction.Input, width=16)
95+
assert isinstance(annotation, _PinAnnotation)
96+
assert annotation.model.direction == "i"
97+
assert annotation.model.width == 16
98+
99+
def test_pin_annotation_as_json():
100+
annotation = _PinAnnotation(direction=io.Direction.Bidir, width=8)
101+
json_output = annotation.as_json()
102+
print(f"json_output: {json_output}") # Debug print using print()
103+
assert isinstance(json_output, dict)
104+
assert json_output["direction"] == "io"
105+
assert json_output["width"] == 8

0 commit comments

Comments
 (0)