diff --git a/compiler/custom/s8_col_end.py b/compiler/custom/s8_col_end.py index f35d691a..a6961027 100644 --- a/compiler/custom/s8_col_end.py +++ b/compiler/custom/s8_col_end.py @@ -22,18 +22,23 @@ class s8_col_end(design.design): if version == "colend": self.name = "s8sram16x16_colend" + structure = "s8sram16x16_colend\x00" elif version == "colend_p_cent": self.name = "s8sram16x16_colend_p_cent" + structure = "s8sram16x16_colend_p_cent\x00" elif version == "colenda": self.name = "s8sram16x16_colenda" + structure = "s8sram16x16_colenda\x00" elif version == "colenda_p_cent": self.name = "s8sram16x16_colenda_p_cent" + structure = "s8sram16x16_colenda_p_cent" else: debug.error("Invalid type for col_end", -1) design.design.__init__(self, name=self.name) (self.width, self.height) = utils.get_libcell_size(self.name, GDS["unit"], - layer["mem"]) + layer["mem"], + structure) pin_map = utils.get_libcell_pins(pin_names, self.name, GDS["unit"]) diff --git a/compiler/modules/replica_bitcell_array.py b/compiler/modules/replica_bitcell_array.py index 4a097402..5589e18b 100644 --- a/compiler/modules/replica_bitcell_array.py +++ b/compiler/modules/replica_bitcell_array.py @@ -45,11 +45,12 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array): debug.check(sum(rbl) <= len(self.all_ports), "Invalid number of RBLs for port configuration.") + if not cell_properties.compare_ports(cell_properties.bitcell_array.use_custom_cell_arrangement): - # Two dummy rows plus replica even if we don't add the column - self.extra_rows = 2 + sum(rbl) - # Two dummy cols plus replica if we add the column - self.extra_cols = 2 + self.add_left_rbl + self.add_right_rbl + # Two dummy rows plus replica even if we don't add the column + self.extra_rows = 2 + sum(rbl) + # Two dummy cols plus replica if we add the column + self.extra_cols = 2 + self.add_left_rbl + self.add_right_rbl self.create_netlist() if not OPTS.netlist_only: @@ -115,31 +116,30 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array): column_offset=column_offset, replica_bit=replica_bit) self.add_mod(self.replica_columns[bit]) - - # Dummy row - self.dummy_row = factory.create(module_type="dummy_array", - cols=self.column_size, - rows=1, - # dummy column + left replica column - column_offset=1 + self.add_left_rbl, - mirror=0) - self.add_mod(self.dummy_row) - - # If there are bitcell end caps, replace the dummy cells on the edge of the bitcell array with end caps. + # If there are bitcell end caps, replace the dummy cells on the edge of the bitcell array with end caps. try: end_caps_enabled = cell_properties.bitcell.end_caps except AttributeError: end_caps_enabled = False + if not cell_properties.compare_ports(cell_properties.bitcell_array.use_custom_cell_arrangement): + # Dummy row + self.dummy_row = factory.create(module_type="dummy_array", + cols=self.column_size, + rows=1, + # dummy column + left replica column + column_offset=1 + self.add_left_rbl, + mirror=0) + self.add_mod(self.dummy_row) - # Dummy Row or Col Cap, depending on bitcell array properties - col_cap_module_type = ("col_cap_array" if end_caps_enabled else "dummy_array") - self.col_cap = factory.create(module_type=col_cap_module_type, - cols=self.column_size, - rows=1, - # dummy column + left replica column(s) - column_offset=1 + self.add_left_rbl, - mirror=0) - self.add_mod(self.col_cap) + # Dummy Row or Col Cap, depending on bitcell array properties + col_cap_module_type = ("col_cap_array" if end_caps_enabled else "dummy_array") + self.col_cap = factory.create(module_type=col_cap_module_type, + cols=self.column_size, + rows=1, + # dummy column + left replica column(s) + column_offset=1 + self.add_left_rbl, + mirror=0) + self.add_mod(self.col_cap) # Dummy Col or Row Cap, depending on bitcell array properties row_cap_module_type = ("row_cap_array" if end_caps_enabled else "dummy_array") diff --git a/compiler/modules/replica_column.py b/compiler/modules/replica_column.py index f1f6eebb..78ec56fd 100644 --- a/compiler/modules/replica_column.py +++ b/compiler/modules/replica_column.py @@ -50,8 +50,6 @@ class replica_column(design.design): self.create_instances() def create_layout(self): - self.height = self.total_size * self.cell.height - self.width = self.cell.width self.place_instances() self.add_layout_pins() @@ -99,6 +97,7 @@ class replica_column(design.design): else: self.replica_cell = factory.create(module_type="s8_bitcell", version = "opt1") self.add_mod(self.replica_cell) + self.cell = self.replica_cell self.replica_cell2 = factory.create(module_type="s8_bitcell", version = "opt1a") self.add_mod(self.replica_cell2) @@ -167,82 +166,121 @@ class replica_column(design.design): custom_replica_column_arrangement(self) def place_instances(self): - from tech import cell_properties - # Flip the mirrors if we have an odd number of replica+dummy rows at the bottom - # so that we will start with mirroring rather than not mirroring - rbl_offset = (self.left_rbl + 1) %2 + if not cell_properties.compare_ports(cell_properties.bitcell_array.use_custom_cell_arrangement): - # if our bitcells are mirrored on the y axis, check if we are in global - # column that needs to be flipped. - dir_y = False - xoffset = 0 - if cell_properties.bitcell.mirror.y and self.column_offset % 2: - dir_y = True - xoffset = self.replica_cell.width + # Flip the mirrors if we have an odd number of replica+dummy rows at the bottom + # so that we will start with mirroring rather than not mirroring + rbl_offset = (self.left_rbl + 1) %2 - for row in range(self.total_size): - # name = "bit_r{0}_{1}".format(row, "rbl") - dir_x = cell_properties.bitcell.mirror.x and (row + rbl_offset) % 2 + # if our bitcells are mirrored on the y axis, check if we are in global + # column that needs to be flipped. + dir_y = False + xoffset = 0 + if cell_properties.bitcell.mirror.y and self.column_offset % 2: + dir_y = True + xoffset = self.replica_cell.width - offset = vector(xoffset, self.cell.height * (row + (row + rbl_offset) % 2)) + for row in range(self.total_size): + # name = "bit_r{0}_{1}".format(row, "rbl") + dir_x = cell_properties.bitcell.mirror.x and (row + rbl_offset) % 2 - if dir_x and dir_y: - dir_key = "XY" - elif dir_x: - dir_key = "MX" - elif dir_y: - dir_key = "MY" - else: - dir_key = "" + offset = vector(xoffset, self.cell.height * (row + (row + rbl_offset) % 2)) - self.cell_inst[row].place(offset=offset, - mirror=dir_key) + if dir_x and dir_y: + dir_key = "XY" + elif dir_x: + dir_key = "MX" + elif dir_y: + dir_key = "MY" + else: + dir_key = "" + + self.cell_inst[row].place(offset=offset, + mirror=dir_key) + else: + from tech import custom_replica_cell_placement + custom_replica_cell_placement(self) def add_layout_pins(self): """ Add the layout pins """ + if not cell_properties.compare_ports(cell_properties.bitcell_array.use_custom_cell_arrangement): + for port in self.all_ports: + bl_pin = self.cell_inst[0].get_pin(self.cell.get_bl_name(port)) + self.add_layout_pin(text="bl_{0}_{1}".format(port, 0), + layer=bl_pin.layer, + offset=bl_pin.ll().scale(1, 0), + width=bl_pin.width(), + height=self.height) + bl_pin = self.cell_inst[0].get_pin(self.cell.get_br_name(port)) + self.add_layout_pin(text="br_{0}_{1}".format(port, 0), + layer=bl_pin.layer, + offset=bl_pin.ll().scale(1, 0), + width=bl_pin.width(), + height=self.height) - for port in self.all_ports: - bl_pin = self.cell_inst[0].get_pin(self.cell.get_bl_name(port)) - self.add_layout_pin(text="bl_{0}_{1}".format(port, 0), - layer=bl_pin.layer, - offset=bl_pin.ll().scale(1, 0), - width=bl_pin.width(), - height=self.height) - bl_pin = self.cell_inst[0].get_pin(self.cell.get_br_name(port)) - self.add_layout_pin(text="br_{0}_{1}".format(port, 0), - layer=bl_pin.layer, - offset=bl_pin.ll().scale(1, 0), - width=bl_pin.width(), - height=self.height) + try: + end_caps_enabled = cell_properties.bitcell.end_caps + except AttributeError: + end_caps_enabled = False + + if end_caps_enabled: + row_range_max = self.total_size - 1 + row_range_min = 1 + else: + row_range_max = self.total_size + row_range_min = 0 + + for port in self.all_ports: + for row in range(row_range_min, row_range_max): + wl_pin = self.cell_inst[row].get_pin(self.cell.get_wl_name(port)) + self.add_layout_pin(text="wl_{0}_{1}".format(port, row), + layer=wl_pin.layer, + offset=wl_pin.ll().scale(0, 1), + width=self.width, + height=wl_pin.height()) + + # Supplies are only connected in the ends + for (index, inst) in self.cell_inst.items(): + for pin_name in ["vdd", "gnd"]: + if inst in [self.cell_inst[0], self.cell_inst[self.total_size - 1]]: + self.copy_power_pins(inst, pin_name) + else: + self.copy_layout_pin(inst, pin_name) + else: + for port in self.all_ports: + bl_pin = self.cell_inst[2].get_pin(self.cell.get_bl_name(port)) + self.add_layout_pin(text="bl_{0}_{1}".format(port, 0), + layer=bl_pin.layer, + offset=bl_pin.ll().scale(1, 0), + width=bl_pin.width(), + height=self.height) + bl_pin = self.cell_inst[2].get_pin(self.cell.get_br_name(port)) + self.add_layout_pin(text="br_{0}_{1}".format(port, 0), + layer=bl_pin.layer, + offset=bl_pin.ll().scale(1, 0), + width=bl_pin.width(), + height=self.height) - try: - end_caps_enabled = cell_properties.bitcell.end_caps - except AttributeError: - end_caps_enabled = False - if end_caps_enabled: row_range_max = self.total_size - 1 row_range_min = 1 - else: - row_range_max = self.total_size - row_range_min = 0 - for port in self.all_ports: - for row in range(row_range_min, row_range_max): - wl_pin = self.cell_inst[row].get_pin(self.cell.get_wl_name(port)) - self.add_layout_pin(text="wl_{0}_{1}".format(port, row), - layer=wl_pin.layer, - offset=wl_pin.ll().scale(0, 1), - width=self.width, - height=wl_pin.height()) + for port in self.all_ports: + for row in range(row_range_min, row_range_max): + wl_pin = self.cell_inst[row].get_pin(self.cell.get_wl_name(port)) + self.add_layout_pin(text="wl_{0}_{1}".format(port, row), + layer=wl_pin.layer, + offset=wl_pin.ll().scale(0, 1), + width=self.width, + height=wl_pin.height()) - # Supplies are only connected in the ends - for (index, inst) in self.cell_inst.items(): - for pin_name in ["vdd", "gnd"]: - if inst in [self.cell_inst[0], self.cell_inst[self.total_size - 1]]: - self.copy_power_pins(inst, pin_name) - else: - self.copy_layout_pin(inst, pin_name) + # # Supplies are only connected in the ends + # for (index, inst) in self.cell_inst.items(): + # for pin_name in ["vdd", "gnd"]: + # if inst in [self.cell_inst[0], self.cell_inst[self.total_size - 1]]: + # self.copy_power_pins(inst, pin_name) + # else: + # self.copy_layout_pin(inst, pin_name) def get_bitline_names(self, port=None): if port == None: diff --git a/compiler/tests/missing_pin.gds b/compiler/tests/missing_pin.gds index 15ea40c5..25df96f6 100644 Binary files a/compiler/tests/missing_pin.gds and b/compiler/tests/missing_pin.gds differ diff --git a/compiler/tests/sram_1b_16_1rw_sky130.log b/compiler/tests/sram_1b_16_1rw_sky130.log index 506212d1..a39cad30 100644 Binary files a/compiler/tests/sram_1b_16_1rw_sky130.log and b/compiler/tests/sram_1b_16_1rw_sky130.log differ diff --git a/missing_pin.gds b/missing_pin.gds index 15ea40c5..25df96f6 100644 Binary files a/missing_pin.gds and b/missing_pin.gds differ diff --git a/sram_1b_16_1rw_sky130.log b/sram_1b_16_1rw_sky130.log index bd642b1d..312dc25b 100644 --- a/sram_1b_16_1rw_sky130.log +++ b/sram_1b_16_1rw_sky130.log @@ -15,3 +15,7 @@ [bitcell_base_array/__init__]: Creating replica_bitcell_array 4 x 4 [replica_bitcell_array/__init__]: Creating replica_bitcell_array 4 x 4 [bitcell_base_array/__init__]: Creating bitcell_array 4 x 4 +ERROR: file s8_bitcell.py: line 91: One port for bitcell only. + +ERROR: file s8_bitcell.py: line 91: One port for bitcell only. +