Skip to content
Merged
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
47 changes: 47 additions & 0 deletions tools/FakeRAM2.0/test/memory_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,53 @@ def test_memory(self):
self.assertEqual(timing_data.cycle_time_ns, 0.1566)
self.assertEqual(timing_data.fo4_ps, 9.0632)

def _create_sp_ram(self, process, width, depth):
mem_config = MemoryConfig.from_json(
{"name": "sample", "width": width, "depth": depth, "banks": 1}
)
return MemoryFactory.create(mem_config, "RAM", "SP", process, TimingData())

def _pin_height(self, process, memory):
return 2 * process.y_offset + memory.get_num_pins() * process.pin_pitch_um

def test_shallow_memory_is_tall_enough_for_its_pins(self):
"""
A 4x25 RAM's bitcells are 1.296 um tall, too short for its 55 pins;
it is made as tall as its pins need, snapped up to 2.8 um
"""

memory = self._create_sp_ram(self._process, 25, 4)
physical = memory.get_physical_data()
self.assertEqual(memory.get_num_pins(), 55)
self.assertGreaterEqual(
physical.get_height(), self._pin_height(self._process, memory)
)
self.assertAlmostEqual(physical.get_height(), 2.8, delta=self._delta)

def test_deep_memory_keeps_bitcell_height(self):
"""A memory whose bitcells already fit its pins is not made taller"""

memory = self._create_sp_ram(self._process, 32, 64)
_, height = self._process.get_macro_dimensions(32, 64, 1, 0)
self.assertGreater(height, self._pin_height(self._process, memory))
self.assertAlmostEqual(
memory.get_physical_data().get_height(), 21.0, delta=self._delta
)

def test_pins_fit_exactly_without_snapping(self):
"""
With a 1 nm snap the height is exactly what the pins need, and
every pin still gets a track
"""

process_data = TestUtils.get_base_process_data().copy()
process_data["snap_height_nm"] = 1
process = Process(process_data)
for width in range(1, 300):
# constructing the memory raises if its pins do not fit
memory = self._create_sp_ram(process, width, 4)
self.assertGreaterEqual(memory.get_physical_data().get_pin_pitch(), 0)


if __name__ == "__main__":
unittest.main()
9 changes: 8 additions & 1 deletion tools/FakeRAM2.0/utils/class_memory.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,18 @@ def __init__(self, mem_config, process, timing_data):
width_um, height_um = self.process.get_macro_dimensions(
self.width_in_bits, self.depth, self.num_banks, self.additional_height
)
# Signal pins are stacked one per track up the left edge, inset
# by y_offset at both ends, so the macro must be at least that
# tall; a shallow memory with many pins is otherwise too short
num_pins = self.get_num_pins()
height_um = max(
height_um,
2 * self.process.y_offset + num_pins * self.process.pin_pitch_um,
)
self.physical.set_extents(width_um, height_um)
self.physical.snap_to_grid(
self.process.snap_width_nm, self.process.snap_height_nm
)
num_pins = self.get_num_pins()
self.physical.set_pin_pitches(
self.get_name(),
num_pins,
Expand Down
5 changes: 0 additions & 5 deletions tools/FakeRAM2.0/utils/class_process.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,11 +119,6 @@ def get_macro_dimensions(self, width_in_bits, depth, num_banks, additional_heigh

total_height += additional_height

min_height = max(
3.5, self.snap_height_nm / 1000.0 if self.snap_height_nm else 0
)
total_height = max(total_height, min_height)

return (total_width, total_height)

def get_tech_nm(self):
Expand Down
6 changes: 5 additions & 1 deletion tools/FakeRAM2.0/utils/physical_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,11 @@ def set_pin_pitches(self, name, num_pins, min_pin_pitch, y_offset):
raise Exception(
f"Error: attempting to set pin pitches before height ({name})"
)
number_of_tracks_available = math.floor((h - 2 * y_offset) / min_pin_pitch)
# Rounded before flooring: a height that fits its pins exactly would
# otherwise lose a track to float error (e.g. 46.99999 -> 46)
number_of_tracks_available = math.floor(
round((h - 2 * y_offset) / min_pin_pitch, 6)
Comment thread
maliberty marked this conversation as resolved.
Resolved
)
number_of_spare_tracks = number_of_tracks_available - num_pins

if number_of_spare_tracks < 0:
Expand Down
Loading