diff --git a/compiler/globals.py b/compiler/globals.py index 68d055ff..1d813e97 100644 --- a/compiler/globals.py +++ b/compiler/globals.py @@ -238,8 +238,8 @@ def setup_bitcell(): OPTS.dummy_bitcell = "dummy_pbitcell" OPTS.replica_bitcell = "replica_pbitcell" else: - num_ports = OPTS.num_rw_ports + OPTS.num_w_ports + OPTS.num_r_ports - OPTS.bitcell = "bitcell_{}port".format(num_ports) + OPTS.num_ports = OPTS.num_rw_ports + OPTS.num_w_ports + OPTS.num_r_ports + OPTS.bitcell = "bitcell_{}port".format(OPTS.num_ports) OPTS.dummy_bitcell = "dummy_" + OPTS.bitcell OPTS.replica_bitcell = "replica_" + OPTS.bitcell diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index 1f06aef3..f02a4f0e 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -72,7 +72,7 @@ class bank(design.design): # self.add_lvs_correspondence_points() # Remember the bank center for further placement - self.bank_array_ll = self.offset_all_coordinates().scale(-1, -1) + #self.bank_array_ll = self.offset_all_coordinates().scale(-1, -1) self.bank_array_ur = self.bitcell_array_inst.ur() self.bank_array_ul = self.bitcell_array_inst.ul() self.DRC_LVS() @@ -362,7 +362,9 @@ class bank(design.design): # A space for wells or jogging m2 self.m2_gap = max(2 * drc("pwell_to_nwell") + drc("nwell_enclose_active"), - 3 * self.m2_pitch) + 3 * self.m2_pitch, + drc("nwell_to_nwell")) + def add_modules(self): """ Add all the modules using the class loader """ @@ -386,11 +388,12 @@ class bank(design.design): cols=self.num_cols + self.num_spare_cols, rows=self.num_rows) self.add_mod(self.bitcell_array) + self.num_spare_cols += (self.bitcell_array.column_size % (self.word_size *self.words_per_row)) self.port_address = [] for port in self.all_ports: self.port_address.append(factory.create(module_type="port_address", - cols=self.bitcell_array.column_size + self.num_spare_cols, + cols=self.bitcell_array.column_size, rows=self.bitcell_array.row_size, port=port)) self.add_mod(self.port_address[port]) @@ -401,8 +404,9 @@ class bank(design.design): temp_pre = factory.create(module_type="port_data", sram_config=self.sram_config, dimension_override=True, - cols=self.bitcell_array.column_size + self.num_spare_cols, + cols=self.bitcell_array.column_size - self.num_spare_cols, rows=self.bitcell_array.row_size, + num_spare_cols=self.num_spare_cols, port=port, bit_offsets=self.bit_offsets) self.port_data.append(temp_pre) @@ -430,7 +434,6 @@ class bank(design.design): temp.append("vdd") temp.append("gnd") - self.connect_inst(temp) def place_bitcell_array(self, offset): @@ -449,10 +452,10 @@ class bank(design.design): temp.extend(["rbl_bl_{0}_{0}".format(port), "rbl_br_{0}_{0}".format(port)]) temp.extend(self.bitcell_array.get_bitline_names(port)) if port in self.read_ports: - for bit in range(int(self.bitcell_array.column_size/self.words_per_row) + self.num_spare_cols): + for bit in range(self.word_size + self.num_spare_cols): temp.append("dout{0}_{1}".format(port, bit)) if port in self.write_ports: - for bit in range(int(self.bitcell_array.column_size/self.words_per_row) + self.num_spare_cols): + for bit in range(self.word_size + self.num_spare_cols): temp.append("din{0}_{1}".format(port, bit)) # Will be empty if no col addr lines sel_names = ["sel{0}_{1}".format(port, x) for x in range(self.num_col_addr_lines)] diff --git a/compiler/modules/hierarchical_predecode.py b/compiler/modules/hierarchical_predecode.py index 2da123a1..386f9bb6 100644 --- a/compiler/modules/hierarchical_predecode.py +++ b/compiler/modules/hierarchical_predecode.py @@ -304,6 +304,7 @@ class hierarchical_predecode(design.design): overlapping_pin_space = drc["{0}_to_{0}".format(self.output_layer)] total_buffer_space = (overlapping_pin_space + via.height) + #FIXME: compute rail locations instead of just guessing and nudging while(True): drc_error = 0 for and_input in self.input_and_rail_pos: diff --git a/compiler/modules/port_data.py b/compiler/modules/port_data.py index c9ebc193..6f66d26f 100644 --- a/compiler/modules/port_data.py +++ b/compiler/modules/port_data.py @@ -21,26 +21,27 @@ class port_data(design.design): Port 0 always has the RBL on the left while port 1 is on the right. """ - def __init__(self, sram_config, port, bit_offsets=None, name="", rows=None, cols=None, dimension_override=False): + def __init__(self, sram_config, port, num_spare_cols=None, bit_offsets=None, name="", rows=None, cols=None, dimension_override=False): sram_config.set_local_config(self) if dimension_override: self.num_rows = rows self.num_cols = cols - self.word_size = int(self.num_cols/self.words_per_row) + self.word_size = sram_config.word_size self.port = port if self.write_size is not None: self.num_wmasks = int(math.ceil(self.word_size / self.write_size)) else: self.num_wmasks = 0 - + + if num_spare_cols is not None: + self.num_spare_cols = num_spare_cols + self.num_spare_cols if self.num_spare_cols is None: self.num_spare_cols = 0 - if not bit_offsets: bitcell = factory.create(module_type=OPTS.bitcell) - if(cell_properties.use_strap): + if(cell_properties.use_strap == True and OPTS.num_ports == 1): strap = factory.create(module_type=cell_properties.strap_module, version=cell_properties.strap_version) precharge_width = bitcell.width + strap.width self.bit_offsets = [] @@ -48,7 +49,6 @@ class port_data(design.design): self.bit_offsets.append(i * precharge_width) else: self.bit_offsets = bit_offsets - if name == "": name = "port_data_{0}".format(self.port) super().__init__(name) @@ -126,7 +126,6 @@ class port_data(design.design): for bit in range(self.num_spare_cols): self.add_pin("sparebl_{0}".format(bit), "INOUT") self.add_pin("sparebr_{0}".format(bit), "INOUT") - if self.port in self.read_ports: for bit in range(self.word_size + self.num_spare_cols): self.add_pin("dout_{}".format(bit), "OUTPUT") @@ -201,10 +200,11 @@ class port_data(design.design): # Used for names/dimensions only cell = factory.create(module_type=OPTS.bitcell) - if(cell_properties.use_strap): + if(cell_properties.use_strap == True and OPTS.num_ports == 1): strap = factory.create(module_type=cell_properties.strap_module, version=cell_properties.strap_version) precharge_width = cell.width + strap.width - + else: + precharge_width = cell.width if self.port == 0: # Append an offset on the left precharge_bit_offsets = [self.bit_offsets[0] - precharge_width] + self.bit_offsets @@ -580,19 +580,32 @@ class port_data(design.design): off = 1 else: off = 0 + if OPTS.num_ports > 1: + self.channel_route_bitlines(inst1=self.column_mux_array_inst, + inst1_bls_template="{inst}_out_{bit}", + inst2=inst2, + num_bits=self.word_size, + inst1_start_bit=start_bit) - self.channel_route_bitlines(inst1=self.column_mux_array_inst, - inst1_bls_template="{inst}_out_{bit}", - inst2=inst2, - num_bits=self.word_size, - inst1_start_bit=start_bit) + self.channel_route_bitlines(inst1=self.precharge_array_inst, + inst1_bls_template="{inst}_{bit}", + inst2=inst2, + num_bits=self.num_spare_cols, + inst1_start_bit=self.num_cols + off, + inst2_start_bit=self.word_size) + else: + self.connect_bitlines(inst1=self.column_mux_array_inst, + inst1_bls_template="{inst}_out_{bit}", + inst2=inst2, + num_bits=self.word_size, + inst1_start_bit=start_bit) - self.channel_route_bitlines(inst1=self.precharge_array_inst, - inst1_bls_template="{inst}_{bit}", - inst2=inst2, - num_bits=self.num_spare_cols, - inst1_start_bit=self.num_cols + off, - inst2_start_bit=self.word_size) + self.connect_bitlines(inst1=self.precharge_array_inst, + inst1_bls_template="{inst}_{bit}", + inst2=inst2, + num_bits=self.num_spare_cols, + inst1_start_bit=self.num_cols + off, + inst2_start_bit=self.word_size) elif layer_props.port_data.channel_route_bitlines: self.channel_route_bitlines(inst1=inst1, diff --git a/compiler/modules/sense_amp_array.py b/compiler/modules/sense_amp_array.py index 01b74c84..be9e9945 100644 --- a/compiler/modules/sense_amp_array.py +++ b/compiler/modules/sense_amp_array.py @@ -8,6 +8,7 @@ import design from vector import vector from sram_factory import factory +from tech import cell_properties import debug from globals import OPTS @@ -41,7 +42,6 @@ class sense_amp_array(design.design): self.en_layer = "m3" else: self.en_layer = "m1" - self.create_netlist() if not OPTS.netlist_only: self.create_layout() @@ -109,15 +109,22 @@ class sense_amp_array(design.design): self.en_name, "vdd", "gnd"]) def place_sense_amp_array(self): - if self.bitcell.width > self.amp.width: - self.amp_spacing = self.bitcell.width + cell = factory.create(module_type=OPTS.bitcell) + if(cell_properties.use_strap == True and OPTS.num_ports == 1): + strap = factory.create(module_type=cell_properties.strap_module, version=cell_properties.strap_version) + precharge_width = cell.width + strap.width + else: + precharge_width = cell.width + + if precharge_width > self.amp.width: + self.amp_spacing = precharge_width else: self.amp_spacing = self.amp.width if not self.offsets: self.offsets = [] for i in range(self.num_cols + self.num_spare_cols): - self.offsets.append(i * self.bitcell.width) + self.offsets.append(i * precharge_width) for i, xoffset in enumerate(self.offsets[0:self.num_cols:self.words_per_row]): if self.bitcell.mirror.y and (i * self.words_per_row + self.column_offset) % 2: @@ -128,7 +135,6 @@ class sense_amp_array(design.design): amp_position = vector(xoffset, 0) self.local_insts[i].place(offset=amp_position, mirror=mirror) - # place spare sense amps (will share the same enable as regular sense amps) for i, xoffset in enumerate(self.offsets[self.num_cols:]): index = self.word_size + i diff --git a/compiler/pgates/column_mux.py b/compiler/pgates/column_mux.py index 1e8c5bf8..6153328a 100644 --- a/compiler/pgates/column_mux.py +++ b/compiler/pgates/column_mux.py @@ -56,7 +56,13 @@ class column_mux(pgate.pgate): self.place_ptx() - self.width = self.bitcell.width + cell = factory.create(module_type=OPTS.bitcell) + if(cell_props.use_strap == True and OPTS.num_ports == 1): + strap = factory.create(module_type=cell_props.strap_module, version=cell_props.strap_version) + precharge_width = cell.width + strap.width + else: + precharge_width = cell.width + self.width = precharge_width self.height = self.nmos_upper.uy() + self.pin_height self.connect_poly() diff --git a/compiler/pgates/precharge.py b/compiler/pgates/precharge.py index c8f6d819..951fe834 100644 --- a/compiler/pgates/precharge.py +++ b/compiler/pgates/precharge.py @@ -30,7 +30,7 @@ class precharge(design.design): self.beta = parameter["beta"] self.ptx_width = self.beta * parameter["min_tx_size"] self.ptx_mults = 1 - if(cell_props.use_strap): + if(cell_props.use_strap == True and OPTS.num_ports == 1): strap = factory.create(module_type=cell_props.strap_module, version=cell_props.strap_version) self.width = self.bitcell.width + strap.width else: