Skip to content

Commit 5484281

Browse files
committed
fixed SV bbox bus msb; black formatting
fixed snapping which was creating off-grid pins added calc_y_step unit test + black formatting Signed-off-by: Jeff Ng <[email protected]>
1 parent db3968e commit 5484281

File tree

8 files changed

+124
-18
lines changed

8 files changed

+124
-18
lines changed

__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
# To get relative imports to work
2-
import os, sys; sys.path.append(os.path.dirname(os.path.realpath(__file__)))
2+
import os, sys
3+
4+
sys.path.append(os.path.dirname(os.path.realpath(__file__)))

test/au/spsram_256x256.au

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5039,7 +5039,7 @@ module spsram_256x256
50395039
endmodule
50405040
(* blackbox *)
50415041
module spsram_256x256 (
5042-
output reg [31:0] rd_out,
5042+
output reg [255:0] rd_out,
50435043
input [7:0] addr_in,
50445044
input we_in,
50455045
input [255:0] wd_in,

test/physical_test.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ class PhysicalDataTest(unittest.TestCase):
1515
def setUp(self):
1616
"""Sets up base_data with example config data"""
1717

18-
1918
def test_empty_physical(self):
2019
"""Tests physical field defaults"""
2120

@@ -39,7 +38,7 @@ def test_set_extents_and_snapping(self):
3938
# Can't snap before setting extents
4039
with self.assertRaises(Exception):
4140
physical.snap_to_grid(1000, 1000)
42-
41+
4342
# Set extents and verify values
4443
physical.set_extents(width, height)
4544
self.assertEqual(physical.get_width(False), width)
@@ -73,13 +72,13 @@ def test_pin_pitches_exception(self):
7372
# Can't set pin pitches before setting height
7473
with self.assertRaises(Exception):
7574
physical.set_pin_pitches("bogus", num_pins, min_pin_pitch, y_offset)
76-
75+
7776
# Try again after setting height
7877
physical.set_extents(height, height)
7978
physical.snap_to_grid(1, 1)
8079
with self.assertRaises(Exception):
8180
physical.set_pin_pitches("bogus", num_pins, min_pin_pitch, y_offset)
82-
83-
81+
82+
8483
if __name__ == "__main__":
8584
unittest.main()

test/process_test.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,29 @@ def test_bitcell_override(self):
153153
self.assertEqual(bitcell_width, process_data["bitcell_width_um"])
154154
self.assertEqual(bitcell_height, process_data["bitcell_height_um"])
155155

156+
def test_y_step_calc(self):
157+
"""
158+
Tests y_step calculation
159+
160+
y_step = pin_pitch (snapped to grid) + pin_width / 2
161+
"""
162+
163+
process = Process(self._base_data)
164+
process._calc_y_step()
165+
# 0.048 + (0.024 / 2) = 0.06
166+
self.assertEqual(process.get_y_step(), 0.06)
167+
168+
# change to different pitch that previously didn't get snapped right
169+
# and try again
170+
base_data = self._base_data.copy()
171+
base_data["metal_track_pitch_nm"] = 23
172+
base_data["pin_pitch_nm"] = 2 * base_data["metal_track_pitch_nm"]
173+
base_data["pin_width_nm"] = 12
174+
process = Process(base_data)
175+
# 0.046 + (0.024 / 2) = 0.06
176+
process._calc_y_step()
177+
self.assertEqual(process.get_y_step(), 0.052)
178+
156179

157180
if __name__ == "__main__":
158181
unittest.main()

test/sv_bbox_test.py

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
#!/usr/bin/env python3
2+
3+
import os
4+
import re
5+
import io
6+
import sys
7+
import unittest
8+
9+
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "utils")))
10+
from single_port_ram_verilog_exporter import SinglePortRAMVerilogExporter
11+
from memory_factory import MemoryFactory
12+
from class_process import Process
13+
from timing_data import TimingData
14+
from test_utils import TestUtils
15+
16+
17+
class SVBBoxDataTest(unittest.TestCase):
18+
"""Unit test for SystemVerilog blackbox class"""
19+
20+
def setUp(self):
21+
"""Sets up base_data with example config data"""
22+
self._process = Process(TestUtils.get_base_process_data())
23+
self._timing_data = TimingData()
24+
self._bus_re = re.compile(
25+
"^\s*\S+\s+(?:reg)?\s*\[\s*(\d+)\:(\d+)\\s*]\s*(\S+)\s*\,"
26+
)
27+
28+
def _extract_bus_msb(self, content):
29+
msb_map = {}
30+
in_strm = io.StringIO(content)
31+
32+
for line in in_strm:
33+
result = self._bus_re.match(line)
34+
if result:
35+
msb = int(result.group(1))
36+
bus_name = result.group(3)
37+
msb_map[bus_name] = msb
38+
return msb_map
39+
40+
def _check_bus_msb(self, mem_name, bus_name, bus_msb_map, exp_msb):
41+
self.assertIn(bus_name, bus_msb_map)
42+
self.assertEqual(
43+
bus_msb_map[bus_name],
44+
exp_msb,
45+
f"msb's don't match for {bus_name} on {mem_name}: {bus_msb_map[bus_name]} {exp_msb}",
46+
)
47+
48+
def _check_bbox(self, words, depth):
49+
name = f"fakeram_16_{depth}"
50+
mem = MemoryFactory.create(
51+
name, words, depth, 4, "RAM", "SP", self._process, self._timing_data
52+
)
53+
exporter = SinglePortRAMVerilogExporter(mem)
54+
strm = io.StringIO()
55+
exporter.export_blackbox(strm)
56+
content = strm.getvalue()
57+
strm.close()
58+
bus_msb_map = self._extract_bus_msb(content)
59+
self._check_bus_msb(name, "rd_out", bus_msb_map, mem.get_data_bus_msb())
60+
self._check_bus_msb(name, "wd_in", bus_msb_map, mem.get_data_bus_msb())
61+
self._check_bus_msb(name, "addr_in", bus_msb_map, mem.get_addr_bus_msb())
62+
63+
def test_spsram_bbox(self):
64+
"""
65+
Tests that the spsram rd_out and wd_in indices are the same and
66+
correct
67+
"""
68+
69+
words = 16
70+
depths = [32, 64, 256]
71+
for depth in depths:
72+
self._check_bbox(words, depth)
73+
74+
75+
if __name__ == "__main__":
76+
unittest.main()

