Fix up to SRAM level with new replica bitcell array ports.

This commit is contained in:
mrg 2020-08-13 14:29:10 -07:00
parent a55909930f
commit 50525e70f4
3 changed files with 90 additions and 37 deletions

View File

@ -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")
@ -115,6 +115,8 @@ class bank(design.design):
""" 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)
self.route_rbl(port) self.route_rbl(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)
@ -950,6 +963,34 @@ class bank(design.design):
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,8 +1002,7 @@ 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)))

View File

@ -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]
@ -190,8 +190,8 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array):
# 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,12 +247,11 @@ 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 """

View File

@ -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))