diff --git a/Makefile b/Makefile index 12c9eaa7..329dc824 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,7 @@ SRAM_LIB_GIT_REPO ?= https://github.com/vlsida/sky130_fd_bd_sram.git # Use this for development #SRAM_LIB_GIT_REPO ?= git@github.com:VLSIDA/sky130_fd_bd_sram.git #SRAM_LIB_GIT_REPO ?= https://github.com/google/skywater-pdk-libs-sky130_fd_bd_sram.git -SRAM_LIB_GIT_COMMIT ?= baa2b14282ee6c8498a9e480c88a5096fdce2b06 +SRAM_LIB_GIT_COMMIT ?= 118c1a628c5f8ffb58a8e1a20de2b67c5058345f # Open PDKs OPEN_PDKS_DIR ?= $(PDK_ROOT)/open_pdks diff --git a/compiler/modules/pattern.py b/compiler/modules/pattern.py index 5d8ac143..84a3f232 100644 --- a/compiler/modules/pattern.py +++ b/compiler/modules/pattern.py @@ -193,7 +193,7 @@ class pattern(): for row in range(self.row_max+1): x = 0 for col in range(self.col_max+1): - inst = self.parent_design.all_inst[row, col] + inst = self.parent_design.all_inst[self.row_max - row, col] self.place_inst(inst, (x, y)) x += inst.width y += inst.height diff --git a/compiler/modules/replica_bitcell_array.py b/compiler/modules/replica_bitcell_array.py index d3dcffac..2004a84c 100644 --- a/compiler/modules/replica_bitcell_array.py +++ b/compiler/modules/replica_bitcell_array.py @@ -325,14 +325,15 @@ class replica_bitcell_array(bitcell_base_array): # Replica wordlines (go by the row instead of replica column because we may have to add a pin # even though the column is in another local bitcell array) - for (names, inst) in zip(self.rbl_wordline_names, self.dummy_row_replica_insts): - for (wl_name, pin_name) in zip(names, self.dummy_rows[0].get_wordline_names()): - pin = inst.get_pin(pin_name) - self.add_layout_pin(text=wl_name, - layer=pin.layer, - offset=pin.ll().scale(0, 1), - width=self.width, - height=pin.height()) + if self.rbl != [0,0]: + for (names, inst) in zip(self.rbl_wordline_names, self.dummy_row_replica_insts): + for (wl_name, pin_name) in zip(names, self.dummy_rows[0].get_wordline_names()): + pin = inst.get_pin(pin_name) + self.add_layout_pin(text=wl_name, + layer=pin.layer, + offset=pin.ll().scale(0, 1), + width=self.width, + height=pin.height()) # Main array bl/br for pin_name in self.all_bitline_names: diff --git a/compiler/modules/replica_column.py b/compiler/modules/replica_column.py index 37eebc2d..13d01237 100644 --- a/compiler/modules/replica_column.py +++ b/compiler/modules/replica_column.py @@ -100,14 +100,13 @@ class replica_column(bitcell_base_array): else: core_block[row][0] = geometry.instance("rbc_{}".format(row), mod=self.replica_cell, is_bitcell=True, mirror='MX') else: - if current_row %2 == 0: + if current_row % 2 == 0: core_block[row][0] = geometry.instance("rbc_{}".format(row), mod=self.dummy_cell, is_bitcell=True) else: core_block[row][0] = geometry.instance("rbc_{}".format(row), mod=self.dummy_cell, is_bitcell=True, mirror='MX') current_row += 1 if self.cell.mirror.y: - print(self.column_offset) for row in range(self.total_size): if self.column_offset % 2 == 0: if core_block[row][0].mirror=='MX': diff --git a/compiler/tests/14_capped_replica_bitcell_array_norbl_1rw_test.py b/compiler/tests/14_capped_replica_bitcell_array_norbl_1rw_test.py index 56080536..2179bc7e 100755 --- a/compiler/tests/14_capped_replica_bitcell_array_norbl_1rw_test.py +++ b/compiler/tests/14_capped_replica_bitcell_array_norbl_1rw_test.py @@ -26,7 +26,7 @@ class capped_replica_bitcell_array_norbl_1rw_test(openram_test): openram.setup_bitcell() debug.info(2, "Testing 7x5 capped replica array for 1rw cell without replica column or dummy row") - a = factory.create(module_type="capped_replica_bitcell_array", cols=7, rows=5, rbl=[0, 0]) + a = factory.create(module_type="capped_replica_bitcell_array", cols=8, rows=6, rbl=[0, 0]) self.local_check(a) openram.end_openram() diff --git a/compiler/tests/Makefile b/compiler/tests/Makefile index 7f1bef57..6453ec81 100644 --- a/compiler/tests/Makefile +++ b/compiler/tests/Makefile @@ -1,3 +1,4 @@ +SHELL := /bin/bash TOP_DIR := $(realpath $(dir $(lastword $(MAKEFILE_LIST)))../..) include $(TOP_DIR)/openram.mk diff --git a/macros/Makefile b/macros/Makefile index b50db045..d7000a62 100644 --- a/macros/Makefile +++ b/macros/Makefile @@ -64,6 +64,9 @@ all: | configs example: $(EXAMPLE_STAMPS) .PHONY: example +sp: sky130_sram_1kbyte_1rw_32x256_8 sky130_sram_2kbyte_1rw_32x512_8 sky130_sram_4kbyte_1rw_32x1024_8 sky130_sram_4kbyte_1rw_64x512_8 +.PHONY: sp + sky130: $(SKY130_STAMPS) .PHONY: sky130 diff --git a/technology/sky130/custom/sky130_bitcell_array.py b/technology/sky130/custom/sky130_bitcell_array.py index 09287d68..f39c95e2 100644 --- a/technology/sky130/custom/sky130_bitcell_array.py +++ b/technology/sky130/custom/sky130_bitcell_array.py @@ -20,8 +20,6 @@ class sky130_bitcell_array(bitcell_array, sky130_bitcell_base_array): Assumes bit-lines and word lines are connected by abutment. """ def __init__(self, rows, cols, column_offset=0, name=""): - if rows % 2 == 0: - debug.error("Invalid number of rows {}. number of rows (excluding dummy rows) must be odd to connect to col ends".format(rows), -1) super().__init__(rows=rows, cols=cols, column_offset=column_offset, name=name) def add_modules(self): @@ -53,7 +51,8 @@ class sky130_bitcell_array(bitcell_array, sky130_bitcell_base_array): pattern.append_row_to_block(bit_block, bit_row_opt1) pattern.append_row_to_block(bit_block, bit_row_opt1a) for row in bit_block: - row = pattern.rotate_list(row, self.column_offset * 2) + row = pattern.rotate_list(row, self.column_offset * 2) + print(bit_block) self.pattern = pattern(self, "bitcell_array", bit_block, num_rows=self.row_size, num_cols=self.column_size, num_cores_x=ceil(self.column_size/2), num_cores_y=ceil(self.row_size/2), name_template="bit_r{0}_c{1}") self.pattern.connect_array() diff --git a/technology/sky130/custom/sky130_bitcell_base_array.py b/technology/sky130/custom/sky130_bitcell_base_array.py index 7ad024ab..292ff39d 100644 --- a/technology/sky130/custom/sky130_bitcell_base_array.py +++ b/technology/sky130/custom/sky130_bitcell_base_array.py @@ -11,7 +11,7 @@ from openram.modules import bitcell_base_array from openram.sram_factory import factory from openram.tech import layer from openram import OPTS - +from openram.modules import pattern class sky130_bitcell_base_array(bitcell_base_array): """ diff --git a/technology/sky130/custom/sky130_replica_bitcell_array.py b/technology/sky130/custom/sky130_replica_bitcell_array.py index 74c9cf76..f6e0639d 100644 --- a/technology/sky130/custom/sky130_replica_bitcell_array.py +++ b/technology/sky130/custom/sky130_replica_bitcell_array.py @@ -27,5 +27,6 @@ class sky130_replica_bitcell_array(replica_bitcell_array, sky130_bitcell_base_ar bitcell (Bl/BR disconnected). """ def __init__(self, rows, cols, rbl=None, left_rbl=None, right_rbl=None, name=""): + debug.check((cols+ sum(rbl)) % 2==0, "must have an even number of cols including replica cols; you can add a spare col to fix this") super().__init__(rows, cols, rbl, left_rbl, right_rbl, name) diff --git a/technology/sky130/custom/sky130_replica_column.py b/technology/sky130/custom/sky130_replica_column.py index 6a749b2d..cedfaf5f 100644 --- a/technology/sky130/custom/sky130_replica_column.py +++ b/technology/sky130/custom/sky130_replica_column.py @@ -43,27 +43,27 @@ class sky130_replica_column(replica_column, sky130_bitcell_base_array): self.cell_inst={} replica_row_opt1 = [geometry.instance("rep_00_opt1", mod=self.replica_cell, is_bitcell=True, mirror='XY')] \ - + [geometry.instance("rep_01_strap", mod=self.strap_p, is_bitcell=False, mirror='MX')]\ + + [geometry.instance("rep_01_strap_p", mod=self.strap_p, is_bitcell=False, mirror='MX')]\ + [geometry.instance("rep_02_opt1", mod=self.replica_cell, is_bitcell=True, mirror='MX')] \ - + [geometry.instance("rep_03_strap_p", mod=self.strap, is_bitcell=False, mirror='MX')] + + [geometry.instance("rep_03_strap", mod=self.strap, is_bitcell=False, mirror='MX')] replica_row_opt1a = [geometry.instance("rep_10_opt1a", mod=self.replica_cell2, is_bitcell=True, mirror='MY')] \ - + [geometry.instance("rep_11_strapa", mod=self.strap_p, is_bitcell=False)] \ + + [geometry.instance("rep_11_strap_p", mod=self.strap_p, is_bitcell=False)] \ + [geometry.instance("rep_12_opt1a", mod=self.replica_cell2, is_bitcell=True)] \ - + [geometry.instance("rep_13_strapa_p", mod=self.strapa, is_bitcell=False)] + + [geometry.instance("rep_13_strapaa", mod=self.strapa, is_bitcell=False)] dummy_row_opt1 = [geometry.instance("dummy_00_opt1", mod=self.dummy_cell, is_bitcell=True, mirror='XY')] \ - + [geometry.instance("dummy_01_strap", mod=self.strap_p, is_bitcell=False, mirror='MX')]\ + + [geometry.instance("dummy_01_strap_p", mod=self.strap_p, is_bitcell=False, mirror='MX')]\ + [geometry.instance("dummy_02_opt1", mod=self.dummy_cell, is_bitcell=True, mirror='MX')] \ - + [geometry.instance("dummy_03_strap_p", mod=self.strap, is_bitcell=False, mirror='MX')] + + [geometry.instance("dummy_03_strap", mod=self.strap, is_bitcell=False, mirror='MX')] dummy_row_opt1a = [geometry.instance("dummy_10_opt1a", mod=self.dummy_cell2, is_bitcell=True, mirror='MY')] \ - + [geometry.instance("dummy_11_strapa", mod=self.strap_p, is_bitcell=False)] \ + + [geometry.instance("dummy_11_strap_p", mod=self.strap_p, is_bitcell=False)] \ + [geometry.instance("dummy_12_opt1a", mod=self.dummy_cell2, is_bitcell=True)] \ - + [geometry.instance("dummy_13_strapa_p", mod=self.strapa, is_bitcell=False)] + + [geometry.instance("dummy_13_strapa", mod=self.strapa, is_bitcell=False)] bit_block = [] - if self.column_offset % 2: + if self.column_offset % 2 == 0: replica_row_opt1 = replica_row_opt1[0:2] replica_row_opt1a = replica_row_opt1a[0:2] dummy_row_opt1 = dummy_row_opt1[0:2] @@ -73,19 +73,19 @@ class sky130_replica_column(replica_column, sky130_bitcell_base_array): replica_row_opt1a = replica_row_opt1a[2:4] dummy_row_opt1 = dummy_row_opt1[2:4] dummy_row_opt1a = dummy_row_opt1a[2:4] - + print(self.row_start) current_row = self.row_start for row in range(self.total_size): # Regular array cells are replica cells # Replic bit specifies which other bit (in the full range (0,total_size) to make a replica cell. # All other cells are dummies if (row == self.replica_bit) or (row >= self.row_start and row < self.row_end): - if current_row % 2 == 0: + if current_row % 2 == 1: pattern.append_row_to_block(bit_block, replica_row_opt1) else: pattern.append_row_to_block(bit_block, replica_row_opt1a) else: - if current_row % 2 == 0: + if current_row % 2 == 1: pattern.append_row_to_block(bit_block, dummy_row_opt1) else: pattern.append_row_to_block(bit_block, dummy_row_opt1a) diff --git a/technology/sky130/custom/sky130_row_cap_array.py b/technology/sky130/custom/sky130_row_cap_array.py index 24e85585..7031e388 100644 --- a/technology/sky130/custom/sky130_row_cap_array.py +++ b/technology/sky130/custom/sky130_row_cap_array.py @@ -56,13 +56,13 @@ class sky130_row_cap_array(row_cap_array, sky130_bitcell_base_array): rowend = geometry.instance("row_cap_rowend", mod=self.rowend, is_bitcell=True, mirror="MX") rowenda = geometry.instance("row_cap_rowenda", mod=self.rowenda, is_bitcell=True) - pattern.append_row_to_block(bit_block, [bottom_corner]) - for row in range(1,self.row_size-1): - if row % 2 == 0: + pattern.append_row_to_block(bit_block, [top_corner]) + for row in range(1, self.row_size-1): + if row % 2 == 1: pattern.append_row_to_block(bit_block, [rowend]) else: pattern.append_row_to_block(bit_block, [rowenda]) - pattern.append_row_to_block(bit_block, [top_corner]) + pattern.append_row_to_block(bit_block, [bottom_corner]) self.pattern = pattern(self, "row_cap_array_" + self.location, bit_block, num_rows=self.row_size, num_cols=self.column_size, num_cores_x=ceil(self.column_size/2), num_cores_y=ceil(self.row_size/2), name_template="row_cap_array" + self.location + "_r{0}_c{1}") self.pattern.connect_array_raw()