mirror of https://github.com/VLSIDA/OpenRAM.git
Replica bitcell array bbox to include unused WL gnd pins.
This commit is contained in:
parent
9c6d8d7aed
commit
70c90ca7fb
|
|
@ -845,11 +845,11 @@ class bank(design.design):
|
|||
self.route_port_address_in(port)
|
||||
|
||||
if port % 2:
|
||||
self.route_port_address_right(port)
|
||||
self.route_port_address_out(port, "right")
|
||||
else:
|
||||
self.route_port_address_left(port)
|
||||
self.route_port_address_out(port, "left")
|
||||
|
||||
def route_port_address_left(self, port):
|
||||
def route_port_address_out(self, port, side="left"):
|
||||
""" Connecting Wordline driver output to Bitcell WL connection """
|
||||
|
||||
driver_names = ["wl_{}".format(x) for x in range(self.num_rows)] + ["rbl_wl"]
|
||||
|
|
@ -857,18 +857,32 @@ class bank(design.design):
|
|||
for (driver_name, array_name) in zip(driver_names, self.bitcell_array.get_wordline_names(port) + [rbl_wl_name]):
|
||||
# The mid guarantees we exit the input cell to the right.
|
||||
driver_wl_pin = self.port_address_inst[port].get_pin(driver_name)
|
||||
driver_wl_pos = driver_wl_pin.rc()
|
||||
if side == "left":
|
||||
driver_wl_pos = driver_wl_pin.rc()
|
||||
else:
|
||||
driver_wl_pos = driver_wl_pin.lc()
|
||||
bitcell_wl_pin = self.bitcell_array_inst.get_pin(array_name)
|
||||
bitcell_wl_pos = bitcell_wl_pin.lc()
|
||||
mid1 = driver_wl_pos.scale(0, 1) + vector(0.5 * self.port_address_inst[port].rx() + 0.5 * self.bitcell_array_inst.lx(), 0)
|
||||
mid2 = mid1.scale(1, 0) + bitcell_wl_pos.scale(0.5, 1)
|
||||
self.add_path(driver_wl_pin.layer, [driver_wl_pos, mid1, mid2])
|
||||
# Via is non-preferred direction because mid1->mid2 is non-preferred direction
|
||||
self.add_via_stack_center(from_layer=driver_wl_pin.layer,
|
||||
to_layer=bitcell_wl_pin.layer,
|
||||
offset=mid2,
|
||||
directions="nonpref")
|
||||
self.add_path(bitcell_wl_pin.layer, [mid2, bitcell_wl_pos])
|
||||
|
||||
if side == "left":
|
||||
bitcell_wl_pos = bitcell_wl_pin.lc()
|
||||
port_address_pos = self.port_address_inst[port].rx()
|
||||
bitcell_array_pos = self.bitcell_array_inst.lx()
|
||||
else:
|
||||
bitcell_wl_pos = bitcell_wl_pin.rc()
|
||||
port_address_pos = self.port_address_inst[port].lx()
|
||||
bitcell_array_pos = self.bitcell_array_inst.rx()
|
||||
|
||||
mid1 = driver_wl_pos.scale(0, 1) + vector(0.5 * port_address_pos + 0.5 * bitcell_array_pos, 0)
|
||||
mid2 = mid1.scale(1, 0) + bitcell_wl_pos.scale(0, 1)
|
||||
if driver_wl_pin.layer != bitcell_wl_pin.layer:
|
||||
self.add_path(driver_wl_pin.layer, [driver_wl_pos, mid1, mid2])
|
||||
self.add_via_stack_center(from_layer=driver_wl_pin.layer,
|
||||
to_layer=bitcell_wl_pin.layer,
|
||||
offset=mid2)
|
||||
self.add_path(bitcell_wl_pin.layer, [mid2, bitcell_wl_pos])
|
||||
else:
|
||||
self.add_path(bitcell_wl_pin.layer, [driver_wl_pos, mid1, mid2, bitcell_wl_pos])
|
||||
|
||||
|
||||
def route_port_address_right(self, port):
|
||||
""" Connecting Wordline driver output to Bitcell WL connection """
|
||||
|
|
@ -888,6 +902,7 @@ class bank(design.design):
|
|||
to_layer=bitcell_wl_pin.layer,
|
||||
offset=mid2)
|
||||
self.add_path(bitcell_wl_pin.layer, [mid2, bitcell_wl_pos])
|
||||
|
||||
|
||||
def route_column_address_lines(self, port):
|
||||
""" Connecting the select lines of column mux to the address bus """
|
||||
|
|
|
|||
|
|
@ -305,14 +305,21 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array):
|
|||
|
||||
def create_layout(self):
|
||||
|
||||
# We will need unused wordlines grounded, so we need to know their layer
|
||||
pin = self.cell.get_pin(self.cell.get_all_wl_names()[0])
|
||||
pin_layer = pin.layer
|
||||
self.unused_pitch = 1.5 * getattr(self, "{}_pitch".format(pin_layer))
|
||||
self.unused_offset = vector(self.unused_pitch, 0)
|
||||
|
||||
# Add extra width on the left and right for the unused WLs
|
||||
self.height = (self.row_size + self.extra_rows) * self.dummy_row.height
|
||||
self.width = (self.column_size + self.extra_cols) * self.cell.width
|
||||
self.width = (self.column_size + self.extra_cols) * self.cell.width + 2 * self.unused_pitch
|
||||
|
||||
# This is a bitcell x bitcell offset to scale
|
||||
self.bitcell_offset = vector(self.cell.width, self.cell.height)
|
||||
|
||||
# Everything is computed with the main array at (0, 0) to start
|
||||
self.bitcell_array_inst.place(offset=[0, 0])
|
||||
# Everything is computed with the main array at (self.unused_pitch, 0) to start
|
||||
self.bitcell_array_inst.place(offset=self.unused_offset)
|
||||
|
||||
self.add_replica_columns()
|
||||
|
||||
|
|
@ -356,7 +363,7 @@ class replica_bitcell_array(bitcell_base_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] - 1)
|
||||
offset = self.bitcell_offset.scale(-len(self.left_rbl) + bit, -self.rbl[0] - 1) + self.unused_offset
|
||||
self.replica_col_insts[port].place(offset)
|
||||
# Grow to the right of the bitcell array, array outward
|
||||
for bit, port in enumerate(self.right_rbl):
|
||||
|
|
@ -367,11 +374,13 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array):
|
|||
# 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]):
|
||||
self.dummy_row_replica_insts[bit].place(offset=self.bitcell_offset.scale(0, -self.rbl[0] + bit + (-self.rbl[0] + bit) % 2),
|
||||
dummy_offset = self.bitcell_offset.scale(0, -self.rbl[0] + bit + (-self.rbl[0] + bit) % 2) + self.unused_offset
|
||||
self.dummy_row_replica_insts[bit].place(offset=dummy_offset,
|
||||
mirror="MX" if (-self.rbl[0] + bit) % 2 else "R0")
|
||||
# These grow up, away from the array
|
||||
for bit in range(self.rbl[1]):
|
||||
self.dummy_row_replica_insts[self.rbl[0] + bit].place(offset=self.bitcell_offset.scale(0, bit + bit % 2) + self.bitcell_array_inst.ul(),
|
||||
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 bit % 2 else "R0")
|
||||
|
||||
def add_end_caps(self):
|
||||
|
|
@ -386,12 +395,12 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array):
|
|||
# FIXME: These depend on the array size itself
|
||||
# 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, -self.rbl[0] - 1 + flip_dummy)
|
||||
dummy_row_offset = self.bitcell_offset.scale(0, -self.rbl[0] - 1 + flip_dummy) + self.unused_offset
|
||||
self.dummy_row_insts[0].place(offset=dummy_row_offset,
|
||||
mirror="MX" if flip_dummy else "R0")
|
||||
# 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(-len(self.left_rbl) - 1, -self.rbl[0] - 1)
|
||||
dummy_col_offset = self.bitcell_offset.scale(-len(self.left_rbl) - 1, -self.rbl[0] - 1) + self.unused_offset
|
||||
self.dummy_col_insts[0].place(offset=dummy_col_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
|
||||
|
|
@ -495,13 +504,13 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array):
|
|||
def ground_pin(self, inst, name):
|
||||
pin = inst.get_pin(name)
|
||||
pin_layer = pin.layer
|
||||
layer_pitch = 1.5 * getattr(self, "{}_pitch".format(pin_layer))
|
||||
|
||||
left_pin_loc = vector(self.dummy_col_insts[0].lx(), pin.cy())
|
||||
right_pin_loc = vector(self.dummy_col_insts[1].rx(), pin.cy())
|
||||
|
||||
# Place the pins a track outside of the array
|
||||
left_loc = left_pin_loc - vector(layer_pitch, 0)
|
||||
right_loc = right_pin_loc + vector(layer_pitch, 0)
|
||||
left_loc = left_pin_loc - vector(self.unused_pitch, 0)
|
||||
right_loc = right_pin_loc + vector(self.unused_pitch, 0)
|
||||
self.add_power_pin("gnd", left_loc, directions=("H", "H"))
|
||||
self.add_power_pin("gnd", right_loc, directions=("H", "H"))
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue