mirror of https://github.com/VLSIDA/OpenRAM.git
Fix up to SRAM level with new replica bitcell array ports.
This commit is contained in:
parent
a55909930f
commit
50525e70f4
|
|
@ -83,7 +83,7 @@ class bank(design.design):
|
||||||
for bit in range(self.word_size + self.num_spare_cols):
|
for bit in range(self.word_size + self.num_spare_cols):
|
||||||
self.add_pin("dout{0}_{1}".format(port, bit), "OUTPUT")
|
self.add_pin("dout{0}_{1}".format(port, bit), "OUTPUT")
|
||||||
for port in self.all_ports:
|
for port in self.all_ports:
|
||||||
self.add_pin_list(self.bitcell_array.get_rbl_bitline_names(self.port_rbl_map[port]), "OUTPUT")
|
self.add_pin_list(self.bitcell_array.get_rbl_bitline_names(port), "OUTPUT")
|
||||||
for port in self.write_ports:
|
for port in self.write_ports:
|
||||||
for bit in range(self.word_size + self.num_spare_cols):
|
for bit in range(self.word_size + self.num_spare_cols):
|
||||||
self.add_pin("din{0}_{1}".format(port, bit), "INPUT")
|
self.add_pin("din{0}_{1}".format(port, bit), "INPUT")
|
||||||
|
|
@ -114,6 +114,8 @@ class bank(design.design):
|
||||||
def route_layout(self):
|
def route_layout(self):
|
||||||
""" Create routing amoung the modules """
|
""" Create routing amoung the modules """
|
||||||
self.route_central_bus()
|
self.route_central_bus()
|
||||||
|
|
||||||
|
self.route_unused_wordlines()
|
||||||
|
|
||||||
for port in self.all_ports:
|
for port in self.all_ports:
|
||||||
self.route_bitlines(port)
|
self.route_bitlines(port)
|
||||||
|
|
@ -375,7 +377,6 @@ class bank(design.design):
|
||||||
rows=self.num_rows)
|
rows=self.num_rows)
|
||||||
self.add_mod(self.port_address)
|
self.add_mod(self.port_address)
|
||||||
|
|
||||||
self.port_rbl_map = self.all_ports
|
|
||||||
self.num_rbl = len(self.all_ports)
|
self.num_rbl = len(self.all_ports)
|
||||||
|
|
||||||
self.bitcell_array = factory.create(module_type="replica_bitcell_array",
|
self.bitcell_array = factory.create(module_type="replica_bitcell_array",
|
||||||
|
|
@ -395,10 +396,24 @@ class bank(design.design):
|
||||||
self.bitcell_array_inst=self.add_inst(name="replica_bitcell_array",
|
self.bitcell_array_inst=self.add_inst(name="replica_bitcell_array",
|
||||||
mod=self.bitcell_array)
|
mod=self.bitcell_array)
|
||||||
temp = []
|
temp = []
|
||||||
|
rbl_names = self.bitcell_array.get_rbl_bitline_names()
|
||||||
|
temp.extend(rbl_names)
|
||||||
bitline_names = self.bitcell_array.get_bitline_names()
|
bitline_names = self.bitcell_array.get_bitline_names()
|
||||||
temp.extend(bitline_names)
|
temp.extend(bitline_names)
|
||||||
# Replace RBL wordline with wl_en#
|
# Replace RBL wordline with wl_en#
|
||||||
wordline_names = [x.replace("rbl_wl_", "wl_en") for x in self.bitcell_array.get_wordline_names()]
|
wordline_names = self.bitcell_array.get_wordline_names()
|
||||||
|
|
||||||
|
rbl_wl_names = []
|
||||||
|
for port in self.all_ports:
|
||||||
|
rbl_wl_names.append(self.bitcell_array.get_rbl_wordline_names(port))
|
||||||
|
|
||||||
|
# Rename the RBL WL to the enable name
|
||||||
|
for port in self.all_ports:
|
||||||
|
wordline_names = [x.replace(rbl_wl_names[port], "wl_en{0}".format(port)) for x in wordline_names]
|
||||||
|
# Connect the other RBL WL to gnd
|
||||||
|
wordline_names = ["gnd" if x.startswith("rbl_wl") else x for x in wordline_names]
|
||||||
|
# Connect the dummy WL to gnd
|
||||||
|
wordline_names = ["gnd" if x.startswith("dummy") else x for x in wordline_names]
|
||||||
temp.extend(wordline_names)
|
temp.extend(wordline_names)
|
||||||
temp.append("vdd")
|
temp.append("vdd")
|
||||||
temp.append("gnd")
|
temp.append("gnd")
|
||||||
|
|
@ -410,14 +425,13 @@ class bank(design.design):
|
||||||
|
|
||||||
def create_port_data(self):
|
def create_port_data(self):
|
||||||
""" Creating Port Data """
|
""" Creating Port Data """
|
||||||
|
|
||||||
self.port_data_inst = [None] * len(self.all_ports)
|
self.port_data_inst = [None] * len(self.all_ports)
|
||||||
for port in self.all_ports:
|
for port in self.all_ports:
|
||||||
self.port_data_inst[port]=self.add_inst(name="port_data{}".format(port),
|
self.port_data_inst[port]=self.add_inst(name="port_data{}".format(port),
|
||||||
mod=self.port_data[port])
|
mod=self.port_data[port])
|
||||||
|
|
||||||
temp = []
|
temp = []
|
||||||
rbl_bl_names=self.bitcell_array.get_rbl_bitline_names(self.port_rbl_map[port])
|
rbl_bl_names = self.bitcell_array.get_rbl_bitline_names(port)
|
||||||
temp.extend(rbl_bl_names)
|
temp.extend(rbl_bl_names)
|
||||||
for col in range(self.num_cols + self.num_spare_cols):
|
for col in range(self.num_cols + self.num_spare_cols):
|
||||||
temp.append("{0}_{1}".format(self.bl_names[port], col))
|
temp.append("{0}_{1}".format(self.bl_names[port], col))
|
||||||
|
|
@ -441,7 +455,6 @@ class bank(design.design):
|
||||||
for bit in range(self.num_spare_cols):
|
for bit in range(self.num_spare_cols):
|
||||||
temp.append("bank_spare_wen{0}_{1}".format(port, bit))
|
temp.append("bank_spare_wen{0}_{1}".format(port, bit))
|
||||||
temp.extend(["vdd", "gnd"])
|
temp.extend(["vdd", "gnd"])
|
||||||
|
|
||||||
self.connect_inst(temp)
|
self.connect_inst(temp)
|
||||||
|
|
||||||
def place_port_data(self, offsets):
|
def place_port_data(self, offsets):
|
||||||
|
|
@ -466,7 +479,7 @@ class bank(design.design):
|
||||||
temp = []
|
temp = []
|
||||||
for bit in range(self.row_addr_size):
|
for bit in range(self.row_addr_size):
|
||||||
temp.append("addr{0}_{1}".format(port, bit + self.col_addr_size))
|
temp.append("addr{0}_{1}".format(port, bit + self.col_addr_size))
|
||||||
temp.append("wl_en{0}".format(port))
|
temp.append("wl_en{}".format(port))
|
||||||
for row in range(self.num_rows):
|
for row in range(self.num_rows):
|
||||||
temp.append("{0}_{1}".format(self.wl_names[port], row))
|
temp.append("{0}_{1}".format(self.wl_names[port], row))
|
||||||
temp.extend(["vdd", "gnd"])
|
temp.extend(["vdd", "gnd"])
|
||||||
|
|
@ -654,7 +667,7 @@ class bank(design.design):
|
||||||
# Port 0
|
# Port 0
|
||||||
# The bank is at (0,0), so this is to the left of the y-axis.
|
# The bank is at (0,0), so this is to the left of the y-axis.
|
||||||
# 2 pitches on the right for vias/jogs to access the inputs
|
# 2 pitches on the right for vias/jogs to access the inputs
|
||||||
control_bus_offset = vector(-self.m3_pitch * self.num_control_lines[0] - self.m3_pitch, self.min_y_offset)
|
control_bus_offset = vector(-self.m3_pitch * self.num_control_lines[0] - 2 * self.m3_pitch, self.min_y_offset)
|
||||||
# The control bus is routed up to two pitches below the bitcell array
|
# The control bus is routed up to two pitches below the bitcell array
|
||||||
control_bus_length = self.main_bitcell_array_bottom - self.min_y_offset - 2 * self.m1_pitch
|
control_bus_length = self.main_bitcell_array_bottom - self.min_y_offset - 2 * self.m1_pitch
|
||||||
self.bus_pins[0] = self.create_bus(layer="m2",
|
self.bus_pins[0] = self.create_bus(layer="m2",
|
||||||
|
|
@ -669,7 +682,7 @@ class bank(design.design):
|
||||||
if len(self.all_ports)==2:
|
if len(self.all_ports)==2:
|
||||||
# The other control bus is routed up to two pitches above the bitcell array
|
# The other control bus is routed up to two pitches above the bitcell array
|
||||||
control_bus_length = self.max_y_offset - self.main_bitcell_array_top - 2 * self.m1_pitch
|
control_bus_length = self.max_y_offset - self.main_bitcell_array_top - 2 * self.m1_pitch
|
||||||
control_bus_offset = vector(self.bitcell_array_right + self.m3_pitch,
|
control_bus_offset = vector(self.bitcell_array_right + 2 * self.m3_pitch,
|
||||||
self.max_y_offset - control_bus_length)
|
self.max_y_offset - control_bus_length)
|
||||||
# The bus for the right port is reversed so that the rbl_wl is closest to the array
|
# The bus for the right port is reversed so that the rbl_wl is closest to the array
|
||||||
self.bus_pins[1] = self.create_bus(layer="m2",
|
self.bus_pins[1] = self.create_bus(layer="m2",
|
||||||
|
|
@ -702,11 +715,11 @@ class bank(design.design):
|
||||||
|
|
||||||
# connect spare bitlines
|
# connect spare bitlines
|
||||||
for i in range(self.num_spare_cols):
|
for i in range(self.num_spare_cols):
|
||||||
self.connect_bitline(inst1, inst2, inst1_bl_name.format(self.num_cols+i), "spare" + inst2_bl_name.format(i))
|
self.connect_bitline(inst1, inst2, inst1_bl_name.format(self.num_cols + i), "spare" + inst2_bl_name.format(i))
|
||||||
self.connect_bitline(inst1, inst2, inst1_br_name.format(self.num_cols+i), "spare" + inst2_br_name.format(i))
|
self.connect_bitline(inst1, inst2, inst1_br_name.format(self.num_cols + i), "spare" + inst2_br_name.format(i))
|
||||||
|
|
||||||
# Connect the replica bitlines
|
# Connect the replica bitlines
|
||||||
rbl_bl_names=self.bitcell_array.get_rbl_bitline_names(self.port_rbl_map[port])
|
rbl_bl_names = self.bitcell_array.get_rbl_bitline_names(port)
|
||||||
for (array_name, data_name) in zip(rbl_bl_names, ["rbl_bl", "rbl_br"]):
|
for (array_name, data_name) in zip(rbl_bl_names, ["rbl_bl", "rbl_br"]):
|
||||||
self.connect_bitline(inst1, inst2, array_name, data_name)
|
self.connect_bitline(inst1, inst2, array_name, data_name)
|
||||||
|
|
||||||
|
|
@ -949,7 +962,35 @@ class bank(design.design):
|
||||||
self.add_label(text=data_name,
|
self.add_label(text=data_name,
|
||||||
layer="m1",
|
layer="m1",
|
||||||
offset=data_pin.center())
|
offset=data_pin.center())
|
||||||
|
|
||||||
|
def route_unused_wordlines(self):
|
||||||
|
""" Connect the unused RBL and dummy wordlines to gnd """
|
||||||
|
gnd_wl_names = []
|
||||||
|
|
||||||
|
# Connect unused RBL WL to gnd
|
||||||
|
array_rbl_names = set([x for x in self.bitcell_array.get_all_wordline_names() if x.startswith("rbl")])
|
||||||
|
dummy_rbl_names = set([x for x in self.bitcell_array.get_all_wordline_names() if x.startswith("dummy")])
|
||||||
|
rbl_wl_names = set([self.bitcell_array.get_rbl_wordline_names(x) for x in self.all_ports])
|
||||||
|
|
||||||
|
gnd_wl_names = list((array_rbl_names - rbl_wl_names) | dummy_rbl_names)
|
||||||
|
|
||||||
|
for wl_name in gnd_wl_names:
|
||||||
|
pin = self.bitcell_array_inst.get_pin(wl_name)
|
||||||
|
pin_layer = pin.layer
|
||||||
|
layer_pitch = getattr(self, "{}_pitch".format(pin_layer))
|
||||||
|
left_pin_loc = pin.lc()
|
||||||
|
right_pin_loc = pin.rc()
|
||||||
|
|
||||||
|
# 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)
|
||||||
|
self.add_power_pin("gnd", left_loc)
|
||||||
|
self.add_power_pin("gnd", right_loc)
|
||||||
|
|
||||||
|
# Add a path to connect to the array
|
||||||
|
self.add_path(pin_layer, [left_loc, left_pin_loc])
|
||||||
|
self.add_path(pin_layer, [right_loc, right_pin_loc])
|
||||||
|
|
||||||
def route_control_lines(self, port):
|
def route_control_lines(self, port):
|
||||||
""" Route the control lines of the entire bank """
|
""" Route the control lines of the entire bank """
|
||||||
|
|
||||||
|
|
@ -961,11 +1002,10 @@ class bank(design.design):
|
||||||
connection.append((self.prefix + "p_en_bar{}".format(port),
|
connection.append((self.prefix + "p_en_bar{}".format(port),
|
||||||
self.port_data_inst[port].get_pin("p_en_bar")))
|
self.port_data_inst[port].get_pin("p_en_bar")))
|
||||||
|
|
||||||
rbl_wl_names = self.bitcell_array.get_rbl_wordline_names(self.port_rbl_map[port])
|
rbl_wl_name = self.bitcell_array.get_rbl_wordline_names(port)
|
||||||
for rbl_wl_name in rbl_wl_names:
|
connection.append((self.prefix + "wl_en{}".format(port),
|
||||||
connection.append((self.prefix + "wl_en{}".format(port),
|
self.bitcell_array_inst.get_pin(rbl_wl_name)))
|
||||||
self.bitcell_array_inst.get_pin(rbl_wl_name)))
|
|
||||||
|
|
||||||
if port in self.write_ports:
|
if port in self.write_ports:
|
||||||
connection.append((self.prefix + "w_en{}".format(port),
|
connection.append((self.prefix + "w_en{}".format(port),
|
||||||
self.port_data_inst[port].get_pin("w_en")))
|
self.port_data_inst[port].get_pin("w_en")))
|
||||||
|
|
@ -1000,7 +1040,7 @@ class bank(design.design):
|
||||||
self.add_wire(self.m1_stack, [pin_pos, mid_pos, control_pos])
|
self.add_wire(self.m1_stack, [pin_pos, mid_pos, control_pos])
|
||||||
self.add_via_center(layers=self.m1_stack,
|
self.add_via_center(layers=self.m1_stack,
|
||||||
offset=control_pos)
|
offset=control_pos)
|
||||||
|
|
||||||
def determine_wordline_stage_efforts(self, external_cout, inp_is_rise=True):
|
def determine_wordline_stage_efforts(self, external_cout, inp_is_rise=True):
|
||||||
"""Get the all the stage efforts for each stage in the path within the bank clk_buf to a wordline"""
|
"""Get the all the stage efforts for each stage in the path within the bank clk_buf to a wordline"""
|
||||||
# Decoder is assumed to have settled before the negative edge of the clock.
|
# Decoder is assumed to have settled before the negative edge of the clock.
|
||||||
|
|
|
||||||
|
|
@ -174,7 +174,7 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array):
|
||||||
|
|
||||||
def add_bitline_pins(self):
|
def add_bitline_pins(self):
|
||||||
|
|
||||||
# All bitline names for all ports
|
# Regular bitline names for all ports
|
||||||
self.bitline_names = []
|
self.bitline_names = []
|
||||||
# Bitline names for each port
|
# Bitline names for each port
|
||||||
self.bitline_names_by_port = [[] for x in self.all_ports]
|
self.bitline_names_by_port = [[] for x in self.all_ports]
|
||||||
|
|
@ -183,15 +183,15 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array):
|
||||||
# Replica wordlines by port (bl only)
|
# Replica wordlines by port (bl only)
|
||||||
self.replica_bl_names = [[] for x in self.all_ports]
|
self.replica_bl_names = [[] for x in self.all_ports]
|
||||||
# Dummy wordlines by port
|
# Dummy wordlines by port
|
||||||
self.dummy_bitline_names = []
|
self.dummy_bitline_names = []
|
||||||
|
|
||||||
# Regular array bitline names
|
# Regular array bitline names
|
||||||
self.bitcell_array_bitline_names = self.bitcell_array.get_all_bitline_names()
|
self.bitcell_array_bitline_names = self.bitcell_array.get_all_bitline_names()
|
||||||
|
|
||||||
# These are the non-indexed names
|
# These are the non-indexed names
|
||||||
dummy_bitline_names = ["dummy_" + x for x in self.cell.get_all_bitline_names()]
|
dummy_bitline_names = ["dummy_" + x for x in self.cell.get_all_bitline_names()]
|
||||||
self.dummy_bitline_names.append([x+"_left" for x in dummy_bitline_names])
|
self.dummy_bitline_names.append([x + "_left" for x in dummy_bitline_names])
|
||||||
self.dummy_bitline_names.append([x+"_right" for x in dummy_bitline_names])
|
self.dummy_bitline_names.append([x + "_right" for x in dummy_bitline_names])
|
||||||
|
|
||||||
# Array of all port bitline names
|
# Array of all port bitline names
|
||||||
for port in range(self.add_left_rbl + self.add_right_rbl):
|
for port in range(self.add_left_rbl + self.add_right_rbl):
|
||||||
|
|
@ -204,14 +204,10 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array):
|
||||||
self.replica_bitline_names[port] = bitline_names
|
self.replica_bitline_names[port] = bitline_names
|
||||||
|
|
||||||
# Dummy bitlines are not connected to anything
|
# Dummy bitlines are not connected to anything
|
||||||
# br pins are not connected to anything
|
|
||||||
for port in range(self.add_left_rbl):
|
|
||||||
self.bitline_names.extend(self.replica_bitline_names[port])
|
|
||||||
self.bitline_names.extend(self.bitcell_array_bitline_names)
|
self.bitline_names.extend(self.bitcell_array_bitline_names)
|
||||||
# br pins are not connected to anything
|
|
||||||
for port in range(self.left_rbl, self.left_rbl + self.right_rbl):
|
|
||||||
self.bitline_names.extend(self.replica_bitline_names[port])
|
|
||||||
|
|
||||||
|
for port in self.all_ports:
|
||||||
|
self.add_pin_list(self.replica_bitline_names[port], "INOUT")
|
||||||
self.add_pin_list(self.bitline_names, "INOUT")
|
self.add_pin_list(self.bitline_names, "INOUT")
|
||||||
|
|
||||||
def add_wordline_pins(self):
|
def add_wordline_pins(self):
|
||||||
|
|
@ -240,7 +236,7 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array):
|
||||||
# Left port WLs
|
# Left port WLs
|
||||||
for port in range(self.left_rbl):
|
for port in range(self.left_rbl):
|
||||||
# Make names for all RBLs
|
# Make names for all RBLs
|
||||||
wl_names=["rbl_{0}_{1}".format(self.cell.get_wl_name(x), port) for x in range(len(self.cell.get_all_wl_names()))]
|
wl_names=["rbl_{0}_{1}".format(x, port) for x in self.cell.get_all_wl_names()]
|
||||||
# Keep track of the pin that is the RBL
|
# Keep track of the pin that is the RBL
|
||||||
self.replica_wordline_names[port] = wl_names
|
self.replica_wordline_names[port] = wl_names
|
||||||
self.wordline_names.extend(wl_names)
|
self.wordline_names.extend(wl_names)
|
||||||
|
|
@ -251,11 +247,10 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array):
|
||||||
# Right port WLs
|
# Right port WLs
|
||||||
for port in range(self.left_rbl, self.left_rbl + self.right_rbl):
|
for port in range(self.left_rbl, self.left_rbl + self.right_rbl):
|
||||||
# Make names for all RBLs
|
# Make names for all RBLs
|
||||||
wl_names=["rbl_{0}_{1}".format(self.cell.get_wl_name(x), port) for x in range(len(self.cell.get_all_wl_names()))]
|
wl_names=["rbl_{0}_{1}".format(x, port) for x in self.cell.get_all_wl_names()]
|
||||||
# Keep track of the pin that is the RBL
|
# Keep track of the pin that is the RBL
|
||||||
self.replica_wordline_names[port] = wl_names
|
self.replica_wordline_names[port] = wl_names
|
||||||
self.wordline_names.extend(wl_names)
|
self.wordline_names.extend(wl_names)
|
||||||
|
|
||||||
|
|
||||||
self.dummy_wordline_names["top"] = ["{0}_top".format(x) for x in dummy_cell_wl_names]
|
self.dummy_wordline_names["top"] = ["{0}_top".format(x) for x in dummy_cell_wl_names]
|
||||||
self.wordline_names.extend(self.dummy_wordline_names["top"])
|
self.wordline_names.extend(self.dummy_wordline_names["top"])
|
||||||
|
|
@ -463,13 +458,30 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array):
|
||||||
for inst in list(self.replica_col_inst.values()):
|
for inst in list(self.replica_col_inst.values()):
|
||||||
self.copy_layout_pin(inst, pin_name)
|
self.copy_layout_pin(inst, pin_name)
|
||||||
|
|
||||||
def get_rbl_wordline_names(self, port):
|
def get_rbl_wordline_names(self, port=None):
|
||||||
""" Return the WL for the given RBL port """
|
"""
|
||||||
return self.replica_wordline_names[port]
|
Return the ACTIVE WL for the given RBL port.
|
||||||
|
Inactive will be set to gnd.
|
||||||
|
"""
|
||||||
|
if port == None:
|
||||||
|
temp = []
|
||||||
|
for port in self.all_ports:
|
||||||
|
temp.extend(self.replica_wordline_names[port])
|
||||||
|
return temp
|
||||||
|
else:
|
||||||
|
wl_names = self.replica_wordline_names[port]
|
||||||
|
return wl_names[port]
|
||||||
|
|
||||||
def get_rbl_bitline_names(self, port):
|
def get_rbl_bitline_names(self, port=None):
|
||||||
""" Return the BL for the given RBL port """
|
""" Return the BL for the given RBL port """
|
||||||
return self.replica_bitline_names[port]
|
if port == None:
|
||||||
|
temp = []
|
||||||
|
for port in self.all_ports:
|
||||||
|
temp.extend(self.replica_bitline_names[port])
|
||||||
|
return temp
|
||||||
|
else:
|
||||||
|
bl_names = self.replica_bitline_names[port]
|
||||||
|
return bl_names[2 * port:2 * port + 2]
|
||||||
|
|
||||||
def get_wordline_names(self):
|
def get_wordline_names(self):
|
||||||
""" Return the wordline names """
|
""" Return the wordline names """
|
||||||
|
|
|
||||||
|
|
@ -346,6 +346,7 @@ class sram_base(design, verilog, lef):
|
||||||
temp.append("dout{0}[{1}]".format(port, bit))
|
temp.append("dout{0}[{1}]".format(port, bit))
|
||||||
for port in self.all_ports:
|
for port in self.all_ports:
|
||||||
temp.append("rbl_bl{0}".format(port))
|
temp.append("rbl_bl{0}".format(port))
|
||||||
|
temp.append("rbl_br{0}".format(port))
|
||||||
for port in self.write_ports:
|
for port in self.write_ports:
|
||||||
for bit in range(self.word_size + self.num_spare_cols):
|
for bit in range(self.word_size + self.num_spare_cols):
|
||||||
temp.append("bank_din{0}[{1}]".format(port, bit))
|
temp.append("bank_din{0}[{1}]".format(port, bit))
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue