mirror of
https://github.com/VLSIDA/OpenRAM.git
synced 2026-08-30 09:58:33 +02:00
Merge branch 'singleport_refactor' into array_gen
This commit is contained in:
@@ -51,10 +51,10 @@ class capped_replica_bitcell_array(bitcell_base_array):
|
||||
self.rbls = self.left_rbl + self.right_rbl
|
||||
|
||||
# Two dummy rows plus replica even if we don't add the column
|
||||
self.extra_rows = sum(self.rbl)
|
||||
self.extra_rows = sum(self.rbl) + 2
|
||||
# If we aren't using row/col caps, then we need to use the bitcell
|
||||
if not self.cell.end_caps:
|
||||
self.extra_rows += 2
|
||||
#if not self.cell.end_caps:
|
||||
# self.extra_rows += 2
|
||||
|
||||
self.create_netlist()
|
||||
if not OPTS.netlist_only:
|
||||
@@ -85,7 +85,7 @@ class capped_replica_bitcell_array(bitcell_base_array):
|
||||
cols=self.column_size + len(self.rbls),
|
||||
rows=1,
|
||||
# dummy column + left replica column(s)
|
||||
column_offset=1,
|
||||
column_offset=0,
|
||||
mirror=0,
|
||||
location="top")
|
||||
|
||||
@@ -93,7 +93,7 @@ class capped_replica_bitcell_array(bitcell_base_array):
|
||||
cols=self.column_size + len(self.rbls),
|
||||
rows=1,
|
||||
# dummy column + left replica column(s)
|
||||
column_offset=1,
|
||||
column_offset=0,
|
||||
mirror=0,
|
||||
location="bottom")
|
||||
|
||||
@@ -104,7 +104,7 @@ class capped_replica_bitcell_array(bitcell_base_array):
|
||||
cols=1,
|
||||
column_offset=0,
|
||||
rows=self.row_size + self.extra_rows,
|
||||
mirror=(self.rbl[0] + 1) % 2)
|
||||
location="left")
|
||||
|
||||
self.row_cap_right = factory.create(module_type=row_cap_module_type,
|
||||
cols=1,
|
||||
@@ -112,9 +112,9 @@ class capped_replica_bitcell_array(bitcell_base_array):
|
||||
# + left replica column(s)
|
||||
# + bitcell columns
|
||||
# + right replica column(s)
|
||||
column_offset=1 + len(self.left_rbl) + self.column_size + self.rbl[0],
|
||||
column_offset=len(self.left_rbl) + self.column_size + self.rbl[0],
|
||||
rows=self.row_size + self.extra_rows,
|
||||
mirror=(self.rbl[0] + 1) % 2)
|
||||
location="right")
|
||||
|
||||
def add_pins(self):
|
||||
|
||||
@@ -201,40 +201,34 @@ class capped_replica_bitcell_array(bitcell_base_array):
|
||||
# row-based or column based power and ground lines.
|
||||
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]))
|
||||
# FIXME: custom sky130 replica module has a better version of this offset
|
||||
self.unused_offset = vector(0.25, 0.25)
|
||||
|
||||
# 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 replica array
|
||||
self.replica_bitcell_array_inst.place(offset=self.unused_offset)
|
||||
self.replica_bitcell_array_inst.place(offset=0)
|
||||
|
||||
self.add_end_caps()
|
||||
|
||||
# shift everything up and right to account for cap cells
|
||||
self.translate_all(self.bitcell_offset.scale(-1, -1))
|
||||
|
||||
self.width = self.dummy_col_insts[1].rx() + self.unused_offset.x
|
||||
self.height = self.dummy_row_insts[1].uy()
|
||||
|
||||
self.add_layout_pins()
|
||||
ll = vector(-1 * self.dummy_col_insts[0].width, -1 * self.dummy_row_insts[0].height)
|
||||
self.translate_all(ll)
|
||||
self.capped_rba_width = self.dummy_col_insts[0].width + self.dummy_row_insts[0].width + self.dummy_col_insts[1].width
|
||||
self.capped_rba_height = self.dummy_col_insts[0].height
|
||||
|
||||
|
||||
#self.route_power_ring(self.supply_stack[2], self.supply_stack[0])
|
||||
self.route_supplies()
|
||||
|
||||
self.route_unused_wordlines()
|
||||
|
||||
lower_left = self.find_lowest_coords()
|
||||
upper_right = self.find_highest_coords()
|
||||
self.width = upper_right.x - lower_left.x
|
||||
self.height = upper_right.y - lower_left.y
|
||||
self.translate_all(lower_left)
|
||||
|
||||
self.reset_coordinates()
|
||||
self.add_layout_pins()
|
||||
self.add_boundary()
|
||||
|
||||
self.DRC_LVS()
|
||||
|
||||
|
||||
def route_power_ring(self, v_layer, h_layer):
|
||||
self.bbox = (vector(0,0), vector(self.capped_rba_width, self.capped_rba_height))
|
||||
self.supply_rail_width = drc["minwidth_m3"]
|
||||
self.supply_rail_pitch = 6 * self.supply_rail_width
|
||||
self.add_power_ring(v_layer=v_layer, h_layer=h_layer)
|
||||
|
||||
def get_main_array_top(self):
|
||||
return self.replica_bitcell_array_inst.by() + self.replica_bitcell_array.get_main_array_top()
|
||||
@@ -248,7 +242,7 @@ class capped_replica_bitcell_array(bitcell_base_array):
|
||||
def get_main_array_right(self):
|
||||
return self.replica_bitcell_array_inst.lx() + self.replica_bitcell_array.get_main_array_right()
|
||||
|
||||
# FIXME: these names need to be changed to reflect what they're actually returning
|
||||
#FIXME: these names need to be changed to reflect what they're actually returning
|
||||
def get_replica_top(self):
|
||||
return self.dummy_row_insts[1].by()
|
||||
|
||||
@@ -261,7 +255,6 @@ class capped_replica_bitcell_array(bitcell_base_array):
|
||||
def get_replica_right(self):
|
||||
return self.dummy_col_insts[1].rx()
|
||||
|
||||
|
||||
def get_column_offsets(self):
|
||||
"""
|
||||
Return an array of the x offsets of all the regular bits
|
||||
@@ -273,26 +266,23 @@ class capped_replica_bitcell_array(bitcell_base_array):
|
||||
def add_end_caps(self):
|
||||
""" Add dummy cells or end caps around the array """
|
||||
|
||||
# Far top dummy row (first row above array is NOT flipped if even number of rows)
|
||||
flip_dummy = (self.row_size + self.rbl[1]) % 2
|
||||
dummy_row_offset = self.bitcell_offset.scale(0, flip_dummy) + self.replica_bitcell_array_inst.ul()
|
||||
self.dummy_row_insts[1].place(offset=dummy_row_offset,
|
||||
mirror="MX" if flip_dummy else "R0")
|
||||
# Far top dummy row
|
||||
offset = self.replica_bitcell_array_inst.ul()
|
||||
self.dummy_row_insts[1].place(offset=offset)
|
||||
|
||||
# Far bottom dummy row (first row below array IS flipped)
|
||||
flip_dummy = (self.rbl[0] + 1) % 2
|
||||
dummy_row_offset = self.bitcell_offset.scale(0, flip_dummy - 1) + self.unused_offset
|
||||
self.dummy_row_insts[0].place(offset=dummy_row_offset,
|
||||
mirror="MX" if flip_dummy else "R0")
|
||||
# Far bottom dummy row
|
||||
dummy_row_height = vector(0, self.dummy_row_insts[0].height)
|
||||
offset = self.replica_bitcell_array_inst.ll() - dummy_row_height
|
||||
self.dummy_row_insts[0].place(offset=offset)
|
||||
|
||||
# Far left dummy col
|
||||
# Shifted down by the number of left RBLs even if we aren't adding replica column to this bitcell array
|
||||
dummy_col_offset = self.bitcell_offset.scale(-1, -1) + self.unused_offset
|
||||
self.dummy_col_insts[0].place(offset=dummy_col_offset)
|
||||
dummy_col_width = vector(self.dummy_col_insts[0].width, 0)
|
||||
offset = self.dummy_row_insts[0].ll() - dummy_col_width
|
||||
self.dummy_col_insts[0].place(offset=offset)
|
||||
|
||||
# Far right dummy col
|
||||
# Shifted down by the number of left RBLs even if we aren't adding replica column to this bitcell array
|
||||
dummy_col_offset = self.bitcell_offset.scale(0, -1) + self.replica_bitcell_array_inst.lr()
|
||||
self.dummy_col_insts[1].place(offset=dummy_col_offset)
|
||||
offset = self.dummy_row_insts[0].lr()
|
||||
self.dummy_col_insts[1].place(offset=offset)
|
||||
|
||||
def add_layout_pins(self):
|
||||
for pin_name in self.used_wordline_names + self.bitline_pin_list:
|
||||
@@ -301,13 +291,13 @@ class capped_replica_bitcell_array(bitcell_base_array):
|
||||
if "wl" in pin_name:
|
||||
# wordlines
|
||||
pin_offset = pin.ll().scale(0, 1)
|
||||
pin_width = self.width
|
||||
pin_width = self.capped_rba_width
|
||||
pin_height = pin.height()
|
||||
else:
|
||||
# bitlines
|
||||
pin_offset = pin.ll().scale(1, 0)
|
||||
pin_width = pin.width()
|
||||
pin_height = self.height
|
||||
pin_height = self.capped_rba_height
|
||||
|
||||
self.add_layout_pin(text=pin_name,
|
||||
layer=pin.layer,
|
||||
@@ -321,56 +311,83 @@ class capped_replica_bitcell_array(bitcell_base_array):
|
||||
bitcell = factory.create(module_type="pbitcell")
|
||||
else:
|
||||
bitcell = getattr(props, "bitcell_{}port".format(OPTS.num_ports))
|
||||
top = True
|
||||
bottom = True
|
||||
left = False
|
||||
right = False
|
||||
|
||||
if top:
|
||||
inst = self.dummy_row_insts[1]
|
||||
if "vdd" in inst.mod.pins:
|
||||
array_pins = inst.get_pins("vdd")
|
||||
for array_pin in array_pins:
|
||||
supply_pin = self.top_vdd_pin
|
||||
self.add_path(array_pin.layer, [array_pin.center(), vector(array_pin.center()[0], supply_pin.center()[1])])
|
||||
self.add_via_stack_center(from_layer = array_pin.layer,
|
||||
to_layer = supply_pin.layer,
|
||||
offset = vector(array_pin.center()[0], supply_pin.center()[1]))
|
||||
|
||||
vdd_dir = bitcell.vdd_dir
|
||||
gnd_dir = bitcell.gnd_dir
|
||||
array_pins = inst.get_pins("gnd")
|
||||
for array_pin in array_pins:
|
||||
supply_pin = self.top_gnd_pin
|
||||
self.add_path(array_pin.layer, [array_pin.center(), vector(array_pin.center()[0], supply_pin.center()[1])])
|
||||
self.add_via_stack_center(from_layer = array_pin.layer,
|
||||
to_layer = supply_pin.layer,
|
||||
offset = vector(array_pin.center()[0], supply_pin.center()[1]))
|
||||
if bottom:
|
||||
inst = self.dummy_row_insts[0]
|
||||
if "vdd" in inst.mod.pins:
|
||||
array_pins = inst.get_pins("vdd")
|
||||
for array_pin in array_pins:
|
||||
supply_pin = self.bottom_vdd_pin
|
||||
self.add_path(array_pin.layer, [array_pin.center(), vector(array_pin.center()[0], supply_pin.center()[1])])
|
||||
self.add_via_stack_center(from_layer = array_pin.layer,
|
||||
to_layer = supply_pin.layer,
|
||||
offset = vector(array_pin.center()[0], supply_pin.center()[1]))
|
||||
|
||||
# vdd/gnd are only connected in the perimeter cells
|
||||
supply_insts = self.dummy_col_insts + self.dummy_row_insts
|
||||
array_pins = inst.get_pins("gnd")
|
||||
for array_pin in array_pins:
|
||||
supply_pin = self.bottom_gnd_pin
|
||||
self.add_path(array_pin.layer, [array_pin.center(), vector(array_pin.center()[0], supply_pin.center()[1])])
|
||||
self.add_via_stack_center(from_layer = array_pin.layer,
|
||||
to_layer = supply_pin.layer,
|
||||
offset = vector(array_pin.center()[0], supply_pin.center()[1]))
|
||||
if left:
|
||||
inst = self.dummy_col_insts[0]
|
||||
if "vdd" in inst.mod.pins:
|
||||
array_pins = inst.get_pins("vdd")
|
||||
for array_pin in array_pins:
|
||||
supply_pin = self.left_vdd_pin
|
||||
self.add_path(array_pin.layer, [array_pin.center(), vector(supply_pin.center()[0], array_pin.center()[1])])
|
||||
self.add_via_stack_center(from_layer = array_pin.layer,
|
||||
to_layer = supply_pin.layer,
|
||||
offset = vector(supply_pin.center()[0], array_pin.center()[1]))
|
||||
|
||||
# For the wordlines
|
||||
top_bot_mult = 1
|
||||
left_right_mult = 1
|
||||
|
||||
# There are always vertical pins for the WLs on the left/right if we have unused wordlines
|
||||
self.left_gnd_locs = self.route_side_pin("gnd", "left", left_right_mult)
|
||||
self.right_gnd_locs = self.route_side_pin("gnd", "right", left_right_mult)
|
||||
# This needs to be big enough so that they aren't in the same supply routing grid
|
||||
left_right_mult = 4
|
||||
|
||||
if gnd_dir == "V":
|
||||
self.top_gnd_locs = self.route_side_pin("gnd", "top", top_bot_mult)
|
||||
self.bot_gnd_locs = self.route_side_pin("gnd", "bot", top_bot_mult)
|
||||
# This needs to be big enough so that they aren't in the same supply routing grid
|
||||
top_bot_mult = 4
|
||||
|
||||
if vdd_dir == "V":
|
||||
self.top_vdd_locs = self.route_side_pin("vdd", "top", top_bot_mult)
|
||||
self.bot_vdd_locs = self.route_side_pin("vdd", "bot", top_bot_mult)
|
||||
elif vdd_dir == "H":
|
||||
self.left_vdd_locs = self.route_side_pin("vdd", "left", left_right_mult)
|
||||
self.right_vdd_locs = self.route_side_pin("vdd", "right", left_right_mult)
|
||||
else:
|
||||
debug.error("Invalid vdd direction {}".format(vdd_dir), -1)
|
||||
|
||||
for inst in supply_insts:
|
||||
for pin in inst.get_pins("vdd"):
|
||||
if vdd_dir == "V":
|
||||
self.connect_side_pin(pin, "top", self.top_vdd_locs[0].y)
|
||||
self.connect_side_pin(pin, "bot", self.bot_vdd_locs[0].y)
|
||||
elif vdd_dir == "H":
|
||||
self.connect_side_pin(pin, "left", self.left_vdd_locs[0].x)
|
||||
self.connect_side_pin(pin, "right", self.right_vdd_locs[0].x)
|
||||
|
||||
for inst in supply_insts:
|
||||
for pin in inst.get_pins("gnd"):
|
||||
if gnd_dir == "V":
|
||||
self.connect_side_pin(pin, "top", self.top_gnd_locs[0].y)
|
||||
self.connect_side_pin(pin, "bot", self.bot_gnd_locs[0].y)
|
||||
elif gnd_dir == "H":
|
||||
self.connect_side_pin(pin, "left", self.left_gnd_locs[0].x)
|
||||
self.connect_side_pin(pin, "right", self.right_gnd_locs[0].x)
|
||||
array_pins = inst.get_pins("gnd")
|
||||
for array_pin in array_pins:
|
||||
supply_pin = self.left_gnd_pin
|
||||
self.add_path(array_pin.layer, [array_pin.center(), vector(supply_pin.center()[0], array_pin.center()[1])])
|
||||
self.add_via_stack_center(from_layer = array_pin.layer,
|
||||
to_layer = supply_pin.layer,
|
||||
offset = vector(supply_pin.center()[0], array_pin.center()[1]))
|
||||
if right:
|
||||
inst = self.dummy_col_insts[1]
|
||||
if "vdd" in inst.mod.pins:
|
||||
array_pins = inst.get_pins("vdd")
|
||||
for array_pin in array_pins:
|
||||
supply_pin = self.right_vdd_pin
|
||||
self.add_path(array_pin.layer, [array_pin.center(), vector(supply_pin.center()[0], array_pin.center()[1])])
|
||||
self.add_via_stack_center(from_layer = array_pin.layer,
|
||||
to_layer = supply_pin.layer,
|
||||
offset = vector(supply_pin.center()[0], array_pin.center()[1]))
|
||||
|
||||
array_pins = inst.get_pins("gnd")
|
||||
for array_pin in array_pins:
|
||||
supply_pin = self.right_gnd_pin
|
||||
self.add_path(array_pin.layer, [array_pin.center(), vector(supply_pin.center()[0], array_pin.center()[1])])
|
||||
self.add_via_stack_center(from_layer = array_pin.layer,
|
||||
to_layer = supply_pin.layer,
|
||||
offset = vector(supply_pin.center()[0], array_pin.center()[1]))
|
||||
def route_unused_wordlines(self):
|
||||
"""
|
||||
Connect the unused RBL and dummy wordlines to gnd
|
||||
|
||||
Reference in New Issue
Block a user