mirror of
https://github.com/VLSIDA/OpenRAM.git
synced 2026-09-02 02:57:53 +02:00
Add dummy bitcell module.
Modify bitcell logic to guess if bitcell is not "bitcell" No longer need to specify replica (and dummy) bitcell explicitly Add support for 1 or 2 port replica array.
This commit is contained in:
+15
-23
@@ -148,11 +148,12 @@ class bank(design.design):
|
||||
|
||||
# The center point for these cells are the upper-right corner of
|
||||
# the bitcell array.
|
||||
# The decoder/driver logic is placed on the right and mirrored on Y-axis.
|
||||
# The write/sense/precharge/mux is placed on the top and mirrored on the X-axis.
|
||||
|
||||
# The port address decoder/driver logic is placed on the right and mirrored on X- and Y-axis.
|
||||
# The port data write/sense/precharge/mux is placed on the top and mirrored on the X-axis.
|
||||
self.bitcell_array_top = self.bitcell_array.height
|
||||
self.bitcell_array_right = self.bitcell_array.width + self.m1_width + self.m2_gap
|
||||
self.bitcell_array_right = self.bitcell_array.width + self.m1_width + self.m2_gap
|
||||
# Offset past the dummy/RBL column
|
||||
self.bitcell_array_left = 2*self.bitcell.width
|
||||
|
||||
self.compute_instance_port0_offsets()
|
||||
if len(self.all_ports)==2:
|
||||
@@ -161,7 +162,7 @@ class bank(design.design):
|
||||
|
||||
def compute_instance_port0_offsets(self):
|
||||
"""
|
||||
Compute the instance offsets for port0.
|
||||
Compute the instance offsets for port0 on the left/bottom of the bank.
|
||||
"""
|
||||
|
||||
port = 0
|
||||
@@ -172,17 +173,15 @@ class bank(design.design):
|
||||
|
||||
# LOWER RIGHT QUADRANT
|
||||
# Below the bitcell array
|
||||
self.port_data_offsets[port] = vector(0,0)
|
||||
self.port_data_offsets[port] = vector(self.bitcell_array_left,0)
|
||||
|
||||
# UPPER LEFT QUADRANT
|
||||
# To the left of the bitcell array
|
||||
# The wordline driver is placed to the right of the main decoder width.
|
||||
x_offset = self.m2_gap + self.port_address.width
|
||||
self.port_address_offsets[port] = vector(-x_offset,0)
|
||||
|
||||
# LOWER LEFT QUADRANT
|
||||
# Place the col decoder left aligned with wordline driver plus halfway under row decoder
|
||||
# Place the col decoder left aligned with row decoder (x_offset doesn't change)
|
||||
# Place the col decoder left aligned with wordline driver
|
||||
# Below the bitcell array with well spacing
|
||||
x_offset = self.central_bus_width[port] + self.port_address.wordline_driver.width
|
||||
if self.col_addr_size > 0:
|
||||
@@ -204,7 +203,7 @@ class bank(design.design):
|
||||
|
||||
def compute_instance_port1_offsets(self):
|
||||
"""
|
||||
Compute the instance offsets for port1 on the top of the bank.
|
||||
Compute the instance offsets for port1 on the right/top of the bank.
|
||||
"""
|
||||
|
||||
port=1
|
||||
@@ -218,12 +217,11 @@ class bank(design.design):
|
||||
|
||||
# LOWER RIGHT QUADRANT
|
||||
# To the left of the bitcell array
|
||||
# The wordline driver is placed to the right of the main decoder width.
|
||||
x_offset = self.bitcell_array_right + self.port_address.width + self.m2_gap
|
||||
self.port_address_offsets[port] = vector(x_offset,0)
|
||||
|
||||
# UPPER RIGHT QUADRANT
|
||||
# Place the col decoder right aligned with wordline driver plus halfway under row decoder
|
||||
# Place the col decoder right aligned with wordline driver
|
||||
# Above the bitcell array with a well spacing
|
||||
x_offset = self.bitcell_array_right + self.central_bus_width[port] + self.port_address.wordline_driver.width
|
||||
if self.col_addr_size > 0:
|
||||
@@ -247,16 +245,12 @@ class bank(design.design):
|
||||
|
||||
self.compute_instance_offsets()
|
||||
|
||||
# UPPER RIGHT QUADRANT
|
||||
self.place_bitcell_array(self.bitcell_array_offset)
|
||||
|
||||
# LOWER RIGHT QUADRANT
|
||||
self.place_port_data(self.port_data_offsets)
|
||||
|
||||
# UPPER LEFT QUADRANT
|
||||
self.place_port_address(self.port_address_offsets)
|
||||
|
||||
# LOWER LEFT QUADRANT
|
||||
self.place_column_decoder(self.column_decoder_offsets)
|
||||
self.place_bank_select(self.bank_select_offsets)
|
||||
|
||||
@@ -274,11 +268,6 @@ class bank(design.design):
|
||||
debug.check(self.num_rows*self.num_cols==self.word_size*self.num_words,"Invalid bank sizes.")
|
||||
debug.check(self.addr_size==self.col_addr_size + self.row_addr_size,"Invalid address break down.")
|
||||
|
||||
# Width for the vdd/gnd rails
|
||||
self.supply_rail_width = 4*self.m2_width
|
||||
# FIXME: This spacing should be width dependent...
|
||||
self.supply_rail_pitch = self.supply_rail_width + 4*self.m2_space
|
||||
|
||||
# The order of the control signals on the control bus:
|
||||
self.input_control_signals = []
|
||||
port_num = 0
|
||||
@@ -328,7 +317,7 @@ class bank(design.design):
|
||||
self.wl_names = self.bitcell.list_all_wl_names()
|
||||
self.bitline_names = self.bitcell.list_all_bitline_names()
|
||||
|
||||
self.bitcell_array = factory.create(module_type="bitcell_array",
|
||||
self.bitcell_array = factory.create(module_type="replica_bitcell_array",
|
||||
cols=self.num_cols,
|
||||
rows=self.num_rows)
|
||||
self.add_mod(self.bitcell_array)
|
||||
@@ -358,11 +347,14 @@ class bank(design.design):
|
||||
self.bitcell_array_inst=self.add_inst(name="bitcell_array",
|
||||
mod=self.bitcell_array)
|
||||
|
||||
|
||||
print(self.bitcell_array.pins)
|
||||
temp = []
|
||||
for col in range(self.num_cols):
|
||||
for bitline in self.bitline_names:
|
||||
temp.append(bitline+"_{0}".format(col))
|
||||
for col in range(2):
|
||||
for bitline in self.bitline_names:
|
||||
temp.append("replica_"+bitline+"_{0}".format(col))
|
||||
for row in range(self.num_rows):
|
||||
for wordline in self.wl_names:
|
||||
temp.append(wordline+"_{0}".format(row))
|
||||
|
||||
@@ -22,13 +22,18 @@ class replica_bitcell_array(design.design):
|
||||
Dummy are the outside columns/rows with WL and BL tied to gnd.
|
||||
Requires a regular bitcell array, replica bitcell, and dummy bitcell (Bl/BR disconnected).
|
||||
"""
|
||||
def __init__(self, cols, rows, name):
|
||||
def __init__(self, cols, rows, num_ports, name):
|
||||
design.design.__init__(self, name)
|
||||
debug.info(1, "Creating {0} {1} x {2}".format(self.name, rows, cols))
|
||||
self.add_comment("rows: {0} cols: {1}".format(rows, cols))
|
||||
|
||||
self.column_size = cols
|
||||
self.row_size = rows
|
||||
self.num_ports = num_ports
|
||||
|
||||
# Two dummy rows/cols plus replica for each port
|
||||
self.extra_rows = 2 + self.num_ports
|
||||
self.extra_cols = 2 + self.num_ports
|
||||
|
||||
self.create_netlist()
|
||||
if not OPTS.netlist_only:
|
||||
@@ -80,19 +85,20 @@ class replica_bitcell_array(design.design):
|
||||
|
||||
# Replica bitline
|
||||
self.replica_column = factory.create(module_type="replica_column",
|
||||
rows=self.row_size + 4)
|
||||
rows=self.row_size + self.extra_rows,
|
||||
num_ports = self.num_ports)
|
||||
self.add_mod(self.replica_column)
|
||||
|
||||
# Dummy row
|
||||
self.dummy_row = factory.create(module_type="dummy_array",
|
||||
rows=1,
|
||||
cols=self.column_size)
|
||||
cols=self.column_size,
|
||||
rows=1)
|
||||
self.add_mod(self.dummy_row)
|
||||
|
||||
# Dummy col
|
||||
self.dummy_col = factory.create(module_type="dummy_array",
|
||||
cols=1,
|
||||
rows=self.row_size + 4)
|
||||
rows=self.row_size + self.extra_rows)
|
||||
self.add_mod(self.dummy_col)
|
||||
|
||||
|
||||
@@ -103,27 +109,33 @@ class replica_bitcell_array(design.design):
|
||||
self.bl_names = [x for x in self.bitcell_array.pins if x.startswith("b")]
|
||||
|
||||
# top/bottom rows (in the middle)
|
||||
self.replica_wl_names = ["replica_"+x for x in self.cell.pins if x.startswith("w")]
|
||||
self.dummy_wl_names = ["dummy_"+x for x in self.cell.pins if x.startswith("w")]
|
||||
self.dummy_bl_names = ["dummy_"+x for x in self.cell.pins if x.startswith("b")]
|
||||
self.replica_wl_names = ["replica_"+x for x in self.cell.list_all_wl_names()]
|
||||
self.dummy_wl_names = ["dummy_"+x for x in self.cell.list_all_wl_names()]
|
||||
self.dummy_bl_names = ["dummy_"+x for x in self.cell.list_all_bitline_names()]
|
||||
self.dummy_row_bl_names = self.bl_names
|
||||
|
||||
# dummy row and replica on each side of the bitcell rows
|
||||
self.replica_col_wl_names = [x+"_0" for x in self.dummy_wl_names] \
|
||||
+ ["replica_"+x+"_0" for x in self.cell.list_all_wl_names()] \
|
||||
+ self.wl_names \
|
||||
+ ["replica_"+x+"_1" for x in self.cell.list_all_wl_names()] \
|
||||
+ [x+"_1" for x in self.dummy_wl_names]
|
||||
self.replica_bl_names = ["replica_"+x for x in self.cell.pins if x.startswith("b")]
|
||||
+ self.wl_names
|
||||
if self.num_ports==2:
|
||||
self.replica_col_wl_names.extend(["replica_"+x+"_1" for x in self.cell.list_all_wl_names()])
|
||||
self.replica_col_wl_names.extend([x+"_1" for x in self.dummy_wl_names])
|
||||
self.replica_bl_names = ["replica_"+x for x in self.cell.list_all_bitline_names()]
|
||||
self.replica_bl0_names = [x+"_0" for x in self.replica_bl_names]
|
||||
self.replica_bl1_names = [x+"_1" for x in self.replica_bl_names]
|
||||
|
||||
# left/right rows
|
||||
self.dummy_col_wl_names = self.replica_col_wl_names
|
||||
|
||||
|
||||
self.add_pin_list(self.bl_names)
|
||||
self.add_pin_list([x+"_0" for x in self.replica_bl_names])
|
||||
self.add_pin_list([x+"_1" for x in self.replica_bl_names])
|
||||
self.add_pin_list([x for x in self.replica_col_wl_names if not x.startswith("dummy")])
|
||||
self.add_pin_list(self.replica_bl0_names)
|
||||
if self.num_ports==2:
|
||||
self.add_pin_list(self.replica_bl1_names)
|
||||
self.add_pin_list(self.wl_names)
|
||||
self.add_pin_list(self.replica_wl_names)
|
||||
#self.add_pin_list([x for x in self.replica_col_wl_names if not x.startswith("dummy")])
|
||||
|
||||
self.add_pin("vdd")
|
||||
self.add_pin("gnd")
|
||||
@@ -142,10 +154,11 @@ class replica_bitcell_array(design.design):
|
||||
self.replica_col_left_inst=self.add_inst(name="replica_col_left",
|
||||
mod=self.replica_column)
|
||||
self.connect_inst([x+"_0" for x in self.replica_bl_names] + self.replica_col_wl_names + supplies)
|
||||
|
||||
self.replica_col_right_inst=self.add_inst(name="replica_col_right",
|
||||
mod=self.replica_column)
|
||||
self.connect_inst([x+"_1" for x in self.replica_bl_names] + self.replica_col_wl_names[::-1] + supplies)
|
||||
|
||||
if self.num_ports==2:
|
||||
self.replica_col_right_inst=self.add_inst(name="replica_col_right",
|
||||
mod=self.replica_column)
|
||||
self.connect_inst([x+"_1" for x in self.replica_bl_names] + self.replica_col_wl_names[::-1] + supplies)
|
||||
|
||||
# Replica rows with replica bitcell
|
||||
self.dummy_row_bottop_inst=self.add_inst(name="dummy_row_bottop",
|
||||
@@ -177,16 +190,17 @@ class replica_bitcell_array(design.design):
|
||||
|
||||
def create_layout(self):
|
||||
|
||||
self.height = (self.row_size+4)*self.dummy_row.height
|
||||
self.width = (self.column_size+4)*self.replica_column.width
|
||||
self.height = (self.row_size+self.extra_rows)*self.dummy_row.height
|
||||
self.width = (self.column_size+self.extra_cols)*self.replica_column.width
|
||||
|
||||
# This is a bitcell x bitcell offset to scale
|
||||
offset = vector(self.replica_column.width, self.dummy_row.height)
|
||||
|
||||
self.bitcell_array_inst.place(offset=[0,0])
|
||||
self.replica_col_left_inst.place(offset=offset.scale(-1,-2))
|
||||
self.replica_col_right_inst.place(offset=offset.scale(0,2)+self.bitcell_array_inst.ur(),
|
||||
mirror="MX")
|
||||
if self.num_ports==2:
|
||||
self.replica_col_right_inst.place(offset=offset.scale(0,2)+self.bitcell_array_inst.ur(),
|
||||
mirror="MX")
|
||||
|
||||
self.dummy_row_toptop_inst.place(offset=offset.scale(0,2)+self.bitcell_array_inst.ul(),
|
||||
mirror="MX")
|
||||
@@ -196,7 +210,11 @@ class replica_bitcell_array(design.design):
|
||||
self.dummy_row_botbot_inst.place(offset=offset.scale(0,-2))
|
||||
|
||||
self.dummy_col_left_inst.place(offset=offset.scale(-2,-2))
|
||||
self.dummy_col_right_inst.place(offset=offset.scale(1,-2)+self.bitcell_array_inst.lr())
|
||||
if self.num_ports==2:
|
||||
self.dummy_col_right_inst.place(offset=offset.scale(1,-2)+self.bitcell_array_inst.lr())
|
||||
else:
|
||||
self.dummy_col_right_inst.place(offset=offset.scale(0,-2)+self.bitcell_array_inst.lr())
|
||||
|
||||
|
||||
self.translate_all(offset.scale(-2,-2))
|
||||
|
||||
@@ -246,7 +264,10 @@ class replica_bitcell_array(design.design):
|
||||
height=pin.height())
|
||||
|
||||
# Replica columns
|
||||
for index,side in enumerate(["left","right"]):
|
||||
replica_sides = ["left"]
|
||||
if self.num_ports==2:
|
||||
replica_sides.append("right")
|
||||
for index,side in enumerate(replica_sides):
|
||||
inst = getattr(self, "replica_col_{}_inst".format(side))
|
||||
pin_names = inst.mod.get_pin_names()
|
||||
for pin_name in pin_names:
|
||||
@@ -262,11 +283,7 @@ class replica_bitcell_array(design.design):
|
||||
|
||||
|
||||
for pin_name in ["vdd","gnd"]:
|
||||
for inst in [self.bitcell_array_inst,
|
||||
self.replica_col_left_inst, self.replica_col_right_inst,
|
||||
self.dummy_col_left_inst, self.dummy_col_right_inst,
|
||||
self.dummy_row_toptop_inst, self.dummy_row_topbot_inst,
|
||||
self.dummy_row_bottop_inst, self.dummy_row_botbot_inst]:
|
||||
for inst in self.insts:
|
||||
pin_list = inst.get_pins(pin_name)
|
||||
for pin in pin_list:
|
||||
self.add_power_pin(name=pin_name, loc=pin.center(), vertical=True, start_layer=pin.layer)
|
||||
|
||||
@@ -16,10 +16,11 @@ class replica_column(design.design):
|
||||
Generate a replica bitline column for the replica array.
|
||||
"""
|
||||
|
||||
def __init__(self, name, rows):
|
||||
def __init__(self, name, rows, num_ports):
|
||||
design.design.__init__(self, name)
|
||||
|
||||
self.row_size = rows
|
||||
self.num_ports = num_ports
|
||||
|
||||
self.create_netlist()
|
||||
if not OPTS.netlist_only:
|
||||
@@ -64,7 +65,7 @@ class replica_column(design.design):
|
||||
self.cell_inst = {}
|
||||
for row in range(self.row_size):
|
||||
name="rbc_{0}".format(row)
|
||||
if row>0 and row<self.row_size-2:
|
||||
if row>0 and row<self.row_size - self.num_ports:
|
||||
self.cell_inst[row]=self.add_inst(name=name,
|
||||
mod=self.replica_cell)
|
||||
else:
|
||||
|
||||
Reference in New Issue
Block a user