diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index cd06a969..4b9c3990 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -83,7 +83,7 @@ class bank(design.design): for bit in range(self.word_size + self.num_spare_cols): self.add_pin("dout{0}_{1}".format(port, bit), "OUTPUT") 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 bit in range(self.word_size + self.num_spare_cols): self.add_pin("din{0}_{1}".format(port, bit), "INPUT") @@ -114,6 +114,8 @@ class bank(design.design): def route_layout(self): """ Create routing amoung the modules """ self.route_central_bus() + + self.route_unused_wordlines() for port in self.all_ports: self.route_bitlines(port) @@ -375,7 +377,6 @@ class bank(design.design): rows=self.num_rows) self.add_mod(self.port_address) - self.port_rbl_map = self.all_ports self.num_rbl = len(self.all_ports) 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", mod=self.bitcell_array) temp = [] + rbl_names = self.bitcell_array.get_rbl_bitline_names() + temp.extend(rbl_names) bitline_names = self.bitcell_array.get_bitline_names() temp.extend(bitline_names) # 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.append("vdd") temp.append("gnd") @@ -410,14 +425,13 @@ class bank(design.design): def create_port_data(self): """ Creating Port Data """ - self.port_data_inst = [None] * len(self.all_ports) for port in self.all_ports: self.port_data_inst[port]=self.add_inst(name="port_data{}".format(port), mod=self.port_data[port]) 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) for col in range(self.num_cols + self.num_spare_cols): 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): temp.append("bank_spare_wen{0}_{1}".format(port, bit)) temp.extend(["vdd", "gnd"]) - self.connect_inst(temp) def place_port_data(self, offsets): @@ -466,7 +479,7 @@ class bank(design.design): temp = [] for bit in range(self.row_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): temp.append("{0}_{1}".format(self.wl_names[port], row)) temp.extend(["vdd", "gnd"]) @@ -654,7 +667,7 @@ class bank(design.design): # Port 0 # 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 - 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 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", @@ -669,7 +682,7 @@ class bank(design.design): if len(self.all_ports)==2: # 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_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) # 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", @@ -702,11 +715,11 @@ class bank(design.design): # connect spare bitlines 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_br_name.format(self.num_cols+i), "spare" + inst2_br_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)) # 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"]): self.connect_bitline(inst1, inst2, array_name, data_name) @@ -949,7 +962,35 @@ class bank(design.design): self.add_label(text=data_name, layer="m1", 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): """ 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), 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]) - for rbl_wl_name in rbl_wl_names: - connection.append((self.prefix + "wl_en{}".format(port), - self.bitcell_array_inst.get_pin(rbl_wl_name))) - + rbl_wl_name = self.bitcell_array.get_rbl_wordline_names(port) + connection.append((self.prefix + "wl_en{}".format(port), + self.bitcell_array_inst.get_pin(rbl_wl_name))) + if port in self.write_ports: connection.append((self.prefix + "w_en{}".format(port), 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_via_center(layers=self.m1_stack, offset=control_pos) - + 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""" # Decoder is assumed to have settled before the negative edge of the clock. diff --git a/compiler/modules/replica_bitcell_array.py b/compiler/modules/replica_bitcell_array.py index 1119d546..48da3630 100644 --- a/compiler/modules/replica_bitcell_array.py +++ b/compiler/modules/replica_bitcell_array.py @@ -174,7 +174,7 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array): def add_bitline_pins(self): - # All bitline names for all ports + # Regular bitline names for all ports self.bitline_names = [] # Bitline names for each port 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) self.replica_bl_names = [[] for x in self.all_ports] # Dummy wordlines by port - self.dummy_bitline_names = [] + self.dummy_bitline_names = [] # Regular array bitline names self.bitcell_array_bitline_names = self.bitcell_array.get_all_bitline_names() # These are the non-indexed 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+"_right" 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]) # Array of all port bitline names 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 # 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) - # 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") def add_wordline_pins(self): @@ -240,7 +236,7 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array): # Left port WLs for port in range(self.left_rbl): # 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 self.replica_wordline_names[port] = 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 for port in range(self.left_rbl, self.left_rbl + self.right_rbl): # 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 self.replica_wordline_names[port] = 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.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()): self.copy_layout_pin(inst, pin_name) - def get_rbl_wordline_names(self, port): - """ Return the WL for the given RBL port """ - return self.replica_wordline_names[port] + def get_rbl_wordline_names(self, port=None): + """ + 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 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): """ Return the wordline names """ diff --git a/compiler/sram/sram_base.py b/compiler/sram/sram_base.py index 12af7cf6..23c05dbf 100644 --- a/compiler/sram/sram_base.py +++ b/compiler/sram/sram_base.py @@ -346,6 +346,7 @@ class sram_base(design, verilog, lef): temp.append("dout{0}[{1}]".format(port, bit)) for port in self.all_ports: temp.append("rbl_bl{0}".format(port)) + temp.append("rbl_br{0}".format(port)) for port in self.write_ports: for bit in range(self.word_size + self.num_spare_cols): temp.append("bank_din{0}[{1}]".format(port, bit))