test/test_utils.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import os
44

5+
56
class TestUtils:
67
@staticmethod
78
def get_base_process_data():
@@ -31,7 +32,6 @@ def get_exec_name(exec_name):
3132

3233
if "COVERAGE_RUN" in os.environ:
3334
exec_cmd = "coverage run --parallel-mode " + exec_name
34-
else: #pragma: nocover
35+
else: # pragma: nocover
3536
exec_cmd = exec_name
3637
return exec_cmd
37-

utils/class_process.py

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ def __init__(self, json_data):
2020
self.pin_width_nm = int(json_data["pin_width_nm"])
2121
self.pin_pitch_nm = int(json_data["pin_pitch_nm"])
2222
self.metal_track_pitch_nm = int(json_data["metal_track_pitch_nm"])
23-
self.contacted_poly_pitch_nm = int(json_data["contacted_poly_pitch_nm"])
24-
self.fin_pitch_nm = int(json_data["fin_pitch_nm"])
23+
self.contacted_poly_pitch_nm = json_data.get("contacted_poly_pitch_nm", None)
24+
self.fin_pitch_nm = json_data.get("fin_pitch_nm", None)
2525
self.manufacturing_grid_nm = int(json_data["manufacturing_grid_nm"])
2626
self.column_mux_factor = int(json_data["column_mux_factor"])
2727

@@ -57,15 +57,21 @@ def __init__(self, json_data):
5757
self.y_offset = 1 * self.pin_pitch_um
5858
# as told by MSK
5959

60-
self.y_step = (
61-
self.y_offset
62-
- (self.y_offset % self.manufacturing_grid_um)
63-
+ (self.pin_width_um / 2.0)
64-
)
65-
60+
self._calc_y_step()
6661
self.bitcell_width_um = json_data.get("bitcell_width_um", None)
6762
self.bitcell_height_um = json_data.get("bitcell_height_um", None)
6863

64+
def _calc_y_step(self):
65+
"""
66+
Calculates y_step, which is really the y location for the center of
67+
the first pin
68+
"""
69+
70+
offset_snap = round(self.y_offset % self.manufacturing_grid_um, 2)
71+
if offset_snap < self.manufacturing_grid_um:
72+
offset_snap = 0
73+
self.y_step = self.y_offset - offset_snap + (self.pin_width_um / 2.0)
74+
6975
def has_defined_bitcell_size(self):
7076
return self.bitcell_width_um and self.bitcell_height_um
7177

utils/single_port_ram_verilog_exporter.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ def export_blackbox(self, out_fh):
116116
addr_bus_msb = mem.get_addr_bus_msb()
117117
data_bus_msb = mem.get_data_bus_msb()
118118
self.export_bb_header(out_fh)
119-
out_fh.write(f" output reg [31:0] rd_out,\n")
119+
out_fh.write(f" output reg [{data_bus_msb}:0] rd_out,\n")
120120
out_fh.write(f" input [{addr_bus_msb}:0] addr_in,\n")
121121
out_fh.write(" input we_in,\n")
122122
out_fh.write(f" input [{data_bus_msb}:0] wd_in,\n")

0 commit comments

Comments
 (0)