From 53d53ec271f287dc049055a3d79e7596c3cabc76 Mon Sep 17 00:00:00 2001 From: Jesse Cirimelli-Low Date: Wed, 14 Jan 2026 12:08:26 -0800 Subject: [PATCH] checkpoint from tt submission --- compiler/characterizer/simulation.py | 8 +- compiler/globals.py | 2 +- compiler/modules/bitcell_base_array.py | 31 ++++++- .../modules/capped_replica_bitcell_array.py | 45 +++++----- compiler/modules/col_cap_array.py | 3 +- compiler/modules/dummy_array.py | 14 +-- compiler/modules/pattern.py | 2 +- compiler/modules/replica_column.py | 5 +- compiler/sram_config.py | 12 +-- compiler/tests/05_bitcell_array_test.py | 2 +- ...ed_replica_bitcell_array_norbl_1rw_test.py | 2 +- ..._replica_bitcell_array_leftrbl_1rw_test.py | 2 +- compiler/tests/19_single_bank_2mux_test.py | 4 +- install_conda.sh | 17 ++-- macros/sram_configs/sky130_sram_1rw_tiny.py | 12 ++- technology/sky130/custom/sky130_col_cap.py | 14 +-- .../sky130/custom/sky130_row_cap_array.py | 2 +- technology/sky130/tech/tech.py | 90 ++++++++++--------- 18 files changed, 154 insertions(+), 113 deletions(-) diff --git a/compiler/characterizer/simulation.py b/compiler/characterizer/simulation.py index 2dec0010..ac91ece2 100644 --- a/compiler/characterizer/simulation.py +++ b/compiler/characterizer/simulation.py @@ -611,10 +611,10 @@ class simulation(): Gets the signal name associated with the bitlines in the bank. """ # FIXME: change to a solution that does not depend on the technology - if OPTS.tech_name == "sky130" and len(self.all_ports) == 1: - cell_mod = factory.create(module_type=OPTS.bitcell, version="opt1") - else: - cell_mod = factory.create(module_type=OPTS.bitcell) + #if OPTS.tech_name == "sky130" and len(self.all_ports) == 1: + # cell_mod = factory.create(module_type=OPTS.bitcell, version="opt1") + #else: + cell_mod = factory.create(module_type=OPTS.bitcell) cell_bl = cell_mod.get_bl_name(port) cell_br = cell_mod.get_br_name(port) diff --git a/compiler/globals.py b/compiler/globals.py index 65bf8567..f64956dc 100644 --- a/compiler/globals.py +++ b/compiler/globals.py @@ -67,7 +67,7 @@ def parse_args(): dest="num_sim_threads"), optparse.make_option("-v", "--verbose", action="count", - dest="verbose_level", + dest="5", help="Increase the verbosity level"), optparse.make_option("-t", "--tech", dest="tech_name", diff --git a/compiler/modules/bitcell_base_array.py b/compiler/modules/bitcell_base_array.py index c92857ee..7c42558f 100644 --- a/compiler/modules/bitcell_base_array.py +++ b/compiler/modules/bitcell_base_array.py @@ -158,10 +158,35 @@ class bitcell_base_array(design): height=wl_pin.height()) def route_supplies(self): + + vdd_found = False + gnd_found = False + for inst in self.insts: - for pin_name in ["vdd", "gnd"]: - if pin_name in inst.mod.get_pin_names(): - self.copy_layout_pin(inst, pin_name) + if 'vdd' in inst.mod.get_pin_names(): + vdd_found = True + if 'gnd' in inst.mod.get_pin_names(): + gnd_found = True + + power_name = 'vdd' + ground_name = 'gnd' + if vdd_found is False or gnd_found is False: + from openram.tech import cell_properties + try: + power_name = cell_properties.power_name + except: + pass + try: + ground_name = cell_properties.ground_name + except: + pass + + + for inst in self.insts: + if power_name in inst.mod.get_pin_names(): + self.copy_layout_pin(inst, power_name, new_name='vdd') + if ground_name in inst.mod.get_pin_names(): + self.copy_layout_pin(inst, ground_name , new_name='gnd') def add_layout_pins(self): """ Add the layout pins """ diff --git a/compiler/modules/capped_replica_bitcell_array.py b/compiler/modules/capped_replica_bitcell_array.py index 8832bc2f..f2289663 100644 --- a/compiler/modules/capped_replica_bitcell_array.py +++ b/compiler/modules/capped_replica_bitcell_array.py @@ -107,6 +107,7 @@ class capped_replica_bitcell_array(bitcell_base_array): self.row_cap_left = factory.create(module_type=row_cap_module_type, cols=1, column_offset=0, + row_offset=len(self.left_rbl)+len(self.right_rbl), rows=self.row_size + self.extra_rows, location="left") @@ -117,6 +118,7 @@ class capped_replica_bitcell_array(bitcell_base_array): # + bitcell columns # + right replica column(s) column_offset=len(self.left_rbl) + self.column_size + self.rbl[0], + row_offset=len(self.left_rbl)+len(self.right_rbl), rows=self.row_size + self.extra_rows, location="right") @@ -181,7 +183,7 @@ class capped_replica_bitcell_array(bitcell_base_array): # Top/bottom dummy rows or col caps self.dummy_row_insts = [] self.dummy_row_insts.append(self.add_inst(name="dummy_row_bot", - mod=self.col_cap_bottom)) + mod=self.col_cap_bottom,)) self.connect_inst(self.bitline_pin_list + ["gnd"] * len(self.col_cap_bottom.get_wordline_names()) + self.supplies) self.dummy_row_insts.append(self.add_inst(name="dummy_row_top", mod=self.col_cap_top)) @@ -217,7 +219,7 @@ class capped_replica_bitcell_array(bitcell_base_array): self.capped_rba_height = self.dummy_col_insts[0].height - #self.route_power_ring(self.supply_stack[2], self.supply_stack[0]) + self.route_power_ring(self.supply_stack[2], self.supply_stack[0]) self.route_supplies() self.route_unused_wordlines() @@ -289,6 +291,7 @@ class capped_replica_bitcell_array(bitcell_base_array): self.dummy_col_insts[1].place(offset=offset) def add_layout_pins(self): + for pin_name in self.used_wordline_names + self.bitline_pin_list: pin = self.replica_bitcell_array_inst.get_pin(pin_name) @@ -308,6 +311,7 @@ class capped_replica_bitcell_array(bitcell_base_array): offset=pin_offset, width=pin_width, height=pin_height) + def route_supplies(self): @@ -322,8 +326,8 @@ class capped_replica_bitcell_array(bitcell_base_array): if top: inst = self.dummy_row_insts[1] - if "vdd" in inst.mod.pins: - array_pins = inst.get_pins("vdd") + if 'vdd' in inst.mod.pins: + array_pins = inst.get_pins('vdd') for array_pin in array_pins: supply_pin = self.top_vdd_pin self.add_path(array_pin.layer, [array_pin.center(), vector(array_pin.center()[0], supply_pin.center()[1])]) @@ -331,7 +335,7 @@ class capped_replica_bitcell_array(bitcell_base_array): to_layer = supply_pin.layer, offset = vector(array_pin.center()[0], supply_pin.center()[1])) - array_pins = inst.get_pins("gnd") + array_pins = inst.get_pins('gnd') for array_pin in array_pins: supply_pin = self.top_gnd_pin self.add_path(array_pin.layer, [array_pin.center(), vector(array_pin.center()[0], supply_pin.center()[1])]) @@ -340,8 +344,8 @@ class capped_replica_bitcell_array(bitcell_base_array): offset = vector(array_pin.center()[0], supply_pin.center()[1])) if bottom: inst = self.dummy_row_insts[0] - if "vdd" in inst.mod.pins: - array_pins = inst.get_pins("vdd") + if 'vdd' in inst.mod.pins: + array_pins = inst.get_pins('vdd') for array_pin in array_pins: supply_pin = self.bottom_vdd_pin self.add_path(array_pin.layer, [array_pin.center(), vector(array_pin.center()[0], supply_pin.center()[1])]) @@ -349,7 +353,7 @@ class capped_replica_bitcell_array(bitcell_base_array): to_layer = supply_pin.layer, offset = vector(array_pin.center()[0], supply_pin.center()[1])) - array_pins = inst.get_pins("gnd") + array_pins = inst.get_pins('gnd') for array_pin in array_pins: supply_pin = self.bottom_gnd_pin self.add_path(array_pin.layer, [array_pin.center(), vector(array_pin.center()[0], supply_pin.center()[1])]) @@ -358,8 +362,8 @@ class capped_replica_bitcell_array(bitcell_base_array): offset = vector(array_pin.center()[0], supply_pin.center()[1])) if left: inst = self.dummy_col_insts[0] - if "vdd" in inst.mod.pins: - array_pins = inst.get_pins("vdd") + if 'vnd' in inst.mod.pins: + array_pins = inst.get_pins('vnd') for array_pin in array_pins: supply_pin = self.left_vdd_pin self.add_path(array_pin.layer, [array_pin.center(), vector(supply_pin.center()[0], array_pin.center()[1])]) @@ -367,7 +371,7 @@ class capped_replica_bitcell_array(bitcell_base_array): to_layer = supply_pin.layer, offset = vector(supply_pin.center()[0], array_pin.center()[1])) - array_pins = inst.get_pins("gnd") + array_pins = inst.get_pins('gnd') for array_pin in array_pins: supply_pin = self.left_gnd_pin self.add_path(array_pin.layer, [array_pin.center(), vector(supply_pin.center()[0], array_pin.center()[1])]) @@ -376,8 +380,8 @@ class capped_replica_bitcell_array(bitcell_base_array): offset = vector(supply_pin.center()[0], array_pin.center()[1])) if right: inst = self.dummy_col_insts[1] - if "vdd" in inst.mod.pins: - array_pins = inst.get_pins("vdd") + if 'vdd' in inst.mod.pins: + array_pins = inst.get_pins('vdd') for array_pin in array_pins: supply_pin = self.right_vdd_pin self.add_path(array_pin.layer, [array_pin.center(), vector(supply_pin.center()[0], array_pin.center()[1])]) @@ -385,29 +389,30 @@ class capped_replica_bitcell_array(bitcell_base_array): to_layer = supply_pin.layer, offset = vector(supply_pin.center()[0], array_pin.center()[1])) - array_pins = inst.get_pins("gnd") + array_pins = inst.get_pins('gnd') for array_pin in array_pins: supply_pin = self.right_gnd_pin self.add_path(array_pin.layer, [array_pin.center(), vector(supply_pin.center()[0], array_pin.center()[1])]) self.add_via_stack_center(from_layer = array_pin.layer, to_layer = supply_pin.layer, - offset = vector(supply_pin.center()[0], array_pin.center()[1])) + offset = vector(supply_pin.center()[0], array_pin.center()[1])) + def route_unused_wordlines(self): """ Connect the unused RBL and dummy wordlines to gnd """ # This grounds all the dummy row word lines for inst in self.dummy_row_insts: - for wl_name in self.col_cap_top.get_wordline_names(): + for wl_name in inst.mod.get_wordline_names(): pin = inst.get_pin(wl_name) - self.connect_side_pin(pin, "left", self.left_gnd_locs[0].x) - self.connect_side_pin(pin, "right", self.right_gnd_locs[0].x) + self.connect_side_pin(pin, "left", self.left_gnd_pin.cx()) + self.connect_side_pin(pin, "right", self.right_gnd_pin.cx()) # Ground the unused replica wordlines for wl_name in self.unused_wordline_names: pin = self.replica_bitcell_array_inst.get_pin(wl_name) - self.connect_side_pin(pin, "left", self.left_gnd_locs[0].x) - self.connect_side_pin(pin, "right", self.right_gnd_locs[0].x) + self.connect_side_pin(pin, "left", self.left_gnd_pin.cx()) + self.connect_side_pin(pin, "right", self.right_gnd_pin.cx()) def route_side_pin(self, name, side, offset_multiple=1): """ diff --git a/compiler/modules/col_cap_array.py b/compiler/modules/col_cap_array.py index bf0198fc..510f7b0c 100644 --- a/compiler/modules/col_cap_array.py +++ b/compiler/modules/col_cap_array.py @@ -6,7 +6,8 @@ from openram.sram_factory import factory from openram import OPTS from .bitcell_base_array import bitcell_base_array - +from openram.base import geometry +from .pattern import pattern class col_cap_array(bitcell_base_array): """ diff --git a/compiler/modules/dummy_array.py b/compiler/modules/dummy_array.py index e9d652ee..5317c187 100644 --- a/compiler/modules/dummy_array.py +++ b/compiler/modules/dummy_array.py @@ -14,7 +14,7 @@ class dummy_array(bitcell_base_array): Generate a dummy row/column for the replica array. """ - def __init__(self, rows, cols, column_offset=0, row_offset=0 ,mirror=0, location="", name=""): + def __init__(self, rows, cols, column_offset=0, row_offset=0 ,mirror=0, location="", name="", left_rbl=0, right_rbl=0): super().__init__(rows=rows, cols=cols, column_offset=column_offset, name=name) self.location = location self.row_offset = row_offset @@ -57,14 +57,14 @@ class dummy_array(bitcell_base_array): self.cell_inst={} if self.cell.mirror.y: core_block = [[0 for x in range(2)] for y in range(2)] - core_block[(0+self.mirror) %2][0] = geometry.instance("core_0_0", mod=self.dummy_cell, is_bitcell=True) - core_block[(1+self.mirror) %2][0] = geometry.instance("core_1_0", mod=self.dummy_cell, is_bitcell=True, mirror='MX') - core_block[(0+self.mirror) %2][1] = geometry.instance("core_0_1", mod=self.dummy_cell, is_bitcell=True, mirror='MY') - core_block[(1+self.mirror) %2][1] = geometry.instance("core_1_1", mod=self.dummy_cell, is_bitcell=True, mirror='XY') + core_block[(0+self.mirror) %2][(1+self.column_offset+self.row_offset) %2] = geometry.instance("core_0_0", mod=self.dummy_cell, is_bitcell=True, mirror='MX') + core_block[(1+self.mirror) %2][(1+self.column_offset+self.row_offset) %2] = geometry.instance("core_1_0", mod=self.dummy_cell, is_bitcell=True) + core_block[(0+self.mirror) %2][(0+self.column_offset+self.row_offset) %2] = geometry.instance("core_0_1", mod=self.dummy_cell, is_bitcell=True, mirror='XY') + core_block[(1+self.mirror) %2][(0+self.column_offset+self.row_offset) %2] = geometry.instance("core_1_1", mod=self.dummy_cell, is_bitcell=True, mirror='MY') else: core_block = [[0 for x in range(1)] for y in range(2)] - core_block[(0+self.mirror) %2][0] = geometry.instance("core_0_0", mod=self.dummy_cell, is_bitcell=True) - core_block[(1+self.mirror) %2][0] = geometry.instance("core_1_0", mod=self.dummy_cell, is_bitcell=True, mirror='MX') + core_block[(0+self.mirror) %2][(1+self.column_offset) %2] = geometry.instance("core_0_0", mod=self.dummy_cell, is_bitcell=True, mirror='MX') + core_block[(1+self.mirror) %2][(1+self.column_offset) %2] = geometry.instance("core_1_0", mod=self.dummy_cell, is_bitcell=True) self.pattern = pattern(self, "dummy_array", core_block, num_rows=self.row_size, num_cols=self.column_size, name_template="bit_r{0}_c{1}") diff --git a/compiler/modules/pattern.py b/compiler/modules/pattern.py index df9ddfb8..798ef331 100644 --- a/compiler/modules/pattern.py +++ b/compiler/modules/pattern.py @@ -187,7 +187,7 @@ class pattern(): inst.place((x, y), inst.mirror, inst.rotate) def place_array(self): - + (self.row_max, self.col_max) = list(self.parent_design.all_inst.keys())[-1] y = 0 for row in range(self.row_max+1): diff --git a/compiler/modules/replica_column.py b/compiler/modules/replica_column.py index 6521fe5b..433ac2ec 100644 --- a/compiler/modules/replica_column.py +++ b/compiler/modules/replica_column.py @@ -95,17 +95,18 @@ class replica_column(bitcell_base_array): # 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: core_block[row][0] = geometry.instance("rbc_{}".format(row), mod=self.replica_cell, is_bitcell=True) 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 == 1: 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: for row in range(self.total_size): if self.column_offset % 2 == 0: diff --git a/compiler/sram_config.py b/compiler/sram_config.py index 369ae3d0..bdd6b245 100644 --- a/compiler/sram_config.py +++ b/compiler/sram_config.py @@ -141,12 +141,12 @@ class sram_config: + " Bank addr size: {}".format(self.bank_addr_size)) num_ports = OPTS.num_rw_ports + OPTS.num_r_ports + OPTS.num_w_ports - if num_ports == 1: - if ((self.num_cols + num_ports + self.num_spare_cols) % self.array_col_multiple != 0): - debug.error("Invalid number of cols including rbl(s): {}. Total cols must be divisible by {}".format(self.num_cols + num_ports + self.num_spare_cols, self.array_col_multiple), -1) - - if ((self.num_rows + num_ports) % self.array_row_multiple != 0): - debug.error("invalid number of rows including dummy row(s): {}. Total cols must be divisible by {}".format(self.num_rows + num_ports, self.array_row_multiple), -1) + #if num_ports == 1: + # if ((self.num_cols + num_ports + self.num_spare_cols) % self.array_col_multiple != 0): + # debug.error("Invalid number of cols including rbl(s): {}. Total cols must be divisible by {}".format(self.num_cols + num_ports + self.num_spare_cols, self.array_col_multiple), -1)# + # + # if ((self.num_rows + num_ports) % self.array_row_multiple != 0): + # debug.error("invalid number of rows including dummy row(s): {}. Total cols must be divisible by {}".format(self.num_rows + num_ports, self.array_row_multiple), -1) def estimate_words_per_row(self, tentative_num_cols, word_size): """ diff --git a/compiler/tests/05_bitcell_array_test.py b/compiler/tests/05_bitcell_array_test.py index bd5d5f01..7a6d3aad 100755 --- a/compiler/tests/05_bitcell_array_test.py +++ b/compiler/tests/05_bitcell_array_test.py @@ -31,7 +31,7 @@ class array_test(openram_test): num_spare_rows = 0 num_spare_cols = 0 - a = factory.create(module_type="bitcell_array", cols=8 + num_spare_cols, rows=8 + num_spare_rows) + a = factory.create(module_type="bitcell_array", cols=2 + num_spare_cols, rows=2 + num_spare_rows) self.local_check(a) openram.end_openram() 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 2a648b89..dad854ed 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/14_replica_bitcell_array_leftrbl_1rw_test.py b/compiler/tests/14_replica_bitcell_array_leftrbl_1rw_test.py index f910c50f..6c1b712c 100755 --- a/compiler/tests/14_replica_bitcell_array_leftrbl_1rw_test.py +++ b/compiler/tests/14_replica_bitcell_array_leftrbl_1rw_test.py @@ -26,7 +26,7 @@ class replica_bitcell_array_leftrbl_1rw_test(openram_test): openram.setup_bitcell() debug.info(2, "Testing 7x5 replica array for 1rw cell with left replica column") - a = factory.create(module_type="replica_bitcell_array", cols=7, rows=5, rbl=[1, 0], left_rbl=[0]) + a = factory.create(module_type="replica_bitcell_array", cols=8, rows=8, rbl=[1, 0], left_rbl=[0]) self.local_check(a) openram.end_openram() diff --git a/compiler/tests/19_single_bank_2mux_test.py b/compiler/tests/19_single_bank_2mux_test.py index 451a253e..6683c9e8 100755 --- a/compiler/tests/19_single_bank_2mux_test.py +++ b/compiler/tests/19_single_bank_2mux_test.py @@ -24,7 +24,9 @@ class single_bank_test(openram_test): from openram import sram_config c = sram_config(word_size=4, - num_words=16) + num_words=16, + num_spare_cols=1, + num_spare_rows=1) c.num_words=32 c.words_per_row=2 diff --git a/install_conda.sh b/install_conda.sh index 6aadd393..d646d624 100755 --- a/install_conda.sh +++ b/install_conda.sh @@ -1,4 +1,7 @@ #!/bin/bash +#CONDA_INSTALLER_URL="https://repo.anaconda.com/miniconda/Miniconda3-py313_25.11.1-1-Linux-x86_64.sh" +#CONDA_INSTALLER_FILE="miniconda_installer_py313.sh" + CONDA_INSTALLER_URL="https://repo.anaconda.com/miniconda/Miniconda3-py38_23.11.0-2-Linux-x86_64.sh" CONDA_INSTALLER_FILE="miniconda_installer_py38.sh" CONDA_HOME="${CONDA_HOME:-miniconda}" @@ -6,12 +9,12 @@ CONDA_HOME="${CONDA_HOME:-miniconda}" # The tool name format is "=". # If you want to use the latest version, just use "". TOOLS="" -TOOLS+="klayout=0.28.3 " -TOOLS+="magic=8.3.497 " +#TOOLS+="klayout=0.28.3 " +TOOLS+="magic=8.3.587 " TOOLS+="netgen=1.5.286 " TOOLS+="ngspice=26 " TOOLS+="trilinos=12.12.1=1 " -TOOLS+="xyce=7.4=3" +TOOLS+="xyce=7.4" # Install miniconda if not already installed if [[ ! -d "${CONDA_HOME}/bin" ]] @@ -24,16 +27,16 @@ then # Prioritize channels to prevent version conflicts conda config --add channels conda-forge conda config --add channels vlsida-eda - - # Install iverilog from conda-eda - conda install -q -y -c litex-hub iverilog - + + #conda install -q -y -c conda-forge trilinos # Install rest of the tools from vlsida-eda for tool in ${TOOLS} do conda install -q -y -c vlsida-eda ${tool} done + # Install iverilog from conda-eda + conda install -q -y -c litex-hub iverilog # Install required Python packages # (This step isn't required but used to prevent possible issues) python3 -m pip install -r requirements.txt --ignore-installed diff --git a/macros/sram_configs/sky130_sram_1rw_tiny.py b/macros/sram_configs/sky130_sram_1rw_tiny.py index 85aa34f4..c4f7ac31 100644 --- a/macros/sram_configs/sky130_sram_1rw_tiny.py +++ b/macros/sram_configs/sky130_sram_1rw_tiny.py @@ -4,12 +4,13 @@ Dual port (1 read/write + 1 read only) 1 kbytes SRAM with byte write. FIXME: What is this useful for? FIXME: Why would you want byte write on this? """ -word_size = 8 # Bits +word_size = 16 # Bits num_words = 16 human_byte_size = "{:.0f}kbytes".format((word_size * num_words)/1024/8) # Allow byte writes -write_size = 2 # Bits +write_size = 8 # Bits +words_per_row = 1 # Dual port num_rw_ports = 1 @@ -17,8 +18,11 @@ num_r_ports = 0 num_w_ports = 0 ports_human = '1rw' -num_spare_cols = 1 -num_spare_rows = 1 +#num_spare_cols = 1 +#num_spare_rows = 1 +netlist_only = True +num_sim_threads = 1 +#analytical_delay = False import os exec(open(os.path.join(os.path.dirname(__file__), 'sky130_sram_common.py')).read()) diff --git a/technology/sky130/custom/sky130_col_cap.py b/technology/sky130/custom/sky130_col_cap.py index c03f35c3..3bedfe19 100644 --- a/technology/sky130/custom/sky130_col_cap.py +++ b/technology/sky130/custom/sky130_col_cap.py @@ -15,19 +15,11 @@ class sky130_col_cap(design): def __init__(self, version, name="",left_rbl=[],right_rbl=[]): if version == "colend": - if OPTS.control_logic == "control_logic_delay" or not right_rbl: - cell_name = "sky130_fd_bd_sram__sram_sp_colend" - else: - cell_name = "sky130_fd_bd_sram__openram_sp_colend_replica" + cell_name = "sky130_fd_bd_sram__sram_sp_colend" prop = props.col_cap_1port_bitcell - elif version == "colenda": - if OPTS.control_logic == "control_logic_delay" or not left_rbl: - cell_name = "sky130_fd_bd_sram__sram_sp_colenda" - else: - cell_name = "sky130_fd_bd_sram__openram_sp_colenda_replica" + cell_name = "sky130_fd_bd_sram__sram_sp_colenda" prop = props.col_cap_1port_bitcell - elif version == "colend_p_cent": cell_name = "sky130_fd_bd_sram__sram_sp_colend_p_cent" prop = props.col_cap_1port_strap_ground @@ -41,5 +33,5 @@ class sky130_col_cap(design): cell_name = "sky130_fd_bd_sram__sram_sp_colenda_cent" prop = props.col_cap_1port_strap_power else: - debug.error("Invalid type for col_end", -1) + debug.error("Invalid type for col_end: {}".format(version), -1) super().__init__(name=name, cell_name=cell_name, prop=prop) diff --git a/technology/sky130/custom/sky130_row_cap_array.py b/technology/sky130/custom/sky130_row_cap_array.py index 7031e388..92d97201 100644 --- a/technology/sky130/custom/sky130_row_cap_array.py +++ b/technology/sky130/custom/sky130_row_cap_array.py @@ -17,7 +17,7 @@ class sky130_row_cap_array(row_cap_array, sky130_bitcell_base_array): """ Generate a dummy row/column for the replica array. """ - def __init__(self, rows, cols, column_offset=0, mirror=0, location="", name=""): + def __init__(self, rows, cols, column_offset=0, row_offset=0, mirror=0, location="", name=""): super().__init__(rows, cols, column_offset=column_offset, location=location, name=name) self.mirror = mirror self.location = location diff --git a/technology/sky130/tech/tech.py b/technology/sky130/tech/tech.py index 40e12903..2a29a88d 100755 --- a/technology/sky130/tech/tech.py +++ b/technology/sky130/tech/tech.py @@ -24,6 +24,7 @@ File containing the process technology parameters for Skywater 130nm. # For example: tech_modules["contact"] = "contact_freepdk45" tech_modules = d.module_type() + # These modules have been hand designed and provided in this repository. tech_modules["nand2_dec"] = "nand2_dec" tech_modules["nand3_dec"] = "nand3_dec" @@ -33,23 +34,24 @@ tech_modules["nand4_dec"] = "nand4_dec" # These are for single port and dual port as a list, # or for both if there is no list, # or only applicable to one if there is no list. -tech_modules["bitcell_1port"] = "sky130_bitcell" -tech_modules["replica_bitcell_1port"] = "sky130_replica_bitcell" -tech_modules["dummy_bitcell_1port"] = "sky130_dummy_bitcell" + +#tech_modules["bitcell_1port"] = "sky130_bitcell" +#tech_modules["replica_bitcell_1port"] = "sky130_replica_bitcell" +#tech_modules["dummy_bitcell_1port"] = "sky130_dummy_bitcell" tech_modules["replica_bitcell_2port"] = "replica_bitcell_2port" tech_modules["dummy_bitcell_2port"] = "dummy_bitcell_2port" tech_modules["bitcell_2port"] = "bitcell_2port" -tech_modules["bitcell_array"] = ["sky130_bitcell_array", "bitcell_array"] -tech_modules["replica_bitcell_array"] = ["sky130_replica_bitcell_array", "replica_bitcell_array"] -tech_modules["capped_replica_bitcell_array"] = ["sky130_capped_replica_bitcell_array", "capped_replica_bitcell_array"] -tech_modules["dummy_array"] = ["sky130_dummy_array", "dummy_array"] +tech_modules["bitcell_array"] = ["bitcell_array", "bitcell_array"] +tech_modules["replica_bitcell_array"] = ["replica_bitcell_array", "replica_bitcell_array"] +tech_modules["capped_replica_bitcell_array"] = ["capped_replica_bitcell_array", "capped_replica_bitcell_array"] +tech_modules["dummy_array"] = ["dummy_array", "dummy_array"] -tech_modules["replica_column"] = ["sky130_replica_column", "replica_column"] +tech_modules["replica_column"] = ["replica_column", "replica_column"] -tech_modules["col_cap_array"] = ["sky130_col_cap_array", "col_cap_array"] -tech_modules["col_cap"] = ["sky130_col_cap", "col_cap_bitcell_2port"] +tech_modules["col_cap_array"] = ["col_cap_array", "col_cap_array"] +tech_modules["col_cap"] = ["col_cap_bitcell_1port", "col_cap_bitcell_2port"] tech_modules["corner"] = ["sky130_corner", None] tech_modules["internal"] = ["sky130_internal", None] tech_modules["row_cap_array"] = ["sky130_row_cap_array", "row_cap_array"] @@ -68,28 +70,32 @@ tech_modules["and4_dec"] = "and4_dec" ################################################### cell_properties = d.cell_properties() -cell_properties.bitcell_power_pin_directions = ("H", "H") +cell_properties.power_name = 'VPWR' +cell_properties.ground_name = 'VGND' + +cell_properties.bitcell_power_pin_directions = ("V", "V") cell_properties.bitcell_1port.mirror.x = True cell_properties.bitcell_1port.mirror.y = True -cell_properties.bitcell_1port.end_caps = True -cell_properties.bitcell_1port.boundary_layer = "mem" -cell_properties.bitcell_1port.port_order = ['bl', 'br', 'gnd', 'vdd', 'vpb', 'vnb', 'wl'] -cell_properties.bitcell_1port.port_types = ["OUTPUT", "OUTPUT", "GROUND", "POWER", "BIAS", "BIAS", "INPUT"] +cell_properties.bitcell_1port.end_caps = False +cell_properties.bitcell_1port.boundary_layer = "boundary" +cell_properties.bitcell_1port.port_order = ['bl', 'br', 'wl', 'vdd', 'gnd'] +cell_properties.bitcell_1port.port_types = ["INPUT", "INPUT", "GROUND", "POWER", "OUTPUT"] cell_properties.bitcell_1port.port_map = {'bl': 'BL', 'br': 'BR', - 'wl': 'WL', + 'gnd': 'VGND', 'vdd': 'VPWR', - 'vnb': 'VNB', - 'vpb': 'VPB', - 'gnd': 'VGND'} + 'wl': 'WL'} + + + cell_properties.bitcell_1port.wl_layer = "m2" cell_properties.bitcell_1port.bl_layer = "m1" cell_properties.bitcell_1port.vdd_layer = "m1" cell_properties.bitcell_1port.vdd_dir = "V" -cell_properties.bitcell_1port.gnd_layer = "m2" -cell_properties.bitcell_1port.gnd_dir = "H" +cell_properties.bitcell_1port.gnd_layer = "m1" +cell_properties.bitcell_1port.gnd_dir = "V" cell_properties.bitcell_2port.mirror.x = True cell_properties.bitcell_2port.mirror.y = True @@ -103,47 +109,45 @@ cell_properties.bitcell_2port.port_map = {'bl0': 'BL0', 'wl1': 'WL1', 'vdd': 'VDD', 'gnd': 'GND'} + cell_properties.bitcell_1port.wl_layer = "m2" -cell_properties.bitcell_1port.vdd_layer = "m2" -cell_properties.bitcell_1port.vdd_dir = "H" -cell_properties.bitcell_1port.gnd_layer = "m2" -cell_properties.bitcell_1port.gnd_dir = "H" +cell_properties.bitcell_1port.vdd_layer = "m1" +cell_properties.bitcell_1port.vdd_dir = "V" +cell_properties.bitcell_1port.gnd_layer = "m1" +cell_properties.bitcell_1port.gnd_dir = "V" cell_properties.bitcell_2port.wl_layer = "m2" cell_properties.bitcell_2port.vdd_layer = "m1" cell_properties.bitcell_2port.vdd_dir = "H" cell_properties.bitcell_2port.gnd_layer = "m2" cell_properties.bitcell_2port.gnd_dir = "H" -cell_properties.col_cap_1port_bitcell = d.cell(['bl', 'br', 'vdd', 'gnd', 'vpb', 'vnb', 'gate'], - ['INPUT', 'INPUT','POWER', 'GROUND', 'BIAS', 'BIAS', 'INPUT'], +cell_properties.col_cap_1port_bitcell = d.cell(['bl', 'br', 'vdd', 'gnd',], + ['INPUT', 'INPUT','POWER', 'GROUND', ], {'bl': 'bl', 'br': 'br', 'vdd': 'vdd', - 'gnd': 'gnd', - 'vnb': 'vnb', - 'vpb': 'vpb', - 'gate': 'gate'}) -cell_properties.col_cap_1port_bitcell.boundary_layer = "mem" + 'gnd': 'gnd',}) +cell_properties.col_cap_1port_bitcell.boundary_layer = "boundary" cell_properties.col_cap_1port_strap_power = d.cell(['vdd', 'vpb', 'vnb'], ['POWER', 'BIAS', 'BIAS'], {'vnb': 'VNB', 'vpb': 'VPB', 'vdd': 'VPWR'}) -cell_properties.col_cap_1port_strap_power.boundary_layer = "mem" +cell_properties.col_cap_1port_strap_power.boundary_layer = "boundary" cell_properties.col_cap_1port_strap_ground = d.cell(['gnd', 'vpb', 'vnb'], ['GROUND', 'BIAS', 'BIAS'], {'vnb': 'VNB', 'vpb': 'VPB', 'gnd': 'VGND'}) -cell_properties.col_cap_1port_strap_ground.boundary_layer = "mem" +cell_properties.col_cap_1port_strap_ground.boundary_layer = "boundary" cell_properties.row_cap_1port_cell = d.cell(['vdd', 'wl'], ['POWER', 'INPUT'], {'wl': 'WL', 'vdd': 'VPWR'}) -cell_properties.row_cap_1port_cell.boundary_layer = "mem" +cell_properties.row_cap_1port_cell.boundary_layer = "boundary" cell_properties.col_cap_2port.port_order = ['bl0', 'br0', 'bl1', 'br1', 'vdd'] cell_properties.col_cap_2port.port_map = {'bl0': 'BL0', @@ -163,7 +167,7 @@ cell_properties.ptx.model_is_subckt = True cell_properties.pgate.add_implants = True -cell_properties.use_strap = True +cell_properties.use_strap = False cell_properties.strap_module = "internal" cell_properties.strap_version = "wlstrap" @@ -219,9 +223,13 @@ cell_properties.write_driver.port_map = {'din': 'DIN', # If it is a list, the first is single port and the second is dual port. # If it is string, it is used for both single and dual port. cell_properties.names["dff"] = "sky130_fd_bd_sram__openram_dff" -cell_properties.names["nand2_dec"] = ["sky130_fd_bd_sram__openram_sp_nand2_dec", "sky130_fd_bd_sram__openram_dp_nand2_dec"] -cell_properties.names["nand3_dec"] = ["sky130_fd_bd_sram__openram_sp_nand3_dec", "sky130_fd_bd_sram__openram_dp_nand3_dec"] -cell_properties.names["nand4_dec"] = ["sky130_fd_bd_sram__openram_sp_nand4_dec", "sky130_fd_bd_sram__openram_dp_nand4_dec"] +cell_properties.names["nand2_dec"] = ["sky130_fd_bd_sram__openram_dp_nand2_dec", "sky130_fd_bd_sram__openram_dp_nand2_dec"] +cell_properties.names["nand3_dec"] = ["sky130_fd_bd_sram__openram_dp_nand3_dec", "sky130_fd_bd_sram__openram_dp_nand3_dec"] +cell_properties.names["nand4_dec"] = ["sky130_fd_bd_sram__openram_dp_nand4_dec", "sky130_fd_bd_sram__openram_dp_nand4_dec"] + +cell_properties.names["bitcell_1port"] = "sky130_custom_cell" +cell_properties.names["replica_bitcell_1port"] = "sky130_custom_replica" +cell_properties.names["dummy_bitcell_1port"] = "sky130_custom_dummy" cell_properties.names["bitcell_2port"] = "sky130_fd_bd_sram__openram_dp_cell" cell_properties.names["dummy_bitcell_2port"] = "sky130_fd_bd_sram__openram_dp_cell_dummy" @@ -253,7 +261,7 @@ layer_properties.hierarchical_predecode.input_layer = "li" layer_properties.hierarchical_predecode.output_layer = "m2" layer_properties.hierarchical_predecode.vertical_supply = True layer_properties.hierarchical_predecode.force_horizontal_input_contact = True - + layer_properties.bank.stack = "m2_stack" layer_properties.bank.pitch = "m3_pitch" @@ -265,7 +273,7 @@ layer_properties.port_address.supply_offset = True layer_properties.port_data.enable_layer = "m1" layer_properties.port_data.channel_route_bitlines = False -layer_properties.replica_column.even_rows = True +layer_properties.replica_column.even_rows = False layer_properties.wordline_driver.vertical_supply = True