Merge branch 'singleport_refactor' into array_gen

This commit is contained in:
Jesse Cirimelli-Low
2025-02-24 23:26:28 -08:00
35 changed files with 1133 additions and 2828 deletions
+49 -43
View File
@@ -4,6 +4,8 @@
# All rights reserved.
#
from openram import debug
from openram.base import round_to_grid
from openram.tech import drc
from openram.base import vector
from openram.base import contact
from openram.sram_factory import factory
@@ -74,7 +76,7 @@ class replica_bitcell_array(bitcell_base_array):
""" Array and dummy/replica columns """
# Bitcell array
self.bitcell_array = factory.create(module_type="bitcell_array",
column_offset=1 + len(self.left_rbl),
column_offset=len(self.left_rbl),
cols=self.column_size,
rows=self.row_size)
@@ -87,11 +89,11 @@ class replica_bitcell_array(bitcell_base_array):
if port in self.left_rbl:
# These go top down starting from the bottom of the bitcell array.
replica_bit = self.rbl[0] - port - 1
column_offset = len(self.left_rbl)
column_offset = 0
elif port in self.right_rbl:
# These go bottom up starting from the top of the bitcell array.
replica_bit = self.rbl[0] + self.row_size + port - 1
column_offset = len(self.left_rbl) + self.column_size + 1
column_offset = len(self.left_rbl) + self.column_size
else:
continue
@@ -102,14 +104,24 @@ class replica_bitcell_array(bitcell_base_array):
replica_bit=replica_bit)
# Dummy row (for replica wordlines)
self.dummy_row = factory.create(module_type="dummy_array",
self.dummy_rows = {}
for port in self.all_ports:
if port in self.left_rbl:
row_offset = self.row_size
mirror = row_offset % 2 + 1
elif port in self.right_rbl:
row_offset = 0
mirror = 0
else:
continue
self.dummy_rows[port] = factory.create(module_type="dummy_array",
cols=self.column_size,
rows=1,
# cap column + left replica column
# FIXME: these col offsets should really start at 0 because
# this is the left edge of the array... but changing them all is work
column_offset=1 + len(self.left_rbl),
mirror=0)
row_offset=row_offset,
column_offset=len(self.left_rbl),
mirror=mirror)
def add_pins(self):
@@ -213,7 +225,7 @@ class replica_bitcell_array(bitcell_base_array):
for port in self.all_ports: # TODO: tie to self.rbl or whatever
if self.rbl[port] != 0:
self.dummy_row_replica_insts.append(self.add_inst(name="dummy_row_{}".format(port),
mod=self.dummy_row))
mod=self.dummy_rows[port]))
self.connect_inst(self.all_bitline_names + self.rbl_wordline_names[port] + self.supplies)
else:
self.dummy_row_replica_insts.append(None)
@@ -225,28 +237,28 @@ class replica_bitcell_array(bitcell_base_array):
self.vertical_pitch = 1.1 * getattr(self, "{}_pitch".format(self.supply_stack[0]))
self.horizontal_pitch = 1.1 * getattr(self, "{}_pitch".format(self.supply_stack[2]))
# This is a bitcell x bitcell offset to scale
self.bitcell_offset = vector(self.cell.width, self.cell.height)
self.col_end_offset = vector(self.cell.width, self.cell.height)
self.row_end_offset = vector(self.cell.width, self.cell.height)
# Everything is computed with the main array
self.bitcell_array_inst.place(offset=0)
self.bitcell_array_inst.place(offset=(0,0))
self.add_replica_columns()
# Array was at (0, 0) but move everything so it is at the lower left
# We move DOWN the number of left RBL even if we didn't add the column to this bitcell array
# Note that this doesn't include the row/col cap
array_offset = self.bitcell_offset.scale(-len(self.left_rbl), -self.rbl[0])
self.translate_all(array_offset)
#rbc_width = (self.replica_col_insts[0].width, 0)
#dummy_height = max(x for x in map(lambda x: x if x != None else 0, self.))
#array_offset = self.bitcell_offset.scale(-len(self.left_rbl), -self.rbl[0])
ll=vector(min([x.lx() for x in self.insts]),min([y.by() for y in self.insts]))
self.translate_all(ll)
self.add_layout_pins()
self.route_supplies()
self.height = (sum(self.rbl) + self.row_size) * self.cell.height
self.width = (len(self.rbls) + self.column_size) * self.cell.width
self.width = max([x.rx() for x in self.insts]) - min([x.lx() for x in self.insts])
self.height = max([x.uy() for x in self.insts]) - min([y.by() for y in self.insts])
self.add_boundary()
@@ -280,25 +292,24 @@ class replica_bitcell_array(bitcell_base_array):
# Grow from left to right, toward the array
for bit, port in enumerate(self.left_rbl):
offset = self.bitcell_offset.scale(-len(self.left_rbl) + bit, -self.rbl[0])
rbc_dimension = vector(self.replica_col_insts[port].width, self.cell.height)
offset = rbc_dimension.scale(-len(self.left_rbl) + bit, -self.rbl[0])
self.replica_col_insts[bit].place(offset)
# Grow to the right of the bitcell array, array outward
for bit, port in enumerate(self.right_rbl):
offset = self.bitcell_array_inst.lr() + self.bitcell_offset.scale(bit, -self.rbl[0])
offset = self.bitcell_array_inst.lr() + rbc_dimension.scale(bit, -self.rbl[0])
self.replica_col_insts[self.rbl[0] + bit].place(offset)
# Replica dummy rows
# Add the dummy rows even if we aren't adding the replica column to this bitcell array
# These grow up, toward the array
for bit in range(self.rbl[0]):
dummy_offset = self.bitcell_offset.scale(0, -self.rbl[0] + bit + (-self.rbl[0] + bit) % 2)
self.dummy_row_replica_insts[bit].place(offset=dummy_offset,
mirror="MX" if (-self.rbl[0] + bit) % 2 else "R0")
dummy_offset = self.bitcell_array_inst.ll() - vector(0, self.dummy_row_replica_insts[bit].height)
self.dummy_row_replica_insts[bit].place(offset=dummy_offset)
# These grow up, away from the array
for bit in range(self.rbl[1]):
dummy_offset = self.bitcell_offset.scale(0, bit + bit % 2) + self.bitcell_array_inst.ul()
self.dummy_row_replica_insts[self.rbl[0] + bit].place(offset=dummy_offset,
mirror="MX" if (self.row_size + bit) % 2 else "R0")
dummy_offset = self.bitcell_array_inst.ul()
self.dummy_row_replica_insts[self.rbl[0] + bit].place(offset=dummy_offset)
def add_layout_pins(self):
""" Add the layout pins """
@@ -316,14 +327,15 @@ class replica_bitcell_array(bitcell_base_array):
# Replica wordlines (go by the row instead of replica column because we may have to add a pin
# even though the column is in another local bitcell array)
for (names, inst) in zip(self.rbl_wordline_names, self.dummy_row_replica_insts):
for (wl_name, pin_name) in zip(names, self.dummy_row.get_wordline_names()):
pin = inst.get_pin(pin_name)
self.add_layout_pin(text=wl_name,
layer=pin.layer,
offset=pin.ll().scale(0, 1),
width=self.width,
height=pin.height())
if self.rbl != [0,0]:
for (names, inst) in zip(self.rbl_wordline_names, self.dummy_row_replica_insts):
for (wl_name, pin_name) in zip(names, self.dummy_rows[0].get_wordline_names()):
pin = inst.get_pin(pin_name)
self.add_layout_pin(text=wl_name,
layer=pin.layer,
offset=pin.ll().scale(0, 1),
width=self.width,
height=pin.height())
# Main array bl/br
for pin_name in self.all_bitline_names:
@@ -347,12 +359,6 @@ class replica_bitcell_array(bitcell_base_array):
width=pin.width(),
height=self.height)
def route_supplies(self):
""" just copy supply pins from all instances """
for inst in self.insts:
for pin_name in ["vdd", "gnd"]:
self.copy_layout_pin(inst, pin_name)
def analytical_power(self, corner, load):
"""Power of Bitcell array and bitline in nW."""
# Dynamic Power from Bitline