From dd2effd28d8bfebc0a9c3ed3adb9a01b0cba28cc Mon Sep 17 00:00:00 2001 From: mrg Date: Wed, 16 Feb 2022 10:54:39 -0800 Subject: [PATCH 001/130] Initial work on separate delay and func simulation --- compiler/base/design.py | 1 - compiler/gen_stimulus.py | 40 +++++++++----------- compiler/openram.py | 11 +++--- compiler/sram/sram.py | 72 +++++++++++++++++++----------------- compiler/sram/sram_base.py | 14 ++----- compiler/sram/sram_config.py | 53 +++++++++++++++++++++++++- 6 files changed, 116 insertions(+), 75 deletions(-) diff --git a/compiler/base/design.py b/compiler/base/design.py index 70a9047b..12fd6c56 100644 --- a/compiler/base/design.py +++ b/compiler/base/design.py @@ -318,4 +318,3 @@ class design(hierarchy_design): design.setup_drc_constants() design.setup_layer_constants() - diff --git a/compiler/gen_stimulus.py b/compiler/gen_stimulus.py index 69e53cd8..d69d867d 100755 --- a/compiler/gen_stimulus.py +++ b/compiler/gen_stimulus.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # See LICENSE for licensing information. # # Copyright (c) 2016-2021 Regents of the University of California and The Board @@ -15,6 +15,7 @@ corner, but should probably be extended. import sys from globals import * +from importlib import reload (OPTS, args) = parse_args() @@ -41,36 +42,30 @@ slew = float(args[3]) import debug init_openram(config_file=config_file, is_unit_test=False) + +from sram_config import sram_config +c = sram_config(word_size=OPTS.word_size, + num_words=OPTS.num_words, + write_size=OPTS.write_size, + num_banks=OPTS.num_banks, + words_per_row=OPTS.words_per_row, + num_spare_rows=OPTS.num_spare_rows, + num_spare_cols=OPTS.num_spare_cols) + +OPTS.netlist_only = True OPTS.check_lvsdrc = False # Put the temp output in the output path since it is what we want to generate! old_openram_temp = OPTS.openram_temp OPTS.openram_temp = OPTS.output_path - - -import sram -class fake_sram(sram.sram): - """ This is an SRAM that doesn't actually create itself, just computes - the sizes. """ - def __init__(self, word_size, num_words, num_banks, name, num_spare_rows): - self.name = name - self.word_size = word_size - self.num_words = num_words - self.num_banks = num_banks - self.num_spare_rows = num_spare_rows - c = reload(__import__(OPTS.bitcell)) - self.mod_bitcell = getattr(c, OPTS.bitcell) - self.bitcell = self.mod_bitcell() - # to get the row, col, etc. - self.compute_sizes() - -sram = fake_sram(OPTS.word_size, OPTS.num_words, OPTS.num_banks, OPTS.output_name) -sp_file = OPTS.output_path+OPTS.output_name + ".sp" +from sram import sram +s = sram(name=OPTS.output_name, sram_config=c) +s.create() from characterizer import delay import tech # Set up the delay and set to the nominal corner -d = delay.delay(sram, sp_file, ("TT", tech.spice["nom_supply_voltage"], tech.spice["nom_temperature"])) +d = delay(s, s.get_sp_name(), ("TT", tech.spice["nom_supply_voltage"], tech.spice["nom_temperature"])) # Set the period d.period = period # Set the load of outputs and slew of inputs @@ -91,4 +86,3 @@ print("Output files are:\n{0}stim.sp\n{0}sram.sp\n{0}reduced.sp".format(OPTS.out OPTS.openram_temp = old_openram_temp # Delete temp files, remove the dir, etc. end_openram() - diff --git a/compiler/openram.py b/compiler/openram.py index 089c0f3a..74f80128 100755 --- a/compiler/openram.py +++ b/compiler/openram.py @@ -48,7 +48,7 @@ g.print_time("Start", start_time) g.report_status() from sram_config import sram_config - +from sram import sram # Configure the SRAM organization c = sram_config(word_size=OPTS.word_size, @@ -73,9 +73,10 @@ for path in output_files: debug.print_raw(path) -from sram import sram -s = sram(sram_config=c, - name=OPTS.output_name) +s = sram(name=OPTS.output_name, sram_config=c) + +# Actually build the SRAM +s.create() # Output the files for the resulting SRAM s.save() @@ -83,5 +84,3 @@ s.save() # Delete temp files etc. g.end_openram() g.print_time("End", datetime.datetime.now(), start_time) - - diff --git a/compiler/sram/sram.py b/compiler/sram/sram.py index 90855d8e..afd57f48 100644 --- a/compiler/sram/sram.py +++ b/compiler/sram/sram.py @@ -21,30 +21,39 @@ class sram(): results. We can later add visualizer and other high-level functions as needed. """ - def __init__(self, sram_config, name): + def __init__(self, name, sram_config): + self.name = name + self.config = sram_config sram_config.set_local_config(self) + self.sp_name = OPTS.output_path + self.name + ".sp" + self.lvs_name = OPTS.output_path + self.name + ".lvs.sp" + self.pex_name = OPTS.output_path + self.name + ".pex.sp" + self.gds_name = OPTS.output_path + self.name + ".gds" + self.lef_name = OPTS.output_path + self.name + ".lef" + self.v_name = OPTS.output_path + self.name + ".v" + # reset the static duplicate name checker for unit tests # in case we create more than one SRAM from design import design design.name_map=[] + def create(self): debug.info(2, "create sram of size {0} with {1} num of words {2} banks".format(self.word_size, self.num_words, self.num_banks)) start_time = datetime.datetime.now() - self.name = name - if self.num_banks == 1: - from sram_1bank import sram_1bank as sram + from sram_1bank import sram_1bank as sram_banked elif self.num_banks == 2: - from sram_2bank import sram_2bank as sram + from sram_2bank import sram_2bank as sram_banked else: debug.error("Invalid number of banks.", -1) - self.s = sram(name, sram_config) + self.s = sram_banked(name=self.name, + sram_config=self.config) self.s.create_netlist() if not OPTS.netlist_only: self.s.create_layout() @@ -52,6 +61,14 @@ class sram(): if not OPTS.is_unit_test: print_time("SRAM creation", datetime.datetime.now(), start_time) + def get_sp_name(self): + if OPTS.use_pex: + # Use the extracted spice file + return self.pex_name + else: + # Use generated spice file for characterization + return self.sp_name + def sp_write(self, name, lvs=False, trim=False): self.s.sp_write(name, lvs, trim) @@ -101,11 +118,10 @@ class sram(): # Save the spice file start_time = datetime.datetime.now() - spname = OPTS.output_path + self.s.name + ".sp" - debug.print_raw("SP: Writing to {0}".format(spname)) - self.sp_write(spname) + debug.print_raw("SP: Writing to {0}".format(self.sp_name)) + self.sp_write(self.sp_name) functional(self.s, - os.path.basename(spname), + os.path.basename(self.sp_name), cycles=200, output_path=OPTS.output_path) print_time("Spice writing", datetime.datetime.now(), start_time) @@ -113,12 +129,11 @@ class sram(): if not OPTS.netlist_only: # Write the layout start_time = datetime.datetime.now() - gdsname = OPTS.output_path + self.s.name + ".gds" - debug.print_raw("GDS: Writing to {0}".format(gdsname)) - self.gds_write(gdsname) + debug.print_raw("GDS: Writing to {0}".format(self.gds_name)) + self.gds_write(self.gds_name) if OPTS.check_lvsdrc: verify.write_drc_script(cell_name=self.s.name, - gds_name=os.path.basename(gdsname), + gds_name=os.path.basename(self.gds_name), extract=True, final_verification=True, output_path=OPTS.output_path) @@ -126,20 +141,18 @@ class sram(): # Create a LEF physical model start_time = datetime.datetime.now() - lefname = OPTS.output_path + self.s.name + ".lef" - debug.print_raw("LEF: Writing to {0}".format(lefname)) - self.lef_write(lefname) + debug.print_raw("LEF: Writing to {0}".format(self.lef_name)) + self.lef_write(self.lef_name) print_time("LEF", datetime.datetime.now(), start_time) # Save the LVS file start_time = datetime.datetime.now() - lvsname = OPTS.output_path + self.s.name + ".lvs.sp" - debug.print_raw("LVS: Writing to {0}".format(lvsname)) - self.sp_write(lvsname, lvs=True) + debug.print_raw("LVS: Writing to {0}".format(self.lvs_name)) + self.sp_write(self.lvs_name, lvs=True) if not OPTS.netlist_only and OPTS.check_lvsdrc: verify.write_lvs_script(cell_name=self.s.name, - gds_name=os.path.basename(gdsname), - sp_name=os.path.basename(lvsname), + gds_name=os.path.basename(self.gds_name), + sp_name=os.path.basename(self.lvs_name), final_verification=True, output_path=OPTS.output_path) print_time("LVS writing", datetime.datetime.now(), start_time) @@ -148,14 +161,8 @@ class sram(): if OPTS.use_pex: start_time = datetime.datetime.now() # Output the extracted design if requested - pexname = OPTS.output_path + self.s.name + ".pex.sp" - spname = OPTS.output_path + self.s.name + ".sp" - verify.run_pex(self.s.name, gdsname, spname, output=pexname) - sp_file = pexname + verify.run_pex(self.s.name, self.gds_name, self.sp_name, output=self.pex_name) print_time("Extraction", datetime.datetime.now(), start_time) - else: - # Use generated spice file for characterization - sp_file = spname # Save a functional simulation file @@ -163,7 +170,7 @@ class sram(): start_time = datetime.datetime.now() from characterizer import lib debug.print_raw("LIB: Characterizing... ") - lib(out_dir=OPTS.output_path, sram=self.s, sp_file=sp_file) + lib(out_dir=OPTS.output_path, sram=self.s, sp_file=self.get_sp_name()) print_time("Characterization", datetime.datetime.now(), start_time) # Write the config file @@ -183,9 +190,8 @@ class sram(): # Write a verilog model start_time = datetime.datetime.now() - vname = OPTS.output_path + self.s.name + ".v" - debug.print_raw("Verilog: Writing to {0}".format(vname)) - self.verilog_write(vname) + debug.print_raw("Verilog: Writing to {0}".format(self.v_name)) + self.verilog_write(self.v_name) print_time("Verilog", datetime.datetime.now(), start_time) # Write out options if specified diff --git a/compiler/sram/sram_base.py b/compiler/sram/sram_base.py index 72c5e3fe..6ecc3a5a 100644 --- a/compiler/sram/sram_base.py +++ b/compiler/sram/sram_base.py @@ -7,7 +7,7 @@ # import datetime import debug -from math import log, ceil +from math import log from importlib import reload from vector import vector from globals import OPTS, print_time @@ -20,8 +20,7 @@ from tech import spice class sram_base(design, verilog, lef): """ - Dynamically generated SRAM by connecting banks to control logic. The - number of banks should be 1 , 2 or 4 + Dynamically generated SRAM by connecting banks to control logic. """ def __init__(self, name, sram_config): design.__init__(self, name) @@ -30,17 +29,10 @@ class sram_base(design, verilog, lef): self.sram_config = sram_config sram_config.set_local_config(self) + sram_config.compute_sizes() self.bank_insts = [] - if self.write_size: - self.num_wmasks = int(ceil(self.word_size / self.write_size)) - else: - self.num_wmasks = 0 - - if not self.num_spare_cols: - self.num_spare_cols = 0 - try: from tech import power_grid self.supply_stack = power_grid diff --git a/compiler/sram/sram_config.py b/compiler/sram/sram_config.py index 4c1bb117..a65387fb 100644 --- a/compiler/sram/sram_config.py +++ b/compiler/sram/sram_config.py @@ -14,7 +14,8 @@ from sram_factory import factory class sram_config: """ This is a structure that is used to hold the SRAM configuration options. """ - def __init__(self, word_size, num_words, write_size=None, num_banks=1, words_per_row=None, num_spare_rows=0, num_spare_cols=0): + def __init__(self, word_size, num_words, write_size=None, num_banks=1, + words_per_row=None, num_spare_rows=0, num_spare_cols=0): self.word_size = word_size self.num_words = num_words # Don't add a write mask if it is the same size as the data word @@ -37,6 +38,16 @@ class sram_config: except ImportError: self.array_col_multiple = 1 + if self.write_size: + self.num_wmasks = int(ceil(self.word_size / self.write_size)) + else: + self.num_wmasks = 0 + + if not self.num_spare_cols: + self.num_spare_cols = 0 + + if not self.num_spare_rows: + self.num_spare_rows = 0 # This will get over-written when we determine the organization self.words_per_row = words_per_row @@ -167,3 +178,43 @@ class sram_config: return int(words_per_row * tentative_num_rows / 16) return words_per_row + + def setup_multiport_constants(self): + """ + These are contants and lists that aid multiport design. + Ports are always in the order RW, W, R. + Port indices start from 0 and increment. + A first RW port will have clk0, csb0, web0, addr0, data0 + A first W port (with no RW ports) will be: clk0, csb0, addr0, data0 + + """ + total_ports = OPTS.num_rw_ports + OPTS.num_w_ports + OPTS.num_r_ports + + # These are the read/write port indices. + self.readwrite_ports = [] + # These are the read/write and write-only port indices + self.write_ports = [] + # These are the write-only port indices. + self.writeonly_ports = [] + # These are the read/write and read-only port indices + self.read_ports = [] + # These are the read-only port indices. + self.readonly_ports = [] + # These are all the ports + self.all_ports = list(range(total_ports)) + + # The order is always fixed as RW, W, R + port_number = 0 + for port in range(OPTS.num_rw_ports): + self.readwrite_ports.append(port_number) + self.write_ports.append(port_number) + self.read_ports.append(port_number) + port_number += 1 + for port in range(OPTS.num_w_ports): + self.write_ports.append(port_number) + self.writeonly_ports.append(port_number) + port_number += 1 + for port in range(OPTS.num_r_ports): + self.read_ports.append(port_number) + self.readonly_ports.append(port_number) + port_number += 1 From a87b2e9446caae0bb367643c850c43d1ad4e38d2 Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Tue, 1 Mar 2022 15:12:03 -0800 Subject: [PATCH 002/130] Adding characterizer executable --- compiler/characterize_existing.py | 64 +++++++++++++++++++++++++++++++ compiler/sram/sram.py | 5 ++- 2 files changed, 67 insertions(+), 2 deletions(-) create mode 100755 compiler/characterize_existing.py diff --git a/compiler/characterize_existing.py b/compiler/characterize_existing.py new file mode 100755 index 00000000..82e95b1b --- /dev/null +++ b/compiler/characterize_existing.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python3 +# See LICENSE for licensing information. +# +# Copyright (c) 2016-2021 Regents of the University of California and The Board +# of Regents for the Oklahoma Agricultural and Mechanical College +# (acting for and on behalf of Oklahoma State University) +# All rights reserved. +# +""" +This script will characterize an SRAM previously generated by OpenRAM given a +configuration file. Configuration option "use_pex" determines whether extracted +or generated spice is used and option "analytical_delay" determines whether +an analytical model or spice simulation is used for characterization. +""" + +import sys +import datetime +from globals import * +from importlib import reload + +(OPTS, args) = parse_args() + +# Override the usage +USAGE = "Usage: {} [options] \nUse -h for help.\n".format(__file__) + +# Check that we are left with a single configuration file as argument. +if len(args) != 1: + print(USAGE) + sys.exit(2) + +# These depend on arguments, so don't load them until now. +import debug + +# Parse config file and set up all the options +init_openram(config_file=args[0], is_unit_test=False) + +# Configure the SRAM organization (duplicated from openram.py) +from sram_config import sram_config +c = sram_config(word_size=OPTS.word_size, + num_words=OPTS.num_words, + write_size=OPTS.write_size, + num_banks=OPTS.num_banks, + words_per_row=OPTS.words_per_row, + num_spare_rows=OPTS.num_spare_rows, + num_spare_cols=OPTS.num_spare_cols) + +# Initialize and create the sram object +from sram import sram +s = sram(name=OPTS.output_name, sram_config=c) +s.create() + +# Characterize the design +start_time = datetime.datetime.now() +from characterizer import lib +debug.print_raw("LIB: Characterizing... ") +lib(out_dir=OPTS.output_path, sram=s.s, sp_file=s.get_sp_name()) +print_time("Characterization", datetime.datetime.now(), start_time) + +# Output info about this run +print("Output file is:\n{0}.lib".format(OPTS.output_path)) +#report_status() #could modify this function to provide relevant info + +# Delete temp files, remove the dir, etc. +end_openram() diff --git a/compiler/sram/sram.py b/compiler/sram/sram.py index afd57f48..fdc8ec76 100644 --- a/compiler/sram/sram.py +++ b/compiler/sram/sram.py @@ -25,6 +25,7 @@ class sram(): self.name = name self.config = sram_config + sram_config.setup_multiport_constants() sram_config.set_local_config(self) self.sp_name = OPTS.output_path + self.name + ".sp" @@ -120,6 +121,8 @@ class sram(): start_time = datetime.datetime.now() debug.print_raw("SP: Writing to {0}".format(self.sp_name)) self.sp_write(self.sp_name) + + # Save a functional simulation file with default period functional(self.s, os.path.basename(self.sp_name), cycles=200, @@ -164,8 +167,6 @@ class sram(): verify.run_pex(self.s.name, self.gds_name, self.sp_name, output=self.pex_name) print_time("Extraction", datetime.datetime.now(), start_time) - # Save a functional simulation file - # Characterize the design start_time = datetime.datetime.now() from characterizer import lib From d47b5612d515082d683b99c1500dea4f57f2e168 Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Wed, 2 Mar 2022 12:18:54 -0800 Subject: [PATCH 003/130] characterizer and functional simulator working from command line --- compiler/characterize_existing.py | 2 + compiler/characterizer/functional.py | 7 +-- compiler/func_sim_existing.py | 70 ++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 3 deletions(-) create mode 100755 compiler/func_sim_existing.py diff --git a/compiler/characterize_existing.py b/compiler/characterize_existing.py index 82e95b1b..f6c83c4b 100755 --- a/compiler/characterize_existing.py +++ b/compiler/characterize_existing.py @@ -34,6 +34,8 @@ import debug # Parse config file and set up all the options init_openram(config_file=args[0], is_unit_test=False) +print_banner() + # Configure the SRAM organization (duplicated from openram.py) from sram_config import sram_config c = sram_config(word_size=OPTS.word_size, diff --git a/compiler/characterizer/functional.py b/compiler/characterizer/functional.py index e7d03f25..3bc94ab7 100644 --- a/compiler/characterizer/functional.py +++ b/compiler/characterizer/functional.py @@ -36,9 +36,6 @@ class functional(simulation): if not corner: corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0]) - if period: - self.period = period - if not output_path: self.output_path = OPTS.openram_temp else: @@ -73,6 +70,10 @@ class functional(simulation): self.set_spice_constants() self.set_stimulus_variables() + # Override default period + if period: + self.period = period + # For the debug signal names self.wordline_row = 0 self.bitline_column = 0 diff --git a/compiler/func_sim_existing.py b/compiler/func_sim_existing.py new file mode 100755 index 00000000..ec89c3d7 --- /dev/null +++ b/compiler/func_sim_existing.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python3 +# See LICENSE for licensing information. +# +# Copyright (c) 2016-2021 Regents of the University of California and The Board +# of Regents for the Oklahoma Agricultural and Mechanical College +# (acting for and on behalf of Oklahoma State University) +# All rights reserved. +# +""" +This script will characterize an SRAM previously generated by OpenRAM given a +configuration file. Configuration option "use_pex" determines whether extracted +or generated spice is used and option "analytical_delay" determines whether +an analytical model or spice simulation is used for characterization. +""" + +import sys +import datetime +from globals import * +from importlib import reload + +(OPTS, args) = parse_args() + +# Override the usage +USAGE = "Usage: {} [options] \nUse -h for help.\n".format(__file__) + +# Check that we are left with a single configuration file as argument. +if len(args) != 3: + print(USAGE) + sys.exit(2) + +# Parse argument +config_file = args[0] +cycles = int(args[1]) +period = float(args[2]) + +# These depend on arguments, so don't load them until now. +import debug + +# Parse config file and set up all the options +init_openram(config_file=config_file, is_unit_test=False) + +print_banner() + +# Configure the SRAM organization (duplicated from openram.py) +from sram_config import sram_config +c = sram_config(word_size=OPTS.word_size, + num_words=OPTS.num_words, + write_size=OPTS.write_size, + num_banks=OPTS.num_banks, + words_per_row=OPTS.words_per_row, + num_spare_rows=OPTS.num_spare_rows, + num_spare_cols=OPTS.num_spare_cols) + +# Initialize and create the sram object +from sram import sram +s = sram(name=OPTS.output_name, sram_config=c) +s.create() + +# Generate stimulus and run functional simulation on the design +start_time = datetime.datetime.now() +from characterizer import functional +debug.print_raw("Functional simulation... ") +f = functional(s.s, cycles=cycles, spfile=s.get_sp_name(), period=period, output_path=OPTS.openram_temp) +(fail, error) = f.run() +print_time("Functional simulation", datetime.datetime.now(), start_time) +print(error) + +# Delete temp files, remove the dir, etc. after success +if fail: + end_openram() From 910980328c3292029b1a94bf57c2471979925fe3 Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Wed, 2 Mar 2022 12:47:05 -0800 Subject: [PATCH 004/130] clarify file location message for user --- compiler/characterize_existing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/characterize_existing.py b/compiler/characterize_existing.py index f6c83c4b..c8456b9f 100755 --- a/compiler/characterize_existing.py +++ b/compiler/characterize_existing.py @@ -59,7 +59,7 @@ lib(out_dir=OPTS.output_path, sram=s.s, sp_file=s.get_sp_name()) print_time("Characterization", datetime.datetime.now(), start_time) # Output info about this run -print("Output file is:\n{0}.lib".format(OPTS.output_path)) +print("Output files are:\n{0}*.lib".format(OPTS.output_path)) #report_status() #could modify this function to provide relevant info # Delete temp files, remove the dir, etc. From 1acc6be3ce12f483c9467393c2f310d687ff84fb Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Wed, 2 Mar 2022 16:38:39 -0800 Subject: [PATCH 005/130] call create() function from sram/__init__ --- compiler/characterize_existing.py | 1 - compiler/func_sim_existing.py | 1 - compiler/gen_stimulus.py | 1 - compiler/openram.py | 7 ++----- compiler/sram/sram.py | 2 ++ 5 files changed, 4 insertions(+), 8 deletions(-) diff --git a/compiler/characterize_existing.py b/compiler/characterize_existing.py index c8456b9f..73a7c235 100755 --- a/compiler/characterize_existing.py +++ b/compiler/characterize_existing.py @@ -49,7 +49,6 @@ c = sram_config(word_size=OPTS.word_size, # Initialize and create the sram object from sram import sram s = sram(name=OPTS.output_name, sram_config=c) -s.create() # Characterize the design start_time = datetime.datetime.now() diff --git a/compiler/func_sim_existing.py b/compiler/func_sim_existing.py index ec89c3d7..0d693e91 100755 --- a/compiler/func_sim_existing.py +++ b/compiler/func_sim_existing.py @@ -54,7 +54,6 @@ c = sram_config(word_size=OPTS.word_size, # Initialize and create the sram object from sram import sram s = sram(name=OPTS.output_name, sram_config=c) -s.create() # Generate stimulus and run functional simulation on the design start_time = datetime.datetime.now() diff --git a/compiler/gen_stimulus.py b/compiler/gen_stimulus.py index d69d867d..c9b4e350 100755 --- a/compiler/gen_stimulus.py +++ b/compiler/gen_stimulus.py @@ -60,7 +60,6 @@ OPTS.openram_temp = OPTS.output_path from sram import sram s = sram(name=OPTS.output_name, sram_config=c) -s.create() from characterizer import delay import tech diff --git a/compiler/openram.py b/compiler/openram.py index 74f80128..240a3f9f 100755 --- a/compiler/openram.py +++ b/compiler/openram.py @@ -72,13 +72,10 @@ debug.print_raw("Output files are: ") for path in output_files: debug.print_raw(path) - +# Initialize the SRAM s = sram(name=OPTS.output_name, sram_config=c) -# Actually build the SRAM -s.create() - -# Output the files for the resulting SRAM +# Generate and output the files for the resulting SRAM s.save() # Delete temp files etc. diff --git a/compiler/sram/sram.py b/compiler/sram/sram.py index fdc8ec76..afa8cd58 100644 --- a/compiler/sram/sram.py +++ b/compiler/sram/sram.py @@ -40,6 +40,8 @@ class sram(): from design import design design.name_map=[] + self.create() + def create(self): debug.info(2, "create sram of size {0} with {1} num of words {2} banks".format(self.word_size, self.num_words, From 353ff7859c0835d7acb7cc9d0b5830986f4c8b36 Mon Sep 17 00:00:00 2001 From: mrg Date: Wed, 16 Feb 2022 10:54:39 -0800 Subject: [PATCH 006/130] Initial work on separate delay and func simulation --- compiler/base/design.py | 1 - compiler/gen_stimulus.py | 40 +++++++++----------- compiler/openram.py | 11 +++--- compiler/sram/sram.py | 72 +++++++++++++++++++----------------- compiler/sram/sram_base.py | 14 ++----- compiler/sram/sram_config.py | 53 +++++++++++++++++++++++++- 6 files changed, 116 insertions(+), 75 deletions(-) diff --git a/compiler/base/design.py b/compiler/base/design.py index 70a9047b..12fd6c56 100644 --- a/compiler/base/design.py +++ b/compiler/base/design.py @@ -318,4 +318,3 @@ class design(hierarchy_design): design.setup_drc_constants() design.setup_layer_constants() - diff --git a/compiler/gen_stimulus.py b/compiler/gen_stimulus.py index 69e53cd8..d69d867d 100755 --- a/compiler/gen_stimulus.py +++ b/compiler/gen_stimulus.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # See LICENSE for licensing information. # # Copyright (c) 2016-2021 Regents of the University of California and The Board @@ -15,6 +15,7 @@ corner, but should probably be extended. import sys from globals import * +from importlib import reload (OPTS, args) = parse_args() @@ -41,36 +42,30 @@ slew = float(args[3]) import debug init_openram(config_file=config_file, is_unit_test=False) + +from sram_config import sram_config +c = sram_config(word_size=OPTS.word_size, + num_words=OPTS.num_words, + write_size=OPTS.write_size, + num_banks=OPTS.num_banks, + words_per_row=OPTS.words_per_row, + num_spare_rows=OPTS.num_spare_rows, + num_spare_cols=OPTS.num_spare_cols) + +OPTS.netlist_only = True OPTS.check_lvsdrc = False # Put the temp output in the output path since it is what we want to generate! old_openram_temp = OPTS.openram_temp OPTS.openram_temp = OPTS.output_path - - -import sram -class fake_sram(sram.sram): - """ This is an SRAM that doesn't actually create itself, just computes - the sizes. """ - def __init__(self, word_size, num_words, num_banks, name, num_spare_rows): - self.name = name - self.word_size = word_size - self.num_words = num_words - self.num_banks = num_banks - self.num_spare_rows = num_spare_rows - c = reload(__import__(OPTS.bitcell)) - self.mod_bitcell = getattr(c, OPTS.bitcell) - self.bitcell = self.mod_bitcell() - # to get the row, col, etc. - self.compute_sizes() - -sram = fake_sram(OPTS.word_size, OPTS.num_words, OPTS.num_banks, OPTS.output_name) -sp_file = OPTS.output_path+OPTS.output_name + ".sp" +from sram import sram +s = sram(name=OPTS.output_name, sram_config=c) +s.create() from characterizer import delay import tech # Set up the delay and set to the nominal corner -d = delay.delay(sram, sp_file, ("TT", tech.spice["nom_supply_voltage"], tech.spice["nom_temperature"])) +d = delay(s, s.get_sp_name(), ("TT", tech.spice["nom_supply_voltage"], tech.spice["nom_temperature"])) # Set the period d.period = period # Set the load of outputs and slew of inputs @@ -91,4 +86,3 @@ print("Output files are:\n{0}stim.sp\n{0}sram.sp\n{0}reduced.sp".format(OPTS.out OPTS.openram_temp = old_openram_temp # Delete temp files, remove the dir, etc. end_openram() - diff --git a/compiler/openram.py b/compiler/openram.py index 089c0f3a..74f80128 100755 --- a/compiler/openram.py +++ b/compiler/openram.py @@ -48,7 +48,7 @@ g.print_time("Start", start_time) g.report_status() from sram_config import sram_config - +from sram import sram # Configure the SRAM organization c = sram_config(word_size=OPTS.word_size, @@ -73,9 +73,10 @@ for path in output_files: debug.print_raw(path) -from sram import sram -s = sram(sram_config=c, - name=OPTS.output_name) +s = sram(name=OPTS.output_name, sram_config=c) + +# Actually build the SRAM +s.create() # Output the files for the resulting SRAM s.save() @@ -83,5 +84,3 @@ s.save() # Delete temp files etc. g.end_openram() g.print_time("End", datetime.datetime.now(), start_time) - - diff --git a/compiler/sram/sram.py b/compiler/sram/sram.py index 90855d8e..afd57f48 100644 --- a/compiler/sram/sram.py +++ b/compiler/sram/sram.py @@ -21,30 +21,39 @@ class sram(): results. We can later add visualizer and other high-level functions as needed. """ - def __init__(self, sram_config, name): + def __init__(self, name, sram_config): + self.name = name + self.config = sram_config sram_config.set_local_config(self) + self.sp_name = OPTS.output_path + self.name + ".sp" + self.lvs_name = OPTS.output_path + self.name + ".lvs.sp" + self.pex_name = OPTS.output_path + self.name + ".pex.sp" + self.gds_name = OPTS.output_path + self.name + ".gds" + self.lef_name = OPTS.output_path + self.name + ".lef" + self.v_name = OPTS.output_path + self.name + ".v" + # reset the static duplicate name checker for unit tests # in case we create more than one SRAM from design import design design.name_map=[] + def create(self): debug.info(2, "create sram of size {0} with {1} num of words {2} banks".format(self.word_size, self.num_words, self.num_banks)) start_time = datetime.datetime.now() - self.name = name - if self.num_banks == 1: - from sram_1bank import sram_1bank as sram + from sram_1bank import sram_1bank as sram_banked elif self.num_banks == 2: - from sram_2bank import sram_2bank as sram + from sram_2bank import sram_2bank as sram_banked else: debug.error("Invalid number of banks.", -1) - self.s = sram(name, sram_config) + self.s = sram_banked(name=self.name, + sram_config=self.config) self.s.create_netlist() if not OPTS.netlist_only: self.s.create_layout() @@ -52,6 +61,14 @@ class sram(): if not OPTS.is_unit_test: print_time("SRAM creation", datetime.datetime.now(), start_time) + def get_sp_name(self): + if OPTS.use_pex: + # Use the extracted spice file + return self.pex_name + else: + # Use generated spice file for characterization + return self.sp_name + def sp_write(self, name, lvs=False, trim=False): self.s.sp_write(name, lvs, trim) @@ -101,11 +118,10 @@ class sram(): # Save the spice file start_time = datetime.datetime.now() - spname = OPTS.output_path + self.s.name + ".sp" - debug.print_raw("SP: Writing to {0}".format(spname)) - self.sp_write(spname) + debug.print_raw("SP: Writing to {0}".format(self.sp_name)) + self.sp_write(self.sp_name) functional(self.s, - os.path.basename(spname), + os.path.basename(self.sp_name), cycles=200, output_path=OPTS.output_path) print_time("Spice writing", datetime.datetime.now(), start_time) @@ -113,12 +129,11 @@ class sram(): if not OPTS.netlist_only: # Write the layout start_time = datetime.datetime.now() - gdsname = OPTS.output_path + self.s.name + ".gds" - debug.print_raw("GDS: Writing to {0}".format(gdsname)) - self.gds_write(gdsname) + debug.print_raw("GDS: Writing to {0}".format(self.gds_name)) + self.gds_write(self.gds_name) if OPTS.check_lvsdrc: verify.write_drc_script(cell_name=self.s.name, - gds_name=os.path.basename(gdsname), + gds_name=os.path.basename(self.gds_name), extract=True, final_verification=True, output_path=OPTS.output_path) @@ -126,20 +141,18 @@ class sram(): # Create a LEF physical model start_time = datetime.datetime.now() - lefname = OPTS.output_path + self.s.name + ".lef" - debug.print_raw("LEF: Writing to {0}".format(lefname)) - self.lef_write(lefname) + debug.print_raw("LEF: Writing to {0}".format(self.lef_name)) + self.lef_write(self.lef_name) print_time("LEF", datetime.datetime.now(), start_time) # Save the LVS file start_time = datetime.datetime.now() - lvsname = OPTS.output_path + self.s.name + ".lvs.sp" - debug.print_raw("LVS: Writing to {0}".format(lvsname)) - self.sp_write(lvsname, lvs=True) + debug.print_raw("LVS: Writing to {0}".format(self.lvs_name)) + self.sp_write(self.lvs_name, lvs=True) if not OPTS.netlist_only and OPTS.check_lvsdrc: verify.write_lvs_script(cell_name=self.s.name, - gds_name=os.path.basename(gdsname), - sp_name=os.path.basename(lvsname), + gds_name=os.path.basename(self.gds_name), + sp_name=os.path.basename(self.lvs_name), final_verification=True, output_path=OPTS.output_path) print_time("LVS writing", datetime.datetime.now(), start_time) @@ -148,14 +161,8 @@ class sram(): if OPTS.use_pex: start_time = datetime.datetime.now() # Output the extracted design if requested - pexname = OPTS.output_path + self.s.name + ".pex.sp" - spname = OPTS.output_path + self.s.name + ".sp" - verify.run_pex(self.s.name, gdsname, spname, output=pexname) - sp_file = pexname + verify.run_pex(self.s.name, self.gds_name, self.sp_name, output=self.pex_name) print_time("Extraction", datetime.datetime.now(), start_time) - else: - # Use generated spice file for characterization - sp_file = spname # Save a functional simulation file @@ -163,7 +170,7 @@ class sram(): start_time = datetime.datetime.now() from characterizer import lib debug.print_raw("LIB: Characterizing... ") - lib(out_dir=OPTS.output_path, sram=self.s, sp_file=sp_file) + lib(out_dir=OPTS.output_path, sram=self.s, sp_file=self.get_sp_name()) print_time("Characterization", datetime.datetime.now(), start_time) # Write the config file @@ -183,9 +190,8 @@ class sram(): # Write a verilog model start_time = datetime.datetime.now() - vname = OPTS.output_path + self.s.name + ".v" - debug.print_raw("Verilog: Writing to {0}".format(vname)) - self.verilog_write(vname) + debug.print_raw("Verilog: Writing to {0}".format(self.v_name)) + self.verilog_write(self.v_name) print_time("Verilog", datetime.datetime.now(), start_time) # Write out options if specified diff --git a/compiler/sram/sram_base.py b/compiler/sram/sram_base.py index 72c5e3fe..6ecc3a5a 100644 --- a/compiler/sram/sram_base.py +++ b/compiler/sram/sram_base.py @@ -7,7 +7,7 @@ # import datetime import debug -from math import log, ceil +from math import log from importlib import reload from vector import vector from globals import OPTS, print_time @@ -20,8 +20,7 @@ from tech import spice class sram_base(design, verilog, lef): """ - Dynamically generated SRAM by connecting banks to control logic. The - number of banks should be 1 , 2 or 4 + Dynamically generated SRAM by connecting banks to control logic. """ def __init__(self, name, sram_config): design.__init__(self, name) @@ -30,17 +29,10 @@ class sram_base(design, verilog, lef): self.sram_config = sram_config sram_config.set_local_config(self) + sram_config.compute_sizes() self.bank_insts = [] - if self.write_size: - self.num_wmasks = int(ceil(self.word_size / self.write_size)) - else: - self.num_wmasks = 0 - - if not self.num_spare_cols: - self.num_spare_cols = 0 - try: from tech import power_grid self.supply_stack = power_grid diff --git a/compiler/sram/sram_config.py b/compiler/sram/sram_config.py index 4c1bb117..a65387fb 100644 --- a/compiler/sram/sram_config.py +++ b/compiler/sram/sram_config.py @@ -14,7 +14,8 @@ from sram_factory import factory class sram_config: """ This is a structure that is used to hold the SRAM configuration options. """ - def __init__(self, word_size, num_words, write_size=None, num_banks=1, words_per_row=None, num_spare_rows=0, num_spare_cols=0): + def __init__(self, word_size, num_words, write_size=None, num_banks=1, + words_per_row=None, num_spare_rows=0, num_spare_cols=0): self.word_size = word_size self.num_words = num_words # Don't add a write mask if it is the same size as the data word @@ -37,6 +38,16 @@ class sram_config: except ImportError: self.array_col_multiple = 1 + if self.write_size: + self.num_wmasks = int(ceil(self.word_size / self.write_size)) + else: + self.num_wmasks = 0 + + if not self.num_spare_cols: + self.num_spare_cols = 0 + + if not self.num_spare_rows: + self.num_spare_rows = 0 # This will get over-written when we determine the organization self.words_per_row = words_per_row @@ -167,3 +178,43 @@ class sram_config: return int(words_per_row * tentative_num_rows / 16) return words_per_row + + def setup_multiport_constants(self): + """ + These are contants and lists that aid multiport design. + Ports are always in the order RW, W, R. + Port indices start from 0 and increment. + A first RW port will have clk0, csb0, web0, addr0, data0 + A first W port (with no RW ports) will be: clk0, csb0, addr0, data0 + + """ + total_ports = OPTS.num_rw_ports + OPTS.num_w_ports + OPTS.num_r_ports + + # These are the read/write port indices. + self.readwrite_ports = [] + # These are the read/write and write-only port indices + self.write_ports = [] + # These are the write-only port indices. + self.writeonly_ports = [] + # These are the read/write and read-only port indices + self.read_ports = [] + # These are the read-only port indices. + self.readonly_ports = [] + # These are all the ports + self.all_ports = list(range(total_ports)) + + # The order is always fixed as RW, W, R + port_number = 0 + for port in range(OPTS.num_rw_ports): + self.readwrite_ports.append(port_number) + self.write_ports.append(port_number) + self.read_ports.append(port_number) + port_number += 1 + for port in range(OPTS.num_w_ports): + self.write_ports.append(port_number) + self.writeonly_ports.append(port_number) + port_number += 1 + for port in range(OPTS.num_r_ports): + self.read_ports.append(port_number) + self.readonly_ports.append(port_number) + port_number += 1 From f9bec36da53b8cac389f9157e87bc7b9b5616149 Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Tue, 1 Mar 2022 15:12:03 -0800 Subject: [PATCH 007/130] Adding characterizer executable --- compiler/characterize_existing.py | 64 +++++++++++++++++++++++++++++++ compiler/sram/sram.py | 5 ++- 2 files changed, 67 insertions(+), 2 deletions(-) create mode 100755 compiler/characterize_existing.py diff --git a/compiler/characterize_existing.py b/compiler/characterize_existing.py new file mode 100755 index 00000000..82e95b1b --- /dev/null +++ b/compiler/characterize_existing.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python3 +# See LICENSE for licensing information. +# +# Copyright (c) 2016-2021 Regents of the University of California and The Board +# of Regents for the Oklahoma Agricultural and Mechanical College +# (acting for and on behalf of Oklahoma State University) +# All rights reserved. +# +""" +This script will characterize an SRAM previously generated by OpenRAM given a +configuration file. Configuration option "use_pex" determines whether extracted +or generated spice is used and option "analytical_delay" determines whether +an analytical model or spice simulation is used for characterization. +""" + +import sys +import datetime +from globals import * +from importlib import reload + +(OPTS, args) = parse_args() + +# Override the usage +USAGE = "Usage: {} [options] \nUse -h for help.\n".format(__file__) + +# Check that we are left with a single configuration file as argument. +if len(args) != 1: + print(USAGE) + sys.exit(2) + +# These depend on arguments, so don't load them until now. +import debug + +# Parse config file and set up all the options +init_openram(config_file=args[0], is_unit_test=False) + +# Configure the SRAM organization (duplicated from openram.py) +from sram_config import sram_config +c = sram_config(word_size=OPTS.word_size, + num_words=OPTS.num_words, + write_size=OPTS.write_size, + num_banks=OPTS.num_banks, + words_per_row=OPTS.words_per_row, + num_spare_rows=OPTS.num_spare_rows, + num_spare_cols=OPTS.num_spare_cols) + +# Initialize and create the sram object +from sram import sram +s = sram(name=OPTS.output_name, sram_config=c) +s.create() + +# Characterize the design +start_time = datetime.datetime.now() +from characterizer import lib +debug.print_raw("LIB: Characterizing... ") +lib(out_dir=OPTS.output_path, sram=s.s, sp_file=s.get_sp_name()) +print_time("Characterization", datetime.datetime.now(), start_time) + +# Output info about this run +print("Output file is:\n{0}.lib".format(OPTS.output_path)) +#report_status() #could modify this function to provide relevant info + +# Delete temp files, remove the dir, etc. +end_openram() diff --git a/compiler/sram/sram.py b/compiler/sram/sram.py index afd57f48..fdc8ec76 100644 --- a/compiler/sram/sram.py +++ b/compiler/sram/sram.py @@ -25,6 +25,7 @@ class sram(): self.name = name self.config = sram_config + sram_config.setup_multiport_constants() sram_config.set_local_config(self) self.sp_name = OPTS.output_path + self.name + ".sp" @@ -120,6 +121,8 @@ class sram(): start_time = datetime.datetime.now() debug.print_raw("SP: Writing to {0}".format(self.sp_name)) self.sp_write(self.sp_name) + + # Save a functional simulation file with default period functional(self.s, os.path.basename(self.sp_name), cycles=200, @@ -164,8 +167,6 @@ class sram(): verify.run_pex(self.s.name, self.gds_name, self.sp_name, output=self.pex_name) print_time("Extraction", datetime.datetime.now(), start_time) - # Save a functional simulation file - # Characterize the design start_time = datetime.datetime.now() from characterizer import lib From a89cd4deeed0650744a0f300363f477104114589 Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Wed, 2 Mar 2022 12:18:54 -0800 Subject: [PATCH 008/130] characterizer and functional simulator working from command line --- compiler/characterize_existing.py | 2 + compiler/characterizer/functional.py | 7 +-- compiler/func_sim_existing.py | 70 ++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 3 deletions(-) create mode 100755 compiler/func_sim_existing.py diff --git a/compiler/characterize_existing.py b/compiler/characterize_existing.py index 82e95b1b..f6c83c4b 100755 --- a/compiler/characterize_existing.py +++ b/compiler/characterize_existing.py @@ -34,6 +34,8 @@ import debug # Parse config file and set up all the options init_openram(config_file=args[0], is_unit_test=False) +print_banner() + # Configure the SRAM organization (duplicated from openram.py) from sram_config import sram_config c = sram_config(word_size=OPTS.word_size, diff --git a/compiler/characterizer/functional.py b/compiler/characterizer/functional.py index e7d03f25..3bc94ab7 100644 --- a/compiler/characterizer/functional.py +++ b/compiler/characterizer/functional.py @@ -36,9 +36,6 @@ class functional(simulation): if not corner: corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0]) - if period: - self.period = period - if not output_path: self.output_path = OPTS.openram_temp else: @@ -73,6 +70,10 @@ class functional(simulation): self.set_spice_constants() self.set_stimulus_variables() + # Override default period + if period: + self.period = period + # For the debug signal names self.wordline_row = 0 self.bitline_column = 0 diff --git a/compiler/func_sim_existing.py b/compiler/func_sim_existing.py new file mode 100755 index 00000000..ec89c3d7 --- /dev/null +++ b/compiler/func_sim_existing.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python3 +# See LICENSE for licensing information. +# +# Copyright (c) 2016-2021 Regents of the University of California and The Board +# of Regents for the Oklahoma Agricultural and Mechanical College +# (acting for and on behalf of Oklahoma State University) +# All rights reserved. +# +""" +This script will characterize an SRAM previously generated by OpenRAM given a +configuration file. Configuration option "use_pex" determines whether extracted +or generated spice is used and option "analytical_delay" determines whether +an analytical model or spice simulation is used for characterization. +""" + +import sys +import datetime +from globals import * +from importlib import reload + +(OPTS, args) = parse_args() + +# Override the usage +USAGE = "Usage: {} [options] \nUse -h for help.\n".format(__file__) + +# Check that we are left with a single configuration file as argument. +if len(args) != 3: + print(USAGE) + sys.exit(2) + +# Parse argument +config_file = args[0] +cycles = int(args[1]) +period = float(args[2]) + +# These depend on arguments, so don't load them until now. +import debug + +# Parse config file and set up all the options +init_openram(config_file=config_file, is_unit_test=False) + +print_banner() + +# Configure the SRAM organization (duplicated from openram.py) +from sram_config import sram_config +c = sram_config(word_size=OPTS.word_size, + num_words=OPTS.num_words, + write_size=OPTS.write_size, + num_banks=OPTS.num_banks, + words_per_row=OPTS.words_per_row, + num_spare_rows=OPTS.num_spare_rows, + num_spare_cols=OPTS.num_spare_cols) + +# Initialize and create the sram object +from sram import sram +s = sram(name=OPTS.output_name, sram_config=c) +s.create() + +# Generate stimulus and run functional simulation on the design +start_time = datetime.datetime.now() +from characterizer import functional +debug.print_raw("Functional simulation... ") +f = functional(s.s, cycles=cycles, spfile=s.get_sp_name(), period=period, output_path=OPTS.openram_temp) +(fail, error) = f.run() +print_time("Functional simulation", datetime.datetime.now(), start_time) +print(error) + +# Delete temp files, remove the dir, etc. after success +if fail: + end_openram() From b216552c3feb1006687d6512436b99ccf1fe4103 Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Wed, 2 Mar 2022 12:47:05 -0800 Subject: [PATCH 009/130] clarify file location message for user --- compiler/characterize_existing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/characterize_existing.py b/compiler/characterize_existing.py index f6c83c4b..c8456b9f 100755 --- a/compiler/characterize_existing.py +++ b/compiler/characterize_existing.py @@ -59,7 +59,7 @@ lib(out_dir=OPTS.output_path, sram=s.s, sp_file=s.get_sp_name()) print_time("Characterization", datetime.datetime.now(), start_time) # Output info about this run -print("Output file is:\n{0}.lib".format(OPTS.output_path)) +print("Output files are:\n{0}*.lib".format(OPTS.output_path)) #report_status() #could modify this function to provide relevant info # Delete temp files, remove the dir, etc. From 043e93e75e38ac0f565057802446a0c106ae1ef1 Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Wed, 2 Mar 2022 16:38:39 -0800 Subject: [PATCH 010/130] call create() function from sram/__init__ --- compiler/characterize_existing.py | 1 - compiler/func_sim_existing.py | 1 - compiler/gen_stimulus.py | 1 - compiler/openram.py | 7 ++----- compiler/sram/sram.py | 2 ++ 5 files changed, 4 insertions(+), 8 deletions(-) diff --git a/compiler/characterize_existing.py b/compiler/characterize_existing.py index c8456b9f..73a7c235 100755 --- a/compiler/characterize_existing.py +++ b/compiler/characterize_existing.py @@ -49,7 +49,6 @@ c = sram_config(word_size=OPTS.word_size, # Initialize and create the sram object from sram import sram s = sram(name=OPTS.output_name, sram_config=c) -s.create() # Characterize the design start_time = datetime.datetime.now() diff --git a/compiler/func_sim_existing.py b/compiler/func_sim_existing.py index ec89c3d7..0d693e91 100755 --- a/compiler/func_sim_existing.py +++ b/compiler/func_sim_existing.py @@ -54,7 +54,6 @@ c = sram_config(word_size=OPTS.word_size, # Initialize and create the sram object from sram import sram s = sram(name=OPTS.output_name, sram_config=c) -s.create() # Generate stimulus and run functional simulation on the design start_time = datetime.datetime.now() diff --git a/compiler/gen_stimulus.py b/compiler/gen_stimulus.py index d69d867d..c9b4e350 100755 --- a/compiler/gen_stimulus.py +++ b/compiler/gen_stimulus.py @@ -60,7 +60,6 @@ OPTS.openram_temp = OPTS.output_path from sram import sram s = sram(name=OPTS.output_name, sram_config=c) -s.create() from characterizer import delay import tech diff --git a/compiler/openram.py b/compiler/openram.py index 74f80128..240a3f9f 100755 --- a/compiler/openram.py +++ b/compiler/openram.py @@ -72,13 +72,10 @@ debug.print_raw("Output files are: ") for path in output_files: debug.print_raw(path) - +# Initialize the SRAM s = sram(name=OPTS.output_name, sram_config=c) -# Actually build the SRAM -s.create() - -# Output the files for the resulting SRAM +# Generate and output the files for the resulting SRAM s.save() # Delete temp files etc. diff --git a/compiler/sram/sram.py b/compiler/sram/sram.py index fdc8ec76..afa8cd58 100644 --- a/compiler/sram/sram.py +++ b/compiler/sram/sram.py @@ -40,6 +40,8 @@ class sram(): from design import design design.name_map=[] + self.create() + def create(self): debug.info(2, "create sram of size {0} with {1} num of words {2} banks".format(self.word_size, self.num_words, From ef710eae7aab2dcba4a415f8bd0ce52d31971580 Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Fri, 4 Mar 2022 13:53:20 -0800 Subject: [PATCH 011/130] reorder sram __init__() argument order for tests that rely on the order --- compiler/sram/sram.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/sram/sram.py b/compiler/sram/sram.py index afa8cd58..627f58bd 100644 --- a/compiler/sram/sram.py +++ b/compiler/sram/sram.py @@ -21,7 +21,7 @@ class sram(): results. We can later add visualizer and other high-level functions as needed. """ - def __init__(self, name, sram_config): + def __init__(self, sram_config, name): self.name = name self.config = sram_config From 4514927a7b40851812037852050d08193a620720 Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Wed, 9 Mar 2022 09:43:00 -0800 Subject: [PATCH 012/130] log sim result after func_sim --- compiler/func_sim_existing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/func_sim_existing.py b/compiler/func_sim_existing.py index 0d693e91..7616fc81 100755 --- a/compiler/func_sim_existing.py +++ b/compiler/func_sim_existing.py @@ -61,8 +61,8 @@ from characterizer import functional debug.print_raw("Functional simulation... ") f = functional(s.s, cycles=cycles, spfile=s.get_sp_name(), period=period, output_path=OPTS.openram_temp) (fail, error) = f.run() +debug.print_raw(error) print_time("Functional simulation", datetime.datetime.now(), start_time) -print(error) # Delete temp files, remove the dir, etc. after success if fail: From 06cd2620f54c713637a31c314d69fe9d08403b14 Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Thu, 14 Apr 2022 10:04:07 -0700 Subject: [PATCH 013/130] force netlist only mode in memchar memfunc, rename char and func scripts, add description for func script --- compiler/{characterize_existing.py => memchar.py} | 2 ++ compiler/{func_sim_existing.py => memfunc.py} | 10 ++++++---- 2 files changed, 8 insertions(+), 4 deletions(-) rename compiler/{characterize_existing.py => memchar.py} (98%) rename compiler/{func_sim_existing.py => memfunc.py} (86%) diff --git a/compiler/characterize_existing.py b/compiler/memchar.py similarity index 98% rename from compiler/characterize_existing.py rename to compiler/memchar.py index 73a7c235..d824e5a6 100755 --- a/compiler/characterize_existing.py +++ b/compiler/memchar.py @@ -46,6 +46,8 @@ c = sram_config(word_size=OPTS.word_size, num_spare_rows=OPTS.num_spare_rows, num_spare_cols=OPTS.num_spare_cols) +OPTS.netlist_only = True + # Initialize and create the sram object from sram import sram s = sram(name=OPTS.output_name, sram_config=c) diff --git a/compiler/func_sim_existing.py b/compiler/memfunc.py similarity index 86% rename from compiler/func_sim_existing.py rename to compiler/memfunc.py index 7616fc81..7d8ed83e 100755 --- a/compiler/func_sim_existing.py +++ b/compiler/memfunc.py @@ -7,10 +7,10 @@ # All rights reserved. # """ -This script will characterize an SRAM previously generated by OpenRAM given a -configuration file. Configuration option "use_pex" determines whether extracted -or generated spice is used and option "analytical_delay" determines whether -an analytical model or spice simulation is used for characterization. +This script will functionally simulate an SRAM previously generated by OpenRAM +given a configuration file. Configuration option "use_pex" determines whether +extracted or generated spice is used. Command line arguments dictate the +number of cycles and period to be simulated. """ import sys @@ -51,6 +51,8 @@ c = sram_config(word_size=OPTS.word_size, num_spare_rows=OPTS.num_spare_rows, num_spare_cols=OPTS.num_spare_cols) +OPTS.netlist_only = True + # Initialize and create the sram object from sram import sram s = sram(name=OPTS.output_name, sram_config=c) From 9ec87c4d526671e3f9938f6b3f40b4195f008d5f Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Thu, 14 Apr 2022 10:13:48 -0700 Subject: [PATCH 014/130] disable lvs/drc in char and func scripts --- compiler/memchar.py | 1 + compiler/memfunc.py | 1 + 2 files changed, 2 insertions(+) diff --git a/compiler/memchar.py b/compiler/memchar.py index d824e5a6..b5eb4909 100755 --- a/compiler/memchar.py +++ b/compiler/memchar.py @@ -47,6 +47,7 @@ c = sram_config(word_size=OPTS.word_size, num_spare_cols=OPTS.num_spare_cols) OPTS.netlist_only = True +OPTS.check_lvsdrc = False # Initialize and create the sram object from sram import sram diff --git a/compiler/memfunc.py b/compiler/memfunc.py index 7d8ed83e..87686455 100755 --- a/compiler/memfunc.py +++ b/compiler/memfunc.py @@ -52,6 +52,7 @@ c = sram_config(word_size=OPTS.word_size, num_spare_cols=OPTS.num_spare_cols) OPTS.netlist_only = True +OPTS.check_lvsdrc = False # Initialize and create the sram object from sram import sram From 45df34c7747d199e59e7e26b0c6b38dfb392cd0c Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Thu, 21 Apr 2022 13:06:13 -0700 Subject: [PATCH 015/130] add tests --- compiler/tests/30_memchar_test.py | 95 ++++++++++++++++++ compiler/tests/30_memfunc_test.py | 98 +++++++++++++++++++ .../tests/configs/config_mem_char_func.py | 16 +++ 3 files changed, 209 insertions(+) create mode 100755 compiler/tests/30_memchar_test.py create mode 100755 compiler/tests/30_memfunc_test.py create mode 100644 compiler/tests/configs/config_mem_char_func.py diff --git a/compiler/tests/30_memchar_test.py b/compiler/tests/30_memchar_test.py new file mode 100755 index 00000000..faca2154 --- /dev/null +++ b/compiler/tests/30_memchar_test.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python3 +# See LICENSE for licensing information. +# +# Copyright (c) 2016-2021 Regents of the University of California and The Board +# of Regents for the Oklahoma Agricultural and Mechanical College +# (acting for and on behalf of Oklahoma State University) +# All rights reserved. +# +import unittest +from testutils import * +import sys, os, re, shutil +sys.path.append(os.getenv("OPENRAM_HOME")) +import globals +from globals import OPTS +import debug +import getpass + + +class openram_front_end_test(openram_test): + + def runTest(self): + OPENRAM_HOME = os.path.abspath(os.environ.get("OPENRAM_HOME")) + config_file = "{}/tests/configs/config_mem_char_func".format(os.getenv("OPENRAM_HOME")) + globals.init_openram(config_file) + + debug.info(1, "Testing commandline characterizer script memchar.py with 2-bit, 16 word SRAM.") + out_file = "testsram" + out_path = "/tmp/testsram_{0}_{1}_{2}".format(OPTS.tech_name, getpass.getuser(), os.getpid()) + + # make sure we start without the files existing + if os.path.exists(out_path): + shutil.rmtree(out_path, ignore_errors=True) + self.assertEqual(os.path.exists(out_path), False) + + try: + os.makedirs(out_path, 0o0750) + except OSError as e: + if e.errno == 17: # errno.EEXIST + os.chmod(out_path, 0o0750) + + # specify the same verbosity for the system call + options = "" + for i in range(OPTS.verbose_level): + options += " -v" + + if OPTS.spice_name: + options += " -s {}".format(OPTS.spice_name) + + if OPTS.tech_name: + options += " -t {}".format(OPTS.tech_name) + + options += " -j 2" + + # Always perform code coverage + if OPTS.coverage == 0: + debug.warning("Failed to find coverage installation. This can be installed with pip3 install coverage") + exe_name = "{0}/memchar.py ".format(OPENRAM_HOME) + else: + exe_name = "{0}{1}/memchar.py ".format(OPTS.coverage_exe, OPENRAM_HOME) + config_name = "{0}/tests/configs/config_mem_char_func.py".format(OPENRAM_HOME) + cmd = "{0} -n -o {1} -p {2} {3} {4} 2>&1 > {5}/output.log".format(exe_name, + out_file, + out_path, + options, + config_name, + out_path) + debug.info(1, cmd) + os.system(cmd) + + # Make sure there is any .lib file + import glob + files = glob.glob('{0}/*.lib'.format(out_path)) + self.assertTrue(len(files)>0) + + # grep any errors from the output + output_log = open("{0}/output.log".format(out_path), "r") + output = output_log.read() + output_log.close() + self.assertEqual(len(re.findall('ERROR', output)), 0) + self.assertEqual(len(re.findall('WARNING', output)), 0) + + # now clean up the directory + if not OPTS.keep_temp: + if os.path.exists(out_path): + shutil.rmtree(out_path, ignore_errors=True) + self.assertEqual(os.path.exists(out_path), False) + + globals.end_openram() + +# run the test from the command line +if __name__ == "__main__": + (OPTS, args) = globals.parse_args() + del sys.argv[1:] + header(__file__, OPTS.tech_name) + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/30_memfunc_test.py b/compiler/tests/30_memfunc_test.py new file mode 100755 index 00000000..c9cf6eb8 --- /dev/null +++ b/compiler/tests/30_memfunc_test.py @@ -0,0 +1,98 @@ +#!/usr/bin/env python3 +# See LICENSE for licensing information. +# +# Copyright (c) 2016-2021 Regents of the University of California and The Board +# of Regents for the Oklahoma Agricultural and Mechanical College +# (acting for and on behalf of Oklahoma State University) +# All rights reserved. +# +from asyncio import subprocess +import unittest +from testutils import * +import sys, os, re, shutil +sys.path.append(os.getenv("OPENRAM_HOME")) +import globals +from globals import OPTS +import debug +import getpass + + +class openram_front_end_test(openram_test): + + def runTest(self): + OPENRAM_HOME = os.path.abspath(os.environ.get("OPENRAM_HOME")) + config_file = "{}/tests/configs/config_mem_char_func".format(os.getenv("OPENRAM_HOME")) + globals.init_openram(config_file) + + debug.info(1, "Testing commandline functional simulator script memfunc.py with 2-bit, 16 word SRAM.") + out_file = "testsram" + out_path = "/tmp/testsram_{0}_{1}_{2}".format(OPTS.tech_name, getpass.getuser(), os.getpid()) + + # make sure we start without the files existing + if os.path.exists(out_path): + shutil.rmtree(out_path, ignore_errors=True) + self.assertEqual(os.path.exists(out_path), False) + + try: + os.makedirs(out_path, 0o0750) + except OSError as e: + if e.errno == 17: # errno.EEXIST + os.chmod(out_path, 0o0750) + + # copy the 2x16 sram spice file into out_path because memfunc.py expects it there + sp_src_file = "{0}/tests/golden/sram_2_16_1_{1}.sp".format(OPENRAM_HOME, OPTS.tech_name) + sp_dst_file = out_path + "/" + OPTS.output_name + ".sp" + shutil.copy(sp_src_file, sp_dst_file) + + # specify the same verbosity for the system call + options = "" + for i in range(OPTS.verbose_level): + options += " -v" + + if OPTS.spice_name: + options += " -s {}".format(OPTS.spice_name) + + if OPTS.tech_name: + options += " -t {}".format(OPTS.tech_name) + + options += " -j 2" + + # Always perform code coverage + if OPTS.coverage == 0: + debug.warning("Failed to find coverage installation. This can be installed with pip3 install coverage") + exe_name = "{0}/memfunc.py ".format(OPENRAM_HOME) + else: + exe_name = "{0}{1}/memfunc.py ".format(OPTS.coverage_exe, OPENRAM_HOME) + config_name = "{0}/tests/configs/config_mem_char_func.py".format(OPENRAM_HOME) + period_and_cycles = 10 + cmd = "{0} -n -o {1} -p {2} {3} {4} {5} {5} 2>&1 > {6}/output.log".format(exe_name, + out_file, + out_path, + options, + config_name, + period_and_cycles, + out_path) + debug.info(1, cmd) + os.system(cmd) + + # grep any errors from the output + output_log = open("{0}/output.log".format(out_path), "r") + output = output_log.read() + output_log.close() + self.assertEqual(len(re.findall('ERROR', output)), 0) + self.assertEqual(len(re.findall('WARNING', output)), 0) + + # now clean up the directory + if not OPTS.keep_temp: + if os.path.exists(out_path): + shutil.rmtree(out_path, ignore_errors=True) + self.assertEqual(os.path.exists(out_path), False) + + globals.end_openram() + +# run the test from the command line +if __name__ == "__main__": + (OPTS, args) = globals.parse_args() + del sys.argv[1:] + header(__file__, OPTS.tech_name) + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/configs/config_mem_char_func.py b/compiler/tests/configs/config_mem_char_func.py new file mode 100644 index 00000000..a825acfc --- /dev/null +++ b/compiler/tests/configs/config_mem_char_func.py @@ -0,0 +1,16 @@ +# See LICENSE for licensing information. +# +# Copyright (c) 2016-2021 Regents of the University of California and The Board +# of Regents for the Oklahoma Agricultural and Mechanical College +# (acting for and on behalf of Oklahoma State University) +# All rights reserved. +# +from globals import OPTS +word_size = 2 +num_words = 16 + +tech_name = OPTS.tech_name +output_name = "sram" + +nominal_corner_only = True +spice_name = "ngspice" From 9aafada1abdf04b29188db2e5b8efc37fd6928a0 Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Thu, 19 May 2022 09:07:45 -0700 Subject: [PATCH 016/130] Fake SRAM and Xyce RAW file option --- compiler/characterizer/fake_sram.py | 61 +++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 compiler/characterizer/fake_sram.py diff --git a/compiler/characterizer/fake_sram.py b/compiler/characterizer/fake_sram.py new file mode 100644 index 00000000..c114d790 --- /dev/null +++ b/compiler/characterizer/fake_sram.py @@ -0,0 +1,61 @@ +import sram_config + +class fake_sram(sram_config.sram_config): + """ This is an SRAM that doesn't actually create itself, just computes + the sizes. """ + def __init__(self, word_size, num_words, num_banks, name, num_spare_rows): + self.name = name + self.word_size = word_size + self.num_words = num_words + self.num_banks = num_banks + self.num_spare_rows = num_spare_rows + # TODO: Get width and height from gds bbox + self.width = 0 + self.height = 0 + #c = reload(__import__(OPTS.bitcell)) + #self.mod_bitcell = getattr(c, OPTS.bitcell) + #self.bitcell = self.mod_bitcell() + # to get the row, col, etc. + self.compute_sizes() + self.setup_multiport_constants() + + def setup_multiport_constants(self): + """ + Taken from ../base/design.py + These are contants and lists that aid multiport design. + Ports are always in the order RW, W, R. + Port indices start from 0 and increment. + A first RW port will have clk0, csb0, web0, addr0, data0 + A first W port (with no RW ports) will be: clk0, csb0, addr0, data0 + + """ + total_ports = OPTS.num_rw_ports + OPTS.num_w_ports + OPTS.num_r_ports + + # These are the read/write port indices. + self.readwrite_ports = [] + # These are the read/write and write-only port indices + self.write_ports = [] + # These are the write-only port indices. + self.writeonly_ports = [] + # These are the read/write and read-only port indices + self.read_ports = [] + # These are the read-only port indices. + self.readonly_ports = [] + # These are all the ports + self.all_ports = list(range(total_ports)) + + # The order is always fixed as RW, W, R + port_number = 0 + for port in range(OPTS.num_rw_ports): + self.readwrite_ports.append(port_number) + self.write_ports.append(port_number) + self.read_ports.append(port_number) + port_number += 1 + for port in range(OPTS.num_w_ports): + self.write_ports.append(port_number) + self.writeonly_ports.append(port_number) + port_number += 1 + for port in range(OPTS.num_r_ports): + self.read_ports.append(port_number) + self.readonly_ports.append(port_number) + port_number += 1 From 471f68fab2d5797be6444ae73668c2859763d2c8 Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Mon, 23 May 2022 10:56:22 -0700 Subject: [PATCH 017/130] Characterizer options --- compiler/options.py | 2 ++ compiler/tests/sram_1b_16_1rw_scn4m_subm.log | 2 ++ 2 files changed, 4 insertions(+) create mode 100644 compiler/tests/sram_1b_16_1rw_scn4m_subm.log diff --git a/compiler/options.py b/compiler/options.py index f3c19283..b7ce0f54 100644 --- a/compiler/options.py +++ b/compiler/options.py @@ -91,6 +91,8 @@ class options(optparse.Values): sim_data_path = None # A list of load/slew tuples use_specified_load_slew = None + # Spice simulation raw file + spice_raw_file = None ################### # Run-time vs accuracy options. diff --git a/compiler/tests/sram_1b_16_1rw_scn4m_subm.log b/compiler/tests/sram_1b_16_1rw_scn4m_subm.log new file mode 100644 index 00000000..0164bbb4 --- /dev/null +++ b/compiler/tests/sram_1b_16_1rw_scn4m_subm.log @@ -0,0 +1,2 @@ +ERROR: file magic.py: line 358: sram LVS mismatch (results in /tmp/openram_bugra_14157_temp/sram.lvs.report) + From 28128157c08f1670def9e7384665acaaec3ef703 Mon Sep 17 00:00:00 2001 From: mrg Date: Wed, 16 Feb 2022 10:54:39 -0800 Subject: [PATCH 018/130] Initial work on separate delay and func simulation --- compiler/base/design.py | 2 - compiler/gen_stimulus.py | 40 +++++++++---------- compiler/modules/sram.py | 68 ++++++++++++++++++--------------- compiler/modules/sram_base.py | 5 +-- compiler/modules/sram_config.py | 53 ++++++++++++++++++++++++- compiler/openram.py | 2 - 6 files changed, 108 insertions(+), 62 deletions(-) diff --git a/compiler/base/design.py b/compiler/base/design.py index 89f7ba82..e83f2439 100644 --- a/compiler/base/design.py +++ b/compiler/base/design.py @@ -126,5 +126,3 @@ class design(hierarchy_design): for inst in self.insts: total_module_power += inst.mod.analytical_power(corner, load) return total_module_power - - diff --git a/compiler/gen_stimulus.py b/compiler/gen_stimulus.py index 69e53cd8..d69d867d 100755 --- a/compiler/gen_stimulus.py +++ b/compiler/gen_stimulus.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # See LICENSE for licensing information. # # Copyright (c) 2016-2021 Regents of the University of California and The Board @@ -15,6 +15,7 @@ corner, but should probably be extended. import sys from globals import * +from importlib import reload (OPTS, args) = parse_args() @@ -41,36 +42,30 @@ slew = float(args[3]) import debug init_openram(config_file=config_file, is_unit_test=False) + +from sram_config import sram_config +c = sram_config(word_size=OPTS.word_size, + num_words=OPTS.num_words, + write_size=OPTS.write_size, + num_banks=OPTS.num_banks, + words_per_row=OPTS.words_per_row, + num_spare_rows=OPTS.num_spare_rows, + num_spare_cols=OPTS.num_spare_cols) + +OPTS.netlist_only = True OPTS.check_lvsdrc = False # Put the temp output in the output path since it is what we want to generate! old_openram_temp = OPTS.openram_temp OPTS.openram_temp = OPTS.output_path - - -import sram -class fake_sram(sram.sram): - """ This is an SRAM that doesn't actually create itself, just computes - the sizes. """ - def __init__(self, word_size, num_words, num_banks, name, num_spare_rows): - self.name = name - self.word_size = word_size - self.num_words = num_words - self.num_banks = num_banks - self.num_spare_rows = num_spare_rows - c = reload(__import__(OPTS.bitcell)) - self.mod_bitcell = getattr(c, OPTS.bitcell) - self.bitcell = self.mod_bitcell() - # to get the row, col, etc. - self.compute_sizes() - -sram = fake_sram(OPTS.word_size, OPTS.num_words, OPTS.num_banks, OPTS.output_name) -sp_file = OPTS.output_path+OPTS.output_name + ".sp" +from sram import sram +s = sram(name=OPTS.output_name, sram_config=c) +s.create() from characterizer import delay import tech # Set up the delay and set to the nominal corner -d = delay.delay(sram, sp_file, ("TT", tech.spice["nom_supply_voltage"], tech.spice["nom_temperature"])) +d = delay(s, s.get_sp_name(), ("TT", tech.spice["nom_supply_voltage"], tech.spice["nom_temperature"])) # Set the period d.period = period # Set the load of outputs and slew of inputs @@ -91,4 +86,3 @@ print("Output files are:\n{0}stim.sp\n{0}sram.sp\n{0}reduced.sp".format(OPTS.out OPTS.openram_temp = old_openram_temp # Delete temp files, remove the dir, etc. end_openram() - diff --git a/compiler/modules/sram.py b/compiler/modules/sram.py index 167a54e5..0b90a704 100644 --- a/compiler/modules/sram.py +++ b/compiler/modules/sram.py @@ -20,22 +20,30 @@ class sram(): results. We can later add visualizer and other high-level functions as needed. """ - def __init__(self, sram_config, name): + def __init__(self, name, sram_config): + self.name = name + self.config = sram_config sram_config.set_local_config(self) + self.sp_name = OPTS.output_path + self.name + ".sp" + self.lvs_name = OPTS.output_path + self.name + ".lvs.sp" + self.pex_name = OPTS.output_path + self.name + ".pex.sp" + self.gds_name = OPTS.output_path + self.name + ".gds" + self.lef_name = OPTS.output_path + self.name + ".lef" + self.v_name = OPTS.output_path + self.name + ".v" + # reset the static duplicate name checker for unit tests # in case we create more than one SRAM from base import design design.name_map=[] + def create(self): debug.info(2, "create sram of size {0} with {1} num of words {2} banks".format(self.word_size, self.num_words, self.num_banks)) start_time = datetime.datetime.now() - self.name = name - if self.num_banks == 1: from .sram_1bank import sram_1bank as sram elif self.num_banks == 2: @@ -43,7 +51,8 @@ class sram(): else: debug.error("Invalid number of banks.", -1) - self.s = sram(name, sram_config) + self.s = sram(name=self.name, + sram_config=self.config) self.s.create_netlist() if not OPTS.netlist_only: self.s.create_layout() @@ -51,6 +60,14 @@ class sram(): if not OPTS.is_unit_test: print_time("SRAM creation", datetime.datetime.now(), start_time) + def get_sp_name(self): + if OPTS.use_pex: + # Use the extracted spice file + return self.pex_name + else: + # Use generated spice file for characterization + return self.sp_name + def sp_write(self, name, lvs=False, trim=False): self.s.sp_write(name, lvs, trim) @@ -84,11 +101,10 @@ class sram(): # Save the spice file start_time = datetime.datetime.now() - spname = OPTS.output_path + self.s.name + ".sp" - debug.print_raw("SP: Writing to {0}".format(spname)) - self.sp_write(spname) + debug.print_raw("SP: Writing to {0}".format(self.sp_name)) + self.sp_write(self.sp_name) functional(self.s, - os.path.basename(spname), + os.path.basename(self.sp_name), cycles=200, output_path=OPTS.output_path) print_time("Spice writing", datetime.datetime.now(), start_time) @@ -96,12 +112,11 @@ class sram(): if not OPTS.netlist_only: # Write the layout start_time = datetime.datetime.now() - gdsname = OPTS.output_path + self.s.name + ".gds" - debug.print_raw("GDS: Writing to {0}".format(gdsname)) - self.gds_write(gdsname) + debug.print_raw("GDS: Writing to {0}".format(self.gds_name)) + self.gds_write(self.gds_name) if OPTS.check_lvsdrc: verify.write_drc_script(cell_name=self.s.name, - gds_name=os.path.basename(gdsname), + gds_name=os.path.basename(self.gds_name), extract=True, final_verification=True, output_path=OPTS.output_path) @@ -109,20 +124,18 @@ class sram(): # Create a LEF physical model start_time = datetime.datetime.now() - lefname = OPTS.output_path + self.s.name + ".lef" - debug.print_raw("LEF: Writing to {0}".format(lefname)) - self.lef_write(lefname) + debug.print_raw("LEF: Writing to {0}".format(self.lef_name)) + self.lef_write(self.lef_name) print_time("LEF", datetime.datetime.now(), start_time) # Save the LVS file start_time = datetime.datetime.now() - lvsname = OPTS.output_path + self.s.name + ".lvs.sp" - debug.print_raw("LVS: Writing to {0}".format(lvsname)) - self.sp_write(lvsname, lvs=True) + debug.print_raw("LVS: Writing to {0}".format(self.lvs_name)) + self.sp_write(self.lvs_name, lvs=True) if not OPTS.netlist_only and OPTS.check_lvsdrc: verify.write_lvs_script(cell_name=self.s.name, - gds_name=os.path.basename(gdsname), - sp_name=os.path.basename(lvsname), + gds_name=os.path.basename(self.gds_name), + sp_name=os.path.basename(self.lvs_name), final_verification=True, output_path=OPTS.output_path) print_time("LVS writing", datetime.datetime.now(), start_time) @@ -131,14 +144,8 @@ class sram(): if OPTS.use_pex: start_time = datetime.datetime.now() # Output the extracted design if requested - pexname = OPTS.output_path + self.s.name + ".pex.sp" - spname = OPTS.output_path + self.s.name + ".sp" - verify.run_pex(self.s.name, gdsname, spname, output=pexname) - sp_file = pexname + verify.run_pex(self.s.name, self.gds_name, self.sp_name, output=self.pex_name) print_time("Extraction", datetime.datetime.now(), start_time) - else: - # Use generated spice file for characterization - sp_file = spname # Save a functional simulation file @@ -146,7 +153,7 @@ class sram(): start_time = datetime.datetime.now() from characterizer import lib debug.print_raw("LIB: Characterizing... ") - lib(out_dir=OPTS.output_path, sram=self.s, sp_file=sp_file) + lib(out_dir=OPTS.output_path, sram=self.s, sp_file=self.get_sp_name()) print_time("Characterization", datetime.datetime.now(), start_time) # Write the config file @@ -166,9 +173,8 @@ class sram(): # Write a verilog model start_time = datetime.datetime.now() - vname = OPTS.output_path + self.s.name + ".v" - debug.print_raw("Verilog: Writing to {0}".format(vname)) - self.verilog_write(vname) + debug.print_raw("Verilog: Writing to {0}".format(self.v_name)) + self.verilog_write(self.v_name) print_time("Verilog", datetime.datetime.now(), start_time) # Write out options if specified diff --git a/compiler/modules/sram_base.py b/compiler/modules/sram_base.py index 722a649d..260b9e34 100644 --- a/compiler/modules/sram_base.py +++ b/compiler/modules/sram_base.py @@ -20,8 +20,7 @@ from tech import spice class sram_base(design, verilog, lef): """ - Dynamically generated SRAM by connecting banks to control logic. The - number of banks should be 1 , 2 or 4 + Dynamically generated SRAM by connecting banks to control logic. """ def __init__(self, name, sram_config): design.__init__(self, name) @@ -30,6 +29,7 @@ class sram_base(design, verilog, lef): self.sram_config = sram_config sram_config.set_local_config(self) + sram_config.compute_sizes() self.bank_insts = [] @@ -41,7 +41,6 @@ class sram_base(design, verilog, lef): if not self.num_spare_cols: self.num_spare_cols = 0 - def add_pins(self): """ Add pins for entire SRAM. """ diff --git a/compiler/modules/sram_config.py b/compiler/modules/sram_config.py index 4c1bb117..a65387fb 100644 --- a/compiler/modules/sram_config.py +++ b/compiler/modules/sram_config.py @@ -14,7 +14,8 @@ from sram_factory import factory class sram_config: """ This is a structure that is used to hold the SRAM configuration options. """ - def __init__(self, word_size, num_words, write_size=None, num_banks=1, words_per_row=None, num_spare_rows=0, num_spare_cols=0): + def __init__(self, word_size, num_words, write_size=None, num_banks=1, + words_per_row=None, num_spare_rows=0, num_spare_cols=0): self.word_size = word_size self.num_words = num_words # Don't add a write mask if it is the same size as the data word @@ -37,6 +38,16 @@ class sram_config: except ImportError: self.array_col_multiple = 1 + if self.write_size: + self.num_wmasks = int(ceil(self.word_size / self.write_size)) + else: + self.num_wmasks = 0 + + if not self.num_spare_cols: + self.num_spare_cols = 0 + + if not self.num_spare_rows: + self.num_spare_rows = 0 # This will get over-written when we determine the organization self.words_per_row = words_per_row @@ -167,3 +178,43 @@ class sram_config: return int(words_per_row * tentative_num_rows / 16) return words_per_row + + def setup_multiport_constants(self): + """ + These are contants and lists that aid multiport design. + Ports are always in the order RW, W, R. + Port indices start from 0 and increment. + A first RW port will have clk0, csb0, web0, addr0, data0 + A first W port (with no RW ports) will be: clk0, csb0, addr0, data0 + + """ + total_ports = OPTS.num_rw_ports + OPTS.num_w_ports + OPTS.num_r_ports + + # These are the read/write port indices. + self.readwrite_ports = [] + # These are the read/write and write-only port indices + self.write_ports = [] + # These are the write-only port indices. + self.writeonly_ports = [] + # These are the read/write and read-only port indices + self.read_ports = [] + # These are the read-only port indices. + self.readonly_ports = [] + # These are all the ports + self.all_ports = list(range(total_ports)) + + # The order is always fixed as RW, W, R + port_number = 0 + for port in range(OPTS.num_rw_ports): + self.readwrite_ports.append(port_number) + self.write_ports.append(port_number) + self.read_ports.append(port_number) + port_number += 1 + for port in range(OPTS.num_w_ports): + self.write_ports.append(port_number) + self.writeonly_ports.append(port_number) + port_number += 1 + for port in range(OPTS.num_r_ports): + self.read_ports.append(port_number) + self.readonly_ports.append(port_number) + port_number += 1 diff --git a/compiler/openram.py b/compiler/openram.py index fbbf4466..2e460668 100755 --- a/compiler/openram.py +++ b/compiler/openram.py @@ -83,5 +83,3 @@ s.save() # Delete temp files etc. g.end_openram() g.print_time("End", datetime.datetime.now(), start_time) - - From e2a52ec0f37e71bf9e8f6cae45ac961e5e421beb Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Tue, 1 Mar 2022 15:12:03 -0800 Subject: [PATCH 019/130] Adding characterizer executable --- compiler/characterize_existing.py | 64 +++++++++++++++++++++++++++++++ compiler/modules/sram.py | 5 ++- 2 files changed, 67 insertions(+), 2 deletions(-) create mode 100755 compiler/characterize_existing.py diff --git a/compiler/characterize_existing.py b/compiler/characterize_existing.py new file mode 100755 index 00000000..82e95b1b --- /dev/null +++ b/compiler/characterize_existing.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python3 +# See LICENSE for licensing information. +# +# Copyright (c) 2016-2021 Regents of the University of California and The Board +# of Regents for the Oklahoma Agricultural and Mechanical College +# (acting for and on behalf of Oklahoma State University) +# All rights reserved. +# +""" +This script will characterize an SRAM previously generated by OpenRAM given a +configuration file. Configuration option "use_pex" determines whether extracted +or generated spice is used and option "analytical_delay" determines whether +an analytical model or spice simulation is used for characterization. +""" + +import sys +import datetime +from globals import * +from importlib import reload + +(OPTS, args) = parse_args() + +# Override the usage +USAGE = "Usage: {} [options] \nUse -h for help.\n".format(__file__) + +# Check that we are left with a single configuration file as argument. +if len(args) != 1: + print(USAGE) + sys.exit(2) + +# These depend on arguments, so don't load them until now. +import debug + +# Parse config file and set up all the options +init_openram(config_file=args[0], is_unit_test=False) + +# Configure the SRAM organization (duplicated from openram.py) +from sram_config import sram_config +c = sram_config(word_size=OPTS.word_size, + num_words=OPTS.num_words, + write_size=OPTS.write_size, + num_banks=OPTS.num_banks, + words_per_row=OPTS.words_per_row, + num_spare_rows=OPTS.num_spare_rows, + num_spare_cols=OPTS.num_spare_cols) + +# Initialize and create the sram object +from sram import sram +s = sram(name=OPTS.output_name, sram_config=c) +s.create() + +# Characterize the design +start_time = datetime.datetime.now() +from characterizer import lib +debug.print_raw("LIB: Characterizing... ") +lib(out_dir=OPTS.output_path, sram=s.s, sp_file=s.get_sp_name()) +print_time("Characterization", datetime.datetime.now(), start_time) + +# Output info about this run +print("Output file is:\n{0}.lib".format(OPTS.output_path)) +#report_status() #could modify this function to provide relevant info + +# Delete temp files, remove the dir, etc. +end_openram() diff --git a/compiler/modules/sram.py b/compiler/modules/sram.py index 0b90a704..127c1b9d 100644 --- a/compiler/modules/sram.py +++ b/compiler/modules/sram.py @@ -24,6 +24,7 @@ class sram(): self.name = name self.config = sram_config + sram_config.setup_multiport_constants() sram_config.set_local_config(self) self.sp_name = OPTS.output_path + self.name + ".sp" @@ -103,6 +104,8 @@ class sram(): start_time = datetime.datetime.now() debug.print_raw("SP: Writing to {0}".format(self.sp_name)) self.sp_write(self.sp_name) + + # Save a functional simulation file with default period functional(self.s, os.path.basename(self.sp_name), cycles=200, @@ -147,8 +150,6 @@ class sram(): verify.run_pex(self.s.name, self.gds_name, self.sp_name, output=self.pex_name) print_time("Extraction", datetime.datetime.now(), start_time) - # Save a functional simulation file - # Characterize the design start_time = datetime.datetime.now() from characterizer import lib From 8793dda40a5b0d0aeedfaee4753673c471e0ad5e Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Wed, 2 Mar 2022 12:18:54 -0800 Subject: [PATCH 020/130] characterizer and functional simulator working from command line --- compiler/characterize_existing.py | 2 + compiler/characterizer/functional.py | 7 +-- compiler/func_sim_existing.py | 70 ++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 3 deletions(-) create mode 100755 compiler/func_sim_existing.py diff --git a/compiler/characterize_existing.py b/compiler/characterize_existing.py index 82e95b1b..f6c83c4b 100755 --- a/compiler/characterize_existing.py +++ b/compiler/characterize_existing.py @@ -34,6 +34,8 @@ import debug # Parse config file and set up all the options init_openram(config_file=args[0], is_unit_test=False) +print_banner() + # Configure the SRAM organization (duplicated from openram.py) from sram_config import sram_config c = sram_config(word_size=OPTS.word_size, diff --git a/compiler/characterizer/functional.py b/compiler/characterizer/functional.py index e7d03f25..3bc94ab7 100644 --- a/compiler/characterizer/functional.py +++ b/compiler/characterizer/functional.py @@ -36,9 +36,6 @@ class functional(simulation): if not corner: corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0]) - if period: - self.period = period - if not output_path: self.output_path = OPTS.openram_temp else: @@ -73,6 +70,10 @@ class functional(simulation): self.set_spice_constants() self.set_stimulus_variables() + # Override default period + if period: + self.period = period + # For the debug signal names self.wordline_row = 0 self.bitline_column = 0 diff --git a/compiler/func_sim_existing.py b/compiler/func_sim_existing.py new file mode 100755 index 00000000..ec89c3d7 --- /dev/null +++ b/compiler/func_sim_existing.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python3 +# See LICENSE for licensing information. +# +# Copyright (c) 2016-2021 Regents of the University of California and The Board +# of Regents for the Oklahoma Agricultural and Mechanical College +# (acting for and on behalf of Oklahoma State University) +# All rights reserved. +# +""" +This script will characterize an SRAM previously generated by OpenRAM given a +configuration file. Configuration option "use_pex" determines whether extracted +or generated spice is used and option "analytical_delay" determines whether +an analytical model or spice simulation is used for characterization. +""" + +import sys +import datetime +from globals import * +from importlib import reload + +(OPTS, args) = parse_args() + +# Override the usage +USAGE = "Usage: {} [options] \nUse -h for help.\n".format(__file__) + +# Check that we are left with a single configuration file as argument. +if len(args) != 3: + print(USAGE) + sys.exit(2) + +# Parse argument +config_file = args[0] +cycles = int(args[1]) +period = float(args[2]) + +# These depend on arguments, so don't load them until now. +import debug + +# Parse config file and set up all the options +init_openram(config_file=config_file, is_unit_test=False) + +print_banner() + +# Configure the SRAM organization (duplicated from openram.py) +from sram_config import sram_config +c = sram_config(word_size=OPTS.word_size, + num_words=OPTS.num_words, + write_size=OPTS.write_size, + num_banks=OPTS.num_banks, + words_per_row=OPTS.words_per_row, + num_spare_rows=OPTS.num_spare_rows, + num_spare_cols=OPTS.num_spare_cols) + +# Initialize and create the sram object +from sram import sram +s = sram(name=OPTS.output_name, sram_config=c) +s.create() + +# Generate stimulus and run functional simulation on the design +start_time = datetime.datetime.now() +from characterizer import functional +debug.print_raw("Functional simulation... ") +f = functional(s.s, cycles=cycles, spfile=s.get_sp_name(), period=period, output_path=OPTS.openram_temp) +(fail, error) = f.run() +print_time("Functional simulation", datetime.datetime.now(), start_time) +print(error) + +# Delete temp files, remove the dir, etc. after success +if fail: + end_openram() From 2bbd293bf24f3e278af1a0f2e3cc971dcc72438b Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Wed, 2 Mar 2022 12:47:05 -0800 Subject: [PATCH 021/130] clarify file location message for user --- compiler/characterize_existing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/characterize_existing.py b/compiler/characterize_existing.py index f6c83c4b..c8456b9f 100755 --- a/compiler/characterize_existing.py +++ b/compiler/characterize_existing.py @@ -59,7 +59,7 @@ lib(out_dir=OPTS.output_path, sram=s.s, sp_file=s.get_sp_name()) print_time("Characterization", datetime.datetime.now(), start_time) # Output info about this run -print("Output file is:\n{0}.lib".format(OPTS.output_path)) +print("Output files are:\n{0}*.lib".format(OPTS.output_path)) #report_status() #could modify this function to provide relevant info # Delete temp files, remove the dir, etc. From 34ee709c692adff96d10d101a69cd21e47110e0d Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Wed, 2 Mar 2022 16:38:39 -0800 Subject: [PATCH 022/130] call create() function from sram/__init__ --- compiler/characterize_existing.py | 1 - compiler/func_sim_existing.py | 1 - compiler/gen_stimulus.py | 1 - compiler/modules/sram.py | 2 ++ 4 files changed, 2 insertions(+), 3 deletions(-) diff --git a/compiler/characterize_existing.py b/compiler/characterize_existing.py index c8456b9f..73a7c235 100755 --- a/compiler/characterize_existing.py +++ b/compiler/characterize_existing.py @@ -49,7 +49,6 @@ c = sram_config(word_size=OPTS.word_size, # Initialize and create the sram object from sram import sram s = sram(name=OPTS.output_name, sram_config=c) -s.create() # Characterize the design start_time = datetime.datetime.now() diff --git a/compiler/func_sim_existing.py b/compiler/func_sim_existing.py index ec89c3d7..0d693e91 100755 --- a/compiler/func_sim_existing.py +++ b/compiler/func_sim_existing.py @@ -54,7 +54,6 @@ c = sram_config(word_size=OPTS.word_size, # Initialize and create the sram object from sram import sram s = sram(name=OPTS.output_name, sram_config=c) -s.create() # Generate stimulus and run functional simulation on the design start_time = datetime.datetime.now() diff --git a/compiler/gen_stimulus.py b/compiler/gen_stimulus.py index d69d867d..c9b4e350 100755 --- a/compiler/gen_stimulus.py +++ b/compiler/gen_stimulus.py @@ -60,7 +60,6 @@ OPTS.openram_temp = OPTS.output_path from sram import sram s = sram(name=OPTS.output_name, sram_config=c) -s.create() from characterizer import delay import tech diff --git a/compiler/modules/sram.py b/compiler/modules/sram.py index 127c1b9d..c6f73295 100644 --- a/compiler/modules/sram.py +++ b/compiler/modules/sram.py @@ -39,6 +39,8 @@ class sram(): from base import design design.name_map=[] + self.create() + def create(self): debug.info(2, "create sram of size {0} with {1} num of words {2} banks".format(self.word_size, self.num_words, From ebe4393d666eb7405ca117b504a4d189631467bd Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Fri, 4 Mar 2022 13:53:20 -0800 Subject: [PATCH 023/130] reorder sram __init__() argument order for tests that rely on the order --- compiler/modules/sram.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/modules/sram.py b/compiler/modules/sram.py index c6f73295..ed2760a1 100644 --- a/compiler/modules/sram.py +++ b/compiler/modules/sram.py @@ -20,7 +20,7 @@ class sram(): results. We can later add visualizer and other high-level functions as needed. """ - def __init__(self, name, sram_config): + def __init__(self, sram_config, name): self.name = name self.config = sram_config From 2adab1ea1a33ca55ccf2f8167bdb8a454f5ff065 Mon Sep 17 00:00:00 2001 From: mrg Date: Wed, 16 Feb 2022 10:54:39 -0800 Subject: [PATCH 024/130] Initial work on separate delay and func simulation --- compiler/modules/sram.py | 2 +- compiler/openram.py | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/compiler/modules/sram.py b/compiler/modules/sram.py index ed2760a1..c6f73295 100644 --- a/compiler/modules/sram.py +++ b/compiler/modules/sram.py @@ -20,7 +20,7 @@ class sram(): results. We can later add visualizer and other high-level functions as needed. """ - def __init__(self, sram_config, name): + def __init__(self, name, sram_config): self.name = name self.config = sram_config diff --git a/compiler/openram.py b/compiler/openram.py index 2e460668..5c4f4df7 100755 --- a/compiler/openram.py +++ b/compiler/openram.py @@ -49,7 +49,6 @@ g.report_status() from modules import sram_config - # Configure the SRAM organization c = sram_config(word_size=OPTS.word_size, num_words=OPTS.num_words, @@ -72,7 +71,6 @@ debug.print_raw("Output files are: ") for path in output_files: debug.print_raw(path) - from modules import sram s = sram(name=OPTS.output_name, sram_config=c) From 3e528a3e75d54d492c446310b14b891ae3b1d471 Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Wed, 9 Mar 2022 09:43:00 -0800 Subject: [PATCH 026/130] log sim result after func_sim --- compiler/func_sim_existing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/func_sim_existing.py b/compiler/func_sim_existing.py index 0d693e91..7616fc81 100755 --- a/compiler/func_sim_existing.py +++ b/compiler/func_sim_existing.py @@ -61,8 +61,8 @@ from characterizer import functional debug.print_raw("Functional simulation... ") f = functional(s.s, cycles=cycles, spfile=s.get_sp_name(), period=period, output_path=OPTS.openram_temp) (fail, error) = f.run() +debug.print_raw(error) print_time("Functional simulation", datetime.datetime.now(), start_time) -print(error) # Delete temp files, remove the dir, etc. after success if fail: From e621890f78119c53b0b64efa81e9a4f5e66ad882 Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Thu, 14 Apr 2022 10:04:07 -0700 Subject: [PATCH 027/130] force netlist only mode in memchar memfunc, rename char and func scripts, add description for func script --- compiler/{characterize_existing.py => memchar.py} | 2 ++ compiler/{func_sim_existing.py => memfunc.py} | 10 ++++++---- 2 files changed, 8 insertions(+), 4 deletions(-) rename compiler/{characterize_existing.py => memchar.py} (98%) rename compiler/{func_sim_existing.py => memfunc.py} (86%) diff --git a/compiler/characterize_existing.py b/compiler/memchar.py similarity index 98% rename from compiler/characterize_existing.py rename to compiler/memchar.py index 73a7c235..d824e5a6 100755 --- a/compiler/characterize_existing.py +++ b/compiler/memchar.py @@ -46,6 +46,8 @@ c = sram_config(word_size=OPTS.word_size, num_spare_rows=OPTS.num_spare_rows, num_spare_cols=OPTS.num_spare_cols) +OPTS.netlist_only = True + # Initialize and create the sram object from sram import sram s = sram(name=OPTS.output_name, sram_config=c) diff --git a/compiler/func_sim_existing.py b/compiler/memfunc.py similarity index 86% rename from compiler/func_sim_existing.py rename to compiler/memfunc.py index 7616fc81..7d8ed83e 100755 --- a/compiler/func_sim_existing.py +++ b/compiler/memfunc.py @@ -7,10 +7,10 @@ # All rights reserved. # """ -This script will characterize an SRAM previously generated by OpenRAM given a -configuration file. Configuration option "use_pex" determines whether extracted -or generated spice is used and option "analytical_delay" determines whether -an analytical model or spice simulation is used for characterization. +This script will functionally simulate an SRAM previously generated by OpenRAM +given a configuration file. Configuration option "use_pex" determines whether +extracted or generated spice is used. Command line arguments dictate the +number of cycles and period to be simulated. """ import sys @@ -51,6 +51,8 @@ c = sram_config(word_size=OPTS.word_size, num_spare_rows=OPTS.num_spare_rows, num_spare_cols=OPTS.num_spare_cols) +OPTS.netlist_only = True + # Initialize and create the sram object from sram import sram s = sram(name=OPTS.output_name, sram_config=c) From 8d1d3c0e90c508059e54c17b2100401e42105c45 Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Thu, 14 Apr 2022 10:13:48 -0700 Subject: [PATCH 028/130] disable lvs/drc in char and func scripts --- compiler/memchar.py | 1 + compiler/memfunc.py | 1 + 2 files changed, 2 insertions(+) diff --git a/compiler/memchar.py b/compiler/memchar.py index d824e5a6..b5eb4909 100755 --- a/compiler/memchar.py +++ b/compiler/memchar.py @@ -47,6 +47,7 @@ c = sram_config(word_size=OPTS.word_size, num_spare_cols=OPTS.num_spare_cols) OPTS.netlist_only = True +OPTS.check_lvsdrc = False # Initialize and create the sram object from sram import sram diff --git a/compiler/memfunc.py b/compiler/memfunc.py index 7d8ed83e..87686455 100755 --- a/compiler/memfunc.py +++ b/compiler/memfunc.py @@ -52,6 +52,7 @@ c = sram_config(word_size=OPTS.word_size, num_spare_cols=OPTS.num_spare_cols) OPTS.netlist_only = True +OPTS.check_lvsdrc = False # Initialize and create the sram object from sram import sram From 8872a3e312add3659a6a91dac5a818238814cad5 Mon Sep 17 00:00:00 2001 From: samuelkcrow Date: Thu, 21 Apr 2022 13:06:13 -0700 Subject: [PATCH 029/130] add tests --- compiler/tests/30_memchar_test.py | 95 ++++++++++++++++++ compiler/tests/30_memfunc_test.py | 98 +++++++++++++++++++ .../tests/configs/config_mem_char_func.py | 16 +++ 3 files changed, 209 insertions(+) create mode 100755 compiler/tests/30_memchar_test.py create mode 100755 compiler/tests/30_memfunc_test.py create mode 100644 compiler/tests/configs/config_mem_char_func.py diff --git a/compiler/tests/30_memchar_test.py b/compiler/tests/30_memchar_test.py new file mode 100755 index 00000000..faca2154 --- /dev/null +++ b/compiler/tests/30_memchar_test.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python3 +# See LICENSE for licensing information. +# +# Copyright (c) 2016-2021 Regents of the University of California and The Board +# of Regents for the Oklahoma Agricultural and Mechanical College +# (acting for and on behalf of Oklahoma State University) +# All rights reserved. +# +import unittest +from testutils import * +import sys, os, re, shutil +sys.path.append(os.getenv("OPENRAM_HOME")) +import globals +from globals import OPTS +import debug +import getpass + + +class openram_front_end_test(openram_test): + + def runTest(self): + OPENRAM_HOME = os.path.abspath(os.environ.get("OPENRAM_HOME")) + config_file = "{}/tests/configs/config_mem_char_func".format(os.getenv("OPENRAM_HOME")) + globals.init_openram(config_file) + + debug.info(1, "Testing commandline characterizer script memchar.py with 2-bit, 16 word SRAM.") + out_file = "testsram" + out_path = "/tmp/testsram_{0}_{1}_{2}".format(OPTS.tech_name, getpass.getuser(), os.getpid()) + + # make sure we start without the files existing + if os.path.exists(out_path): + shutil.rmtree(out_path, ignore_errors=True) + self.assertEqual(os.path.exists(out_path), False) + + try: + os.makedirs(out_path, 0o0750) + except OSError as e: + if e.errno == 17: # errno.EEXIST + os.chmod(out_path, 0o0750) + + # specify the same verbosity for the system call + options = "" + for i in range(OPTS.verbose_level): + options += " -v" + + if OPTS.spice_name: + options += " -s {}".format(OPTS.spice_name) + + if OPTS.tech_name: + options += " -t {}".format(OPTS.tech_name) + + options += " -j 2" + + # Always perform code coverage + if OPTS.coverage == 0: + debug.warning("Failed to find coverage installation. This can be installed with pip3 install coverage") + exe_name = "{0}/memchar.py ".format(OPENRAM_HOME) + else: + exe_name = "{0}{1}/memchar.py ".format(OPTS.coverage_exe, OPENRAM_HOME) + config_name = "{0}/tests/configs/config_mem_char_func.py".format(OPENRAM_HOME) + cmd = "{0} -n -o {1} -p {2} {3} {4} 2>&1 > {5}/output.log".format(exe_name, + out_file, + out_path, + options, + config_name, + out_path) + debug.info(1, cmd) + os.system(cmd) + + # Make sure there is any .lib file + import glob + files = glob.glob('{0}/*.lib'.format(out_path)) + self.assertTrue(len(files)>0) + + # grep any errors from the output + output_log = open("{0}/output.log".format(out_path), "r") + output = output_log.read() + output_log.close() + self.assertEqual(len(re.findall('ERROR', output)), 0) + self.assertEqual(len(re.findall('WARNING', output)), 0) + + # now clean up the directory + if not OPTS.keep_temp: + if os.path.exists(out_path): + shutil.rmtree(out_path, ignore_errors=True) + self.assertEqual(os.path.exists(out_path), False) + + globals.end_openram() + +# run the test from the command line +if __name__ == "__main__": + (OPTS, args) = globals.parse_args() + del sys.argv[1:] + header(__file__, OPTS.tech_name) + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/30_memfunc_test.py b/compiler/tests/30_memfunc_test.py new file mode 100755 index 00000000..c9cf6eb8 --- /dev/null +++ b/compiler/tests/30_memfunc_test.py @@ -0,0 +1,98 @@ +#!/usr/bin/env python3 +# See LICENSE for licensing information. +# +# Copyright (c) 2016-2021 Regents of the University of California and The Board +# of Regents for the Oklahoma Agricultural and Mechanical College +# (acting for and on behalf of Oklahoma State University) +# All rights reserved. +# +from asyncio import subprocess +import unittest +from testutils import * +import sys, os, re, shutil +sys.path.append(os.getenv("OPENRAM_HOME")) +import globals +from globals import OPTS +import debug +import getpass + + +class openram_front_end_test(openram_test): + + def runTest(self): + OPENRAM_HOME = os.path.abspath(os.environ.get("OPENRAM_HOME")) + config_file = "{}/tests/configs/config_mem_char_func".format(os.getenv("OPENRAM_HOME")) + globals.init_openram(config_file) + + debug.info(1, "Testing commandline functional simulator script memfunc.py with 2-bit, 16 word SRAM.") + out_file = "testsram" + out_path = "/tmp/testsram_{0}_{1}_{2}".format(OPTS.tech_name, getpass.getuser(), os.getpid()) + + # make sure we start without the files existing + if os.path.exists(out_path): + shutil.rmtree(out_path, ignore_errors=True) + self.assertEqual(os.path.exists(out_path), False) + + try: + os.makedirs(out_path, 0o0750) + except OSError as e: + if e.errno == 17: # errno.EEXIST + os.chmod(out_path, 0o0750) + + # copy the 2x16 sram spice file into out_path because memfunc.py expects it there + sp_src_file = "{0}/tests/golden/sram_2_16_1_{1}.sp".format(OPENRAM_HOME, OPTS.tech_name) + sp_dst_file = out_path + "/" + OPTS.output_name + ".sp" + shutil.copy(sp_src_file, sp_dst_file) + + # specify the same verbosity for the system call + options = "" + for i in range(OPTS.verbose_level): + options += " -v" + + if OPTS.spice_name: + options += " -s {}".format(OPTS.spice_name) + + if OPTS.tech_name: + options += " -t {}".format(OPTS.tech_name) + + options += " -j 2" + + # Always perform code coverage + if OPTS.coverage == 0: + debug.warning("Failed to find coverage installation. This can be installed with pip3 install coverage") + exe_name = "{0}/memfunc.py ".format(OPENRAM_HOME) + else: + exe_name = "{0}{1}/memfunc.py ".format(OPTS.coverage_exe, OPENRAM_HOME) + config_name = "{0}/tests/configs/config_mem_char_func.py".format(OPENRAM_HOME) + period_and_cycles = 10 + cmd = "{0} -n -o {1} -p {2} {3} {4} {5} {5} 2>&1 > {6}/output.log".format(exe_name, + out_file, + out_path, + options, + config_name, + period_and_cycles, + out_path) + debug.info(1, cmd) + os.system(cmd) + + # grep any errors from the output + output_log = open("{0}/output.log".format(out_path), "r") + output = output_log.read() + output_log.close() + self.assertEqual(len(re.findall('ERROR', output)), 0) + self.assertEqual(len(re.findall('WARNING', output)), 0) + + # now clean up the directory + if not OPTS.keep_temp: + if os.path.exists(out_path): + shutil.rmtree(out_path, ignore_errors=True) + self.assertEqual(os.path.exists(out_path), False) + + globals.end_openram() + +# run the test from the command line +if __name__ == "__main__": + (OPTS, args) = globals.parse_args() + del sys.argv[1:] + header(__file__, OPTS.tech_name) + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/configs/config_mem_char_func.py b/compiler/tests/configs/config_mem_char_func.py new file mode 100644 index 00000000..a825acfc --- /dev/null +++ b/compiler/tests/configs/config_mem_char_func.py @@ -0,0 +1,16 @@ +# See LICENSE for licensing information. +# +# Copyright (c) 2016-2021 Regents of the University of California and The Board +# of Regents for the Oklahoma Agricultural and Mechanical College +# (acting for and on behalf of Oklahoma State University) +# All rights reserved. +# +from globals import OPTS +word_size = 2 +num_words = 16 + +tech_name = OPTS.tech_name +output_name = "sram" + +nominal_corner_only = True +spice_name = "ngspice" From 219b29a8334a50ca9a9d239e3656c5eb2bc60a8b Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Thu, 19 May 2022 09:07:45 -0700 Subject: [PATCH 030/130] Fake SRAM and Xyce RAW file option --- compiler/characterizer/fake_sram.py | 61 +++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 compiler/characterizer/fake_sram.py diff --git a/compiler/characterizer/fake_sram.py b/compiler/characterizer/fake_sram.py new file mode 100644 index 00000000..c114d790 --- /dev/null +++ b/compiler/characterizer/fake_sram.py @@ -0,0 +1,61 @@ +import sram_config + +class fake_sram(sram_config.sram_config): + """ This is an SRAM that doesn't actually create itself, just computes + the sizes. """ + def __init__(self, word_size, num_words, num_banks, name, num_spare_rows): + self.name = name + self.word_size = word_size + self.num_words = num_words + self.num_banks = num_banks + self.num_spare_rows = num_spare_rows + # TODO: Get width and height from gds bbox + self.width = 0 + self.height = 0 + #c = reload(__import__(OPTS.bitcell)) + #self.mod_bitcell = getattr(c, OPTS.bitcell) + #self.bitcell = self.mod_bitcell() + # to get the row, col, etc. + self.compute_sizes() + self.setup_multiport_constants() + + def setup_multiport_constants(self): + """ + Taken from ../base/design.py + These are contants and lists that aid multiport design. + Ports are always in the order RW, W, R. + Port indices start from 0 and increment. + A first RW port will have clk0, csb0, web0, addr0, data0 + A first W port (with no RW ports) will be: clk0, csb0, addr0, data0 + + """ + total_ports = OPTS.num_rw_ports + OPTS.num_w_ports + OPTS.num_r_ports + + # These are the read/write port indices. + self.readwrite_ports = [] + # These are the read/write and write-only port indices + self.write_ports = [] + # These are the write-only port indices. + self.writeonly_ports = [] + # These are the read/write and read-only port indices + self.read_ports = [] + # These are the read-only port indices. + self.readonly_ports = [] + # These are all the ports + self.all_ports = list(range(total_ports)) + + # The order is always fixed as RW, W, R + port_number = 0 + for port in range(OPTS.num_rw_ports): + self.readwrite_ports.append(port_number) + self.write_ports.append(port_number) + self.read_ports.append(port_number) + port_number += 1 + for port in range(OPTS.num_w_ports): + self.write_ports.append(port_number) + self.writeonly_ports.append(port_number) + port_number += 1 + for port in range(OPTS.num_r_ports): + self.read_ports.append(port_number) + self.readonly_ports.append(port_number) + port_number += 1 From 2101067e4a5e8c1eb444743ac7d011cd5f6cf8bd Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Mon, 23 May 2022 10:56:22 -0700 Subject: [PATCH 031/130] Characterizer options --- compiler/options.py | 2 ++ compiler/tests/sram_1b_16_1rw_scn4m_subm.log | 2 ++ 2 files changed, 4 insertions(+) create mode 100644 compiler/tests/sram_1b_16_1rw_scn4m_subm.log diff --git a/compiler/options.py b/compiler/options.py index 770045b3..d80b302f 100644 --- a/compiler/options.py +++ b/compiler/options.py @@ -91,6 +91,8 @@ class options(optparse.Values): sim_data_path = None # A list of load/slew tuples use_specified_load_slew = None + # Spice simulation raw file + spice_raw_file = None ################### # Run-time vs accuracy options. diff --git a/compiler/tests/sram_1b_16_1rw_scn4m_subm.log b/compiler/tests/sram_1b_16_1rw_scn4m_subm.log new file mode 100644 index 00000000..0164bbb4 --- /dev/null +++ b/compiler/tests/sram_1b_16_1rw_scn4m_subm.log @@ -0,0 +1,2 @@ +ERROR: file magic.py: line 358: sram LVS mismatch (results in /tmp/openram_bugra_14157_temp/sram.lvs.report) + From ae107b635f51666156770f0264d65af534c4de07 Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Wed, 10 Aug 2022 09:37:02 -0700 Subject: [PATCH 032/130] Enable datasheet generation by default --- compiler/options.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/options.py b/compiler/options.py index d80b302f..4e589e1e 100644 --- a/compiler/options.py +++ b/compiler/options.py @@ -115,7 +115,7 @@ class options(optparse.Values): # Output config with all options output_extended_config = False # Output temporary file used to format HTML page - output_datasheet_info = False + output_datasheet_info = True # Determines which analytical model to use. # Available Models: elmore, linear_regression model_name = "elmore" From c7975e32747e3bb67d5bf272615aeb4e5d84dbf2 Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Wed, 10 Aug 2022 11:58:52 -0700 Subject: [PATCH 033/130] Use fake sram in memchar --- compiler/characterizer/fake_sram.py | 6 +-- compiler/memchar.py | 4 +- compiler/tests/b3v3_1check.log | 5 +++ compiler/tests/sram.log | 59 +++++++++++++++++++++++++++++ 4 files changed, 68 insertions(+), 6 deletions(-) create mode 100644 compiler/tests/b3v3_1check.log create mode 100644 compiler/tests/sram.log diff --git a/compiler/characterizer/fake_sram.py b/compiler/characterizer/fake_sram.py index c114d790..689be714 100644 --- a/compiler/characterizer/fake_sram.py +++ b/compiler/characterizer/fake_sram.py @@ -1,4 +1,6 @@ import sram_config +import OPTS + class fake_sram(sram_config.sram_config): """ This is an SRAM that doesn't actually create itself, just computes @@ -12,10 +14,6 @@ class fake_sram(sram_config.sram_config): # TODO: Get width and height from gds bbox self.width = 0 self.height = 0 - #c = reload(__import__(OPTS.bitcell)) - #self.mod_bitcell = getattr(c, OPTS.bitcell) - #self.bitcell = self.mod_bitcell() - # to get the row, col, etc. self.compute_sizes() self.setup_multiport_constants() diff --git a/compiler/memchar.py b/compiler/memchar.py index b5eb4909..ba6b25cf 100755 --- a/compiler/memchar.py +++ b/compiler/memchar.py @@ -49,8 +49,8 @@ c = sram_config(word_size=OPTS.word_size, OPTS.netlist_only = True OPTS.check_lvsdrc = False -# Initialize and create the sram object -from sram import sram +# Initialize and create a fake sram object +import fake_sran as sram s = sram(name=OPTS.output_name, sram_config=c) # Characterize the design diff --git a/compiler/tests/b3v3_1check.log b/compiler/tests/b3v3_1check.log new file mode 100644 index 00000000..6903570b --- /dev/null +++ b/compiler/tests/b3v3_1check.log @@ -0,0 +1,5 @@ +BSIM3V3.1 Parameter Check +Model = p +W = 6e-07, L = 8e-07 +Warning: Pd = 0 is less than W. +Warning: Ps = 0 is less than W. diff --git a/compiler/tests/sram.log b/compiler/tests/sram.log new file mode 100644 index 00000000..a5b407c5 --- /dev/null +++ b/compiler/tests/sram.log @@ -0,0 +1,59 @@ +ERROR: file testutils.py: line 266: Mismatching files: +file1=/tmp/openram_bugra_979_temp//sram_2_16_1_scn4m_subm_TT_5p0V_25C.lib +file2=/openram/compiler/tests/golden/sram_2_16_1_scn4m_subm_TT_5p0V_25C_analytical.lib + +ERROR: file testutils.py: line 268: MISMATCH Line (74): + type (wmask){ +!= +cell (sram____scnm_subm){ + +ERROR: file testutils.py: line 268: MISMATCH Line (75): + base_type : array; +!= + memory(){ + +ERROR: file testutils.py: line 268: MISMATCH Line (76): + data_type : bit; +!= + type : ram; + +ERROR: file testutils.py: line 268: MISMATCH Line (77): + bit_width : ; +!= + address_width : ; + +ERROR: file testutils.py: line 268: MISMATCH Line (78): + bit_from : ; +!= + word_width : ; + +ERROR: file testutils.py: line 268: MISMATCH Line (79): + bit_to : ; +!= + } + +ERROR: file testutils.py: line 268: MISMATCH Line (80): + } +!= + interface_timing : true; + +ERROR: file testutils.py: line 268: MISMATCH Line (81): + +!= + dont_use : true; + +ERROR: file testutils.py: line 268: MISMATCH Line (82): +cell (sram____scnm_subm){ +!= + map_only : true; + +ERROR: file testutils.py: line 268: MISMATCH Line (83): + memory(){ +!= + dont_touch : true; + +ERROR: file testutils.py: line 268: MISMATCH Line (84): + type : ram; +!= + area : ; + From 3f941d2fffce03b651340b8a10b4be0cfd7316eb Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Wed, 10 Aug 2022 12:59:54 -0700 Subject: [PATCH 034/130] Copy over the CSV read function to fake_sram --- compiler/characterizer/fake_sram.py | 75 +++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/compiler/characterizer/fake_sram.py b/compiler/characterizer/fake_sram.py index 689be714..b52bf55f 100644 --- a/compiler/characterizer/fake_sram.py +++ b/compiler/characterizer/fake_sram.py @@ -57,3 +57,78 @@ class fake_sram(sram_config.sram_config): self.read_ports.append(port_number) self.readonly_ports.append(port_number) port_number += 1 + + def parse_characterizer_csv(f, pages): + """ + Parses output data of the Liberty file generator in order to construct the timing and + current table + """ + #TODO: Func taken from datasheet_gen.py. Read datasheet.info and extract sram members + with open(f) as csv_file: + csv_reader = csv.reader(csv_file, delimiter=',') + for row in csv_reader: + + found = 0 + col = 0 + + # defines layout of csv file + NAME = row[col] + col += 1 + + NUM_WORDS = row[col] + col += 1 + + NUM_BANKS = row[col] + col += 1 + + NUM_RW_PORTS = row[col] + col += 1 + + NUM_W_PORTS = row[col] + col += 1 + + NUM_R_PORTS = row[col] + col += 1 + + TECH_NAME = row[col] + col += 1 + + TEMP = row[col] + col += 1 + + VOLT = row[col] + col += 1 + + PROC = row[col] + col += 1 + + MIN_PERIOD = row[col] + col += 1 + + OUT_DIR = row[col] + col += 1 + + LIB_NAME = row[col] + col += 1 + + WORD_SIZE = row[col] + col += 1 + + ORIGIN_ID = row[col] + col += 1 + + DATETIME = row[col] + col += 1 + + ANALYTICAL_MODEL = row[col] + col += 1 + + DRC = row[col] + col += 1 + + LVS = row[col] + col += 1 + + AREA = row[col] + col += 1 + From bd6621cb884dbb9e77bd27a7177f0c5a0082433a Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Wed, 10 Aug 2022 14:21:54 -0700 Subject: [PATCH 035/130] Increase random value range by 1 --- compiler/characterizer/functional.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/characterizer/functional.py b/compiler/characterizer/functional.py index 3bc94ab7..c1f1949d 100644 --- a/compiler/characterizer/functional.py +++ b/compiler/characterizer/functional.py @@ -348,7 +348,7 @@ class functional(simulation): def gen_data(self): """ Generates a random word to write. """ # Don't use 0 or max value - random_value = random.randint(1, self.max_data - 1) + random_value = random.randint(1, self.max_data) data_bits = binary_repr(random_value, self.word_size) if self.num_spare_cols>0: random_value = random.randint(0, self.max_col_data) From f602c6b2639ca311da6e4d31c7577d93ef92b15f Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Fri, 12 Aug 2022 23:29:33 -0700 Subject: [PATCH 036/130] HTML parsing for fake_sram added --- compiler/characterizer/fake_sram.py | 157 +++++++++++++--------------- compiler/memchar.py | 16 +-- 2 files changed, 79 insertions(+), 94 deletions(-) diff --git a/compiler/characterizer/fake_sram.py b/compiler/characterizer/fake_sram.py index b52bf55f..7eb1deb4 100644 --- a/compiler/characterizer/fake_sram.py +++ b/compiler/characterizer/fake_sram.py @@ -1,21 +1,53 @@ -import sram_config -import OPTS +from modules import sram_config +from math import ceil +import re -class fake_sram(sram_config.sram_config): - """ This is an SRAM that doesn't actually create itself, just computes - the sizes. """ - def __init__(self, word_size, num_words, num_banks, name, num_spare_rows): +class fake_sram(sram_config): + """ + This is an SRAM class that doesn't actually create an instance. + It will read neccessary members from HTML file from a previous run. + """ + def __init__(self, name, word_size, num_words, write_size=None, num_banks=1, + words_per_row=None, num_spare_rows=0, num_spare_cols=0): self.name = name self.word_size = word_size self.num_words = num_words + # Don't add a write mask if it is the same size as the data word + if write_size and write_size==word_size: + self.write_size = None + else: + self.write_size = write_size self.num_banks = num_banks self.num_spare_rows = num_spare_rows - # TODO: Get width and height from gds bbox - self.width = 0 - self.height = 0 + self.num_spare_cols = num_spare_cols + + try: + from tech import array_row_multiple + self.array_row_multiple = array_row_multiple + except ImportError: + self.array_row_multiple = 1 + try: + from tech import array_col_multiple + self.array_col_multiple = array_col_multiple + except ImportError: + self.array_col_multiple = 1 + + if self.write_size: + self.num_wmasks = int(ceil(self.word_size / self.write_size)) + else: + self.num_wmasks = 0 + + if not self.num_spare_cols: + self.num_spare_cols = 0 + + if not self.num_spare_rows: + self.num_spare_rows = 0 + + # This will get over-written when we determine the organization + self.words_per_row = words_per_row + self.compute_sizes() - self.setup_multiport_constants() def setup_multiport_constants(self): """ @@ -27,7 +59,7 @@ class fake_sram(sram_config.sram_config): A first W port (with no RW ports) will be: clk0, csb0, addr0, data0 """ - total_ports = OPTS.num_rw_ports + OPTS.num_w_ports + OPTS.num_r_ports + total_ports = self.num_rw_ports + self.num_w_ports + self.num_r_ports # These are the read/write port indices. self.readwrite_ports = [] @@ -44,91 +76,44 @@ class fake_sram(sram_config.sram_config): # The order is always fixed as RW, W, R port_number = 0 - for port in range(OPTS.num_rw_ports): + for port in range(self.num_rw_ports): self.readwrite_ports.append(port_number) self.write_ports.append(port_number) self.read_ports.append(port_number) port_number += 1 - for port in range(OPTS.num_w_ports): + for port in range(self.num_w_ports): self.write_ports.append(port_number) self.writeonly_ports.append(port_number) port_number += 1 - for port in range(OPTS.num_r_ports): + for port in range(self.num_r_ports): self.read_ports.append(port_number) self.readonly_ports.append(port_number) port_number += 1 - def parse_characterizer_csv(f, pages): + def parse_html(self, filename): """ - Parses output data of the Liberty file generator in order to construct the timing and - current table + Parse the HTML file generated from previous SRAM generation + and populate the members """ - #TODO: Func taken from datasheet_gen.py. Read datasheet.info and extract sram members - with open(f) as csv_file: - csv_reader = csv.reader(csv_file, delimiter=',') - for row in csv_reader: - - found = 0 - col = 0 - - # defines layout of csv file - NAME = row[col] - col += 1 - - NUM_WORDS = row[col] - col += 1 - - NUM_BANKS = row[col] - col += 1 - - NUM_RW_PORTS = row[col] - col += 1 - - NUM_W_PORTS = row[col] - col += 1 - - NUM_R_PORTS = row[col] - col += 1 - - TECH_NAME = row[col] - col += 1 - - TEMP = row[col] - col += 1 - - VOLT = row[col] - col += 1 - - PROC = row[col] - col += 1 - - MIN_PERIOD = row[col] - col += 1 - - OUT_DIR = row[col] - col += 1 - - LIB_NAME = row[col] - col += 1 - - WORD_SIZE = row[col] - col += 1 - - ORIGIN_ID = row[col] - col += 1 - - DATETIME = row[col] - col += 1 - - ANALYTICAL_MODEL = row[col] - col += 1 - - DRC = row[col] - col += 1 - - LVS = row[col] - col += 1 - - AREA = row[col] - col += 1 - + with open(filename, 'r') as html: + for line in html: + if 'Ports and Configuration' in line: + tableRE = re.compile(r'(\w*)(\w*)') + values = tableRE.finditer(line) + for val in values: + if val.group(1) == 'WORD_SIZE': + self.word_size = int(val.group(2)) + elif val.group(1) == 'NUM_WORDS': + self.num_words = int(val.group(2)) + elif val.group(1) == 'NUM_BANKS': + self.num_banks = int(val.group(2)) + elif val.group(1) == 'NUM_RW_PORTS': + self.num_rw_ports = int(val.group(2)) + elif val.group(1) == 'NUM_R_PORTS': + self.num_r_ports = int(val.group(2)) + elif val.group(1) == 'NUM_W_PORTS': + self.num_w_ports = int(val.group(2)) + elif val.group(1) == 'Area (µm2)': + self.height = int(val.group(2) ** 0.5) + self.width = int(val.group(2) ** 0.5) + break diff --git a/compiler/memchar.py b/compiler/memchar.py index ba6b25cf..819fe283 100755 --- a/compiler/memchar.py +++ b/compiler/memchar.py @@ -24,7 +24,7 @@ from importlib import reload USAGE = "Usage: {} [options] \nUse -h for help.\n".format(__file__) # Check that we are left with a single configuration file as argument. -if len(args) != 1: +if len(args) != 2: print(USAGE) sys.exit(2) @@ -37,8 +37,9 @@ init_openram(config_file=args[0], is_unit_test=False) print_banner() # Configure the SRAM organization (duplicated from openram.py) -from sram_config import sram_config -c = sram_config(word_size=OPTS.word_size, +from characterizer.fake_sram import fake_sram +s = fake_sram(name=OPTS.output_name, + word_size=OPTS.word_size, num_words=OPTS.num_words, write_size=OPTS.write_size, num_banks=OPTS.num_banks, @@ -46,18 +47,17 @@ c = sram_config(word_size=OPTS.word_size, num_spare_rows=OPTS.num_spare_rows, num_spare_cols=OPTS.num_spare_cols) +s.parse_html(args[1]) +s.setup_multiport_constants() + OPTS.netlist_only = True OPTS.check_lvsdrc = False -# Initialize and create a fake sram object -import fake_sran as sram -s = sram(name=OPTS.output_name, sram_config=c) - # Characterize the design start_time = datetime.datetime.now() from characterizer import lib debug.print_raw("LIB: Characterizing... ") -lib(out_dir=OPTS.output_path, sram=s.s, sp_file=s.get_sp_name()) +lib(out_dir=OPTS.output_path, sram=s, sp_file=OPTS.output_path + OPTS.output_name + ".sp") print_time("Characterization", datetime.datetime.now(), start_time) # Output info about this run From 9fba946f1861cad4c2ef0081a03c49206833a018 Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Thu, 18 Aug 2022 12:54:09 -0700 Subject: [PATCH 037/130] Characterizer use_model set to false --- compiler/memchar.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/memchar.py b/compiler/memchar.py index 819fe283..99c6492f 100755 --- a/compiler/memchar.py +++ b/compiler/memchar.py @@ -57,7 +57,7 @@ OPTS.check_lvsdrc = False start_time = datetime.datetime.now() from characterizer import lib debug.print_raw("LIB: Characterizing... ") -lib(out_dir=OPTS.output_path, sram=s, sp_file=OPTS.output_path + OPTS.output_name + ".sp") +lib(out_dir=OPTS.output_path, sram=s, sp_file=OPTS.output_path + OPTS.output_name + ".sp", use_model=False) print_time("Characterization", datetime.datetime.now(), start_time) # Output info about this run From efd6da5300ae5c347582791f5becccfc115311c3 Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Thu, 18 Aug 2022 12:54:39 -0700 Subject: [PATCH 038/130] Parse pins from HTML --- compiler/characterizer/fake_sram.py | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/compiler/characterizer/fake_sram.py b/compiler/characterizer/fake_sram.py index 7eb1deb4..223f6868 100644 --- a/compiler/characterizer/fake_sram.py +++ b/compiler/characterizer/fake_sram.py @@ -48,6 +48,7 @@ class fake_sram(sram_config): self.words_per_row = words_per_row self.compute_sizes() + self.pins = ['vdd', 'gnd', 'clk0'] # TODO: remove clk def setup_multiport_constants(self): """ @@ -90,6 +91,13 @@ class fake_sram(sram_config): self.readonly_ports.append(port_number) port_number += 1 + def str_to_pins(self, s): + pinsRE = re.compile(r'^(\w+)\[(\d+):(\d+)\]') + match = pinsRE.match(s) + port, start, end = match.group(1, 2, 3) + pins = [port + '[' + str(p) + ']' for p in range(int(start) - int(end) + 1)] + return pins + def parse_html(self, filename): """ Parse the HTML file generated from previous SRAM generation @@ -98,8 +106,8 @@ class fake_sram(sram_config): with open(filename, 'r') as html: for line in html: if 'Ports and Configuration' in line: - tableRE = re.compile(r'(\w*)(\w*)') - values = tableRE.finditer(line) + configRE = re.compile(r'(\w*)(\w*)') + values = configRE.finditer(line) for val in values: if val.group(1) == 'WORD_SIZE': self.word_size = int(val.group(2)) @@ -116,4 +124,15 @@ class fake_sram(sram_config): elif val.group(1) == 'Area (µm2)': self.height = int(val.group(2) ** 0.5) self.width = int(val.group(2) ** 0.5) - break + if 'Timing Data' in line: + timingRE = re.compile(r'([\w\[\]:]*) \w* \w*[\w\.]*[\w\.]*\w*') + values = timingRE.finditer(line) + for val in values: + if '[' in val.group(1): + pins = self.str_to_pins(val.group(1)) + for pin in pins: + if pin not in self.pins: + self.pins.append(pin) + else: + if val.group(1) not in self.pins: + self.pins.append(val.group(1)) From f0a46659533f55502fcc8344449b9fce9db85370 Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Thu, 18 Aug 2022 20:35:02 -0700 Subject: [PATCH 039/130] Add top process averness --- compiler/memchar.py | 2 ++ compiler/memfunc.py | 2 ++ compiler/openram.py | 2 ++ 3 files changed, 6 insertions(+) diff --git a/compiler/memchar.py b/compiler/memchar.py index 99c6492f..4de9e58c 100755 --- a/compiler/memchar.py +++ b/compiler/memchar.py @@ -28,6 +28,8 @@ if len(args) != 2: print(USAGE) sys.exit(2) +OPTS.top_process = 'memchar' + # These depend on arguments, so don't load them until now. import debug diff --git a/compiler/memfunc.py b/compiler/memfunc.py index 87686455..c0dfe25e 100755 --- a/compiler/memfunc.py +++ b/compiler/memfunc.py @@ -28,6 +28,8 @@ if len(args) != 3: print(USAGE) sys.exit(2) +OPTS.top_process = 'memfunc' + # Parse argument config_file = args[0] cycles = int(args[1]) diff --git a/compiler/openram.py b/compiler/openram.py index 5c4f4df7..a0dcdfba 100755 --- a/compiler/openram.py +++ b/compiler/openram.py @@ -27,6 +27,8 @@ if len(args) != 1: print(g.USAGE) sys.exit(2) +# Set top process to openram +OPTS.top_process = 'openram' # These depend on arguments, so don't load them until now. import debug From 56879bf48ba66921cfd1e44e24c2d0f8172252a4 Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Thu, 18 Aug 2022 20:35:34 -0700 Subject: [PATCH 040/130] Cleanup --- compiler/tests/sram.log | 59 ----------------------------------------- 1 file changed, 59 deletions(-) delete mode 100644 compiler/tests/sram.log diff --git a/compiler/tests/sram.log b/compiler/tests/sram.log deleted file mode 100644 index a5b407c5..00000000 --- a/compiler/tests/sram.log +++ /dev/null @@ -1,59 +0,0 @@ -ERROR: file testutils.py: line 266: Mismatching files: -file1=/tmp/openram_bugra_979_temp//sram_2_16_1_scn4m_subm_TT_5p0V_25C.lib -file2=/openram/compiler/tests/golden/sram_2_16_1_scn4m_subm_TT_5p0V_25C_analytical.lib - -ERROR: file testutils.py: line 268: MISMATCH Line (74): - type (wmask){ -!= -cell (sram____scnm_subm){ - -ERROR: file testutils.py: line 268: MISMATCH Line (75): - base_type : array; -!= - memory(){ - -ERROR: file testutils.py: line 268: MISMATCH Line (76): - data_type : bit; -!= - type : ram; - -ERROR: file testutils.py: line 268: MISMATCH Line (77): - bit_width : ; -!= - address_width : ; - -ERROR: file testutils.py: line 268: MISMATCH Line (78): - bit_from : ; -!= - word_width : ; - -ERROR: file testutils.py: line 268: MISMATCH Line (79): - bit_to : ; -!= - } - -ERROR: file testutils.py: line 268: MISMATCH Line (80): - } -!= - interface_timing : true; - -ERROR: file testutils.py: line 268: MISMATCH Line (81): - -!= - dont_use : true; - -ERROR: file testutils.py: line 268: MISMATCH Line (82): -cell (sram____scnm_subm){ -!= - map_only : true; - -ERROR: file testutils.py: line 268: MISMATCH Line (83): - memory(){ -!= - dont_touch : true; - -ERROR: file testutils.py: line 268: MISMATCH Line (84): - type : ram; -!= - area : ; - From eceb35f205b9a7574e6b5c0336c68e127475df43 Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Thu, 18 Aug 2022 20:38:09 -0700 Subject: [PATCH 041/130] Skip graph exclusions on memchar --- compiler/characterizer/simulation.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/compiler/characterizer/simulation.py b/compiler/characterizer/simulation.py index b2ccd79e..568b639d 100644 --- a/compiler/characterizer/simulation.py +++ b/compiler/characterizer/simulation.py @@ -493,11 +493,12 @@ class simulation(): # other initializations can only be done during analysis when a bit has been selected # for testing. - self.sram.bank.graph_exclude_precharge() - self.sram.graph_exclude_addr_dff() - self.sram.graph_exclude_data_dff() - self.sram.graph_exclude_ctrl_dffs() - self.sram.bank.bitcell_array.graph_exclude_replica_col_bits() + if OPTS.top_process != 'memchar': + self.sram.bank.graph_exclude_precharge() + self.sram.graph_exclude_addr_dff() + self.sram.graph_exclude_data_dff() + self.sram.graph_exclude_ctrl_dffs() + self.sram.bank.bitcell_array.graph_exclude_replica_col_bits() def set_internal_spice_names(self): """ From d3753556c168936170e370f6cbfc26c5c00e22da Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Thu, 18 Aug 2022 21:09:48 -0700 Subject: [PATCH 042/130] Pin generation instead of parsing --- compiler/characterizer/fake_sram.py | 59 +++++++++++++++++++---------- compiler/memchar.py | 1 + compiler/options.py | 2 + 3 files changed, 42 insertions(+), 20 deletions(-) diff --git a/compiler/characterizer/fake_sram.py b/compiler/characterizer/fake_sram.py index 223f6868..44c98606 100644 --- a/compiler/characterizer/fake_sram.py +++ b/compiler/characterizer/fake_sram.py @@ -48,7 +48,6 @@ class fake_sram(sram_config): self.words_per_row = words_per_row self.compute_sizes() - self.pins = ['vdd', 'gnd', 'clk0'] # TODO: remove clk def setup_multiport_constants(self): """ @@ -91,13 +90,6 @@ class fake_sram(sram_config): self.readonly_ports.append(port_number) port_number += 1 - def str_to_pins(self, s): - pinsRE = re.compile(r'^(\w+)\[(\d+):(\d+)\]') - match = pinsRE.match(s) - port, start, end = match.group(1, 2, 3) - pins = [port + '[' + str(p) + ']' for p in range(int(start) - int(end) + 1)] - return pins - def parse_html(self, filename): """ Parse the HTML file generated from previous SRAM generation @@ -124,15 +116,42 @@ class fake_sram(sram_config): elif val.group(1) == 'Area (µm2)': self.height = int(val.group(2) ** 0.5) self.width = int(val.group(2) ** 0.5) - if 'Timing Data' in line: - timingRE = re.compile(r'([\w\[\]:]*) \w* \w*[\w\.]*[\w\.]*\w*') - values = timingRE.finditer(line) - for val in values: - if '[' in val.group(1): - pins = self.str_to_pins(val.group(1)) - for pin in pins: - if pin not in self.pins: - self.pins.append(pin) - else: - if val.group(1) not in self.pins: - self.pins.append(val.group(1)) + self.compute_sizes() + + def generate_pins(self): + self.pins = ['vdd', 'gnd'] + self.pins.extend(['clk{}'.format(port) for port in range( + self.num_rw_ports + self.num_r_ports + self.num_w_ports)]) + for port in range(self.num_rw_ports): + self.pins.extend(['din{0}[{1}]]'.format(port, bit) + for bit in range(self.num_cols)]) + self.pins.extend(['dout{0}[{1}]]'.format(port, bit) + for bit in range(self.num_cols)]) + self.pins.extend(['addr{0}[{1}]]'.format(port, bit) + for bit in range(self.addr_size)]) + if self.num_wmasks != 0: + self.pins.extend(['wmask{0}[{1}]]'.format(port, bit) + for bit in range(self.num_wmasks)]) + + self.pins.extend(['csb{}'.format(port), 'web{}'.format(port)]) + + start_port = self.num_rw_ports + for port in range(start_port, start_port + self.num_r_ports): + self.pins.extend(['dout{0}[{1}]]'.format(port, bit) + for bit in range(self.num_cols)]) + self.pins.extend(['addr{0}[{1}]]'.format(port, bit) + for bit in range(self.addr_size)]) + + self.pins.extend(['csb{}'.format(port)]) + + start_port += self.num_r_ports + for port in range(start_port, start_port + self.num_w_ports): + self.pins.extend(['din{0}[{1}]]'.format(port, bit) + for bit in range(self.num_cols)]) + self.pins.extend(['addr{0}[{1}]]'.format(port, bit) + for bit in range(self.addr_size)]) + if self.num_wmasks != 0: + self.pins.extend(['wmask{0}[{1}]]'.format(port, bit) + for bit in range(self.num_wmasks)]) + + self.pins.extend(['csb{}'.format(port), 'web{}'.format(port)]) diff --git a/compiler/memchar.py b/compiler/memchar.py index 4de9e58c..c4ce6dad 100755 --- a/compiler/memchar.py +++ b/compiler/memchar.py @@ -50,6 +50,7 @@ s = fake_sram(name=OPTS.output_name, num_spare_cols=OPTS.num_spare_cols) s.parse_html(args[1]) +s.generate_pins() s.setup_multiport_constants() OPTS.netlist_only = True diff --git a/compiler/options.py b/compiler/options.py index 4e589e1e..516f9817 100644 --- a/compiler/options.py +++ b/compiler/options.py @@ -123,6 +123,8 @@ class options(optparse.Values): ################### # Tool options ################### + # Top process that was ran (openram, memchar, memfunc) + top_process = None # Variable to select the variant of spice spice_name = None # The spice executable being used which is derived from the user PATH. From 05ab45f39b8a39af2d4dbb1b62393a54b7e268b3 Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Tue, 30 Aug 2022 09:15:35 -0700 Subject: [PATCH 043/130] Added graph store and read functionality --- compiler/base/timing_graph.py | 30 ++++++++++++++++++++++++++++++ compiler/memchar.py | 3 +++ compiler/modules/sram.py | 11 +++++++++++ compiler/options.py | 2 ++ 4 files changed, 46 insertions(+) diff --git a/compiler/base/timing_graph.py b/compiler/base/timing_graph.py index 46d7b518..9c6301f5 100644 --- a/compiler/base/timing_graph.py +++ b/compiler/base/timing_graph.py @@ -1,6 +1,7 @@ import copy from collections import defaultdict import debug +import json class timing_graph(): @@ -139,6 +140,35 @@ class timing_graph(): return [self.edge_mods[(path[i], path[i+1])] for i in range(len(path)-1)] + def write(self, filename): + """ + Export graph to a JSON file + """ + # TODO: Find a proper way to store edge_mods values + with open(filename, 'w') as f: + f.write( + json.dumps( + { + 'graph': + {key: list(val) for key, val in self.graph.items()}, + 'edge_mods': + { + ', '.join(key): str(value) + for key, value in self.edge_mods.items() + } + } + ) + ) + + def read(self, filename): + """ + Read graph from JSON file + """ + with open(filename, 'r') as f: + d = json.loads(f.read()) + self.graph = {key: set(value) for key, value in d['graph'].items()} + self.edge_mods = {tuple(key.split(', ')): value for key, value in d['edge_mods'].items()} + def __str__(self): """ override print function output """ diff --git a/compiler/memchar.py b/compiler/memchar.py index c4ce6dad..425a8abd 100755 --- a/compiler/memchar.py +++ b/compiler/memchar.py @@ -56,6 +56,9 @@ s.setup_multiport_constants() OPTS.netlist_only = True OPTS.check_lvsdrc = False +# TODO: remove this after adding trimmed netlist gen to sram run +OPTS.trim_netlist = False + # Characterize the design start_time = datetime.datetime.now() from characterizer import lib diff --git a/compiler/modules/sram.py b/compiler/modules/sram.py index c6f73295..2a722709 100644 --- a/compiler/modules/sram.py +++ b/compiler/modules/sram.py @@ -9,6 +9,7 @@ import datetime import os import debug from characterizer import functional +from base import timing_graph from globals import OPTS, print_time import shutil @@ -187,3 +188,13 @@ class sram(): debug.print_raw("Extended Config: Writing to {0}".format(oname)) self.extended_config_write(oname) print_time("Extended Config", datetime.datetime.now(), start_time) + + # Write the graph if specified + if OPTS.write_graph: + start_time = datetime.datetime.now() + oname = OPTS.output_path + OPTS.output_name + "_graph.json" + debug.print_raw("Graph: Writing to {0}".format(oname)) + graph = timing_graph() + self.s.build_graph(graph, self.name, self.s.pins) + graph.write(oname) + print_time("Graph", datetime.datetime.now(), start_time) diff --git a/compiler/options.py b/compiler/options.py index 516f9817..6c518d09 100644 --- a/compiler/options.py +++ b/compiler/options.py @@ -119,6 +119,8 @@ class options(optparse.Values): # Determines which analytical model to use. # Available Models: elmore, linear_regression model_name = "elmore" + # Write graph to a file + write_graph = False ################### # Tool options From fcfb9391f67f446175d991376aaa2947cc73001c Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Thu, 1 Sep 2022 16:19:14 -0700 Subject: [PATCH 044/130] Code formatting --- compiler/characterizer/delay.py | 33 ++++++++++++----------- compiler/characterizer/functional.py | 7 +++-- compiler/characterizer/measurements.py | 36 ++++++++++++++------------ compiler/characterizer/simulation.py | 26 +++++++++---------- 4 files changed, 51 insertions(+), 51 deletions(-) diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index 40a623c6..80540b94 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -605,8 +605,8 @@ class delay(simulation): return net original_net = net net = net[len(prefix):] - net = net.replace(".", "_").replace("[", "\[").replace("]", "\]") - for pattern in ["\sN_{}_[MXmx]\S+_[gsd]".format(net), net]: + net = net.replace(".", "_").replace("[", r"\[").replace("]", r"\]") + for pattern in [r"\sN_{}_[MXmx]\S+_[gsd]".format(net), net]: try: match = check_output(["grep", "-m1", "-o", "-iE", pattern, self.sp_file]) return prefix + match.decode().strip() @@ -616,8 +616,8 @@ class delay(simulation): def load_all_measure_nets(self): measurement_nets = set() - for port, meas in zip(self.targ_read_ports * len(self.read_meas_lists) + - self.targ_write_ports * len(self.write_meas_lists), + for port, meas in zip(self.targ_read_ports * len(self.read_meas_lists) + + self.targ_write_ports * len(self.write_meas_lists), self.read_meas_lists + self.write_meas_lists): for measurement in meas: visited = getattr(measurement, 'pex_visited', False) @@ -791,7 +791,7 @@ class delay(simulation): for port in self.targ_write_ports: if not self.check_bit_measures(self.write_bit_meas, port): - return(False, {}) + return (False, {}) debug.info(2, "Checking write values for port {0}".format(port)) write_port_dict = {} @@ -805,7 +805,7 @@ class delay(simulation): for port in self.targ_read_ports: # First, check that the memory has the right values at the right times if not self.check_bit_measures(self.read_bit_meas, port): - return(False, {}) + return (False, {}) debug.info(2, "Checking read delay values for port {0}".format(port)) # Check sen timing, then bitlines, then general measurements. @@ -942,7 +942,7 @@ class delay(simulation): if type(val) != float or val > self.period / 2: debug.info(1, 'Failed measurement:{}={}'.format(meas.name, val)) value_dict[meas.name] = val - #debug.info(0, "value_dict={}".format(value_dict)) + # debug.info(0, "value_dict={}".format(value_dict)) return value_dict def run_power_simulation(self): @@ -1145,7 +1145,7 @@ class delay(simulation): self.analysis_init(probe_address, probe_data) loads = [] slews = [] - for load,slew in load_slews: + for load, slew in load_slews: loads.append(load) slews.append(slew) self.load=max(loads) @@ -1168,15 +1168,15 @@ class delay(simulation): # 4) At the minimum period, measure the delay, slew and power for all slew/load pairs. self.period = min_period char_port_data = self.simulate_loads_and_slews(load_slews, leakage_offset) - if OPTS.use_specified_load_slew != None and len(load_slews) > 1: + if OPTS.use_specified_load_slew is not None and len(load_slews) > 1: debug.warning("Path delay lists not correctly generated for characterizations of more than 1 load,slew") # Get and save the path delays bl_names, bl_delays, sen_names, sen_delays = self.get_delay_lists(self.path_delays) # Removed from characterization output temporarily - #char_sram_data["bl_path_measures"] = bl_delays - #char_sram_data["sen_path_measures"] = sen_delays - #char_sram_data["bl_path_names"] = bl_names - #char_sram_data["sen_path_names"] = sen_names + # char_sram_data["bl_path_measures"] = bl_delays + # char_sram_data["sen_path_measures"] = sen_delays + # char_sram_data["bl_path_names"] = bl_names + # char_sram_data["sen_path_names"] = sen_names # FIXME: low-to-high delays are altered to be independent of the period. This makes the lib results less accurate. self.alter_lh_char_data(char_port_data) @@ -1185,7 +1185,7 @@ class delay(simulation): def alter_lh_char_data(self, char_port_data): """Copies high-to-low data to low-to-high data to make them consistent on the same clock edge.""" - # This is basically a hack solution which should be removed/fixed later. + # This is basically a hack solution which should be removed/fixed later. for port in self.all_ports: char_port_data[port]['delay_lh'] = char_port_data[port]['delay_hl'] char_port_data[port]['slew_lh'] = char_port_data[port]['slew_hl'] @@ -1194,7 +1194,6 @@ class delay(simulation): """Simulate all specified output loads and input slews pairs of all ports""" measure_data = self.get_empty_measure_data_dict() - path_dict = {} # Set the target simulation ports to all available ports. This make sims slower but failed sims exit anyways. self.targ_read_ports = self.read_ports self.targ_write_ports = self.write_ports @@ -1352,9 +1351,9 @@ class delay(simulation): # Get any available read/write port in case only a single write or read ports is being characterized. cur_read_port = self.get_available_port(get_read_port=True) cur_write_port = self.get_available_port(get_read_port=False) - debug.check(cur_read_port != None, + debug.check(cur_read_port is not None, "Characterizer requires at least 1 read port") - debug.check(cur_write_port != None, + debug.check(cur_write_port is not None, "Characterizer requires at least 1 write port") # Create test cycles for specified target ports. diff --git a/compiler/characterizer/functional.py b/compiler/characterizer/functional.py index c1f1949d..b6a57fb3 100644 --- a/compiler/characterizer/functional.py +++ b/compiler/characterizer/functional.py @@ -146,7 +146,6 @@ class functional(simulation): comment = self.gen_cycle_comment("noop", "0" * self.word_size, "0" * self.addr_size, "0" * self.num_wmasks, 0, self.t_current) self.add_noop_all_ports(comment) - # 1. Write all the write ports 2x to seed a bunch of locations. for i in range(3): for port in self.write_ports: @@ -268,7 +267,7 @@ class functional(simulation): self.read_check.append([word, "{0}{1}".format(self.dout_name, port), self.t_current + self.period, - int(self.t_current/self.period)]) + int(self.t_current / self.period)]) def read_stim_results(self): # Extract dout values from spice timing.lis @@ -319,8 +318,8 @@ class functional(simulation): cycle, self.read_results[i][2], check_name) - return(0, error) - return(1, "SUCCESS") + return (0, error) + return (1, "SUCCESS") def gen_wmask(self): wmask = "" diff --git a/compiler/characterizer/measurements.py b/compiler/characterizer/measurements.py index fcbb562f..d4811d63 100644 --- a/compiler/characterizer/measurements.py +++ b/compiler/characterizer/measurements.py @@ -11,16 +11,18 @@ from abc import ABC, abstractmethod from .stimuli import * from .charutils import * + class spice_measurement(ABC): """Base class for spice stimulus measurements.""" def __init__(self, measure_name, measure_scale=None, has_port=True): - #Names must be unique for correct spice simulation, but not enforced here. + # Names must be unique for correct spice simulation, but not enforced here. self.name = measure_name self.measure_scale = measure_scale - self.has_port = has_port #Needed for error checking - #Some meta values used externally. variables are added here for consistency accross the objects + self.has_port = has_port # Needed for error checking + # Some meta values used externally. variables are added here for consistency accross the objects self.meta_str = None self.meta_add_delay = False + @abstractmethod def get_measure_function(self): return None @@ -31,27 +33,27 @@ class spice_measurement(ABC): def write_measure(self, stim_obj, input_tuple): measure_func = self.get_measure_function() - if measure_func == None: - debug.error("Did not set measure function",1) + if measure_func is None: + debug.error("Did not set measure function", 1) measure_vals = self.get_measure_values(*input_tuple) measure_func(stim_obj, *measure_vals) def retrieve_measure(self, port=None): self.port_error_check(port) - if port != None: + if port is not None: value = parse_spice_list("timing", "{0}{1}".format(self.name.lower(), port)) else: value = parse_spice_list("timing", "{0}".format(self.name.lower())) - if type(value)!=float or self.measure_scale == None: + if type(value)!=float or self.measure_scale is None: return value else: - return value*self.measure_scale + return value * self.measure_scale def port_error_check(self, port): - if self.has_port and port == None: - debug.error("Cannot retrieve measurement, port input was expected.",1) - elif not self.has_port and port != None: - debug.error("Unexpected port input received during measure retrieval.",1) + if self.has_port and port is None: + debug.error("Cannot retrieve measurement, port input was expected.", 1) + elif not self.has_port and port is not None: + debug.error("Unexpected port input received during measure retrieval.", 1) class delay_measure(spice_measurement): @@ -90,7 +92,7 @@ class delay_measure(spice_measurement): trig_val = self.trig_val_of_vdd * vdd_voltage targ_val = self.targ_val_of_vdd * vdd_voltage - if port != None: + if port is not None: # For dictionary indexing reasons, the name is formatted differently than the signals meas_name = "{}{}".format(self.name, port) trig_name = self.trig_name_no_port.format(port) @@ -120,7 +122,7 @@ class slew_measure(delay_measure): self.trig_val_of_vdd = 0.9 self.targ_val_of_vdd = 0.1 else: - debug.error("Unrecognised slew measurement direction={}".format(slew_dir_str),1) + debug.error("Unrecognised slew measurement direction={}".format(slew_dir_str), 1) self.trig_name_no_port = signal_name self.targ_name_no_port = signal_name @@ -145,7 +147,7 @@ class power_measure(spice_measurement): def get_measure_values(self, t_initial, t_final, port=None): """Constructs inputs to stimulus measurement function. Variant values are inputs here.""" self.port_error_check(port) - if port != None: + if port is not None: meas_name = "{}{}".format(self.name, port) else: meas_name = self.name @@ -172,7 +174,7 @@ class voltage_when_measure(spice_measurement): def get_measure_values(self, trig_td, vdd_voltage, port=None): """Constructs inputs to stimulus measurement function. Variant values are inputs here.""" self.port_error_check(port) - if port != None: + if port is not None: # For dictionary indexing reasons, the name is formatted differently than the signals meas_name = "{}{}".format(self.name, port) trig_name = self.trig_name_no_port.format(port) @@ -203,7 +205,7 @@ class voltage_at_measure(spice_measurement): def get_measure_values(self, time_at, port=None): """Constructs inputs to stimulus measurement function. Variant values are inputs here.""" self.port_error_check(port) - if port != None: + if port is not None: # For dictionary indexing reasons, the name is formatted differently than the signals meas_name = "{}{}".format(self.name, port) targ_name = self.targ_name_no_port.format(port) diff --git a/compiler/characterizer/simulation.py b/compiler/characterizer/simulation.py index 568b639d..d256554a 100644 --- a/compiler/characterizer/simulation.py +++ b/compiler/characterizer/simulation.py @@ -235,7 +235,7 @@ class simulation(): self.add_wmask(wmask, port) self.add_spare_wen("1" * self.num_spare_cols, port) - #Add noops to all other ports. + # Add noops to all other ports. for unselected_port in self.all_ports: if unselected_port != port: self.add_noop_one_port(unselected_port) @@ -267,7 +267,7 @@ class simulation(): self.add_wmask("0" * self.num_wmasks, port) self.add_spare_wen("0" * self.num_spare_cols, port) - #Add noops to all other ports. + # Add noops to all other ports. for unselected_port in self.all_ports: if unselected_port != port: self.add_noop_one_port(unselected_port) @@ -356,14 +356,14 @@ class simulation(): self.add_noop_one_port(port) - #Add noops to all other ports. + # Add noops to all other ports. for unselected_port in self.all_ports: if unselected_port != port: self.add_noop_one_port(unselected_port) def append_cycle_comment(self, port, comment): """Add comment to list to be printed in stimulus file""" - #Clean up time before appending. Make spacing dynamic as well. + # Clean up time before appending. Make spacing dynamic as well. time = "{0:.2f} ns:".format(self.t_current) time_spacing = len(time) + 6 self.cycle_comments.append("Cycle {0:<6d} Port {1:<6} {2:<{3}}: {4}".format(len(self.cycle_times), @@ -388,7 +388,7 @@ class simulation(): split_word2 = [x + '_' * (n != 0 and n % 4 == 0) for n, x in enumerate(split_word)] # Join the word unreversed back together new_word = ''.join(reversed(split_word2)) - return(new_word) + return (new_word) # Split extra cols if self.num_spare_cols > 0: @@ -414,9 +414,9 @@ class simulation(): comment = "\tWriting {0} to address {1} (from port {2}) during cycle {3} ({4}ns - {5}ns)".format(word, addr, port, - int(t_current/self.period), + int(t_current / self.period), t_current, - t_current+self.period) + t_current + self.period) elif op == "partial_write": str = "\tWriting (partial) {0} to address {1} with mask bit {2} (from port {3}) during cycle {4} ({5}ns - {6}ns)" comment = str.format(word, @@ -454,7 +454,7 @@ class simulation(): for i in range(abits): pin_names.append("{0}{1}_{2}".format(addr_name, port, i)) - #Control signals not finalized. + # Control signals not finalized. for port in range(total_ports): pin_names.append("CSB{0}".format(port)) for port in range(total_ports): @@ -516,9 +516,9 @@ class simulation(): self.sen_name = sen_with_port debug.warning("Error occurred while determining SEN name. Can cause faults in simulation.") - column_addr = self.get_column_addr() + # column_addr = self.get_column_addr() bl_name_port, br_name_port = self.get_bl_name(self.graph.all_paths, port) - port_pos = -1 - len(str(column_addr)) - len(str(port)) + # port_pos = -1 - len(str(column_addr)) - len(str(port)) if bl_name_port.endswith(str(port) + "_" + str(self.bitline_column)): # single port SRAM case, bl will not be numbered eg bl_0 self.bl_name = bl_name_port @@ -536,7 +536,7 @@ class simulation(): '{}{}_{}'.format(self.dout_name, port, self.probe_data)) self.sen_name = self.get_sen_name(self.graph.all_paths) - #debug.info(2, "s_en {}".format(self.sen_name)) + # debug.info(2, "s_en {}".format(self.sen_name)) self.bl_name = "bl{0}_{1}".format(port, OPTS.word_size - 1) self.br_name = "br{0}_{1}".format(port, OPTS.word_size - 1) @@ -564,10 +564,10 @@ class simulation(): Creates timing graph to generate the timing paths for the SRAM output. """ - #Make exclusions dependent on the bit being tested. + # Make exclusions dependent on the bit being tested. self.sram.clear_exclude_bits() # Removes previous bit exclusions self.sram.graph_exclude_bits(self.wordline_row, self.bitline_column) - port=self.read_ports[0] #FIXME, port_data requires a port specification, assuming single port for now + port=self.read_ports[0] # FIXME, port_data requires a port specification, assuming single port for now if self.words_per_row > 1: self.sram.graph_clear_column_mux(port) self.sram.graph_exclude_column_mux(self.bitline_column, port) From b9dbad4750ba26e1471756110668caa47a7ae0c5 Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Fri, 9 Sep 2022 11:48:13 -0700 Subject: [PATCH 045/130] Separate measure statements from stimulus --- compiler/characterizer/delay.py | 22 ++++++++++++++++++---- compiler/characterizer/stimuli.py | 17 +++++++++-------- 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index 80540b94..10781df8 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -388,12 +388,17 @@ class delay(simulation): temp_stim = "{0}/{1}".format(OPTS.openram_temp, self.delay_stim_sp) self.sf = open(temp_stim, "w") + # creates and opens measure file for writing + self.delay_meas_sp = "delay_meas.sp" + temp_meas = "{0}/{1}".format(OPTS.openram_temp, self.delay_meas_sp) + self.mf = open(temp_meas, "w") + if OPTS.spice_name == "spectre": self.sf.write("simulator lang=spice\n") self.sf.write("* Delay stimulus for period of {0}n load={1}fF slew={2}ns\n\n".format(self.period, self.load, self.slew)) - self.stim = stimuli(self.sf, self.corner) + self.stim = stimuli(self.sf, self.mf, self.corner) # include files in stimulus file self.stim.write_include(self.trim_sp_file) @@ -418,6 +423,7 @@ class delay(simulation): t_rise=self.slew, t_fall=self.slew) + self.stim.write_include(temp_meas) # self.load_all_measure_nets() self.write_delay_measures() # self.write_simulation_saves() @@ -426,6 +432,7 @@ class delay(simulation): self.stim.write_control(self.cycle_times[-1] + self.period) self.sf.close() + self.mf.close() def write_power_stimulus(self, trim): """ Creates a stimulus file to measure leakage power only. @@ -440,6 +447,11 @@ class delay(simulation): self.sf.write("* Power stimulus for period of {0}n\n\n".format(self.period)) self.stim = stimuli(self.sf, self.corner) + # creates and opens measure file for writing + self.power_meas_sp = "power_meas.sp" + temp_meas = "{0}/{1}".format(opts.openram_temp, self.power_meas_sp) + self.mf = open(temp_meas, "w") + # include UNTRIMMED files in stimulus file if trim: self.stim.write_include(self.trim_sp_file) @@ -470,12 +482,14 @@ class delay(simulation): for port in self.all_ports: self.stim.gen_constant(sig_name="CLK{0}".format(port), v_val=0) + self.stim.write_include(temp_meas) self.write_power_measures() # run until the end of the cycle time self.stim.write_control(2 * self.period) self.sf.close() + self.mf.close() def get_measure_variants(self, port, measure_obj, measure_type=None): """ @@ -587,15 +601,15 @@ class delay(simulation): # Output some comments to aid where cycles start and # what is happening for comment in self.cycle_comments: - self.sf.write("* {0}\n".format(comment)) + self.mf.write("* {0}\n".format(comment)) self.sf.write("\n") for read_port in self.targ_read_ports: - self.sf.write("* Read ports {0}\n".format(read_port)) + self.mf.write("* Read ports {0}\n".format(read_port)) self.write_delay_measures_read_port(read_port) for write_port in self.targ_write_ports: - self.sf.write("* Write ports {0}\n".format(write_port)) + self.mf.write("* Write ports {0}\n".format(write_port)) self.write_delay_measures_write_port(write_port) def load_pex_net(self, net: str): diff --git a/compiler/characterizer/stimuli.py b/compiler/characterizer/stimuli.py index b9e4b3c7..8c91b49f 100644 --- a/compiler/characterizer/stimuli.py +++ b/compiler/characterizer/stimuli.py @@ -22,7 +22,7 @@ from globals import OPTS class stimuli(): """ Class for providing stimuli functions """ - def __init__(self, stim_file, corner): + def __init__(self, stim_file, meas_file, corner): self.vdd_name = "vdd" self.gnd_name = "gnd" self.pmos_name = tech.spice["pmos"] @@ -31,6 +31,7 @@ class stimuli(): self.tx_length = tech.drc["minlength_channel"] self.sf = stim_file + self.mf = meas_file (self.process, self.voltage, self.temperature) = corner found = False @@ -136,7 +137,7 @@ class stimuli(): offset, t_rise, t_fall, - 0.5*period-0.5*t_rise-0.5*t_fall, + 0.5 * period - 0.5 * t_rise - 0.5 * t_fall, period)) def gen_pwl(self, sig_name, clk_times, data_values, period, slew, setup): @@ -181,7 +182,7 @@ class stimuli(): def gen_meas_delay(self, meas_name, trig_name, targ_name, trig_val, targ_val, trig_dir, targ_dir, trig_td, targ_td): """ Creates the .meas statement for the measurement of delay """ measure_string=".meas tran {0} TRIG v({1}) VAL={2} {3}=1 TD={4}n TARG v({5}) VAL={6} {7}=1 TD={8}n\n\n" - self.sf.write(measure_string.format(meas_name.lower(), + self.mf.write(measure_string.format(meas_name.lower(), trig_name, trig_val, trig_dir, @@ -194,7 +195,7 @@ class stimuli(): def gen_meas_find_voltage(self, meas_name, trig_name, targ_name, trig_val, trig_dir, trig_td): """ Creates the .meas statement for the measurement of delay """ measure_string=".meas tran {0} FIND v({1}) WHEN v({2})={3}v {4}=1 TD={5}n \n\n" - self.sf.write(measure_string.format(meas_name.lower(), + self.mf.write(measure_string.format(meas_name.lower(), targ_name, trig_name, trig_val, @@ -204,7 +205,7 @@ class stimuli(): def gen_meas_find_voltage_at_time(self, meas_name, targ_name, time_at): """ Creates the .meas statement for voltage at time""" measure_string=".meas tran {0} FIND v({1}) AT={2}n \n\n" - self.sf.write(measure_string.format(meas_name.lower(), + self.mf.write(measure_string.format(meas_name.lower(), targ_name, time_at)) @@ -215,15 +216,15 @@ class stimuli(): power_exp = "power" else: power_exp = "par('(-1*v(" + str(self.vdd_name) + ")*I(v" + str(self.vdd_name) + "))')" - self.sf.write(".meas tran {0} avg {1} from={2}n to={3}n\n\n".format(meas_name.lower(), + self.mf.write(".meas tran {0} avg {1} from={2}n to={3}n\n\n".format(meas_name.lower(), power_exp, t_initial, t_final)) def gen_meas_value(self, meas_name, dout, t_initial, t_final): measure_string=".meas tran {0} FIND v({1}) AT={2}n\n\n".format(meas_name.lower(), dout, (t_initial + t_final) / 2) - #measure_string=".meas tran {0} AVG v({1}) FROM={2}n TO={3}n\n\n".format(meas_name.lower(), dout, t_initial, t_final) - self.sf.write(measure_string) + # measure_string=".meas tran {0} AVG v({1}) FROM={2}n TO={3}n\n\n".format(meas_name.lower(), dout, t_initial, t_final) + self.mf.write(measure_string) def write_control(self, end_time, runlvl=4): """ Write the control cards to run and end the simulation """ From b1e4c83373797e771a7ce55bc199042593bfc887 Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Fri, 9 Sep 2022 12:51:53 -0700 Subject: [PATCH 046/130] Move measure functions from stimuli to measure --- compiler/characterizer/delay.py | 2 + compiler/characterizer/functional.py | 1 + compiler/characterizer/measurements.py | 55 ++++++++++++++++++++------ 3 files changed, 46 insertions(+), 12 deletions(-) diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index 10781df8..dc52e8b4 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -698,6 +698,8 @@ class delay(simulation): self.sf.write("\n* Measure statements for idle leakage power\n") # add measure statements for power + # TODO: Convert to measure statement insted of using stimuli + # measure = power_measure('leakage_power', t_initial = self.period t_final = 2 * self.period self.stim.gen_meas_power(meas_name="leakage_power", diff --git a/compiler/characterizer/functional.py b/compiler/characterizer/functional.py index b6a57fb3..c0a0a980 100644 --- a/compiler/characterizer/functional.py +++ b/compiler/characterizer/functional.py @@ -484,6 +484,7 @@ class functional(simulation): measure_name, voltage_value, eo_period)) + # TODO: Convert to measurement statement instead of stimuli self.stim.gen_meas_value(meas_name=measure_name, dout=signal_name, t_initial=t_initial, diff --git a/compiler/characterizer/measurements.py b/compiler/characterizer/measurements.py index d4811d63..c29ed920 100644 --- a/compiler/characterizer/measurements.py +++ b/compiler/characterizer/measurements.py @@ -27,16 +27,17 @@ class spice_measurement(ABC): def get_measure_function(self): return None + @abstractmethod + def measure_function(self): + return None + @abstractmethod def get_measure_values(self): return None def write_measure(self, stim_obj, input_tuple): - measure_func = self.get_measure_function() - if measure_func is None: - debug.error("Did not set measure function", 1) measure_vals = self.get_measure_values(*input_tuple) - measure_func(stim_obj, *measure_vals) + self.measure_func(stim_obj, *measure_vals) def retrieve_measure(self, port=None): self.port_error_check(port) @@ -72,8 +73,18 @@ class delay_measure(spice_measurement): spice_measurement.__init__(self, measure_name, measure_scale, has_port) self.set_meas_constants(trig_name, targ_name, trig_dir_str, targ_dir_str, trig_vdd, targ_vdd) - def get_measure_function(self): - return stimuli.gen_meas_delay + def measure_function(self, stim_obj, meas_name, trig_name, targ_name, trig_val, targ_val, trig_dir, targ_dir, trig_td, targ_td): + """ Creates the .meas statement for the measurement of delay """ + measure_string=".meas tran {0} TRIG v({1}) VAL={2} {3}=1 TD={4}n TARG v({5}) VAL={6} {7}=1 TD={8}n\n\n" + stim_obj.mf.write(measure_string.format(meas_name.lower(), + trig_name, + trig_val, + trig_dir, + trig_td, + targ_name, + targ_val, + targ_dir, + targ_td)) def set_meas_constants(self, trig_name, targ_name, trig_dir_str, targ_dir_str, trig_vdd, targ_vdd): """Set the constants for this measurement: signal names, directions, and trigger scales""" @@ -136,8 +147,17 @@ class power_measure(spice_measurement): spice_measurement.__init__(self, measure_name, measure_scale, has_port) self.set_meas_constants(power_type) - def get_measure_function(self): - return stimuli.gen_meas_power + def measure_function(self, stim_obj, meas_name, t_initial, t_final): + """ Creates the .meas statement for the measurement of avg power """ + # power mea cmd is different in different spice: + if OPTS.spice_name == "hspice": + power_exp = "power" + else: + power_exp = "par('(-1*v(" + str(self.vdd_name) + ")*I(v" + str(self.vdd_name) + "))')" + stim_obj.mf.write(".meas tran {0} avg {1} from={2}n to={3}n\n\n".format(meas_name.lower(), + power_exp, + t_initial, + t_final)) def set_meas_constants(self, power_type): """Sets values useful for power simulations. This value is only meta related to the lib file (rise/fall)""" @@ -161,8 +181,15 @@ class voltage_when_measure(spice_measurement): spice_measurement.__init__(self, measure_name, measure_scale, has_port) self.set_meas_constants(trig_name, targ_name, trig_dir_str, trig_vdd) - def get_measure_function(self): - return stimuli.gen_meas_find_voltage + def gen_meas_find_voltage(self, stim_obj, meas_name, trig_name, targ_name, trig_val, trig_dir, trig_td): + """ Creates the .meas statement for the measurement of delay """ + measure_string=".meas tran {0} FIND v({1}) WHEN v({2})={3}v {4}=1 TD={5}n \n\n" + stim_obj.mf.write(measure_string.format(meas_name.lower(), + targ_name, + trig_name, + trig_val, + trig_dir, + trig_td)) def set_meas_constants(self, trig_name, targ_name, trig_dir_str, trig_vdd): """Sets values useful for power simulations. This value is only meta related to the lib file (rise/fall)""" @@ -195,8 +222,12 @@ class voltage_at_measure(spice_measurement): spice_measurement.__init__(self, measure_name, measure_scale, has_port) self.set_meas_constants(targ_name) - def get_measure_function(self): - return stimuli.gen_meas_find_voltage_at_time + def gen_meas_find_voltage_at_time(self, stim_obj, meas_name, targ_name, time_at): + """ Creates the .meas statement for voltage at time""" + measure_string=".meas tran {0} FIND v({1}) AT={2}n \n\n" + stim_obj.mf.write(measure_string.format(meas_name.lower(), + targ_name, + time_at)) def set_meas_constants(self, targ_name): """Sets values useful for power simulations. This value is only meta related to the lib file (rise/fall)""" From 214f55f8d71ac14cfc8d382192e49cf658d39cca Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Wed, 14 Sep 2022 14:34:22 -0700 Subject: [PATCH 047/130] Save trimmed spice and stimulus --- compiler/characterizer/delay.py | 23 ++++++++++++++------- compiler/characterizer/functional.py | 5 ++++- compiler/modules/sram.py | 31 ++++++++++++++++++---------- 3 files changed, 39 insertions(+), 20 deletions(-) diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index dc52e8b4..59633a5b 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -37,7 +37,7 @@ class delay(simulation): """ - def __init__(self, sram, spfile, corner): + def __init__(self, sram, spfile, corner, output_path=None): super().__init__(sram, spfile, corner) self.targ_read_ports = [] @@ -47,6 +47,12 @@ class delay(simulation): self.num_wmasks = int(math.ceil(self.word_size / self.write_size)) else: self.num_wmasks = 0 + + if output_path is None: + self.output_path = OPTS.openram_temp + else: + self.output_path = output_path + self.set_load_slew(0, 0) self.set_corner(corner) self.create_signal_names() @@ -385,12 +391,12 @@ class delay(simulation): # creates and opens stimulus file for writing self.delay_stim_sp = "delay_stim.sp" - temp_stim = "{0}/{1}".format(OPTS.openram_temp, self.delay_stim_sp) + temp_stim = "{0}/{1}".format(self.output_path, self.delay_stim_sp) self.sf = open(temp_stim, "w") # creates and opens measure file for writing self.delay_meas_sp = "delay_meas.sp" - temp_meas = "{0}/{1}".format(OPTS.openram_temp, self.delay_meas_sp) + temp_meas = "{0}/{1}".format(self.output_path, self.delay_meas_sp) self.mf = open(temp_meas, "w") if OPTS.spice_name == "spectre": @@ -442,7 +448,7 @@ class delay(simulation): # creates and opens stimulus file for writing self.power_stim_sp = "power_stim.sp" - temp_stim = "{0}/{1}".format(OPTS.openram_temp, self.power_stim_sp) + temp_stim = "{0}/{1}".format(self.output_path, self.power_stim_sp) self.sf = open(temp_stim, "w") self.sf.write("* Power stimulus for period of {0}n\n\n".format(self.period)) self.stim = stimuli(self.sf, self.corner) @@ -1131,16 +1137,17 @@ class delay(simulation): # Set up to trim the netlist here if that is enabled if OPTS.trim_netlist: - self.trim_sp_file = "{0}trimmed.sp".format(OPTS.openram_temp) + self.trim_sp_file = "{0}trimmed.sp".format(self.output_path) self.sram.sp_write(self.trim_sp_file, lvs=False, trim=True) else: # The non-reduced netlist file when it is disabled - self.trim_sp_file = "{0}sram.sp".format(OPTS.openram_temp) + self.trim_sp_file = "{0}sram.sp".format(self.output_path) # The non-reduced netlist file for power simulation - self.sim_sp_file = "{0}sram.sp".format(OPTS.openram_temp) + self.sim_sp_file = "{0}sram.sp".format(self.output_path) # Make a copy in temp for debugging - shutil.copy(self.sp_file, self.sim_sp_file) + if self.sp_file != self.sim_sp_file: + shutil.copy(self.sp_file, self.sim_sp_file) def analysis_init(self, probe_address, probe_data): """Sets values which are dependent on the data address/bit being tested.""" diff --git a/compiler/characterizer/functional.py b/compiler/characterizer/functional.py index c0a0a980..fea58207 100644 --- a/compiler/characterizer/functional.py +++ b/compiler/characterizer/functional.py @@ -383,7 +383,10 @@ class functional(simulation): temp_stim = "{0}/{1}".format(self.output_path, self.stim_sp) self.sf = open(temp_stim, "w") self.sf.write("* Functional test stimulus file for {0}ns period\n\n".format(self.period)) - self.stim = stimuli(self.sf, self.corner) + self.meas_sp = "functional_meas.sp" + temp_meas = "{0}/{1}".format(self.output_path, self.meas_sp) + self.mf = open(temp_meas, "w") + self.stim = stimuli(self.sf, self.mf, self.corner) # Write include statements self.stim.write_include(self.sp_file) diff --git a/compiler/modules/sram.py b/compiler/modules/sram.py index 2a722709..ba548e80 100644 --- a/compiler/modules/sram.py +++ b/compiler/modules/sram.py @@ -8,7 +8,7 @@ import datetime import os import debug -from characterizer import functional +from characterizer import functional, delay from base import timing_graph from globals import OPTS, print_time import shutil @@ -115,6 +115,25 @@ class sram(): output_path=OPTS.output_path) print_time("Spice writing", datetime.datetime.now(), start_time) + # Save stimulus and measurement file + start_time = datetime.datetime.now() + debug.print_raw("DELAY: Writing stimulus...") + d = delay(self.s, self.get_sp_name(), ("TT", 5, 25), output_path=OPTS.output_path) + if (self.s.num_spare_rows == 0): + probe_address = "1" * self.s.addr_size + else: + probe_address = "0" + "1" * (self.s.addr_size - 1) + probe_data = self.s.word_size - 1 + d.analysis_init(probe_address, probe_data) + d.targ_read_ports.extend(self.s.read_ports) + d.targ_write_ports = [self.s.write_ports[0]] + d.write_delay_stimulus() + print_time("DELAY", datetime.datetime.now(), start_time) + + # Save trimmed spice file + temp_trim_sp = "{0}trimmed.sp".format(OPTS.output_path) + self.sp_write(temp_trim_sp, lvs=False, trim=True) + if not OPTS.netlist_only: # Write the layout start_time = datetime.datetime.now() @@ -188,13 +207,3 @@ class sram(): debug.print_raw("Extended Config: Writing to {0}".format(oname)) self.extended_config_write(oname) print_time("Extended Config", datetime.datetime.now(), start_time) - - # Write the graph if specified - if OPTS.write_graph: - start_time = datetime.datetime.now() - oname = OPTS.output_path + OPTS.output_name + "_graph.json" - debug.print_raw("Graph: Writing to {0}".format(oname)) - graph = timing_graph() - self.s.build_graph(graph, self.name, self.s.pins) - graph.write(oname) - print_time("Graph", datetime.datetime.now(), start_time) From 2d8d90952e8cf54fe2034adceaa3e2a52ca9436a Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Wed, 14 Sep 2022 14:34:50 -0700 Subject: [PATCH 048/130] Fix measure functions --- compiler/characterizer/measurements.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/compiler/characterizer/measurements.py b/compiler/characterizer/measurements.py index c29ed920..ec2fd638 100644 --- a/compiler/characterizer/measurements.py +++ b/compiler/characterizer/measurements.py @@ -23,10 +23,6 @@ class spice_measurement(ABC): self.meta_str = None self.meta_add_delay = False - @abstractmethod - def get_measure_function(self): - return None - @abstractmethod def measure_function(self): return None @@ -37,7 +33,7 @@ class spice_measurement(ABC): def write_measure(self, stim_obj, input_tuple): measure_vals = self.get_measure_values(*input_tuple) - self.measure_func(stim_obj, *measure_vals) + self.measure_function(stim_obj, *measure_vals) def retrieve_measure(self, port=None): self.port_error_check(port) @@ -153,7 +149,8 @@ class power_measure(spice_measurement): if OPTS.spice_name == "hspice": power_exp = "power" else: - power_exp = "par('(-1*v(" + str(self.vdd_name) + ")*I(v" + str(self.vdd_name) + "))')" + # FIXME: Obtain proper vdd and gnd name + power_exp = "par('(-1*v(" + "vdd" + ")*I(v" + "vdd" + "))')" stim_obj.mf.write(".meas tran {0} avg {1} from={2}n to={3}n\n\n".format(meas_name.lower(), power_exp, t_initial, @@ -181,7 +178,7 @@ class voltage_when_measure(spice_measurement): spice_measurement.__init__(self, measure_name, measure_scale, has_port) self.set_meas_constants(trig_name, targ_name, trig_dir_str, trig_vdd) - def gen_meas_find_voltage(self, stim_obj, meas_name, trig_name, targ_name, trig_val, trig_dir, trig_td): + def measure_function(self, stim_obj, meas_name, trig_name, targ_name, trig_val, trig_dir, trig_td): """ Creates the .meas statement for the measurement of delay """ measure_string=".meas tran {0} FIND v({1}) WHEN v({2})={3}v {4}=1 TD={5}n \n\n" stim_obj.mf.write(measure_string.format(meas_name.lower(), @@ -222,7 +219,7 @@ class voltage_at_measure(spice_measurement): spice_measurement.__init__(self, measure_name, measure_scale, has_port) self.set_meas_constants(targ_name) - def gen_meas_find_voltage_at_time(self, stim_obj, meas_name, targ_name, time_at): + def measure_function(self, stim_obj, meas_name, targ_name, time_at): """ Creates the .meas statement for voltage at time""" measure_string=".meas tran {0} FIND v({1}) AT={2}n \n\n" stim_obj.mf.write(measure_string.format(meas_name.lower(), From c6440dc16d75a86cabd84c8a35a52a8be9078976 Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Tue, 27 Sep 2022 13:44:28 -0700 Subject: [PATCH 049/130] restore netlist on memchar --- compiler/characterizer/delay.py | 7 +++-- compiler/characterizer/fake_sram.py | 41 +++-------------------------- 2 files changed, 8 insertions(+), 40 deletions(-) diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index 59633a5b..cec1d49a 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -1130,15 +1130,17 @@ class delay(simulation): Netlist reduced for simulation. """ super().set_probe(probe_address, probe_data) - self.prepare_netlist() def prepare_netlist(self): """ Prepare a trimmed netlist and regular netlist. """ # Set up to trim the netlist here if that is enabled + # TODO: Copy old netlist if memchar if OPTS.trim_netlist: self.trim_sp_file = "{0}trimmed.sp".format(self.output_path) - self.sram.sp_write(self.trim_sp_file, lvs=False, trim=True) + # Only genrate spice when running openram process + if OPTS.top_process == "openram": + self.sram.sp_write(self.trim_sp_file, lvs=False, trim=True) else: # The non-reduced netlist file when it is disabled self.trim_sp_file = "{0}sram.sp".format(self.output_path) @@ -1153,6 +1155,7 @@ class delay(simulation): """Sets values which are dependent on the data address/bit being tested.""" self.set_probe(probe_address, probe_data) + self.prepare_netlist() self.create_graph() self.set_internal_spice_names() self.create_measurement_names() diff --git a/compiler/characterizer/fake_sram.py b/compiler/characterizer/fake_sram.py index 44c98606..1799fc82 100644 --- a/compiler/characterizer/fake_sram.py +++ b/compiler/characterizer/fake_sram.py @@ -10,44 +10,9 @@ class fake_sram(sram_config): """ def __init__(self, name, word_size, num_words, write_size=None, num_banks=1, words_per_row=None, num_spare_rows=0, num_spare_cols=0): - self.name = name - self.word_size = word_size - self.num_words = num_words - # Don't add a write mask if it is the same size as the data word - if write_size and write_size==word_size: - self.write_size = None - else: - self.write_size = write_size - self.num_banks = num_banks - self.num_spare_rows = num_spare_rows - self.num_spare_cols = num_spare_cols - - try: - from tech import array_row_multiple - self.array_row_multiple = array_row_multiple - except ImportError: - self.array_row_multiple = 1 - try: - from tech import array_col_multiple - self.array_col_multiple = array_col_multiple - except ImportError: - self.array_col_multiple = 1 - - if self.write_size: - self.num_wmasks = int(ceil(self.word_size / self.write_size)) - else: - self.num_wmasks = 0 - - if not self.num_spare_cols: - self.num_spare_cols = 0 - - if not self.num_spare_rows: - self.num_spare_rows = 0 - - # This will get over-written when we determine the organization - self.words_per_row = words_per_row - - self.compute_sizes() + sram_config.__init__(self, name, word_size, num_words, write_size=None, + num_banks=1, words_per_row=None, num_spare_rows=0, + num_spare_cols=0) def setup_multiport_constants(self): """ From 6603220258c4393a614762859392384ec67b625f Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Tue, 4 Oct 2022 15:05:38 -0700 Subject: [PATCH 050/130] Fake sram using sram class as base --- compiler/characterizer/fake_sram_v2.py | 51 ++++++++++++++++++++++++++ compiler/memchar.py | 25 +++++++------ compiler/modules/sram.py | 4 +- 3 files changed, 66 insertions(+), 14 deletions(-) create mode 100644 compiler/characterizer/fake_sram_v2.py diff --git a/compiler/characterizer/fake_sram_v2.py b/compiler/characterizer/fake_sram_v2.py new file mode 100644 index 00000000..134c15ac --- /dev/null +++ b/compiler/characterizer/fake_sram_v2.py @@ -0,0 +1,51 @@ +# This is a temp file. Remove either this or the fake_sram.py + +from modules import sram +import debug +from globals import OPTS +import os + + +class fake_sram_v2(sram): + + def create_netlist(self): + # Make sure spice file is here + debug.check(os.path.exists(self.sp_name), "Spice netlist in {} not found".format(self.sp_name)) + + def generate_pins(self): + self.pins = ['vdd', 'gnd'] + self.pins.extend(['clk{}'.format(port) for port in range( + OPTS.num_rw_ports + OPTS.num_r_ports + OPTS.num_w_ports)]) + for port in range(OPTS.num_rw_ports): + self.pins.extend(['din{0}[{1}]'.format(port, bit) + for bit in range(self.num_cols)]) + self.pins.extend(['dout{0}[{1}]'.format(port, bit) + for bit in range(self.num_cols)]) + self.pins.extend(['addr{0}[{1}]'.format(port, bit) + for bit in range(self.addr_size)]) + #if self.num_wmasks != 0: + # self.pins.extend(['wmask{0}[{1}]'.format(port, bit) + # for bit in range(self.num_wmasks)]) + + self.pins.extend(['csb{}'.format(port), 'web{}'.format(port)]) + + start_port = OPTS.num_rw_ports + for port in range(start_port, start_port + OPTS.num_r_ports): + self.pins.extend(['dout{0}[{1}]'.format(port, bit) + for bit in range(self.num_cols)]) + self.pins.extend(['addr{0}[{1}]'.format(port, bit) + for bit in range(self.addr_size)]) + + self.pins.extend(['csb{}'.format(port)]) + + start_port += OPTS.num_r_ports + for port in range(start_port, start_port + OPTS.num_w_ports): + self.pins.extend(['din{0}[{1}]'.format(port, bit) + for bit in range(self.num_cols)]) + self.pins.extend(['addr{0}[{1}]'.format(port, bit) + for bit in range(self.addr_size)]) + if self.num_wmasks != 0: + self.pins.extend(['wmask{0}[{1}]'.format(port, bit) + for bit in range(self.num_wmasks)]) + + self.pins.extend(['csb{}'.format(port), 'web{}'.format(port)]) diff --git a/compiler/memchar.py b/compiler/memchar.py index 425a8abd..1d140050 100755 --- a/compiler/memchar.py +++ b/compiler/memchar.py @@ -39,19 +39,22 @@ init_openram(config_file=args[0], is_unit_test=False) print_banner() # Configure the SRAM organization (duplicated from openram.py) -from characterizer.fake_sram import fake_sram -s = fake_sram(name=OPTS.output_name, - word_size=OPTS.word_size, - num_words=OPTS.num_words, - write_size=OPTS.write_size, - num_banks=OPTS.num_banks, - words_per_row=OPTS.words_per_row, - num_spare_rows=OPTS.num_spare_rows, - num_spare_cols=OPTS.num_spare_cols) +#from characterizer.fake_sram import fake_sram +from modules import sram_config +from characterizer.fake_sram_v2 import fake_sram_v2 +config = sram_config(word_size=OPTS.word_size, + num_words=OPTS.num_words, + write_size=OPTS.write_size, + num_banks=OPTS.num_banks, + words_per_row=OPTS.words_per_row, + num_spare_rows=OPTS.num_spare_rows, + num_spare_cols=OPTS.num_spare_cols) +s = fake_sram_v2(name=OPTS.output_name, + sram_config=config) -s.parse_html(args[1]) +#s.parse_html(args[1]) s.generate_pins() -s.setup_multiport_constants() +#s.setup_multiport_constants() OPTS.netlist_only = True OPTS.check_lvsdrc = False diff --git a/compiler/modules/sram.py b/compiler/modules/sram.py index 37590887..912e82c5 100644 --- a/compiler/modules/sram.py +++ b/compiler/modules/sram.py @@ -48,11 +48,9 @@ class sram(): self.num_banks)) start_time = datetime.datetime.now() - self.name = name - from .sram_1bank import sram_1bank as sram - self.s = sram(name, sram_config) + self.s = sram(self.name, self.config) self.s.create_netlist() if not OPTS.netlist_only: From 816eff711d68c54485545f6e6b42108d6fa7f91c Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Tue, 29 Nov 2022 14:48:35 -0800 Subject: [PATCH 051/130] Recover function for measures --- compiler/characterizer/delay.py | 109 ++++++++++++++++++++++++---- compiler/characterizer/fake_sram.py | 30 +++++--- 2 files changed, 112 insertions(+), 27 deletions(-) diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index 76f693d8..ded58f93 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -17,6 +17,8 @@ from .bit_polarity import * from globals import OPTS from .simulation import simulation from .measurements import * +from os import path +import re class delay(simulation): @@ -118,8 +120,10 @@ class delay(simulation): # Other measurements associated with the read port not included in the liberty file read_measures.append(self.create_bitline_measurement_objects()) read_measures.append(self.create_debug_measurement_objects()) - read_measures.append(self.create_read_bit_measures()) - read_measures.append(self.create_sen_and_bitline_path_measures()) + # TODO: Maybe don't do this here (?) + if OPTS.top_process != "memchar": + read_measures.append(self.create_read_bit_measures()) + read_measures.append(self.create_sen_and_bitline_path_measures()) return read_measures @@ -245,8 +249,8 @@ class delay(simulation): def create_sen_and_bitline_path_measures(self): """Create measurements for the s_en and bitline paths for individual delays per stage.""" - # FIXME: There should be a default_read_port variable in this case, pathing is done with this - # but is never mentioned otherwise +# # FIXME: There should be a default_read_port variable in this case, pathing is done with this +# # but is never mentioned otherwise port = self.read_ports[0] sen_and_port = self.sen_name + str(port) bl_and_port = self.bl_name.format(port) # bl_name contains a '{}' for the port @@ -391,12 +395,12 @@ class delay(simulation): # creates and opens stimulus file for writing self.delay_stim_sp = "delay_stim.sp" - temp_stim = "{0}/{1}".format(self.output_path, self.delay_stim_sp) + temp_stim = path.join(self.output_path, self.delay_stim_sp) self.sf = open(temp_stim, "w") # creates and opens measure file for writing self.delay_meas_sp = "delay_meas.sp" - temp_meas = "{0}/{1}".format(self.output_path, self.delay_meas_sp) + temp_meas = path.join(self.output_path, self.delay_meas_sp) self.mf = open(temp_meas, "w") if OPTS.spice_name == "spectre": @@ -429,7 +433,7 @@ class delay(simulation): t_rise=self.slew, t_fall=self.slew) - self.stim.write_include(temp_meas) + self.sf.write(".include {0}".format(temp_meas)) # self.load_all_measure_nets() self.write_delay_measures() # self.write_simulation_saves() @@ -448,15 +452,15 @@ class delay(simulation): # creates and opens stimulus file for writing self.power_stim_sp = "power_stim.sp" - temp_stim = "{0}/{1}".format(self.output_path, self.power_stim_sp) + temp_stim = path.join(self.output_path, self.power_stim_sp) self.sf = open(temp_stim, "w") self.sf.write("* Power stimulus for period of {0}n\n\n".format(self.period)) - self.stim = stimuli(self.sf, self.corner) # creates and opens measure file for writing self.power_meas_sp = "power_meas.sp" - temp_meas = "{0}/{1}".format(opts.openram_temp, self.power_meas_sp) + temp_meas = path.join(self.output_path, self.power_meas_sp) self.mf = open(temp_meas, "w") + self.stim = stimuli(self.sf, self.mf, self.corner) # include UNTRIMMED files in stimulus file if trim: @@ -488,7 +492,7 @@ class delay(simulation): for port in self.all_ports: self.stim.gen_constant(sig_name="CLK{0}".format(port), v_val=0) - self.stim.write_include(temp_meas) + self.sf.write(".include {}".format(temp_meas)) self.write_power_measures() # run until the end of the cycle time @@ -1151,15 +1155,90 @@ class delay(simulation): if self.sp_file != self.sim_sp_file: shutil.copy(self.sp_file, self.sim_sp_file) + def recover_measurment_objects(self): + mf = open(path.join(OPTS.output_path, "delay_meas.sp"), "r") + measure_text = mf.read() + port_iter = re.finditer(r"\* (Read|Write) ports (\d*)", measure_text) + port_measure_lines = [] + loc = 0 + port_name = '' + for port in port_iter: + port_measure_lines.append((port_name, measure_txt[loc:port.end(0)])) + loc = port.start(0) + port_name = port.group(1) + port.group(2) + + mf.close() + # Cycle comments, not sure if i need this + cycle_lines = port_measure_lines.pop(0)[1] + # For now just recover the bit_measures and sen_and_bitline_path_measures + self.read_meas_lists.append([]) + bit_measure_rule = re.compile(r"\.meas tran (v_q_a\d+_b\d+_(read|write)_(zero|one)\d+) FIND v\((.*)\) AT=(\d+(\.\d+)?)n") + for measures in port_measure_lines: + port_name = measures[0] + text = measures[1] + bit_measure_iter = bit_measure_rule.finditer(text) + for bit_measure in bit_measure_iter: + meas_name = bit_measure.group(1) + read = bit_measure.group(2) == "read" + probe = bit_measure.group(4) + polarity = bit_polarity.NONINVERTING + if "q_bar" in meas_name: + polarity = bit_polarity.INVERTING + meas = voltage_at_measure(meas_name, probe) + if read: + self.read_bit_meas[polarity].append(meas) + self.read_meas_lists[-1].append(meas) + else: + self.write_bit_meas[polarity].append(meas) + self.write_meas_lists[-1].append(meas) + + delay_path_rule = re.compile(r"\.meas tran delay_(.*)_to_(.*) TRIG v\((.*)\) VAL=(\d+(\.\d+)?) (RISE|FALL)=(\d+) TD=(\d+(\.\d+)?)n TARG v\((.*)\) VAL=(\d+(\.\d+)?) (RISE|FALL)=(\d+) TD=(\d+(\.\d+)?)n") + port = self.read_ports[0] + sen_and_port = self.sen_name + str(port) + bl_and_port = self.bl_name.format(port) # bl_name contains a '{}' for the port + meas_buff = [] + for measures in port_measure_lines: + port_name = measures[0] + text = measures[1] + delay_path_iter = delay_path_rule.finditer(text) + for delay_path_measure in delay_path_iter: + from_ = delay_path_measure.group(1) + to_ = delay_path_measure.group(2) + trig_rise = delay_path_measure.group(5) + targ_rise = delay_path_measure.group(10) + meas_name = "delay_{0}_to_{1}".format(from_, to_) + meas = delay_measure(meas_name, from_, to_, trig_rise, targ_rise, measure_scale=1e9, has_port=False) + meas.meta_str = sram_op.READ_ZERO + meas.meta_add_delay = True + meas_buff.append(meas) + # TODO: we are losing duplicate measures here + if from_ == sen_and_port: + self.sen_path_meas.extend(meas_buff.copy()) + meas_buff.clear() + elif from_ == bl_and_port: + self.bl_path_meas.extend(meas_buff) + meas_buff.clear() + self.read_meas_lists.append(self.sen_path_meas + self.bl_path_meas) + + + def analysis_init(self, probe_address, probe_data): """Sets values which are dependent on the data address/bit being tested.""" self.set_probe(probe_address, probe_data) self.prepare_netlist() - self.create_graph() - self.set_internal_spice_names() - self.create_measurement_names() - self.create_measurement_objects() + if OPTS.top_process == "memchar": + # TODO: fix + self.bl_name = "xsram.xbank0.bl_0_{}" + self.br_name = "xsram.xbank0.br_0_{}" + self.sen_name = "xsram.s_en" + self.create_measurement_objects() + self.recover_measurment_objects() + else: + self.create_graph() + self.set_internal_spice_names() + self.create_measurement_names() + self.create_measurement_objects() def analyze(self, probe_address, probe_data, load_slews): """ diff --git a/compiler/characterizer/fake_sram.py b/compiler/characterizer/fake_sram.py index 1799fc82..9d2a409c 100644 --- a/compiler/characterizer/fake_sram.py +++ b/compiler/characterizer/fake_sram.py @@ -10,9 +10,14 @@ class fake_sram(sram_config): """ def __init__(self, name, word_size, num_words, write_size=None, num_banks=1, words_per_row=None, num_spare_rows=0, num_spare_cols=0): - sram_config.__init__(self, name, word_size, num_words, write_size=None, - num_banks=1, words_per_row=None, num_spare_rows=0, - num_spare_cols=0) + sram_config.__init__(self, word_size, num_words, write_size, + num_banks, words_per_row, num_spare_rows, + num_spare_cols) + self.name = name + if write_size and self.write_size != self.word_size: + self.num_wmasks = int(ceil(self.word_size / self.write_size)) + else: + self.num_wmasks = 0 def setup_multiport_constants(self): """ @@ -88,35 +93,36 @@ class fake_sram(sram_config): self.pins.extend(['clk{}'.format(port) for port in range( self.num_rw_ports + self.num_r_ports + self.num_w_ports)]) for port in range(self.num_rw_ports): - self.pins.extend(['din{0}[{1}]]'.format(port, bit) + self.pins.extend(['din{0}[{1}]'.format(port, bit) for bit in range(self.num_cols)]) - self.pins.extend(['dout{0}[{1}]]'.format(port, bit) + self.pins.extend(['dout{0}[{1}]'.format(port, bit) for bit in range(self.num_cols)]) - self.pins.extend(['addr{0}[{1}]]'.format(port, bit) + self.pins.extend(['addr{0}[{1}]'.format(port, bit) for bit in range(self.addr_size)]) if self.num_wmasks != 0: - self.pins.extend(['wmask{0}[{1}]]'.format(port, bit) + print(self.num_wmasks) + self.pins.extend(['wmask{0}[{1}]'.format(port, bit) for bit in range(self.num_wmasks)]) self.pins.extend(['csb{}'.format(port), 'web{}'.format(port)]) start_port = self.num_rw_ports for port in range(start_port, start_port + self.num_r_ports): - self.pins.extend(['dout{0}[{1}]]'.format(port, bit) + self.pins.extend(['dout{0}[{1}]'.format(port, bit) for bit in range(self.num_cols)]) - self.pins.extend(['addr{0}[{1}]]'.format(port, bit) + self.pins.extend(['addr{0}[{1}]'.format(port, bit) for bit in range(self.addr_size)]) self.pins.extend(['csb{}'.format(port)]) start_port += self.num_r_ports for port in range(start_port, start_port + self.num_w_ports): - self.pins.extend(['din{0}[{1}]]'.format(port, bit) + self.pins.extend(['din{0}[{1}]'.format(port, bit) for bit in range(self.num_cols)]) - self.pins.extend(['addr{0}[{1}]]'.format(port, bit) + self.pins.extend(['addr{0}[{1}]'.format(port, bit) for bit in range(self.addr_size)]) if self.num_wmasks != 0: - self.pins.extend(['wmask{0}[{1}]]'.format(port, bit) + self.pins.extend(['wmask{0}[{1}]'.format(port, bit) for bit in range(self.num_wmasks)]) self.pins.extend(['csb{}'.format(port), 'web{}'.format(port)]) From c6485277f312d5f09c3ac472553756f0bac7c56b Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Tue, 29 Nov 2022 14:53:02 -0800 Subject: [PATCH 052/130] New import method into memchar script --- compiler/memchar.py | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/compiler/memchar.py b/compiler/memchar.py index 1d140050..02ed8a3a 100755 --- a/compiler/memchar.py +++ b/compiler/memchar.py @@ -17,6 +17,10 @@ import sys import datetime from globals import * from importlib import reload +try: + import openram +except: + sys.path.append(os.getenv("OPENRAM_HOME")) (OPTS, args) = parse_args() @@ -39,22 +43,19 @@ init_openram(config_file=args[0], is_unit_test=False) print_banner() # Configure the SRAM organization (duplicated from openram.py) -#from characterizer.fake_sram import fake_sram -from modules import sram_config -from characterizer.fake_sram_v2 import fake_sram_v2 -config = sram_config(word_size=OPTS.word_size, - num_words=OPTS.num_words, - write_size=OPTS.write_size, - num_banks=OPTS.num_banks, - words_per_row=OPTS.words_per_row, - num_spare_rows=OPTS.num_spare_rows, - num_spare_cols=OPTS.num_spare_cols) -s = fake_sram_v2(name=OPTS.output_name, - sram_config=config) +from characterizer.fake_sram import fake_sram +s = fake_sram(name=OPTS.output_name, + word_size=OPTS.word_size, + num_words=OPTS.num_words, + write_size=OPTS.write_size, + num_banks=OPTS.num_banks, + words_per_row=OPTS.words_per_row, + num_spare_rows=OPTS.num_spare_rows, + num_spare_cols=OPTS.num_spare_cols) -#s.parse_html(args[1]) +s.parse_html(args[1]) s.generate_pins() -#s.setup_multiport_constants() +s.setup_multiport_constants() OPTS.netlist_only = True OPTS.check_lvsdrc = False From db85e8ecd674b9635999906c5b44786f896db5b6 Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Tue, 13 Dec 2022 07:53:58 -0800 Subject: [PATCH 053/130] standalone char and func --- compiler/characterizer/delay.py | 56 +++++++++++++++++---------- compiler/characterizer/functional.py | 38 +++++++++++------- compiler/modules/sram.py | 11 ++++-- compiler/modules/sram_config.py | 5 --- compiler/{memchar.py => sram_char.py} | 0 compiler/{memfunc.py => sram_func.py} | 28 +++++++------- 6 files changed, 84 insertions(+), 54 deletions(-) rename compiler/{memchar.py => sram_char.py} (100%) rename compiler/{memfunc.py => sram_func.py} (72%) diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index ded58f93..53874f23 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -59,6 +59,7 @@ class delay(simulation): self.set_corner(corner) self.create_signal_names() self.add_graph_exclusions() + self.meas_id = 0 def create_measurement_objects(self): """ Create the measurements used for read and write ports """ @@ -167,7 +168,9 @@ class delay(simulation): write_measures = [] write_measures.append(self.write_lib_meas) - write_measures.append(self.create_write_bit_measures()) + if OPTS.top_process != "memchar": + write_measures.append(self.create_write_bit_measures()) + return write_measures def create_debug_measurement_objects(self): @@ -265,8 +268,8 @@ class delay(simulation): bitline_path = bl_paths[0] # Get the measures - self.sen_path_meas = self.create_delay_path_measures(sen_path) - self.bl_path_meas = self.create_delay_path_measures(bitline_path) + self.sen_path_meas = self.create_delay_path_measures(sen_path, "sen") + self.bl_path_meas = self.create_delay_path_measures(bitline_path, "bl") all_meas = self.sen_path_meas + self.bl_path_meas # Paths could have duplicate measurements, remove them before they go to the stim file @@ -288,7 +291,7 @@ class delay(simulation): return unique_measures - def create_delay_path_measures(self, path): + def create_delay_path_measures(self, path, process): """Creates measurements for each net along given path.""" # Determine the directions (RISE/FALL) of signals @@ -300,6 +303,8 @@ class delay(simulation): cur_net, next_net = path[i], path[i + 1] cur_dir, next_dir = path_dirs[i], path_dirs[i + 1] meas_name = "delay_{0}_to_{1}".format(cur_net, next_net) + meas_name += "_" + process + "_id" + str(self.meas_id) + self.meas_id += 1 if i + 1 != len(path) - 1: path_meas.append(delay_measure(meas_name, cur_net, next_net, cur_dir, next_dir, measure_scale=1e9, has_port=False)) else: # Make the last measurement always measure on FALL because is a read 0 @@ -1163,15 +1168,17 @@ class delay(simulation): loc = 0 port_name = '' for port in port_iter: - port_measure_lines.append((port_name, measure_txt[loc:port.end(0)])) + port_measure_lines.append((port_name, measure_text[loc:port.end(0)])) loc = port.start(0) port_name = port.group(1) + port.group(2) mf.close() # Cycle comments, not sure if i need this - cycle_lines = port_measure_lines.pop(0)[1] + # cycle_lines = port_measure_lines.pop(0)[1] # For now just recover the bit_measures and sen_and_bitline_path_measures self.read_meas_lists.append([]) + self.read_bit_meas = {bit_polarity.NONINVERTING: [], bit_polarity.INVERTING: []} + self.write_bit_meas = {bit_polarity.NONINVERTING: [], bit_polarity.INVERTING: []} bit_measure_rule = re.compile(r"\.meas tran (v_q_a\d+_b\d+_(read|write)_(zero|one)\d+) FIND v\((.*)\) AT=(\d+(\.\d+)?)n") for measures in port_measure_lines: port_name = measures[0] @@ -1180,43 +1187,52 @@ class delay(simulation): for bit_measure in bit_measure_iter: meas_name = bit_measure.group(1) read = bit_measure.group(2) == "read" + cycle = bit_measure.group(3) probe = bit_measure.group(4) polarity = bit_polarity.NONINVERTING if "q_bar" in meas_name: polarity = bit_polarity.INVERTING meas = voltage_at_measure(meas_name, probe) if read: + if cycle == "one": + meas.meta_str = sram_op.READ_ONE + else: + meas.meta_str = sram_op.READ_ZERO self.read_bit_meas[polarity].append(meas) self.read_meas_lists[-1].append(meas) else: + if cycle == "one": + meas.meta_str = sram_op.WRITE_ONE + else: + meas.meta_str = sram_op.WRITE_ZERO self.write_bit_meas[polarity].append(meas) self.write_meas_lists[-1].append(meas) - delay_path_rule = re.compile(r"\.meas tran delay_(.*)_to_(.*) TRIG v\((.*)\) VAL=(\d+(\.\d+)?) (RISE|FALL)=(\d+) TD=(\d+(\.\d+)?)n TARG v\((.*)\) VAL=(\d+(\.\d+)?) (RISE|FALL)=(\d+) TD=(\d+(\.\d+)?)n") + delay_path_rule = re.compile(r"\.meas tran delay_(.*)_to_(.*)_(sen|bl)_(id\d*) TRIG v\((.*)\) VAL=(\d+(\.\d+)?) (RISE|FALL)=(\d+) TD=(\d+(\.\d+)?)n TARG v\((.*)\) VAL=(\d+(\.\d+)?) (RISE|FALL)=(\d+) TD=(\d+(\.\d+)?)n") port = self.read_ports[0] - sen_and_port = self.sen_name + str(port) - bl_and_port = self.bl_name.format(port) # bl_name contains a '{}' for the port meas_buff = [] + self.sen_path_meas = [] + self.bl_path_meas = [] for measures in port_measure_lines: - port_name = measures[0] text = measures[1] delay_path_iter = delay_path_rule.finditer(text) for delay_path_measure in delay_path_iter: from_ = delay_path_measure.group(1) to_ = delay_path_measure.group(2) - trig_rise = delay_path_measure.group(5) - targ_rise = delay_path_measure.group(10) - meas_name = "delay_{0}_to_{1}".format(from_, to_) + path_ = delay_path_measure.group(3) + id_ = delay_path_measure.group(4) + trig_rise = delay_path_measure.group(8) + targ_rise = delay_path_measure.group(15) + meas_name = "delay_{0}_to_{1}_{2}_{3}".format(from_, to_, path_, id_) meas = delay_measure(meas_name, from_, to_, trig_rise, targ_rise, measure_scale=1e9, has_port=False) meas.meta_str = sram_op.READ_ZERO meas.meta_add_delay = True meas_buff.append(meas) - # TODO: we are losing duplicate measures here - if from_ == sen_and_port: + if path_ == "sen": self.sen_path_meas.extend(meas_buff.copy()) meas_buff.clear() - elif from_ == bl_and_port: - self.bl_path_meas.extend(meas_buff) + elif path_ == "bl": + self.bl_path_meas.extend(meas_buff.copy()) meas_buff.clear() self.read_meas_lists.append(self.sen_path_meas + self.bl_path_meas) @@ -1229,9 +1245,9 @@ class delay(simulation): self.prepare_netlist() if OPTS.top_process == "memchar": # TODO: fix - self.bl_name = "xsram.xbank0.bl_0_{}" - self.br_name = "xsram.xbank0.br_0_{}" - self.sen_name = "xsram.s_en" + self.bl_name = "xsram:xbank0:bl_0_{}" + self.br_name = "xsram:xbank0:br_0_{}" + self.sen_name = "xsram:s_en" self.create_measurement_objects() self.recover_measurment_objects() else: diff --git a/compiler/characterizer/functional.py b/compiler/characterizer/functional.py index 947f2f7e..58cf3eeb 100644 --- a/compiler/characterizer/functional.py +++ b/compiler/characterizer/functional.py @@ -14,6 +14,7 @@ from .stimuli import * from .charutils import * from globals import OPTS from .simulation import simulation +from .measurements import voltage_at_measure class functional(simulation): @@ -78,9 +79,12 @@ class functional(simulation): self.wordline_row = 0 self.bitline_column = 0 self.create_signal_names() - self.add_graph_exclusions() - self.create_graph() - self.set_internal_spice_names() + #self.add_graph_exclusions() + #self.create_graph() + #self.set_internal_spice_names() + self.bl_name = "xsram:xbank0:bl_0_{}" + self.br_name = "xsram:xbank0:br_0_{}" + self.sen_name = "xsram:s_en" self.q_name, self.qbar_name = self.get_bit_name() debug.info(2, "q:\t\t{0}".format(self.q_name)) debug.info(2, "qbar:\t{0}".format(self.qbar_name)) @@ -275,7 +279,8 @@ class functional(simulation): sp_read_value = "" for bit in range(self.word_size + self.num_spare_cols): measure_name = "v{0}_{1}ck{2}".format(dout_port.lower(), bit, cycle) - value = parse_spice_list("timing", measure_name) + # value = parse_spice_list("timing", measure_name) + value = self.measures[measure_name].retrieve_measure(port=0) # FIXME: Ignore the spare columns for now if bit >= self.word_size: value = 0 @@ -473,6 +478,7 @@ class functional(simulation): # Generate dout value measurements self.sf.write("\n * Generation of dout measurements\n") + self.measures = {} for (word, dout_port, eo_period, cycle) in self.read_check: t_initial = eo_period @@ -480,7 +486,7 @@ class functional(simulation): num_bits = self.word_size + self.num_spare_cols for bit in range(num_bits): signal_name = "{0}_{1}".format(dout_port, bit) - measure_name = "V{0}ck{1}".format(signal_name, cycle) + measure_name = "v{0}ck{1}".format(signal_name, cycle) voltage_value = self.stim.get_voltage(word[num_bits - bit - 1]) self.stim.add_comment("* CHECK {0} {1} = {2} time = {3}".format(signal_name, @@ -488,10 +494,13 @@ class functional(simulation): voltage_value, eo_period)) # TODO: Convert to measurement statement instead of stimuli - self.stim.gen_meas_value(meas_name=measure_name, - dout=signal_name, - t_initial=t_initial, - t_final=t_final) + meas = voltage_at_measure(measure_name, signal_name) + self.measures[measure_name] = meas + meas.write_measure(self.stim, ((t_initial + t_final) / 2, 0)) + # self.stim.gen_meas_value(meas_name=measure_name, + # dout=signal_name, + # t_initial=t_initial, + # t_final=t_final) self.stim.write_control(self.cycle_times[-1] + self.period) self.sf.close() @@ -499,10 +508,13 @@ class functional(simulation): # FIXME: Similar function to delay.py, refactor this def get_bit_name(self): """ Get a bit cell name """ - (cell_name, cell_inst) = self.sram.get_cell_name(self.sram.name, 0, 0) - storage_names = cell_inst.mod.get_storage_net_names() - debug.check(len(storage_names) == 2, ("Only inverting/non-inverting storage nodes" - "supported for characterization. Storage nets={0}").format(storage_names)) + # TODO: Find a way to get the cell_name and storage_names statically + # (cell_name, cell_inst) = self.sram.get_cell_name(self.sram.name, 0, 0) + # storage_names = cell_inst.mod.get_storage_net_names() + # debug.check(len(storage_names) == 2, ("Only inverting/non-inverting storage nodes" + # "supported for characterization. Storage nets={0}").format(storage_names)) + cell_name = "xsram:xbank0:xbitcell_array:xbitcell_array:xbit_r0_c0" + storage_names = ("Q", "Q_bar") q_name = cell_name + OPTS.hier_seperator + str(storage_names[0]) qbar_name = cell_name + OPTS.hier_seperator + str(storage_names[1]) diff --git a/compiler/modules/sram.py b/compiler/modules/sram.py index 912e82c5..4b083fcb 100644 --- a/compiler/modules/sram.py +++ b/compiler/modules/sram.py @@ -173,9 +173,14 @@ class sram(): # Characterize the design start_time = datetime.datetime.now() - from characterizer import lib - debug.print_raw("LIB: Characterizing... ") - lib(out_dir=OPTS.output_path, sram=self.s, sp_file=self.get_sp_name()) + from characterizer import delay + debug.print_raw("LIB: Writing Analysis File... ") + d = delay(self, self.get_sp_name(), ("TT", 5, 25)) + if (self.sram.num_spare_rows == 0): + probe_address = "1" * self.sram.addr_size + else: + probe_address = "0" + "1" * (self.sram.addr_size - 1) + d.analysis_init(probe_address, probe_data) print_time("Characterization", datetime.datetime.now(), start_time) # Write the config file diff --git a/compiler/modules/sram_config.py b/compiler/modules/sram_config.py index 6f147f67..55e48484 100644 --- a/compiler/modules/sram_config.py +++ b/compiler/modules/sram_config.py @@ -39,11 +39,6 @@ class sram_config: except ImportError: self.array_col_multiple = 1 - if self.write_size: - self.num_wmasks = int(ceil(self.word_size / self.write_size)) - else: - self.num_wmasks = 0 - if not self.num_spare_cols: self.num_spare_cols = 0 diff --git a/compiler/memchar.py b/compiler/sram_char.py similarity index 100% rename from compiler/memchar.py rename to compiler/sram_char.py diff --git a/compiler/memfunc.py b/compiler/sram_func.py similarity index 72% rename from compiler/memfunc.py rename to compiler/sram_func.py index c0dfe25e..8eaaf2fd 100755 --- a/compiler/memfunc.py +++ b/compiler/sram_func.py @@ -44,27 +44,29 @@ init_openram(config_file=config_file, is_unit_test=False) print_banner() # Configure the SRAM organization (duplicated from openram.py) -from sram_config import sram_config -c = sram_config(word_size=OPTS.word_size, - num_words=OPTS.num_words, - write_size=OPTS.write_size, - num_banks=OPTS.num_banks, - words_per_row=OPTS.words_per_row, - num_spare_rows=OPTS.num_spare_rows, - num_spare_cols=OPTS.num_spare_cols) +#from sram_config import sram_config +from characterizer.fake_sram import fake_sram +s = fake_sram(name=OPTS.output_name, + word_size=OPTS.word_size, + num_words=OPTS.num_words, + write_size=OPTS.write_size, + num_banks=OPTS.num_banks, + words_per_row=OPTS.words_per_row, + num_spare_rows=OPTS.num_spare_rows, + num_spare_cols=OPTS.num_spare_cols) + +s.parse_html(OPTS.output_path + "sram.html") +s.generate_pins() +s.setup_multiport_constants() OPTS.netlist_only = True OPTS.check_lvsdrc = False -# Initialize and create the sram object -from sram import sram -s = sram(name=OPTS.output_name, sram_config=c) - # Generate stimulus and run functional simulation on the design start_time = datetime.datetime.now() from characterizer import functional debug.print_raw("Functional simulation... ") -f = functional(s.s, cycles=cycles, spfile=s.get_sp_name(), period=period, output_path=OPTS.openram_temp) +f = functional(s, cycles=cycles, spfile=OPTS.output_path + OPTS.output_name + ".sp", period=period, output_path=OPTS.openram_temp) (fail, error) = f.run() debug.print_raw(error) print_time("Functional simulation", datetime.datetime.now(), start_time) From 8a67626e55ed90b4a1c02e4f6fdf33c1f459b94c Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Tue, 13 Dec 2022 08:32:44 -0800 Subject: [PATCH 054/130] add back the characterizer to save function --- compiler/modules/sram.py | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/compiler/modules/sram.py b/compiler/modules/sram.py index 4b083fcb..039a46d3 100644 --- a/compiler/modules/sram.py +++ b/compiler/modules/sram.py @@ -173,14 +173,9 @@ class sram(): # Characterize the design start_time = datetime.datetime.now() - from characterizer import delay - debug.print_raw("LIB: Writing Analysis File... ") - d = delay(self, self.get_sp_name(), ("TT", 5, 25)) - if (self.sram.num_spare_rows == 0): - probe_address = "1" * self.sram.addr_size - else: - probe_address = "0" + "1" * (self.sram.addr_size - 1) - d.analysis_init(probe_address, probe_data) + from openram.characterizer import lib + debug.print_raw("LIB: Characterizing... ") + lib(out_dir=OPTS.output_path, sram=self.s, sp_file=self.get_sp_name()) print_time("Characterization", datetime.datetime.now(), start_time) # Write the config file From d27d77bcf8d1ea8b3ffe49b1e2ac1455635b4657 Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Tue, 17 Jan 2023 10:40:44 -0800 Subject: [PATCH 055/130] fix din size in fake sram --- compiler/characterizer/fake_sram.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/characterizer/fake_sram.py b/compiler/characterizer/fake_sram.py index 9d2a409c..001e1398 100644 --- a/compiler/characterizer/fake_sram.py +++ b/compiler/characterizer/fake_sram.py @@ -94,9 +94,9 @@ class fake_sram(sram_config): self.num_rw_ports + self.num_r_ports + self.num_w_ports)]) for port in range(self.num_rw_ports): self.pins.extend(['din{0}[{1}]'.format(port, bit) - for bit in range(self.num_cols)]) + for bit in range(self.word_size)]) self.pins.extend(['dout{0}[{1}]'.format(port, bit) - for bit in range(self.num_cols)]) + for bit in range(self.word_size)]) self.pins.extend(['addr{0}[{1}]'.format(port, bit) for bit in range(self.addr_size)]) if self.num_wmasks != 0: From 7fdc5cc782f51a4a47030f20d106d8dfd22f8f9e Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Thu, 19 Jan 2023 11:39:16 -0800 Subject: [PATCH 056/130] modify char to work with older macro --- compiler/characterizer/delay.py | 92 ++++++++++++++++------------ compiler/characterizer/fake_sram.py | 9 ++- compiler/characterizer/functional.py | 5 +- compiler/characterizer/setup_hold.py | 2 +- compiler/sram_func.py | 2 +- 5 files changed, 61 insertions(+), 49 deletions(-) diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index 53874f23..272b2094 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -121,9 +121,9 @@ class delay(simulation): # Other measurements associated with the read port not included in the liberty file read_measures.append(self.create_bitline_measurement_objects()) read_measures.append(self.create_debug_measurement_objects()) + read_measures.append(self.create_read_bit_measures()) # TODO: Maybe don't do this here (?) if OPTS.top_process != "memchar": - read_measures.append(self.create_read_bit_measures()) read_measures.append(self.create_sen_and_bitline_path_measures()) return read_measures @@ -168,8 +168,7 @@ class delay(simulation): write_measures = [] write_measures.append(self.write_lib_meas) - if OPTS.top_process != "memchar": - write_measures.append(self.create_write_bit_measures()) + write_measures.append(self.create_write_bit_measures()) return write_measures @@ -229,8 +228,11 @@ class delay(simulation): bit_col = self.get_data_bit_column_number(probe_address, probe_data) bit_row = self.get_address_row_number(probe_address) - (cell_name, cell_inst) = self.sram.get_cell_name(self.sram.name, bit_row, bit_col) - storage_names = cell_inst.mod.get_storage_net_names() + #(cell_name, cell_inst) = self.sram.get_cell_name(self.sram.name, bit_row, bit_col) + cell_name = OPTS.hier_seperator.join(("X" + self.sram.name, "xbank0", "xreplica_bitcell_array", "xbitcell_array", "xbit_r{}_c{}".format(bit_row, bit_col))) + #cell_name = OPTS.hier_seperator.join(("X" + self.sram.name, "xbank0", "xbitcell_array", "xbitcell_array", "xbit_r{}_c{}".format(bit_row, bit_col))) + storage_names = ("Q", "Q_bar") + #storage_names = cell_inst.mod.get_storage_net_names() debug.check(len(storage_names) == 2, ("Only inverting/non-inverting storage nodes" "supported for characterization. Storage nets={0}").format(storage_names)) if OPTS.use_pex and OPTS.pex_exe[0] != "calibre": @@ -859,7 +861,8 @@ class delay(simulation): result[port].update(read_port_dict) - self.path_delays = self.check_path_measures() + if self.sen_path_meas and self.bl_path_meas: + self.path_delays = self.check_path_measures() return (True, result) @@ -950,7 +953,7 @@ class delay(simulation): def check_bitline_meas(self, v_discharged_bl, v_charged_bl): """ Checks the value of the discharging bitline. Confirms s_en timing errors. - Returns true if the bitlines are at there expected value. + Returns true if the bitlines are at there their value. """ # The inputs looks at discharge/charged bitline rather than left or right (bl/br) # Performs two checks, discharging bitline is at least 10% away from vdd and there is a @@ -1161,7 +1164,13 @@ class delay(simulation): shutil.copy(self.sp_file, self.sim_sp_file) def recover_measurment_objects(self): - mf = open(path.join(OPTS.output_path, "delay_meas.sp"), "r") + mf_path = path.join(OPTS.output_path, "delay_meas.sp") + self.sen_path_meas = None + self.bl_path_meas = None + if not path.exists(mf_path): + debug.info(1, "Delay measure file not found. Skipping measure recovery") + return + mf = open(mf_path, "r") measure_text = mf.read() port_iter = re.finditer(r"\* (Read|Write) ports (\d*)", measure_text) port_measure_lines = [] @@ -1179,34 +1188,34 @@ class delay(simulation): self.read_meas_lists.append([]) self.read_bit_meas = {bit_polarity.NONINVERTING: [], bit_polarity.INVERTING: []} self.write_bit_meas = {bit_polarity.NONINVERTING: [], bit_polarity.INVERTING: []} - bit_measure_rule = re.compile(r"\.meas tran (v_q_a\d+_b\d+_(read|write)_(zero|one)\d+) FIND v\((.*)\) AT=(\d+(\.\d+)?)n") - for measures in port_measure_lines: - port_name = measures[0] - text = measures[1] - bit_measure_iter = bit_measure_rule.finditer(text) - for bit_measure in bit_measure_iter: - meas_name = bit_measure.group(1) - read = bit_measure.group(2) == "read" - cycle = bit_measure.group(3) - probe = bit_measure.group(4) - polarity = bit_polarity.NONINVERTING - if "q_bar" in meas_name: - polarity = bit_polarity.INVERTING - meas = voltage_at_measure(meas_name, probe) - if read: - if cycle == "one": - meas.meta_str = sram_op.READ_ONE - else: - meas.meta_str = sram_op.READ_ZERO - self.read_bit_meas[polarity].append(meas) - self.read_meas_lists[-1].append(meas) - else: - if cycle == "one": - meas.meta_str = sram_op.WRITE_ONE - else: - meas.meta_str = sram_op.WRITE_ZERO - self.write_bit_meas[polarity].append(meas) - self.write_meas_lists[-1].append(meas) +# bit_measure_rule = re.compile(r"\.meas tran (v_q_a\d+_b\d+_(read|write)_(zero|one)\d+) FIND v\((.*)\) AT=(\d+(\.\d+)?)n") +# for measures in port_measure_lines: +# port_name = measures[0] +# text = measures[1] +# bit_measure_iter = bit_measure_rule.finditer(text) +# for bit_measure in bit_measure_iter: +# meas_name = bit_measure.group(1) +# read = bit_measure.group(2) == "read" +# cycle = bit_measure.group(3) +# probe = bit_measure.group(4) +# polarity = bit_polarity.NONINVERTING +# if "q_bar" in meas_name: +# polarity = bit_polarity.INVERTING +# meas = voltage_at_measure(meas_name, probe) +# if read: +# if cycle == "one": +# meas.meta_str = sram_op.READ_ONE +# else: +# meas.meta_str = sram_op.READ_ZERO +# self.read_bit_meas[polarity].append(meas) +# self.read_meas_lists[-1].append(meas) +# else: +# if cycle == "one": +# meas.meta_str = sram_op.WRITE_ONE +# else: +# meas.meta_str = sram_op.WRITE_ZERO +# self.write_bit_meas[polarity].append(meas) +# self.write_meas_lists[-1].append(meas) delay_path_rule = re.compile(r"\.meas tran delay_(.*)_to_(.*)_(sen|bl)_(id\d*) TRIG v\((.*)\) VAL=(\d+(\.\d+)?) (RISE|FALL)=(\d+) TD=(\d+(\.\d+)?)n TARG v\((.*)\) VAL=(\d+(\.\d+)?) (RISE|FALL)=(\d+) TD=(\d+(\.\d+)?)n") port = self.read_ports[0] @@ -1244,10 +1253,10 @@ class delay(simulation): self.set_probe(probe_address, probe_data) self.prepare_netlist() if OPTS.top_process == "memchar": - # TODO: fix - self.bl_name = "xsram:xbank0:bl_0_{}" - self.br_name = "xsram:xbank0:br_0_{}" - self.sen_name = "xsram:s_en" + # TODO: guess the bl and br. It can be "bl_..." or "bl..." + self.bl_name = "X{0}{1}xbank0{1}bl{{}}_{2}".format(self.sram.name, OPTS.hier_seperator, self.bitline_column) + self.br_name = "X{0}{1}xbank0{1}br{{}}_{2}".format(self.sram.name, OPTS.hier_seperator, self.bitline_column) + self.sen_name = "X{0}{1}xbank0{1}s_en".format(self.sram.name, OPTS.hier_seperator) self.create_measurement_objects() self.recover_measurment_objects() else: @@ -1522,3 +1531,6 @@ class delay(simulation): self.stim.gen_pwl("CSB{0}".format(port), self.cycle_times, self.csb_values[port], self.period, self.slew, 0.05) if port in self.readwrite_ports: self.stim.gen_pwl("WEB{0}".format(port), self.cycle_times, self.web_values[port], self.period, self.slew, 0.05) + if self.sram.num_wmasks: + for bit in range(self.sram.num_wmasks): + self.stim.gen_pwl("WMASK{0}_{1}".format(port, bit), self.cycle_times, self.wmask_values[port][bit], self.period, self.slew, 0.05) diff --git a/compiler/characterizer/fake_sram.py b/compiler/characterizer/fake_sram.py index 9d2a409c..b1eb2353 100644 --- a/compiler/characterizer/fake_sram.py +++ b/compiler/characterizer/fake_sram.py @@ -94,13 +94,12 @@ class fake_sram(sram_config): self.num_rw_ports + self.num_r_ports + self.num_w_ports)]) for port in range(self.num_rw_ports): self.pins.extend(['din{0}[{1}]'.format(port, bit) - for bit in range(self.num_cols)]) + for bit in range(self.word_size)]) self.pins.extend(['dout{0}[{1}]'.format(port, bit) - for bit in range(self.num_cols)]) + for bit in range(self.word_size)]) self.pins.extend(['addr{0}[{1}]'.format(port, bit) for bit in range(self.addr_size)]) if self.num_wmasks != 0: - print(self.num_wmasks) self.pins.extend(['wmask{0}[{1}]'.format(port, bit) for bit in range(self.num_wmasks)]) @@ -109,7 +108,7 @@ class fake_sram(sram_config): start_port = self.num_rw_ports for port in range(start_port, start_port + self.num_r_ports): self.pins.extend(['dout{0}[{1}]'.format(port, bit) - for bit in range(self.num_cols)]) + for bit in range(self.word_size)]) self.pins.extend(['addr{0}[{1}]'.format(port, bit) for bit in range(self.addr_size)]) @@ -118,7 +117,7 @@ class fake_sram(sram_config): start_port += self.num_r_ports for port in range(start_port, start_port + self.num_w_ports): self.pins.extend(['din{0}[{1}]'.format(port, bit) - for bit in range(self.num_cols)]) + for bit in range(self.word_size)]) self.pins.extend(['addr{0}[{1}]'.format(port, bit) for bit in range(self.addr_size)]) if self.num_wmasks != 0: diff --git a/compiler/characterizer/functional.py b/compiler/characterizer/functional.py index 58cf3eeb..70e0b4f4 100644 --- a/compiler/characterizer/functional.py +++ b/compiler/characterizer/functional.py @@ -299,10 +299,11 @@ class functional(simulation): self.v_low, self.v_high) except ValueError: - error ="FAILED: {0}_{1} value {2} at time {3}n is not a float.".format(dout_port, + error ="FAILED: {0}_{1} value {2} at time {3}n is not a float. Measure: {4}".format(dout_port, bit, value, - eo_period) + eo_period, + measure_name) return (0, error) self.read_results.append([sp_read_value, dout_port, eo_period, cycle]) diff --git a/compiler/characterizer/setup_hold.py b/compiler/characterizer/setup_hold.py index ec1a9e5e..17fc0e2b 100644 --- a/compiler/characterizer/setup_hold.py +++ b/compiler/characterizer/setup_hold.py @@ -42,7 +42,7 @@ class setup_hold(): self.stim_sp = "sh_stim.sp" temp_stim = OPTS.openram_temp + self.stim_sp self.sf = open(temp_stim, "w") - self.stim = stimuli(self.sf, self.corner) + self.stim = stimuli(self.sf, self.mf, self.corner) self.write_header(correct_value) diff --git a/compiler/sram_func.py b/compiler/sram_func.py index 8eaaf2fd..ee378fa4 100755 --- a/compiler/sram_func.py +++ b/compiler/sram_func.py @@ -55,7 +55,7 @@ s = fake_sram(name=OPTS.output_name, num_spare_rows=OPTS.num_spare_rows, num_spare_cols=OPTS.num_spare_cols) -s.parse_html(OPTS.output_path + "sram.html") +s.parse_html(OPTS.output_path + s.name + ".html") s.generate_pins() s.setup_multiport_constants() From 817dc8a06301d9400f426cc9a23b2f52bf6c9b94 Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Fri, 20 Jan 2023 12:50:09 -0800 Subject: [PATCH 057/130] Guess the bl format --- compiler/characterizer/delay.py | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index c5c0910b..28a965e8 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -229,7 +229,7 @@ class delay(simulation): bit_col = self.get_data_bit_column_number(probe_address, probe_data) bit_row = self.get_address_row_number(probe_address) #(cell_name, cell_inst) = self.sram.get_cell_name(self.sram.name, bit_row, bit_col) - cell_name = OPTS.hier_seperator.join(("X" + self.sram.name, "xbank0", "xreplica_bitcell_array", "xbitcell_array", "xbit_r{}_c{}".format(bit_row, bit_col))) + cell_name = "X{0}{3}xbank0{3}xreplica_bitcell_array{3}xbitcell_array{3}x_bit_r{1}_c{2}".format(self.sram_name, bit_row, bit_col, OPTS.hier_seperator) #cell_name = OPTS.hier_seperator.join(("X" + self.sram.name, "xbank0", "xbitcell_array", "xbitcell_array", "xbit_r{}_c{}".format(bit_row, bit_col))) storage_names = ("Q", "Q_bar") #storage_names = cell_inst.mod.get_storage_net_names() @@ -1245,6 +1245,29 @@ class delay(simulation): meas_buff.clear() self.read_meas_lists.append(self.sen_path_meas + self.bl_path_meas) + def guess_spice_names(self): + """This is run in place of get_spice_names function from simulation.py when + running stand-alone characterizer.""" + # TODO: Find a better method + with open(self.sp_file, "r") as file: + bl_prefix = None + br_prefix = None + for line in file: + if re.search("bl_\d_\d", line): + bl_prefix = "bl_" + br_prefix = "br_" + break + if re.search("bl\d_\d", line): + bl_prefix = "bl" + br_prefix = "br" + break + debug.check(bl_prefix, "Could not guess the bitline name.") + self.bl_name = "X{0}{1}xbank0{1}{2}{{}}_{3}".format(self.sram.name, OPTS.hier_seperator, bl_prefix, self.bitline_column) + self.br_name = "X{0}{1}xbank0{1}{2}{{}}_{3}".format(self.sram.name, OPTS.hier_seperator, br_prefix, self.bitline_column) + self.sen_name = "X{0}{1}xbank0{1}s_en".format(self.sram.name, OPTS.hier_seperator) + + + def analysis_init(self, probe_address, probe_data): @@ -1253,10 +1276,7 @@ class delay(simulation): self.set_probe(probe_address, probe_data) self.prepare_netlist() if OPTS.top_process == "memchar": - # TODO: guess the bl and br. It can be "bl_..." or "bl..." - self.bl_name = "X{0}{1}xbank0{1}bl{{}}_{2}".format(self.sram.name, OPTS.hier_seperator, self.bitline_column) - self.br_name = "X{0}{1}xbank0{1}br{{}}_{2}".format(self.sram.name, OPTS.hier_seperator, self.bitline_column) - self.sen_name = "X{0}{1}xbank0{1}s_en".format(self.sram.name, OPTS.hier_seperator) + self.guess_spice_names() self.create_measurement_objects() self.recover_measurment_objects() else: From 149abe1dbd1510c53f1dfd4b9f4b6de09032b4a7 Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Mon, 23 Jan 2023 17:44:38 -0800 Subject: [PATCH 058/130] expose fake_sram to library --- compiler/characterizer/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/characterizer/__init__.py b/compiler/characterizer/__init__.py index 8fba0986..95fc4877 100644 --- a/compiler/characterizer/__init__.py +++ b/compiler/characterizer/__init__.py @@ -19,6 +19,7 @@ from .simulation import * from .measurements import * from .model_check import * from .analytical_util import * +from .fake_sram import * debug.info(1, "Initializing characterizer...") OPTS.spice_exe = "" From 8de3be8529b4a55e9d7213e59aaf3bd674916431 Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Mon, 23 Jan 2023 17:48:30 -0800 Subject: [PATCH 059/130] Changed the standalone characterizer interface --- compiler/characterizer/fake_sram.py | 2 +- compiler/sram_char.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/characterizer/fake_sram.py b/compiler/characterizer/fake_sram.py index 928f4903..709fec8f 100644 --- a/compiler/characterizer/fake_sram.py +++ b/compiler/characterizer/fake_sram.py @@ -1,4 +1,4 @@ -from openram.modules import sram_config +from openram import sram_config from math import ceil import re diff --git a/compiler/sram_char.py b/compiler/sram_char.py index c602e59b..897bc154 100755 --- a/compiler/sram_char.py +++ b/compiler/sram_char.py @@ -62,8 +62,8 @@ s = fake_sram(name=OPTS.output_name, num_spare_rows=OPTS.num_spare_rows, num_spare_cols=OPTS.num_spare_cols) -debug.check(os.path.exists(args[1], "Spice netlist file {} not found.".format(args[1]))) -debug.check(os.path.exists(args[2], "HTML report file {} not found.".format(args[2]))) +debug.check(os.path.exists(args[1]), "Spice netlist file {} not found.".format(args[1])) +debug.check(os.path.exists(args[2]), "HTML report file {} not found.".format(args[2])) sp_file = args[1] html_file = args[2] s.parse_html(html_file) From 5695cd69c621ae2c4fcf5e475d5f7db3efb7494e Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Tue, 31 Jan 2023 13:08:13 -0800 Subject: [PATCH 060/130] removed html report requirement for sram_char.py --- compiler/characterizer/fake_sram.py | 49 +++++++---------------------- compiler/sram_char.py | 7 ++--- 2 files changed, 13 insertions(+), 43 deletions(-) diff --git a/compiler/characterizer/fake_sram.py b/compiler/characterizer/fake_sram.py index 709fec8f..86c5cf4e 100644 --- a/compiler/characterizer/fake_sram.py +++ b/compiler/characterizer/fake_sram.py @@ -1,6 +1,7 @@ from openram import sram_config from math import ceil import re +from openram import OPTS class fake_sram(sram_config): @@ -29,7 +30,7 @@ class fake_sram(sram_config): A first W port (with no RW ports) will be: clk0, csb0, addr0, data0 """ - total_ports = self.num_rw_ports + self.num_w_ports + self.num_r_ports + total_ports = OPTS.num_rw_ports + OPTS.num_w_ports + OPTS.num_r_ports # These are the read/write port indices. self.readwrite_ports = [] @@ -46,53 +47,25 @@ class fake_sram(sram_config): # The order is always fixed as RW, W, R port_number = 0 - for port in range(self.num_rw_ports): + for port in range(OPTS.num_rw_ports): self.readwrite_ports.append(port_number) self.write_ports.append(port_number) self.read_ports.append(port_number) port_number += 1 - for port in range(self.num_w_ports): + for port in range(OPTS.num_w_ports): self.write_ports.append(port_number) self.writeonly_ports.append(port_number) port_number += 1 - for port in range(self.num_r_ports): + for port in range(OPTS.num_r_ports): self.read_ports.append(port_number) self.readonly_ports.append(port_number) port_number += 1 - def parse_html(self, filename): - """ - Parse the HTML file generated from previous SRAM generation - and populate the members - """ - with open(filename, 'r') as html: - for line in html: - if 'Ports and Configuration' in line: - configRE = re.compile(r'(\w*)(\w*)') - values = configRE.finditer(line) - for val in values: - if val.group(1) == 'WORD_SIZE': - self.word_size = int(val.group(2)) - elif val.group(1) == 'NUM_WORDS': - self.num_words = int(val.group(2)) - elif val.group(1) == 'NUM_BANKS': - self.num_banks = int(val.group(2)) - elif val.group(1) == 'NUM_RW_PORTS': - self.num_rw_ports = int(val.group(2)) - elif val.group(1) == 'NUM_R_PORTS': - self.num_r_ports = int(val.group(2)) - elif val.group(1) == 'NUM_W_PORTS': - self.num_w_ports = int(val.group(2)) - elif val.group(1) == 'Area (µm2)': - self.height = int(val.group(2) ** 0.5) - self.width = int(val.group(2) ** 0.5) - self.compute_sizes() - def generate_pins(self): self.pins = ['vdd', 'gnd'] self.pins.extend(['clk{}'.format(port) for port in range( - self.num_rw_ports + self.num_r_ports + self.num_w_ports)]) - for port in range(self.num_rw_ports): + OPTS.num_rw_ports + OPTS.num_r_ports + OPTS.num_w_ports)]) + for port in range(OPTS.num_rw_ports): self.pins.extend(['din{0}[{1}]'.format(port, bit) for bit in range(self.word_size)]) self.pins.extend(['dout{0}[{1}]'.format(port, bit) @@ -105,8 +78,8 @@ class fake_sram(sram_config): self.pins.extend(['csb{}'.format(port), 'web{}'.format(port)]) - start_port = self.num_rw_ports - for port in range(start_port, start_port + self.num_r_ports): + start_port = OPTS.num_rw_ports + for port in range(start_port, start_port + OPTS.num_r_ports): self.pins.extend(['dout{0}[{1}]'.format(port, bit) for bit in range(self.word_size)]) self.pins.extend(['addr{0}[{1}]'.format(port, bit) @@ -114,8 +87,8 @@ class fake_sram(sram_config): self.pins.extend(['csb{}'.format(port)]) - start_port += self.num_r_ports - for port in range(start_port, start_port + self.num_w_ports): + start_port += OPTS.num_r_ports + for port in range(start_port, start_port + OPTS.num_w_ports): self.pins.extend(['din{0}[{1}]'.format(port, bit) for bit in range(self.word_size)]) self.pins.extend(['addr{0}[{1}]'.format(port, bit) diff --git a/compiler/sram_char.py b/compiler/sram_char.py index 897bc154..47a621bf 100755 --- a/compiler/sram_char.py +++ b/compiler/sram_char.py @@ -34,10 +34,10 @@ except: (OPTS, args) = openram.parse_args() # Override the usage -USAGE = "Usage: {} [options] \nUse -h for help.\n".format(__file__) +USAGE = "Usage: {} [options] \nUse -h for help.\n".format(__file__) # Check that we are left with a single configuration file as argument. -if len(args) != 3: +if len(args) != 2: print(USAGE) sys.exit(2) @@ -63,10 +63,7 @@ s = fake_sram(name=OPTS.output_name, num_spare_cols=OPTS.num_spare_cols) debug.check(os.path.exists(args[1]), "Spice netlist file {} not found.".format(args[1])) -debug.check(os.path.exists(args[2]), "HTML report file {} not found.".format(args[2])) sp_file = args[1] -html_file = args[2] -s.parse_html(html_file) s.generate_pins() s.setup_multiport_constants() From da86d507667e02ade7a1cd9fa5efbf4e60fa107e Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Tue, 31 Jan 2023 13:08:40 -0800 Subject: [PATCH 061/130] Guess the bitcell name format --- compiler/characterizer/delay.py | 40 +++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index 28a965e8..4bcc2158 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -112,9 +112,10 @@ class delay(simulation): self.read_lib_meas[-1].meta_str = "disabled_read0" # This will later add a half-period to the spice time delay. Only for reading 0. - for obj in self.read_lib_meas: - if obj.meta_str is sram_op.READ_ZERO: - obj.meta_add_delay = True + # FIXME: Removed this to check, see if it affects anything + #for obj in self.read_lib_meas: + # if obj.meta_str is sram_op.READ_ZERO: + # obj.meta_add_delay = True read_measures = [] read_measures.append(self.read_lib_meas) @@ -228,11 +229,13 @@ class delay(simulation): bit_col = self.get_data_bit_column_number(probe_address, probe_data) bit_row = self.get_address_row_number(probe_address) - #(cell_name, cell_inst) = self.sram.get_cell_name(self.sram.name, bit_row, bit_col) - cell_name = "X{0}{3}xbank0{3}xreplica_bitcell_array{3}xbitcell_array{3}x_bit_r{1}_c{2}".format(self.sram_name, bit_row, bit_col, OPTS.hier_seperator) - #cell_name = OPTS.hier_seperator.join(("X" + self.sram.name, "xbank0", "xbitcell_array", "xbitcell_array", "xbit_r{}_c{}".format(bit_row, bit_col))) - storage_names = ("Q", "Q_bar") - #storage_names = cell_inst.mod.get_storage_net_names() + if OPTS.top_process == "memchar": + cell_name = self.cell_format.format(self.sram.name, bit_row, bit_col, OPTS.hier_seperator) + #cell_name = "X{0}{3}xbank0{3}xreplica_bitcell_array{3}xbitcell_array{3}xbit_r{1}_c{2}".format(self.sram.name, bit_row, bit_col, OPTS.hier_seperator) + storage_names = ("Q", "Q_bar") + else: + (cell_name, cell_inst) = self.sram.get_cell_name(self.sram.name, bit_row, bit_col) + storage_names = cell_inst.mod.get_storage_net_names() debug.check(len(storage_names) == 2, ("Only inverting/non-inverting storage nodes" "supported for characterization. Storage nets={0}").format(storage_names)) if OPTS.use_pex and OPTS.pex_exe[0] != "calibre": @@ -1149,9 +1152,10 @@ class delay(simulation): # Set up to trim the netlist here if that is enabled # TODO: Copy old netlist if memchar if OPTS.trim_netlist: - self.trim_sp_file = "{0}trimmed.sp".format(self.output_path) + #self.trim_sp_file = "{0}trimmed.sp".format(self.output_path) + self.trim_sp_file = "{0}trimmed.sp".format(OPTS.openram_temp) # Only genrate spice when running openram process - if OPTS.top_process == "openram": + if OPTS.top_process != "memchar": self.sram.sp_write(self.trim_sp_file, lvs=False, trim=True) else: # The non-reduced netlist file when it is disabled @@ -1246,25 +1250,31 @@ class delay(simulation): self.read_meas_lists.append(self.sen_path_meas + self.bl_path_meas) def guess_spice_names(self): - """This is run in place of get_spice_names function from simulation.py when - running stand-alone characterizer.""" + """This is run in place of set_internal_spice_names function from + simulation.py when running stand-alone characterizer.""" # TODO: Find a better method with open(self.sp_file, "r") as file: bl_prefix = None br_prefix = None + replica_bitcell_array_name = None for line in file: if re.search("bl_\d_\d", line): bl_prefix = "bl_" br_prefix = "br_" - break if re.search("bl\d_\d", line): bl_prefix = "bl" br_prefix = "br" + if re.search("Xreplica_bitcell_array", line): + replica_bitcell_array_name = "replica_bitcell_array" + if bl_prefix and replica_bitcell_array_name: break debug.check(bl_prefix, "Could not guess the bitline name.") self.bl_name = "X{0}{1}xbank0{1}{2}{{}}_{3}".format(self.sram.name, OPTS.hier_seperator, bl_prefix, self.bitline_column) self.br_name = "X{0}{1}xbank0{1}{2}{{}}_{3}".format(self.sram.name, OPTS.hier_seperator, br_prefix, self.bitline_column) self.sen_name = "X{0}{1}xbank0{1}s_en".format(self.sram.name, OPTS.hier_seperator) + if not replica_bitcell_array_name: + replica_bitcell_array_name = "bitcell_array" + self.cell_format = "X{{0}}{{3}}xbank0{{3}}x{0}{{3}}xbitcell_array{{3}}xbit_r{{1}}_c{{2}}".format(replica_bitcell_array_name) @@ -1277,6 +1287,7 @@ class delay(simulation): self.prepare_netlist() if OPTS.top_process == "memchar": self.guess_spice_names() + self.create_measurement_names() self.create_measurement_objects() self.recover_measurment_objects() else: @@ -1321,7 +1332,8 @@ class delay(simulation): if OPTS.use_specified_load_slew is not None and len(load_slews) > 1: debug.warning("Path delay lists not correctly generated for characterizations of more than 1 load,slew") # Get and save the path delays - bl_names, bl_delays, sen_names, sen_delays = self.get_delay_lists(self.path_delays) + if self.sen_path_meas and self.bl_path_meas: + bl_names, bl_delays, sen_names, sen_delays = self.get_delay_lists(self.path_delays) # Removed from characterization output temporarily # char_sram_data["bl_path_measures"] = bl_delays # char_sram_data["sen_path_measures"] = sen_delays From 0d60c76e3bfd1d37849004af2d33e9a0d7793fdc Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Fri, 3 Feb 2023 16:36:14 -0800 Subject: [PATCH 062/130] Fixed naming issues in trim_spice --- compiler/characterizer/trim_spice.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/compiler/characterizer/trim_spice.py b/compiler/characterizer/trim_spice.py index da2ce2ad..ca943318 100644 --- a/compiler/characterizer/trim_spice.py +++ b/compiler/characterizer/trim_spice.py @@ -85,14 +85,15 @@ class trim_spice(): wl_regex = r"wl\d*_{}".format(wl_address) bl_regex = r"bl\d*_{}".format(int(self.words_per_row*data_bit + col_address)) + bl_no_port_regex = r"bl_{}".format(int(self.words_per_row*data_bit + col_address)) + self.remove_insts("bitcell_array",[wl_regex,bl_regex]) # 2. Keep sense amps basd on BL - # FIXME: The bit lines are not indexed the same in sense_amp_array - #self.remove_insts("sense_amp_array",[bl_regex]) + self.remove_insts("sense_amp_array",[bl_no_port_regex]) # 3. Keep column muxes basd on BL - self.remove_insts("column_mux_array", [bl_regex]) + self.remove_insts("single_level_column_mux_array", [bl_no_port_regex]) # 4. Keep write driver based on DATA data_regex = r"data_{}".format(data_bit) From 39104fa9d83c39709c6c994285d452f47b6629aa Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Mon, 6 Feb 2023 14:13:56 -0800 Subject: [PATCH 063/130] Delay measure always measure from clk neg edge --- compiler/characterizer/delay.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index 4bcc2158..a38d1da3 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -88,10 +88,12 @@ class delay(simulation): self.clk_frmt = "clk{0}" # Unformatted clock name targ_name = "{0}{{}}_{1}".format(self.dout_name, self.probe_data) # Empty values are the port and probe data bit self.delay_meas = [] - self.delay_meas.append(delay_measure("delay_lh", self.clk_frmt, targ_name, "RISE", "RISE", measure_scale=1e9)) + self.delay_meas.append(delay_measure("delay_lh", self.clk_frmt, targ_name, "FALL", "RISE", measure_scale=1e9)) self.delay_meas[-1].meta_str = sram_op.READ_ONE # Used to index time delay values when measurements written to spice file. + self.dealy_meas[-1].meta_add_delay = True self.delay_meas.append(delay_measure("delay_hl", self.clk_frmt, targ_name, "FALL", "FALL", measure_scale=1e9)) self.delay_meas[-1].meta_str = sram_op.READ_ZERO + self.dealy_meas[-1].meta_add_delay = True self.read_lib_meas+=self.delay_meas self.slew_meas = [] @@ -1029,8 +1031,8 @@ class delay(simulation): slews_str = "slew_hl={0} slew_lh={1}".format(slew_hl, slew_lh) # high-to-low delays start at neg. clk edge, so they need to be less than half_period half_period = self.period / 2 - if abs(delay_hl)>half_period or abs(delay_lh)>self.period or abs(slew_hl)>half_period or abs(slew_lh)>self.period \ - or delay_hl<0 or delay_lh<0 or slew_hl<0 or slew_lh<0: + if abs(delay_hl)>half_period or abs(delay_lh)>self.half_period or abs(slew_hl)>half_period or abs(slew_lh)>self.period \ + or (delay_hl<0 and delay_lh<0) or slew_hl<0 or slew_lh<0: debug.info(2, "UNsuccessful simulation (in ns):\n\t\t{0}\n\t\t{1}\n\t\t{2}".format(period_load_slew_str, delays_str, slews_str)) From b70f919a2b47a9a20b4ddd232ccffe9e7fb3bf5f Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Tue, 14 Feb 2023 12:01:14 -0800 Subject: [PATCH 064/130] Characterize only nom corner --- compiler/characterizer/lib.py | 1 + compiler/sram_char.py | 1 + 2 files changed, 2 insertions(+) diff --git a/compiler/characterizer/lib.py b/compiler/characterizer/lib.py index 0d75d80f..d2e0c227 100644 --- a/compiler/characterizer/lib.py +++ b/compiler/characterizer/lib.py @@ -82,6 +82,7 @@ class lib: debug.info(1, "Slews: {0}".format(self.slews)) debug.info(1, "Loads: {0}".format(self.loads)) debug.info(1, "self.load_slews : {0}".format(self.load_slews)) + def create_corners(self): """ Create corners for characterization. """ # Get the corners from the options file diff --git a/compiler/sram_char.py b/compiler/sram_char.py index 47a621bf..41b89512 100755 --- a/compiler/sram_char.py +++ b/compiler/sram_char.py @@ -69,6 +69,7 @@ s.setup_multiport_constants() OPTS.netlist_only = True OPTS.check_lvsdrc = False +OPTS.nomimal_corner_only = True # TODO: remove this after adding trimmed netlist gen to sram run OPTS.trim_netlist = False From 4ec2dd2d1fbd09e16039a01c6026352616076b12 Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Tue, 14 Feb 2023 12:44:57 -0800 Subject: [PATCH 065/130] Format fixes --- compiler/characterizer/setup_hold.py | 49 ++++++++++++++++++---------- 1 file changed, 31 insertions(+), 18 deletions(-) diff --git a/compiler/characterizer/setup_hold.py b/compiler/characterizer/setup_hold.py index a47a8d14..cdc01046 100644 --- a/compiler/characterizer/setup_hold.py +++ b/compiler/characterizer/setup_hold.py @@ -42,6 +42,12 @@ class setup_hold(): self.stim_sp = "sh_stim.sp" temp_stim = OPTS.openram_temp + self.stim_sp self.sf = open(temp_stim, "w") + + # creates and opens the measure file for writing + self.meas_sp = "sh_meas.sp" + temp_meas = OPTS.openram_temp + self.meas_sp + self.mf = open(temp_meas, "w") + self.stim = stimuli(self.sf, self.mf, self.corner) self.write_header(correct_value) @@ -61,8 +67,10 @@ class setup_hold(): correct_value=correct_value) self.stim.write_control(4 * self.period) + self.sf.write(".include {}".format(temp_meas)) self.sf.close() + self.mf.close() def write_header(self, correct_value): """ Write the header file with all the models and the power supplies. """ @@ -131,7 +139,7 @@ class setup_hold(): else: dout_rise_or_fall = "FALL" - self.sf.write("\n* Measure statements for pass/fail verification\n") + self.mf.write("\n* Measure statements for pass/fail verification\n") trig_name = "clk" targ_name = "Q" trig_val = targ_val = 0.5 * self.vdd_voltage @@ -168,29 +176,33 @@ class setup_hold(): target_time=feasible_bound, correct_value=correct_value) self.stim.run_sim(self.stim_sp) - ideal_clk_to_q = convert_to_float(parse_spice_list("timing", "clk2q_delay")) + ideal_clk_to_q = convert_to_float(parse_spice_list("timing", + "clk2q_delay")) # We use a 1/2 speed clock for some reason... setuphold_time = (feasible_bound - 2 * self.period) if mode == "SETUP": # SETUP is clk-din, not din-clk passing_setuphold_time = -1 * setuphold_time else: passing_setuphold_time = setuphold_time - debug.info(2, "*** {0} CHECK: {1} Ideal Clk-to-Q: {2} Setup/Hold: {3}".format(mode, - correct_value, - ideal_clk_to_q, - setuphold_time)) + debug.info(2, "*** {0} CHECK: {1} Ideal Clk-to-Q: {2} Setup/Hold: {3}" + .format(mode, + correct_value, + ideal_clk_to_q, + setuphold_time)) if type(ideal_clk_to_q)!=float: debug.error("Initial hold time fails for data value feasible " - "bound {0} Clk-to-Q {1} Setup/Hold {2}".format(feasible_bound, - ideal_clk_to_q, - setuphold_time), + "bound {0} Clk-to-Q {1} Setup/Hold {2}" + .format(feasible_bound, + ideal_clk_to_q, + setuphold_time), 2) - debug.info(2, "Checked initial {0} time {1}, data at {2}, clock at {3} ".format(mode, - setuphold_time, - feasible_bound, - 2 * self.period)) + debug.info(2, "Checked initial {0} time {1}, data at {2}, clock at {3} " + .format(mode, + setuphold_time, + feasible_bound, + 2 * self.period)) while True: target_time = (feasible_bound + infeasible_bound) / 2 @@ -198,11 +210,12 @@ class setup_hold(): target_time=target_time, correct_value=correct_value) - debug.info(2, "{0} value: {1} Target time: {2} Infeasible: {3} Feasible: {4}".format(mode, - correct_value, - target_time, - infeasible_bound, - feasible_bound)) + debug.info(2, "{0} value: {1} Target time: {2} Infeasible: {3} Feasible: {4}" + .format(mode, + correct_value, + target_time, + infeasible_bound, + feasible_bound)) self.stim.run_sim(self.stim_sp) clk_to_q = convert_to_float(parse_spice_list("timing", "clk2q_delay")) From 7a62ec00304b799b1e8f9b35fea5d1fa7fcc685d Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Thu, 16 Feb 2023 19:36:14 -0800 Subject: [PATCH 066/130] Fixed typo --- compiler/characterizer/delay.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index 261a56ad..62429d8a 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -90,10 +90,10 @@ class delay(simulation): self.delay_meas = [] self.delay_meas.append(delay_measure("delay_lh", self.clk_frmt, targ_name, "FALL", "RISE", measure_scale=1e9)) self.delay_meas[-1].meta_str = sram_op.READ_ONE # Used to index time delay values when measurements written to spice file. - self.dealy_meas[-1].meta_add_delay = True + self.delay_meas[-1].meta_add_delay = True self.delay_meas.append(delay_measure("delay_hl", self.clk_frmt, targ_name, "FALL", "FALL", measure_scale=1e9)) self.delay_meas[-1].meta_str = sram_op.READ_ZERO - self.dealy_meas[-1].meta_add_delay = True + self.delay[-1].meta_add_delay = True self.read_lib_meas+=self.delay_meas self.slew_meas = [] From c8a06a131746c4f1968c7308f4304f1693118695 Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Fri, 17 Feb 2023 14:27:15 -0800 Subject: [PATCH 067/130] Properly trim wrapped instances --- compiler/base/hierarchy_spice.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/compiler/base/hierarchy_spice.py b/compiler/base/hierarchy_spice.py index da92c0fb..5d92ab25 100644 --- a/compiler/base/hierarchy_spice.py +++ b/compiler/base/hierarchy_spice.py @@ -394,11 +394,17 @@ class spice(): " ".join(self.conns[i]))) sp.write("\n") else: - wrapped_connections = "\n+ ".join(tr.wrap(" ".join(self.conns[i]))) + if trim and self.insts[i].name in self.trim_insts: + wrapped_connections = "\n*+ ".join(tr.wrap(" ".join(self.conns[i]))) + sp.write("X{0}\n*+ {1}\n*+ {2}\n".format(self.insts[i].name, + wrapped_connections, + self.insts[i].mod.cell_name)) + else: + wrapped_connections = "\n+ ".join(tr.wrap(" ".join(self.conns[i]))) + sp.write("X{0}\n+ {1}\n+ {2}\n".format(self.insts[i].name, + wrapped_connections, + self.insts[i].mod.cell_name)) - sp.write("X{0}\n+ {1}\n+ {2}\n".format(self.insts[i].name, - wrapped_connections, - self.insts[i].mod.cell_name)) sp.write(".ENDS {0}\n".format(self.cell_name)) From 4436c61a39f18c7f5b85116063c4ba28002dab38 Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Fri, 17 Feb 2023 14:35:09 -0800 Subject: [PATCH 068/130] discard if precharge delay is captured --- compiler/characterizer/delay.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index 62429d8a..fd779343 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -90,10 +90,10 @@ class delay(simulation): self.delay_meas = [] self.delay_meas.append(delay_measure("delay_lh", self.clk_frmt, targ_name, "FALL", "RISE", measure_scale=1e9)) self.delay_meas[-1].meta_str = sram_op.READ_ONE # Used to index time delay values when measurements written to spice file. - self.delay_meas[-1].meta_add_delay = True + self.delay_meas[-1].meta_add_delay = False self.delay_meas.append(delay_measure("delay_hl", self.clk_frmt, targ_name, "FALL", "FALL", measure_scale=1e9)) self.delay_meas[-1].meta_str = sram_op.READ_ZERO - self.delay[-1].meta_add_delay = True + self.delay_meas[-1].meta_add_delay = False self.read_lib_meas+=self.delay_meas self.slew_meas = [] @@ -1031,7 +1031,7 @@ class delay(simulation): slews_str = "slew_hl={0} slew_lh={1}".format(slew_hl, slew_lh) # high-to-low delays start at neg. clk edge, so they need to be less than half_period half_period = self.period / 2 - if abs(delay_hl)>half_period or abs(delay_lh)>self.half_period or abs(slew_hl)>half_period or abs(slew_lh)>self.period \ + if abs(delay_hl)>half_period or abs(delay_lh)>half_period or abs(slew_hl)>half_period or abs(slew_lh)>self.period \ or (delay_hl<0 and delay_lh<0) or slew_hl<0 or slew_lh<0: debug.info(2, "UNsuccessful simulation (in ns):\n\t\t{0}\n\t\t{1}\n\t\t{2}".format(period_load_slew_str, delays_str, @@ -1042,6 +1042,13 @@ class delay(simulation): delays_str, slews_str)) + if delay_lh < 0 and delay_hl > 0: + result_dict["delay_lh"] = result_dict["delay_hl"] + debug.info(2, "delay_lh captured precharge, using delay_hl instead") + elif delay_hl < 0 and delay_lh > 0: + result_dict["delay_hl"] = result_dict["delay_lh"] + debug.info(2, "delay_hl captured precharge, using delay_lh instead") + return True def find_min_period(self, feasible_delays): From 3b69cafde7f97691561e1bf4f2140978687fd90d Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Fri, 17 Feb 2023 19:15:14 -0800 Subject: [PATCH 069/130] Update Xyce char tests --- compiler/characterizer/stimuli.py | 2 +- compiler/tests/21_model_delay_test.py | 4 +++- compiler/tests/21_xyce_delay_test.py | 28 +++++++++++++-------------- 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/compiler/characterizer/stimuli.py b/compiler/characterizer/stimuli.py index 5e692fc0..c2bf3e39 100644 --- a/compiler/characterizer/stimuli.py +++ b/compiler/characterizer/stimuli.py @@ -279,7 +279,7 @@ class stimuli(): self.sf.write(".OPTIONS DEVICE TEMP={}\n".format(self.temperature)) self.sf.write(".OPTIONS MEASURE MEASFAIL=1\n") self.sf.write(".OPTIONS LINSOL type=klu\n") - self.sf.write(".OPTIONS TIMEINT RELTOL=1e-6 ABSTOL=1e-10 method=gear minorder=2\n") + self.sf.write(".OPTIONS TIMEINT RELTOL=1e-3 ABSTOL=1e-6 method=gear minorder=2\n") # Format: .TRAN self.sf.write(".TRAN {0}p {1}n 0n {0}p\n".format(timestep, end_time)) elif OPTS.spice_name: diff --git a/compiler/tests/21_model_delay_test.py b/compiler/tests/21_model_delay_test.py index 5a6d1ce3..46e2e66f 100755 --- a/compiler/tests/21_model_delay_test.py +++ b/compiler/tests/21_model_delay_test.py @@ -25,6 +25,8 @@ class model_delay_test(openram_test): openram.init_openram(config_file, is_unit_test=True) OPTS.analytical_delay = False OPTS.netlist_only = True + OPTS.spice_name = "Xyce" + OPTS.num_sim_threads = 8 # This is a hack to reload the characterizer __init__ with the spice version from importlib import reload @@ -93,7 +95,7 @@ class model_delay_test(openram_test): else: self.assertTrue(False) # other techs fail - debug.info(3, 'spice_delays {}'.fomrat(spice_delays)) + debug.info(3, 'spice_delays {}'.format(spice_delays)) debug.info(3, 'model_delays {}'.format(model_delays)) # Check if no too many or too few results diff --git a/compiler/tests/21_xyce_delay_test.py b/compiler/tests/21_xyce_delay_test.py index be5a70ee..1c62ad1b 100755 --- a/compiler/tests/21_xyce_delay_test.py +++ b/compiler/tests/21_xyce_delay_test.py @@ -84,20 +84,20 @@ class timing_sram_test(openram_test): 'write0_power': [0.429895901], 'write1_power': [0.383337501]} elif OPTS.tech_name == "scn4m_subm": - golden_data = {'delay_hl': [1.884186], - 'delay_lh': [1.884186], - 'disabled_read0_power': [20.86336], - 'disabled_read1_power': [22.10636], - 'disabled_write0_power': [22.62321], - 'disabled_write1_power': [23.316010000000002], - 'leakage_power': 13.351170000000002, - 'min_period': 7.188, - 'read0_power': [29.90159], - 'read1_power': [30.47858], - 'slew_hl': [2.042723], - 'slew_lh': [2.042723], - 'write0_power': [32.13199], - 'write1_power': [28.46703]} + golden_data = {'delay_hl': [1.78586], + 'delay_lh': [1.78586], + 'disabled_read0_power': [7.8296693788], + 'disabled_read1_power': [9.1464723788], + 'disabled_write0_power': [9.6889073788], + 'disabled_write1_power': [10.4123023788], + 'leakage_power': 0.0002442851, + 'min_period': 6.875, + 'read0_power': [16.995952378800002], + 'read1_power': [17.5845523788], + 'slew_hl': [2.039202], + 'slew_lh': [2.039202], + 'write0_power': [19.785462378800002], + 'write1_power': [15.742192378799999]} else: self.assertTrue(False) # other techs fail # Check if no too many or too few results From 3496ac8f5a290639054961508202d069ba7dc7c4 Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Tue, 21 Feb 2023 13:23:29 -0800 Subject: [PATCH 070/130] Added buffer to sense_amp output (need to resize) --- technology/freepdk45/sp_lib/sense_amp.sp | 15 ++++++++++----- technology/scn4m_subm/sp_lib/sense_amp.sp | 14 +++++++++----- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/technology/freepdk45/sp_lib/sense_amp.sp b/technology/freepdk45/sp_lib/sense_amp.sp index b5778306..21cdf1e5 100644 --- a/technology/freepdk45/sp_lib/sense_amp.sp +++ b/technology/freepdk45/sp_lib/sense_amp.sp @@ -1,11 +1,16 @@ .SUBCKT sense_amp bl br dout en vdd gnd -M_1 dout net_1 vdd vdd pmos_vtg w=540.0n l=50.0n -M_3 net_1 dout vdd vdd pmos_vtg w=540.0n l=50.0n -M_2 dout net_1 net_2 gnd nmos_vtg w=270.0n l=50.0n -M_8 net_1 dout net_2 gnd nmos_vtg w=270.0n l=50.0n -M_5 bl en dout vdd pmos_vtg w=720.0n l=50.0n +M_1 dint net_1 vdd vdd pmos_vtg w=540.0n l=50.0n +M_3 net_1 dint vdd vdd pmos_vtg w=540.0n l=50.0n +M_2 dint net_1 net_2 gnd nmos_vtg w=270.0n l=50.0n +M_8 net_1 dint net_2 gnd nmos_vtg w=270.0n l=50.0n +M_5 bl en dint vdd pmos_vtg w=720.0n l=50.0n M_6 br en net_1 vdd pmos_vtg w=720.0n l=50.0n M_7 net_2 en gnd gnd nmos_vtg w=270.0n l=50.0n + +M_8 dout_bar dint vdd vdd pmos_vtg w=720.0n l=50.0n +M_9 dout_bar dint gnd gnd nmos_vtg w=270.0n l=50.0n +M_10 dout dout_bar vdd vdd pmos_vtg w=720.0n l=50.0n +M_11 dout dout_bar gnd gnd nmos_vtg w=270.0n l=50.0n .ENDS sense_amp diff --git a/technology/scn4m_subm/sp_lib/sense_amp.sp b/technology/scn4m_subm/sp_lib/sense_amp.sp index 70622413..b3496b03 100644 --- a/technology/scn4m_subm/sp_lib/sense_amp.sp +++ b/technology/scn4m_subm/sp_lib/sense_amp.sp @@ -5,11 +5,15 @@ * SPICE3 file created from sense_amp.ext - technology: scmos M1000 gnd en a_56_432# gnd n w=1.8u l=0.4u -M1001 a_56_432# a_48_304# dout gnd n w=1.8u l=0.4u -M1002 a_48_304# dout a_56_432# gnd n w=1.8u l=0.4u -M1003 vdd a_48_304# dout vdd p w=3.6u l=0.4u -M1004 a_48_304# dout vdd vdd p w=3.6u l=0.4u -M1005 bl en dout vdd p w=4.8u l=0.4u +M1001 a_56_432# a_48_304# dint gnd n w=1.8u l=0.4u +M1002 a_48_304# dint a_56_432# gnd n w=1.8u l=0.4u +M1003 vdd a_48_304# dint vdd p w=3.6u l=0.4u +M1004 a_48_304# dint vdd vdd p w=3.6u l=0.4u +M1005 bl en dint vdd p w=4.8u l=0.4u M1006 a_48_304# en br vdd p w=4.8u l=0.4u +M1007 dout_bar dint vdd vdd p w=3.6u l=0.4u +M1008 gnd dint dout_bar gnd n w=1.8u l=0.4u +M1009 dout dout_bar vdd vdd p w=3.6u l=0.4u +M1010 gnd dout_bar dout gnd n w=1.8u l=0.4u .ENDS From bce71af0ad99b947ec68a46c0b8f2829b265cb85 Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Tue, 21 Feb 2023 13:51:13 -0800 Subject: [PATCH 071/130] Moved main scripts to root dir --- compiler/sram_char.py => sram_char.py | 2 +- compiler/sram_func.py => sram_func.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) rename compiler/sram_char.py => sram_char.py (97%) rename compiler/sram_func.py => sram_func.py (96%) diff --git a/compiler/sram_char.py b/sram_char.py similarity index 97% rename from compiler/sram_char.py rename to sram_char.py index 41b89512..c5024bc2 100755 --- a/compiler/sram_char.py +++ b/sram_char.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # See LICENSE for licensing information. # -# Copyright (c) 2016-2021 Regents of the University of California and The Board +# Copyright (c) 2016-2023 Regents of the University of California and The Board # of Regents for the Oklahoma Agricultural and Mechanical College # (acting for and on behalf of Oklahoma State University) # All rights reserved. diff --git a/compiler/sram_func.py b/sram_func.py similarity index 96% rename from compiler/sram_func.py rename to sram_func.py index 352a66ef..fd152e67 100755 --- a/compiler/sram_func.py +++ b/sram_func.py @@ -1,14 +1,14 @@ #!/usr/bin/env python3 # See LICENSE for licensing information. # -# Copyright (c) 2016-2021 Regents of the University of California and The Board +# Copyright (c) 2016-2023 Regents of the University of California and The Board # of Regents for the Oklahoma Agricultural and Mechanical College # (acting for and on behalf of Oklahoma State University) # All rights reserved. # """ -This script will functionally simulate an SRAM previously generated by OpenRAM -given a configuration file. Configuration option "use_pex" determines whether +This script will functionally simulate an SRAM previously generated by OpenRAM +given a configuration file. Configuration option "use_pex" determines whether extracted or generated spice is used. Command line arguments dictate the number of cycles and period to be simulated. """ From 8650315179771012dbb3bed6e486247a8f14020f Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Tue, 21 Feb 2023 13:52:21 -0800 Subject: [PATCH 072/130] Updated copyright headers --- compiler/characterizer/fake_sram.py | 6 ++++++ compiler/tests/30_memchar_test.py | 2 +- compiler/tests/30_memfunc_test.py | 2 +- compiler/tests/configs/config_mem_char_func.py | 2 +- 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/compiler/characterizer/fake_sram.py b/compiler/characterizer/fake_sram.py index 86c5cf4e..c4f12bf8 100644 --- a/compiler/characterizer/fake_sram.py +++ b/compiler/characterizer/fake_sram.py @@ -1,3 +1,9 @@ +# See LICENSE for licensing information. +# +# Copyright (c) 2016-{} Regents of the University of California, Santa Cruz +# All rights reserved +# + from openram import sram_config from math import ceil import re diff --git a/compiler/tests/30_memchar_test.py b/compiler/tests/30_memchar_test.py index faca2154..d9cab4bd 100755 --- a/compiler/tests/30_memchar_test.py +++ b/compiler/tests/30_memchar_test.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # See LICENSE for licensing information. # -# Copyright (c) 2016-2021 Regents of the University of California and The Board +# Copyright (c) 2016-2023 Regents of the University of California and The Board # of Regents for the Oklahoma Agricultural and Mechanical College # (acting for and on behalf of Oklahoma State University) # All rights reserved. diff --git a/compiler/tests/30_memfunc_test.py b/compiler/tests/30_memfunc_test.py index c9cf6eb8..5a74d774 100755 --- a/compiler/tests/30_memfunc_test.py +++ b/compiler/tests/30_memfunc_test.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # See LICENSE for licensing information. # -# Copyright (c) 2016-2021 Regents of the University of California and The Board +# Copyright (c) 2016-2023 Regents of the University of California and The Board # of Regents for the Oklahoma Agricultural and Mechanical College # (acting for and on behalf of Oklahoma State University) # All rights reserved. diff --git a/compiler/tests/configs/config_mem_char_func.py b/compiler/tests/configs/config_mem_char_func.py index a825acfc..c6adc0aa 100644 --- a/compiler/tests/configs/config_mem_char_func.py +++ b/compiler/tests/configs/config_mem_char_func.py @@ -1,6 +1,6 @@ # See LICENSE for licensing information. # -# Copyright (c) 2016-2021 Regents of the University of California and The Board +# Copyright (c) 2016-2023 Regents of the University of California and The Board # of Regents for the Oklahoma Agricultural and Mechanical College # (acting for and on behalf of Oklahoma State University) # All rights reserved. From 6eb0ecd82b0fe1e2b15ddc06f3228f9750c95416 Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Tue, 21 Feb 2023 14:07:08 -0800 Subject: [PATCH 073/130] fixed copyright again --- compiler/characterizer/fake_sram.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/compiler/characterizer/fake_sram.py b/compiler/characterizer/fake_sram.py index c4f12bf8..d1a97c33 100644 --- a/compiler/characterizer/fake_sram.py +++ b/compiler/characterizer/fake_sram.py @@ -1,12 +1,10 @@ # See LICENSE for licensing information. # -# Copyright (c) 2016-{} Regents of the University of California, Santa Cruz -# All rights reserved +# Copyright (c) 2016-2023 Regents of the University of California, Santa Cruz +# All rights reserved. # - from openram import sram_config from math import ceil -import re from openram import OPTS From f7f61fee271c4bf78d1c9be4fb02087efef799a4 Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Wed, 22 Feb 2023 12:38:47 -0800 Subject: [PATCH 074/130] Format fixes --- compiler/characterizer/delay.py | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index fd779343..db759b8a 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -1261,19 +1261,18 @@ class delay(simulation): def guess_spice_names(self): """This is run in place of set_internal_spice_names function from simulation.py when running stand-alone characterizer.""" - # TODO: Find a better method with open(self.sp_file, "r") as file: bl_prefix = None br_prefix = None replica_bitcell_array_name = None for line in file: - if re.search("bl_\d_\d", line): + if re.search(r"bl_\d_\d", line): bl_prefix = "bl_" br_prefix = "br_" - if re.search("bl\d_\d", line): + if re.search(r"bl\d_\d", line): bl_prefix = "bl" br_prefix = "br" - if re.search("Xreplica_bitcell_array", line): + if re.search(r"Xreplica_bitcell_array", line): replica_bitcell_array_name = "replica_bitcell_array" if bl_prefix and replica_bitcell_array_name: break @@ -1285,10 +1284,6 @@ class delay(simulation): replica_bitcell_array_name = "bitcell_array" self.cell_format = "X{{0}}{{3}}xbank0{{3}}x{0}{{3}}xbitcell_array{{3}}xbit_r{{1}}_c{{2}}".format(replica_bitcell_array_name) - - - - def analysis_init(self, probe_address, probe_data): """Sets values which are dependent on the data address/bit being tested.""" From c447ec49eb5b31c03fcb2c7e37addd196dd3fb7e Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Thu, 23 Feb 2023 15:14:39 -0800 Subject: [PATCH 075/130] Added the new import method --- sram_char.py | 19 +++++-------------- sram_func.py | 18 ++++-------------- 2 files changed, 9 insertions(+), 28 deletions(-) diff --git a/sram_char.py b/sram_char.py index c5024bc2..a6968bf8 100755 --- a/sram_char.py +++ b/sram_char.py @@ -16,20 +16,11 @@ an analytical model or spice simulation is used for characterization. import sys import datetime from globals import * -try: - import openram -except: - # If openram library isn't found as a python package, - # import it from the $OPENRAM_HOME path. - import importlib.util - OPENRAM_HOME = os.getenv("OPENRAM_HOME") - # Import using spec since the directory can be named something - # other than "openram". - spec = importlib.util.spec_from_file_location("openram", "{}/../__init__.py".format(OPENRAM_HOME)) - module = importlib.util.module_from_spec(spec) - sys.modules["openram"] = module - spec.loader.exec_module(module) - import openram + +# You don't need the next two lines if you're sure that openram package is installed +from common import * +make_openram_package() +import openram (OPTS, args) = openram.parse_args() diff --git a/sram_func.py b/sram_func.py index fd152e67..3d9fecca 100755 --- a/sram_func.py +++ b/sram_func.py @@ -17,20 +17,10 @@ import sys import datetime from globals import * -try: - import openram -except: - # If openram library isn't found as a python package, - # import it from the $OPENRAM_HOME path. - import importlib.util - OPENRAM_HOME = os.getenv("OPENRAM_HOME") - # Import using spec since the directory can be named something - # other than "openram". - spec = importlib.util.spec_from_file_location("openram", "{}/../__init__.py".format(OPENRAM_HOME)) - module = importlib.util.module_from_spec(spec) - sys.modules["openram"] = module - spec.loader.exec_module(module) - import openram +# You don't need the next two lines if you're sure that openram package is installed +from common import * +make_openram_pacakage() +import openram (OPTS, args) = openram.parse_args() From 249d1b9c1d8323571acfd6f67974c75f1a8d0a7e Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Fri, 24 Feb 2023 16:42:39 -0800 Subject: [PATCH 076/130] Moved sram_op and bit_polarity --- compiler/characterizer/bit_polarity.py | 14 ------------ compiler/characterizer/charutils.py | 31 ++++++++++++++++++++++++++ compiler/characterizer/sram_op.py | 15 ------------- 3 files changed, 31 insertions(+), 29 deletions(-) delete mode 100644 compiler/characterizer/bit_polarity.py delete mode 100644 compiler/characterizer/sram_op.py diff --git a/compiler/characterizer/bit_polarity.py b/compiler/characterizer/bit_polarity.py deleted file mode 100644 index 5a6b6a06..00000000 --- a/compiler/characterizer/bit_polarity.py +++ /dev/null @@ -1,14 +0,0 @@ -# See LICENSE for licensing information. -# -# Copyright (c) 2016-2023 Regents of the University of California and The Board -# of Regents for the Oklahoma Agricultural and Mechanical College -# (acting for and on behalf of Oklahoma State University) -# All rights reserved. -# - -from enum import Enum - -class bit_polarity(Enum): - NONINVERTING = 0 - INVERTING = 1 - diff --git a/compiler/characterizer/charutils.py b/compiler/characterizer/charutils.py index 872901b7..1c365fd5 100644 --- a/compiler/characterizer/charutils.py +++ b/compiler/characterizer/charutils.py @@ -7,6 +7,7 @@ # import os import re +from enum import Enum from openram import debug from openram import OPTS @@ -107,3 +108,33 @@ def check_dict_values_is_float(dict): if type(value)!=float: return False return True + + +def bidir_search(func, upper, lower, time_out=9): + """ + Performs bidirectional search over given function with given + upper and lower bounds. + """ + time_count = 0 + while time_count < time_out: + val = (upper + lower) / 2 + if func(val): + return (True, val) + time_count += 1 + return (False, 0) + + +class bit_polarity(Enum): + NONINVERTING = 0 + INVERTING = 1 + + +class sram_op(Enum): + READ_ZERO = 0 + READ_ONE = 1 + WRITE_ZERO = 2 + WRITE_ONE = 3 + DISABLED_READ_ZERO = 4 + DISABLED_READ_ONE = 5 + DISABLED_WRITE_ZERO = 6 + DISABLED_WRITE_ONE = 7 diff --git a/compiler/characterizer/sram_op.py b/compiler/characterizer/sram_op.py deleted file mode 100644 index 3aeca925..00000000 --- a/compiler/characterizer/sram_op.py +++ /dev/null @@ -1,15 +0,0 @@ -# See LICENSE for licensing information. -# -# Copyright (c) 2016-2023 Regents of the University of California and The Board -# of Regents for the Oklahoma Agricultural and Mechanical College -# (acting for and on behalf of Oklahoma State University) -# All rights reserved. -# - -from enum import Enum - -class sram_op(Enum): - READ_ZERO = 0 - READ_ONE = 1 - WRITE_ZERO = 2 - WRITE_ONE = 3 From 8d0c46d0690de3e6b3b6fedd41b426fd8f7e89c7 Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Wed, 12 Apr 2023 11:48:20 -0700 Subject: [PATCH 077/130] Fix import issue --- compiler/characterizer/delay.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index db759b8a..78e57f88 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -13,8 +13,6 @@ from openram import OPTS from .stimuli import * from .trim_spice import * from .charutils import * -from .sram_op import * -from .bit_polarity import * from .simulation import simulation from .measurements import * from os import path @@ -1282,7 +1280,7 @@ class delay(simulation): self.sen_name = "X{0}{1}xbank0{1}s_en".format(self.sram.name, OPTS.hier_seperator) if not replica_bitcell_array_name: replica_bitcell_array_name = "bitcell_array" - self.cell_format = "X{{0}}{{3}}xbank0{{3}}x{0}{{3}}xbitcell_array{{3}}xbit_r{{1}}_c{{2}}".format(replica_bitcell_array_name) + self.cell_format = "X{{0}}{{3}}xbank0{{3}}xbitcell_array{{3}}x{0}{{3}}xbitcell_array{{3}}xbit_r{{1}}_c{{2}}".format(replica_bitcell_array_name) def analysis_init(self, probe_address, probe_data): """Sets values which are dependent on the data address/bit being tested.""" From 0ff1d1a23dd849ab10cef4ada57f86c0ed943d86 Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Wed, 12 Apr 2023 11:49:32 -0700 Subject: [PATCH 078/130] Added buff to sense_amp in scmos --- technology/scn4m_subm/gds_lib/sense_amp.gds | Bin 8312 -> 12232 bytes technology/scn4m_subm/mag_lib/sense_amp.mag | 276 ++++++++++++-------- technology/scn4m_subm/sp_lib/sense_amp.sp | 8 +- 3 files changed, 166 insertions(+), 118 deletions(-) diff --git a/technology/scn4m_subm/gds_lib/sense_amp.gds b/technology/scn4m_subm/gds_lib/sense_amp.gds index 5ffbb0d53e3ad45cbe16f30f7bcf9dd6620ecc89..c6a71401c2617416e3dfd4f15460871d37b34342 100644 GIT binary patch literal 12232 zcmb7~O>CT36^3tYXW}$d$0==onm{dn+B8iZx243D3b+D9ARwZs3sVYpOF}JCf|Zuk zR+CJt{mA}ad+D8vGGzm_l}ffr86;7N;y6`s(OwXRDN7ZL0yb$`7xXvR^;uFV;&zH>Ick53Q8)!ktnM-5T)Qv!$S$YOneqT@1f@@_P79>8XG0 zMk(E1)NkImri&%rlwS3B=1SQ&qsh^be%vpV-u54Fk3Zx7+q0#7Sno6cd?oTRrKf(z znQ>zL&DR%W{7vb(f2x$H)W?w)&)kw<|2Ng1`l;`u3sJv0y&3hJ(yRVMCF(Wl$NfU- zssH}7rR>mnJ*XdZ*SeOvbW?iU|5$tcyS-9=qw!*`n15J`Ibljq{p9>Rc^N;Gb%Sn7 zPyIWWOZl;`-vb8+{P|od=%(7M{`0zC_{~cj;WwqHeth3rDdphofG=H-{!F!}ey-1{ zei~n&(o;WiS?kPK6EC_cz3rcAub+EQ zYu;8Az2*mt`6Ce4T_|VOopLzPCyxd341!?G}^fZ6o_t;wa%@gVm-ISjCca3YV{j-$us{`(R zM&l{nRD0@Y{^Do-nE24mnxA=!m-%Z>F2?*drKj=9bN9a@e{;`sk-sTD^^+$)Vw?ET z&6=NcAM5<^{D6O)jq{wT_B1~8_u^K}UvsG!^VgJ~`n!5BKIX5958bT!?^_EW^A|tF zhi=yVmt`6Ce4T_|VOopL5n1H)Fn=Us{UulPNvTf6vYEGvDz;eCTG)zwb`?SjYGw zK6JC@=iG*mb!6g0H*0?C|D0m6513z24(O)zYW?`A+r&rxX3bBX_^8{&hi=yV)QOM! zO?>EP%}}u3+O0U+BkNQn~)Nj`O)QOM!O?>EP%}<^9sNckgZr1$N|IE>- z-~9B=sNa-ctsfutoA{{Ttof-EAN8B~(9N2kI`L7zi4WbZ`Kf<)F6uX*UXS`s>DBu2 zQNM|g`puf3I`L7zi4WbZ`Kc2h^_%$6&6=Ne&*vV_FXnOOf^H6d{<-V?k8ffl{16}G zVb=V_d1Nx;n@3k8z9~H&f8yXHu89xbtoe!mv7-^+{P@j?Z%VJm$47hDBo7h;QN}zFG4#?~dG#^P~BZ<(QAA^fW$s9-fcJ7Y;ptylecwxu*JON-=qEymvL8A4BPBe4bmpxf%JJ#78%!r+&_jm)F8?(hs^R zJ@qrsUzmyfP3k~5rC0sWuWJ01vq?Yh7fP@C&#lM$GwG-C^(j5|Gfwz;c4b~x{^(}S zPn@sai2P0ZK{utR@mZ(%h;QOUH*0?8_Zj8N_?fJOX5RNHJ&n)4`zgi8Z_*FCDLwV` zxf>t(nmjj0H*0?4JT(=5lYX36)1Jns&L^~;`xL+te^)qhl zy_|Q<>CG5VQ+n0ke|9n1Ji`#_$NfUJSN)y2h;PzgSv$s_M(21aX>evxBVyE z_YdCp*YWV1f4drfQ+nzr*Ed$;`kQY`LpPyh4BsRJ!z3qRZef>B$ zUs;K>hskqjbW?ijCnozfu}t=TbaQC`-xi^-EA#_uEJATU_CbsJ?P>kAQ#bjW^y7Y;_SE0)#rKq)-}$~0(hs^RJ@s>qStraD z)8BiV(o;X{obOMGYvMyUrKf(@3Fo~2e%lZqx~cZ6|MFU_ACvyvFO;78$@BcJ$ltuQ z5&4_aQ$PLVBY%@Tnz((|{KS8GN%1EKq#x(iw5RcDUr=n;y-9!Ww`ouPTz{W?P3D2; zMbn=8shj&A@lEnTH;3+j+ty$IoH`!o1@2dz8_uoAUiJaE?_b;e>|2~$@tO34ZVsJa zxB1y8@%^u4!=o1=%)14&wUaf^VcLkx>@u4?+^IAhaXZmx>@rx?})?oGZ}w$Q+k>|_g&)R zH|Yo6ti@-XIH$5sO#1P-HtlJA)(PKplCL=}4c(NU`Z;rxJLgZ6e$Y+nslVI1`|mIC zp_@a`54X*K-bY;S-=^N*_nWo&)cMFp)NkTLH>IcfQzvtU`Ib3^5eyIGs(ksHSMXN{CIKwctQNGt7%XDj5FVpu-BR1 zcTMTJe>3XjI#VxX&NBZ^>23dK+w)g%@4wiyc|qnKFH^tv{auC7-+ycV?;nxYVgEq`AvokN|MFXd5pFMRN> zSMzrf^XnV`J0@fE_6+a4s|MYZ`(x5MutOu$d60j*hj-5X<2$?-W2~g{SzS3_xER^& J(nySz{{l6kQY!!e literal 8312 zcmaKxO>9*~7=}Okb18U%A_x>vk)KczrGf~E(Hco4!T3YaR5YP#3zeTjtycTz(9b471O>OIYS~n-BZ%$tL@!E}u&At5}ee%b#GynYk^u(#fL-T*0KNmau z3wEn%_YFj}*7d}JXsz#wh=YT@`nP($KAL`kUoNEIP5rNLqkby?&2FFL?7`p1l5eWL z>A&6d*FKGy(BWG(J#%_Eg4|S|^?R2i&OVOV@}TAq&mzc8wP*cJ_alz(iWquS^W=C0 zxvBQ1f3R6Ub^mfN;?;$k*B8@#Otoiy>SP@1H$R_E^_$A`zG`1T7_qa#Jx}H9|EAiT z{#(uZ+cOc98t;`SHLuP^keh1H`a=ezW^NhyEH=eDl(B8sAi&^%)0` z@l8B(v*fo_`*(v8t5vgkeqI}$a#MMB{Ps-p_zdAgJaV(-zx*(Ho4=}wM{bsU>ilLn z)o*^gnCdr`7wgBPZWE9C&5}=@c+_v=k((u-edE}@wBMO02K0U^HM=IBzY-&9_#ACLM?JnA<~K6TrN!j258^{SaPdw&r;*pyrpLyaje-n?~EcwinW0}86U*x9p z;{5TLzlq2E&63YN@tD7fM{bsU9DX>~Z2n%gXX|I4e0G?>$=*$FD$n}N6OZ|uc;sfu zXP$V>-^3#~OFr|%W6mZXxmog==ipSDzscC-rt;$a@tD7f$NbHb&oOw+-z01Plziri z$NWuPao-!9@2%vf+Ot02v(65r`c1|sH$7jXr!}U2^QihGHHe=pWE}4a`ND^iz2&RG#%&Cp_kFvJT{C$!DDXOR0X7e#lMb+3~kL zNIv7^yAE>vsy*v-e(xDhXo z+4OlgkM7d@uiR9g9iQWd=aX+97)idVJnQrP36JyD#3MJm{KL)l(o~g-sOKx_Zza8WAzTvN63Ha^@p zqp?S7mVC}T#^JuvWc|ra<=Oh#Hy9V+q#ts#G(PLZ-pS|0q#v(q)!rQcNPYcG>%MO$ zt(VE)4S7FIcve|Yi!ne3V5rt+*$eY`l|P3rKxs`ji;eY|-8 zctL#6t7>ohA2-h*9A2EiCht2hQ@^hGZ9SIO-@mp0Zs}3h+PaE=xASj%NB`(w7kN!Z z+kY3=eOqg&H96g3>+D^zSB_#-{dHjN^>x-(HaZq0baZ;u%D hr>pr<*&C{(e$5}nUzYVQYRrl2w{NB6R;$Lo_zyW|ko5on diff --git a/technology/scn4m_subm/mag_lib/sense_amp.mag b/technology/scn4m_subm/mag_lib/sense_amp.mag index e5fa4373..7dc36202 100644 --- a/technology/scn4m_subm/mag_lib/sense_amp.mag +++ b/technology/scn4m_subm/mag_lib/sense_amp.mag @@ -1,136 +1,184 @@ magic tech scmos -timestamp 1536089670 +timestamp 1680718477 << nwell >> -rect 0 0 40 102 +rect 0 28 40 153 << pwell >> -rect 0 102 40 163 +rect 0 153 40 214 +rect 0 0 40 28 << ntransistor >> -rect 21 130 23 139 -rect 12 108 14 117 -rect 20 108 22 117 +rect 21 181 23 190 +rect 12 159 14 168 +rect 20 159 22 168 +rect 13 10 15 22 +rect 21 18 23 22 << ptransistor >> -rect 12 78 14 96 -rect 20 78 22 96 -rect 11 20 13 44 -rect 27 20 29 44 +rect 12 129 14 147 +rect 20 129 22 147 +rect 11 71 13 95 +rect 27 71 29 95 +rect 13 34 15 58 +rect 21 34 23 42 << ndiffusion >> -rect 20 130 21 139 -rect 23 130 24 139 -rect 11 108 12 117 -rect 14 108 15 117 -rect 19 108 20 117 -rect 22 108 23 117 +rect 20 181 21 190 +rect 23 181 24 190 +rect 11 159 12 168 +rect 14 159 15 168 +rect 19 159 20 168 +rect 22 159 23 168 +rect 12 10 13 22 +rect 15 10 16 22 +rect 20 18 21 22 +rect 23 18 24 22 << pdiffusion >> -rect 7 94 12 96 -rect 11 80 12 94 -rect 7 78 12 80 -rect 14 94 20 96 -rect 14 80 15 94 -rect 19 80 20 94 -rect 14 78 20 80 -rect 22 94 27 96 -rect 22 80 23 94 -rect 22 78 27 80 -rect 10 20 11 44 -rect 13 20 14 44 -rect 26 20 27 44 -rect 29 20 30 44 +rect 7 145 12 147 +rect 11 131 12 145 +rect 7 129 12 131 +rect 14 145 20 147 +rect 14 131 15 145 +rect 19 131 20 145 +rect 14 129 20 131 +rect 22 145 27 147 +rect 22 131 23 145 +rect 22 129 27 131 +rect 10 71 11 95 +rect 13 71 14 95 +rect 26 71 27 95 +rect 29 71 30 95 +rect 12 34 13 58 +rect 15 34 16 58 +rect 20 34 21 42 +rect 23 34 24 42 << ndcontact >> -rect 16 130 20 139 -rect 24 130 28 139 -rect 7 108 11 117 -rect 15 108 19 117 -rect 23 108 27 117 +rect 16 181 20 190 +rect 24 181 28 190 +rect 7 159 11 168 +rect 15 159 19 168 +rect 23 159 27 168 +rect 8 10 12 22 +rect 16 10 20 22 +rect 24 18 28 22 << pdcontact >> -rect 7 80 11 94 -rect 15 80 19 94 -rect 23 80 27 94 -rect 6 20 10 44 -rect 14 20 18 44 -rect 22 20 26 44 -rect 30 20 34 44 +rect 7 131 11 145 +rect 15 131 19 145 +rect 23 131 27 145 +rect 6 71 10 95 +rect 14 71 18 95 +rect 22 71 26 95 +rect 30 71 34 95 +rect 8 34 12 58 +rect 16 34 20 58 +rect 24 34 28 42 << psubstratepcontact >> -rect 32 137 36 141 +rect 32 188 36 192 +rect 28 4 32 8 << nsubstratencontact >> -rect 27 70 31 74 +rect 27 121 31 125 +rect 27 55 31 59 << polysilicon >> -rect 21 139 23 149 -rect 21 129 23 130 -rect 3 127 23 129 -rect 3 47 5 127 -rect 12 122 34 124 -rect 12 117 14 122 -rect 20 117 22 119 -rect 12 96 14 108 -rect 20 96 22 108 -rect 32 105 34 122 -rect 30 101 34 105 -rect 12 76 14 78 -rect 20 69 22 78 -rect 13 67 22 69 -rect 9 55 11 65 -rect 32 55 34 101 -rect 33 51 34 55 -rect 3 45 13 47 -rect 11 44 13 45 -rect 27 44 29 46 -rect 11 19 13 20 -rect 27 19 29 20 -rect 11 17 29 19 +rect 21 190 23 200 +rect 21 180 23 181 +rect 3 178 23 180 +rect 3 98 5 178 +rect 12 173 34 175 +rect 12 168 14 173 +rect 20 168 22 170 +rect 12 147 14 159 +rect 20 147 22 159 +rect 32 156 34 173 +rect 30 152 34 156 +rect 12 127 14 129 +rect 20 120 22 129 +rect 13 118 22 120 +rect 9 106 11 116 +rect 32 106 34 152 +rect 33 102 34 106 +rect 3 96 13 98 +rect 11 95 13 96 +rect 27 95 29 97 +rect 11 70 13 71 +rect 27 70 29 71 +rect 11 68 29 70 +rect 7 63 23 65 +rect 13 58 15 60 +rect 21 42 23 63 +rect 13 31 15 34 +rect 13 27 14 31 +rect 13 22 15 27 +rect 21 22 23 34 +rect 21 16 23 18 +rect 13 8 15 10 << polycontact >> -rect 20 149 24 153 -rect 26 101 30 105 -rect 9 65 13 69 -rect 9 51 13 55 -rect 29 51 33 55 +rect 20 200 24 204 +rect 26 152 30 156 +rect 9 116 13 120 +rect 9 102 13 106 +rect 29 102 33 106 +rect 3 63 7 67 +rect 14 27 18 31 << metal1 >> -rect -2 149 20 153 -rect 24 149 36 153 -rect 28 133 32 137 -rect 16 117 19 130 -rect 7 94 11 108 -rect 23 105 27 108 -rect 23 101 26 105 -rect 7 69 11 80 -rect 15 94 19 96 -rect 15 78 19 80 -rect 23 94 27 101 -rect 23 78 27 80 -rect 15 75 18 78 -rect 15 74 31 75 -rect 15 72 27 74 -rect 7 65 9 69 -rect 6 44 9 54 -rect 33 51 34 55 -rect 31 44 34 51 -rect 3 20 6 23 -rect 3 15 7 20 +rect -2 200 20 204 +rect 24 200 36 204 +rect 28 184 32 188 +rect 16 168 19 181 +rect 7 145 11 159 +rect 23 156 27 159 +rect 23 152 26 156 +rect 7 120 11 131 +rect 15 145 19 147 +rect 15 129 19 131 +rect 23 145 27 152 +rect 23 129 27 131 +rect 15 126 18 129 +rect 15 125 31 126 +rect 15 123 27 125 +rect 7 116 9 120 +rect 6 95 9 105 +rect 33 102 34 106 +rect 31 95 34 102 +rect 3 71 6 74 +rect 3 67 7 71 +rect 20 55 27 58 +rect 8 22 11 34 +rect 24 30 28 34 +rect 18 27 28 30 +rect 24 22 28 27 +rect 3 10 8 13 +rect 3 9 10 10 +rect 3 8 7 9 +rect 16 7 20 10 +rect 16 4 28 7 << m2contact >> -rect 32 133 36 137 -rect 27 66 31 70 -rect 13 44 17 48 -rect 22 44 26 48 -rect 3 11 7 15 +rect 32 184 36 188 +rect 27 117 31 121 +rect 13 95 17 99 +rect 22 95 26 99 +rect 27 51 31 55 +rect 3 4 7 8 +rect 28 8 32 12 << metal2 >> -rect 10 48 14 163 -rect 20 48 24 163 -rect 32 129 36 133 -rect 27 62 31 66 -rect 10 44 13 48 -rect 20 44 22 48 -rect 3 0 7 11 -rect 10 0 14 44 -rect 20 0 24 44 +rect 10 99 14 214 +rect 20 99 24 214 +rect 32 180 36 184 +rect 27 113 31 117 +rect 10 95 13 99 +rect 20 95 22 99 +rect 3 0 7 4 +rect 10 0 14 95 +rect 20 0 24 95 +rect 27 47 31 51 +rect 28 12 32 16 << bb >> -rect 0 0 34 163 +rect 0 0 34 214 << labels >> -flabel metal1 0 149 0 149 4 FreeSans 26 0 0 0 en -rlabel metal2 34 131 34 131 1 gnd -rlabel metal2 29 64 29 64 1 vdd -rlabel metal2 12 161 12 161 5 bl -rlabel metal2 22 161 22 161 5 br -rlabel metal2 5 3 5 3 1 dout +rlabel metal2 5 2 5 2 1 dout +rlabel metal2 30 14 30 14 1 gnd +rlabel metal2 29 49 29 49 1 vdd +rlabel metal2 22 212 22 212 5 br +rlabel metal2 12 212 12 212 5 bl +rlabel metal2 29 115 29 115 1 vdd +rlabel metal2 34 182 34 182 1 gnd +flabel metal1 0 200 0 200 4 FreeSans 26 0 0 0 en << properties >> string path 270.000 468.000 270.000 486.000 288.000 486.000 288.000 468.000 270.000 468.000 << end >> diff --git a/technology/scn4m_subm/sp_lib/sense_amp.sp b/technology/scn4m_subm/sp_lib/sense_amp.sp index b3496b03..2b72262e 100644 --- a/technology/scn4m_subm/sp_lib/sense_amp.sp +++ b/technology/scn4m_subm/sp_lib/sense_amp.sp @@ -12,8 +12,8 @@ M1004 a_48_304# dint vdd vdd p w=3.6u l=0.4u M1005 bl en dint vdd p w=4.8u l=0.4u M1006 a_48_304# en br vdd p w=4.8u l=0.4u -M1007 dout_bar dint vdd vdd p w=3.6u l=0.4u -M1008 gnd dint dout_bar gnd n w=1.8u l=0.4u -M1009 dout dout_bar vdd vdd p w=3.6u l=0.4u -M1010 gnd dout_bar dout gnd n w=1.8u l=0.4u +M1007 dout_bar dint vdd vdd p w=1.6u l=0.4u +M1008 gnd dint dout_bar gnd n w=0.8u l=0.4u +M1009 dout dout_bar vdd vdd p w=4.8u l=0.4u +M1010 gnd dout_bar dout gnd n w=2.4u l=0.4u .ENDS From 027b93ab8346efd9c347964bc635e53928a63823 Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Wed, 12 Apr 2023 11:49:55 -0700 Subject: [PATCH 079/130] Added buff to sense_amp in freepdk45 --- technology/freepdk45/gds_lib/sense_amp.gds | Bin 14318 -> 17514 bytes technology/freepdk45/sp_lib/sense_amp.sp | 6 +++--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/technology/freepdk45/gds_lib/sense_amp.gds b/technology/freepdk45/gds_lib/sense_amp.gds index f0bfebfd210fedacdcc5a82b7f040a3b13e89b58..9c59cf9ec7e48b526b3e3452580cc46b05c6c393 100644 GIT binary patch literal 17514 zcmcJWdyHLG6~_0y_uSiQXQuQqZRunBE`^!WAb~&)s6<1IDTW9bN>pAg7_Eg;O2WHH z6km?h5g8U(hi7#jbMAVRoA^t%$hDcB(7$AVD-?!HO&g0JP&7~ug;IH>P z=R0e!eb(M*pM9^P7uxOf!-`gW)^ni>1ryue4N(bxhZ}@rtcpga~@1H0==MT7VqmO(1u`@lsC>_kkU-Su&zx)}GFG>gN{$AC8 z9vA%+*pA^(qW|Vpl-}2WQ~a!V`fXetRZ%*ajDH06KPA5Ee8Bo|_>Z9e8-C`^`%J2C zMCpC^zu`ZE`f2zXS9PMg5vBLlPs7jnsuR_XD7~+KTCsjknhau1r<4O$Ky$V z=bxBg|ABUZ8xP|ATPsQjlm0g5V4g?P-)$^2R0JddQW^^Jn3{cBfw zd~pzez5Viu^vC1L_RrK`&!2Ibzc@(yXX@wt&p0IeozFi}I+)HM&pn>Ud7M7Z|DyCk z{mh&3#XZ_8K3pT z^GNzwf1>oa^q*S!8}Xw)_tbQJjvpMiai(^Q(%(tH%a@2qW;5qwsf@SCkIc{l)+J{Y=;M{VMdQtvf-k16dEE zba1-%_xXQc>@vqR#7k zKh^b)^!>Eq=lsIw2x-q1^rtAj@A=a3v%YyAN#6j^*M`4;ej8wZZ}|Ji*8uZN!+!+h zYj%DAtMy0p9rmwC?tisUt|+~4|4RO?-2do&8s0xShp}%_Tm--PJU+jI&m#8OSf|60 z@`3g7qU&3Ibk2(7gXI41k80%j@#9%P_s4i1#~1x2r8oDNr^J`PKfZJ@8K3>i@ohx= z*}uGwQF=G;XB_(3Zu&|}e~b9?mvLi!>ACi|@4$SG`Gw@Zbo;**rGv@*>Ek}S5$~Jy zbDlCvZ|<)*`oHe)k6&Il<7dBdTpRZzF8YuAlSb*Q((R{@`F{6YMzTbs{F_*lOs(f)Wm+5bGwI7YOeezxBzJ=6ZWzlIWXa3xWC9zJm z{u8D5?axl>KU;6Z&wX9?zbG9{=3kF5pEyW-=Ffd#BiC{0KdzgM(wpBeG}=#}tv5-0 zKS5u~oqk;$Pqx1vzx2iHllbG zJ0q{d`A_WO+3Cl#e%`0@I(NqFfzrXOe+>E3Z}*$^$GQWhgGoQ@XVurd&N$!GCrSsC ze)c=hBk5!Ri_&v`)=lws_`vS5Anu1K9jwP6j_VU!Ulfbr!TO&pzJ-5}R_v~HU7Ym* zK4Xtslnze|#G>rR6E;<@~p`vtfy7rr&>qo{TS)29$q=Q+1595;lk(b>sN(Ynv)@+YY&N+;} z_;N+YkH?dKyPqFLT-?|0cJQkei>QNX|GUxd-SClUf9HcWO5dIKhuhHSPay}ed!Dyf zlny51<9m11NAZ}mdttmzr1YXWKdQd{{repp|}>`??g%mlm7PS+)vWS_aBk|cs%V#-Pw5{eXL(mdM-Ze zi|3K_vHnEqIe+KYL^GN!5|3&FJKkqNkBkAM)7o}(Y$b0TRp8wdG=PybJv-$Hp z=1(8<7p3R?%zH8B4s!YTJbzI-n2gW7c^*k0^B1LO{rGLb@tAw~8-dNpq4SZ7(!pf> z?ir{zw4FS@3qD*?I+*l#-i-N!OE7m9H&tZ&5| z1>3)|`*usbf1q?Q;m5rD24e4bcJIV>ZbTa*r5F2Ce)Ri3)bD2J%F~c9=1);Nn1~M_ zo?G@_2d+b0KEFiiVA}sO*2ClQfg8||{QZ?E9ZdRLPk8;1te^IWE3$s#@ua_4AJ-q` zv*^1MYvj7bk0<>$Z=z<&O}B!FDo#cnO!`$fq}4C#M`S(4<4Hg7-@^UK8|3b)WM|R#{DsfkMY0aKE%iP7nesJ%=%YMRDRCC^c$s5Wc(-Nd3O=~ z;Bj2X{i>pLFd3io9^;ea_j_DXI+*mc|JZLN=X=h-qI59nXS>(pxlOJ+&*O{I!K9yY z*I(-K*Z&=PoQ2P#^h@*pmH&4Ch6la>nYwq5%7XCf5y!+lK`1ji@!-)N^xxjsRH1wACb~JzeIa=R+?>r7K{>aV$LAH3~ z5v7Cm>>K{pCZ2^BgY>n2Qc*gX@T2P9{@Y6SzUpoGIcjZ{1KR2bBS4hiw|Z;%!|QRC0@~{3 z^A&CN;>Q#Dd)3-o8miac-thDgrGr_&ty18(RSW#0^uEh}a30H+Br4Oh3&sLLoBP5U6>wa-V)WLN9<86fT`BuWXoR>>V&%~#XaY)9c zUzDDUUp#_Y@@cdiWOb7 zZ*X!oc&MUuFxmg~9f!4mT?Yx$KM^S%O!~Q-$T+sEi1@av7%4p$-*zPt->!qW^fNxm z`0;o;KKgCV7Mw@^3`GBxl)fd?e)v|easTS?xWA0_QG^QKRf zp3VPy>`G(K=kw#JT_BzxqI57>KlIHj+&>TFjsB9-i@bmS3ir>)JV1X*=_~U71t+Dw?*lXbU6{Um8 z`ZM3{?mv2&`^6fUM@;T2^II9)O~x9sr1a*la-;ox?<#+N z@(lXnAU=!dRK?5Di}|5Hx>n!&ymi9Dk5?u>R{GCezp6@UvYm)>2dD~%WCclH~PxU`{TZD_p`pQOV<9Z{TSLs5&j2Dw*Wi< literal 14318 zcmcJVYlvM}8HU%{=aQMsr8AS6N#>T!oXNCAQt6+fZDT{cfC?39iM3EMsfm?PC$VV? zl3G)X)*Fgo#S(w0D5bTaRTNtqu%uPd8WsE_h@gdn&?-elyfwb>x7NFF$y(i+Lj%Jz ze0x9VTi>_WT6>?JaXpu1?{$l_5*V>9PN!;whi`yGT!t+~f0$ii64gqhI#=p?fO^z4a}d4 z&%Bx^nm3~2wfR%=nP2ln^F~y>Hh)^>>(_qCxuqSb8{GaY%$@rSDh_rgaVYFx6+b)a zeUg3~CyMmL@kaiR>wJE(iC-SSJh9362ldPKGcW5Gn~Z;8|0ALQp!I!ILCf!tNBi&2 zd!MA=daxkbI}K{rCHrH(>t&`0Ij- zgVFxCe&&6We)hhC^uzIH{<)Apu!&z8|3&<8Jeq${zfwQ)Tm6Ae#y_af`8TtKyx_L~ zpnsVEqT*n*e$F4BN7Cc`6BTdj&+Yg5#U_4v{PINl;dpfXgZkzAnV0p8O~yZ{&;6fy zNcNrgKT&ZoUjNB({Xu%%|3&)T-<$fZoB72ietG=zMEc=)bo_(*p+2jVd0D^MWc&mB zSa-c`ex8nuBR|%ks5ls{pYw<3k@PtKM8#jt@2(eqIltmyG(Xo5&m%Q%QSsN(XWh(m zvHBHHYWi@%mW>t>#d*56?KgZiCMP4h!KlyqtLHp=T)(2?DZl>wV9#&o@Hu#ni#&f+$A9Vdcgyv2 z{M=_r+jlX3QE{+bf5m72v`^D(aQ~_J_4VIi|Eu`*`PX3mRs0Rizu|KK+BbyjP4fNO z<0W!F_~YgNUEuTm1<&Jrp)V?4dw&)6>-n4bt>60b8!`UuYCnD>#vhJH$Is);Lvq~o zM8#9%FZ&#SIe!yBdkFgl)(gq^f7$;EDh@`+Pmk{@jrhJppX<)3c=i2drT=BWo$K8Nq! z=;a*upNr#3UwLvbe2(H^)Mx#CPe5Gbk(ebnIJddQu{)>v&{E^E2`=2=f zdE^Cm3}c~vw4mZ(Ie*2^KIwguzCHg1(htYu{>k8j^m+Y6^ZoIt--5&QNP4Z$6;vFI z`t7&ies?#<4fekVK3h<6FzU1KJddQG-BeKVl+Wk4=|8~(=P;L8zolYOVqxo4k&m-xveo^t1Z#UWf*gv{(7r+M!x)2BB`SFal^9=HXYkT3| zSWs~=>UZ~Hzq=CY!JXHEXA3G0M*a4GL;t|>d(l7qh^#*xkNTZ&;QQ}Ecwql1@~;+D z9E|$>{_w-Gk1DlR2+=^V_0vvX8eE5dF(+M?&YH5VBG&Z?*G`cGH?;sf&YIiDh@{d)^mRT zk(__oy9#pth2v4bbHtCC9EIC?u^?*+$D_XO+jw_Eu08=iTd*JEVAR*VBW?a;{)wEA z;ds>Ny5%^vemQ=72Lmb&MtxrQ&Afgf>*xFt6$hif?R)4wS?}LSh=Wnz_N`lyAN$vq zKO;Z(FL5fw!KA|l;=}3u3lI4`i`f6|IWSOhFq)s^o4q{vFZuB= z1}Y9lefEv#k$hg__(jFzzW=+Ioo76`{`vPWqT;FhPrh!ker?^s7i~Qw4o1h%`-R=7 z$S070Ux`=x`-$#fqyF#5@ccT9RpxqITUfQd`4)a3UFhz8j{kmn%#GULm31(VS6pwd zcX+*$eXRWS%(u0c9n`2r#g%=?XRr9|y4@u~yKCNGQ1RN+L&bOh4tGD$?tY&tXm>w< zyxhHt&!U`Uhr zxoH1>;m>M=m%k1ty{90LFphswpY`*vzU(O+cVX^+95<;r81-Ab?eiVU{H-4s{(Aa{j-I&d(*5qoFrPd0Z(rX?{?3Hu$LhK5 z&P&hUx(D_iuD#ptsPukwdF^rSY{zOho<) Date: Wed, 12 Apr 2023 15:45:19 -0700 Subject: [PATCH 080/130] include statement position fixed --- compiler/characterizer/setup_hold.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/characterizer/setup_hold.py b/compiler/characterizer/setup_hold.py index 09557600..9a26b2a4 100644 --- a/compiler/characterizer/setup_hold.py +++ b/compiler/characterizer/setup_hold.py @@ -62,12 +62,12 @@ class setup_hold(): correct_value=correct_value) self.write_clock() + self.sf.write(".include {}\n".format(temp_meas)) self.write_measures(mode=mode, correct_value=correct_value) self.stim.write_control(4 * self.period) - self.sf.write(".include {}".format(temp_meas)) self.sf.close() self.mf.close() From 6af9c556a95f629ce4dc54f9e09004ae07574934 Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Wed, 19 Apr 2023 12:41:39 -0700 Subject: [PATCH 081/130] Fix char tests --- compiler/tests/30_memchar_test.py | 60 ++++++++++--------- .../tests/configs/config_mem_char_func.py | 2 +- 2 files changed, 33 insertions(+), 29 deletions(-) diff --git a/compiler/tests/30_memchar_test.py b/compiler/tests/30_memchar_test.py index d9cab4bd..5fe45f96 100755 --- a/compiler/tests/30_memchar_test.py +++ b/compiler/tests/30_memchar_test.py @@ -6,26 +6,33 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # +import sys, os, re +import shutil +import getpass import unittest from testutils import * -import sys, os, re, shutil -sys.path.append(os.getenv("OPENRAM_HOME")) -import globals -from globals import OPTS -import debug -import getpass + +import openram +from openram import debug +from openram import OPTS -class openram_front_end_test(openram_test): +class sram_char_test(openram_test): def runTest(self): - OPENRAM_HOME = os.path.abspath(os.environ.get("OPENRAM_HOME")) - config_file = "{}/tests/configs/config_mem_char_func".format(os.getenv("OPENRAM_HOME")) - globals.init_openram(config_file) - - debug.info(1, "Testing commandline characterizer script memchar.py with 2-bit, 16 word SRAM.") + global OPTS out_file = "testsram" out_path = "/tmp/testsram_{0}_{1}_{2}".format(OPTS.tech_name, getpass.getuser(), os.getpid()) + OPTS.output_name = out_file + OPTS.output_path = out_path + + OPENRAM_HOME = os.path.abspath(os.environ.get("OPENRAM_HOME")) + config_file = "{}/tests/configs/config_mem_char_func".format(OPENRAM_HOME) + + openram.init_openram(config_file, is_unit_test=False) + sp_file = "{0}/tests/sp_files/sram_2_16_1_{1}.sp".format(OPENRAM_HOME, OPTS.tech_name) + + debug.info(1, "Testing commandline characterizer script sram_char.py with 2-bit, 16 word SRAM.") # make sure we start without the files existing if os.path.exists(out_path): @@ -54,26 +61,22 @@ class openram_front_end_test(openram_test): # Always perform code coverage if OPTS.coverage == 0: debug.warning("Failed to find coverage installation. This can be installed with pip3 install coverage") - exe_name = "{0}/memchar.py ".format(OPENRAM_HOME) + exe_name = "{0}/../sram_char.py ".format(OPENRAM_HOME) else: - exe_name = "{0}{1}/memchar.py ".format(OPTS.coverage_exe, OPENRAM_HOME) + exe_name = "{0}{1}/../sram_char.py ".format(OPTS.coverage_exe, OPENRAM_HOME) config_name = "{0}/tests/configs/config_mem_char_func.py".format(OPENRAM_HOME) - cmd = "{0} -n -o {1} -p {2} {3} {4} 2>&1 > {5}/output.log".format(exe_name, - out_file, - out_path, - options, - config_name, - out_path) + cmd = "{0} -n -o {1} -p {2} {3} {4} {5} 2>&1 > {6}/output.log".format(exe_name, + out_file, + out_path, + options, + config_name, + sp_file, + out_path) debug.info(1, cmd) os.system(cmd) - # Make sure there is any .lib file - import glob - files = glob.glob('{0}/*.lib'.format(out_path)) - self.assertTrue(len(files)>0) - # grep any errors from the output - output_log = open("{0}/output.log".format(out_path), "r") + output_log = open("{0}/{1}.log".format(out_path, out_file), "r") output = output_log.read() output_log.close() self.assertEqual(len(re.findall('ERROR', output)), 0) @@ -85,11 +88,12 @@ class openram_front_end_test(openram_test): shutil.rmtree(out_path, ignore_errors=True) self.assertEqual(os.path.exists(out_path), False) - globals.end_openram() + openram.end_openram() + # run the test from the command line if __name__ == "__main__": - (OPTS, args) = globals.parse_args() + (OPTS, args) = openram.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/configs/config_mem_char_func.py b/compiler/tests/configs/config_mem_char_func.py index c6adc0aa..65a021fe 100644 --- a/compiler/tests/configs/config_mem_char_func.py +++ b/compiler/tests/configs/config_mem_char_func.py @@ -5,7 +5,7 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -from globals import OPTS +from openram import OPTS word_size = 2 num_words = 16 From 7ed99278bdecc3ef90fafe5f7ea29b7f72cb761e Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Wed, 19 Apr 2023 12:42:02 -0700 Subject: [PATCH 082/130] Sense amp fixes --- technology/freepdk45/sp_lib/sense_amp.sp | 8 ++++---- technology/scn4m_subm/gds_lib/sense_amp.gds | Bin 12232 -> 12296 bytes technology/scn4m_subm/mag_lib/sense_amp.mag | 19 +++++++++---------- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/technology/freepdk45/sp_lib/sense_amp.sp b/technology/freepdk45/sp_lib/sense_amp.sp index 7c543d95..8daf8a00 100644 --- a/technology/freepdk45/sp_lib/sense_amp.sp +++ b/technology/freepdk45/sp_lib/sense_amp.sp @@ -8,9 +8,9 @@ M_5 bl en dint vdd pmos_vtg w=720.0n l=50.0n M_6 br en net_1 vdd pmos_vtg w=720.0n l=50.0n M_7 net_2 en gnd gnd nmos_vtg w=270.0n l=50.0n -M_8 dout_bar dint vdd vdd pmos_vtg w=180.0n l=50.0n -M_9 dout_bar dint gnd gnd nmos_vtg w=90.0n l=50.0n -M_10 dout dout_bar vdd vdd pmos_vtg w=540.0n l=50.0n -M_11 dout dout_bar gnd gnd nmos_vtg w=270.0n l=50.0n +M_9 dout_bar dint vdd vdd pmos_vtg w=180.0n l=50.0n +M_10 dout_bar dint gnd gnd nmos_vtg w=90.0n l=50.0n +M_11 dout dout_bar vdd vdd pmos_vtg w=540.0n l=50.0n +M_12 dout dout_bar gnd gnd nmos_vtg w=270.0n l=50.0n .ENDS sense_amp diff --git a/technology/scn4m_subm/gds_lib/sense_amp.gds b/technology/scn4m_subm/gds_lib/sense_amp.gds index c6a71401c2617416e3dfd4f15460871d37b34342..5790e4bc18487fadbea4d9158dc6c0429ca0408e 100644 GIT binary patch delta 616 zcmZvZF;Buk6vzLzO-lJI5{&JMn~`Ucwuq4{9fPvdhflv)#WUWV8eik#({x*SSZ0q5&d0UQL+0Jb!-2m zKhifdKAHlBIdJ;Er~d^|o>`b@!a6qN5P;VK8tpyHLxA#3uaixjXFm>C%Gm-ZqdiLx z%2j!$x6MR-?B=dt)h@I0s$HgE%@(b1H*(g1n*z+>0Th!1jHqS0b|&c*Gwp#C zqII^>mboJt#z>n)bEB-pr)~X7%&xmHMm`z63AN0u&Gcl<@=%K8QGO;rvfn$D)1Fli Seo+YRo4YH(3eYU6o-G!O>&be5&u;iB#nWDnn3F4*hg@bE@lvf4B}XD5husWUBp2gM6{da zB^-SMaV(ws2<9XnBjOOg%kO?U_ndQ`y&VTIp+R7$rQrfP3@pJx`0E_q1j+h8@oV-d zqK!kKH38i6W6F1ca%O8%#JVe@%}+r1Koni@H@Kx-40gbWpP>(~T7M3p?8e=uz8&z8)mA1yD)@W> rect 0 28 40 153 << pwell >> @@ -71,7 +71,7 @@ rect 16 34 20 58 rect 24 34 28 42 << psubstratepcontact >> rect 32 188 36 192 -rect 28 4 32 8 +rect 32 13 36 17 << nsubstratencontact >> rect 27 121 31 125 rect 27 55 31 59 @@ -143,19 +143,18 @@ rect 8 22 11 34 rect 24 30 28 34 rect 18 27 28 30 rect 24 22 28 27 -rect 3 10 8 13 -rect 3 9 10 10 -rect 3 8 7 9 -rect 16 7 20 10 -rect 16 4 28 7 +rect 20 13 32 15 +rect 20 12 36 13 +rect 8 8 11 10 +rect 7 5 11 8 << m2contact >> rect 32 184 36 188 rect 27 117 31 121 rect 13 95 17 99 rect 22 95 26 99 rect 27 51 31 55 +rect 32 17 36 21 rect 3 4 7 8 -rect 28 8 32 12 << metal2 >> rect 10 99 14 214 rect 20 99 24 214 @@ -167,18 +166,18 @@ rect 3 0 7 4 rect 10 0 14 95 rect 20 0 24 95 rect 27 47 31 51 -rect 28 12 32 16 +rect 32 21 36 25 << bb >> rect 0 0 34 214 << labels >> rlabel metal2 5 2 5 2 1 dout -rlabel metal2 30 14 30 14 1 gnd rlabel metal2 29 49 29 49 1 vdd rlabel metal2 22 212 22 212 5 br rlabel metal2 12 212 12 212 5 bl rlabel metal2 29 115 29 115 1 vdd rlabel metal2 34 182 34 182 1 gnd flabel metal1 0 200 0 200 4 FreeSans 26 0 0 0 en +rlabel metal2 34 23 34 23 1 gnd << properties >> string path 270.000 468.000 270.000 486.000 288.000 486.000 288.000 468.000 270.000 468.000 << end >> From bd7b2c22c7b88b074001db712975caa8aadd3bf8 Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Wed, 19 Apr 2023 17:23:00 -0700 Subject: [PATCH 083/130] Added spice files for the command line char --- .../tests/sp_files/sram_2_16_1_freepdk45.sp | 1646 ++++++++++++++++ .../tests/sp_files/sram_2_16_1_scn4m_subm.sp | 1656 +++++++++++++++++ 2 files changed, 3302 insertions(+) create mode 100644 compiler/tests/sp_files/sram_2_16_1_freepdk45.sp create mode 100644 compiler/tests/sp_files/sram_2_16_1_scn4m_subm.sp diff --git a/compiler/tests/sp_files/sram_2_16_1_freepdk45.sp b/compiler/tests/sp_files/sram_2_16_1_freepdk45.sp new file mode 100644 index 00000000..28a07dd3 --- /dev/null +++ b/compiler/tests/sp_files/sram_2_16_1_freepdk45.sp @@ -0,0 +1,1646 @@ +************************************************** +* OpenRAM generated memory. +* Words: 16 +* Data bits: 1 +* Banks: 1 +* Column mux: 1:1 +* Trimmed: False +* LVS: False +************************************************** + +* spice ptx M{0} {1} pmos_vtg m=1 w=0.27u l=0.05u pd=0.64u ps=0.64u as=0.03p ad=0.03p + +* spice ptx M{0} {1} nmos_vtg m=1 w=0.09u l=0.05u pd=0.28u ps=0.28u as=0.01p ad=0.01p + +.SUBCKT sram_pinv_3 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +Mpinv_pmos Z A vdd vdd pmos_vtg m=1 w=0.27u l=0.05u pd=0.64u ps=0.64u as=0.03p ad=0.03p +Mpinv_nmos Z A gnd gnd nmos_vtg m=1 w=0.09u l=0.05u pd=0.28u ps=0.28u as=0.01p ad=0.01p +.ENDS sram_pinv_3 + +* spice ptx M{0} {1} pmos_vtg m=2 w=0.675u l=0.05u pd=1.45u ps=1.45u as=0.08p ad=0.08p + +* spice ptx M{0} {1} nmos_vtg m=2 w=0.225u l=0.05u pd=0.55u ps=0.55u as=0.03p ad=0.03p + +.SUBCKT sram_pinv_8 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +Mpinv_pmos Z A vdd vdd pmos_vtg m=2 w=0.675u l=0.05u pd=1.45u ps=1.45u as=0.08p ad=0.08p +Mpinv_nmos Z A gnd gnd nmos_vtg m=2 w=0.225u l=0.05u pd=0.55u ps=0.55u as=0.03p ad=0.03p +.ENDS sram_pinv_8 + +.SUBCKT sram_pinv_5 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +Mpinv_pmos Z A vdd vdd pmos_vtg m=1 w=0.27u l=0.05u pd=0.64u ps=0.64u as=0.03p ad=0.03p +Mpinv_nmos Z A gnd gnd nmos_vtg m=1 w=0.09u l=0.05u pd=0.28u ps=0.28u as=0.01p ad=0.01p +.ENDS sram_pinv_5 + +.SUBCKT sram_pdriver_1 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* sizes: [1, 5] +Xbuf_inv1 ++ A Zb1_int vdd gnd ++ sram_pinv_5 +Xbuf_inv2 ++ Zb1_int Z vdd gnd ++ sram_pinv_8 +.ENDS sram_pdriver_1 + +* spice ptx M{0} {1} nmos_vtg m=1 w=0.18u l=0.05u pd=0.46u ps=0.46u as=0.02p ad=0.02p + +* spice ptx M{0} {1} nmos_vtg m=1 w=0.18u l=0.05u pd=0.46u ps=0.46u as=0.02p ad=0.02p + +* spice ptx M{0} {1} pmos_vtg m=1 w=0.27u l=0.05u pd=0.64u ps=0.64u as=0.03p ad=0.03p + +.SUBCKT sram_pnand2_0 ++ A B Z vdd gnd +* INPUT : A +* INPUT : B +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +Mpnand2_pmos1 vdd A Z vdd pmos_vtg m=1 w=0.27u l=0.05u pd=0.64u ps=0.64u as=0.03p ad=0.03p +Mpnand2_pmos2 Z B vdd vdd pmos_vtg m=1 w=0.27u l=0.05u pd=0.64u ps=0.64u as=0.03p ad=0.03p +Mpnand2_nmos1 Z B net1 gnd nmos_vtg m=1 w=0.18u l=0.05u pd=0.46u ps=0.46u as=0.02p ad=0.02p +Mpnand2_nmos2 net1 A gnd gnd nmos_vtg m=1 w=0.18u l=0.05u pd=0.46u ps=0.46u as=0.02p ad=0.02p +.ENDS sram_pnand2_0 + +* spice ptx M{0} {1} nmos_vtg m=4 w=0.27u l=0.05u pd=0.64u ps=0.64u as=0.03p ad=0.03p + +* spice ptx M{0} {1} pmos_vtg m=4 w=0.81u l=0.05u pd=1.72u ps=1.72u as=0.10p ad=0.10p + +.SUBCKT sram_pinv_2 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +Mpinv_pmos Z A vdd vdd pmos_vtg m=4 w=0.81u l=0.05u pd=1.72u ps=1.72u as=0.10p ad=0.10p +Mpinv_nmos Z A gnd gnd nmos_vtg m=4 w=0.27u l=0.05u pd=0.64u ps=0.64u as=0.03p ad=0.03p +.ENDS sram_pinv_2 + +.SUBCKT sram_pdriver ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* sizes: [12] +Xbuf_inv1 ++ A Z vdd gnd ++ sram_pinv_2 +.ENDS sram_pdriver + +.SUBCKT sram_pand2 ++ A B Z vdd gnd +* INPUT : A +* INPUT : B +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +Xpand2_nand ++ A B zb_int vdd gnd ++ sram_pnand2_0 +Xpand2_inv ++ zb_int Z vdd gnd ++ sram_pdriver +.ENDS sram_pand2 + +* spice ptx M{0} {1} pmos_vtg m=1 w=0.54u l=0.05u pd=1.18u ps=1.18u as=0.07p ad=0.07p + +* spice ptx M{0} {1} nmos_vtg m=1 w=0.18u l=0.05u pd=0.46u ps=0.46u as=0.02p ad=0.02p + +.SUBCKT sram_pinv_0 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +Mpinv_pmos Z A vdd vdd pmos_vtg m=1 w=0.54u l=0.05u pd=1.18u ps=1.18u as=0.07p ad=0.07p +Mpinv_nmos Z A gnd gnd nmos_vtg m=1 w=0.18u l=0.05u pd=0.46u ps=0.46u as=0.02p ad=0.02p +.ENDS sram_pinv_0 + +* spice ptx M{0} {1} pmos_vtg m=2 w=0.54u l=0.05u pd=1.18u ps=1.18u as=0.07p ad=0.07p + +* spice ptx M{0} {1} nmos_vtg m=2 w=0.18u l=0.05u pd=0.46u ps=0.46u as=0.02p ad=0.02p + +.SUBCKT sram_pinv_1 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +Mpinv_pmos Z A vdd vdd pmos_vtg m=2 w=0.54u l=0.05u pd=1.18u ps=1.18u as=0.07p ad=0.07p +Mpinv_nmos Z A gnd gnd nmos_vtg m=2 w=0.18u l=0.05u pd=0.46u ps=0.46u as=0.02p ad=0.02p +.ENDS sram_pinv_1 +* File: DFFPOSX1.pex.netlist +* Created: Wed Jan 2 18:36:24 2008 +* Program "Calibre xRC" +* Version "v2007.2_34.24" +* +.subckt dff D Q clk vdd gnd +* +MM21 Q a_66_6# gnd gnd NMOS_VTG L=5e-08 W=5e-07 +MM19 a_76_6# a_2_6# a_66_6# gnd NMOS_VTG L=5e-08 W=2.5e-07 +MM20 gnd Q a_76_6# gnd NMOS_VTG L=5e-08 W=2.5e-07 +MM18 a_66_6# clk a_61_6# gnd NMOS_VTG L=5e-08 W=2.5e-07 +MM17 a_61_6# a_34_4# gnd gnd NMOS_VTG L=5e-08 W=2.5e-07 +MM10 gnd clk a_2_6# gnd NMOS_VTG L=5e-08 W=5e-07 +MM16 a_34_4# a_22_6# gnd gnd NMOS_VTG L=5e-08 W=2.5e-07 +MM15 gnd a_34_4# a_31_6# gnd NMOS_VTG L=5e-08 W=2.5e-07 +MM14 a_31_6# clk a_22_6# gnd NMOS_VTG L=5e-08 W=2.5e-07 +MM13 a_22_6# a_2_6# a_17_6# gnd NMOS_VTG L=5e-08 W=2.5e-07 +MM12 a_17_6# D gnd gnd NMOS_VTG L=5e-08 W=2.5e-07 +MM11 Q a_66_6# vdd vdd PMOS_VTG L=5e-08 W=1e-06 +MM9 vdd Q a_76_84# vdd PMOS_VTG L=5e-08 W=2.5e-07 +MM8 a_76_84# clk a_66_6# vdd PMOS_VTG L=5e-08 W=2.5e-07 +MM7 a_66_6# a_2_6# a_61_74# vdd PMOS_VTG L=5e-08 W=5e-07 +MM6 a_61_74# a_34_4# vdd vdd PMOS_VTG L=5e-08 W=5e-07 +MM0 vdd clk a_2_6# vdd PMOS_VTG L=5e-08 W=1e-06 +MM5 a_34_4# a_22_6# vdd vdd PMOS_VTG L=5e-08 W=5e-07 +MM4 vdd a_34_4# a_31_74# vdd PMOS_VTG L=5e-08 W=5e-07 +MM3 a_31_74# a_2_6# a_22_6# vdd PMOS_VTG L=5e-08 W=5e-07 +MM2 a_22_6# clk a_17_74# vdd PMOS_VTG L=5e-08 W=5e-07 +MM1 a_17_74# D vdd vdd PMOS_VTG L=5e-08 W=5e-07 +* c_9 a_66_6# 0 0.271997f +* c_20 clk 0 0.350944f +* c_27 Q 0 0.202617f +* c_32 a_76_84# 0 0.0210573f +* c_38 a_76_6# 0 0.0204911f +* c_45 a_34_4# 0 0.172306f +* c_55 a_2_6# 0 0.283119f +* c_59 a_22_6# 0 0.157312f +* c_64 D 0 0.0816386f +* c_73 gnd 0 0.254131f +* c_81 vdd 0 0.23624f +* +*.include "dff.pex.netlist.dff.pxi" +* +.ends +* +* + +.SUBCKT sram_dff_buf_0 ++ D Q Qb clk vdd gnd +* INPUT : D +* OUTPUT: Q +* OUTPUT: Qb +* INPUT : clk +* POWER : vdd +* GROUND: gnd +* inv1: 2 inv2: 4 +Xdff_buf_dff ++ D qint clk vdd gnd ++ dff +Xdff_buf_inv1 ++ qint Qb vdd gnd ++ sram_pinv_0 +Xdff_buf_inv2 ++ Qb Q vdd gnd ++ sram_pinv_1 +.ENDS sram_dff_buf_0 + +.SUBCKT sram_dff_buf_array ++ din_0 din_1 dout_0 dout_bar_0 dout_1 dout_bar_1 clk vdd gnd +* INPUT : din_0 +* INPUT : din_1 +* OUTPUT: dout_0 +* OUTPUT: dout_bar_0 +* OUTPUT: dout_1 +* OUTPUT: dout_bar_1 +* INPUT : clk +* POWER : vdd +* GROUND: gnd +* inv1: 2 inv2: 4 +Xdff_r0_c0 ++ din_0 dout_0 dout_bar_0 clk vdd gnd ++ sram_dff_buf_0 +Xdff_r1_c0 ++ din_1 dout_1 dout_bar_1 clk vdd gnd ++ sram_dff_buf_0 +.ENDS sram_dff_buf_array + +.SUBCKT sram_pnand2_1 ++ A B Z vdd gnd +* INPUT : A +* INPUT : B +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +Mpnand2_pmos1 vdd A Z vdd pmos_vtg m=1 w=0.27u l=0.05u pd=0.64u ps=0.64u as=0.03p ad=0.03p +Mpnand2_pmos2 Z B vdd vdd pmos_vtg m=1 w=0.27u l=0.05u pd=0.64u ps=0.64u as=0.03p ad=0.03p +Mpnand2_nmos1 Z B net1 gnd nmos_vtg m=1 w=0.18u l=0.05u pd=0.46u ps=0.46u as=0.02p ad=0.02p +Mpnand2_nmos2 net1 A gnd gnd nmos_vtg m=1 w=0.18u l=0.05u pd=0.46u ps=0.46u as=0.02p ad=0.02p +.ENDS sram_pnand2_1 + +.SUBCKT sram_pdriver_3 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* sizes: [1] +Xbuf_inv1 ++ A Z vdd gnd ++ sram_pinv_5 +.ENDS sram_pdriver_3 + +* spice ptx M{0} {1} nmos_vtg m=1 w=0.18u l=0.05u pd=0.46u ps=0.46u as=0.02p ad=0.02p + +.SUBCKT sram_pnand3_0 ++ A B C Z vdd gnd +* INPUT : A +* INPUT : B +* INPUT : C +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +Mpnand3_pmos1 vdd A Z vdd pmos_vtg m=1 w=0.27u l=0.05u pd=0.64u ps=0.64u as=0.03p ad=0.03p +Mpnand3_pmos2 Z B vdd vdd pmos_vtg m=1 w=0.27u l=0.05u pd=0.64u ps=0.64u as=0.03p ad=0.03p +Mpnand3_pmos3 Z C vdd vdd pmos_vtg m=1 w=0.27u l=0.05u pd=0.64u ps=0.64u as=0.03p ad=0.03p +Mpnand3_nmos1 Z C net1 gnd nmos_vtg m=1 w=0.18u l=0.05u pd=0.46u ps=0.46u as=0.02p ad=0.02p +Mpnand3_nmos2 net1 B net2 gnd nmos_vtg m=1 w=0.18u l=0.05u pd=0.46u ps=0.46u as=0.02p ad=0.02p +Mpnand3_nmos3 net2 A gnd gnd nmos_vtg m=1 w=0.18u l=0.05u pd=0.46u ps=0.46u as=0.02p ad=0.02p +.ENDS sram_pnand3_0 + +.SUBCKT sram_pand3_0 ++ A B C Z vdd gnd +* INPUT : A +* INPUT : B +* INPUT : C +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +Xpand3_nand ++ A B C zb_int vdd gnd ++ sram_pnand3_0 +Xpand3_inv ++ zb_int Z vdd gnd ++ sram_pdriver_3 +.ENDS sram_pand3_0 + +.SUBCKT sram_pinv_10 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +Mpinv_pmos Z A vdd vdd pmos_vtg m=1 w=0.27u l=0.05u pd=0.64u ps=0.64u as=0.03p ad=0.03p +Mpinv_nmos Z A gnd gnd nmos_vtg m=1 w=0.09u l=0.05u pd=0.28u ps=0.28u as=0.01p ad=0.01p +.ENDS sram_pinv_10 + +.SUBCKT sram_delay_chain ++ in out vdd gnd +* INPUT : in +* OUTPUT: out +* POWER : vdd +* GROUND: gnd +* fanouts: [4, 4, 4, 4, 4, 4, 4, 4, 4] +Xdinv0 ++ in dout_1 vdd gnd ++ sram_pinv_10 +Xdload_0_0 ++ dout_1 n_0_0 vdd gnd ++ sram_pinv_10 +Xdload_0_1 ++ dout_1 n_0_1 vdd gnd ++ sram_pinv_10 +Xdload_0_2 ++ dout_1 n_0_2 vdd gnd ++ sram_pinv_10 +Xdload_0_3 ++ dout_1 n_0_3 vdd gnd ++ sram_pinv_10 +Xdinv1 ++ dout_1 dout_2 vdd gnd ++ sram_pinv_10 +Xdload_1_0 ++ dout_2 n_1_0 vdd gnd ++ sram_pinv_10 +Xdload_1_1 ++ dout_2 n_1_1 vdd gnd ++ sram_pinv_10 +Xdload_1_2 ++ dout_2 n_1_2 vdd gnd ++ sram_pinv_10 +Xdload_1_3 ++ dout_2 n_1_3 vdd gnd ++ sram_pinv_10 +Xdinv2 ++ dout_2 dout_3 vdd gnd ++ sram_pinv_10 +Xdload_2_0 ++ dout_3 n_2_0 vdd gnd ++ sram_pinv_10 +Xdload_2_1 ++ dout_3 n_2_1 vdd gnd ++ sram_pinv_10 +Xdload_2_2 ++ dout_3 n_2_2 vdd gnd ++ sram_pinv_10 +Xdload_2_3 ++ dout_3 n_2_3 vdd gnd ++ sram_pinv_10 +Xdinv3 ++ dout_3 dout_4 vdd gnd ++ sram_pinv_10 +Xdload_3_0 ++ dout_4 n_3_0 vdd gnd ++ sram_pinv_10 +Xdload_3_1 ++ dout_4 n_3_1 vdd gnd ++ sram_pinv_10 +Xdload_3_2 ++ dout_4 n_3_2 vdd gnd ++ sram_pinv_10 +Xdload_3_3 ++ dout_4 n_3_3 vdd gnd ++ sram_pinv_10 +Xdinv4 ++ dout_4 dout_5 vdd gnd ++ sram_pinv_10 +Xdload_4_0 ++ dout_5 n_4_0 vdd gnd ++ sram_pinv_10 +Xdload_4_1 ++ dout_5 n_4_1 vdd gnd ++ sram_pinv_10 +Xdload_4_2 ++ dout_5 n_4_2 vdd gnd ++ sram_pinv_10 +Xdload_4_3 ++ dout_5 n_4_3 vdd gnd ++ sram_pinv_10 +Xdinv5 ++ dout_5 dout_6 vdd gnd ++ sram_pinv_10 +Xdload_5_0 ++ dout_6 n_5_0 vdd gnd ++ sram_pinv_10 +Xdload_5_1 ++ dout_6 n_5_1 vdd gnd ++ sram_pinv_10 +Xdload_5_2 ++ dout_6 n_5_2 vdd gnd ++ sram_pinv_10 +Xdload_5_3 ++ dout_6 n_5_3 vdd gnd ++ sram_pinv_10 +Xdinv6 ++ dout_6 dout_7 vdd gnd ++ sram_pinv_10 +Xdload_6_0 ++ dout_7 n_6_0 vdd gnd ++ sram_pinv_10 +Xdload_6_1 ++ dout_7 n_6_1 vdd gnd ++ sram_pinv_10 +Xdload_6_2 ++ dout_7 n_6_2 vdd gnd ++ sram_pinv_10 +Xdload_6_3 ++ dout_7 n_6_3 vdd gnd ++ sram_pinv_10 +Xdinv7 ++ dout_7 dout_8 vdd gnd ++ sram_pinv_10 +Xdload_7_0 ++ dout_8 n_7_0 vdd gnd ++ sram_pinv_10 +Xdload_7_1 ++ dout_8 n_7_1 vdd gnd ++ sram_pinv_10 +Xdload_7_2 ++ dout_8 n_7_2 vdd gnd ++ sram_pinv_10 +Xdload_7_3 ++ dout_8 n_7_3 vdd gnd ++ sram_pinv_10 +Xdinv8 ++ dout_8 out vdd gnd ++ sram_pinv_10 +Xdload_8_0 ++ out n_8_0 vdd gnd ++ sram_pinv_10 +Xdload_8_1 ++ out n_8_1 vdd gnd ++ sram_pinv_10 +Xdload_8_2 ++ out n_8_2 vdd gnd ++ sram_pinv_10 +Xdload_8_3 ++ out n_8_3 vdd gnd ++ sram_pinv_10 +.ENDS sram_delay_chain + +* spice ptx M{0} {1} nmos_vtg m=4 w=0.2925u l=0.05u pd=0.68u ps=0.68u as=0.04p ad=0.04p + +* spice ptx M{0} {1} pmos_vtg m=4 w=0.8775000000000001u l=0.05u pd=1.86u ps=1.86u as=0.11p ad=0.11p + +.SUBCKT sram_pinv_7 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +Mpinv_pmos Z A vdd vdd pmos_vtg m=4 w=0.8775000000000001u l=0.05u pd=1.86u ps=1.86u as=0.11p ad=0.11p +Mpinv_nmos Z A gnd gnd nmos_vtg m=4 w=0.2925u l=0.05u pd=0.68u ps=0.68u as=0.04p ad=0.04p +.ENDS sram_pinv_7 + +.SUBCKT sram_pinv_6 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +Mpinv_pmos Z A vdd vdd pmos_vtg m=2 w=0.54u l=0.05u pd=1.18u ps=1.18u as=0.07p ad=0.07p +Mpinv_nmos Z A gnd gnd nmos_vtg m=2 w=0.18u l=0.05u pd=0.46u ps=0.46u as=0.02p ad=0.02p +.ENDS sram_pinv_6 + +.SUBCKT sram_pdriver_0 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* sizes: [1, 1, 4, 13] +Xbuf_inv1 ++ A Zb1_int vdd gnd ++ sram_pinv_5 +Xbuf_inv2 ++ Zb1_int Zb2_int vdd gnd ++ sram_pinv_5 +Xbuf_inv3 ++ Zb2_int Zb3_int vdd gnd ++ sram_pinv_6 +Xbuf_inv4 ++ Zb3_int Z vdd gnd ++ sram_pinv_7 +.ENDS sram_pdriver_0 + +* spice ptx M{0} {1} pmos_vtg m=3 w=0.81u l=0.05u pd=1.72u ps=1.72u as=0.10p ad=0.10p + +* spice ptx M{0} {1} nmos_vtg m=3 w=0.27u l=0.05u pd=0.64u ps=0.64u as=0.03p ad=0.03p + +.SUBCKT sram_pinv_9 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +Mpinv_pmos Z A vdd vdd pmos_vtg m=3 w=0.81u l=0.05u pd=1.72u ps=1.72u as=0.10p ad=0.10p +Mpinv_nmos Z A gnd gnd nmos_vtg m=3 w=0.27u l=0.05u pd=0.64u ps=0.64u as=0.03p ad=0.03p +.ENDS sram_pinv_9 + +.SUBCKT sram_pdriver_2 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* sizes: [9] +Xbuf_inv1 ++ A Z vdd gnd ++ sram_pinv_9 +.ENDS sram_pdriver_2 + +.SUBCKT sram_pand3 ++ A B C Z vdd gnd +* INPUT : A +* INPUT : B +* INPUT : C +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +Xpand3_nand ++ A B C zb_int vdd gnd ++ sram_pnand3_0 +Xpand3_inv ++ zb_int Z vdd gnd ++ sram_pdriver_2 +.ENDS sram_pand3 + +.SUBCKT sram_pdriver_4 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* sizes: [1, 1] +Xbuf_inv1 ++ A Zb1_int vdd gnd ++ sram_pinv_5 +Xbuf_inv2 ++ Zb1_int Z vdd gnd ++ sram_pinv_5 +.ENDS sram_pdriver_4 + +.SUBCKT sram_control_logic_rw ++ csb web clk rbl_bl s_en w_en p_en_bar wl_en clk_buf vdd gnd +* INPUT : csb +* INPUT : web +* INPUT : clk +* INPUT : rbl_bl +* OUTPUT: s_en +* OUTPUT: w_en +* OUTPUT: p_en_bar +* OUTPUT: wl_en +* OUTPUT: clk_buf +* POWER : vdd +* GROUND: gnd +* word_size 1 +Xctrl_dffs ++ csb web cs_bar cs we_bar we clk_buf vdd gnd ++ sram_dff_buf_array +Xclkbuf ++ clk clk_buf vdd gnd ++ sram_pdriver_0 +Xinv_clk_bar ++ clk_buf clk_bar vdd gnd ++ sram_pinv_3 +Xand2_gated_clk_bar ++ clk_bar cs gated_clk_bar vdd gnd ++ sram_pand2 +Xand2_gated_clk_buf ++ clk_buf cs gated_clk_buf vdd gnd ++ sram_pand2 +Xbuf_wl_en ++ gated_clk_bar wl_en vdd gnd ++ sram_pdriver_1 +Xrbl_bl_delay_inv ++ rbl_bl_delay rbl_bl_delay_bar vdd gnd ++ sram_pinv_3 +Xw_en_and ++ we rbl_bl_delay_bar gated_clk_bar w_en vdd gnd ++ sram_pand3 +Xbuf_s_en_and ++ rbl_bl_delay gated_clk_bar we_bar s_en vdd gnd ++ sram_pand3_0 +Xdelay_chain ++ rbl_bl rbl_bl_delay vdd gnd ++ sram_delay_chain +Xnand_p_en_bar ++ gated_clk_buf rbl_bl_delay p_en_bar_unbuf vdd gnd ++ sram_pnand2_1 +Xbuf_p_en_bar ++ p_en_bar_unbuf p_en_bar vdd gnd ++ sram_pdriver_4 +.ENDS sram_control_logic_rw + +.SUBCKT sense_amp bl br dout en vdd gnd +M_1 dint net_1 vdd vdd pmos_vtg w=540.0n l=50.0n +M_3 net_1 dint vdd vdd pmos_vtg w=540.0n l=50.0n +M_2 dint net_1 net_2 gnd nmos_vtg w=270.0n l=50.0n +M_8 net_1 dint net_2 gnd nmos_vtg w=270.0n l=50.0n +M_5 bl en dint vdd pmos_vtg w=720.0n l=50.0n +M_6 br en net_1 vdd pmos_vtg w=720.0n l=50.0n +M_7 net_2 en gnd gnd nmos_vtg w=270.0n l=50.0n + +M_8 dout_bar dint vdd vdd pmos_vtg w=180.0n l=50.0n +M_9 dout_bar dint gnd gnd nmos_vtg w=90.0n l=50.0n +M_10 dout dout_bar vdd vdd pmos_vtg w=540.0n l=50.0n +M_11 dout dout_bar gnd gnd nmos_vtg w=270.0n l=50.0n +.ENDS sense_amp + + +.SUBCKT sram_sense_amp_array ++ data_0 bl_0 br_0 en vdd gnd +* OUTPUT: data_0 +* INPUT : bl_0 +* INPUT : br_0 +* INPUT : en +* POWER : vdd +* GROUND: gnd +* words_per_row: 1 +Xsa_d0 ++ bl_0 br_0 data_0 en vdd gnd ++ sense_amp +.ENDS sram_sense_amp_array + +.SUBCKT sram_precharge_0 ++ bl br en_bar vdd +* OUTPUT: bl +* OUTPUT: br +* INPUT : en_bar +* POWER : vdd +Mlower_pmos bl en_bar br vdd pmos_vtg m=1 w=0.27u l=0.05u pd=0.64u ps=0.64u as=0.03p ad=0.03p +Mupper_pmos1 bl en_bar vdd vdd pmos_vtg m=1 w=0.27u l=0.05u pd=0.64u ps=0.64u as=0.03p ad=0.03p +Mupper_pmos2 br en_bar vdd vdd pmos_vtg m=1 w=0.27u l=0.05u pd=0.64u ps=0.64u as=0.03p ad=0.03p +.ENDS sram_precharge_0 + +.SUBCKT sram_precharge_array ++ bl_0 br_0 bl_1 br_1 en_bar vdd +* OUTPUT: bl_0 +* OUTPUT: br_0 +* OUTPUT: bl_1 +* OUTPUT: br_1 +* INPUT : en_bar +* POWER : vdd +* cols: 2 size: 1 bl: bl br: br +Xpre_column_0 ++ bl_0 br_0 en_bar vdd ++ sram_precharge_0 +Xpre_column_1 ++ bl_1 br_1 en_bar vdd ++ sram_precharge_0 +.ENDS sram_precharge_array + +.SUBCKT write_driver din bl br en vdd gnd +*inverters for enable and data input +minP bl_bar din vdd vdd pmos_vtg w=360.000000n l=50.000000n +minN bl_bar din gnd gnd nmos_vtg w=180.000000n l=50.000000n +moutP en_bar en vdd vdd pmos_vtg w=360.000000n l=50.000000n +moutN en_bar en gnd gnd nmos_vtg w=180.000000n l=50.000000n + +*tristate for BL +mout0P int1 bl_bar vdd vdd pmos_vtg w=360.000000n l=50.000000n +mout0P2 bl en_bar int1 vdd pmos_vtg w=360.000000n l=50.000000n +mout0N bl en int2 gnd nmos_vtg w=180.000000n l=50.000000n +mout0N2 int2 bl_bar gnd gnd nmos_vtg w=180.000000n l=50.000000n + +*tristate for BR +mout1P int3 din vdd vdd pmos_vtg w=360.000000n l=50.000000n +mout1P2 br en_bar int3 vdd pmos_vtg w=360.000000n l=50.000000n +mout1N br en int4 gnd nmos_vtg w=180.000000n l=50.000000n +mout1N2 int4 din gnd gnd nmos_vtg w=180.000000n l=50.000000n +.ENDS write_driver + + +.SUBCKT sram_write_driver_array ++ data_0 bl_0 br_0 en vdd gnd +* INPUT : data_0 +* OUTPUT: bl_0 +* OUTPUT: br_0 +* INPUT : en +* POWER : vdd +* GROUND: gnd +* word_size 1 +Xwrite_driver0 ++ data_0 bl_0 br_0 en vdd gnd ++ write_driver +.ENDS sram_write_driver_array + +.SUBCKT sram_port_data ++ rbl_bl rbl_br bl_0 br_0 dout_0 din_0 s_en p_en_bar w_en vdd gnd +* INOUT : rbl_bl +* INOUT : rbl_br +* INOUT : bl_0 +* INOUT : br_0 +* OUTPUT: dout_0 +* INPUT : din_0 +* INPUT : s_en +* INPUT : p_en_bar +* INPUT : w_en +* POWER : vdd +* GROUND: gnd +Xprecharge_array0 ++ rbl_bl rbl_br bl_0 br_0 p_en_bar vdd ++ sram_precharge_array +Xsense_amp_array0 ++ dout_0 bl_0 br_0 s_en vdd gnd ++ sram_sense_amp_array +Xwrite_driver_array0 ++ din_0 bl_0 br_0 w_en vdd gnd ++ sram_write_driver_array +.ENDS sram_port_data + +.SUBCKT sram_pnand2 ++ A B Z vdd gnd +* INPUT : A +* INPUT : B +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +Mpnand2_pmos1 vdd A Z vdd pmos_vtg m=1 w=0.27u l=0.05u pd=0.64u ps=0.64u as=0.03p ad=0.03p +Mpnand2_pmos2 Z B vdd vdd pmos_vtg m=1 w=0.27u l=0.05u pd=0.64u ps=0.64u as=0.03p ad=0.03p +Mpnand2_nmos1 Z B net1 gnd nmos_vtg m=1 w=0.18u l=0.05u pd=0.46u ps=0.46u as=0.02p ad=0.02p +Mpnand2_nmos2 net1 A gnd gnd nmos_vtg m=1 w=0.18u l=0.05u pd=0.46u ps=0.46u as=0.02p ad=0.02p +.ENDS sram_pnand2 + +.SUBCKT sram_pinv ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +Mpinv_pmos Z A vdd vdd pmos_vtg m=1 w=0.27u l=0.05u pd=0.64u ps=0.64u as=0.03p ad=0.03p +Mpinv_nmos Z A gnd gnd nmos_vtg m=1 w=0.09u l=0.05u pd=0.28u ps=0.28u as=0.01p ad=0.01p +.ENDS sram_pinv + +.SUBCKT sram_and2_dec_0 ++ A B Z vdd gnd +* INPUT : A +* INPUT : B +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* size: 1 +Xpand2_dec_nand ++ A B zb_int vdd gnd ++ sram_pnand2 +Xpand2_dec_inv ++ zb_int Z vdd gnd ++ sram_pinv +.ENDS sram_and2_dec_0 + +.SUBCKT sram_and2_dec ++ A B Z vdd gnd +* INPUT : A +* INPUT : B +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* size: 1 +Xpand2_dec_nand ++ A B zb_int vdd gnd ++ sram_pnand2 +Xpand2_dec_inv ++ zb_int Z vdd gnd ++ sram_pinv +.ENDS sram_and2_dec + +.SUBCKT sram_hierarchical_predecode2x4 ++ in_0 in_1 out_0 out_1 out_2 out_3 vdd gnd +* INPUT : in_0 +* INPUT : in_1 +* OUTPUT: out_0 +* OUTPUT: out_1 +* OUTPUT: out_2 +* OUTPUT: out_3 +* POWER : vdd +* GROUND: gnd +Xpre_inv_0 ++ in_0 inbar_0 vdd gnd ++ sram_pinv +Xpre_inv_1 ++ in_1 inbar_1 vdd gnd ++ sram_pinv +XXpre2x4_and_0 ++ inbar_0 inbar_1 out_0 vdd gnd ++ sram_and2_dec +XXpre2x4_and_1 ++ in_0 inbar_1 out_1 vdd gnd ++ sram_and2_dec +XXpre2x4_and_2 ++ inbar_0 in_1 out_2 vdd gnd ++ sram_and2_dec +XXpre2x4_and_3 ++ in_0 in_1 out_3 vdd gnd ++ sram_and2_dec +.ENDS sram_hierarchical_predecode2x4 + +.SUBCKT sram_hierarchical_decoder ++ addr_0 addr_1 addr_2 addr_3 decode_0 decode_1 decode_2 decode_3 ++ decode_4 decode_5 decode_6 decode_7 decode_8 decode_9 decode_10 ++ decode_11 decode_12 decode_13 decode_14 decode_15 vdd gnd +* INPUT : addr_0 +* INPUT : addr_1 +* INPUT : addr_2 +* INPUT : addr_3 +* OUTPUT: decode_0 +* OUTPUT: decode_1 +* OUTPUT: decode_2 +* OUTPUT: decode_3 +* OUTPUT: decode_4 +* OUTPUT: decode_5 +* OUTPUT: decode_6 +* OUTPUT: decode_7 +* OUTPUT: decode_8 +* OUTPUT: decode_9 +* OUTPUT: decode_10 +* OUTPUT: decode_11 +* OUTPUT: decode_12 +* OUTPUT: decode_13 +* OUTPUT: decode_14 +* OUTPUT: decode_15 +* POWER : vdd +* GROUND: gnd +Xpre_0 ++ addr_0 addr_1 out_0 out_1 out_2 out_3 vdd gnd ++ sram_hierarchical_predecode2x4 +Xpre_1 ++ addr_2 addr_3 out_4 out_5 out_6 out_7 vdd gnd ++ sram_hierarchical_predecode2x4 +XDEC_AND_0 ++ out_0 out_4 decode_0 vdd gnd ++ sram_and2_dec +XDEC_AND_4 ++ out_0 out_5 decode_4 vdd gnd ++ sram_and2_dec +XDEC_AND_8 ++ out_0 out_6 decode_8 vdd gnd ++ sram_and2_dec +XDEC_AND_12 ++ out_0 out_7 decode_12 vdd gnd ++ sram_and2_dec +XDEC_AND_1 ++ out_1 out_4 decode_1 vdd gnd ++ sram_and2_dec +XDEC_AND_5 ++ out_1 out_5 decode_5 vdd gnd ++ sram_and2_dec +XDEC_AND_9 ++ out_1 out_6 decode_9 vdd gnd ++ sram_and2_dec +XDEC_AND_13 ++ out_1 out_7 decode_13 vdd gnd ++ sram_and2_dec +XDEC_AND_2 ++ out_2 out_4 decode_2 vdd gnd ++ sram_and2_dec +XDEC_AND_6 ++ out_2 out_5 decode_6 vdd gnd ++ sram_and2_dec +XDEC_AND_10 ++ out_2 out_6 decode_10 vdd gnd ++ sram_and2_dec +XDEC_AND_14 ++ out_2 out_7 decode_14 vdd gnd ++ sram_and2_dec +XDEC_AND_3 ++ out_3 out_4 decode_3 vdd gnd ++ sram_and2_dec +XDEC_AND_7 ++ out_3 out_5 decode_7 vdd gnd ++ sram_and2_dec +XDEC_AND_11 ++ out_3 out_6 decode_11 vdd gnd ++ sram_and2_dec +XDEC_AND_15 ++ out_3 out_7 decode_15 vdd gnd ++ sram_and2_dec +.ENDS sram_hierarchical_decoder + +.SUBCKT sram_wordline_driver ++ A B Z vdd gnd +* INPUT : A +* INPUT : B +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +Xwld_nand ++ A B zb_int vdd gnd ++ sram_pnand2 +Xwl_driver ++ zb_int Z vdd gnd ++ sram_pinv +.ENDS sram_wordline_driver + +.SUBCKT sram_wordline_driver_array ++ in_0 in_1 in_2 in_3 in_4 in_5 in_6 in_7 in_8 in_9 in_10 in_11 in_12 ++ in_13 in_14 in_15 wl_0 wl_1 wl_2 wl_3 wl_4 wl_5 wl_6 wl_7 wl_8 wl_9 ++ wl_10 wl_11 wl_12 wl_13 wl_14 wl_15 en vdd gnd +* INPUT : in_0 +* INPUT : in_1 +* INPUT : in_2 +* INPUT : in_3 +* INPUT : in_4 +* INPUT : in_5 +* INPUT : in_6 +* INPUT : in_7 +* INPUT : in_8 +* INPUT : in_9 +* INPUT : in_10 +* INPUT : in_11 +* INPUT : in_12 +* INPUT : in_13 +* INPUT : in_14 +* INPUT : in_15 +* OUTPUT: wl_0 +* OUTPUT: wl_1 +* OUTPUT: wl_2 +* OUTPUT: wl_3 +* OUTPUT: wl_4 +* OUTPUT: wl_5 +* OUTPUT: wl_6 +* OUTPUT: wl_7 +* OUTPUT: wl_8 +* OUTPUT: wl_9 +* OUTPUT: wl_10 +* OUTPUT: wl_11 +* OUTPUT: wl_12 +* OUTPUT: wl_13 +* OUTPUT: wl_14 +* OUTPUT: wl_15 +* INPUT : en +* POWER : vdd +* GROUND: gnd +* rows: 16 cols: 1 +Xwl_driver_and0 ++ in_0 en wl_0 vdd gnd ++ sram_wordline_driver +Xwl_driver_and1 ++ in_1 en wl_1 vdd gnd ++ sram_wordline_driver +Xwl_driver_and2 ++ in_2 en wl_2 vdd gnd ++ sram_wordline_driver +Xwl_driver_and3 ++ in_3 en wl_3 vdd gnd ++ sram_wordline_driver +Xwl_driver_and4 ++ in_4 en wl_4 vdd gnd ++ sram_wordline_driver +Xwl_driver_and5 ++ in_5 en wl_5 vdd gnd ++ sram_wordline_driver +Xwl_driver_and6 ++ in_6 en wl_6 vdd gnd ++ sram_wordline_driver +Xwl_driver_and7 ++ in_7 en wl_7 vdd gnd ++ sram_wordline_driver +Xwl_driver_and8 ++ in_8 en wl_8 vdd gnd ++ sram_wordline_driver +Xwl_driver_and9 ++ in_9 en wl_9 vdd gnd ++ sram_wordline_driver +Xwl_driver_and10 ++ in_10 en wl_10 vdd gnd ++ sram_wordline_driver +Xwl_driver_and11 ++ in_11 en wl_11 vdd gnd ++ sram_wordline_driver +Xwl_driver_and12 ++ in_12 en wl_12 vdd gnd ++ sram_wordline_driver +Xwl_driver_and13 ++ in_13 en wl_13 vdd gnd ++ sram_wordline_driver +Xwl_driver_and14 ++ in_14 en wl_14 vdd gnd ++ sram_wordline_driver +Xwl_driver_and15 ++ in_15 en wl_15 vdd gnd ++ sram_wordline_driver +.ENDS sram_wordline_driver_array + +.SUBCKT sram_port_address ++ addr_0 addr_1 addr_2 addr_3 wl_en wl_0 wl_1 wl_2 wl_3 wl_4 wl_5 wl_6 ++ wl_7 wl_8 wl_9 wl_10 wl_11 wl_12 wl_13 wl_14 wl_15 rbl_wl vdd gnd +* INPUT : addr_0 +* INPUT : addr_1 +* INPUT : addr_2 +* INPUT : addr_3 +* INPUT : wl_en +* OUTPUT: wl_0 +* OUTPUT: wl_1 +* OUTPUT: wl_2 +* OUTPUT: wl_3 +* OUTPUT: wl_4 +* OUTPUT: wl_5 +* OUTPUT: wl_6 +* OUTPUT: wl_7 +* OUTPUT: wl_8 +* OUTPUT: wl_9 +* OUTPUT: wl_10 +* OUTPUT: wl_11 +* OUTPUT: wl_12 +* OUTPUT: wl_13 +* OUTPUT: wl_14 +* OUTPUT: wl_15 +* OUTPUT: rbl_wl +* POWER : vdd +* GROUND: gnd +Xrow_decoder ++ addr_0 addr_1 addr_2 addr_3 dec_out_0 dec_out_1 dec_out_2 dec_out_3 ++ dec_out_4 dec_out_5 dec_out_6 dec_out_7 dec_out_8 dec_out_9 dec_out_10 ++ dec_out_11 dec_out_12 dec_out_13 dec_out_14 dec_out_15 vdd gnd ++ sram_hierarchical_decoder +Xwordline_driver ++ dec_out_0 dec_out_1 dec_out_2 dec_out_3 dec_out_4 dec_out_5 dec_out_6 ++ dec_out_7 dec_out_8 dec_out_9 dec_out_10 dec_out_11 dec_out_12 ++ dec_out_13 dec_out_14 dec_out_15 wl_0 wl_1 wl_2 wl_3 wl_4 wl_5 wl_6 ++ wl_7 wl_8 wl_9 wl_10 wl_11 wl_12 wl_13 wl_14 wl_15 wl_en vdd gnd ++ sram_wordline_driver_array +Xrbl_driver ++ wl_en vdd rbl_wl vdd gnd ++ sram_and2_dec_0 +.ENDS sram_port_address + +.SUBCKT dummy_cell_1rw bl br wl vdd gnd +* Inverter 1 +MM0 Q_bar Q gnd gnd NMOS_VTG W=205.00n L=50n +MM4 Q_bar Q vdd vdd PMOS_VTG W=90n L=50n + +* Inverer 2 +MM1 Q Q_bar gnd gnd NMOS_VTG W=205.00n L=50n +MM5 Q Q_bar vdd vdd PMOS_VTG W=90n L=50n + +* Access transistors +MM3 bl_noconn wl Q gnd NMOS_VTG W=135.00n L=50n +MM2 br_noconn wl Q_bar gnd NMOS_VTG W=135.00n L=50n +.ENDS dummy_cell_1rw + + +.SUBCKT sram_dummy_array_2 ++ bl_0_0 br_0_0 wl_0_0 wl_0_1 wl_0_2 wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 ++ wl_0_8 wl_0_9 wl_0_10 wl_0_11 wl_0_12 wl_0_13 wl_0_14 wl_0_15 wl_0_16 ++ wl_0_17 wl_0_18 vdd gnd +* INOUT : bl_0_0 +* INOUT : br_0_0 +* INPUT : wl_0_0 +* INPUT : wl_0_1 +* INPUT : wl_0_2 +* INPUT : wl_0_3 +* INPUT : wl_0_4 +* INPUT : wl_0_5 +* INPUT : wl_0_6 +* INPUT : wl_0_7 +* INPUT : wl_0_8 +* INPUT : wl_0_9 +* INPUT : wl_0_10 +* INPUT : wl_0_11 +* INPUT : wl_0_12 +* INPUT : wl_0_13 +* INPUT : wl_0_14 +* INPUT : wl_0_15 +* INPUT : wl_0_16 +* INPUT : wl_0_17 +* INPUT : wl_0_18 +* POWER : vdd +* GROUND: gnd +Xbit_r0_c0 ++ bl_0_0 br_0_0 wl_0_0 vdd gnd ++ dummy_cell_1rw +Xbit_r1_c0 ++ bl_0_0 br_0_0 wl_0_1 vdd gnd ++ dummy_cell_1rw +Xbit_r2_c0 ++ bl_0_0 br_0_0 wl_0_2 vdd gnd ++ dummy_cell_1rw +Xbit_r3_c0 ++ bl_0_0 br_0_0 wl_0_3 vdd gnd ++ dummy_cell_1rw +Xbit_r4_c0 ++ bl_0_0 br_0_0 wl_0_4 vdd gnd ++ dummy_cell_1rw +Xbit_r5_c0 ++ bl_0_0 br_0_0 wl_0_5 vdd gnd ++ dummy_cell_1rw +Xbit_r6_c0 ++ bl_0_0 br_0_0 wl_0_6 vdd gnd ++ dummy_cell_1rw +Xbit_r7_c0 ++ bl_0_0 br_0_0 wl_0_7 vdd gnd ++ dummy_cell_1rw +Xbit_r8_c0 ++ bl_0_0 br_0_0 wl_0_8 vdd gnd ++ dummy_cell_1rw +Xbit_r9_c0 ++ bl_0_0 br_0_0 wl_0_9 vdd gnd ++ dummy_cell_1rw +Xbit_r10_c0 ++ bl_0_0 br_0_0 wl_0_10 vdd gnd ++ dummy_cell_1rw +Xbit_r11_c0 ++ bl_0_0 br_0_0 wl_0_11 vdd gnd ++ dummy_cell_1rw +Xbit_r12_c0 ++ bl_0_0 br_0_0 wl_0_12 vdd gnd ++ dummy_cell_1rw +Xbit_r13_c0 ++ bl_0_0 br_0_0 wl_0_13 vdd gnd ++ dummy_cell_1rw +Xbit_r14_c0 ++ bl_0_0 br_0_0 wl_0_14 vdd gnd ++ dummy_cell_1rw +Xbit_r15_c0 ++ bl_0_0 br_0_0 wl_0_15 vdd gnd ++ dummy_cell_1rw +Xbit_r16_c0 ++ bl_0_0 br_0_0 wl_0_16 vdd gnd ++ dummy_cell_1rw +Xbit_r17_c0 ++ bl_0_0 br_0_0 wl_0_17 vdd gnd ++ dummy_cell_1rw +Xbit_r18_c0 ++ bl_0_0 br_0_0 wl_0_18 vdd gnd ++ dummy_cell_1rw +.ENDS sram_dummy_array_2 + +.SUBCKT sram_dummy_array_3 ++ bl_0_0 br_0_0 wl_0_0 wl_0_1 wl_0_2 wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 ++ wl_0_8 wl_0_9 wl_0_10 wl_0_11 wl_0_12 wl_0_13 wl_0_14 wl_0_15 wl_0_16 ++ wl_0_17 wl_0_18 vdd gnd +* INOUT : bl_0_0 +* INOUT : br_0_0 +* INPUT : wl_0_0 +* INPUT : wl_0_1 +* INPUT : wl_0_2 +* INPUT : wl_0_3 +* INPUT : wl_0_4 +* INPUT : wl_0_5 +* INPUT : wl_0_6 +* INPUT : wl_0_7 +* INPUT : wl_0_8 +* INPUT : wl_0_9 +* INPUT : wl_0_10 +* INPUT : wl_0_11 +* INPUT : wl_0_12 +* INPUT : wl_0_13 +* INPUT : wl_0_14 +* INPUT : wl_0_15 +* INPUT : wl_0_16 +* INPUT : wl_0_17 +* INPUT : wl_0_18 +* POWER : vdd +* GROUND: gnd +Xbit_r0_c0 ++ bl_0_0 br_0_0 wl_0_0 vdd gnd ++ dummy_cell_1rw +Xbit_r1_c0 ++ bl_0_0 br_0_0 wl_0_1 vdd gnd ++ dummy_cell_1rw +Xbit_r2_c0 ++ bl_0_0 br_0_0 wl_0_2 vdd gnd ++ dummy_cell_1rw +Xbit_r3_c0 ++ bl_0_0 br_0_0 wl_0_3 vdd gnd ++ dummy_cell_1rw +Xbit_r4_c0 ++ bl_0_0 br_0_0 wl_0_4 vdd gnd ++ dummy_cell_1rw +Xbit_r5_c0 ++ bl_0_0 br_0_0 wl_0_5 vdd gnd ++ dummy_cell_1rw +Xbit_r6_c0 ++ bl_0_0 br_0_0 wl_0_6 vdd gnd ++ dummy_cell_1rw +Xbit_r7_c0 ++ bl_0_0 br_0_0 wl_0_7 vdd gnd ++ dummy_cell_1rw +Xbit_r8_c0 ++ bl_0_0 br_0_0 wl_0_8 vdd gnd ++ dummy_cell_1rw +Xbit_r9_c0 ++ bl_0_0 br_0_0 wl_0_9 vdd gnd ++ dummy_cell_1rw +Xbit_r10_c0 ++ bl_0_0 br_0_0 wl_0_10 vdd gnd ++ dummy_cell_1rw +Xbit_r11_c0 ++ bl_0_0 br_0_0 wl_0_11 vdd gnd ++ dummy_cell_1rw +Xbit_r12_c0 ++ bl_0_0 br_0_0 wl_0_12 vdd gnd ++ dummy_cell_1rw +Xbit_r13_c0 ++ bl_0_0 br_0_0 wl_0_13 vdd gnd ++ dummy_cell_1rw +Xbit_r14_c0 ++ bl_0_0 br_0_0 wl_0_14 vdd gnd ++ dummy_cell_1rw +Xbit_r15_c0 ++ bl_0_0 br_0_0 wl_0_15 vdd gnd ++ dummy_cell_1rw +Xbit_r16_c0 ++ bl_0_0 br_0_0 wl_0_16 vdd gnd ++ dummy_cell_1rw +Xbit_r17_c0 ++ bl_0_0 br_0_0 wl_0_17 vdd gnd ++ dummy_cell_1rw +Xbit_r18_c0 ++ bl_0_0 br_0_0 wl_0_18 vdd gnd ++ dummy_cell_1rw +.ENDS sram_dummy_array_3 + +.SUBCKT sram_dummy_array ++ bl_0_0 br_0_0 wl_0_0 vdd gnd +* INOUT : bl_0_0 +* INOUT : br_0_0 +* INPUT : wl_0_0 +* POWER : vdd +* GROUND: gnd +Xbit_r0_c0 ++ bl_0_0 br_0_0 wl_0_0 vdd gnd ++ dummy_cell_1rw +.ENDS sram_dummy_array + +.SUBCKT cell_1rw bl br wl vdd gnd +* Inverter 1 +MM0 Q_bar Q gnd gnd NMOS_VTG W=205.00n L=50n +MM4 Q_bar Q vdd vdd PMOS_VTG W=90n L=50n + +* Inverer 2 +MM1 Q Q_bar gnd gnd NMOS_VTG W=205.00n L=50n +MM5 Q Q_bar vdd vdd PMOS_VTG W=90n L=50n + +* Access transistors +MM3 bl wl Q gnd NMOS_VTG W=135.00n L=50n +MM2 br wl Q_bar gnd NMOS_VTG W=135.00n L=50n +.ENDS cell_1rw + + +.SUBCKT sram_bitcell_array ++ bl_0_0 br_0_0 wl_0_0 wl_0_1 wl_0_2 wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 ++ wl_0_8 wl_0_9 wl_0_10 wl_0_11 wl_0_12 wl_0_13 wl_0_14 wl_0_15 vdd gnd +* INOUT : bl_0_0 +* INOUT : br_0_0 +* INPUT : wl_0_0 +* INPUT : wl_0_1 +* INPUT : wl_0_2 +* INPUT : wl_0_3 +* INPUT : wl_0_4 +* INPUT : wl_0_5 +* INPUT : wl_0_6 +* INPUT : wl_0_7 +* INPUT : wl_0_8 +* INPUT : wl_0_9 +* INPUT : wl_0_10 +* INPUT : wl_0_11 +* INPUT : wl_0_12 +* INPUT : wl_0_13 +* INPUT : wl_0_14 +* INPUT : wl_0_15 +* POWER : vdd +* GROUND: gnd +* rows: 16 cols: 1 +Xbit_r0_c0 ++ bl_0_0 br_0_0 wl_0_0 vdd gnd ++ cell_1rw +Xbit_r1_c0 ++ bl_0_0 br_0_0 wl_0_1 vdd gnd ++ cell_1rw +Xbit_r2_c0 ++ bl_0_0 br_0_0 wl_0_2 vdd gnd ++ cell_1rw +Xbit_r3_c0 ++ bl_0_0 br_0_0 wl_0_3 vdd gnd ++ cell_1rw +Xbit_r4_c0 ++ bl_0_0 br_0_0 wl_0_4 vdd gnd ++ cell_1rw +Xbit_r5_c0 ++ bl_0_0 br_0_0 wl_0_5 vdd gnd ++ cell_1rw +Xbit_r6_c0 ++ bl_0_0 br_0_0 wl_0_6 vdd gnd ++ cell_1rw +Xbit_r7_c0 ++ bl_0_0 br_0_0 wl_0_7 vdd gnd ++ cell_1rw +Xbit_r8_c0 ++ bl_0_0 br_0_0 wl_0_8 vdd gnd ++ cell_1rw +Xbit_r9_c0 ++ bl_0_0 br_0_0 wl_0_9 vdd gnd ++ cell_1rw +Xbit_r10_c0 ++ bl_0_0 br_0_0 wl_0_10 vdd gnd ++ cell_1rw +Xbit_r11_c0 ++ bl_0_0 br_0_0 wl_0_11 vdd gnd ++ cell_1rw +Xbit_r12_c0 ++ bl_0_0 br_0_0 wl_0_12 vdd gnd ++ cell_1rw +Xbit_r13_c0 ++ bl_0_0 br_0_0 wl_0_13 vdd gnd ++ cell_1rw +Xbit_r14_c0 ++ bl_0_0 br_0_0 wl_0_14 vdd gnd ++ cell_1rw +Xbit_r15_c0 ++ bl_0_0 br_0_0 wl_0_15 vdd gnd ++ cell_1rw +.ENDS sram_bitcell_array + +.SUBCKT replica_cell_1rw bl br wl vdd gnd +* Inverter 1 +MM0 vdd Q gnd gnd NMOS_VTG W=205.00n L=50n +MM4 vdd Q vdd vdd PMOS_VTG W=90n L=50n + +* Inverer 2 +MM1 Q vdd gnd gnd NMOS_VTG W=205.00n L=50n +MM5 Q vdd vdd vdd PMOS_VTG W=90n L=50n + +* Access transistors +MM3 bl wl Q gnd NMOS_VTG W=135.00n L=50n +MM2 br wl vdd gnd NMOS_VTG W=135.00n L=50n +.ENDS cell_1rw + + +.SUBCKT sram_replica_column ++ bl_0_0 br_0_0 wl_0_0 wl_0_1 wl_0_2 wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 ++ wl_0_8 wl_0_9 wl_0_10 wl_0_11 wl_0_12 wl_0_13 wl_0_14 wl_0_15 wl_0_16 ++ vdd gnd +* OUTPUT: bl_0_0 +* OUTPUT: br_0_0 +* INPUT : wl_0_0 +* INPUT : wl_0_1 +* INPUT : wl_0_2 +* INPUT : wl_0_3 +* INPUT : wl_0_4 +* INPUT : wl_0_5 +* INPUT : wl_0_6 +* INPUT : wl_0_7 +* INPUT : wl_0_8 +* INPUT : wl_0_9 +* INPUT : wl_0_10 +* INPUT : wl_0_11 +* INPUT : wl_0_12 +* INPUT : wl_0_13 +* INPUT : wl_0_14 +* INPUT : wl_0_15 +* INPUT : wl_0_16 +* POWER : vdd +* GROUND: gnd +Xrbc_0 ++ bl_0_0 br_0_0 wl_0_0 vdd gnd ++ replica_cell_1rw +Xrbc_1 ++ bl_0_0 br_0_0 wl_0_1 vdd gnd ++ replica_cell_1rw +Xrbc_2 ++ bl_0_0 br_0_0 wl_0_2 vdd gnd ++ replica_cell_1rw +Xrbc_3 ++ bl_0_0 br_0_0 wl_0_3 vdd gnd ++ replica_cell_1rw +Xrbc_4 ++ bl_0_0 br_0_0 wl_0_4 vdd gnd ++ replica_cell_1rw +Xrbc_5 ++ bl_0_0 br_0_0 wl_0_5 vdd gnd ++ replica_cell_1rw +Xrbc_6 ++ bl_0_0 br_0_0 wl_0_6 vdd gnd ++ replica_cell_1rw +Xrbc_7 ++ bl_0_0 br_0_0 wl_0_7 vdd gnd ++ replica_cell_1rw +Xrbc_8 ++ bl_0_0 br_0_0 wl_0_8 vdd gnd ++ replica_cell_1rw +Xrbc_9 ++ bl_0_0 br_0_0 wl_0_9 vdd gnd ++ replica_cell_1rw +Xrbc_10 ++ bl_0_0 br_0_0 wl_0_10 vdd gnd ++ replica_cell_1rw +Xrbc_11 ++ bl_0_0 br_0_0 wl_0_11 vdd gnd ++ replica_cell_1rw +Xrbc_12 ++ bl_0_0 br_0_0 wl_0_12 vdd gnd ++ replica_cell_1rw +Xrbc_13 ++ bl_0_0 br_0_0 wl_0_13 vdd gnd ++ replica_cell_1rw +Xrbc_14 ++ bl_0_0 br_0_0 wl_0_14 vdd gnd ++ replica_cell_1rw +Xrbc_15 ++ bl_0_0 br_0_0 wl_0_15 vdd gnd ++ replica_cell_1rw +Xrbc_16 ++ bl_0_0 br_0_0 wl_0_16 vdd gnd ++ replica_cell_1rw +.ENDS sram_replica_column + +.SUBCKT sram_replica_bitcell_array ++ rbl_bl_0_0 rbl_br_0_0 bl_0_0 br_0_0 rbl_wl_0_0 wl_0_0 wl_0_1 wl_0_2 ++ wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 wl_0_8 wl_0_9 wl_0_10 wl_0_11 ++ wl_0_12 wl_0_13 wl_0_14 wl_0_15 vdd gnd +* INOUT : rbl_bl_0_0 +* INOUT : rbl_br_0_0 +* INOUT : bl_0_0 +* INOUT : br_0_0 +* INPUT : rbl_wl_0_0 +* INPUT : wl_0_0 +* INPUT : wl_0_1 +* INPUT : wl_0_2 +* INPUT : wl_0_3 +* INPUT : wl_0_4 +* INPUT : wl_0_5 +* INPUT : wl_0_6 +* INPUT : wl_0_7 +* INPUT : wl_0_8 +* INPUT : wl_0_9 +* INPUT : wl_0_10 +* INPUT : wl_0_11 +* INPUT : wl_0_12 +* INPUT : wl_0_13 +* INPUT : wl_0_14 +* INPUT : wl_0_15 +* POWER : vdd +* GROUND: gnd +* rbl: [1, 0] left_rbl: [0] right_rbl: [] +Xbitcell_array ++ bl_0_0 br_0_0 wl_0_0 wl_0_1 wl_0_2 wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 ++ wl_0_8 wl_0_9 wl_0_10 wl_0_11 wl_0_12 wl_0_13 wl_0_14 wl_0_15 vdd gnd ++ sram_bitcell_array +Xreplica_col_0 ++ rbl_bl_0_0 rbl_br_0_0 rbl_wl_0_0 wl_0_0 wl_0_1 wl_0_2 wl_0_3 wl_0_4 ++ wl_0_5 wl_0_6 wl_0_7 wl_0_8 wl_0_9 wl_0_10 wl_0_11 wl_0_12 wl_0_13 ++ wl_0_14 wl_0_15 vdd gnd ++ sram_replica_column +Xdummy_row_0 ++ bl_0_0 br_0_0 rbl_wl_0_0 vdd gnd ++ sram_dummy_array +.ENDS sram_replica_bitcell_array + +.SUBCKT sram_dummy_array_0 ++ bl_0_0 br_0_0 bl_0_1 br_0_1 wl_0_0 vdd gnd +* INOUT : bl_0_0 +* INOUT : br_0_0 +* INOUT : bl_0_1 +* INOUT : br_0_1 +* INPUT : wl_0_0 +* POWER : vdd +* GROUND: gnd +Xbit_r0_c0 ++ bl_0_0 br_0_0 wl_0_0 vdd gnd ++ dummy_cell_1rw +Xbit_r0_c1 ++ bl_0_1 br_0_1 wl_0_0 vdd gnd ++ dummy_cell_1rw +.ENDS sram_dummy_array_0 + +.SUBCKT sram_dummy_array_1 ++ bl_0_0 br_0_0 bl_0_1 br_0_1 wl_0_0 vdd gnd +* INOUT : bl_0_0 +* INOUT : br_0_0 +* INOUT : bl_0_1 +* INOUT : br_0_1 +* INPUT : wl_0_0 +* POWER : vdd +* GROUND: gnd +Xbit_r0_c0 ++ bl_0_0 br_0_0 wl_0_0 vdd gnd ++ dummy_cell_1rw +Xbit_r0_c1 ++ bl_0_1 br_0_1 wl_0_0 vdd gnd ++ dummy_cell_1rw +.ENDS sram_dummy_array_1 + +.SUBCKT sram_capped_replica_bitcell_array ++ rbl_bl_0_0 rbl_br_0_0 bl_0_0 br_0_0 rbl_wl_0_0 wl_0_0 wl_0_1 wl_0_2 ++ wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 wl_0_8 wl_0_9 wl_0_10 wl_0_11 ++ wl_0_12 wl_0_13 wl_0_14 wl_0_15 vdd gnd +* INOUT : rbl_bl_0_0 +* INOUT : rbl_br_0_0 +* INOUT : bl_0_0 +* INOUT : br_0_0 +* INPUT : rbl_wl_0_0 +* INPUT : wl_0_0 +* INPUT : wl_0_1 +* INPUT : wl_0_2 +* INPUT : wl_0_3 +* INPUT : wl_0_4 +* INPUT : wl_0_5 +* INPUT : wl_0_6 +* INPUT : wl_0_7 +* INPUT : wl_0_8 +* INPUT : wl_0_9 +* INPUT : wl_0_10 +* INPUT : wl_0_11 +* INPUT : wl_0_12 +* INPUT : wl_0_13 +* INPUT : wl_0_14 +* INPUT : wl_0_15 +* POWER : vdd +* GROUND: gnd +* rbl: [1, 0] left_rbl: [0] right_rbl: [] +Xreplica_bitcell_array ++ rbl_bl_0_0 rbl_br_0_0 bl_0_0 br_0_0 rbl_wl_0_0 wl_0_0 wl_0_1 wl_0_2 ++ wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 wl_0_8 wl_0_9 wl_0_10 wl_0_11 ++ wl_0_12 wl_0_13 wl_0_14 wl_0_15 vdd gnd ++ sram_replica_bitcell_array +Xdummy_row_bot ++ rbl_bl_0_0 rbl_br_0_0 bl_0_0 br_0_0 gnd vdd gnd ++ sram_dummy_array_1 +Xdummy_row_top ++ rbl_bl_0_0 rbl_br_0_0 bl_0_0 br_0_0 gnd vdd gnd ++ sram_dummy_array_0 +Xdummy_col_left ++ dummy_left_bl_0_0 dummy_left_br_0_0 gnd rbl_wl_0_0 wl_0_0 wl_0_1 ++ wl_0_2 wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 wl_0_8 wl_0_9 wl_0_10 ++ wl_0_11 wl_0_12 wl_0_13 wl_0_14 wl_0_15 gnd vdd gnd ++ sram_dummy_array_2 +Xdummy_col_right ++ dummy_right_bl_0_0 dummy_right_br_0_0 gnd rbl_wl_0_0 wl_0_0 wl_0_1 ++ wl_0_2 wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 wl_0_8 wl_0_9 wl_0_10 ++ wl_0_11 wl_0_12 wl_0_13 wl_0_14 wl_0_15 gnd vdd gnd ++ sram_dummy_array_3 +.ENDS sram_capped_replica_bitcell_array + +.SUBCKT sram_bank ++ dout0_0 rbl_bl_0_0 din0_0 addr0_0 addr0_1 addr0_2 addr0_3 s_en0 ++ p_en_bar0 w_en0 wl_en0 vdd gnd +* OUTPUT: dout0_0 +* OUTPUT: rbl_bl_0_0 +* INPUT : din0_0 +* INPUT : addr0_0 +* INPUT : addr0_1 +* INPUT : addr0_2 +* INPUT : addr0_3 +* INPUT : s_en0 +* INPUT : p_en_bar0 +* INPUT : w_en0 +* INPUT : wl_en0 +* POWER : vdd +* GROUND: gnd +Xbitcell_array ++ rbl_bl_0_0 rbl_br_0_0 bl_0_0 br_0_0 rbl_wl0 wl_0_0 wl_0_1 wl_0_2 ++ wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 wl_0_8 wl_0_9 wl_0_10 wl_0_11 ++ wl_0_12 wl_0_13 wl_0_14 wl_0_15 vdd gnd ++ sram_capped_replica_bitcell_array +Xport_data0 ++ rbl_bl_0_0 rbl_br_0_0 bl_0_0 br_0_0 dout0_0 din0_0 s_en0 p_en_bar0 ++ w_en0 vdd gnd ++ sram_port_data +Xport_address0 ++ addr0_0 addr0_1 addr0_2 addr0_3 wl_en0 wl_0_0 wl_0_1 wl_0_2 wl_0_3 ++ wl_0_4 wl_0_5 wl_0_6 wl_0_7 wl_0_8 wl_0_9 wl_0_10 wl_0_11 wl_0_12 ++ wl_0_13 wl_0_14 wl_0_15 rbl_wl0 vdd gnd ++ sram_port_address +.ENDS sram_bank + +.SUBCKT sram_row_addr_dff ++ din_0 din_1 din_2 din_3 dout_0 dout_1 dout_2 dout_3 clk vdd gnd +* INPUT : din_0 +* INPUT : din_1 +* INPUT : din_2 +* INPUT : din_3 +* OUTPUT: dout_0 +* OUTPUT: dout_1 +* OUTPUT: dout_2 +* OUTPUT: dout_3 +* INPUT : clk +* POWER : vdd +* GROUND: gnd +* rows: 4 cols: 1 +Xdff_r0_c0 ++ din_0 dout_0 clk vdd gnd ++ dff +Xdff_r1_c0 ++ din_1 dout_1 clk vdd gnd ++ dff +Xdff_r2_c0 ++ din_2 dout_2 clk vdd gnd ++ dff +Xdff_r3_c0 ++ din_3 dout_3 clk vdd gnd ++ dff +.ENDS sram_row_addr_dff + +.SUBCKT sram_data_dff ++ din_0 dout_0 clk vdd gnd +* INPUT : din_0 +* OUTPUT: dout_0 +* INPUT : clk +* POWER : vdd +* GROUND: gnd +* rows: 1 cols: 1 +Xdff_r0_c0 ++ din_0 dout_0 clk vdd gnd ++ dff +.ENDS sram_data_dff + +.SUBCKT sram ++ din0[0] addr0[0] addr0[1] addr0[2] addr0[3] csb0 web0 clk0 dout0[0] ++ vdd gnd +* INPUT : din0[0] +* INPUT : addr0[0] +* INPUT : addr0[1] +* INPUT : addr0[2] +* INPUT : addr0[3] +* INPUT : csb0 +* INPUT : web0 +* INPUT : clk0 +* OUTPUT: dout0[0] +* POWER : vdd +* GROUND: gnd +Xbank0 ++ dout0[0] rbl_bl0 bank_din0_0 a0_0 a0_1 a0_2 a0_3 s_en0 p_en_bar0 w_en0 ++ wl_en0 vdd gnd ++ sram_bank +Xcontrol0 ++ csb0 web0 clk0 rbl_bl0 s_en0 w_en0 p_en_bar0 wl_en0 clk_buf0 vdd gnd ++ sram_control_logic_rw +Xrow_address0 ++ addr0[0] addr0[1] addr0[2] addr0[3] a0_0 a0_1 a0_2 a0_3 clk_buf0 vdd ++ gnd ++ sram_row_addr_dff +Xdata_dff0 ++ din0[0] bank_din0_0 clk_buf0 vdd gnd ++ sram_data_dff +.ENDS sram diff --git a/compiler/tests/sp_files/sram_2_16_1_scn4m_subm.sp b/compiler/tests/sp_files/sram_2_16_1_scn4m_subm.sp new file mode 100644 index 00000000..947ff987 --- /dev/null +++ b/compiler/tests/sp_files/sram_2_16_1_scn4m_subm.sp @@ -0,0 +1,1656 @@ +************************************************** +* OpenRAM generated memory. +* Words: 16 +* Data bits: 1 +* Banks: 1 +* Column mux: 1:1 +* Trimmed: False +* LVS: False +************************************************** + +* spice ptx M{0} {1} n m=1 w=0.8u l=0.4u pd=2.40u ps=2.40u as=0.80p ad=0.80p + +* spice ptx M{0} {1} p m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p + +.SUBCKT sram_pinv ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +Mpinv_pmos Z A vdd vdd p m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p +Mpinv_nmos Z A gnd gnd n m=1 w=0.8u l=0.4u pd=2.40u ps=2.40u as=0.80p ad=0.80p +.ENDS sram_pinv + +* spice ptx M{0} {1} n m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p + +* spice ptx M{0} {1} p m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p + +* spice ptx M{0} {1} n m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p + +.SUBCKT sram_pnand2 ++ A B Z vdd gnd +* INPUT : A +* INPUT : B +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +Mpnand2_pmos1 vdd A Z vdd p m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p +Mpnand2_pmos2 Z B vdd vdd p m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p +Mpnand2_nmos1 Z B net1 gnd n m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p +Mpnand2_nmos2 net1 A gnd gnd n m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p +.ENDS sram_pnand2 + +.SUBCKT sram_wordline_driver ++ A B Z vdd gnd +* INPUT : A +* INPUT : B +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +Xwld_nand ++ A B zb_int vdd gnd ++ sram_pnand2 +Xwl_driver ++ zb_int Z vdd gnd ++ sram_pinv +.ENDS sram_wordline_driver + +.SUBCKT sram_wordline_driver_array ++ in_0 in_1 in_2 in_3 in_4 in_5 in_6 in_7 in_8 in_9 in_10 in_11 in_12 ++ in_13 in_14 in_15 wl_0 wl_1 wl_2 wl_3 wl_4 wl_5 wl_6 wl_7 wl_8 wl_9 ++ wl_10 wl_11 wl_12 wl_13 wl_14 wl_15 en vdd gnd +* INPUT : in_0 +* INPUT : in_1 +* INPUT : in_2 +* INPUT : in_3 +* INPUT : in_4 +* INPUT : in_5 +* INPUT : in_6 +* INPUT : in_7 +* INPUT : in_8 +* INPUT : in_9 +* INPUT : in_10 +* INPUT : in_11 +* INPUT : in_12 +* INPUT : in_13 +* INPUT : in_14 +* INPUT : in_15 +* OUTPUT: wl_0 +* OUTPUT: wl_1 +* OUTPUT: wl_2 +* OUTPUT: wl_3 +* OUTPUT: wl_4 +* OUTPUT: wl_5 +* OUTPUT: wl_6 +* OUTPUT: wl_7 +* OUTPUT: wl_8 +* OUTPUT: wl_9 +* OUTPUT: wl_10 +* OUTPUT: wl_11 +* OUTPUT: wl_12 +* OUTPUT: wl_13 +* OUTPUT: wl_14 +* OUTPUT: wl_15 +* INPUT : en +* POWER : vdd +* GROUND: gnd +* rows: 16 cols: 1 +Xwl_driver_and0 ++ in_0 en wl_0 vdd gnd ++ sram_wordline_driver +Xwl_driver_and1 ++ in_1 en wl_1 vdd gnd ++ sram_wordline_driver +Xwl_driver_and2 ++ in_2 en wl_2 vdd gnd ++ sram_wordline_driver +Xwl_driver_and3 ++ in_3 en wl_3 vdd gnd ++ sram_wordline_driver +Xwl_driver_and4 ++ in_4 en wl_4 vdd gnd ++ sram_wordline_driver +Xwl_driver_and5 ++ in_5 en wl_5 vdd gnd ++ sram_wordline_driver +Xwl_driver_and6 ++ in_6 en wl_6 vdd gnd ++ sram_wordline_driver +Xwl_driver_and7 ++ in_7 en wl_7 vdd gnd ++ sram_wordline_driver +Xwl_driver_and8 ++ in_8 en wl_8 vdd gnd ++ sram_wordline_driver +Xwl_driver_and9 ++ in_9 en wl_9 vdd gnd ++ sram_wordline_driver +Xwl_driver_and10 ++ in_10 en wl_10 vdd gnd ++ sram_wordline_driver +Xwl_driver_and11 ++ in_11 en wl_11 vdd gnd ++ sram_wordline_driver +Xwl_driver_and12 ++ in_12 en wl_12 vdd gnd ++ sram_wordline_driver +Xwl_driver_and13 ++ in_13 en wl_13 vdd gnd ++ sram_wordline_driver +Xwl_driver_and14 ++ in_14 en wl_14 vdd gnd ++ sram_wordline_driver +Xwl_driver_and15 ++ in_15 en wl_15 vdd gnd ++ sram_wordline_driver +.ENDS sram_wordline_driver_array + +.SUBCKT sram_and2_dec_0 ++ A B Z vdd gnd +* INPUT : A +* INPUT : B +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* size: 1 +Xpand2_dec_nand ++ A B zb_int vdd gnd ++ sram_pnand2 +Xpand2_dec_inv ++ zb_int Z vdd gnd ++ sram_pinv +.ENDS sram_and2_dec_0 + +.SUBCKT sram_and2_dec ++ A B Z vdd gnd +* INPUT : A +* INPUT : B +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* size: 1 +Xpand2_dec_nand ++ A B zb_int vdd gnd ++ sram_pnand2 +Xpand2_dec_inv ++ zb_int Z vdd gnd ++ sram_pinv +.ENDS sram_and2_dec + +.SUBCKT sram_hierarchical_predecode2x4 ++ in_0 in_1 out_0 out_1 out_2 out_3 vdd gnd +* INPUT : in_0 +* INPUT : in_1 +* OUTPUT: out_0 +* OUTPUT: out_1 +* OUTPUT: out_2 +* OUTPUT: out_3 +* POWER : vdd +* GROUND: gnd +Xpre_inv_0 ++ in_0 inbar_0 vdd gnd ++ sram_pinv +Xpre_inv_1 ++ in_1 inbar_1 vdd gnd ++ sram_pinv +XXpre2x4_and_0 ++ inbar_0 inbar_1 out_0 vdd gnd ++ sram_and2_dec +XXpre2x4_and_1 ++ in_0 inbar_1 out_1 vdd gnd ++ sram_and2_dec +XXpre2x4_and_2 ++ inbar_0 in_1 out_2 vdd gnd ++ sram_and2_dec +XXpre2x4_and_3 ++ in_0 in_1 out_3 vdd gnd ++ sram_and2_dec +.ENDS sram_hierarchical_predecode2x4 + +.SUBCKT sram_hierarchical_decoder ++ addr_0 addr_1 addr_2 addr_3 decode_0 decode_1 decode_2 decode_3 ++ decode_4 decode_5 decode_6 decode_7 decode_8 decode_9 decode_10 ++ decode_11 decode_12 decode_13 decode_14 decode_15 vdd gnd +* INPUT : addr_0 +* INPUT : addr_1 +* INPUT : addr_2 +* INPUT : addr_3 +* OUTPUT: decode_0 +* OUTPUT: decode_1 +* OUTPUT: decode_2 +* OUTPUT: decode_3 +* OUTPUT: decode_4 +* OUTPUT: decode_5 +* OUTPUT: decode_6 +* OUTPUT: decode_7 +* OUTPUT: decode_8 +* OUTPUT: decode_9 +* OUTPUT: decode_10 +* OUTPUT: decode_11 +* OUTPUT: decode_12 +* OUTPUT: decode_13 +* OUTPUT: decode_14 +* OUTPUT: decode_15 +* POWER : vdd +* GROUND: gnd +Xpre_0 ++ addr_0 addr_1 out_0 out_1 out_2 out_3 vdd gnd ++ sram_hierarchical_predecode2x4 +Xpre_1 ++ addr_2 addr_3 out_4 out_5 out_6 out_7 vdd gnd ++ sram_hierarchical_predecode2x4 +XDEC_AND_0 ++ out_0 out_4 decode_0 vdd gnd ++ sram_and2_dec +XDEC_AND_4 ++ out_0 out_5 decode_4 vdd gnd ++ sram_and2_dec +XDEC_AND_8 ++ out_0 out_6 decode_8 vdd gnd ++ sram_and2_dec +XDEC_AND_12 ++ out_0 out_7 decode_12 vdd gnd ++ sram_and2_dec +XDEC_AND_1 ++ out_1 out_4 decode_1 vdd gnd ++ sram_and2_dec +XDEC_AND_5 ++ out_1 out_5 decode_5 vdd gnd ++ sram_and2_dec +XDEC_AND_9 ++ out_1 out_6 decode_9 vdd gnd ++ sram_and2_dec +XDEC_AND_13 ++ out_1 out_7 decode_13 vdd gnd ++ sram_and2_dec +XDEC_AND_2 ++ out_2 out_4 decode_2 vdd gnd ++ sram_and2_dec +XDEC_AND_6 ++ out_2 out_5 decode_6 vdd gnd ++ sram_and2_dec +XDEC_AND_10 ++ out_2 out_6 decode_10 vdd gnd ++ sram_and2_dec +XDEC_AND_14 ++ out_2 out_7 decode_14 vdd gnd ++ sram_and2_dec +XDEC_AND_3 ++ out_3 out_4 decode_3 vdd gnd ++ sram_and2_dec +XDEC_AND_7 ++ out_3 out_5 decode_7 vdd gnd ++ sram_and2_dec +XDEC_AND_11 ++ out_3 out_6 decode_11 vdd gnd ++ sram_and2_dec +XDEC_AND_15 ++ out_3 out_7 decode_15 vdd gnd ++ sram_and2_dec +.ENDS sram_hierarchical_decoder + +.SUBCKT sram_port_address ++ addr_0 addr_1 addr_2 addr_3 wl_en wl_0 wl_1 wl_2 wl_3 wl_4 wl_5 wl_6 ++ wl_7 wl_8 wl_9 wl_10 wl_11 wl_12 wl_13 wl_14 wl_15 rbl_wl vdd gnd +* INPUT : addr_0 +* INPUT : addr_1 +* INPUT : addr_2 +* INPUT : addr_3 +* INPUT : wl_en +* OUTPUT: wl_0 +* OUTPUT: wl_1 +* OUTPUT: wl_2 +* OUTPUT: wl_3 +* OUTPUT: wl_4 +* OUTPUT: wl_5 +* OUTPUT: wl_6 +* OUTPUT: wl_7 +* OUTPUT: wl_8 +* OUTPUT: wl_9 +* OUTPUT: wl_10 +* OUTPUT: wl_11 +* OUTPUT: wl_12 +* OUTPUT: wl_13 +* OUTPUT: wl_14 +* OUTPUT: wl_15 +* OUTPUT: rbl_wl +* POWER : vdd +* GROUND: gnd +Xrow_decoder ++ addr_0 addr_1 addr_2 addr_3 dec_out_0 dec_out_1 dec_out_2 dec_out_3 ++ dec_out_4 dec_out_5 dec_out_6 dec_out_7 dec_out_8 dec_out_9 dec_out_10 ++ dec_out_11 dec_out_12 dec_out_13 dec_out_14 dec_out_15 vdd gnd ++ sram_hierarchical_decoder +Xwordline_driver ++ dec_out_0 dec_out_1 dec_out_2 dec_out_3 dec_out_4 dec_out_5 dec_out_6 ++ dec_out_7 dec_out_8 dec_out_9 dec_out_10 dec_out_11 dec_out_12 ++ dec_out_13 dec_out_14 dec_out_15 wl_0 wl_1 wl_2 wl_3 wl_4 wl_5 wl_6 ++ wl_7 wl_8 wl_9 wl_10 wl_11 wl_12 wl_13 wl_14 wl_15 wl_en vdd gnd ++ sram_wordline_driver_array +Xrbl_driver ++ wl_en vdd rbl_wl vdd gnd ++ sram_and2_dec_0 +.ENDS sram_port_address +*********************** Write_Driver ****************************** +.SUBCKT write_driver din bl br en vdd gnd + +**** Inverter to conver Data_in to data_in_bar ****** +* din_bar = inv(din) +M_1 din_bar din gnd gnd n W=0.8u L=0.4u +M_2 din_bar din vdd vdd p W=1.4u L=0.4u + +**** 2input nand gate follwed by inverter to drive BL ****** +* din_bar_gated = nand(en, din) +M_3 din_bar_gated en net_7 gnd n W=1.4u L=0.4u +M_4 net_7 din gnd gnd n W=1.4u L=0.4u +M_5 din_bar_gated en vdd vdd p W=1.4u L=0.4u +M_6 din_bar_gated din vdd vdd p W=1.4u L=0.4u +* din_bar_gated_bar = inv(din_bar_gated) +M_7 din_bar_gated_bar din_bar_gated vdd vdd p W=1.4u L=0.4u +M_8 din_bar_gated_bar din_bar_gated gnd gnd n W=0.8u L=0.4u + +**** 2input nand gate follwed by inverter to drive BR****** +* din_gated = nand(en, din_bar) +M_9 din_gated en vdd vdd p W=1.4u L=0.4u +M_10 din_gated en net_8 gnd n W=1.4u L=0.4u +M_11 net_8 din_bar gnd gnd n W=1.4u L=0.4u +M_12 din_gated din_bar vdd vdd p W=1.4u L=0.4u +* din_gated_bar = inv(din_gated) +M_13 din_gated_bar din_gated vdd vdd p W=1.4u L=0.4u +M_14 din_gated_bar din_gated gnd gnd n W=0.8u L=0.4u + +************************************************ +* pull down with en enable +M_15 bl din_gated_bar gnd gnd n W=2.4u L=0.4u +M_16 br din_bar_gated_bar gnd gnd n W=2.4u L=0.4u + + + +.ENDS $ write_driver + +.SUBCKT sram_write_driver_array ++ data_0 bl_0 br_0 en vdd gnd +* INPUT : data_0 +* OUTPUT: bl_0 +* OUTPUT: br_0 +* INPUT : en +* POWER : vdd +* GROUND: gnd +* word_size 1 +Xwrite_driver0 ++ data_0 bl_0 br_0 en vdd gnd ++ write_driver +.ENDS sram_write_driver_array + +.SUBCKT sram_precharge_0 ++ bl br en_bar vdd +* OUTPUT: bl +* OUTPUT: br +* INPUT : en_bar +* POWER : vdd +Mlower_pmos bl en_bar br vdd p m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p +Mupper_pmos1 bl en_bar vdd vdd p m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p +Mupper_pmos2 br en_bar vdd vdd p m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p +.ENDS sram_precharge_0 + +.SUBCKT sram_precharge_array ++ bl_0 br_0 bl_1 br_1 en_bar vdd +* OUTPUT: bl_0 +* OUTPUT: br_0 +* OUTPUT: bl_1 +* OUTPUT: br_1 +* INPUT : en_bar +* POWER : vdd +* cols: 2 size: 1 bl: bl br: br +Xpre_column_0 ++ bl_0 br_0 en_bar vdd ++ sram_precharge_0 +Xpre_column_1 ++ bl_1 br_1 en_bar vdd ++ sram_precharge_0 +.ENDS sram_precharge_array +*********************** "sense_amp" ****************************** + +.SUBCKT sense_amp bl br dout en vdd gnd + +* SPICE3 file created from sense_amp.ext - technology: scmos + +M1000 gnd en a_56_432# gnd n w=1.8u l=0.4u +M1001 a_56_432# a_48_304# dint gnd n w=1.8u l=0.4u +M1002 a_48_304# dint a_56_432# gnd n w=1.8u l=0.4u +M1003 vdd a_48_304# dint vdd p w=3.6u l=0.4u +M1004 a_48_304# dint vdd vdd p w=3.6u l=0.4u +M1005 bl en dint vdd p w=4.8u l=0.4u +M1006 a_48_304# en br vdd p w=4.8u l=0.4u + +M1007 dout_bar dint vdd vdd p w=1.6u l=0.4u +M1008 gnd dint dout_bar gnd n w=0.8u l=0.4u +M1009 dout dout_bar vdd vdd p w=4.8u l=0.4u +M1010 gnd dout_bar dout gnd n w=2.4u l=0.4u +.ENDS + +.SUBCKT sram_sense_amp_array ++ data_0 bl_0 br_0 en vdd gnd +* OUTPUT: data_0 +* INPUT : bl_0 +* INPUT : br_0 +* INPUT : en +* POWER : vdd +* GROUND: gnd +* words_per_row: 1 +Xsa_d0 ++ bl_0 br_0 data_0 en vdd gnd ++ sense_amp +.ENDS sram_sense_amp_array + +.SUBCKT sram_port_data ++ rbl_bl rbl_br bl_0 br_0 dout_0 din_0 s_en p_en_bar w_en vdd gnd +* INOUT : rbl_bl +* INOUT : rbl_br +* INOUT : bl_0 +* INOUT : br_0 +* OUTPUT: dout_0 +* INPUT : din_0 +* INPUT : s_en +* INPUT : p_en_bar +* INPUT : w_en +* POWER : vdd +* GROUND: gnd +Xprecharge_array0 ++ rbl_bl rbl_br bl_0 br_0 p_en_bar vdd ++ sram_precharge_array +Xsense_amp_array0 ++ dout_0 bl_0 br_0 s_en vdd gnd ++ sram_sense_amp_array +Xwrite_driver_array0 ++ din_0 bl_0 br_0 w_en vdd gnd ++ sram_write_driver_array +.ENDS sram_port_data + +*********************** "cell_1rw" ****************************** +.SUBCKT cell_1rw bl br wl vdd gnd +* SPICE3 file created from cell_1rw.ext - technology: scmos + +* Inverter 1 +M1000 Q Q_bar vdd vdd p w=0.6u l=0.8u +M1002 Q Q_bar gnd gnd n w=1.6u l=0.4u + +* Inverter 2 +M1001 vdd Q Q_bar vdd p w=0.6u l=0.8u +M1003 gnd Q Q_bar gnd n w=1.6u l=0.4u + +* Access transistors +M1004 Q wl bl gnd n w=0.8u l=0.4u +M1005 Q_bar wl br gnd n w=0.8u l=0.4u + +.ENDS + +.SUBCKT sram_bitcell_array ++ bl_0_0 br_0_0 wl_0_0 wl_0_1 wl_0_2 wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 ++ wl_0_8 wl_0_9 wl_0_10 wl_0_11 wl_0_12 wl_0_13 wl_0_14 wl_0_15 vdd gnd +* INOUT : bl_0_0 +* INOUT : br_0_0 +* INPUT : wl_0_0 +* INPUT : wl_0_1 +* INPUT : wl_0_2 +* INPUT : wl_0_3 +* INPUT : wl_0_4 +* INPUT : wl_0_5 +* INPUT : wl_0_6 +* INPUT : wl_0_7 +* INPUT : wl_0_8 +* INPUT : wl_0_9 +* INPUT : wl_0_10 +* INPUT : wl_0_11 +* INPUT : wl_0_12 +* INPUT : wl_0_13 +* INPUT : wl_0_14 +* INPUT : wl_0_15 +* POWER : vdd +* GROUND: gnd +* rows: 16 cols: 1 +Xbit_r0_c0 ++ bl_0_0 br_0_0 wl_0_0 vdd gnd ++ cell_1rw +Xbit_r1_c0 ++ bl_0_0 br_0_0 wl_0_1 vdd gnd ++ cell_1rw +Xbit_r2_c0 ++ bl_0_0 br_0_0 wl_0_2 vdd gnd ++ cell_1rw +Xbit_r3_c0 ++ bl_0_0 br_0_0 wl_0_3 vdd gnd ++ cell_1rw +Xbit_r4_c0 ++ bl_0_0 br_0_0 wl_0_4 vdd gnd ++ cell_1rw +Xbit_r5_c0 ++ bl_0_0 br_0_0 wl_0_5 vdd gnd ++ cell_1rw +Xbit_r6_c0 ++ bl_0_0 br_0_0 wl_0_6 vdd gnd ++ cell_1rw +Xbit_r7_c0 ++ bl_0_0 br_0_0 wl_0_7 vdd gnd ++ cell_1rw +Xbit_r8_c0 ++ bl_0_0 br_0_0 wl_0_8 vdd gnd ++ cell_1rw +Xbit_r9_c0 ++ bl_0_0 br_0_0 wl_0_9 vdd gnd ++ cell_1rw +Xbit_r10_c0 ++ bl_0_0 br_0_0 wl_0_10 vdd gnd ++ cell_1rw +Xbit_r11_c0 ++ bl_0_0 br_0_0 wl_0_11 vdd gnd ++ cell_1rw +Xbit_r12_c0 ++ bl_0_0 br_0_0 wl_0_12 vdd gnd ++ cell_1rw +Xbit_r13_c0 ++ bl_0_0 br_0_0 wl_0_13 vdd gnd ++ cell_1rw +Xbit_r14_c0 ++ bl_0_0 br_0_0 wl_0_14 vdd gnd ++ cell_1rw +Xbit_r15_c0 ++ bl_0_0 br_0_0 wl_0_15 vdd gnd ++ cell_1rw +.ENDS sram_bitcell_array + +*********************** "dummy_cell_1rw" ****************************** +.SUBCKT dummy_cell_1rw bl br wl vdd gnd + +* Inverter 1 +M1000 Q Q_bar vdd vdd p w=0.6u l=0.8u +M1002 Q Q_bar gnd gnd n w=1.6u l=0.4u + +* Inverter 2 +M1001 vdd Q Q_bar vdd p w=0.6u l=0.8u +M1003 gnd Q Q_bar gnd n w=1.6u l=0.4u + +* Access transistors +M1004 Q wl bl_noconn gnd n w=0.8u l=0.4u +M1005 Q_bar wl br_noconn gnd n w=0.8u l=0.4u + +.ENDS + +.SUBCKT sram_dummy_array ++ bl_0_0 br_0_0 wl_0_0 vdd gnd +* INOUT : bl_0_0 +* INOUT : br_0_0 +* INPUT : wl_0_0 +* POWER : vdd +* GROUND: gnd +Xbit_r0_c0 ++ bl_0_0 br_0_0 wl_0_0 vdd gnd ++ dummy_cell_1rw +.ENDS sram_dummy_array + +*********************** "cell_1rw" ****************************** +.SUBCKT replica_cell_1rw bl br wl vdd gnd +* SPICE3 file created from cell_1rw.ext - technology: scmos + +* Inverter 1 +M1000 Q vdd vdd vdd p w=0.6u l=0.8u +M1002 Q vdd gnd gnd n w=1.6u l=0.4u + +* Inverter 2 +M1001 vdd Q vdd vdd p w=0.6u l=0.8u +M1003 gnd Q vdd gnd n w=1.6u l=0.4u + +* Access transistors +M1004 Q wl bl gnd n w=0.8u l=0.4u +M1005 vdd wl br gnd n w=0.8u l=0.4u + +.ENDS + +.SUBCKT sram_replica_column ++ bl_0_0 br_0_0 wl_0_0 wl_0_1 wl_0_2 wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 ++ wl_0_8 wl_0_9 wl_0_10 wl_0_11 wl_0_12 wl_0_13 wl_0_14 wl_0_15 wl_0_16 ++ vdd gnd +* OUTPUT: bl_0_0 +* OUTPUT: br_0_0 +* INPUT : wl_0_0 +* INPUT : wl_0_1 +* INPUT : wl_0_2 +* INPUT : wl_0_3 +* INPUT : wl_0_4 +* INPUT : wl_0_5 +* INPUT : wl_0_6 +* INPUT : wl_0_7 +* INPUT : wl_0_8 +* INPUT : wl_0_9 +* INPUT : wl_0_10 +* INPUT : wl_0_11 +* INPUT : wl_0_12 +* INPUT : wl_0_13 +* INPUT : wl_0_14 +* INPUT : wl_0_15 +* INPUT : wl_0_16 +* POWER : vdd +* GROUND: gnd +Xrbc_0 ++ bl_0_0 br_0_0 wl_0_0 vdd gnd ++ replica_cell_1rw +Xrbc_1 ++ bl_0_0 br_0_0 wl_0_1 vdd gnd ++ replica_cell_1rw +Xrbc_2 ++ bl_0_0 br_0_0 wl_0_2 vdd gnd ++ replica_cell_1rw +Xrbc_3 ++ bl_0_0 br_0_0 wl_0_3 vdd gnd ++ replica_cell_1rw +Xrbc_4 ++ bl_0_0 br_0_0 wl_0_4 vdd gnd ++ replica_cell_1rw +Xrbc_5 ++ bl_0_0 br_0_0 wl_0_5 vdd gnd ++ replica_cell_1rw +Xrbc_6 ++ bl_0_0 br_0_0 wl_0_6 vdd gnd ++ replica_cell_1rw +Xrbc_7 ++ bl_0_0 br_0_0 wl_0_7 vdd gnd ++ replica_cell_1rw +Xrbc_8 ++ bl_0_0 br_0_0 wl_0_8 vdd gnd ++ replica_cell_1rw +Xrbc_9 ++ bl_0_0 br_0_0 wl_0_9 vdd gnd ++ replica_cell_1rw +Xrbc_10 ++ bl_0_0 br_0_0 wl_0_10 vdd gnd ++ replica_cell_1rw +Xrbc_11 ++ bl_0_0 br_0_0 wl_0_11 vdd gnd ++ replica_cell_1rw +Xrbc_12 ++ bl_0_0 br_0_0 wl_0_12 vdd gnd ++ replica_cell_1rw +Xrbc_13 ++ bl_0_0 br_0_0 wl_0_13 vdd gnd ++ replica_cell_1rw +Xrbc_14 ++ bl_0_0 br_0_0 wl_0_14 vdd gnd ++ replica_cell_1rw +Xrbc_15 ++ bl_0_0 br_0_0 wl_0_15 vdd gnd ++ replica_cell_1rw +Xrbc_16 ++ bl_0_0 br_0_0 wl_0_16 vdd gnd ++ replica_cell_1rw +.ENDS sram_replica_column + +.SUBCKT sram_replica_bitcell_array ++ rbl_bl_0_0 rbl_br_0_0 bl_0_0 br_0_0 rbl_wl_0_0 wl_0_0 wl_0_1 wl_0_2 ++ wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 wl_0_8 wl_0_9 wl_0_10 wl_0_11 ++ wl_0_12 wl_0_13 wl_0_14 wl_0_15 vdd gnd +* INOUT : rbl_bl_0_0 +* INOUT : rbl_br_0_0 +* INOUT : bl_0_0 +* INOUT : br_0_0 +* INPUT : rbl_wl_0_0 +* INPUT : wl_0_0 +* INPUT : wl_0_1 +* INPUT : wl_0_2 +* INPUT : wl_0_3 +* INPUT : wl_0_4 +* INPUT : wl_0_5 +* INPUT : wl_0_6 +* INPUT : wl_0_7 +* INPUT : wl_0_8 +* INPUT : wl_0_9 +* INPUT : wl_0_10 +* INPUT : wl_0_11 +* INPUT : wl_0_12 +* INPUT : wl_0_13 +* INPUT : wl_0_14 +* INPUT : wl_0_15 +* POWER : vdd +* GROUND: gnd +* rbl: [1, 0] left_rbl: [0] right_rbl: [] +Xbitcell_array ++ bl_0_0 br_0_0 wl_0_0 wl_0_1 wl_0_2 wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 ++ wl_0_8 wl_0_9 wl_0_10 wl_0_11 wl_0_12 wl_0_13 wl_0_14 wl_0_15 vdd gnd ++ sram_bitcell_array +Xreplica_col_0 ++ rbl_bl_0_0 rbl_br_0_0 rbl_wl_0_0 wl_0_0 wl_0_1 wl_0_2 wl_0_3 wl_0_4 ++ wl_0_5 wl_0_6 wl_0_7 wl_0_8 wl_0_9 wl_0_10 wl_0_11 wl_0_12 wl_0_13 ++ wl_0_14 wl_0_15 vdd gnd ++ sram_replica_column +Xdummy_row_0 ++ bl_0_0 br_0_0 rbl_wl_0_0 vdd gnd ++ sram_dummy_array +.ENDS sram_replica_bitcell_array + +.SUBCKT sram_dummy_array_2 ++ bl_0_0 br_0_0 wl_0_0 wl_0_1 wl_0_2 wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 ++ wl_0_8 wl_0_9 wl_0_10 wl_0_11 wl_0_12 wl_0_13 wl_0_14 wl_0_15 wl_0_16 ++ wl_0_17 wl_0_18 vdd gnd +* INOUT : bl_0_0 +* INOUT : br_0_0 +* INPUT : wl_0_0 +* INPUT : wl_0_1 +* INPUT : wl_0_2 +* INPUT : wl_0_3 +* INPUT : wl_0_4 +* INPUT : wl_0_5 +* INPUT : wl_0_6 +* INPUT : wl_0_7 +* INPUT : wl_0_8 +* INPUT : wl_0_9 +* INPUT : wl_0_10 +* INPUT : wl_0_11 +* INPUT : wl_0_12 +* INPUT : wl_0_13 +* INPUT : wl_0_14 +* INPUT : wl_0_15 +* INPUT : wl_0_16 +* INPUT : wl_0_17 +* INPUT : wl_0_18 +* POWER : vdd +* GROUND: gnd +Xbit_r0_c0 ++ bl_0_0 br_0_0 wl_0_0 vdd gnd ++ dummy_cell_1rw +Xbit_r1_c0 ++ bl_0_0 br_0_0 wl_0_1 vdd gnd ++ dummy_cell_1rw +Xbit_r2_c0 ++ bl_0_0 br_0_0 wl_0_2 vdd gnd ++ dummy_cell_1rw +Xbit_r3_c0 ++ bl_0_0 br_0_0 wl_0_3 vdd gnd ++ dummy_cell_1rw +Xbit_r4_c0 ++ bl_0_0 br_0_0 wl_0_4 vdd gnd ++ dummy_cell_1rw +Xbit_r5_c0 ++ bl_0_0 br_0_0 wl_0_5 vdd gnd ++ dummy_cell_1rw +Xbit_r6_c0 ++ bl_0_0 br_0_0 wl_0_6 vdd gnd ++ dummy_cell_1rw +Xbit_r7_c0 ++ bl_0_0 br_0_0 wl_0_7 vdd gnd ++ dummy_cell_1rw +Xbit_r8_c0 ++ bl_0_0 br_0_0 wl_0_8 vdd gnd ++ dummy_cell_1rw +Xbit_r9_c0 ++ bl_0_0 br_0_0 wl_0_9 vdd gnd ++ dummy_cell_1rw +Xbit_r10_c0 ++ bl_0_0 br_0_0 wl_0_10 vdd gnd ++ dummy_cell_1rw +Xbit_r11_c0 ++ bl_0_0 br_0_0 wl_0_11 vdd gnd ++ dummy_cell_1rw +Xbit_r12_c0 ++ bl_0_0 br_0_0 wl_0_12 vdd gnd ++ dummy_cell_1rw +Xbit_r13_c0 ++ bl_0_0 br_0_0 wl_0_13 vdd gnd ++ dummy_cell_1rw +Xbit_r14_c0 ++ bl_0_0 br_0_0 wl_0_14 vdd gnd ++ dummy_cell_1rw +Xbit_r15_c0 ++ bl_0_0 br_0_0 wl_0_15 vdd gnd ++ dummy_cell_1rw +Xbit_r16_c0 ++ bl_0_0 br_0_0 wl_0_16 vdd gnd ++ dummy_cell_1rw +Xbit_r17_c0 ++ bl_0_0 br_0_0 wl_0_17 vdd gnd ++ dummy_cell_1rw +Xbit_r18_c0 ++ bl_0_0 br_0_0 wl_0_18 vdd gnd ++ dummy_cell_1rw +.ENDS sram_dummy_array_2 + +.SUBCKT sram_dummy_array_0 ++ bl_0_0 br_0_0 bl_0_1 br_0_1 wl_0_0 vdd gnd +* INOUT : bl_0_0 +* INOUT : br_0_0 +* INOUT : bl_0_1 +* INOUT : br_0_1 +* INPUT : wl_0_0 +* POWER : vdd +* GROUND: gnd +Xbit_r0_c0 ++ bl_0_0 br_0_0 wl_0_0 vdd gnd ++ dummy_cell_1rw +Xbit_r0_c1 ++ bl_0_1 br_0_1 wl_0_0 vdd gnd ++ dummy_cell_1rw +.ENDS sram_dummy_array_0 + +.SUBCKT sram_dummy_array_3 ++ bl_0_0 br_0_0 wl_0_0 wl_0_1 wl_0_2 wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 ++ wl_0_8 wl_0_9 wl_0_10 wl_0_11 wl_0_12 wl_0_13 wl_0_14 wl_0_15 wl_0_16 ++ wl_0_17 wl_0_18 vdd gnd +* INOUT : bl_0_0 +* INOUT : br_0_0 +* INPUT : wl_0_0 +* INPUT : wl_0_1 +* INPUT : wl_0_2 +* INPUT : wl_0_3 +* INPUT : wl_0_4 +* INPUT : wl_0_5 +* INPUT : wl_0_6 +* INPUT : wl_0_7 +* INPUT : wl_0_8 +* INPUT : wl_0_9 +* INPUT : wl_0_10 +* INPUT : wl_0_11 +* INPUT : wl_0_12 +* INPUT : wl_0_13 +* INPUT : wl_0_14 +* INPUT : wl_0_15 +* INPUT : wl_0_16 +* INPUT : wl_0_17 +* INPUT : wl_0_18 +* POWER : vdd +* GROUND: gnd +Xbit_r0_c0 ++ bl_0_0 br_0_0 wl_0_0 vdd gnd ++ dummy_cell_1rw +Xbit_r1_c0 ++ bl_0_0 br_0_0 wl_0_1 vdd gnd ++ dummy_cell_1rw +Xbit_r2_c0 ++ bl_0_0 br_0_0 wl_0_2 vdd gnd ++ dummy_cell_1rw +Xbit_r3_c0 ++ bl_0_0 br_0_0 wl_0_3 vdd gnd ++ dummy_cell_1rw +Xbit_r4_c0 ++ bl_0_0 br_0_0 wl_0_4 vdd gnd ++ dummy_cell_1rw +Xbit_r5_c0 ++ bl_0_0 br_0_0 wl_0_5 vdd gnd ++ dummy_cell_1rw +Xbit_r6_c0 ++ bl_0_0 br_0_0 wl_0_6 vdd gnd ++ dummy_cell_1rw +Xbit_r7_c0 ++ bl_0_0 br_0_0 wl_0_7 vdd gnd ++ dummy_cell_1rw +Xbit_r8_c0 ++ bl_0_0 br_0_0 wl_0_8 vdd gnd ++ dummy_cell_1rw +Xbit_r9_c0 ++ bl_0_0 br_0_0 wl_0_9 vdd gnd ++ dummy_cell_1rw +Xbit_r10_c0 ++ bl_0_0 br_0_0 wl_0_10 vdd gnd ++ dummy_cell_1rw +Xbit_r11_c0 ++ bl_0_0 br_0_0 wl_0_11 vdd gnd ++ dummy_cell_1rw +Xbit_r12_c0 ++ bl_0_0 br_0_0 wl_0_12 vdd gnd ++ dummy_cell_1rw +Xbit_r13_c0 ++ bl_0_0 br_0_0 wl_0_13 vdd gnd ++ dummy_cell_1rw +Xbit_r14_c0 ++ bl_0_0 br_0_0 wl_0_14 vdd gnd ++ dummy_cell_1rw +Xbit_r15_c0 ++ bl_0_0 br_0_0 wl_0_15 vdd gnd ++ dummy_cell_1rw +Xbit_r16_c0 ++ bl_0_0 br_0_0 wl_0_16 vdd gnd ++ dummy_cell_1rw +Xbit_r17_c0 ++ bl_0_0 br_0_0 wl_0_17 vdd gnd ++ dummy_cell_1rw +Xbit_r18_c0 ++ bl_0_0 br_0_0 wl_0_18 vdd gnd ++ dummy_cell_1rw +.ENDS sram_dummy_array_3 + +.SUBCKT sram_dummy_array_1 ++ bl_0_0 br_0_0 bl_0_1 br_0_1 wl_0_0 vdd gnd +* INOUT : bl_0_0 +* INOUT : br_0_0 +* INOUT : bl_0_1 +* INOUT : br_0_1 +* INPUT : wl_0_0 +* POWER : vdd +* GROUND: gnd +Xbit_r0_c0 ++ bl_0_0 br_0_0 wl_0_0 vdd gnd ++ dummy_cell_1rw +Xbit_r0_c1 ++ bl_0_1 br_0_1 wl_0_0 vdd gnd ++ dummy_cell_1rw +.ENDS sram_dummy_array_1 + +.SUBCKT sram_capped_replica_bitcell_array ++ rbl_bl_0_0 rbl_br_0_0 bl_0_0 br_0_0 rbl_wl_0_0 wl_0_0 wl_0_1 wl_0_2 ++ wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 wl_0_8 wl_0_9 wl_0_10 wl_0_11 ++ wl_0_12 wl_0_13 wl_0_14 wl_0_15 vdd gnd +* INOUT : rbl_bl_0_0 +* INOUT : rbl_br_0_0 +* INOUT : bl_0_0 +* INOUT : br_0_0 +* INPUT : rbl_wl_0_0 +* INPUT : wl_0_0 +* INPUT : wl_0_1 +* INPUT : wl_0_2 +* INPUT : wl_0_3 +* INPUT : wl_0_4 +* INPUT : wl_0_5 +* INPUT : wl_0_6 +* INPUT : wl_0_7 +* INPUT : wl_0_8 +* INPUT : wl_0_9 +* INPUT : wl_0_10 +* INPUT : wl_0_11 +* INPUT : wl_0_12 +* INPUT : wl_0_13 +* INPUT : wl_0_14 +* INPUT : wl_0_15 +* POWER : vdd +* GROUND: gnd +* rbl: [1, 0] left_rbl: [0] right_rbl: [] +Xreplica_bitcell_array ++ rbl_bl_0_0 rbl_br_0_0 bl_0_0 br_0_0 rbl_wl_0_0 wl_0_0 wl_0_1 wl_0_2 ++ wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 wl_0_8 wl_0_9 wl_0_10 wl_0_11 ++ wl_0_12 wl_0_13 wl_0_14 wl_0_15 vdd gnd ++ sram_replica_bitcell_array +Xdummy_row_bot ++ rbl_bl_0_0 rbl_br_0_0 bl_0_0 br_0_0 gnd vdd gnd ++ sram_dummy_array_1 +Xdummy_row_top ++ rbl_bl_0_0 rbl_br_0_0 bl_0_0 br_0_0 gnd vdd gnd ++ sram_dummy_array_0 +Xdummy_col_left ++ dummy_left_bl_0_0 dummy_left_br_0_0 gnd rbl_wl_0_0 wl_0_0 wl_0_1 ++ wl_0_2 wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 wl_0_8 wl_0_9 wl_0_10 ++ wl_0_11 wl_0_12 wl_0_13 wl_0_14 wl_0_15 gnd vdd gnd ++ sram_dummy_array_2 +Xdummy_col_right ++ dummy_right_bl_0_0 dummy_right_br_0_0 gnd rbl_wl_0_0 wl_0_0 wl_0_1 ++ wl_0_2 wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 wl_0_8 wl_0_9 wl_0_10 ++ wl_0_11 wl_0_12 wl_0_13 wl_0_14 wl_0_15 gnd vdd gnd ++ sram_dummy_array_3 +.ENDS sram_capped_replica_bitcell_array + +.SUBCKT sram_bank ++ dout0_0 rbl_bl_0_0 din0_0 addr0_0 addr0_1 addr0_2 addr0_3 s_en0 ++ p_en_bar0 w_en0 wl_en0 vdd gnd +* OUTPUT: dout0_0 +* OUTPUT: rbl_bl_0_0 +* INPUT : din0_0 +* INPUT : addr0_0 +* INPUT : addr0_1 +* INPUT : addr0_2 +* INPUT : addr0_3 +* INPUT : s_en0 +* INPUT : p_en_bar0 +* INPUT : w_en0 +* INPUT : wl_en0 +* POWER : vdd +* GROUND: gnd +Xbitcell_array ++ rbl_bl_0_0 rbl_br_0_0 bl_0_0 br_0_0 rbl_wl0 wl_0_0 wl_0_1 wl_0_2 ++ wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 wl_0_8 wl_0_9 wl_0_10 wl_0_11 ++ wl_0_12 wl_0_13 wl_0_14 wl_0_15 vdd gnd ++ sram_capped_replica_bitcell_array +Xport_data0 ++ rbl_bl_0_0 rbl_br_0_0 bl_0_0 br_0_0 dout0_0 din0_0 s_en0 p_en_bar0 ++ w_en0 vdd gnd ++ sram_port_data +Xport_address0 ++ addr0_0 addr0_1 addr0_2 addr0_3 wl_en0 wl_0_0 wl_0_1 wl_0_2 wl_0_3 ++ wl_0_4 wl_0_5 wl_0_6 wl_0_7 wl_0_8 wl_0_9 wl_0_10 wl_0_11 wl_0_12 ++ wl_0_13 wl_0_14 wl_0_15 rbl_wl0 vdd gnd ++ sram_port_address +.ENDS sram_bank +*********************** "dff" ****************************** +* Positive edge-triggered FF +.SUBCKT dff D Q clk vdd gnd + +* SPICE3 file created from dff.ext - technology: scmos + +M1000 vdd clk a_24_24# vdd p w=8u l=0.4u +M1001 a_84_296# D vdd vdd p w=4u l=0.4u +M1002 a_104_24# clk a_84_296# vdd p w=4u l=0.4u +M1003 a_140_296# a_24_24# a_104_24# vdd p w=4u l=0.4u +M1004 vdd a_152_16# a_140_296# vdd p w=4u l=0.4u +M1005 a_152_16# a_104_24# vdd vdd p w=4u l=0.4u +M1006 a_260_296# a_152_16# vdd vdd p w=4u l=0.4u +M1007 a_280_24# a_24_24# a_260_296# vdd p w=4u l=0.4u +M1008 a_320_336# clk a_280_24# vdd p w=2u l=0.4u +M1009 vdd Q a_320_336# vdd p w=2u l=0.4u +M1010 gnd clk a_24_24# gnd n w=4u l=0.4u +M1011 Q a_280_24# vdd vdd p w=8u l=0.4u +M1012 a_84_24# D gnd gnd n w=2u l=0.4u +M1013 a_104_24# a_24_24# a_84_24# gnd n w=2u l=0.4u +M1014 a_140_24# clk a_104_24# gnd n w=2u l=0.4u +M1015 gnd a_152_16# a_140_24# gnd n w=2u l=0.4u +M1016 a_152_16# a_104_24# gnd gnd n w=2u l=0.4u +M1017 a_260_24# a_152_16# gnd gnd n w=2u l=0.4u +M1018 a_280_24# clk a_260_24# gnd n w=2u l=0.4u +M1019 a_320_24# a_24_24# a_280_24# gnd n w=2u l=0.4u +M1020 gnd Q a_320_24# gnd n w=2u l=0.4u +M1021 Q a_280_24# gnd gnd n w=4u l=0.4u + +.ENDS + +.SUBCKT sram_row_addr_dff ++ din_0 din_1 din_2 din_3 dout_0 dout_1 dout_2 dout_3 clk vdd gnd +* INPUT : din_0 +* INPUT : din_1 +* INPUT : din_2 +* INPUT : din_3 +* OUTPUT: dout_0 +* OUTPUT: dout_1 +* OUTPUT: dout_2 +* OUTPUT: dout_3 +* INPUT : clk +* POWER : vdd +* GROUND: gnd +* rows: 4 cols: 1 +Xdff_r0_c0 ++ din_0 dout_0 clk vdd gnd ++ dff +Xdff_r1_c0 ++ din_1 dout_1 clk vdd gnd ++ dff +Xdff_r2_c0 ++ din_2 dout_2 clk vdd gnd ++ dff +Xdff_r3_c0 ++ din_3 dout_3 clk vdd gnd ++ dff +.ENDS sram_row_addr_dff + +* spice ptx M{0} {1} n m=3 w=3.2u l=0.4u pd=7.20u ps=7.20u as=3.20p ad=3.20p + +* spice ptx M{0} {1} p m=3 w=6.4u l=0.4u pd=13.60u ps=13.60u as=6.40p ad=6.40p + +.SUBCKT sram_pinv_2 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +Mpinv_pmos Z A vdd vdd p m=3 w=6.4u l=0.4u pd=13.60u ps=13.60u as=6.40p ad=6.40p +Mpinv_nmos Z A gnd gnd n m=3 w=3.2u l=0.4u pd=7.20u ps=7.20u as=3.20p ad=3.20p +.ENDS sram_pinv_2 + +.SUBCKT sram_pdriver ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* sizes: [12] +Xbuf_inv1 ++ A Z vdd gnd ++ sram_pinv_2 +.ENDS sram_pdriver + +.SUBCKT sram_pnand2_0 ++ A B Z vdd gnd +* INPUT : A +* INPUT : B +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +Mpnand2_pmos1 vdd A Z vdd p m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p +Mpnand2_pmos2 Z B vdd vdd p m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p +Mpnand2_nmos1 Z B net1 gnd n m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p +Mpnand2_nmos2 net1 A gnd gnd n m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p +.ENDS sram_pnand2_0 + +.SUBCKT sram_pand2 ++ A B Z vdd gnd +* INPUT : A +* INPUT : B +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +Xpand2_nand ++ A B zb_int vdd gnd ++ sram_pnand2_0 +Xpand2_inv ++ zb_int Z vdd gnd ++ sram_pdriver +.ENDS sram_pand2 + +.SUBCKT sram_pinv_10 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +Mpinv_pmos Z A vdd vdd p m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p +Mpinv_nmos Z A gnd gnd n m=1 w=0.8u l=0.4u pd=2.40u ps=2.40u as=0.80p ad=0.80p +.ENDS sram_pinv_10 + +.SUBCKT sram_delay_chain ++ in out vdd gnd +* INPUT : in +* OUTPUT: out +* POWER : vdd +* GROUND: gnd +* fanouts: [4, 4, 4, 4, 4, 4, 4, 4, 4] +Xdinv0 ++ in dout_1 vdd gnd ++ sram_pinv_10 +Xdload_0_0 ++ dout_1 n_0_0 vdd gnd ++ sram_pinv_10 +Xdload_0_1 ++ dout_1 n_0_1 vdd gnd ++ sram_pinv_10 +Xdload_0_2 ++ dout_1 n_0_2 vdd gnd ++ sram_pinv_10 +Xdload_0_3 ++ dout_1 n_0_3 vdd gnd ++ sram_pinv_10 +Xdinv1 ++ dout_1 dout_2 vdd gnd ++ sram_pinv_10 +Xdload_1_0 ++ dout_2 n_1_0 vdd gnd ++ sram_pinv_10 +Xdload_1_1 ++ dout_2 n_1_1 vdd gnd ++ sram_pinv_10 +Xdload_1_2 ++ dout_2 n_1_2 vdd gnd ++ sram_pinv_10 +Xdload_1_3 ++ dout_2 n_1_3 vdd gnd ++ sram_pinv_10 +Xdinv2 ++ dout_2 dout_3 vdd gnd ++ sram_pinv_10 +Xdload_2_0 ++ dout_3 n_2_0 vdd gnd ++ sram_pinv_10 +Xdload_2_1 ++ dout_3 n_2_1 vdd gnd ++ sram_pinv_10 +Xdload_2_2 ++ dout_3 n_2_2 vdd gnd ++ sram_pinv_10 +Xdload_2_3 ++ dout_3 n_2_3 vdd gnd ++ sram_pinv_10 +Xdinv3 ++ dout_3 dout_4 vdd gnd ++ sram_pinv_10 +Xdload_3_0 ++ dout_4 n_3_0 vdd gnd ++ sram_pinv_10 +Xdload_3_1 ++ dout_4 n_3_1 vdd gnd ++ sram_pinv_10 +Xdload_3_2 ++ dout_4 n_3_2 vdd gnd ++ sram_pinv_10 +Xdload_3_3 ++ dout_4 n_3_3 vdd gnd ++ sram_pinv_10 +Xdinv4 ++ dout_4 dout_5 vdd gnd ++ sram_pinv_10 +Xdload_4_0 ++ dout_5 n_4_0 vdd gnd ++ sram_pinv_10 +Xdload_4_1 ++ dout_5 n_4_1 vdd gnd ++ sram_pinv_10 +Xdload_4_2 ++ dout_5 n_4_2 vdd gnd ++ sram_pinv_10 +Xdload_4_3 ++ dout_5 n_4_3 vdd gnd ++ sram_pinv_10 +Xdinv5 ++ dout_5 dout_6 vdd gnd ++ sram_pinv_10 +Xdload_5_0 ++ dout_6 n_5_0 vdd gnd ++ sram_pinv_10 +Xdload_5_1 ++ dout_6 n_5_1 vdd gnd ++ sram_pinv_10 +Xdload_5_2 ++ dout_6 n_5_2 vdd gnd ++ sram_pinv_10 +Xdload_5_3 ++ dout_6 n_5_3 vdd gnd ++ sram_pinv_10 +Xdinv6 ++ dout_6 dout_7 vdd gnd ++ sram_pinv_10 +Xdload_6_0 ++ dout_7 n_6_0 vdd gnd ++ sram_pinv_10 +Xdload_6_1 ++ dout_7 n_6_1 vdd gnd ++ sram_pinv_10 +Xdload_6_2 ++ dout_7 n_6_2 vdd gnd ++ sram_pinv_10 +Xdload_6_3 ++ dout_7 n_6_3 vdd gnd ++ sram_pinv_10 +Xdinv7 ++ dout_7 dout_8 vdd gnd ++ sram_pinv_10 +Xdload_7_0 ++ dout_8 n_7_0 vdd gnd ++ sram_pinv_10 +Xdload_7_1 ++ dout_8 n_7_1 vdd gnd ++ sram_pinv_10 +Xdload_7_2 ++ dout_8 n_7_2 vdd gnd ++ sram_pinv_10 +Xdload_7_3 ++ dout_8 n_7_3 vdd gnd ++ sram_pinv_10 +Xdinv8 ++ dout_8 out vdd gnd ++ sram_pinv_10 +Xdload_8_0 ++ out n_8_0 vdd gnd ++ sram_pinv_10 +Xdload_8_1 ++ out n_8_1 vdd gnd ++ sram_pinv_10 +Xdload_8_2 ++ out n_8_2 vdd gnd ++ sram_pinv_10 +Xdload_8_3 ++ out n_8_3 vdd gnd ++ sram_pinv_10 +.ENDS sram_delay_chain + +.SUBCKT sram_pinv_5 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +Mpinv_pmos Z A vdd vdd p m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p +Mpinv_nmos Z A gnd gnd n m=1 w=0.8u l=0.4u pd=2.40u ps=2.40u as=0.80p ad=0.80p +.ENDS sram_pinv_5 + +.SUBCKT sram_pdriver_4 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* sizes: [1, 1] +Xbuf_inv1 ++ A Zb1_int vdd gnd ++ sram_pinv_5 +Xbuf_inv2 ++ Zb1_int Z vdd gnd ++ sram_pinv_5 +.ENDS sram_pdriver_4 + +* spice ptx M{0} {1} n m=1 w=3.2u l=0.4u pd=7.20u ps=7.20u as=3.20p ad=3.20p + +* spice ptx M{0} {1} p m=1 w=6.4u l=0.4u pd=13.60u ps=13.60u as=6.40p ad=6.40p + +.SUBCKT sram_pinv_1 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +Mpinv_pmos Z A vdd vdd p m=1 w=6.4u l=0.4u pd=13.60u ps=13.60u as=6.40p ad=6.40p +Mpinv_nmos Z A gnd gnd n m=1 w=3.2u l=0.4u pd=7.20u ps=7.20u as=3.20p ad=3.20p +.ENDS sram_pinv_1 + +* spice ptx M{0} {1} n m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p + +* spice ptx M{0} {1} p m=1 w=3.2u l=0.4u pd=7.20u ps=7.20u as=3.20p ad=3.20p + +.SUBCKT sram_pinv_0 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +Mpinv_pmos Z A vdd vdd p m=1 w=3.2u l=0.4u pd=7.20u ps=7.20u as=3.20p ad=3.20p +Mpinv_nmos Z A gnd gnd n m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p +.ENDS sram_pinv_0 + +.SUBCKT sram_dff_buf_0 ++ D Q Qb clk vdd gnd +* INPUT : D +* OUTPUT: Q +* OUTPUT: Qb +* INPUT : clk +* POWER : vdd +* GROUND: gnd +* inv1: 2 inv2: 4 +Xdff_buf_dff ++ D qint clk vdd gnd ++ dff +Xdff_buf_inv1 ++ qint Qb vdd gnd ++ sram_pinv_0 +Xdff_buf_inv2 ++ Qb Q vdd gnd ++ sram_pinv_1 +.ENDS sram_dff_buf_0 + +.SUBCKT sram_dff_buf_array ++ din_0 din_1 dout_0 dout_bar_0 dout_1 dout_bar_1 clk vdd gnd +* INPUT : din_0 +* INPUT : din_1 +* OUTPUT: dout_0 +* OUTPUT: dout_bar_0 +* OUTPUT: dout_1 +* OUTPUT: dout_bar_1 +* INPUT : clk +* POWER : vdd +* GROUND: gnd +* inv1: 2 inv2: 4 +Xdff_r0_c0 ++ din_0 dout_0 dout_bar_0 clk vdd gnd ++ sram_dff_buf_0 +Xdff_r1_c0 ++ din_1 dout_1 dout_bar_1 clk vdd gnd ++ sram_dff_buf_0 +.ENDS sram_dff_buf_array + +* spice ptx M{0} {1} p m=2 w=7.2u l=0.4u pd=15.20u ps=15.20u as=7.20p ad=7.20p + +* spice ptx M{0} {1} n m=2 w=3.6u l=0.4u pd=8.00u ps=8.00u as=3.60p ad=3.60p + +.SUBCKT sram_pinv_9 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +Mpinv_pmos Z A vdd vdd p m=2 w=7.2u l=0.4u pd=15.20u ps=15.20u as=7.20p ad=7.20p +Mpinv_nmos Z A gnd gnd n m=2 w=3.6u l=0.4u pd=8.00u ps=8.00u as=3.60p ad=3.60p +.ENDS sram_pinv_9 + +.SUBCKT sram_pdriver_2 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* sizes: [9] +Xbuf_inv1 ++ A Z vdd gnd ++ sram_pinv_9 +.ENDS sram_pdriver_2 + +* spice ptx M{0} {1} n m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p + +.SUBCKT sram_pnand3_0 ++ A B C Z vdd gnd +* INPUT : A +* INPUT : B +* INPUT : C +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +Mpnand3_pmos1 vdd A Z vdd p m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p +Mpnand3_pmos2 Z B vdd vdd p m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p +Mpnand3_pmos3 Z C vdd vdd p m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p +Mpnand3_nmos1 Z C net1 gnd n m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p +Mpnand3_nmos2 net1 B net2 gnd n m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p +Mpnand3_nmos3 net2 A gnd gnd n m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p +.ENDS sram_pnand3_0 + +.SUBCKT sram_pand3 ++ A B C Z vdd gnd +* INPUT : A +* INPUT : B +* INPUT : C +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +Xpand3_nand ++ A B C zb_int vdd gnd ++ sram_pnand3_0 +Xpand3_inv ++ zb_int Z vdd gnd ++ sram_pdriver_2 +.ENDS sram_pand3 + +.SUBCKT sram_pinv_3 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +Mpinv_pmos Z A vdd vdd p m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p +Mpinv_nmos Z A gnd gnd n m=1 w=0.8u l=0.4u pd=2.40u ps=2.40u as=0.80p ad=0.80p +.ENDS sram_pinv_3 + +* spice ptx M{0} {1} p m=1 w=8.0u l=0.4u pd=16.80u ps=16.80u as=8.00p ad=8.00p + +* spice ptx M{0} {1} n m=1 w=4.0u l=0.4u pd=8.80u ps=8.80u as=4.00p ad=4.00p + +.SUBCKT sram_pinv_8 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +Mpinv_pmos Z A vdd vdd p m=1 w=8.0u l=0.4u pd=16.80u ps=16.80u as=8.00p ad=8.00p +Mpinv_nmos Z A gnd gnd n m=1 w=4.0u l=0.4u pd=8.80u ps=8.80u as=4.00p ad=4.00p +.ENDS sram_pinv_8 + +.SUBCKT sram_pdriver_1 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* sizes: [1, 5] +Xbuf_inv1 ++ A Zb1_int vdd gnd ++ sram_pinv_5 +Xbuf_inv2 ++ Zb1_int Z vdd gnd ++ sram_pinv_8 +.ENDS sram_pdriver_1 + +.SUBCKT sram_pdriver_3 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* sizes: [1] +Xbuf_inv1 ++ A Z vdd gnd ++ sram_pinv_5 +.ENDS sram_pdriver_3 + +.SUBCKT sram_pand3_0 ++ A B C Z vdd gnd +* INPUT : A +* INPUT : B +* INPUT : C +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +Xpand3_nand ++ A B C zb_int vdd gnd ++ sram_pnand3_0 +Xpand3_inv ++ zb_int Z vdd gnd ++ sram_pdriver_3 +.ENDS sram_pand3_0 + +.SUBCKT sram_pnand2_1 ++ A B Z vdd gnd +* INPUT : A +* INPUT : B +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +Mpnand2_pmos1 vdd A Z vdd p m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p +Mpnand2_pmos2 Z B vdd vdd p m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p +Mpnand2_nmos1 Z B net1 gnd n m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p +Mpnand2_nmos2 net1 A gnd gnd n m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p +.ENDS sram_pnand2_1 + +* spice ptx M{0} {1} p m=3 w=6.9u l=0.4u pd=14.60u ps=14.60u as=6.90p ad=6.90p + +* spice ptx M{0} {1} n m=3 w=3.5u l=0.4u pd=7.80u ps=7.80u as=3.50p ad=3.50p + +.SUBCKT sram_pinv_7 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +Mpinv_pmos Z A vdd vdd p m=3 w=6.9u l=0.4u pd=14.60u ps=14.60u as=6.90p ad=6.90p +Mpinv_nmos Z A gnd gnd n m=3 w=3.5u l=0.4u pd=7.80u ps=7.80u as=3.50p ad=3.50p +.ENDS sram_pinv_7 + +.SUBCKT sram_pinv_6 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +Mpinv_pmos Z A vdd vdd p m=1 w=6.4u l=0.4u pd=13.60u ps=13.60u as=6.40p ad=6.40p +Mpinv_nmos Z A gnd gnd n m=1 w=3.2u l=0.4u pd=7.20u ps=7.20u as=3.20p ad=3.20p +.ENDS sram_pinv_6 + +.SUBCKT sram_pdriver_0 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* sizes: [1, 1, 4, 13] +Xbuf_inv1 ++ A Zb1_int vdd gnd ++ sram_pinv_5 +Xbuf_inv2 ++ Zb1_int Zb2_int vdd gnd ++ sram_pinv_5 +Xbuf_inv3 ++ Zb2_int Zb3_int vdd gnd ++ sram_pinv_6 +Xbuf_inv4 ++ Zb3_int Z vdd gnd ++ sram_pinv_7 +.ENDS sram_pdriver_0 + +.SUBCKT sram_control_logic_rw ++ csb web clk rbl_bl s_en w_en p_en_bar wl_en clk_buf vdd gnd +* INPUT : csb +* INPUT : web +* INPUT : clk +* INPUT : rbl_bl +* OUTPUT: s_en +* OUTPUT: w_en +* OUTPUT: p_en_bar +* OUTPUT: wl_en +* OUTPUT: clk_buf +* POWER : vdd +* GROUND: gnd +* word_size 1 +Xctrl_dffs ++ csb web cs_bar cs we_bar we clk_buf vdd gnd ++ sram_dff_buf_array +Xclkbuf ++ clk clk_buf vdd gnd ++ sram_pdriver_0 +Xinv_clk_bar ++ clk_buf clk_bar vdd gnd ++ sram_pinv_3 +Xand2_gated_clk_bar ++ clk_bar cs gated_clk_bar vdd gnd ++ sram_pand2 +Xand2_gated_clk_buf ++ clk_buf cs gated_clk_buf vdd gnd ++ sram_pand2 +Xbuf_wl_en ++ gated_clk_bar wl_en vdd gnd ++ sram_pdriver_1 +Xrbl_bl_delay_inv ++ rbl_bl_delay rbl_bl_delay_bar vdd gnd ++ sram_pinv_3 +Xw_en_and ++ we rbl_bl_delay_bar gated_clk_bar w_en vdd gnd ++ sram_pand3 +Xbuf_s_en_and ++ rbl_bl_delay gated_clk_bar we_bar s_en vdd gnd ++ sram_pand3_0 +Xdelay_chain ++ rbl_bl rbl_bl_delay vdd gnd ++ sram_delay_chain +Xnand_p_en_bar ++ gated_clk_buf rbl_bl_delay p_en_bar_unbuf vdd gnd ++ sram_pnand2_1 +Xbuf_p_en_bar ++ p_en_bar_unbuf p_en_bar vdd gnd ++ sram_pdriver_4 +.ENDS sram_control_logic_rw + +.SUBCKT sram_data_dff ++ din_0 dout_0 clk vdd gnd +* INPUT : din_0 +* OUTPUT: dout_0 +* INPUT : clk +* POWER : vdd +* GROUND: gnd +* rows: 1 cols: 1 +Xdff_r0_c0 ++ din_0 dout_0 clk vdd gnd ++ dff +.ENDS sram_data_dff + +.SUBCKT sram ++ din0[0] addr0[0] addr0[1] addr0[2] addr0[3] csb0 web0 clk0 dout0[0] ++ vdd gnd +* INPUT : din0[0] +* INPUT : addr0[0] +* INPUT : addr0[1] +* INPUT : addr0[2] +* INPUT : addr0[3] +* INPUT : csb0 +* INPUT : web0 +* INPUT : clk0 +* OUTPUT: dout0[0] +* POWER : vdd +* GROUND: gnd +Xbank0 ++ dout0[0] rbl_bl0 bank_din0_0 a0_0 a0_1 a0_2 a0_3 s_en0 p_en_bar0 w_en0 ++ wl_en0 vdd gnd ++ sram_bank +Xcontrol0 ++ csb0 web0 clk0 rbl_bl0 s_en0 w_en0 p_en_bar0 wl_en0 clk_buf0 vdd gnd ++ sram_control_logic_rw +Xrow_address0 ++ addr0[0] addr0[1] addr0[2] addr0[3] a0_0 a0_1 a0_2 a0_3 clk_buf0 vdd ++ gnd ++ sram_row_addr_dff +Xdata_dff0 ++ din0[0] bank_din0_0 clk_buf0 vdd gnd ++ sram_data_dff +.ENDS sram From 44ca70bd16b6164e4b102284b84318d16d12c3df Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Wed, 19 Apr 2023 17:23:46 -0700 Subject: [PATCH 084/130] Updated golden values for freepdk --- .../tests/21_ngspice_delay_extra_rows_test.py | 28 +++++++++---------- compiler/tests/21_ngspice_delay_test.py | 28 +++++++++---------- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/compiler/tests/21_ngspice_delay_extra_rows_test.py b/compiler/tests/21_ngspice_delay_extra_rows_test.py index bf2dc358..f1b0f554 100755 --- a/compiler/tests/21_ngspice_delay_extra_rows_test.py +++ b/compiler/tests/21_ngspice_delay_extra_rows_test.py @@ -61,20 +61,20 @@ class timing_sram_test(openram_test): data.update(port_data[0]) if OPTS.tech_name == "freepdk45": - golden_data = {'slew_lh': [0.2592187], - 'slew_hl': [0.2592187], - 'delay_lh': [0.2465583], - 'disabled_write0_power': [0.1924678], - 'disabled_read0_power': [0.152483], - 'write0_power': [0.3409064], - 'disabled_read1_power': [0.1737818], - 'read0_power': [0.3096708], - 'read1_power': [0.3107916], - 'delay_hl': [0.2465583], - 'write1_power': [0.26915849999999997], - 'leakage_power': 0.002044307, - 'min_period': 0.898, - 'disabled_write1_power': [0.201411]} + golden_data = {'delay_hl': [0.263898], + 'delay_lh': [0.263898], + 'disabled_read0_power': [0.06625703], + 'disabled_read1_power': [0.07531121], + 'disabled_write0_power': [0.09350641999999999], + 'disabled_write1_power': [0.09988823000000001], + 'leakage_power': 0.01192385, + 'min_period': 2.031, + 'read0_power': [0.14745439999999999], + 'read1_power': [0.1470831], + 'slew_hl': [0.027165], + 'slew_lh': [0.027165], + 'write0_power': [0.1630546], + 'write1_power': [0.1319501]} elif OPTS.tech_name == "scn4m_subm": golden_data = {'read1_power': [12.11658], 'write1_power': [10.52653], diff --git a/compiler/tests/21_ngspice_delay_test.py b/compiler/tests/21_ngspice_delay_test.py index 8f3e05be..4f17d978 100755 --- a/compiler/tests/21_ngspice_delay_test.py +++ b/compiler/tests/21_ngspice_delay_test.py @@ -69,20 +69,20 @@ class timing_sram_test(openram_test): data.update(port_data[0]) if OPTS.tech_name == "freepdk45": - golden_data = {'delay_hl': [0.24671600000000002], - 'delay_lh': [0.24671600000000002], - 'disabled_read0_power': [0.1749204], - 'disabled_read1_power': [0.1873704], - 'disabled_write0_power': [0.204619], - 'disabled_write1_power': [0.2262653], - 'leakage_power': 0.0021375310000000002, - 'min_period': 0.977, - 'read0_power': [0.3856875], - 'read1_power': [0.38856060000000003], - 'slew_hl': [0.2842019], - 'slew_lh': [0.2842019], - 'write0_power': [0.45274410000000004], - 'write1_power': [0.38727789999999995]} + golden_data = {'delay_hl': [0.2764415], + 'delay_lh': [0.2764415], + 'disabled_read0_power': [0.18364834], + 'disabled_read1_power': [0.20878333999999998], + 'disabled_write0_power': [0.24064433999999998], + 'disabled_write1_power': [0.27207664], + 'leakage_power': 0.0443369, + 'min_period': 0.938, + 'read0_power': [0.37790994], + 'read1_power': [0.37646214], + 'slew_hl': [0.0266144], + 'slew_lh': [0.0266144], + 'write0_power': [0.44694044], + 'write1_power': [0.36824544000000003]} elif OPTS.tech_name == "scn4m_subm": golden_data = {'delay_hl': [1.882508], 'delay_lh': [1.882508], From 07411892c12b031991d6ebdea63379395e6712fa Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Wed, 19 Apr 2023 18:33:43 -0700 Subject: [PATCH 085/130] Moved memchar test tmp dir to results --- compiler/tests/30_memchar_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/tests/30_memchar_test.py b/compiler/tests/30_memchar_test.py index 5fe45f96..5c272b64 100755 --- a/compiler/tests/30_memchar_test.py +++ b/compiler/tests/30_memchar_test.py @@ -22,7 +22,7 @@ class sram_char_test(openram_test): def runTest(self): global OPTS out_file = "testsram" - out_path = "/tmp/testsram_{0}_{1}_{2}".format(OPTS.tech_name, getpass.getuser(), os.getpid()) + out_path = "{0}/testsram_{1}_{2}_{3}".format(OPTS.openram_temp, OPTS.tech_name, getpass.getuser(), os.getpid()) OPTS.output_name = out_file OPTS.output_path = out_path From 3f94e228609caed70279bcf84d199e72c7180cf5 Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Wed, 19 Apr 2023 18:44:09 -0700 Subject: [PATCH 086/130] Fixed memchar test output name --- compiler/tests/30_memchar_test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/tests/30_memchar_test.py b/compiler/tests/30_memchar_test.py index 5c272b64..b9a41fd7 100755 --- a/compiler/tests/30_memchar_test.py +++ b/compiler/tests/30_memchar_test.py @@ -23,14 +23,14 @@ class sram_char_test(openram_test): global OPTS out_file = "testsram" out_path = "{0}/testsram_{1}_{2}_{3}".format(OPTS.openram_temp, OPTS.tech_name, getpass.getuser(), os.getpid()) - OPTS.output_name = out_file + OPTS.output_name = "sram_2_16_1_{0}".format(OPTS.tech_name) OPTS.output_path = out_path OPENRAM_HOME = os.path.abspath(os.environ.get("OPENRAM_HOME")) config_file = "{}/tests/configs/config_mem_char_func".format(OPENRAM_HOME) openram.init_openram(config_file, is_unit_test=False) - sp_file = "{0}/tests/sp_files/sram_2_16_1_{1}.sp".format(OPENRAM_HOME, OPTS.tech_name) + sp_file = "{0}/tests/sp_files/{1}.sp".format(OPENRAM_HOME, OPTS.output_name) debug.info(1, "Testing commandline characterizer script sram_char.py with 2-bit, 16 word SRAM.") From b2b7e1fa4d114b7766b9f39d37efa8501d5235f0 Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Wed, 19 Apr 2023 18:51:34 -0700 Subject: [PATCH 087/130] fixed the test name --- compiler/tests/30_memchar_test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/tests/30_memchar_test.py b/compiler/tests/30_memchar_test.py index b9a41fd7..748abecf 100755 --- a/compiler/tests/30_memchar_test.py +++ b/compiler/tests/30_memchar_test.py @@ -21,9 +21,9 @@ class sram_char_test(openram_test): def runTest(self): global OPTS - out_file = "testsram" + out_file = "sram_2_16_1_{0}".format(OPTS.tech_name) out_path = "{0}/testsram_{1}_{2}_{3}".format(OPTS.openram_temp, OPTS.tech_name, getpass.getuser(), os.getpid()) - OPTS.output_name = "sram_2_16_1_{0}".format(OPTS.tech_name) + OPTS.output_name = out_file OPTS.output_path = out_path OPENRAM_HOME = os.path.abspath(os.environ.get("OPENRAM_HOME")) From afe37e591500cc299d5bac8b5768eeb0e5b0e21c Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Wed, 19 Apr 2023 18:57:38 -0700 Subject: [PATCH 088/130] sp file sram instance name fix --- compiler/tests/sp_files/sram_2_16_1_freepdk45.sp | 4 ++-- compiler/tests/sp_files/sram_2_16_1_scn4m_subm.sp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/tests/sp_files/sram_2_16_1_freepdk45.sp b/compiler/tests/sp_files/sram_2_16_1_freepdk45.sp index 28a07dd3..55ab3e6b 100644 --- a/compiler/tests/sp_files/sram_2_16_1_freepdk45.sp +++ b/compiler/tests/sp_files/sram_2_16_1_freepdk45.sp @@ -1615,7 +1615,7 @@ Xdff_r0_c0 + dff .ENDS sram_data_dff -.SUBCKT sram +.SUBCKT sram_2_16_1_freepdk45 + din0[0] addr0[0] addr0[1] addr0[2] addr0[3] csb0 web0 clk0 dout0[0] + vdd gnd * INPUT : din0[0] @@ -1643,4 +1643,4 @@ Xrow_address0 Xdata_dff0 + din0[0] bank_din0_0 clk_buf0 vdd gnd + sram_data_dff -.ENDS sram +.ENDS sram_2_16_1_freepdk45 diff --git a/compiler/tests/sp_files/sram_2_16_1_scn4m_subm.sp b/compiler/tests/sp_files/sram_2_16_1_scn4m_subm.sp index 947ff987..667e1df4 100644 --- a/compiler/tests/sp_files/sram_2_16_1_scn4m_subm.sp +++ b/compiler/tests/sp_files/sram_2_16_1_scn4m_subm.sp @@ -1625,7 +1625,7 @@ Xdff_r0_c0 + dff .ENDS sram_data_dff -.SUBCKT sram +.SUBCKT sram_2_16_1_scn4m_subm + din0[0] addr0[0] addr0[1] addr0[2] addr0[3] csb0 web0 clk0 dout0[0] + vdd gnd * INPUT : din0[0] @@ -1653,4 +1653,4 @@ Xrow_address0 Xdata_dff0 + din0[0] bank_din0_0 clk_buf0 vdd gnd + sram_data_dff -.ENDS sram +.ENDS sram_2_16_1_scn4m_subm From dbb8bb85cbceb714a522890607721f72cd9f67e1 Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Mon, 15 May 2023 16:28:35 -0700 Subject: [PATCH 089/130] Fixed golden values for ngspice delay tests --- .../tests/21_ngspice_delay_extra_rows_test.py | 29 +- compiler/tests/21_ngspice_delay_test.py | 29 +- .../tests/configs/config_mem_char_func.py | 3 +- .../tests/sp_files/sram_2_16_1_freepdk45.sp | 1680 +++++++------ .../tests/sp_files/sram_2_16_1_scn4m_subm.sp | 2232 +++++++++-------- 5 files changed, 2090 insertions(+), 1883 deletions(-) diff --git a/compiler/tests/21_ngspice_delay_extra_rows_test.py b/compiler/tests/21_ngspice_delay_extra_rows_test.py index f1b0f554..531816f5 100755 --- a/compiler/tests/21_ngspice_delay_extra_rows_test.py +++ b/compiler/tests/21_ngspice_delay_extra_rows_test.py @@ -76,20 +76,21 @@ class timing_sram_test(openram_test): 'write0_power': [0.1630546], 'write1_power': [0.1319501]} elif OPTS.tech_name == "scn4m_subm": - golden_data = {'read1_power': [12.11658], - 'write1_power': [10.52653], - 'read0_power': [11.956710000000001], - 'disabled_write0_power': [7.673665], - 'disabled_write1_power': [7.981922000000001], - 'slew_lh': [1.868836], - 'slew_hl': [1.868836], - 'delay_hl': [1.8598510000000001], - 'delay_lh': [1.8598510000000001], - 'leakage_power': 0.005457728, - 'disabled_read0_power': [5.904712], - 'min_period': 6.875, - 'disabled_read1_power': [7.132159], - 'write0_power': [13.406400000000001]} + golden_data = {'delay_hl': [1.8259260000000002], + 'delay_lh': [1.8259260000000002], + 'disabled_read0_power': [6.722809], + 'disabled_read1_power': [8.104113], + 'disabled_write0_power': [8.900671], + 'disabled_write1_power': [9.188668], + 'leakage_power': 0.6977637, + 'min_period': 6.562, + 'read0_power': [15.45948], + 'read1_power': [15.48587], + 'slew_hl': [0.1936536], + 'slew_lh': [0.1936536], + 'write0_power': [17.03442], + 'write1_power': [13.05424]} + else: self.assertTrue(False) # other techs fail diff --git a/compiler/tests/21_ngspice_delay_test.py b/compiler/tests/21_ngspice_delay_test.py index 4f17d978..eaf5d8a2 100755 --- a/compiler/tests/21_ngspice_delay_test.py +++ b/compiler/tests/21_ngspice_delay_test.py @@ -84,20 +84,21 @@ class timing_sram_test(openram_test): 'write0_power': [0.44694044], 'write1_power': [0.36824544000000003]} elif OPTS.tech_name == "scn4m_subm": - golden_data = {'delay_hl': [1.882508], - 'delay_lh': [1.882508], - 'disabled_read0_power': [7.487227], - 'disabled_read1_power': [8.749013], - 'disabled_write0_power': [9.268901], - 'disabled_write1_power': [9.962973], - 'leakage_power': 0.0046686359999999994, - 'min_period': 7.188, - 'read0_power': [16.64011], - 'read1_power': [17.20825], - 'slew_hl': [2.039655], - 'slew_lh': [2.039655], - 'write0_power': [19.31883], - 'write1_power': [15.297369999999999]} + golden_data = {'delay_hl': [1.905376], + 'delay_lh': [1.905376], + 'disabled_read0_power': [7.673850999999999], + 'disabled_read1_power': [10.051073], + 'disabled_write0_power': [10.638803], + 'disabled_write1_power': [10.385253], + 'leakage_power': 2.704021, + 'min_period': 6.875, + 'read0_power': [17.583853], + 'read1_power': [17.689162999999997], + 'slew_hl': [0.19331199999999998], + 'slew_lh': [0.19331199999999998], + 'write0_power': [20.607043], + 'write1_power': [16.107403]} + else: self.assertTrue(False) # other techs fail diff --git a/compiler/tests/configs/config_mem_char_func.py b/compiler/tests/configs/config_mem_char_func.py index 65a021fe..767f2c75 100644 --- a/compiler/tests/configs/config_mem_char_func.py +++ b/compiler/tests/configs/config_mem_char_func.py @@ -12,5 +12,6 @@ num_words = 16 tech_name = OPTS.tech_name output_name = "sram" +analytical_delay = False nominal_corner_only = True -spice_name = "ngspice" +spice_name = "Xyce" diff --git a/compiler/tests/sp_files/sram_2_16_1_freepdk45.sp b/compiler/tests/sp_files/sram_2_16_1_freepdk45.sp index 55ab3e6b..c638e514 100644 --- a/compiler/tests/sp_files/sram_2_16_1_freepdk45.sp +++ b/compiler/tests/sp_files/sram_2_16_1_freepdk45.sp @@ -1,153 +1,12 @@ ************************************************** * OpenRAM generated memory. * Words: 16 -* Data bits: 1 +* Data bits: 2 * Banks: 1 * Column mux: 1:1 * Trimmed: False * LVS: False ************************************************** - -* spice ptx M{0} {1} pmos_vtg m=1 w=0.27u l=0.05u pd=0.64u ps=0.64u as=0.03p ad=0.03p - -* spice ptx M{0} {1} nmos_vtg m=1 w=0.09u l=0.05u pd=0.28u ps=0.28u as=0.01p ad=0.01p - -.SUBCKT sram_pinv_3 -+ A Z vdd gnd -* INPUT : A -* OUTPUT: Z -* POWER : vdd -* GROUND: gnd -Mpinv_pmos Z A vdd vdd pmos_vtg m=1 w=0.27u l=0.05u pd=0.64u ps=0.64u as=0.03p ad=0.03p -Mpinv_nmos Z A gnd gnd nmos_vtg m=1 w=0.09u l=0.05u pd=0.28u ps=0.28u as=0.01p ad=0.01p -.ENDS sram_pinv_3 - -* spice ptx M{0} {1} pmos_vtg m=2 w=0.675u l=0.05u pd=1.45u ps=1.45u as=0.08p ad=0.08p - -* spice ptx M{0} {1} nmos_vtg m=2 w=0.225u l=0.05u pd=0.55u ps=0.55u as=0.03p ad=0.03p - -.SUBCKT sram_pinv_8 -+ A Z vdd gnd -* INPUT : A -* OUTPUT: Z -* POWER : vdd -* GROUND: gnd -Mpinv_pmos Z A vdd vdd pmos_vtg m=2 w=0.675u l=0.05u pd=1.45u ps=1.45u as=0.08p ad=0.08p -Mpinv_nmos Z A gnd gnd nmos_vtg m=2 w=0.225u l=0.05u pd=0.55u ps=0.55u as=0.03p ad=0.03p -.ENDS sram_pinv_8 - -.SUBCKT sram_pinv_5 -+ A Z vdd gnd -* INPUT : A -* OUTPUT: Z -* POWER : vdd -* GROUND: gnd -Mpinv_pmos Z A vdd vdd pmos_vtg m=1 w=0.27u l=0.05u pd=0.64u ps=0.64u as=0.03p ad=0.03p -Mpinv_nmos Z A gnd gnd nmos_vtg m=1 w=0.09u l=0.05u pd=0.28u ps=0.28u as=0.01p ad=0.01p -.ENDS sram_pinv_5 - -.SUBCKT sram_pdriver_1 -+ A Z vdd gnd -* INPUT : A -* OUTPUT: Z -* POWER : vdd -* GROUND: gnd -* sizes: [1, 5] -Xbuf_inv1 -+ A Zb1_int vdd gnd -+ sram_pinv_5 -Xbuf_inv2 -+ Zb1_int Z vdd gnd -+ sram_pinv_8 -.ENDS sram_pdriver_1 - -* spice ptx M{0} {1} nmos_vtg m=1 w=0.18u l=0.05u pd=0.46u ps=0.46u as=0.02p ad=0.02p - -* spice ptx M{0} {1} nmos_vtg m=1 w=0.18u l=0.05u pd=0.46u ps=0.46u as=0.02p ad=0.02p - -* spice ptx M{0} {1} pmos_vtg m=1 w=0.27u l=0.05u pd=0.64u ps=0.64u as=0.03p ad=0.03p - -.SUBCKT sram_pnand2_0 -+ A B Z vdd gnd -* INPUT : A -* INPUT : B -* OUTPUT: Z -* POWER : vdd -* GROUND: gnd -Mpnand2_pmos1 vdd A Z vdd pmos_vtg m=1 w=0.27u l=0.05u pd=0.64u ps=0.64u as=0.03p ad=0.03p -Mpnand2_pmos2 Z B vdd vdd pmos_vtg m=1 w=0.27u l=0.05u pd=0.64u ps=0.64u as=0.03p ad=0.03p -Mpnand2_nmos1 Z B net1 gnd nmos_vtg m=1 w=0.18u l=0.05u pd=0.46u ps=0.46u as=0.02p ad=0.02p -Mpnand2_nmos2 net1 A gnd gnd nmos_vtg m=1 w=0.18u l=0.05u pd=0.46u ps=0.46u as=0.02p ad=0.02p -.ENDS sram_pnand2_0 - -* spice ptx M{0} {1} nmos_vtg m=4 w=0.27u l=0.05u pd=0.64u ps=0.64u as=0.03p ad=0.03p - -* spice ptx M{0} {1} pmos_vtg m=4 w=0.81u l=0.05u pd=1.72u ps=1.72u as=0.10p ad=0.10p - -.SUBCKT sram_pinv_2 -+ A Z vdd gnd -* INPUT : A -* OUTPUT: Z -* POWER : vdd -* GROUND: gnd -Mpinv_pmos Z A vdd vdd pmos_vtg m=4 w=0.81u l=0.05u pd=1.72u ps=1.72u as=0.10p ad=0.10p -Mpinv_nmos Z A gnd gnd nmos_vtg m=4 w=0.27u l=0.05u pd=0.64u ps=0.64u as=0.03p ad=0.03p -.ENDS sram_pinv_2 - -.SUBCKT sram_pdriver -+ A Z vdd gnd -* INPUT : A -* OUTPUT: Z -* POWER : vdd -* GROUND: gnd -* sizes: [12] -Xbuf_inv1 -+ A Z vdd gnd -+ sram_pinv_2 -.ENDS sram_pdriver - -.SUBCKT sram_pand2 -+ A B Z vdd gnd -* INPUT : A -* INPUT : B -* OUTPUT: Z -* POWER : vdd -* GROUND: gnd -Xpand2_nand -+ A B zb_int vdd gnd -+ sram_pnand2_0 -Xpand2_inv -+ zb_int Z vdd gnd -+ sram_pdriver -.ENDS sram_pand2 - -* spice ptx M{0} {1} pmos_vtg m=1 w=0.54u l=0.05u pd=1.18u ps=1.18u as=0.07p ad=0.07p - -* spice ptx M{0} {1} nmos_vtg m=1 w=0.18u l=0.05u pd=0.46u ps=0.46u as=0.02p ad=0.02p - -.SUBCKT sram_pinv_0 -+ A Z vdd gnd -* INPUT : A -* OUTPUT: Z -* POWER : vdd -* GROUND: gnd -Mpinv_pmos Z A vdd vdd pmos_vtg m=1 w=0.54u l=0.05u pd=1.18u ps=1.18u as=0.07p ad=0.07p -Mpinv_nmos Z A gnd gnd nmos_vtg m=1 w=0.18u l=0.05u pd=0.46u ps=0.46u as=0.02p ad=0.02p -.ENDS sram_pinv_0 - -* spice ptx M{0} {1} pmos_vtg m=2 w=0.54u l=0.05u pd=1.18u ps=1.18u as=0.07p ad=0.07p - -* spice ptx M{0} {1} nmos_vtg m=2 w=0.18u l=0.05u pd=0.46u ps=0.46u as=0.02p ad=0.02p - -.SUBCKT sram_pinv_1 -+ A Z vdd gnd -* INPUT : A -* OUTPUT: Z -* POWER : vdd -* GROUND: gnd -Mpinv_pmos Z A vdd vdd pmos_vtg m=2 w=0.54u l=0.05u pd=1.18u ps=1.18u as=0.07p ad=0.07p -Mpinv_nmos Z A gnd gnd nmos_vtg m=2 w=0.18u l=0.05u pd=0.46u ps=0.46u as=0.02p ad=0.02p -.ENDS sram_pinv_1 * File: DFFPOSX1.pex.netlist * Created: Wed Jan 2 18:36:24 2008 * Program "Calibre xRC" @@ -195,7 +54,211 @@ MM1 a_17_74# D vdd vdd PMOS_VTG L=5e-08 W=5e-07 * * -.SUBCKT sram_dff_buf_0 +.SUBCKT sram_2_16_1_freepdk45_data_dff ++ din_0 din_1 dout_0 dout_1 clk vdd gnd +* INPUT : din_0 +* INPUT : din_1 +* OUTPUT: dout_0 +* OUTPUT: dout_1 +* INPUT : clk +* POWER : vdd +* GROUND: gnd +* rows: 1 cols: 2 +Xdff_r0_c0 ++ din_0 dout_0 clk vdd gnd ++ dff +Xdff_r0_c1 ++ din_1 dout_1 clk vdd gnd ++ dff +.ENDS sram_2_16_1_freepdk45_data_dff + +* spice ptx M{0} {1} pmos_vtg m=1 w=0.27u l=0.05u pd=0.64u ps=0.64u as=0.03p ad=0.03p + +* spice ptx M{0} {1} nmos_vtg m=1 w=0.09u l=0.05u pd=0.28u ps=0.28u as=0.01p ad=0.01p + +.SUBCKT sram_2_16_1_freepdk45_pinv_10 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +Mpinv_pmos Z A vdd vdd pmos_vtg m=1 w=0.27u l=0.05u pd=0.64u ps=0.64u as=0.03p ad=0.03p +Mpinv_nmos Z A gnd gnd nmos_vtg m=1 w=0.09u l=0.05u pd=0.28u ps=0.28u as=0.01p ad=0.01p +.ENDS sram_2_16_1_freepdk45_pinv_10 + +.SUBCKT sram_2_16_1_freepdk45_delay_chain ++ in out vdd gnd +* INPUT : in +* OUTPUT: out +* POWER : vdd +* GROUND: gnd +* fanouts: [4, 4, 4, 4, 4, 4, 4, 4, 4] +Xdinv0 ++ in dout_1 vdd gnd ++ sram_2_16_1_freepdk45_pinv_10 +Xdload_0_0 ++ dout_1 n_0_0 vdd gnd ++ sram_2_16_1_freepdk45_pinv_10 +Xdload_0_1 ++ dout_1 n_0_1 vdd gnd ++ sram_2_16_1_freepdk45_pinv_10 +Xdload_0_2 ++ dout_1 n_0_2 vdd gnd ++ sram_2_16_1_freepdk45_pinv_10 +Xdload_0_3 ++ dout_1 n_0_3 vdd gnd ++ sram_2_16_1_freepdk45_pinv_10 +Xdinv1 ++ dout_1 dout_2 vdd gnd ++ sram_2_16_1_freepdk45_pinv_10 +Xdload_1_0 ++ dout_2 n_1_0 vdd gnd ++ sram_2_16_1_freepdk45_pinv_10 +Xdload_1_1 ++ dout_2 n_1_1 vdd gnd ++ sram_2_16_1_freepdk45_pinv_10 +Xdload_1_2 ++ dout_2 n_1_2 vdd gnd ++ sram_2_16_1_freepdk45_pinv_10 +Xdload_1_3 ++ dout_2 n_1_3 vdd gnd ++ sram_2_16_1_freepdk45_pinv_10 +Xdinv2 ++ dout_2 dout_3 vdd gnd ++ sram_2_16_1_freepdk45_pinv_10 +Xdload_2_0 ++ dout_3 n_2_0 vdd gnd ++ sram_2_16_1_freepdk45_pinv_10 +Xdload_2_1 ++ dout_3 n_2_1 vdd gnd ++ sram_2_16_1_freepdk45_pinv_10 +Xdload_2_2 ++ dout_3 n_2_2 vdd gnd ++ sram_2_16_1_freepdk45_pinv_10 +Xdload_2_3 ++ dout_3 n_2_3 vdd gnd ++ sram_2_16_1_freepdk45_pinv_10 +Xdinv3 ++ dout_3 dout_4 vdd gnd ++ sram_2_16_1_freepdk45_pinv_10 +Xdload_3_0 ++ dout_4 n_3_0 vdd gnd ++ sram_2_16_1_freepdk45_pinv_10 +Xdload_3_1 ++ dout_4 n_3_1 vdd gnd ++ sram_2_16_1_freepdk45_pinv_10 +Xdload_3_2 ++ dout_4 n_3_2 vdd gnd ++ sram_2_16_1_freepdk45_pinv_10 +Xdload_3_3 ++ dout_4 n_3_3 vdd gnd ++ sram_2_16_1_freepdk45_pinv_10 +Xdinv4 ++ dout_4 dout_5 vdd gnd ++ sram_2_16_1_freepdk45_pinv_10 +Xdload_4_0 ++ dout_5 n_4_0 vdd gnd ++ sram_2_16_1_freepdk45_pinv_10 +Xdload_4_1 ++ dout_5 n_4_1 vdd gnd ++ sram_2_16_1_freepdk45_pinv_10 +Xdload_4_2 ++ dout_5 n_4_2 vdd gnd ++ sram_2_16_1_freepdk45_pinv_10 +Xdload_4_3 ++ dout_5 n_4_3 vdd gnd ++ sram_2_16_1_freepdk45_pinv_10 +Xdinv5 ++ dout_5 dout_6 vdd gnd ++ sram_2_16_1_freepdk45_pinv_10 +Xdload_5_0 ++ dout_6 n_5_0 vdd gnd ++ sram_2_16_1_freepdk45_pinv_10 +Xdload_5_1 ++ dout_6 n_5_1 vdd gnd ++ sram_2_16_1_freepdk45_pinv_10 +Xdload_5_2 ++ dout_6 n_5_2 vdd gnd ++ sram_2_16_1_freepdk45_pinv_10 +Xdload_5_3 ++ dout_6 n_5_3 vdd gnd ++ sram_2_16_1_freepdk45_pinv_10 +Xdinv6 ++ dout_6 dout_7 vdd gnd ++ sram_2_16_1_freepdk45_pinv_10 +Xdload_6_0 ++ dout_7 n_6_0 vdd gnd ++ sram_2_16_1_freepdk45_pinv_10 +Xdload_6_1 ++ dout_7 n_6_1 vdd gnd ++ sram_2_16_1_freepdk45_pinv_10 +Xdload_6_2 ++ dout_7 n_6_2 vdd gnd ++ sram_2_16_1_freepdk45_pinv_10 +Xdload_6_3 ++ dout_7 n_6_3 vdd gnd ++ sram_2_16_1_freepdk45_pinv_10 +Xdinv7 ++ dout_7 dout_8 vdd gnd ++ sram_2_16_1_freepdk45_pinv_10 +Xdload_7_0 ++ dout_8 n_7_0 vdd gnd ++ sram_2_16_1_freepdk45_pinv_10 +Xdload_7_1 ++ dout_8 n_7_1 vdd gnd ++ sram_2_16_1_freepdk45_pinv_10 +Xdload_7_2 ++ dout_8 n_7_2 vdd gnd ++ sram_2_16_1_freepdk45_pinv_10 +Xdload_7_3 ++ dout_8 n_7_3 vdd gnd ++ sram_2_16_1_freepdk45_pinv_10 +Xdinv8 ++ dout_8 out vdd gnd ++ sram_2_16_1_freepdk45_pinv_10 +Xdload_8_0 ++ out n_8_0 vdd gnd ++ sram_2_16_1_freepdk45_pinv_10 +Xdload_8_1 ++ out n_8_1 vdd gnd ++ sram_2_16_1_freepdk45_pinv_10 +Xdload_8_2 ++ out n_8_2 vdd gnd ++ sram_2_16_1_freepdk45_pinv_10 +Xdload_8_3 ++ out n_8_3 vdd gnd ++ sram_2_16_1_freepdk45_pinv_10 +.ENDS sram_2_16_1_freepdk45_delay_chain + +* spice ptx M{0} {1} pmos_vtg m=1 w=0.54u l=0.05u pd=1.18u ps=1.18u as=0.07p ad=0.07p + +* spice ptx M{0} {1} nmos_vtg m=1 w=0.18u l=0.05u pd=0.46u ps=0.46u as=0.02p ad=0.02p + +.SUBCKT sram_2_16_1_freepdk45_pinv_0 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +Mpinv_pmos Z A vdd vdd pmos_vtg m=1 w=0.54u l=0.05u pd=1.18u ps=1.18u as=0.07p ad=0.07p +Mpinv_nmos Z A gnd gnd nmos_vtg m=1 w=0.18u l=0.05u pd=0.46u ps=0.46u as=0.02p ad=0.02p +.ENDS sram_2_16_1_freepdk45_pinv_0 + +* spice ptx M{0} {1} nmos_vtg m=2 w=0.18u l=0.05u pd=0.46u ps=0.46u as=0.02p ad=0.02p + +* spice ptx M{0} {1} pmos_vtg m=2 w=0.54u l=0.05u pd=1.18u ps=1.18u as=0.07p ad=0.07p + +.SUBCKT sram_2_16_1_freepdk45_pinv_1 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +Mpinv_pmos Z A vdd vdd pmos_vtg m=2 w=0.54u l=0.05u pd=1.18u ps=1.18u as=0.07p ad=0.07p +Mpinv_nmos Z A gnd gnd nmos_vtg m=2 w=0.18u l=0.05u pd=0.46u ps=0.46u as=0.02p ad=0.02p +.ENDS sram_2_16_1_freepdk45_pinv_1 + +.SUBCKT sram_2_16_1_freepdk45_dff_buf_0 + D Q Qb clk vdd gnd * INPUT : D * OUTPUT: Q @@ -209,13 +272,13 @@ Xdff_buf_dff + dff Xdff_buf_inv1 + qint Qb vdd gnd -+ sram_pinv_0 ++ sram_2_16_1_freepdk45_pinv_0 Xdff_buf_inv2 + Qb Q vdd gnd -+ sram_pinv_1 -.ENDS sram_dff_buf_0 ++ sram_2_16_1_freepdk45_pinv_1 +.ENDS sram_2_16_1_freepdk45_dff_buf_0 -.SUBCKT sram_dff_buf_array +.SUBCKT sram_2_16_1_freepdk45_dff_buf_array + din_0 din_1 dout_0 dout_bar_0 dout_1 dout_bar_1 clk vdd gnd * INPUT : din_0 * INPUT : din_1 @@ -229,13 +292,29 @@ Xdff_buf_inv2 * inv1: 2 inv2: 4 Xdff_r0_c0 + din_0 dout_0 dout_bar_0 clk vdd gnd -+ sram_dff_buf_0 ++ sram_2_16_1_freepdk45_dff_buf_0 Xdff_r1_c0 + din_1 dout_1 dout_bar_1 clk vdd gnd -+ sram_dff_buf_0 -.ENDS sram_dff_buf_array ++ sram_2_16_1_freepdk45_dff_buf_0 +.ENDS sram_2_16_1_freepdk45_dff_buf_array -.SUBCKT sram_pnand2_1 +.SUBCKT sram_2_16_1_freepdk45_pinv_3 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +Mpinv_pmos Z A vdd vdd pmos_vtg m=1 w=0.27u l=0.05u pd=0.64u ps=0.64u as=0.03p ad=0.03p +Mpinv_nmos Z A gnd gnd nmos_vtg m=1 w=0.09u l=0.05u pd=0.28u ps=0.28u as=0.01p ad=0.01p +.ENDS sram_2_16_1_freepdk45_pinv_3 + +* spice ptx M{0} {1} pmos_vtg m=1 w=0.27u l=0.05u pd=0.64u ps=0.64u as=0.03p ad=0.03p + +* spice ptx M{0} {1} nmos_vtg m=1 w=0.18u l=0.05u pd=0.46u ps=0.46u as=0.02p ad=0.02p + +* spice ptx M{0} {1} nmos_vtg m=1 w=0.18u l=0.05u pd=0.46u ps=0.46u as=0.02p ad=0.02p + +.SUBCKT sram_2_16_1_freepdk45_pnand2_1 + A B Z vdd gnd * INPUT : A * INPUT : B @@ -246,23 +325,176 @@ Mpnand2_pmos1 vdd A Z vdd pmos_vtg m=1 w=0.27u l=0.05u pd=0.64u ps=0.64u as=0.03 Mpnand2_pmos2 Z B vdd vdd pmos_vtg m=1 w=0.27u l=0.05u pd=0.64u ps=0.64u as=0.03p ad=0.03p Mpnand2_nmos1 Z B net1 gnd nmos_vtg m=1 w=0.18u l=0.05u pd=0.46u ps=0.46u as=0.02p ad=0.02p Mpnand2_nmos2 net1 A gnd gnd nmos_vtg m=1 w=0.18u l=0.05u pd=0.46u ps=0.46u as=0.02p ad=0.02p -.ENDS sram_pnand2_1 +.ENDS sram_2_16_1_freepdk45_pnand2_1 -.SUBCKT sram_pdriver_3 +* spice ptx M{0} {1} pmos_vtg m=2 w=0.675u l=0.05u pd=1.45u ps=1.45u as=0.08p ad=0.08p + +* spice ptx M{0} {1} nmos_vtg m=2 w=0.225u l=0.05u pd=0.55u ps=0.55u as=0.03p ad=0.03p + +.SUBCKT sram_2_16_1_freepdk45_pinv_7 + A Z vdd gnd * INPUT : A * OUTPUT: Z * POWER : vdd * GROUND: gnd -* sizes: [1] +Mpinv_pmos Z A vdd vdd pmos_vtg m=2 w=0.675u l=0.05u pd=1.45u ps=1.45u as=0.08p ad=0.08p +Mpinv_nmos Z A gnd gnd nmos_vtg m=2 w=0.225u l=0.05u pd=0.55u ps=0.55u as=0.03p ad=0.03p +.ENDS sram_2_16_1_freepdk45_pinv_7 + +.SUBCKT sram_2_16_1_freepdk45_pinv_5 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +Mpinv_pmos Z A vdd vdd pmos_vtg m=1 w=0.27u l=0.05u pd=0.64u ps=0.64u as=0.03p ad=0.03p +Mpinv_nmos Z A gnd gnd nmos_vtg m=1 w=0.09u l=0.05u pd=0.28u ps=0.28u as=0.01p ad=0.01p +.ENDS sram_2_16_1_freepdk45_pinv_5 + +.SUBCKT sram_2_16_1_freepdk45_pdriver_1 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* sizes: [1, 5] +Xbuf_inv1 ++ A Zb1_int vdd gnd ++ sram_2_16_1_freepdk45_pinv_5 +Xbuf_inv2 ++ Zb1_int Z vdd gnd ++ sram_2_16_1_freepdk45_pinv_7 +.ENDS sram_2_16_1_freepdk45_pdriver_1 + +.SUBCKT sram_2_16_1_freepdk45_pnand2_0 ++ A B Z vdd gnd +* INPUT : A +* INPUT : B +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +Mpnand2_pmos1 vdd A Z vdd pmos_vtg m=1 w=0.27u l=0.05u pd=0.64u ps=0.64u as=0.03p ad=0.03p +Mpnand2_pmos2 Z B vdd vdd pmos_vtg m=1 w=0.27u l=0.05u pd=0.64u ps=0.64u as=0.03p ad=0.03p +Mpnand2_nmos1 Z B net1 gnd nmos_vtg m=1 w=0.18u l=0.05u pd=0.46u ps=0.46u as=0.02p ad=0.02p +Mpnand2_nmos2 net1 A gnd gnd nmos_vtg m=1 w=0.18u l=0.05u pd=0.46u ps=0.46u as=0.02p ad=0.02p +.ENDS sram_2_16_1_freepdk45_pnand2_0 + +* spice ptx M{0} {1} pmos_vtg m=4 w=0.81u l=0.05u pd=1.72u ps=1.72u as=0.10p ad=0.10p + +* spice ptx M{0} {1} nmos_vtg m=4 w=0.27u l=0.05u pd=0.64u ps=0.64u as=0.03p ad=0.03p + +.SUBCKT sram_2_16_1_freepdk45_pinv_2 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +Mpinv_pmos Z A vdd vdd pmos_vtg m=4 w=0.81u l=0.05u pd=1.72u ps=1.72u as=0.10p ad=0.10p +Mpinv_nmos Z A gnd gnd nmos_vtg m=4 w=0.27u l=0.05u pd=0.64u ps=0.64u as=0.03p ad=0.03p +.ENDS sram_2_16_1_freepdk45_pinv_2 + +.SUBCKT sram_2_16_1_freepdk45_pdriver ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* sizes: [12] Xbuf_inv1 + A Z vdd gnd -+ sram_pinv_5 -.ENDS sram_pdriver_3 ++ sram_2_16_1_freepdk45_pinv_2 +.ENDS sram_2_16_1_freepdk45_pdriver + +.SUBCKT sram_2_16_1_freepdk45_pand2 ++ A B Z vdd gnd +* INPUT : A +* INPUT : B +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +Xpand2_nand ++ A B zb_int vdd gnd ++ sram_2_16_1_freepdk45_pnand2_0 +Xpand2_inv ++ zb_int Z vdd gnd ++ sram_2_16_1_freepdk45_pdriver +.ENDS sram_2_16_1_freepdk45_pand2 + +* spice ptx M{0} {1} pmos_vtg m=5 w=0.81u l=0.05u pd=1.72u ps=1.72u as=0.10p ad=0.10p + +* spice ptx M{0} {1} nmos_vtg m=5 w=0.27u l=0.05u pd=0.64u ps=0.64u as=0.03p ad=0.03p + +.SUBCKT sram_2_16_1_freepdk45_pinv_8 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +Mpinv_pmos Z A vdd vdd pmos_vtg m=5 w=0.81u l=0.05u pd=1.72u ps=1.72u as=0.10p ad=0.10p +Mpinv_nmos Z A gnd gnd nmos_vtg m=5 w=0.27u l=0.05u pd=0.64u ps=0.64u as=0.03p ad=0.03p +.ENDS sram_2_16_1_freepdk45_pinv_8 + +.SUBCKT sram_2_16_1_freepdk45_pinv_6 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +Mpinv_pmos Z A vdd vdd pmos_vtg m=1 w=0.54u l=0.05u pd=1.18u ps=1.18u as=0.07p ad=0.07p +Mpinv_nmos Z A gnd gnd nmos_vtg m=1 w=0.18u l=0.05u pd=0.46u ps=0.46u as=0.02p ad=0.02p +.ENDS sram_2_16_1_freepdk45_pinv_6 + +.SUBCKT sram_2_16_1_freepdk45_pdriver_0 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* sizes: [1, 2, 5, 15] +Xbuf_inv1 ++ A Zb1_int vdd gnd ++ sram_2_16_1_freepdk45_pinv_5 +Xbuf_inv2 ++ Zb1_int Zb2_int vdd gnd ++ sram_2_16_1_freepdk45_pinv_6 +Xbuf_inv3 ++ Zb2_int Zb3_int vdd gnd ++ sram_2_16_1_freepdk45_pinv_7 +Xbuf_inv4 ++ Zb3_int Z vdd gnd ++ sram_2_16_1_freepdk45_pinv_8 +.ENDS sram_2_16_1_freepdk45_pdriver_0 + +.SUBCKT sram_2_16_1_freepdk45_pdriver_4 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* sizes: [1, 1] +Xbuf_inv1 ++ A Zb1_int vdd gnd ++ sram_2_16_1_freepdk45_pinv_5 +Xbuf_inv2 ++ Zb1_int Z vdd gnd ++ sram_2_16_1_freepdk45_pinv_5 +.ENDS sram_2_16_1_freepdk45_pdriver_4 + +.SUBCKT sram_2_16_1_freepdk45_pdriver_3 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* sizes: [2] +Xbuf_inv1 ++ A Z vdd gnd ++ sram_2_16_1_freepdk45_pinv_6 +.ENDS sram_2_16_1_freepdk45_pdriver_3 * spice ptx M{0} {1} nmos_vtg m=1 w=0.18u l=0.05u pd=0.46u ps=0.46u as=0.02p ad=0.02p -.SUBCKT sram_pnand3_0 +.SUBCKT sram_2_16_1_freepdk45_pnand3_0 + A B C Z vdd gnd * INPUT : A * INPUT : B @@ -276,9 +508,9 @@ Mpnand3_pmos3 Z C vdd vdd pmos_vtg m=1 w=0.27u l=0.05u pd=0.64u ps=0.64u as=0.03 Mpnand3_nmos1 Z C net1 gnd nmos_vtg m=1 w=0.18u l=0.05u pd=0.46u ps=0.46u as=0.02p ad=0.02p Mpnand3_nmos2 net1 B net2 gnd nmos_vtg m=1 w=0.18u l=0.05u pd=0.46u ps=0.46u as=0.02p ad=0.02p Mpnand3_nmos3 net2 A gnd gnd nmos_vtg m=1 w=0.18u l=0.05u pd=0.46u ps=0.46u as=0.02p ad=0.02p -.ENDS sram_pnand3_0 +.ENDS sram_2_16_1_freepdk45_pnand3_0 -.SUBCKT sram_pand3_0 +.SUBCKT sram_2_16_1_freepdk45_pand3_0 + A B C Z vdd gnd * INPUT : A * INPUT : B @@ -288,238 +520,39 @@ Mpnand3_nmos3 net2 A gnd gnd nmos_vtg m=1 w=0.18u l=0.05u pd=0.46u ps=0.46u as=0 * GROUND: gnd Xpand3_nand + A B C zb_int vdd gnd -+ sram_pnand3_0 ++ sram_2_16_1_freepdk45_pnand3_0 Xpand3_inv + zb_int Z vdd gnd -+ sram_pdriver_3 -.ENDS sram_pand3_0 ++ sram_2_16_1_freepdk45_pdriver_3 +.ENDS sram_2_16_1_freepdk45_pand3_0 -.SUBCKT sram_pinv_10 +* spice ptx M{0} {1} pmos_vtg m=3 w=0.9u l=0.05u pd=1.90u ps=1.90u as=0.11p ad=0.11p + +* spice ptx M{0} {1} nmos_vtg m=3 w=0.3u l=0.05u pd=0.70u ps=0.70u as=0.04p ad=0.04p + +.SUBCKT sram_2_16_1_freepdk45_pinv_9 + A Z vdd gnd * INPUT : A * OUTPUT: Z * POWER : vdd * GROUND: gnd -Mpinv_pmos Z A vdd vdd pmos_vtg m=1 w=0.27u l=0.05u pd=0.64u ps=0.64u as=0.03p ad=0.03p -Mpinv_nmos Z A gnd gnd nmos_vtg m=1 w=0.09u l=0.05u pd=0.28u ps=0.28u as=0.01p ad=0.01p -.ENDS sram_pinv_10 +Mpinv_pmos Z A vdd vdd pmos_vtg m=3 w=0.9u l=0.05u pd=1.90u ps=1.90u as=0.11p ad=0.11p +Mpinv_nmos Z A gnd gnd nmos_vtg m=3 w=0.3u l=0.05u pd=0.70u ps=0.70u as=0.04p ad=0.04p +.ENDS sram_2_16_1_freepdk45_pinv_9 -.SUBCKT sram_delay_chain -+ in out vdd gnd -* INPUT : in -* OUTPUT: out -* POWER : vdd -* GROUND: gnd -* fanouts: [4, 4, 4, 4, 4, 4, 4, 4, 4] -Xdinv0 -+ in dout_1 vdd gnd -+ sram_pinv_10 -Xdload_0_0 -+ dout_1 n_0_0 vdd gnd -+ sram_pinv_10 -Xdload_0_1 -+ dout_1 n_0_1 vdd gnd -+ sram_pinv_10 -Xdload_0_2 -+ dout_1 n_0_2 vdd gnd -+ sram_pinv_10 -Xdload_0_3 -+ dout_1 n_0_3 vdd gnd -+ sram_pinv_10 -Xdinv1 -+ dout_1 dout_2 vdd gnd -+ sram_pinv_10 -Xdload_1_0 -+ dout_2 n_1_0 vdd gnd -+ sram_pinv_10 -Xdload_1_1 -+ dout_2 n_1_1 vdd gnd -+ sram_pinv_10 -Xdload_1_2 -+ dout_2 n_1_2 vdd gnd -+ sram_pinv_10 -Xdload_1_3 -+ dout_2 n_1_3 vdd gnd -+ sram_pinv_10 -Xdinv2 -+ dout_2 dout_3 vdd gnd -+ sram_pinv_10 -Xdload_2_0 -+ dout_3 n_2_0 vdd gnd -+ sram_pinv_10 -Xdload_2_1 -+ dout_3 n_2_1 vdd gnd -+ sram_pinv_10 -Xdload_2_2 -+ dout_3 n_2_2 vdd gnd -+ sram_pinv_10 -Xdload_2_3 -+ dout_3 n_2_3 vdd gnd -+ sram_pinv_10 -Xdinv3 -+ dout_3 dout_4 vdd gnd -+ sram_pinv_10 -Xdload_3_0 -+ dout_4 n_3_0 vdd gnd -+ sram_pinv_10 -Xdload_3_1 -+ dout_4 n_3_1 vdd gnd -+ sram_pinv_10 -Xdload_3_2 -+ dout_4 n_3_2 vdd gnd -+ sram_pinv_10 -Xdload_3_3 -+ dout_4 n_3_3 vdd gnd -+ sram_pinv_10 -Xdinv4 -+ dout_4 dout_5 vdd gnd -+ sram_pinv_10 -Xdload_4_0 -+ dout_5 n_4_0 vdd gnd -+ sram_pinv_10 -Xdload_4_1 -+ dout_5 n_4_1 vdd gnd -+ sram_pinv_10 -Xdload_4_2 -+ dout_5 n_4_2 vdd gnd -+ sram_pinv_10 -Xdload_4_3 -+ dout_5 n_4_3 vdd gnd -+ sram_pinv_10 -Xdinv5 -+ dout_5 dout_6 vdd gnd -+ sram_pinv_10 -Xdload_5_0 -+ dout_6 n_5_0 vdd gnd -+ sram_pinv_10 -Xdload_5_1 -+ dout_6 n_5_1 vdd gnd -+ sram_pinv_10 -Xdload_5_2 -+ dout_6 n_5_2 vdd gnd -+ sram_pinv_10 -Xdload_5_3 -+ dout_6 n_5_3 vdd gnd -+ sram_pinv_10 -Xdinv6 -+ dout_6 dout_7 vdd gnd -+ sram_pinv_10 -Xdload_6_0 -+ dout_7 n_6_0 vdd gnd -+ sram_pinv_10 -Xdload_6_1 -+ dout_7 n_6_1 vdd gnd -+ sram_pinv_10 -Xdload_6_2 -+ dout_7 n_6_2 vdd gnd -+ sram_pinv_10 -Xdload_6_3 -+ dout_7 n_6_3 vdd gnd -+ sram_pinv_10 -Xdinv7 -+ dout_7 dout_8 vdd gnd -+ sram_pinv_10 -Xdload_7_0 -+ dout_8 n_7_0 vdd gnd -+ sram_pinv_10 -Xdload_7_1 -+ dout_8 n_7_1 vdd gnd -+ sram_pinv_10 -Xdload_7_2 -+ dout_8 n_7_2 vdd gnd -+ sram_pinv_10 -Xdload_7_3 -+ dout_8 n_7_3 vdd gnd -+ sram_pinv_10 -Xdinv8 -+ dout_8 out vdd gnd -+ sram_pinv_10 -Xdload_8_0 -+ out n_8_0 vdd gnd -+ sram_pinv_10 -Xdload_8_1 -+ out n_8_1 vdd gnd -+ sram_pinv_10 -Xdload_8_2 -+ out n_8_2 vdd gnd -+ sram_pinv_10 -Xdload_8_3 -+ out n_8_3 vdd gnd -+ sram_pinv_10 -.ENDS sram_delay_chain - -* spice ptx M{0} {1} nmos_vtg m=4 w=0.2925u l=0.05u pd=0.68u ps=0.68u as=0.04p ad=0.04p - -* spice ptx M{0} {1} pmos_vtg m=4 w=0.8775000000000001u l=0.05u pd=1.86u ps=1.86u as=0.11p ad=0.11p - -.SUBCKT sram_pinv_7 +.SUBCKT sram_2_16_1_freepdk45_pdriver_2 + A Z vdd gnd * INPUT : A * OUTPUT: Z * POWER : vdd * GROUND: gnd -Mpinv_pmos Z A vdd vdd pmos_vtg m=4 w=0.8775000000000001u l=0.05u pd=1.86u ps=1.86u as=0.11p ad=0.11p -Mpinv_nmos Z A gnd gnd nmos_vtg m=4 w=0.2925u l=0.05u pd=0.68u ps=0.68u as=0.04p ad=0.04p -.ENDS sram_pinv_7 - -.SUBCKT sram_pinv_6 -+ A Z vdd gnd -* INPUT : A -* OUTPUT: Z -* POWER : vdd -* GROUND: gnd -Mpinv_pmos Z A vdd vdd pmos_vtg m=2 w=0.54u l=0.05u pd=1.18u ps=1.18u as=0.07p ad=0.07p -Mpinv_nmos Z A gnd gnd nmos_vtg m=2 w=0.18u l=0.05u pd=0.46u ps=0.46u as=0.02p ad=0.02p -.ENDS sram_pinv_6 - -.SUBCKT sram_pdriver_0 -+ A Z vdd gnd -* INPUT : A -* OUTPUT: Z -* POWER : vdd -* GROUND: gnd -* sizes: [1, 1, 4, 13] -Xbuf_inv1 -+ A Zb1_int vdd gnd -+ sram_pinv_5 -Xbuf_inv2 -+ Zb1_int Zb2_int vdd gnd -+ sram_pinv_5 -Xbuf_inv3 -+ Zb2_int Zb3_int vdd gnd -+ sram_pinv_6 -Xbuf_inv4 -+ Zb3_int Z vdd gnd -+ sram_pinv_7 -.ENDS sram_pdriver_0 - -* spice ptx M{0} {1} pmos_vtg m=3 w=0.81u l=0.05u pd=1.72u ps=1.72u as=0.10p ad=0.10p - -* spice ptx M{0} {1} nmos_vtg m=3 w=0.27u l=0.05u pd=0.64u ps=0.64u as=0.03p ad=0.03p - -.SUBCKT sram_pinv_9 -+ A Z vdd gnd -* INPUT : A -* OUTPUT: Z -* POWER : vdd -* GROUND: gnd -Mpinv_pmos Z A vdd vdd pmos_vtg m=3 w=0.81u l=0.05u pd=1.72u ps=1.72u as=0.10p ad=0.10p -Mpinv_nmos Z A gnd gnd nmos_vtg m=3 w=0.27u l=0.05u pd=0.64u ps=0.64u as=0.03p ad=0.03p -.ENDS sram_pinv_9 - -.SUBCKT sram_pdriver_2 -+ A Z vdd gnd -* INPUT : A -* OUTPUT: Z -* POWER : vdd -* GROUND: gnd -* sizes: [9] +* sizes: [10] Xbuf_inv1 + A Z vdd gnd -+ sram_pinv_9 -.ENDS sram_pdriver_2 ++ sram_2_16_1_freepdk45_pinv_9 +.ENDS sram_2_16_1_freepdk45_pdriver_2 -.SUBCKT sram_pand3 +.SUBCKT sram_2_16_1_freepdk45_pand3 + A B C Z vdd gnd * INPUT : A * INPUT : B @@ -529,28 +562,13 @@ Xbuf_inv1 * GROUND: gnd Xpand3_nand + A B C zb_int vdd gnd -+ sram_pnand3_0 ++ sram_2_16_1_freepdk45_pnand3_0 Xpand3_inv + zb_int Z vdd gnd -+ sram_pdriver_2 -.ENDS sram_pand3 ++ sram_2_16_1_freepdk45_pdriver_2 +.ENDS sram_2_16_1_freepdk45_pand3 -.SUBCKT sram_pdriver_4 -+ A Z vdd gnd -* INPUT : A -* OUTPUT: Z -* POWER : vdd -* GROUND: gnd -* sizes: [1, 1] -Xbuf_inv1 -+ A Zb1_int vdd gnd -+ sram_pinv_5 -Xbuf_inv2 -+ Zb1_int Z vdd gnd -+ sram_pinv_5 -.ENDS sram_pdriver_4 - -.SUBCKT sram_control_logic_rw +.SUBCKT sram_2_16_1_freepdk45_control_logic_rw + csb web clk rbl_bl s_en w_en p_en_bar wl_en clk_buf vdd gnd * INPUT : csb * INPUT : web @@ -563,163 +581,74 @@ Xbuf_inv2 * OUTPUT: clk_buf * POWER : vdd * GROUND: gnd -* word_size 1 +* word_size 2 Xctrl_dffs + csb web cs_bar cs we_bar we clk_buf vdd gnd -+ sram_dff_buf_array ++ sram_2_16_1_freepdk45_dff_buf_array Xclkbuf + clk clk_buf vdd gnd -+ sram_pdriver_0 ++ sram_2_16_1_freepdk45_pdriver_0 Xinv_clk_bar + clk_buf clk_bar vdd gnd -+ sram_pinv_3 ++ sram_2_16_1_freepdk45_pinv_3 Xand2_gated_clk_bar + clk_bar cs gated_clk_bar vdd gnd -+ sram_pand2 ++ sram_2_16_1_freepdk45_pand2 Xand2_gated_clk_buf + clk_buf cs gated_clk_buf vdd gnd -+ sram_pand2 ++ sram_2_16_1_freepdk45_pand2 Xbuf_wl_en + gated_clk_bar wl_en vdd gnd -+ sram_pdriver_1 ++ sram_2_16_1_freepdk45_pdriver_1 Xrbl_bl_delay_inv + rbl_bl_delay rbl_bl_delay_bar vdd gnd -+ sram_pinv_3 ++ sram_2_16_1_freepdk45_pinv_3 Xw_en_and + we rbl_bl_delay_bar gated_clk_bar w_en vdd gnd -+ sram_pand3 ++ sram_2_16_1_freepdk45_pand3 Xbuf_s_en_and + rbl_bl_delay gated_clk_bar we_bar s_en vdd gnd -+ sram_pand3_0 ++ sram_2_16_1_freepdk45_pand3_0 Xdelay_chain + rbl_bl rbl_bl_delay vdd gnd -+ sram_delay_chain ++ sram_2_16_1_freepdk45_delay_chain Xnand_p_en_bar + gated_clk_buf rbl_bl_delay p_en_bar_unbuf vdd gnd -+ sram_pnand2_1 ++ sram_2_16_1_freepdk45_pnand2_1 Xbuf_p_en_bar + p_en_bar_unbuf p_en_bar vdd gnd -+ sram_pdriver_4 -.ENDS sram_control_logic_rw ++ sram_2_16_1_freepdk45_pdriver_4 +.ENDS sram_2_16_1_freepdk45_control_logic_rw -.SUBCKT sense_amp bl br dout en vdd gnd -M_1 dint net_1 vdd vdd pmos_vtg w=540.0n l=50.0n -M_3 net_1 dint vdd vdd pmos_vtg w=540.0n l=50.0n -M_2 dint net_1 net_2 gnd nmos_vtg w=270.0n l=50.0n -M_8 net_1 dint net_2 gnd nmos_vtg w=270.0n l=50.0n -M_5 bl en dint vdd pmos_vtg w=720.0n l=50.0n -M_6 br en net_1 vdd pmos_vtg w=720.0n l=50.0n -M_7 net_2 en gnd gnd nmos_vtg w=270.0n l=50.0n - -M_8 dout_bar dint vdd vdd pmos_vtg w=180.0n l=50.0n -M_9 dout_bar dint gnd gnd nmos_vtg w=90.0n l=50.0n -M_10 dout dout_bar vdd vdd pmos_vtg w=540.0n l=50.0n -M_11 dout dout_bar gnd gnd nmos_vtg w=270.0n l=50.0n -.ENDS sense_amp - - -.SUBCKT sram_sense_amp_array -+ data_0 bl_0 br_0 en vdd gnd -* OUTPUT: data_0 -* INPUT : bl_0 -* INPUT : br_0 -* INPUT : en -* POWER : vdd -* GROUND: gnd -* words_per_row: 1 -Xsa_d0 -+ bl_0 br_0 data_0 en vdd gnd -+ sense_amp -.ENDS sram_sense_amp_array - -.SUBCKT sram_precharge_0 -+ bl br en_bar vdd -* OUTPUT: bl -* OUTPUT: br -* INPUT : en_bar -* POWER : vdd -Mlower_pmos bl en_bar br vdd pmos_vtg m=1 w=0.27u l=0.05u pd=0.64u ps=0.64u as=0.03p ad=0.03p -Mupper_pmos1 bl en_bar vdd vdd pmos_vtg m=1 w=0.27u l=0.05u pd=0.64u ps=0.64u as=0.03p ad=0.03p -Mupper_pmos2 br en_bar vdd vdd pmos_vtg m=1 w=0.27u l=0.05u pd=0.64u ps=0.64u as=0.03p ad=0.03p -.ENDS sram_precharge_0 - -.SUBCKT sram_precharge_array -+ bl_0 br_0 bl_1 br_1 en_bar vdd -* OUTPUT: bl_0 -* OUTPUT: br_0 -* OUTPUT: bl_1 -* OUTPUT: br_1 -* INPUT : en_bar -* POWER : vdd -* cols: 2 size: 1 bl: bl br: br -Xpre_column_0 -+ bl_0 br_0 en_bar vdd -+ sram_precharge_0 -Xpre_column_1 -+ bl_1 br_1 en_bar vdd -+ sram_precharge_0 -.ENDS sram_precharge_array - -.SUBCKT write_driver din bl br en vdd gnd -*inverters for enable and data input -minP bl_bar din vdd vdd pmos_vtg w=360.000000n l=50.000000n -minN bl_bar din gnd gnd nmos_vtg w=180.000000n l=50.000000n -moutP en_bar en vdd vdd pmos_vtg w=360.000000n l=50.000000n -moutN en_bar en gnd gnd nmos_vtg w=180.000000n l=50.000000n - -*tristate for BL -mout0P int1 bl_bar vdd vdd pmos_vtg w=360.000000n l=50.000000n -mout0P2 bl en_bar int1 vdd pmos_vtg w=360.000000n l=50.000000n -mout0N bl en int2 gnd nmos_vtg w=180.000000n l=50.000000n -mout0N2 int2 bl_bar gnd gnd nmos_vtg w=180.000000n l=50.000000n - -*tristate for BR -mout1P int3 din vdd vdd pmos_vtg w=360.000000n l=50.000000n -mout1P2 br en_bar int3 vdd pmos_vtg w=360.000000n l=50.000000n -mout1N br en int4 gnd nmos_vtg w=180.000000n l=50.000000n -mout1N2 int4 din gnd gnd nmos_vtg w=180.000000n l=50.000000n -.ENDS write_driver - - -.SUBCKT sram_write_driver_array -+ data_0 bl_0 br_0 en vdd gnd -* INPUT : data_0 -* OUTPUT: bl_0 -* OUTPUT: br_0 -* INPUT : en -* POWER : vdd -* GROUND: gnd -* word_size 1 -Xwrite_driver0 -+ data_0 bl_0 br_0 en vdd gnd -+ write_driver -.ENDS sram_write_driver_array - -.SUBCKT sram_port_data -+ rbl_bl rbl_br bl_0 br_0 dout_0 din_0 s_en p_en_bar w_en vdd gnd -* INOUT : rbl_bl -* INOUT : rbl_br -* INOUT : bl_0 -* INOUT : br_0 -* OUTPUT: dout_0 +.SUBCKT sram_2_16_1_freepdk45_row_addr_dff ++ din_0 din_1 din_2 din_3 dout_0 dout_1 dout_2 dout_3 clk vdd gnd * INPUT : din_0 -* INPUT : s_en -* INPUT : p_en_bar -* INPUT : w_en +* INPUT : din_1 +* INPUT : din_2 +* INPUT : din_3 +* OUTPUT: dout_0 +* OUTPUT: dout_1 +* OUTPUT: dout_2 +* OUTPUT: dout_3 +* INPUT : clk * POWER : vdd * GROUND: gnd -Xprecharge_array0 -+ rbl_bl rbl_br bl_0 br_0 p_en_bar vdd -+ sram_precharge_array -Xsense_amp_array0 -+ dout_0 bl_0 br_0 s_en vdd gnd -+ sram_sense_amp_array -Xwrite_driver_array0 -+ din_0 bl_0 br_0 w_en vdd gnd -+ sram_write_driver_array -.ENDS sram_port_data +* rows: 4 cols: 1 +Xdff_r0_c0 ++ din_0 dout_0 clk vdd gnd ++ dff +Xdff_r1_c0 ++ din_1 dout_1 clk vdd gnd ++ dff +Xdff_r2_c0 ++ din_2 dout_2 clk vdd gnd ++ dff +Xdff_r3_c0 ++ din_3 dout_3 clk vdd gnd ++ dff +.ENDS sram_2_16_1_freepdk45_row_addr_dff -.SUBCKT sram_pnand2 +.SUBCKT sram_2_16_1_freepdk45_pnand2 + A B Z vdd gnd * INPUT : A * INPUT : B @@ -730,9 +659,9 @@ Mpnand2_pmos1 vdd A Z vdd pmos_vtg m=1 w=0.27u l=0.05u pd=0.64u ps=0.64u as=0.03 Mpnand2_pmos2 Z B vdd vdd pmos_vtg m=1 w=0.27u l=0.05u pd=0.64u ps=0.64u as=0.03p ad=0.03p Mpnand2_nmos1 Z B net1 gnd nmos_vtg m=1 w=0.18u l=0.05u pd=0.46u ps=0.46u as=0.02p ad=0.02p Mpnand2_nmos2 net1 A gnd gnd nmos_vtg m=1 w=0.18u l=0.05u pd=0.46u ps=0.46u as=0.02p ad=0.02p -.ENDS sram_pnand2 +.ENDS sram_2_16_1_freepdk45_pnand2 -.SUBCKT sram_pinv +.SUBCKT sram_2_16_1_freepdk45_pinv + A Z vdd gnd * INPUT : A * OUTPUT: Z @@ -740,9 +669,9 @@ Mpnand2_nmos2 net1 A gnd gnd nmos_vtg m=1 w=0.18u l=0.05u pd=0.46u ps=0.46u as=0 * GROUND: gnd Mpinv_pmos Z A vdd vdd pmos_vtg m=1 w=0.27u l=0.05u pd=0.64u ps=0.64u as=0.03p ad=0.03p Mpinv_nmos Z A gnd gnd nmos_vtg m=1 w=0.09u l=0.05u pd=0.28u ps=0.28u as=0.01p ad=0.01p -.ENDS sram_pinv +.ENDS sram_2_16_1_freepdk45_pinv -.SUBCKT sram_and2_dec_0 +.SUBCKT sram_2_16_1_freepdk45_and2_dec_0 + A B Z vdd gnd * INPUT : A * INPUT : B @@ -752,13 +681,13 @@ Mpinv_nmos Z A gnd gnd nmos_vtg m=1 w=0.09u l=0.05u pd=0.28u ps=0.28u as=0.01p a * size: 1 Xpand2_dec_nand + A B zb_int vdd gnd -+ sram_pnand2 ++ sram_2_16_1_freepdk45_pnand2 Xpand2_dec_inv + zb_int Z vdd gnd -+ sram_pinv -.ENDS sram_and2_dec_0 ++ sram_2_16_1_freepdk45_pinv +.ENDS sram_2_16_1_freepdk45_and2_dec_0 -.SUBCKT sram_and2_dec +.SUBCKT sram_2_16_1_freepdk45_and2_dec + A B Z vdd gnd * INPUT : A * INPUT : B @@ -768,13 +697,13 @@ Xpand2_dec_inv * size: 1 Xpand2_dec_nand + A B zb_int vdd gnd -+ sram_pnand2 ++ sram_2_16_1_freepdk45_pnand2 Xpand2_dec_inv + zb_int Z vdd gnd -+ sram_pinv -.ENDS sram_and2_dec ++ sram_2_16_1_freepdk45_pinv +.ENDS sram_2_16_1_freepdk45_and2_dec -.SUBCKT sram_hierarchical_predecode2x4 +.SUBCKT sram_2_16_1_freepdk45_hierarchical_predecode2x4 + in_0 in_1 out_0 out_1 out_2 out_3 vdd gnd * INPUT : in_0 * INPUT : in_1 @@ -786,25 +715,25 @@ Xpand2_dec_inv * GROUND: gnd Xpre_inv_0 + in_0 inbar_0 vdd gnd -+ sram_pinv ++ sram_2_16_1_freepdk45_pinv Xpre_inv_1 + in_1 inbar_1 vdd gnd -+ sram_pinv ++ sram_2_16_1_freepdk45_pinv XXpre2x4_and_0 + inbar_0 inbar_1 out_0 vdd gnd -+ sram_and2_dec ++ sram_2_16_1_freepdk45_and2_dec XXpre2x4_and_1 + in_0 inbar_1 out_1 vdd gnd -+ sram_and2_dec ++ sram_2_16_1_freepdk45_and2_dec XXpre2x4_and_2 + inbar_0 in_1 out_2 vdd gnd -+ sram_and2_dec ++ sram_2_16_1_freepdk45_and2_dec XXpre2x4_and_3 + in_0 in_1 out_3 vdd gnd -+ sram_and2_dec -.ENDS sram_hierarchical_predecode2x4 ++ sram_2_16_1_freepdk45_and2_dec +.ENDS sram_2_16_1_freepdk45_hierarchical_predecode2x4 -.SUBCKT sram_hierarchical_decoder +.SUBCKT sram_2_16_1_freepdk45_hierarchical_decoder + addr_0 addr_1 addr_2 addr_3 decode_0 decode_1 decode_2 decode_3 + decode_4 decode_5 decode_6 decode_7 decode_8 decode_9 decode_10 + decode_11 decode_12 decode_13 decode_14 decode_15 vdd gnd @@ -832,61 +761,61 @@ XXpre2x4_and_3 * GROUND: gnd Xpre_0 + addr_0 addr_1 out_0 out_1 out_2 out_3 vdd gnd -+ sram_hierarchical_predecode2x4 ++ sram_2_16_1_freepdk45_hierarchical_predecode2x4 Xpre_1 + addr_2 addr_3 out_4 out_5 out_6 out_7 vdd gnd -+ sram_hierarchical_predecode2x4 ++ sram_2_16_1_freepdk45_hierarchical_predecode2x4 XDEC_AND_0 + out_0 out_4 decode_0 vdd gnd -+ sram_and2_dec ++ sram_2_16_1_freepdk45_and2_dec XDEC_AND_4 + out_0 out_5 decode_4 vdd gnd -+ sram_and2_dec ++ sram_2_16_1_freepdk45_and2_dec XDEC_AND_8 + out_0 out_6 decode_8 vdd gnd -+ sram_and2_dec ++ sram_2_16_1_freepdk45_and2_dec XDEC_AND_12 + out_0 out_7 decode_12 vdd gnd -+ sram_and2_dec ++ sram_2_16_1_freepdk45_and2_dec XDEC_AND_1 + out_1 out_4 decode_1 vdd gnd -+ sram_and2_dec ++ sram_2_16_1_freepdk45_and2_dec XDEC_AND_5 + out_1 out_5 decode_5 vdd gnd -+ sram_and2_dec ++ sram_2_16_1_freepdk45_and2_dec XDEC_AND_9 + out_1 out_6 decode_9 vdd gnd -+ sram_and2_dec ++ sram_2_16_1_freepdk45_and2_dec XDEC_AND_13 + out_1 out_7 decode_13 vdd gnd -+ sram_and2_dec ++ sram_2_16_1_freepdk45_and2_dec XDEC_AND_2 + out_2 out_4 decode_2 vdd gnd -+ sram_and2_dec ++ sram_2_16_1_freepdk45_and2_dec XDEC_AND_6 + out_2 out_5 decode_6 vdd gnd -+ sram_and2_dec ++ sram_2_16_1_freepdk45_and2_dec XDEC_AND_10 + out_2 out_6 decode_10 vdd gnd -+ sram_and2_dec ++ sram_2_16_1_freepdk45_and2_dec XDEC_AND_14 + out_2 out_7 decode_14 vdd gnd -+ sram_and2_dec ++ sram_2_16_1_freepdk45_and2_dec XDEC_AND_3 + out_3 out_4 decode_3 vdd gnd -+ sram_and2_dec ++ sram_2_16_1_freepdk45_and2_dec XDEC_AND_7 + out_3 out_5 decode_7 vdd gnd -+ sram_and2_dec ++ sram_2_16_1_freepdk45_and2_dec XDEC_AND_11 + out_3 out_6 decode_11 vdd gnd -+ sram_and2_dec ++ sram_2_16_1_freepdk45_and2_dec XDEC_AND_15 + out_3 out_7 decode_15 vdd gnd -+ sram_and2_dec -.ENDS sram_hierarchical_decoder ++ sram_2_16_1_freepdk45_and2_dec +.ENDS sram_2_16_1_freepdk45_hierarchical_decoder -.SUBCKT sram_wordline_driver +.SUBCKT sram_2_16_1_freepdk45_wordline_driver + A B Z vdd gnd * INPUT : A * INPUT : B @@ -895,13 +824,13 @@ XDEC_AND_15 * GROUND: gnd Xwld_nand + A B zb_int vdd gnd -+ sram_pnand2 ++ sram_2_16_1_freepdk45_pnand2 Xwl_driver + zb_int Z vdd gnd -+ sram_pinv -.ENDS sram_wordline_driver ++ sram_2_16_1_freepdk45_pinv +.ENDS sram_2_16_1_freepdk45_wordline_driver -.SUBCKT sram_wordline_driver_array +.SUBCKT sram_2_16_1_freepdk45_wordline_driver_array + in_0 in_1 in_2 in_3 in_4 in_5 in_6 in_7 in_8 in_9 in_10 in_11 in_12 + in_13 in_14 in_15 wl_0 wl_1 wl_2 wl_3 wl_4 wl_5 wl_6 wl_7 wl_8 wl_9 + wl_10 wl_11 wl_12 wl_13 wl_14 wl_15 en vdd gnd @@ -940,58 +869,58 @@ Xwl_driver * INPUT : en * POWER : vdd * GROUND: gnd -* rows: 16 cols: 1 +* rows: 16 cols: 2 Xwl_driver_and0 + in_0 en wl_0 vdd gnd -+ sram_wordline_driver ++ sram_2_16_1_freepdk45_wordline_driver Xwl_driver_and1 + in_1 en wl_1 vdd gnd -+ sram_wordline_driver ++ sram_2_16_1_freepdk45_wordline_driver Xwl_driver_and2 + in_2 en wl_2 vdd gnd -+ sram_wordline_driver ++ sram_2_16_1_freepdk45_wordline_driver Xwl_driver_and3 + in_3 en wl_3 vdd gnd -+ sram_wordline_driver ++ sram_2_16_1_freepdk45_wordline_driver Xwl_driver_and4 + in_4 en wl_4 vdd gnd -+ sram_wordline_driver ++ sram_2_16_1_freepdk45_wordline_driver Xwl_driver_and5 + in_5 en wl_5 vdd gnd -+ sram_wordline_driver ++ sram_2_16_1_freepdk45_wordline_driver Xwl_driver_and6 + in_6 en wl_6 vdd gnd -+ sram_wordline_driver ++ sram_2_16_1_freepdk45_wordline_driver Xwl_driver_and7 + in_7 en wl_7 vdd gnd -+ sram_wordline_driver ++ sram_2_16_1_freepdk45_wordline_driver Xwl_driver_and8 + in_8 en wl_8 vdd gnd -+ sram_wordline_driver ++ sram_2_16_1_freepdk45_wordline_driver Xwl_driver_and9 + in_9 en wl_9 vdd gnd -+ sram_wordline_driver ++ sram_2_16_1_freepdk45_wordline_driver Xwl_driver_and10 + in_10 en wl_10 vdd gnd -+ sram_wordline_driver ++ sram_2_16_1_freepdk45_wordline_driver Xwl_driver_and11 + in_11 en wl_11 vdd gnd -+ sram_wordline_driver ++ sram_2_16_1_freepdk45_wordline_driver Xwl_driver_and12 + in_12 en wl_12 vdd gnd -+ sram_wordline_driver ++ sram_2_16_1_freepdk45_wordline_driver Xwl_driver_and13 + in_13 en wl_13 vdd gnd -+ sram_wordline_driver ++ sram_2_16_1_freepdk45_wordline_driver Xwl_driver_and14 + in_14 en wl_14 vdd gnd -+ sram_wordline_driver ++ sram_2_16_1_freepdk45_wordline_driver Xwl_driver_and15 + in_15 en wl_15 vdd gnd -+ sram_wordline_driver -.ENDS sram_wordline_driver_array ++ sram_2_16_1_freepdk45_wordline_driver +.ENDS sram_2_16_1_freepdk45_wordline_driver_array -.SUBCKT sram_port_address +.SUBCKT sram_2_16_1_freepdk45_port_address + addr_0 addr_1 addr_2 addr_3 wl_en wl_0 wl_1 wl_2 wl_3 wl_4 wl_5 wl_6 + wl_7 wl_8 wl_9 wl_10 wl_11 wl_12 wl_13 wl_14 wl_15 rbl_wl vdd gnd * INPUT : addr_0 @@ -1022,17 +951,156 @@ Xrow_decoder + addr_0 addr_1 addr_2 addr_3 dec_out_0 dec_out_1 dec_out_2 dec_out_3 + dec_out_4 dec_out_5 dec_out_6 dec_out_7 dec_out_8 dec_out_9 dec_out_10 + dec_out_11 dec_out_12 dec_out_13 dec_out_14 dec_out_15 vdd gnd -+ sram_hierarchical_decoder ++ sram_2_16_1_freepdk45_hierarchical_decoder Xwordline_driver + dec_out_0 dec_out_1 dec_out_2 dec_out_3 dec_out_4 dec_out_5 dec_out_6 + dec_out_7 dec_out_8 dec_out_9 dec_out_10 dec_out_11 dec_out_12 + dec_out_13 dec_out_14 dec_out_15 wl_0 wl_1 wl_2 wl_3 wl_4 wl_5 wl_6 + wl_7 wl_8 wl_9 wl_10 wl_11 wl_12 wl_13 wl_14 wl_15 wl_en vdd gnd -+ sram_wordline_driver_array ++ sram_2_16_1_freepdk45_wordline_driver_array Xrbl_driver + wl_en vdd rbl_wl vdd gnd -+ sram_and2_dec_0 -.ENDS sram_port_address ++ sram_2_16_1_freepdk45_and2_dec_0 +.ENDS sram_2_16_1_freepdk45_port_address + +.SUBCKT write_driver din bl br en vdd gnd +*inverters for enable and data input +minP bl_bar din vdd vdd pmos_vtg w=360.000000n l=50.000000n +minN bl_bar din gnd gnd nmos_vtg w=180.000000n l=50.000000n +moutP en_bar en vdd vdd pmos_vtg w=360.000000n l=50.000000n +moutN en_bar en gnd gnd nmos_vtg w=180.000000n l=50.000000n + +*tristate for BL +mout0P int1 bl_bar vdd vdd pmos_vtg w=360.000000n l=50.000000n +mout0P2 bl en_bar int1 vdd pmos_vtg w=360.000000n l=50.000000n +mout0N bl en int2 gnd nmos_vtg w=180.000000n l=50.000000n +mout0N2 int2 bl_bar gnd gnd nmos_vtg w=180.000000n l=50.000000n + +*tristate for BR +mout1P int3 din vdd vdd pmos_vtg w=360.000000n l=50.000000n +mout1P2 br en_bar int3 vdd pmos_vtg w=360.000000n l=50.000000n +mout1N br en int4 gnd nmos_vtg w=180.000000n l=50.000000n +mout1N2 int4 din gnd gnd nmos_vtg w=180.000000n l=50.000000n +.ENDS write_driver + + +.SUBCKT sram_2_16_1_freepdk45_write_driver_array ++ data_0 data_1 bl_0 br_0 bl_1 br_1 en vdd gnd +* INPUT : data_0 +* INPUT : data_1 +* OUTPUT: bl_0 +* OUTPUT: br_0 +* OUTPUT: bl_1 +* OUTPUT: br_1 +* INPUT : en +* POWER : vdd +* GROUND: gnd +* word_size 2 +Xwrite_driver0 ++ data_0 bl_0 br_0 en vdd gnd ++ write_driver +Xwrite_driver1 ++ data_1 bl_1 br_1 en vdd gnd ++ write_driver +.ENDS sram_2_16_1_freepdk45_write_driver_array + +.SUBCKT sense_amp bl br dout en vdd gnd +M_1 dint net_1 vdd vdd pmos_vtg w=540.0n l=50.0n +M_3 net_1 dint vdd vdd pmos_vtg w=540.0n l=50.0n +M_2 dint net_1 net_2 gnd nmos_vtg w=270.0n l=50.0n +M_8 net_1 dint net_2 gnd nmos_vtg w=270.0n l=50.0n +M_5 bl en dint vdd pmos_vtg w=720.0n l=50.0n +M_6 br en net_1 vdd pmos_vtg w=720.0n l=50.0n +M_7 net_2 en gnd gnd nmos_vtg w=270.0n l=50.0n + +M_9 dout_bar dint vdd vdd pmos_vtg w=180.0n l=50.0n +M_10 dout_bar dint gnd gnd nmos_vtg w=90.0n l=50.0n +M_11 dout dout_bar vdd vdd pmos_vtg w=540.0n l=50.0n +M_12 dout dout_bar gnd gnd nmos_vtg w=270.0n l=50.0n +.ENDS sense_amp + + +.SUBCKT sram_2_16_1_freepdk45_sense_amp_array ++ data_0 bl_0 br_0 data_1 bl_1 br_1 en vdd gnd +* OUTPUT: data_0 +* INPUT : bl_0 +* INPUT : br_0 +* OUTPUT: data_1 +* INPUT : bl_1 +* INPUT : br_1 +* INPUT : en +* POWER : vdd +* GROUND: gnd +* words_per_row: 1 +Xsa_d0 ++ bl_0 br_0 data_0 en vdd gnd ++ sense_amp +Xsa_d1 ++ bl_1 br_1 data_1 en vdd gnd ++ sense_amp +.ENDS sram_2_16_1_freepdk45_sense_amp_array + +.SUBCKT sram_2_16_1_freepdk45_precharge_0 ++ bl br en_bar vdd +* OUTPUT: bl +* OUTPUT: br +* INPUT : en_bar +* POWER : vdd +Mlower_pmos bl en_bar br vdd pmos_vtg m=1 w=0.27u l=0.05u pd=0.64u ps=0.64u as=0.03p ad=0.03p +Mupper_pmos1 bl en_bar vdd vdd pmos_vtg m=1 w=0.27u l=0.05u pd=0.64u ps=0.64u as=0.03p ad=0.03p +Mupper_pmos2 br en_bar vdd vdd pmos_vtg m=1 w=0.27u l=0.05u pd=0.64u ps=0.64u as=0.03p ad=0.03p +.ENDS sram_2_16_1_freepdk45_precharge_0 + +.SUBCKT sram_2_16_1_freepdk45_precharge_array ++ bl_0 br_0 bl_1 br_1 bl_2 br_2 en_bar vdd +* OUTPUT: bl_0 +* OUTPUT: br_0 +* OUTPUT: bl_1 +* OUTPUT: br_1 +* OUTPUT: bl_2 +* OUTPUT: br_2 +* INPUT : en_bar +* POWER : vdd +* cols: 3 size: 1 bl: bl br: br +Xpre_column_0 ++ bl_0 br_0 en_bar vdd ++ sram_2_16_1_freepdk45_precharge_0 +Xpre_column_1 ++ bl_1 br_1 en_bar vdd ++ sram_2_16_1_freepdk45_precharge_0 +Xpre_column_2 ++ bl_2 br_2 en_bar vdd ++ sram_2_16_1_freepdk45_precharge_0 +.ENDS sram_2_16_1_freepdk45_precharge_array + +.SUBCKT sram_2_16_1_freepdk45_port_data ++ rbl_bl rbl_br bl_0 br_0 bl_1 br_1 dout_0 dout_1 din_0 din_1 s_en ++ p_en_bar w_en vdd gnd +* INOUT : rbl_bl +* INOUT : rbl_br +* INOUT : bl_0 +* INOUT : br_0 +* INOUT : bl_1 +* INOUT : br_1 +* OUTPUT: dout_0 +* OUTPUT: dout_1 +* INPUT : din_0 +* INPUT : din_1 +* INPUT : s_en +* INPUT : p_en_bar +* INPUT : w_en +* POWER : vdd +* GROUND: gnd +Xprecharge_array0 ++ rbl_bl rbl_br bl_0 br_0 bl_1 br_1 p_en_bar vdd ++ sram_2_16_1_freepdk45_precharge_array +Xsense_amp_array0 ++ dout_0 bl_0 br_0 dout_1 bl_1 br_1 s_en vdd gnd ++ sram_2_16_1_freepdk45_sense_amp_array +Xwrite_driver_array0 ++ din_0 din_1 bl_0 br_0 bl_1 br_1 w_en vdd gnd ++ sram_2_16_1_freepdk45_write_driver_array +.ENDS sram_2_16_1_freepdk45_port_data .SUBCKT dummy_cell_1rw bl br wl vdd gnd * Inverter 1 @@ -1049,7 +1117,7 @@ MM2 br_noconn wl Q_bar gnd NMOS_VTG W=135.00n L=50n .ENDS dummy_cell_1rw -.SUBCKT sram_dummy_array_2 +.SUBCKT sram_2_16_1_freepdk45_dummy_array_3 + bl_0_0 br_0_0 wl_0_0 wl_0_1 wl_0_2 wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 + wl_0_8 wl_0_9 wl_0_10 wl_0_11 wl_0_12 wl_0_13 wl_0_14 wl_0_15 wl_0_16 + wl_0_17 wl_0_18 vdd gnd @@ -1133,105 +1201,7 @@ Xbit_r17_c0 Xbit_r18_c0 + bl_0_0 br_0_0 wl_0_18 vdd gnd + dummy_cell_1rw -.ENDS sram_dummy_array_2 - -.SUBCKT sram_dummy_array_3 -+ bl_0_0 br_0_0 wl_0_0 wl_0_1 wl_0_2 wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 -+ wl_0_8 wl_0_9 wl_0_10 wl_0_11 wl_0_12 wl_0_13 wl_0_14 wl_0_15 wl_0_16 -+ wl_0_17 wl_0_18 vdd gnd -* INOUT : bl_0_0 -* INOUT : br_0_0 -* INPUT : wl_0_0 -* INPUT : wl_0_1 -* INPUT : wl_0_2 -* INPUT : wl_0_3 -* INPUT : wl_0_4 -* INPUT : wl_0_5 -* INPUT : wl_0_6 -* INPUT : wl_0_7 -* INPUT : wl_0_8 -* INPUT : wl_0_9 -* INPUT : wl_0_10 -* INPUT : wl_0_11 -* INPUT : wl_0_12 -* INPUT : wl_0_13 -* INPUT : wl_0_14 -* INPUT : wl_0_15 -* INPUT : wl_0_16 -* INPUT : wl_0_17 -* INPUT : wl_0_18 -* POWER : vdd -* GROUND: gnd -Xbit_r0_c0 -+ bl_0_0 br_0_0 wl_0_0 vdd gnd -+ dummy_cell_1rw -Xbit_r1_c0 -+ bl_0_0 br_0_0 wl_0_1 vdd gnd -+ dummy_cell_1rw -Xbit_r2_c0 -+ bl_0_0 br_0_0 wl_0_2 vdd gnd -+ dummy_cell_1rw -Xbit_r3_c0 -+ bl_0_0 br_0_0 wl_0_3 vdd gnd -+ dummy_cell_1rw -Xbit_r4_c0 -+ bl_0_0 br_0_0 wl_0_4 vdd gnd -+ dummy_cell_1rw -Xbit_r5_c0 -+ bl_0_0 br_0_0 wl_0_5 vdd gnd -+ dummy_cell_1rw -Xbit_r6_c0 -+ bl_0_0 br_0_0 wl_0_6 vdd gnd -+ dummy_cell_1rw -Xbit_r7_c0 -+ bl_0_0 br_0_0 wl_0_7 vdd gnd -+ dummy_cell_1rw -Xbit_r8_c0 -+ bl_0_0 br_0_0 wl_0_8 vdd gnd -+ dummy_cell_1rw -Xbit_r9_c0 -+ bl_0_0 br_0_0 wl_0_9 vdd gnd -+ dummy_cell_1rw -Xbit_r10_c0 -+ bl_0_0 br_0_0 wl_0_10 vdd gnd -+ dummy_cell_1rw -Xbit_r11_c0 -+ bl_0_0 br_0_0 wl_0_11 vdd gnd -+ dummy_cell_1rw -Xbit_r12_c0 -+ bl_0_0 br_0_0 wl_0_12 vdd gnd -+ dummy_cell_1rw -Xbit_r13_c0 -+ bl_0_0 br_0_0 wl_0_13 vdd gnd -+ dummy_cell_1rw -Xbit_r14_c0 -+ bl_0_0 br_0_0 wl_0_14 vdd gnd -+ dummy_cell_1rw -Xbit_r15_c0 -+ bl_0_0 br_0_0 wl_0_15 vdd gnd -+ dummy_cell_1rw -Xbit_r16_c0 -+ bl_0_0 br_0_0 wl_0_16 vdd gnd -+ dummy_cell_1rw -Xbit_r17_c0 -+ bl_0_0 br_0_0 wl_0_17 vdd gnd -+ dummy_cell_1rw -Xbit_r18_c0 -+ bl_0_0 br_0_0 wl_0_18 vdd gnd -+ dummy_cell_1rw -.ENDS sram_dummy_array_3 - -.SUBCKT sram_dummy_array -+ bl_0_0 br_0_0 wl_0_0 vdd gnd -* INOUT : bl_0_0 -* INOUT : br_0_0 -* INPUT : wl_0_0 -* POWER : vdd -* GROUND: gnd -Xbit_r0_c0 -+ bl_0_0 br_0_0 wl_0_0 vdd gnd -+ dummy_cell_1rw -.ENDS sram_dummy_array +.ENDS sram_2_16_1_freepdk45_dummy_array_3 .SUBCKT cell_1rw bl br wl vdd gnd * Inverter 1 @@ -1248,11 +1218,14 @@ MM2 br wl Q_bar gnd NMOS_VTG W=135.00n L=50n .ENDS cell_1rw -.SUBCKT sram_bitcell_array -+ bl_0_0 br_0_0 wl_0_0 wl_0_1 wl_0_2 wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 -+ wl_0_8 wl_0_9 wl_0_10 wl_0_11 wl_0_12 wl_0_13 wl_0_14 wl_0_15 vdd gnd +.SUBCKT sram_2_16_1_freepdk45_bitcell_array ++ bl_0_0 br_0_0 bl_0_1 br_0_1 wl_0_0 wl_0_1 wl_0_2 wl_0_3 wl_0_4 wl_0_5 ++ wl_0_6 wl_0_7 wl_0_8 wl_0_9 wl_0_10 wl_0_11 wl_0_12 wl_0_13 wl_0_14 ++ wl_0_15 vdd gnd * INOUT : bl_0_0 * INOUT : br_0_0 +* INOUT : bl_0_1 +* INOUT : br_0_1 * INPUT : wl_0_0 * INPUT : wl_0_1 * INPUT : wl_0_2 @@ -1271,7 +1244,7 @@ MM2 br wl Q_bar gnd NMOS_VTG W=135.00n L=50n * INPUT : wl_0_15 * POWER : vdd * GROUND: gnd -* rows: 16 cols: 1 +* rows: 16 cols: 2 Xbit_r0_c0 + bl_0_0 br_0_0 wl_0_0 vdd gnd + cell_1rw @@ -1320,7 +1293,72 @@ Xbit_r14_c0 Xbit_r15_c0 + bl_0_0 br_0_0 wl_0_15 vdd gnd + cell_1rw -.ENDS sram_bitcell_array +Xbit_r0_c1 ++ bl_0_1 br_0_1 wl_0_0 vdd gnd ++ cell_1rw +Xbit_r1_c1 ++ bl_0_1 br_0_1 wl_0_1 vdd gnd ++ cell_1rw +Xbit_r2_c1 ++ bl_0_1 br_0_1 wl_0_2 vdd gnd ++ cell_1rw +Xbit_r3_c1 ++ bl_0_1 br_0_1 wl_0_3 vdd gnd ++ cell_1rw +Xbit_r4_c1 ++ bl_0_1 br_0_1 wl_0_4 vdd gnd ++ cell_1rw +Xbit_r5_c1 ++ bl_0_1 br_0_1 wl_0_5 vdd gnd ++ cell_1rw +Xbit_r6_c1 ++ bl_0_1 br_0_1 wl_0_6 vdd gnd ++ cell_1rw +Xbit_r7_c1 ++ bl_0_1 br_0_1 wl_0_7 vdd gnd ++ cell_1rw +Xbit_r8_c1 ++ bl_0_1 br_0_1 wl_0_8 vdd gnd ++ cell_1rw +Xbit_r9_c1 ++ bl_0_1 br_0_1 wl_0_9 vdd gnd ++ cell_1rw +Xbit_r10_c1 ++ bl_0_1 br_0_1 wl_0_10 vdd gnd ++ cell_1rw +Xbit_r11_c1 ++ bl_0_1 br_0_1 wl_0_11 vdd gnd ++ cell_1rw +Xbit_r12_c1 ++ bl_0_1 br_0_1 wl_0_12 vdd gnd ++ cell_1rw +Xbit_r13_c1 ++ bl_0_1 br_0_1 wl_0_13 vdd gnd ++ cell_1rw +Xbit_r14_c1 ++ bl_0_1 br_0_1 wl_0_14 vdd gnd ++ cell_1rw +Xbit_r15_c1 ++ bl_0_1 br_0_1 wl_0_15 vdd gnd ++ cell_1rw +.ENDS sram_2_16_1_freepdk45_bitcell_array + +.SUBCKT sram_2_16_1_freepdk45_dummy_array ++ bl_0_0 br_0_0 bl_0_1 br_0_1 wl_0_0 vdd gnd +* INOUT : bl_0_0 +* INOUT : br_0_0 +* INOUT : bl_0_1 +* INOUT : br_0_1 +* INPUT : wl_0_0 +* POWER : vdd +* GROUND: gnd +Xbit_r0_c0 ++ bl_0_0 br_0_0 wl_0_0 vdd gnd ++ dummy_cell_1rw +Xbit_r0_c1 ++ bl_0_1 br_0_1 wl_0_0 vdd gnd ++ dummy_cell_1rw +.ENDS sram_2_16_1_freepdk45_dummy_array .SUBCKT replica_cell_1rw bl br wl vdd gnd * Inverter 1 @@ -1337,7 +1375,7 @@ MM2 br wl vdd gnd NMOS_VTG W=135.00n L=50n .ENDS cell_1rw -.SUBCKT sram_replica_column +.SUBCKT sram_2_16_1_freepdk45_replica_column + bl_0_0 br_0_0 wl_0_0 wl_0_1 wl_0_2 wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 + wl_0_8 wl_0_9 wl_0_10 wl_0_11 wl_0_12 wl_0_13 wl_0_14 wl_0_15 wl_0_16 + vdd gnd @@ -1413,16 +1451,18 @@ Xrbc_15 Xrbc_16 + bl_0_0 br_0_0 wl_0_16 vdd gnd + replica_cell_1rw -.ENDS sram_replica_column +.ENDS sram_2_16_1_freepdk45_replica_column -.SUBCKT sram_replica_bitcell_array -+ rbl_bl_0_0 rbl_br_0_0 bl_0_0 br_0_0 rbl_wl_0_0 wl_0_0 wl_0_1 wl_0_2 -+ wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 wl_0_8 wl_0_9 wl_0_10 wl_0_11 -+ wl_0_12 wl_0_13 wl_0_14 wl_0_15 vdd gnd +.SUBCKT sram_2_16_1_freepdk45_replica_bitcell_array ++ rbl_bl_0_0 rbl_br_0_0 bl_0_0 br_0_0 bl_0_1 br_0_1 rbl_wl_0_0 wl_0_0 ++ wl_0_1 wl_0_2 wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 wl_0_8 wl_0_9 wl_0_10 ++ wl_0_11 wl_0_12 wl_0_13 wl_0_14 wl_0_15 vdd gnd * INOUT : rbl_bl_0_0 * INOUT : rbl_br_0_0 * INOUT : bl_0_0 * INOUT : br_0_0 +* INOUT : bl_0_1 +* INOUT : br_0_1 * INPUT : rbl_wl_0_0 * INPUT : wl_0_0 * INPUT : wl_0_1 @@ -1444,25 +1484,28 @@ Xrbc_16 * GROUND: gnd * rbl: [1, 0] left_rbl: [0] right_rbl: [] Xbitcell_array -+ bl_0_0 br_0_0 wl_0_0 wl_0_1 wl_0_2 wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 -+ wl_0_8 wl_0_9 wl_0_10 wl_0_11 wl_0_12 wl_0_13 wl_0_14 wl_0_15 vdd gnd -+ sram_bitcell_array ++ bl_0_0 br_0_0 bl_0_1 br_0_1 wl_0_0 wl_0_1 wl_0_2 wl_0_3 wl_0_4 wl_0_5 ++ wl_0_6 wl_0_7 wl_0_8 wl_0_9 wl_0_10 wl_0_11 wl_0_12 wl_0_13 wl_0_14 ++ wl_0_15 vdd gnd ++ sram_2_16_1_freepdk45_bitcell_array Xreplica_col_0 + rbl_bl_0_0 rbl_br_0_0 rbl_wl_0_0 wl_0_0 wl_0_1 wl_0_2 wl_0_3 wl_0_4 + wl_0_5 wl_0_6 wl_0_7 wl_0_8 wl_0_9 wl_0_10 wl_0_11 wl_0_12 wl_0_13 + wl_0_14 wl_0_15 vdd gnd -+ sram_replica_column ++ sram_2_16_1_freepdk45_replica_column Xdummy_row_0 -+ bl_0_0 br_0_0 rbl_wl_0_0 vdd gnd -+ sram_dummy_array -.ENDS sram_replica_bitcell_array ++ bl_0_0 br_0_0 bl_0_1 br_0_1 rbl_wl_0_0 vdd gnd ++ sram_2_16_1_freepdk45_dummy_array +.ENDS sram_2_16_1_freepdk45_replica_bitcell_array -.SUBCKT sram_dummy_array_0 -+ bl_0_0 br_0_0 bl_0_1 br_0_1 wl_0_0 vdd gnd +.SUBCKT sram_2_16_1_freepdk45_dummy_array_1 ++ bl_0_0 br_0_0 bl_0_1 br_0_1 bl_0_2 br_0_2 wl_0_0 vdd gnd * INOUT : bl_0_0 * INOUT : br_0_0 * INOUT : bl_0_1 * INOUT : br_0_1 +* INOUT : bl_0_2 +* INOUT : br_0_2 * INPUT : wl_0_0 * POWER : vdd * GROUND: gnd @@ -1472,14 +1515,19 @@ Xbit_r0_c0 Xbit_r0_c1 + bl_0_1 br_0_1 wl_0_0 vdd gnd + dummy_cell_1rw -.ENDS sram_dummy_array_0 +Xbit_r0_c2 ++ bl_0_2 br_0_2 wl_0_0 vdd gnd ++ dummy_cell_1rw +.ENDS sram_2_16_1_freepdk45_dummy_array_1 -.SUBCKT sram_dummy_array_1 -+ bl_0_0 br_0_0 bl_0_1 br_0_1 wl_0_0 vdd gnd +.SUBCKT sram_2_16_1_freepdk45_dummy_array_0 ++ bl_0_0 br_0_0 bl_0_1 br_0_1 bl_0_2 br_0_2 wl_0_0 vdd gnd * INOUT : bl_0_0 * INOUT : br_0_0 * INOUT : bl_0_1 * INOUT : br_0_1 +* INOUT : bl_0_2 +* INOUT : br_0_2 * INPUT : wl_0_0 * POWER : vdd * GROUND: gnd @@ -1489,16 +1537,107 @@ Xbit_r0_c0 Xbit_r0_c1 + bl_0_1 br_0_1 wl_0_0 vdd gnd + dummy_cell_1rw -.ENDS sram_dummy_array_1 +Xbit_r0_c2 ++ bl_0_2 br_0_2 wl_0_0 vdd gnd ++ dummy_cell_1rw +.ENDS sram_2_16_1_freepdk45_dummy_array_0 -.SUBCKT sram_capped_replica_bitcell_array -+ rbl_bl_0_0 rbl_br_0_0 bl_0_0 br_0_0 rbl_wl_0_0 wl_0_0 wl_0_1 wl_0_2 -+ wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 wl_0_8 wl_0_9 wl_0_10 wl_0_11 -+ wl_0_12 wl_0_13 wl_0_14 wl_0_15 vdd gnd +.SUBCKT sram_2_16_1_freepdk45_dummy_array_2 ++ bl_0_0 br_0_0 wl_0_0 wl_0_1 wl_0_2 wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 ++ wl_0_8 wl_0_9 wl_0_10 wl_0_11 wl_0_12 wl_0_13 wl_0_14 wl_0_15 wl_0_16 ++ wl_0_17 wl_0_18 vdd gnd +* INOUT : bl_0_0 +* INOUT : br_0_0 +* INPUT : wl_0_0 +* INPUT : wl_0_1 +* INPUT : wl_0_2 +* INPUT : wl_0_3 +* INPUT : wl_0_4 +* INPUT : wl_0_5 +* INPUT : wl_0_6 +* INPUT : wl_0_7 +* INPUT : wl_0_8 +* INPUT : wl_0_9 +* INPUT : wl_0_10 +* INPUT : wl_0_11 +* INPUT : wl_0_12 +* INPUT : wl_0_13 +* INPUT : wl_0_14 +* INPUT : wl_0_15 +* INPUT : wl_0_16 +* INPUT : wl_0_17 +* INPUT : wl_0_18 +* POWER : vdd +* GROUND: gnd +Xbit_r0_c0 ++ bl_0_0 br_0_0 wl_0_0 vdd gnd ++ dummy_cell_1rw +Xbit_r1_c0 ++ bl_0_0 br_0_0 wl_0_1 vdd gnd ++ dummy_cell_1rw +Xbit_r2_c0 ++ bl_0_0 br_0_0 wl_0_2 vdd gnd ++ dummy_cell_1rw +Xbit_r3_c0 ++ bl_0_0 br_0_0 wl_0_3 vdd gnd ++ dummy_cell_1rw +Xbit_r4_c0 ++ bl_0_0 br_0_0 wl_0_4 vdd gnd ++ dummy_cell_1rw +Xbit_r5_c0 ++ bl_0_0 br_0_0 wl_0_5 vdd gnd ++ dummy_cell_1rw +Xbit_r6_c0 ++ bl_0_0 br_0_0 wl_0_6 vdd gnd ++ dummy_cell_1rw +Xbit_r7_c0 ++ bl_0_0 br_0_0 wl_0_7 vdd gnd ++ dummy_cell_1rw +Xbit_r8_c0 ++ bl_0_0 br_0_0 wl_0_8 vdd gnd ++ dummy_cell_1rw +Xbit_r9_c0 ++ bl_0_0 br_0_0 wl_0_9 vdd gnd ++ dummy_cell_1rw +Xbit_r10_c0 ++ bl_0_0 br_0_0 wl_0_10 vdd gnd ++ dummy_cell_1rw +Xbit_r11_c0 ++ bl_0_0 br_0_0 wl_0_11 vdd gnd ++ dummy_cell_1rw +Xbit_r12_c0 ++ bl_0_0 br_0_0 wl_0_12 vdd gnd ++ dummy_cell_1rw +Xbit_r13_c0 ++ bl_0_0 br_0_0 wl_0_13 vdd gnd ++ dummy_cell_1rw +Xbit_r14_c0 ++ bl_0_0 br_0_0 wl_0_14 vdd gnd ++ dummy_cell_1rw +Xbit_r15_c0 ++ bl_0_0 br_0_0 wl_0_15 vdd gnd ++ dummy_cell_1rw +Xbit_r16_c0 ++ bl_0_0 br_0_0 wl_0_16 vdd gnd ++ dummy_cell_1rw +Xbit_r17_c0 ++ bl_0_0 br_0_0 wl_0_17 vdd gnd ++ dummy_cell_1rw +Xbit_r18_c0 ++ bl_0_0 br_0_0 wl_0_18 vdd gnd ++ dummy_cell_1rw +.ENDS sram_2_16_1_freepdk45_dummy_array_2 + +.SUBCKT sram_2_16_1_freepdk45_capped_replica_bitcell_array ++ rbl_bl_0_0 rbl_br_0_0 bl_0_0 br_0_0 bl_0_1 br_0_1 rbl_wl_0_0 wl_0_0 ++ wl_0_1 wl_0_2 wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 wl_0_8 wl_0_9 wl_0_10 ++ wl_0_11 wl_0_12 wl_0_13 wl_0_14 wl_0_15 vdd gnd * INOUT : rbl_bl_0_0 * INOUT : rbl_br_0_0 * INOUT : bl_0_0 * INOUT : br_0_0 +* INOUT : bl_0_1 +* INOUT : br_0_1 * INPUT : rbl_wl_0_0 * INPUT : wl_0_0 * INPUT : wl_0_1 @@ -1520,34 +1659,36 @@ Xbit_r0_c1 * GROUND: gnd * rbl: [1, 0] left_rbl: [0] right_rbl: [] Xreplica_bitcell_array -+ rbl_bl_0_0 rbl_br_0_0 bl_0_0 br_0_0 rbl_wl_0_0 wl_0_0 wl_0_1 wl_0_2 -+ wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 wl_0_8 wl_0_9 wl_0_10 wl_0_11 -+ wl_0_12 wl_0_13 wl_0_14 wl_0_15 vdd gnd -+ sram_replica_bitcell_array ++ rbl_bl_0_0 rbl_br_0_0 bl_0_0 br_0_0 bl_0_1 br_0_1 rbl_wl_0_0 wl_0_0 ++ wl_0_1 wl_0_2 wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 wl_0_8 wl_0_9 wl_0_10 ++ wl_0_11 wl_0_12 wl_0_13 wl_0_14 wl_0_15 vdd gnd ++ sram_2_16_1_freepdk45_replica_bitcell_array Xdummy_row_bot -+ rbl_bl_0_0 rbl_br_0_0 bl_0_0 br_0_0 gnd vdd gnd -+ sram_dummy_array_1 ++ rbl_bl_0_0 rbl_br_0_0 bl_0_0 br_0_0 bl_0_1 br_0_1 gnd vdd gnd ++ sram_2_16_1_freepdk45_dummy_array_1 Xdummy_row_top -+ rbl_bl_0_0 rbl_br_0_0 bl_0_0 br_0_0 gnd vdd gnd -+ sram_dummy_array_0 ++ rbl_bl_0_0 rbl_br_0_0 bl_0_0 br_0_0 bl_0_1 br_0_1 gnd vdd gnd ++ sram_2_16_1_freepdk45_dummy_array_0 Xdummy_col_left + dummy_left_bl_0_0 dummy_left_br_0_0 gnd rbl_wl_0_0 wl_0_0 wl_0_1 + wl_0_2 wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 wl_0_8 wl_0_9 wl_0_10 + wl_0_11 wl_0_12 wl_0_13 wl_0_14 wl_0_15 gnd vdd gnd -+ sram_dummy_array_2 ++ sram_2_16_1_freepdk45_dummy_array_2 Xdummy_col_right + dummy_right_bl_0_0 dummy_right_br_0_0 gnd rbl_wl_0_0 wl_0_0 wl_0_1 + wl_0_2 wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 wl_0_8 wl_0_9 wl_0_10 + wl_0_11 wl_0_12 wl_0_13 wl_0_14 wl_0_15 gnd vdd gnd -+ sram_dummy_array_3 -.ENDS sram_capped_replica_bitcell_array ++ sram_2_16_1_freepdk45_dummy_array_3 +.ENDS sram_2_16_1_freepdk45_capped_replica_bitcell_array -.SUBCKT sram_bank -+ dout0_0 rbl_bl_0_0 din0_0 addr0_0 addr0_1 addr0_2 addr0_3 s_en0 -+ p_en_bar0 w_en0 wl_en0 vdd gnd +.SUBCKT sram_2_16_1_freepdk45_bank ++ dout0_0 dout0_1 rbl_bl_0_0 din0_0 din0_1 addr0_0 addr0_1 addr0_2 ++ addr0_3 s_en0 p_en_bar0 w_en0 wl_en0 vdd gnd * OUTPUT: dout0_0 +* OUTPUT: dout0_1 * OUTPUT: rbl_bl_0_0 * INPUT : din0_0 +* INPUT : din0_1 * INPUT : addr0_0 * INPUT : addr0_1 * INPUT : addr0_2 @@ -1559,66 +1700,26 @@ Xdummy_col_right * POWER : vdd * GROUND: gnd Xbitcell_array -+ rbl_bl_0_0 rbl_br_0_0 bl_0_0 br_0_0 rbl_wl0 wl_0_0 wl_0_1 wl_0_2 -+ wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 wl_0_8 wl_0_9 wl_0_10 wl_0_11 -+ wl_0_12 wl_0_13 wl_0_14 wl_0_15 vdd gnd -+ sram_capped_replica_bitcell_array ++ rbl_bl_0_0 rbl_br_0_0 bl_0_0 br_0_0 bl_0_1 br_0_1 rbl_wl0 wl_0_0 ++ wl_0_1 wl_0_2 wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 wl_0_8 wl_0_9 wl_0_10 ++ wl_0_11 wl_0_12 wl_0_13 wl_0_14 wl_0_15 vdd gnd ++ sram_2_16_1_freepdk45_capped_replica_bitcell_array Xport_data0 -+ rbl_bl_0_0 rbl_br_0_0 bl_0_0 br_0_0 dout0_0 din0_0 s_en0 p_en_bar0 -+ w_en0 vdd gnd -+ sram_port_data ++ rbl_bl_0_0 rbl_br_0_0 bl_0_0 br_0_0 bl_0_1 br_0_1 dout0_0 dout0_1 ++ din0_0 din0_1 s_en0 p_en_bar0 w_en0 vdd gnd ++ sram_2_16_1_freepdk45_port_data Xport_address0 + addr0_0 addr0_1 addr0_2 addr0_3 wl_en0 wl_0_0 wl_0_1 wl_0_2 wl_0_3 + wl_0_4 wl_0_5 wl_0_6 wl_0_7 wl_0_8 wl_0_9 wl_0_10 wl_0_11 wl_0_12 + wl_0_13 wl_0_14 wl_0_15 rbl_wl0 vdd gnd -+ sram_port_address -.ENDS sram_bank - -.SUBCKT sram_row_addr_dff -+ din_0 din_1 din_2 din_3 dout_0 dout_1 dout_2 dout_3 clk vdd gnd -* INPUT : din_0 -* INPUT : din_1 -* INPUT : din_2 -* INPUT : din_3 -* OUTPUT: dout_0 -* OUTPUT: dout_1 -* OUTPUT: dout_2 -* OUTPUT: dout_3 -* INPUT : clk -* POWER : vdd -* GROUND: gnd -* rows: 4 cols: 1 -Xdff_r0_c0 -+ din_0 dout_0 clk vdd gnd -+ dff -Xdff_r1_c0 -+ din_1 dout_1 clk vdd gnd -+ dff -Xdff_r2_c0 -+ din_2 dout_2 clk vdd gnd -+ dff -Xdff_r3_c0 -+ din_3 dout_3 clk vdd gnd -+ dff -.ENDS sram_row_addr_dff - -.SUBCKT sram_data_dff -+ din_0 dout_0 clk vdd gnd -* INPUT : din_0 -* OUTPUT: dout_0 -* INPUT : clk -* POWER : vdd -* GROUND: gnd -* rows: 1 cols: 1 -Xdff_r0_c0 -+ din_0 dout_0 clk vdd gnd -+ dff -.ENDS sram_data_dff ++ sram_2_16_1_freepdk45_port_address +.ENDS sram_2_16_1_freepdk45_bank .SUBCKT sram_2_16_1_freepdk45 -+ din0[0] addr0[0] addr0[1] addr0[2] addr0[3] csb0 web0 clk0 dout0[0] -+ vdd gnd ++ din0[0] din0[1] addr0[0] addr0[1] addr0[2] addr0[3] csb0 web0 clk0 ++ dout0[0] dout0[1] vdd gnd * INPUT : din0[0] +* INPUT : din0[1] * INPUT : addr0[0] * INPUT : addr0[1] * INPUT : addr0[2] @@ -1627,20 +1728,21 @@ Xdff_r0_c0 * INPUT : web0 * INPUT : clk0 * OUTPUT: dout0[0] +* OUTPUT: dout0[1] * POWER : vdd * GROUND: gnd Xbank0 -+ dout0[0] rbl_bl0 bank_din0_0 a0_0 a0_1 a0_2 a0_3 s_en0 p_en_bar0 w_en0 -+ wl_en0 vdd gnd -+ sram_bank ++ dout0[0] dout0[1] rbl_bl0 bank_din0_0 bank_din0_1 a0_0 a0_1 a0_2 a0_3 ++ s_en0 p_en_bar0 w_en0 wl_en0 vdd gnd ++ sram_2_16_1_freepdk45_bank Xcontrol0 + csb0 web0 clk0 rbl_bl0 s_en0 w_en0 p_en_bar0 wl_en0 clk_buf0 vdd gnd -+ sram_control_logic_rw ++ sram_2_16_1_freepdk45_control_logic_rw Xrow_address0 + addr0[0] addr0[1] addr0[2] addr0[3] a0_0 a0_1 a0_2 a0_3 clk_buf0 vdd + gnd -+ sram_row_addr_dff ++ sram_2_16_1_freepdk45_row_addr_dff Xdata_dff0 -+ din0[0] bank_din0_0 clk_buf0 vdd gnd -+ sram_data_dff ++ din0[0] din0[1] bank_din0_0 bank_din0_1 clk_buf0 vdd gnd ++ sram_2_16_1_freepdk45_data_dff .ENDS sram_2_16_1_freepdk45 diff --git a/compiler/tests/sp_files/sram_2_16_1_scn4m_subm.sp b/compiler/tests/sp_files/sram_2_16_1_scn4m_subm.sp index 667e1df4..c6836a9d 100644 --- a/compiler/tests/sp_files/sram_2_16_1_scn4m_subm.sp +++ b/compiler/tests/sp_files/sram_2_16_1_scn4m_subm.sp @@ -1,594 +1,13 @@ ************************************************** * OpenRAM generated memory. * Words: 16 -* Data bits: 1 +* Data bits: 2 * Banks: 1 * Column mux: 1:1 * Trimmed: False * LVS: False ************************************************** -* spice ptx M{0} {1} n m=1 w=0.8u l=0.4u pd=2.40u ps=2.40u as=0.80p ad=0.80p - -* spice ptx M{0} {1} p m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p - -.SUBCKT sram_pinv -+ A Z vdd gnd -* INPUT : A -* OUTPUT: Z -* POWER : vdd -* GROUND: gnd -Mpinv_pmos Z A vdd vdd p m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p -Mpinv_nmos Z A gnd gnd n m=1 w=0.8u l=0.4u pd=2.40u ps=2.40u as=0.80p ad=0.80p -.ENDS sram_pinv - -* spice ptx M{0} {1} n m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p - -* spice ptx M{0} {1} p m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p - -* spice ptx M{0} {1} n m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p - -.SUBCKT sram_pnand2 -+ A B Z vdd gnd -* INPUT : A -* INPUT : B -* OUTPUT: Z -* POWER : vdd -* GROUND: gnd -Mpnand2_pmos1 vdd A Z vdd p m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p -Mpnand2_pmos2 Z B vdd vdd p m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p -Mpnand2_nmos1 Z B net1 gnd n m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p -Mpnand2_nmos2 net1 A gnd gnd n m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p -.ENDS sram_pnand2 - -.SUBCKT sram_wordline_driver -+ A B Z vdd gnd -* INPUT : A -* INPUT : B -* OUTPUT: Z -* POWER : vdd -* GROUND: gnd -Xwld_nand -+ A B zb_int vdd gnd -+ sram_pnand2 -Xwl_driver -+ zb_int Z vdd gnd -+ sram_pinv -.ENDS sram_wordline_driver - -.SUBCKT sram_wordline_driver_array -+ in_0 in_1 in_2 in_3 in_4 in_5 in_6 in_7 in_8 in_9 in_10 in_11 in_12 -+ in_13 in_14 in_15 wl_0 wl_1 wl_2 wl_3 wl_4 wl_5 wl_6 wl_7 wl_8 wl_9 -+ wl_10 wl_11 wl_12 wl_13 wl_14 wl_15 en vdd gnd -* INPUT : in_0 -* INPUT : in_1 -* INPUT : in_2 -* INPUT : in_3 -* INPUT : in_4 -* INPUT : in_5 -* INPUT : in_6 -* INPUT : in_7 -* INPUT : in_8 -* INPUT : in_9 -* INPUT : in_10 -* INPUT : in_11 -* INPUT : in_12 -* INPUT : in_13 -* INPUT : in_14 -* INPUT : in_15 -* OUTPUT: wl_0 -* OUTPUT: wl_1 -* OUTPUT: wl_2 -* OUTPUT: wl_3 -* OUTPUT: wl_4 -* OUTPUT: wl_5 -* OUTPUT: wl_6 -* OUTPUT: wl_7 -* OUTPUT: wl_8 -* OUTPUT: wl_9 -* OUTPUT: wl_10 -* OUTPUT: wl_11 -* OUTPUT: wl_12 -* OUTPUT: wl_13 -* OUTPUT: wl_14 -* OUTPUT: wl_15 -* INPUT : en -* POWER : vdd -* GROUND: gnd -* rows: 16 cols: 1 -Xwl_driver_and0 -+ in_0 en wl_0 vdd gnd -+ sram_wordline_driver -Xwl_driver_and1 -+ in_1 en wl_1 vdd gnd -+ sram_wordline_driver -Xwl_driver_and2 -+ in_2 en wl_2 vdd gnd -+ sram_wordline_driver -Xwl_driver_and3 -+ in_3 en wl_3 vdd gnd -+ sram_wordline_driver -Xwl_driver_and4 -+ in_4 en wl_4 vdd gnd -+ sram_wordline_driver -Xwl_driver_and5 -+ in_5 en wl_5 vdd gnd -+ sram_wordline_driver -Xwl_driver_and6 -+ in_6 en wl_6 vdd gnd -+ sram_wordline_driver -Xwl_driver_and7 -+ in_7 en wl_7 vdd gnd -+ sram_wordline_driver -Xwl_driver_and8 -+ in_8 en wl_8 vdd gnd -+ sram_wordline_driver -Xwl_driver_and9 -+ in_9 en wl_9 vdd gnd -+ sram_wordline_driver -Xwl_driver_and10 -+ in_10 en wl_10 vdd gnd -+ sram_wordline_driver -Xwl_driver_and11 -+ in_11 en wl_11 vdd gnd -+ sram_wordline_driver -Xwl_driver_and12 -+ in_12 en wl_12 vdd gnd -+ sram_wordline_driver -Xwl_driver_and13 -+ in_13 en wl_13 vdd gnd -+ sram_wordline_driver -Xwl_driver_and14 -+ in_14 en wl_14 vdd gnd -+ sram_wordline_driver -Xwl_driver_and15 -+ in_15 en wl_15 vdd gnd -+ sram_wordline_driver -.ENDS sram_wordline_driver_array - -.SUBCKT sram_and2_dec_0 -+ A B Z vdd gnd -* INPUT : A -* INPUT : B -* OUTPUT: Z -* POWER : vdd -* GROUND: gnd -* size: 1 -Xpand2_dec_nand -+ A B zb_int vdd gnd -+ sram_pnand2 -Xpand2_dec_inv -+ zb_int Z vdd gnd -+ sram_pinv -.ENDS sram_and2_dec_0 - -.SUBCKT sram_and2_dec -+ A B Z vdd gnd -* INPUT : A -* INPUT : B -* OUTPUT: Z -* POWER : vdd -* GROUND: gnd -* size: 1 -Xpand2_dec_nand -+ A B zb_int vdd gnd -+ sram_pnand2 -Xpand2_dec_inv -+ zb_int Z vdd gnd -+ sram_pinv -.ENDS sram_and2_dec - -.SUBCKT sram_hierarchical_predecode2x4 -+ in_0 in_1 out_0 out_1 out_2 out_3 vdd gnd -* INPUT : in_0 -* INPUT : in_1 -* OUTPUT: out_0 -* OUTPUT: out_1 -* OUTPUT: out_2 -* OUTPUT: out_3 -* POWER : vdd -* GROUND: gnd -Xpre_inv_0 -+ in_0 inbar_0 vdd gnd -+ sram_pinv -Xpre_inv_1 -+ in_1 inbar_1 vdd gnd -+ sram_pinv -XXpre2x4_and_0 -+ inbar_0 inbar_1 out_0 vdd gnd -+ sram_and2_dec -XXpre2x4_and_1 -+ in_0 inbar_1 out_1 vdd gnd -+ sram_and2_dec -XXpre2x4_and_2 -+ inbar_0 in_1 out_2 vdd gnd -+ sram_and2_dec -XXpre2x4_and_3 -+ in_0 in_1 out_3 vdd gnd -+ sram_and2_dec -.ENDS sram_hierarchical_predecode2x4 - -.SUBCKT sram_hierarchical_decoder -+ addr_0 addr_1 addr_2 addr_3 decode_0 decode_1 decode_2 decode_3 -+ decode_4 decode_5 decode_6 decode_7 decode_8 decode_9 decode_10 -+ decode_11 decode_12 decode_13 decode_14 decode_15 vdd gnd -* INPUT : addr_0 -* INPUT : addr_1 -* INPUT : addr_2 -* INPUT : addr_3 -* OUTPUT: decode_0 -* OUTPUT: decode_1 -* OUTPUT: decode_2 -* OUTPUT: decode_3 -* OUTPUT: decode_4 -* OUTPUT: decode_5 -* OUTPUT: decode_6 -* OUTPUT: decode_7 -* OUTPUT: decode_8 -* OUTPUT: decode_9 -* OUTPUT: decode_10 -* OUTPUT: decode_11 -* OUTPUT: decode_12 -* OUTPUT: decode_13 -* OUTPUT: decode_14 -* OUTPUT: decode_15 -* POWER : vdd -* GROUND: gnd -Xpre_0 -+ addr_0 addr_1 out_0 out_1 out_2 out_3 vdd gnd -+ sram_hierarchical_predecode2x4 -Xpre_1 -+ addr_2 addr_3 out_4 out_5 out_6 out_7 vdd gnd -+ sram_hierarchical_predecode2x4 -XDEC_AND_0 -+ out_0 out_4 decode_0 vdd gnd -+ sram_and2_dec -XDEC_AND_4 -+ out_0 out_5 decode_4 vdd gnd -+ sram_and2_dec -XDEC_AND_8 -+ out_0 out_6 decode_8 vdd gnd -+ sram_and2_dec -XDEC_AND_12 -+ out_0 out_7 decode_12 vdd gnd -+ sram_and2_dec -XDEC_AND_1 -+ out_1 out_4 decode_1 vdd gnd -+ sram_and2_dec -XDEC_AND_5 -+ out_1 out_5 decode_5 vdd gnd -+ sram_and2_dec -XDEC_AND_9 -+ out_1 out_6 decode_9 vdd gnd -+ sram_and2_dec -XDEC_AND_13 -+ out_1 out_7 decode_13 vdd gnd -+ sram_and2_dec -XDEC_AND_2 -+ out_2 out_4 decode_2 vdd gnd -+ sram_and2_dec -XDEC_AND_6 -+ out_2 out_5 decode_6 vdd gnd -+ sram_and2_dec -XDEC_AND_10 -+ out_2 out_6 decode_10 vdd gnd -+ sram_and2_dec -XDEC_AND_14 -+ out_2 out_7 decode_14 vdd gnd -+ sram_and2_dec -XDEC_AND_3 -+ out_3 out_4 decode_3 vdd gnd -+ sram_and2_dec -XDEC_AND_7 -+ out_3 out_5 decode_7 vdd gnd -+ sram_and2_dec -XDEC_AND_11 -+ out_3 out_6 decode_11 vdd gnd -+ sram_and2_dec -XDEC_AND_15 -+ out_3 out_7 decode_15 vdd gnd -+ sram_and2_dec -.ENDS sram_hierarchical_decoder - -.SUBCKT sram_port_address -+ addr_0 addr_1 addr_2 addr_3 wl_en wl_0 wl_1 wl_2 wl_3 wl_4 wl_5 wl_6 -+ wl_7 wl_8 wl_9 wl_10 wl_11 wl_12 wl_13 wl_14 wl_15 rbl_wl vdd gnd -* INPUT : addr_0 -* INPUT : addr_1 -* INPUT : addr_2 -* INPUT : addr_3 -* INPUT : wl_en -* OUTPUT: wl_0 -* OUTPUT: wl_1 -* OUTPUT: wl_2 -* OUTPUT: wl_3 -* OUTPUT: wl_4 -* OUTPUT: wl_5 -* OUTPUT: wl_6 -* OUTPUT: wl_7 -* OUTPUT: wl_8 -* OUTPUT: wl_9 -* OUTPUT: wl_10 -* OUTPUT: wl_11 -* OUTPUT: wl_12 -* OUTPUT: wl_13 -* OUTPUT: wl_14 -* OUTPUT: wl_15 -* OUTPUT: rbl_wl -* POWER : vdd -* GROUND: gnd -Xrow_decoder -+ addr_0 addr_1 addr_2 addr_3 dec_out_0 dec_out_1 dec_out_2 dec_out_3 -+ dec_out_4 dec_out_5 dec_out_6 dec_out_7 dec_out_8 dec_out_9 dec_out_10 -+ dec_out_11 dec_out_12 dec_out_13 dec_out_14 dec_out_15 vdd gnd -+ sram_hierarchical_decoder -Xwordline_driver -+ dec_out_0 dec_out_1 dec_out_2 dec_out_3 dec_out_4 dec_out_5 dec_out_6 -+ dec_out_7 dec_out_8 dec_out_9 dec_out_10 dec_out_11 dec_out_12 -+ dec_out_13 dec_out_14 dec_out_15 wl_0 wl_1 wl_2 wl_3 wl_4 wl_5 wl_6 -+ wl_7 wl_8 wl_9 wl_10 wl_11 wl_12 wl_13 wl_14 wl_15 wl_en vdd gnd -+ sram_wordline_driver_array -Xrbl_driver -+ wl_en vdd rbl_wl vdd gnd -+ sram_and2_dec_0 -.ENDS sram_port_address -*********************** Write_Driver ****************************** -.SUBCKT write_driver din bl br en vdd gnd - -**** Inverter to conver Data_in to data_in_bar ****** -* din_bar = inv(din) -M_1 din_bar din gnd gnd n W=0.8u L=0.4u -M_2 din_bar din vdd vdd p W=1.4u L=0.4u - -**** 2input nand gate follwed by inverter to drive BL ****** -* din_bar_gated = nand(en, din) -M_3 din_bar_gated en net_7 gnd n W=1.4u L=0.4u -M_4 net_7 din gnd gnd n W=1.4u L=0.4u -M_5 din_bar_gated en vdd vdd p W=1.4u L=0.4u -M_6 din_bar_gated din vdd vdd p W=1.4u L=0.4u -* din_bar_gated_bar = inv(din_bar_gated) -M_7 din_bar_gated_bar din_bar_gated vdd vdd p W=1.4u L=0.4u -M_8 din_bar_gated_bar din_bar_gated gnd gnd n W=0.8u L=0.4u - -**** 2input nand gate follwed by inverter to drive BR****** -* din_gated = nand(en, din_bar) -M_9 din_gated en vdd vdd p W=1.4u L=0.4u -M_10 din_gated en net_8 gnd n W=1.4u L=0.4u -M_11 net_8 din_bar gnd gnd n W=1.4u L=0.4u -M_12 din_gated din_bar vdd vdd p W=1.4u L=0.4u -* din_gated_bar = inv(din_gated) -M_13 din_gated_bar din_gated vdd vdd p W=1.4u L=0.4u -M_14 din_gated_bar din_gated gnd gnd n W=0.8u L=0.4u - -************************************************ -* pull down with en enable -M_15 bl din_gated_bar gnd gnd n W=2.4u L=0.4u -M_16 br din_bar_gated_bar gnd gnd n W=2.4u L=0.4u - - - -.ENDS $ write_driver - -.SUBCKT sram_write_driver_array -+ data_0 bl_0 br_0 en vdd gnd -* INPUT : data_0 -* OUTPUT: bl_0 -* OUTPUT: br_0 -* INPUT : en -* POWER : vdd -* GROUND: gnd -* word_size 1 -Xwrite_driver0 -+ data_0 bl_0 br_0 en vdd gnd -+ write_driver -.ENDS sram_write_driver_array - -.SUBCKT sram_precharge_0 -+ bl br en_bar vdd -* OUTPUT: bl -* OUTPUT: br -* INPUT : en_bar -* POWER : vdd -Mlower_pmos bl en_bar br vdd p m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p -Mupper_pmos1 bl en_bar vdd vdd p m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p -Mupper_pmos2 br en_bar vdd vdd p m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p -.ENDS sram_precharge_0 - -.SUBCKT sram_precharge_array -+ bl_0 br_0 bl_1 br_1 en_bar vdd -* OUTPUT: bl_0 -* OUTPUT: br_0 -* OUTPUT: bl_1 -* OUTPUT: br_1 -* INPUT : en_bar -* POWER : vdd -* cols: 2 size: 1 bl: bl br: br -Xpre_column_0 -+ bl_0 br_0 en_bar vdd -+ sram_precharge_0 -Xpre_column_1 -+ bl_1 br_1 en_bar vdd -+ sram_precharge_0 -.ENDS sram_precharge_array -*********************** "sense_amp" ****************************** - -.SUBCKT sense_amp bl br dout en vdd gnd - -* SPICE3 file created from sense_amp.ext - technology: scmos - -M1000 gnd en a_56_432# gnd n w=1.8u l=0.4u -M1001 a_56_432# a_48_304# dint gnd n w=1.8u l=0.4u -M1002 a_48_304# dint a_56_432# gnd n w=1.8u l=0.4u -M1003 vdd a_48_304# dint vdd p w=3.6u l=0.4u -M1004 a_48_304# dint vdd vdd p w=3.6u l=0.4u -M1005 bl en dint vdd p w=4.8u l=0.4u -M1006 a_48_304# en br vdd p w=4.8u l=0.4u - -M1007 dout_bar dint vdd vdd p w=1.6u l=0.4u -M1008 gnd dint dout_bar gnd n w=0.8u l=0.4u -M1009 dout dout_bar vdd vdd p w=4.8u l=0.4u -M1010 gnd dout_bar dout gnd n w=2.4u l=0.4u -.ENDS - -.SUBCKT sram_sense_amp_array -+ data_0 bl_0 br_0 en vdd gnd -* OUTPUT: data_0 -* INPUT : bl_0 -* INPUT : br_0 -* INPUT : en -* POWER : vdd -* GROUND: gnd -* words_per_row: 1 -Xsa_d0 -+ bl_0 br_0 data_0 en vdd gnd -+ sense_amp -.ENDS sram_sense_amp_array - -.SUBCKT sram_port_data -+ rbl_bl rbl_br bl_0 br_0 dout_0 din_0 s_en p_en_bar w_en vdd gnd -* INOUT : rbl_bl -* INOUT : rbl_br -* INOUT : bl_0 -* INOUT : br_0 -* OUTPUT: dout_0 -* INPUT : din_0 -* INPUT : s_en -* INPUT : p_en_bar -* INPUT : w_en -* POWER : vdd -* GROUND: gnd -Xprecharge_array0 -+ rbl_bl rbl_br bl_0 br_0 p_en_bar vdd -+ sram_precharge_array -Xsense_amp_array0 -+ dout_0 bl_0 br_0 s_en vdd gnd -+ sram_sense_amp_array -Xwrite_driver_array0 -+ din_0 bl_0 br_0 w_en vdd gnd -+ sram_write_driver_array -.ENDS sram_port_data - -*********************** "cell_1rw" ****************************** -.SUBCKT cell_1rw bl br wl vdd gnd -* SPICE3 file created from cell_1rw.ext - technology: scmos - -* Inverter 1 -M1000 Q Q_bar vdd vdd p w=0.6u l=0.8u -M1002 Q Q_bar gnd gnd n w=1.6u l=0.4u - -* Inverter 2 -M1001 vdd Q Q_bar vdd p w=0.6u l=0.8u -M1003 gnd Q Q_bar gnd n w=1.6u l=0.4u - -* Access transistors -M1004 Q wl bl gnd n w=0.8u l=0.4u -M1005 Q_bar wl br gnd n w=0.8u l=0.4u - -.ENDS - -.SUBCKT sram_bitcell_array -+ bl_0_0 br_0_0 wl_0_0 wl_0_1 wl_0_2 wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 -+ wl_0_8 wl_0_9 wl_0_10 wl_0_11 wl_0_12 wl_0_13 wl_0_14 wl_0_15 vdd gnd -* INOUT : bl_0_0 -* INOUT : br_0_0 -* INPUT : wl_0_0 -* INPUT : wl_0_1 -* INPUT : wl_0_2 -* INPUT : wl_0_3 -* INPUT : wl_0_4 -* INPUT : wl_0_5 -* INPUT : wl_0_6 -* INPUT : wl_0_7 -* INPUT : wl_0_8 -* INPUT : wl_0_9 -* INPUT : wl_0_10 -* INPUT : wl_0_11 -* INPUT : wl_0_12 -* INPUT : wl_0_13 -* INPUT : wl_0_14 -* INPUT : wl_0_15 -* POWER : vdd -* GROUND: gnd -* rows: 16 cols: 1 -Xbit_r0_c0 -+ bl_0_0 br_0_0 wl_0_0 vdd gnd -+ cell_1rw -Xbit_r1_c0 -+ bl_0_0 br_0_0 wl_0_1 vdd gnd -+ cell_1rw -Xbit_r2_c0 -+ bl_0_0 br_0_0 wl_0_2 vdd gnd -+ cell_1rw -Xbit_r3_c0 -+ bl_0_0 br_0_0 wl_0_3 vdd gnd -+ cell_1rw -Xbit_r4_c0 -+ bl_0_0 br_0_0 wl_0_4 vdd gnd -+ cell_1rw -Xbit_r5_c0 -+ bl_0_0 br_0_0 wl_0_5 vdd gnd -+ cell_1rw -Xbit_r6_c0 -+ bl_0_0 br_0_0 wl_0_6 vdd gnd -+ cell_1rw -Xbit_r7_c0 -+ bl_0_0 br_0_0 wl_0_7 vdd gnd -+ cell_1rw -Xbit_r8_c0 -+ bl_0_0 br_0_0 wl_0_8 vdd gnd -+ cell_1rw -Xbit_r9_c0 -+ bl_0_0 br_0_0 wl_0_9 vdd gnd -+ cell_1rw -Xbit_r10_c0 -+ bl_0_0 br_0_0 wl_0_10 vdd gnd -+ cell_1rw -Xbit_r11_c0 -+ bl_0_0 br_0_0 wl_0_11 vdd gnd -+ cell_1rw -Xbit_r12_c0 -+ bl_0_0 br_0_0 wl_0_12 vdd gnd -+ cell_1rw -Xbit_r13_c0 -+ bl_0_0 br_0_0 wl_0_13 vdd gnd -+ cell_1rw -Xbit_r14_c0 -+ bl_0_0 br_0_0 wl_0_14 vdd gnd -+ cell_1rw -Xbit_r15_c0 -+ bl_0_0 br_0_0 wl_0_15 vdd gnd -+ cell_1rw -.ENDS sram_bitcell_array - -*********************** "dummy_cell_1rw" ****************************** -.SUBCKT dummy_cell_1rw bl br wl vdd gnd - -* Inverter 1 -M1000 Q Q_bar vdd vdd p w=0.6u l=0.8u -M1002 Q Q_bar gnd gnd n w=1.6u l=0.4u - -* Inverter 2 -M1001 vdd Q Q_bar vdd p w=0.6u l=0.8u -M1003 gnd Q Q_bar gnd n w=1.6u l=0.4u - -* Access transistors -M1004 Q wl bl_noconn gnd n w=0.8u l=0.4u -M1005 Q_bar wl br_noconn gnd n w=0.8u l=0.4u - -.ENDS - -.SUBCKT sram_dummy_array -+ bl_0_0 br_0_0 wl_0_0 vdd gnd -* INOUT : bl_0_0 -* INOUT : br_0_0 -* INPUT : wl_0_0 -* POWER : vdd -* GROUND: gnd -Xbit_r0_c0 -+ bl_0_0 br_0_0 wl_0_0 vdd gnd -+ dummy_cell_1rw -.ENDS sram_dummy_array - *********************** "cell_1rw" ****************************** .SUBCKT replica_cell_1rw bl br wl vdd gnd * SPICE3 file created from cell_1rw.ext - technology: scmos @@ -607,7 +26,7 @@ M1005 vdd wl br gnd n w=0.8u l=0.4u .ENDS -.SUBCKT sram_replica_column +.SUBCKT sram_2_16_1_scn4m_subm_replica_column + bl_0_0 br_0_0 wl_0_0 wl_0_1 wl_0_2 wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 + wl_0_8 wl_0_9 wl_0_10 wl_0_11 wl_0_12 wl_0_13 wl_0_14 wl_0_15 wl_0_16 + vdd gnd @@ -683,16 +102,195 @@ Xrbc_15 Xrbc_16 + bl_0_0 br_0_0 wl_0_16 vdd gnd + replica_cell_1rw -.ENDS sram_replica_column +.ENDS sram_2_16_1_scn4m_subm_replica_column -.SUBCKT sram_replica_bitcell_array -+ rbl_bl_0_0 rbl_br_0_0 bl_0_0 br_0_0 rbl_wl_0_0 wl_0_0 wl_0_1 wl_0_2 -+ wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 wl_0_8 wl_0_9 wl_0_10 wl_0_11 -+ wl_0_12 wl_0_13 wl_0_14 wl_0_15 vdd gnd +*********************** "cell_1rw" ****************************** +.SUBCKT cell_1rw bl br wl vdd gnd +* SPICE3 file created from cell_1rw.ext - technology: scmos + +* Inverter 1 +M1000 Q Q_bar vdd vdd p w=0.6u l=0.8u +M1002 Q Q_bar gnd gnd n w=1.6u l=0.4u + +* Inverter 2 +M1001 vdd Q Q_bar vdd p w=0.6u l=0.8u +M1003 gnd Q Q_bar gnd n w=1.6u l=0.4u + +* Access transistors +M1004 Q wl bl gnd n w=0.8u l=0.4u +M1005 Q_bar wl br gnd n w=0.8u l=0.4u + +.ENDS + +.SUBCKT sram_2_16_1_scn4m_subm_bitcell_array ++ bl_0_0 br_0_0 bl_0_1 br_0_1 wl_0_0 wl_0_1 wl_0_2 wl_0_3 wl_0_4 wl_0_5 ++ wl_0_6 wl_0_7 wl_0_8 wl_0_9 wl_0_10 wl_0_11 wl_0_12 wl_0_13 wl_0_14 ++ wl_0_15 vdd gnd +* INOUT : bl_0_0 +* INOUT : br_0_0 +* INOUT : bl_0_1 +* INOUT : br_0_1 +* INPUT : wl_0_0 +* INPUT : wl_0_1 +* INPUT : wl_0_2 +* INPUT : wl_0_3 +* INPUT : wl_0_4 +* INPUT : wl_0_5 +* INPUT : wl_0_6 +* INPUT : wl_0_7 +* INPUT : wl_0_8 +* INPUT : wl_0_9 +* INPUT : wl_0_10 +* INPUT : wl_0_11 +* INPUT : wl_0_12 +* INPUT : wl_0_13 +* INPUT : wl_0_14 +* INPUT : wl_0_15 +* POWER : vdd +* GROUND: gnd +* rows: 16 cols: 2 +Xbit_r0_c0 ++ bl_0_0 br_0_0 wl_0_0 vdd gnd ++ cell_1rw +Xbit_r1_c0 ++ bl_0_0 br_0_0 wl_0_1 vdd gnd ++ cell_1rw +Xbit_r2_c0 ++ bl_0_0 br_0_0 wl_0_2 vdd gnd ++ cell_1rw +Xbit_r3_c0 ++ bl_0_0 br_0_0 wl_0_3 vdd gnd ++ cell_1rw +Xbit_r4_c0 ++ bl_0_0 br_0_0 wl_0_4 vdd gnd ++ cell_1rw +Xbit_r5_c0 ++ bl_0_0 br_0_0 wl_0_5 vdd gnd ++ cell_1rw +Xbit_r6_c0 ++ bl_0_0 br_0_0 wl_0_6 vdd gnd ++ cell_1rw +Xbit_r7_c0 ++ bl_0_0 br_0_0 wl_0_7 vdd gnd ++ cell_1rw +Xbit_r8_c0 ++ bl_0_0 br_0_0 wl_0_8 vdd gnd ++ cell_1rw +Xbit_r9_c0 ++ bl_0_0 br_0_0 wl_0_9 vdd gnd ++ cell_1rw +Xbit_r10_c0 ++ bl_0_0 br_0_0 wl_0_10 vdd gnd ++ cell_1rw +Xbit_r11_c0 ++ bl_0_0 br_0_0 wl_0_11 vdd gnd ++ cell_1rw +Xbit_r12_c0 ++ bl_0_0 br_0_0 wl_0_12 vdd gnd ++ cell_1rw +Xbit_r13_c0 ++ bl_0_0 br_0_0 wl_0_13 vdd gnd ++ cell_1rw +Xbit_r14_c0 ++ bl_0_0 br_0_0 wl_0_14 vdd gnd ++ cell_1rw +Xbit_r15_c0 ++ bl_0_0 br_0_0 wl_0_15 vdd gnd ++ cell_1rw +Xbit_r0_c1 ++ bl_0_1 br_0_1 wl_0_0 vdd gnd ++ cell_1rw +Xbit_r1_c1 ++ bl_0_1 br_0_1 wl_0_1 vdd gnd ++ cell_1rw +Xbit_r2_c1 ++ bl_0_1 br_0_1 wl_0_2 vdd gnd ++ cell_1rw +Xbit_r3_c1 ++ bl_0_1 br_0_1 wl_0_3 vdd gnd ++ cell_1rw +Xbit_r4_c1 ++ bl_0_1 br_0_1 wl_0_4 vdd gnd ++ cell_1rw +Xbit_r5_c1 ++ bl_0_1 br_0_1 wl_0_5 vdd gnd ++ cell_1rw +Xbit_r6_c1 ++ bl_0_1 br_0_1 wl_0_6 vdd gnd ++ cell_1rw +Xbit_r7_c1 ++ bl_0_1 br_0_1 wl_0_7 vdd gnd ++ cell_1rw +Xbit_r8_c1 ++ bl_0_1 br_0_1 wl_0_8 vdd gnd ++ cell_1rw +Xbit_r9_c1 ++ bl_0_1 br_0_1 wl_0_9 vdd gnd ++ cell_1rw +Xbit_r10_c1 ++ bl_0_1 br_0_1 wl_0_10 vdd gnd ++ cell_1rw +Xbit_r11_c1 ++ bl_0_1 br_0_1 wl_0_11 vdd gnd ++ cell_1rw +Xbit_r12_c1 ++ bl_0_1 br_0_1 wl_0_12 vdd gnd ++ cell_1rw +Xbit_r13_c1 ++ bl_0_1 br_0_1 wl_0_13 vdd gnd ++ cell_1rw +Xbit_r14_c1 ++ bl_0_1 br_0_1 wl_0_14 vdd gnd ++ cell_1rw +Xbit_r15_c1 ++ bl_0_1 br_0_1 wl_0_15 vdd gnd ++ cell_1rw +.ENDS sram_2_16_1_scn4m_subm_bitcell_array + +*********************** "dummy_cell_1rw" ****************************** +.SUBCKT dummy_cell_1rw bl br wl vdd gnd + +* Inverter 1 +M1000 Q Q_bar vdd vdd p w=0.6u l=0.8u +M1002 Q Q_bar gnd gnd n w=1.6u l=0.4u + +* Inverter 2 +M1001 vdd Q Q_bar vdd p w=0.6u l=0.8u +M1003 gnd Q Q_bar gnd n w=1.6u l=0.4u + +* Access transistors +M1004 Q wl bl_noconn gnd n w=0.8u l=0.4u +M1005 Q_bar wl br_noconn gnd n w=0.8u l=0.4u + +.ENDS + +.SUBCKT sram_2_16_1_scn4m_subm_dummy_array ++ bl_0_0 br_0_0 bl_0_1 br_0_1 wl_0_0 vdd gnd +* INOUT : bl_0_0 +* INOUT : br_0_0 +* INOUT : bl_0_1 +* INOUT : br_0_1 +* INPUT : wl_0_0 +* POWER : vdd +* GROUND: gnd +Xbit_r0_c0 ++ bl_0_0 br_0_0 wl_0_0 vdd gnd ++ dummy_cell_1rw +Xbit_r0_c1 ++ bl_0_1 br_0_1 wl_0_0 vdd gnd ++ dummy_cell_1rw +.ENDS sram_2_16_1_scn4m_subm_dummy_array + +.SUBCKT sram_2_16_1_scn4m_subm_replica_bitcell_array ++ rbl_bl_0_0 rbl_br_0_0 bl_0_0 br_0_0 bl_0_1 br_0_1 rbl_wl_0_0 wl_0_0 ++ wl_0_1 wl_0_2 wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 wl_0_8 wl_0_9 wl_0_10 ++ wl_0_11 wl_0_12 wl_0_13 wl_0_14 wl_0_15 vdd gnd * INOUT : rbl_bl_0_0 * INOUT : rbl_br_0_0 * INOUT : bl_0_0 * INOUT : br_0_0 +* INOUT : bl_0_1 +* INOUT : br_0_1 * INPUT : rbl_wl_0_0 * INPUT : wl_0_0 * INPUT : wl_0_1 @@ -714,20 +312,21 @@ Xrbc_16 * GROUND: gnd * rbl: [1, 0] left_rbl: [0] right_rbl: [] Xbitcell_array -+ bl_0_0 br_0_0 wl_0_0 wl_0_1 wl_0_2 wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 -+ wl_0_8 wl_0_9 wl_0_10 wl_0_11 wl_0_12 wl_0_13 wl_0_14 wl_0_15 vdd gnd -+ sram_bitcell_array ++ bl_0_0 br_0_0 bl_0_1 br_0_1 wl_0_0 wl_0_1 wl_0_2 wl_0_3 wl_0_4 wl_0_5 ++ wl_0_6 wl_0_7 wl_0_8 wl_0_9 wl_0_10 wl_0_11 wl_0_12 wl_0_13 wl_0_14 ++ wl_0_15 vdd gnd ++ sram_2_16_1_scn4m_subm_bitcell_array Xreplica_col_0 + rbl_bl_0_0 rbl_br_0_0 rbl_wl_0_0 wl_0_0 wl_0_1 wl_0_2 wl_0_3 wl_0_4 + wl_0_5 wl_0_6 wl_0_7 wl_0_8 wl_0_9 wl_0_10 wl_0_11 wl_0_12 wl_0_13 + wl_0_14 wl_0_15 vdd gnd -+ sram_replica_column ++ sram_2_16_1_scn4m_subm_replica_column Xdummy_row_0 -+ bl_0_0 br_0_0 rbl_wl_0_0 vdd gnd -+ sram_dummy_array -.ENDS sram_replica_bitcell_array ++ bl_0_0 br_0_0 bl_0_1 br_0_1 rbl_wl_0_0 vdd gnd ++ sram_2_16_1_scn4m_subm_dummy_array +.ENDS sram_2_16_1_scn4m_subm_replica_bitcell_array -.SUBCKT sram_dummy_array_2 +.SUBCKT sram_2_16_1_scn4m_subm_dummy_array_2 + bl_0_0 br_0_0 wl_0_0 wl_0_1 wl_0_2 wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 + wl_0_8 wl_0_9 wl_0_10 wl_0_11 wl_0_12 wl_0_13 wl_0_14 wl_0_15 wl_0_16 + wl_0_17 wl_0_18 vdd gnd @@ -811,14 +410,16 @@ Xbit_r17_c0 Xbit_r18_c0 + bl_0_0 br_0_0 wl_0_18 vdd gnd + dummy_cell_1rw -.ENDS sram_dummy_array_2 +.ENDS sram_2_16_1_scn4m_subm_dummy_array_2 -.SUBCKT sram_dummy_array_0 -+ bl_0_0 br_0_0 bl_0_1 br_0_1 wl_0_0 vdd gnd +.SUBCKT sram_2_16_1_scn4m_subm_dummy_array_0 ++ bl_0_0 br_0_0 bl_0_1 br_0_1 bl_0_2 br_0_2 wl_0_0 vdd gnd * INOUT : bl_0_0 * INOUT : br_0_0 * INOUT : bl_0_1 * INOUT : br_0_1 +* INOUT : bl_0_2 +* INOUT : br_0_2 * INPUT : wl_0_0 * POWER : vdd * GROUND: gnd @@ -828,9 +429,34 @@ Xbit_r0_c0 Xbit_r0_c1 + bl_0_1 br_0_1 wl_0_0 vdd gnd + dummy_cell_1rw -.ENDS sram_dummy_array_0 +Xbit_r0_c2 ++ bl_0_2 br_0_2 wl_0_0 vdd gnd ++ dummy_cell_1rw +.ENDS sram_2_16_1_scn4m_subm_dummy_array_0 -.SUBCKT sram_dummy_array_3 +.SUBCKT sram_2_16_1_scn4m_subm_dummy_array_1 ++ bl_0_0 br_0_0 bl_0_1 br_0_1 bl_0_2 br_0_2 wl_0_0 vdd gnd +* INOUT : bl_0_0 +* INOUT : br_0_0 +* INOUT : bl_0_1 +* INOUT : br_0_1 +* INOUT : bl_0_2 +* INOUT : br_0_2 +* INPUT : wl_0_0 +* POWER : vdd +* GROUND: gnd +Xbit_r0_c0 ++ bl_0_0 br_0_0 wl_0_0 vdd gnd ++ dummy_cell_1rw +Xbit_r0_c1 ++ bl_0_1 br_0_1 wl_0_0 vdd gnd ++ dummy_cell_1rw +Xbit_r0_c2 ++ bl_0_2 br_0_2 wl_0_0 vdd gnd ++ dummy_cell_1rw +.ENDS sram_2_16_1_scn4m_subm_dummy_array_1 + +.SUBCKT sram_2_16_1_scn4m_subm_dummy_array_3 + bl_0_0 br_0_0 wl_0_0 wl_0_1 wl_0_2 wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 + wl_0_8 wl_0_9 wl_0_10 wl_0_11 wl_0_12 wl_0_13 wl_0_14 wl_0_15 wl_0_16 + wl_0_17 wl_0_18 vdd gnd @@ -914,33 +540,18 @@ Xbit_r17_c0 Xbit_r18_c0 + bl_0_0 br_0_0 wl_0_18 vdd gnd + dummy_cell_1rw -.ENDS sram_dummy_array_3 +.ENDS sram_2_16_1_scn4m_subm_dummy_array_3 -.SUBCKT sram_dummy_array_1 -+ bl_0_0 br_0_0 bl_0_1 br_0_1 wl_0_0 vdd gnd -* INOUT : bl_0_0 -* INOUT : br_0_0 -* INOUT : bl_0_1 -* INOUT : br_0_1 -* INPUT : wl_0_0 -* POWER : vdd -* GROUND: gnd -Xbit_r0_c0 -+ bl_0_0 br_0_0 wl_0_0 vdd gnd -+ dummy_cell_1rw -Xbit_r0_c1 -+ bl_0_1 br_0_1 wl_0_0 vdd gnd -+ dummy_cell_1rw -.ENDS sram_dummy_array_1 - -.SUBCKT sram_capped_replica_bitcell_array -+ rbl_bl_0_0 rbl_br_0_0 bl_0_0 br_0_0 rbl_wl_0_0 wl_0_0 wl_0_1 wl_0_2 -+ wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 wl_0_8 wl_0_9 wl_0_10 wl_0_11 -+ wl_0_12 wl_0_13 wl_0_14 wl_0_15 vdd gnd +.SUBCKT sram_2_16_1_scn4m_subm_capped_replica_bitcell_array ++ rbl_bl_0_0 rbl_br_0_0 bl_0_0 br_0_0 bl_0_1 br_0_1 rbl_wl_0_0 wl_0_0 ++ wl_0_1 wl_0_2 wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 wl_0_8 wl_0_9 wl_0_10 ++ wl_0_11 wl_0_12 wl_0_13 wl_0_14 wl_0_15 vdd gnd * INOUT : rbl_bl_0_0 * INOUT : rbl_br_0_0 * INOUT : bl_0_0 * INOUT : br_0_0 +* INOUT : bl_0_1 +* INOUT : br_0_1 * INPUT : rbl_wl_0_0 * INPUT : wl_0_0 * INPUT : wl_0_1 @@ -962,34 +573,518 @@ Xbit_r0_c1 * GROUND: gnd * rbl: [1, 0] left_rbl: [0] right_rbl: [] Xreplica_bitcell_array -+ rbl_bl_0_0 rbl_br_0_0 bl_0_0 br_0_0 rbl_wl_0_0 wl_0_0 wl_0_1 wl_0_2 -+ wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 wl_0_8 wl_0_9 wl_0_10 wl_0_11 -+ wl_0_12 wl_0_13 wl_0_14 wl_0_15 vdd gnd -+ sram_replica_bitcell_array ++ rbl_bl_0_0 rbl_br_0_0 bl_0_0 br_0_0 bl_0_1 br_0_1 rbl_wl_0_0 wl_0_0 ++ wl_0_1 wl_0_2 wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 wl_0_8 wl_0_9 wl_0_10 ++ wl_0_11 wl_0_12 wl_0_13 wl_0_14 wl_0_15 vdd gnd ++ sram_2_16_1_scn4m_subm_replica_bitcell_array Xdummy_row_bot -+ rbl_bl_0_0 rbl_br_0_0 bl_0_0 br_0_0 gnd vdd gnd -+ sram_dummy_array_1 ++ rbl_bl_0_0 rbl_br_0_0 bl_0_0 br_0_0 bl_0_1 br_0_1 gnd vdd gnd ++ sram_2_16_1_scn4m_subm_dummy_array_1 Xdummy_row_top -+ rbl_bl_0_0 rbl_br_0_0 bl_0_0 br_0_0 gnd vdd gnd -+ sram_dummy_array_0 ++ rbl_bl_0_0 rbl_br_0_0 bl_0_0 br_0_0 bl_0_1 br_0_1 gnd vdd gnd ++ sram_2_16_1_scn4m_subm_dummy_array_0 Xdummy_col_left + dummy_left_bl_0_0 dummy_left_br_0_0 gnd rbl_wl_0_0 wl_0_0 wl_0_1 + wl_0_2 wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 wl_0_8 wl_0_9 wl_0_10 + wl_0_11 wl_0_12 wl_0_13 wl_0_14 wl_0_15 gnd vdd gnd -+ sram_dummy_array_2 ++ sram_2_16_1_scn4m_subm_dummy_array_2 Xdummy_col_right + dummy_right_bl_0_0 dummy_right_br_0_0 gnd rbl_wl_0_0 wl_0_0 wl_0_1 + wl_0_2 wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 wl_0_8 wl_0_9 wl_0_10 + wl_0_11 wl_0_12 wl_0_13 wl_0_14 wl_0_15 gnd vdd gnd -+ sram_dummy_array_3 -.ENDS sram_capped_replica_bitcell_array ++ sram_2_16_1_scn4m_subm_dummy_array_3 +.ENDS sram_2_16_1_scn4m_subm_capped_replica_bitcell_array +*********************** "sense_amp" ****************************** -.SUBCKT sram_bank -+ dout0_0 rbl_bl_0_0 din0_0 addr0_0 addr0_1 addr0_2 addr0_3 s_en0 -+ p_en_bar0 w_en0 wl_en0 vdd gnd +.SUBCKT sense_amp bl br dout en vdd gnd + +* SPICE3 file created from sense_amp.ext - technology: scmos + +M1000 gnd en a_56_432# gnd n w=1.8u l=0.4u +M1001 a_56_432# a_48_304# dint gnd n w=1.8u l=0.4u +M1002 a_48_304# dint a_56_432# gnd n w=1.8u l=0.4u +M1003 vdd a_48_304# dint vdd p w=3.6u l=0.4u +M1004 a_48_304# dint vdd vdd p w=3.6u l=0.4u +M1005 bl en dint vdd p w=4.8u l=0.4u +M1006 a_48_304# en br vdd p w=4.8u l=0.4u + +M1007 dout_bar dint vdd vdd p w=1.6u l=0.4u +M1008 gnd dint dout_bar gnd n w=0.8u l=0.4u +M1009 dout dout_bar vdd vdd p w=4.8u l=0.4u +M1010 gnd dout_bar dout gnd n w=2.4u l=0.4u +.ENDS + +.SUBCKT sram_2_16_1_scn4m_subm_sense_amp_array ++ data_0 bl_0 br_0 data_1 bl_1 br_1 en vdd gnd +* OUTPUT: data_0 +* INPUT : bl_0 +* INPUT : br_0 +* OUTPUT: data_1 +* INPUT : bl_1 +* INPUT : br_1 +* INPUT : en +* POWER : vdd +* GROUND: gnd +* words_per_row: 1 +Xsa_d0 ++ bl_0 br_0 data_0 en vdd gnd ++ sense_amp +Xsa_d1 ++ bl_1 br_1 data_1 en vdd gnd ++ sense_amp +.ENDS sram_2_16_1_scn4m_subm_sense_amp_array + +* spice ptx M{0} {1} p m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p + +.SUBCKT sram_2_16_1_scn4m_subm_precharge_0 ++ bl br en_bar vdd +* OUTPUT: bl +* OUTPUT: br +* INPUT : en_bar +* POWER : vdd +Mlower_pmos bl en_bar br vdd p m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p +Mupper_pmos1 bl en_bar vdd vdd p m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p +Mupper_pmos2 br en_bar vdd vdd p m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p +.ENDS sram_2_16_1_scn4m_subm_precharge_0 + +.SUBCKT sram_2_16_1_scn4m_subm_precharge_array ++ bl_0 br_0 bl_1 br_1 bl_2 br_2 en_bar vdd +* OUTPUT: bl_0 +* OUTPUT: br_0 +* OUTPUT: bl_1 +* OUTPUT: br_1 +* OUTPUT: bl_2 +* OUTPUT: br_2 +* INPUT : en_bar +* POWER : vdd +* cols: 3 size: 1 bl: bl br: br +Xpre_column_0 ++ bl_0 br_0 en_bar vdd ++ sram_2_16_1_scn4m_subm_precharge_0 +Xpre_column_1 ++ bl_1 br_1 en_bar vdd ++ sram_2_16_1_scn4m_subm_precharge_0 +Xpre_column_2 ++ bl_2 br_2 en_bar vdd ++ sram_2_16_1_scn4m_subm_precharge_0 +.ENDS sram_2_16_1_scn4m_subm_precharge_array +*********************** Write_Driver ****************************** +.SUBCKT write_driver din bl br en vdd gnd + +**** Inverter to conver Data_in to data_in_bar ****** +* din_bar = inv(din) +M_1 din_bar din gnd gnd n W=0.8u L=0.4u +M_2 din_bar din vdd vdd p W=1.4u L=0.4u + +**** 2input nand gate follwed by inverter to drive BL ****** +* din_bar_gated = nand(en, din) +M_3 din_bar_gated en net_7 gnd n W=1.4u L=0.4u +M_4 net_7 din gnd gnd n W=1.4u L=0.4u +M_5 din_bar_gated en vdd vdd p W=1.4u L=0.4u +M_6 din_bar_gated din vdd vdd p W=1.4u L=0.4u +* din_bar_gated_bar = inv(din_bar_gated) +M_7 din_bar_gated_bar din_bar_gated vdd vdd p W=1.4u L=0.4u +M_8 din_bar_gated_bar din_bar_gated gnd gnd n W=0.8u L=0.4u + +**** 2input nand gate follwed by inverter to drive BR****** +* din_gated = nand(en, din_bar) +M_9 din_gated en vdd vdd p W=1.4u L=0.4u +M_10 din_gated en net_8 gnd n W=1.4u L=0.4u +M_11 net_8 din_bar gnd gnd n W=1.4u L=0.4u +M_12 din_gated din_bar vdd vdd p W=1.4u L=0.4u +* din_gated_bar = inv(din_gated) +M_13 din_gated_bar din_gated vdd vdd p W=1.4u L=0.4u +M_14 din_gated_bar din_gated gnd gnd n W=0.8u L=0.4u + +************************************************ +* pull down with en enable +M_15 bl din_gated_bar gnd gnd n W=2.4u L=0.4u +M_16 br din_bar_gated_bar gnd gnd n W=2.4u L=0.4u + + + +.ENDS $ write_driver + +.SUBCKT sram_2_16_1_scn4m_subm_write_driver_array ++ data_0 data_1 bl_0 br_0 bl_1 br_1 en vdd gnd +* INPUT : data_0 +* INPUT : data_1 +* OUTPUT: bl_0 +* OUTPUT: br_0 +* OUTPUT: bl_1 +* OUTPUT: br_1 +* INPUT : en +* POWER : vdd +* GROUND: gnd +* word_size 2 +Xwrite_driver0 ++ data_0 bl_0 br_0 en vdd gnd ++ write_driver +Xwrite_driver1 ++ data_1 bl_1 br_1 en vdd gnd ++ write_driver +.ENDS sram_2_16_1_scn4m_subm_write_driver_array + +.SUBCKT sram_2_16_1_scn4m_subm_port_data ++ rbl_bl rbl_br bl_0 br_0 bl_1 br_1 dout_0 dout_1 din_0 din_1 s_en ++ p_en_bar w_en vdd gnd +* INOUT : rbl_bl +* INOUT : rbl_br +* INOUT : bl_0 +* INOUT : br_0 +* INOUT : bl_1 +* INOUT : br_1 +* OUTPUT: dout_0 +* OUTPUT: dout_1 +* INPUT : din_0 +* INPUT : din_1 +* INPUT : s_en +* INPUT : p_en_bar +* INPUT : w_en +* POWER : vdd +* GROUND: gnd +Xprecharge_array0 ++ rbl_bl rbl_br bl_0 br_0 bl_1 br_1 p_en_bar vdd ++ sram_2_16_1_scn4m_subm_precharge_array +Xsense_amp_array0 ++ dout_0 bl_0 br_0 dout_1 bl_1 br_1 s_en vdd gnd ++ sram_2_16_1_scn4m_subm_sense_amp_array +Xwrite_driver_array0 ++ din_0 din_1 bl_0 br_0 bl_1 br_1 w_en vdd gnd ++ sram_2_16_1_scn4m_subm_write_driver_array +.ENDS sram_2_16_1_scn4m_subm_port_data + +* spice ptx M{0} {1} p m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p + +* spice ptx M{0} {1} n m=1 w=0.8u l=0.4u pd=2.40u ps=2.40u as=0.80p ad=0.80p + +.SUBCKT sram_2_16_1_scn4m_subm_pinv ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +Mpinv_pmos Z A vdd vdd p m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p +Mpinv_nmos Z A gnd gnd n m=1 w=0.8u l=0.4u pd=2.40u ps=2.40u as=0.80p ad=0.80p +.ENDS sram_2_16_1_scn4m_subm_pinv + +* spice ptx M{0} {1} n m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p + +* spice ptx M{0} {1} n m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p + +.SUBCKT sram_2_16_1_scn4m_subm_pnand2 ++ A B Z vdd gnd +* INPUT : A +* INPUT : B +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +Mpnand2_pmos1 vdd A Z vdd p m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p +Mpnand2_pmos2 Z B vdd vdd p m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p +Mpnand2_nmos1 Z B net1 gnd n m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p +Mpnand2_nmos2 net1 A gnd gnd n m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p +.ENDS sram_2_16_1_scn4m_subm_pnand2 + +.SUBCKT sram_2_16_1_scn4m_subm_and2_dec ++ A B Z vdd gnd +* INPUT : A +* INPUT : B +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* size: 1 +Xpand2_dec_nand ++ A B zb_int vdd gnd ++ sram_2_16_1_scn4m_subm_pnand2 +Xpand2_dec_inv ++ zb_int Z vdd gnd ++ sram_2_16_1_scn4m_subm_pinv +.ENDS sram_2_16_1_scn4m_subm_and2_dec + +.SUBCKT sram_2_16_1_scn4m_subm_hierarchical_predecode2x4 ++ in_0 in_1 out_0 out_1 out_2 out_3 vdd gnd +* INPUT : in_0 +* INPUT : in_1 +* OUTPUT: out_0 +* OUTPUT: out_1 +* OUTPUT: out_2 +* OUTPUT: out_3 +* POWER : vdd +* GROUND: gnd +Xpre_inv_0 ++ in_0 inbar_0 vdd gnd ++ sram_2_16_1_scn4m_subm_pinv +Xpre_inv_1 ++ in_1 inbar_1 vdd gnd ++ sram_2_16_1_scn4m_subm_pinv +XXpre2x4_and_0 ++ inbar_0 inbar_1 out_0 vdd gnd ++ sram_2_16_1_scn4m_subm_and2_dec +XXpre2x4_and_1 ++ in_0 inbar_1 out_1 vdd gnd ++ sram_2_16_1_scn4m_subm_and2_dec +XXpre2x4_and_2 ++ inbar_0 in_1 out_2 vdd gnd ++ sram_2_16_1_scn4m_subm_and2_dec +XXpre2x4_and_3 ++ in_0 in_1 out_3 vdd gnd ++ sram_2_16_1_scn4m_subm_and2_dec +.ENDS sram_2_16_1_scn4m_subm_hierarchical_predecode2x4 + +.SUBCKT sram_2_16_1_scn4m_subm_hierarchical_decoder ++ addr_0 addr_1 addr_2 addr_3 decode_0 decode_1 decode_2 decode_3 ++ decode_4 decode_5 decode_6 decode_7 decode_8 decode_9 decode_10 ++ decode_11 decode_12 decode_13 decode_14 decode_15 vdd gnd +* INPUT : addr_0 +* INPUT : addr_1 +* INPUT : addr_2 +* INPUT : addr_3 +* OUTPUT: decode_0 +* OUTPUT: decode_1 +* OUTPUT: decode_2 +* OUTPUT: decode_3 +* OUTPUT: decode_4 +* OUTPUT: decode_5 +* OUTPUT: decode_6 +* OUTPUT: decode_7 +* OUTPUT: decode_8 +* OUTPUT: decode_9 +* OUTPUT: decode_10 +* OUTPUT: decode_11 +* OUTPUT: decode_12 +* OUTPUT: decode_13 +* OUTPUT: decode_14 +* OUTPUT: decode_15 +* POWER : vdd +* GROUND: gnd +Xpre_0 ++ addr_0 addr_1 out_0 out_1 out_2 out_3 vdd gnd ++ sram_2_16_1_scn4m_subm_hierarchical_predecode2x4 +Xpre_1 ++ addr_2 addr_3 out_4 out_5 out_6 out_7 vdd gnd ++ sram_2_16_1_scn4m_subm_hierarchical_predecode2x4 +XDEC_AND_0 ++ out_0 out_4 decode_0 vdd gnd ++ sram_2_16_1_scn4m_subm_and2_dec +XDEC_AND_4 ++ out_0 out_5 decode_4 vdd gnd ++ sram_2_16_1_scn4m_subm_and2_dec +XDEC_AND_8 ++ out_0 out_6 decode_8 vdd gnd ++ sram_2_16_1_scn4m_subm_and2_dec +XDEC_AND_12 ++ out_0 out_7 decode_12 vdd gnd ++ sram_2_16_1_scn4m_subm_and2_dec +XDEC_AND_1 ++ out_1 out_4 decode_1 vdd gnd ++ sram_2_16_1_scn4m_subm_and2_dec +XDEC_AND_5 ++ out_1 out_5 decode_5 vdd gnd ++ sram_2_16_1_scn4m_subm_and2_dec +XDEC_AND_9 ++ out_1 out_6 decode_9 vdd gnd ++ sram_2_16_1_scn4m_subm_and2_dec +XDEC_AND_13 ++ out_1 out_7 decode_13 vdd gnd ++ sram_2_16_1_scn4m_subm_and2_dec +XDEC_AND_2 ++ out_2 out_4 decode_2 vdd gnd ++ sram_2_16_1_scn4m_subm_and2_dec +XDEC_AND_6 ++ out_2 out_5 decode_6 vdd gnd ++ sram_2_16_1_scn4m_subm_and2_dec +XDEC_AND_10 ++ out_2 out_6 decode_10 vdd gnd ++ sram_2_16_1_scn4m_subm_and2_dec +XDEC_AND_14 ++ out_2 out_7 decode_14 vdd gnd ++ sram_2_16_1_scn4m_subm_and2_dec +XDEC_AND_3 ++ out_3 out_4 decode_3 vdd gnd ++ sram_2_16_1_scn4m_subm_and2_dec +XDEC_AND_7 ++ out_3 out_5 decode_7 vdd gnd ++ sram_2_16_1_scn4m_subm_and2_dec +XDEC_AND_11 ++ out_3 out_6 decode_11 vdd gnd ++ sram_2_16_1_scn4m_subm_and2_dec +XDEC_AND_15 ++ out_3 out_7 decode_15 vdd gnd ++ sram_2_16_1_scn4m_subm_and2_dec +.ENDS sram_2_16_1_scn4m_subm_hierarchical_decoder + +.SUBCKT sram_2_16_1_scn4m_subm_wordline_driver ++ A B Z vdd gnd +* INPUT : A +* INPUT : B +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +Xwld_nand ++ A B zb_int vdd gnd ++ sram_2_16_1_scn4m_subm_pnand2 +Xwl_driver ++ zb_int Z vdd gnd ++ sram_2_16_1_scn4m_subm_pinv +.ENDS sram_2_16_1_scn4m_subm_wordline_driver + +.SUBCKT sram_2_16_1_scn4m_subm_wordline_driver_array ++ in_0 in_1 in_2 in_3 in_4 in_5 in_6 in_7 in_8 in_9 in_10 in_11 in_12 ++ in_13 in_14 in_15 wl_0 wl_1 wl_2 wl_3 wl_4 wl_5 wl_6 wl_7 wl_8 wl_9 ++ wl_10 wl_11 wl_12 wl_13 wl_14 wl_15 en vdd gnd +* INPUT : in_0 +* INPUT : in_1 +* INPUT : in_2 +* INPUT : in_3 +* INPUT : in_4 +* INPUT : in_5 +* INPUT : in_6 +* INPUT : in_7 +* INPUT : in_8 +* INPUT : in_9 +* INPUT : in_10 +* INPUT : in_11 +* INPUT : in_12 +* INPUT : in_13 +* INPUT : in_14 +* INPUT : in_15 +* OUTPUT: wl_0 +* OUTPUT: wl_1 +* OUTPUT: wl_2 +* OUTPUT: wl_3 +* OUTPUT: wl_4 +* OUTPUT: wl_5 +* OUTPUT: wl_6 +* OUTPUT: wl_7 +* OUTPUT: wl_8 +* OUTPUT: wl_9 +* OUTPUT: wl_10 +* OUTPUT: wl_11 +* OUTPUT: wl_12 +* OUTPUT: wl_13 +* OUTPUT: wl_14 +* OUTPUT: wl_15 +* INPUT : en +* POWER : vdd +* GROUND: gnd +* rows: 16 cols: 2 +Xwl_driver_and0 ++ in_0 en wl_0 vdd gnd ++ sram_2_16_1_scn4m_subm_wordline_driver +Xwl_driver_and1 ++ in_1 en wl_1 vdd gnd ++ sram_2_16_1_scn4m_subm_wordline_driver +Xwl_driver_and2 ++ in_2 en wl_2 vdd gnd ++ sram_2_16_1_scn4m_subm_wordline_driver +Xwl_driver_and3 ++ in_3 en wl_3 vdd gnd ++ sram_2_16_1_scn4m_subm_wordline_driver +Xwl_driver_and4 ++ in_4 en wl_4 vdd gnd ++ sram_2_16_1_scn4m_subm_wordline_driver +Xwl_driver_and5 ++ in_5 en wl_5 vdd gnd ++ sram_2_16_1_scn4m_subm_wordline_driver +Xwl_driver_and6 ++ in_6 en wl_6 vdd gnd ++ sram_2_16_1_scn4m_subm_wordline_driver +Xwl_driver_and7 ++ in_7 en wl_7 vdd gnd ++ sram_2_16_1_scn4m_subm_wordline_driver +Xwl_driver_and8 ++ in_8 en wl_8 vdd gnd ++ sram_2_16_1_scn4m_subm_wordline_driver +Xwl_driver_and9 ++ in_9 en wl_9 vdd gnd ++ sram_2_16_1_scn4m_subm_wordline_driver +Xwl_driver_and10 ++ in_10 en wl_10 vdd gnd ++ sram_2_16_1_scn4m_subm_wordline_driver +Xwl_driver_and11 ++ in_11 en wl_11 vdd gnd ++ sram_2_16_1_scn4m_subm_wordline_driver +Xwl_driver_and12 ++ in_12 en wl_12 vdd gnd ++ sram_2_16_1_scn4m_subm_wordline_driver +Xwl_driver_and13 ++ in_13 en wl_13 vdd gnd ++ sram_2_16_1_scn4m_subm_wordline_driver +Xwl_driver_and14 ++ in_14 en wl_14 vdd gnd ++ sram_2_16_1_scn4m_subm_wordline_driver +Xwl_driver_and15 ++ in_15 en wl_15 vdd gnd ++ sram_2_16_1_scn4m_subm_wordline_driver +.ENDS sram_2_16_1_scn4m_subm_wordline_driver_array + +.SUBCKT sram_2_16_1_scn4m_subm_and2_dec_0 ++ A B Z vdd gnd +* INPUT : A +* INPUT : B +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* size: 1 +Xpand2_dec_nand ++ A B zb_int vdd gnd ++ sram_2_16_1_scn4m_subm_pnand2 +Xpand2_dec_inv ++ zb_int Z vdd gnd ++ sram_2_16_1_scn4m_subm_pinv +.ENDS sram_2_16_1_scn4m_subm_and2_dec_0 + +.SUBCKT sram_2_16_1_scn4m_subm_port_address ++ addr_0 addr_1 addr_2 addr_3 wl_en wl_0 wl_1 wl_2 wl_3 wl_4 wl_5 wl_6 ++ wl_7 wl_8 wl_9 wl_10 wl_11 wl_12 wl_13 wl_14 wl_15 rbl_wl vdd gnd +* INPUT : addr_0 +* INPUT : addr_1 +* INPUT : addr_2 +* INPUT : addr_3 +* INPUT : wl_en +* OUTPUT: wl_0 +* OUTPUT: wl_1 +* OUTPUT: wl_2 +* OUTPUT: wl_3 +* OUTPUT: wl_4 +* OUTPUT: wl_5 +* OUTPUT: wl_6 +* OUTPUT: wl_7 +* OUTPUT: wl_8 +* OUTPUT: wl_9 +* OUTPUT: wl_10 +* OUTPUT: wl_11 +* OUTPUT: wl_12 +* OUTPUT: wl_13 +* OUTPUT: wl_14 +* OUTPUT: wl_15 +* OUTPUT: rbl_wl +* POWER : vdd +* GROUND: gnd +Xrow_decoder ++ addr_0 addr_1 addr_2 addr_3 dec_out_0 dec_out_1 dec_out_2 dec_out_3 ++ dec_out_4 dec_out_5 dec_out_6 dec_out_7 dec_out_8 dec_out_9 dec_out_10 ++ dec_out_11 dec_out_12 dec_out_13 dec_out_14 dec_out_15 vdd gnd ++ sram_2_16_1_scn4m_subm_hierarchical_decoder +Xwordline_driver ++ dec_out_0 dec_out_1 dec_out_2 dec_out_3 dec_out_4 dec_out_5 dec_out_6 ++ dec_out_7 dec_out_8 dec_out_9 dec_out_10 dec_out_11 dec_out_12 ++ dec_out_13 dec_out_14 dec_out_15 wl_0 wl_1 wl_2 wl_3 wl_4 wl_5 wl_6 ++ wl_7 wl_8 wl_9 wl_10 wl_11 wl_12 wl_13 wl_14 wl_15 wl_en vdd gnd ++ sram_2_16_1_scn4m_subm_wordline_driver_array +Xrbl_driver ++ wl_en vdd rbl_wl vdd gnd ++ sram_2_16_1_scn4m_subm_and2_dec_0 +.ENDS sram_2_16_1_scn4m_subm_port_address + +.SUBCKT sram_2_16_1_scn4m_subm_bank ++ dout0_0 dout0_1 rbl_bl_0_0 din0_0 din0_1 addr0_0 addr0_1 addr0_2 ++ addr0_3 s_en0 p_en_bar0 w_en0 wl_en0 vdd gnd * OUTPUT: dout0_0 +* OUTPUT: dout0_1 * OUTPUT: rbl_bl_0_0 * INPUT : din0_0 +* INPUT : din0_1 * INPUT : addr0_0 * INPUT : addr0_1 * INPUT : addr0_2 @@ -1001,20 +1096,20 @@ Xdummy_col_right * POWER : vdd * GROUND: gnd Xbitcell_array -+ rbl_bl_0_0 rbl_br_0_0 bl_0_0 br_0_0 rbl_wl0 wl_0_0 wl_0_1 wl_0_2 -+ wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 wl_0_8 wl_0_9 wl_0_10 wl_0_11 -+ wl_0_12 wl_0_13 wl_0_14 wl_0_15 vdd gnd -+ sram_capped_replica_bitcell_array ++ rbl_bl_0_0 rbl_br_0_0 bl_0_0 br_0_0 bl_0_1 br_0_1 rbl_wl0 wl_0_0 ++ wl_0_1 wl_0_2 wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 wl_0_8 wl_0_9 wl_0_10 ++ wl_0_11 wl_0_12 wl_0_13 wl_0_14 wl_0_15 vdd gnd ++ sram_2_16_1_scn4m_subm_capped_replica_bitcell_array Xport_data0 -+ rbl_bl_0_0 rbl_br_0_0 bl_0_0 br_0_0 dout0_0 din0_0 s_en0 p_en_bar0 -+ w_en0 vdd gnd -+ sram_port_data ++ rbl_bl_0_0 rbl_br_0_0 bl_0_0 br_0_0 bl_0_1 br_0_1 dout0_0 dout0_1 ++ din0_0 din0_1 s_en0 p_en_bar0 w_en0 vdd gnd ++ sram_2_16_1_scn4m_subm_port_data Xport_address0 + addr0_0 addr0_1 addr0_2 addr0_3 wl_en0 wl_0_0 wl_0_1 wl_0_2 wl_0_3 + wl_0_4 wl_0_5 wl_0_6 wl_0_7 wl_0_8 wl_0_9 wl_0_10 wl_0_11 wl_0_12 + wl_0_13 wl_0_14 wl_0_15 rbl_wl0 vdd gnd -+ sram_port_address -.ENDS sram_bank ++ sram_2_16_1_scn4m_subm_port_address +.ENDS sram_2_16_1_scn4m_subm_bank *********************** "dff" ****************************** * Positive edge-triggered FF .SUBCKT dff D Q clk vdd gnd @@ -1046,7 +1141,25 @@ M1021 Q a_280_24# gnd gnd n w=4u l=0.4u .ENDS -.SUBCKT sram_row_addr_dff +.SUBCKT sram_2_16_1_scn4m_subm_data_dff ++ din_0 din_1 dout_0 dout_1 clk vdd gnd +* INPUT : din_0 +* INPUT : din_1 +* OUTPUT: dout_0 +* OUTPUT: dout_1 +* INPUT : clk +* POWER : vdd +* GROUND: gnd +* rows: 1 cols: 2 +Xdff_r0_c0 ++ din_0 dout_0 clk vdd gnd ++ dff +Xdff_r0_c1 ++ din_1 dout_1 clk vdd gnd ++ dff +.ENDS sram_2_16_1_scn4m_subm_data_dff + +.SUBCKT sram_2_16_1_scn4m_subm_row_addr_dff + din_0 din_1 din_2 din_3 dout_0 dout_1 dout_2 dout_3 clk vdd gnd * INPUT : din_0 * INPUT : din_1 @@ -1072,63 +1185,23 @@ Xdff_r2_c0 Xdff_r3_c0 + din_3 dout_3 clk vdd gnd + dff -.ENDS sram_row_addr_dff +.ENDS sram_2_16_1_scn4m_subm_row_addr_dff -* spice ptx M{0} {1} n m=3 w=3.2u l=0.4u pd=7.20u ps=7.20u as=3.20p ad=3.20p +* spice ptx M{0} {1} n m=1 w=4.0u l=0.4u pd=8.80u ps=8.80u as=4.00p ad=4.00p -* spice ptx M{0} {1} p m=3 w=6.4u l=0.4u pd=13.60u ps=13.60u as=6.40p ad=6.40p +* spice ptx M{0} {1} p m=1 w=8.0u l=0.4u pd=16.80u ps=16.80u as=8.00p ad=8.00p -.SUBCKT sram_pinv_2 +.SUBCKT sram_2_16_1_scn4m_subm_pinv_7 + A Z vdd gnd * INPUT : A * OUTPUT: Z * POWER : vdd * GROUND: gnd -Mpinv_pmos Z A vdd vdd p m=3 w=6.4u l=0.4u pd=13.60u ps=13.60u as=6.40p ad=6.40p -Mpinv_nmos Z A gnd gnd n m=3 w=3.2u l=0.4u pd=7.20u ps=7.20u as=3.20p ad=3.20p -.ENDS sram_pinv_2 +Mpinv_pmos Z A vdd vdd p m=1 w=8.0u l=0.4u pd=16.80u ps=16.80u as=8.00p ad=8.00p +Mpinv_nmos Z A gnd gnd n m=1 w=4.0u l=0.4u pd=8.80u ps=8.80u as=4.00p ad=4.00p +.ENDS sram_2_16_1_scn4m_subm_pinv_7 -.SUBCKT sram_pdriver -+ A Z vdd gnd -* INPUT : A -* OUTPUT: Z -* POWER : vdd -* GROUND: gnd -* sizes: [12] -Xbuf_inv1 -+ A Z vdd gnd -+ sram_pinv_2 -.ENDS sram_pdriver - -.SUBCKT sram_pnand2_0 -+ A B Z vdd gnd -* INPUT : A -* INPUT : B -* OUTPUT: Z -* POWER : vdd -* GROUND: gnd -Mpnand2_pmos1 vdd A Z vdd p m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p -Mpnand2_pmos2 Z B vdd vdd p m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p -Mpnand2_nmos1 Z B net1 gnd n m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p -Mpnand2_nmos2 net1 A gnd gnd n m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p -.ENDS sram_pnand2_0 - -.SUBCKT sram_pand2 -+ A B Z vdd gnd -* INPUT : A -* INPUT : B -* OUTPUT: Z -* POWER : vdd -* GROUND: gnd -Xpand2_nand -+ A B zb_int vdd gnd -+ sram_pnand2_0 -Xpand2_inv -+ zb_int Z vdd gnd -+ sram_pdriver -.ENDS sram_pand2 - -.SUBCKT sram_pinv_10 +.SUBCKT sram_2_16_1_scn4m_subm_pinv_5 + A Z vdd gnd * INPUT : A * OUTPUT: Z @@ -1136,274 +1209,26 @@ Xpand2_inv * GROUND: gnd Mpinv_pmos Z A vdd vdd p m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p Mpinv_nmos Z A gnd gnd n m=1 w=0.8u l=0.4u pd=2.40u ps=2.40u as=0.80p ad=0.80p -.ENDS sram_pinv_10 +.ENDS sram_2_16_1_scn4m_subm_pinv_5 -.SUBCKT sram_delay_chain -+ in out vdd gnd -* INPUT : in -* OUTPUT: out -* POWER : vdd -* GROUND: gnd -* fanouts: [4, 4, 4, 4, 4, 4, 4, 4, 4] -Xdinv0 -+ in dout_1 vdd gnd -+ sram_pinv_10 -Xdload_0_0 -+ dout_1 n_0_0 vdd gnd -+ sram_pinv_10 -Xdload_0_1 -+ dout_1 n_0_1 vdd gnd -+ sram_pinv_10 -Xdload_0_2 -+ dout_1 n_0_2 vdd gnd -+ sram_pinv_10 -Xdload_0_3 -+ dout_1 n_0_3 vdd gnd -+ sram_pinv_10 -Xdinv1 -+ dout_1 dout_2 vdd gnd -+ sram_pinv_10 -Xdload_1_0 -+ dout_2 n_1_0 vdd gnd -+ sram_pinv_10 -Xdload_1_1 -+ dout_2 n_1_1 vdd gnd -+ sram_pinv_10 -Xdload_1_2 -+ dout_2 n_1_2 vdd gnd -+ sram_pinv_10 -Xdload_1_3 -+ dout_2 n_1_3 vdd gnd -+ sram_pinv_10 -Xdinv2 -+ dout_2 dout_3 vdd gnd -+ sram_pinv_10 -Xdload_2_0 -+ dout_3 n_2_0 vdd gnd -+ sram_pinv_10 -Xdload_2_1 -+ dout_3 n_2_1 vdd gnd -+ sram_pinv_10 -Xdload_2_2 -+ dout_3 n_2_2 vdd gnd -+ sram_pinv_10 -Xdload_2_3 -+ dout_3 n_2_3 vdd gnd -+ sram_pinv_10 -Xdinv3 -+ dout_3 dout_4 vdd gnd -+ sram_pinv_10 -Xdload_3_0 -+ dout_4 n_3_0 vdd gnd -+ sram_pinv_10 -Xdload_3_1 -+ dout_4 n_3_1 vdd gnd -+ sram_pinv_10 -Xdload_3_2 -+ dout_4 n_3_2 vdd gnd -+ sram_pinv_10 -Xdload_3_3 -+ dout_4 n_3_3 vdd gnd -+ sram_pinv_10 -Xdinv4 -+ dout_4 dout_5 vdd gnd -+ sram_pinv_10 -Xdload_4_0 -+ dout_5 n_4_0 vdd gnd -+ sram_pinv_10 -Xdload_4_1 -+ dout_5 n_4_1 vdd gnd -+ sram_pinv_10 -Xdload_4_2 -+ dout_5 n_4_2 vdd gnd -+ sram_pinv_10 -Xdload_4_3 -+ dout_5 n_4_3 vdd gnd -+ sram_pinv_10 -Xdinv5 -+ dout_5 dout_6 vdd gnd -+ sram_pinv_10 -Xdload_5_0 -+ dout_6 n_5_0 vdd gnd -+ sram_pinv_10 -Xdload_5_1 -+ dout_6 n_5_1 vdd gnd -+ sram_pinv_10 -Xdload_5_2 -+ dout_6 n_5_2 vdd gnd -+ sram_pinv_10 -Xdload_5_3 -+ dout_6 n_5_3 vdd gnd -+ sram_pinv_10 -Xdinv6 -+ dout_6 dout_7 vdd gnd -+ sram_pinv_10 -Xdload_6_0 -+ dout_7 n_6_0 vdd gnd -+ sram_pinv_10 -Xdload_6_1 -+ dout_7 n_6_1 vdd gnd -+ sram_pinv_10 -Xdload_6_2 -+ dout_7 n_6_2 vdd gnd -+ sram_pinv_10 -Xdload_6_3 -+ dout_7 n_6_3 vdd gnd -+ sram_pinv_10 -Xdinv7 -+ dout_7 dout_8 vdd gnd -+ sram_pinv_10 -Xdload_7_0 -+ dout_8 n_7_0 vdd gnd -+ sram_pinv_10 -Xdload_7_1 -+ dout_8 n_7_1 vdd gnd -+ sram_pinv_10 -Xdload_7_2 -+ dout_8 n_7_2 vdd gnd -+ sram_pinv_10 -Xdload_7_3 -+ dout_8 n_7_3 vdd gnd -+ sram_pinv_10 -Xdinv8 -+ dout_8 out vdd gnd -+ sram_pinv_10 -Xdload_8_0 -+ out n_8_0 vdd gnd -+ sram_pinv_10 -Xdload_8_1 -+ out n_8_1 vdd gnd -+ sram_pinv_10 -Xdload_8_2 -+ out n_8_2 vdd gnd -+ sram_pinv_10 -Xdload_8_3 -+ out n_8_3 vdd gnd -+ sram_pinv_10 -.ENDS sram_delay_chain - -.SUBCKT sram_pinv_5 +.SUBCKT sram_2_16_1_scn4m_subm_pdriver_1 + A Z vdd gnd * INPUT : A * OUTPUT: Z * POWER : vdd * GROUND: gnd -Mpinv_pmos Z A vdd vdd p m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p -Mpinv_nmos Z A gnd gnd n m=1 w=0.8u l=0.4u pd=2.40u ps=2.40u as=0.80p ad=0.80p -.ENDS sram_pinv_5 - -.SUBCKT sram_pdriver_4 -+ A Z vdd gnd -* INPUT : A -* OUTPUT: Z -* POWER : vdd -* GROUND: gnd -* sizes: [1, 1] +* sizes: [1, 5] Xbuf_inv1 + A Zb1_int vdd gnd -+ sram_pinv_5 ++ sram_2_16_1_scn4m_subm_pinv_5 Xbuf_inv2 + Zb1_int Z vdd gnd -+ sram_pinv_5 -.ENDS sram_pdriver_4 - -* spice ptx M{0} {1} n m=1 w=3.2u l=0.4u pd=7.20u ps=7.20u as=3.20p ad=3.20p - -* spice ptx M{0} {1} p m=1 w=6.4u l=0.4u pd=13.60u ps=13.60u as=6.40p ad=6.40p - -.SUBCKT sram_pinv_1 -+ A Z vdd gnd -* INPUT : A -* OUTPUT: Z -* POWER : vdd -* GROUND: gnd -Mpinv_pmos Z A vdd vdd p m=1 w=6.4u l=0.4u pd=13.60u ps=13.60u as=6.40p ad=6.40p -Mpinv_nmos Z A gnd gnd n m=1 w=3.2u l=0.4u pd=7.20u ps=7.20u as=3.20p ad=3.20p -.ENDS sram_pinv_1 ++ sram_2_16_1_scn4m_subm_pinv_7 +.ENDS sram_2_16_1_scn4m_subm_pdriver_1 * spice ptx M{0} {1} n m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p -* spice ptx M{0} {1} p m=1 w=3.2u l=0.4u pd=7.20u ps=7.20u as=3.20p ad=3.20p - -.SUBCKT sram_pinv_0 -+ A Z vdd gnd -* INPUT : A -* OUTPUT: Z -* POWER : vdd -* GROUND: gnd -Mpinv_pmos Z A vdd vdd p m=1 w=3.2u l=0.4u pd=7.20u ps=7.20u as=3.20p ad=3.20p -Mpinv_nmos Z A gnd gnd n m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p -.ENDS sram_pinv_0 - -.SUBCKT sram_dff_buf_0 -+ D Q Qb clk vdd gnd -* INPUT : D -* OUTPUT: Q -* OUTPUT: Qb -* INPUT : clk -* POWER : vdd -* GROUND: gnd -* inv1: 2 inv2: 4 -Xdff_buf_dff -+ D qint clk vdd gnd -+ dff -Xdff_buf_inv1 -+ qint Qb vdd gnd -+ sram_pinv_0 -Xdff_buf_inv2 -+ Qb Q vdd gnd -+ sram_pinv_1 -.ENDS sram_dff_buf_0 - -.SUBCKT sram_dff_buf_array -+ din_0 din_1 dout_0 dout_bar_0 dout_1 dout_bar_1 clk vdd gnd -* INPUT : din_0 -* INPUT : din_1 -* OUTPUT: dout_0 -* OUTPUT: dout_bar_0 -* OUTPUT: dout_1 -* OUTPUT: dout_bar_1 -* INPUT : clk -* POWER : vdd -* GROUND: gnd -* inv1: 2 inv2: 4 -Xdff_r0_c0 -+ din_0 dout_0 dout_bar_0 clk vdd gnd -+ sram_dff_buf_0 -Xdff_r1_c0 -+ din_1 dout_1 dout_bar_1 clk vdd gnd -+ sram_dff_buf_0 -.ENDS sram_dff_buf_array - -* spice ptx M{0} {1} p m=2 w=7.2u l=0.4u pd=15.20u ps=15.20u as=7.20p ad=7.20p - -* spice ptx M{0} {1} n m=2 w=3.6u l=0.4u pd=8.00u ps=8.00u as=3.60p ad=3.60p - -.SUBCKT sram_pinv_9 -+ A Z vdd gnd -* INPUT : A -* OUTPUT: Z -* POWER : vdd -* GROUND: gnd -Mpinv_pmos Z A vdd vdd p m=2 w=7.2u l=0.4u pd=15.20u ps=15.20u as=7.20p ad=7.20p -Mpinv_nmos Z A gnd gnd n m=2 w=3.6u l=0.4u pd=8.00u ps=8.00u as=3.60p ad=3.60p -.ENDS sram_pinv_9 - -.SUBCKT sram_pdriver_2 -+ A Z vdd gnd -* INPUT : A -* OUTPUT: Z -* POWER : vdd -* GROUND: gnd -* sizes: [9] -Xbuf_inv1 -+ A Z vdd gnd -+ sram_pinv_9 -.ENDS sram_pdriver_2 - -* spice ptx M{0} {1} n m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p - -.SUBCKT sram_pnand3_0 +.SUBCKT sram_2_16_1_scn4m_subm_pnand3_0 + A B C Z vdd gnd * INPUT : A * INPUT : B @@ -1417,9 +1242,35 @@ Mpnand3_pmos3 Z C vdd vdd p m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60 Mpnand3_nmos1 Z C net1 gnd n m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p Mpnand3_nmos2 net1 B net2 gnd n m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p Mpnand3_nmos3 net2 A gnd gnd n m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p -.ENDS sram_pnand3_0 +.ENDS sram_2_16_1_scn4m_subm_pnand3_0 -.SUBCKT sram_pand3 +* spice ptx M{0} {1} n m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p + +* spice ptx M{0} {1} p m=1 w=3.2u l=0.4u pd=7.20u ps=7.20u as=3.20p ad=3.20p + +.SUBCKT sram_2_16_1_scn4m_subm_pinv_6 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +Mpinv_pmos Z A vdd vdd p m=1 w=3.2u l=0.4u pd=7.20u ps=7.20u as=3.20p ad=3.20p +Mpinv_nmos Z A gnd gnd n m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p +.ENDS sram_2_16_1_scn4m_subm_pinv_6 + +.SUBCKT sram_2_16_1_scn4m_subm_pdriver_3 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* sizes: [2] +Xbuf_inv1 ++ A Z vdd gnd ++ sram_2_16_1_scn4m_subm_pinv_6 +.ENDS sram_2_16_1_scn4m_subm_pdriver_3 + +.SUBCKT sram_2_16_1_scn4m_subm_pand3_0 + A B C Z vdd gnd * INPUT : A * INPUT : B @@ -1429,13 +1280,13 @@ Mpnand3_nmos3 net2 A gnd gnd n m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1 * GROUND: gnd Xpand3_nand + A B C zb_int vdd gnd -+ sram_pnand3_0 ++ sram_2_16_1_scn4m_subm_pnand3_0 Xpand3_inv + zb_int Z vdd gnd -+ sram_pdriver_2 -.ENDS sram_pand3 ++ sram_2_16_1_scn4m_subm_pdriver_3 +.ENDS sram_2_16_1_scn4m_subm_pand3_0 -.SUBCKT sram_pinv_3 +.SUBCKT sram_2_16_1_scn4m_subm_pinv_10 + A Z vdd gnd * INPUT : A * OUTPUT: Z @@ -1443,66 +1294,153 @@ Xpand3_inv * GROUND: gnd Mpinv_pmos Z A vdd vdd p m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p Mpinv_nmos Z A gnd gnd n m=1 w=0.8u l=0.4u pd=2.40u ps=2.40u as=0.80p ad=0.80p -.ENDS sram_pinv_3 +.ENDS sram_2_16_1_scn4m_subm_pinv_10 -* spice ptx M{0} {1} p m=1 w=8.0u l=0.4u pd=16.80u ps=16.80u as=8.00p ad=8.00p - -* spice ptx M{0} {1} n m=1 w=4.0u l=0.4u pd=8.80u ps=8.80u as=4.00p ad=4.00p - -.SUBCKT sram_pinv_8 -+ A Z vdd gnd -* INPUT : A -* OUTPUT: Z +.SUBCKT sram_2_16_1_scn4m_subm_delay_chain ++ in out vdd gnd +* INPUT : in +* OUTPUT: out * POWER : vdd * GROUND: gnd -Mpinv_pmos Z A vdd vdd p m=1 w=8.0u l=0.4u pd=16.80u ps=16.80u as=8.00p ad=8.00p -Mpinv_nmos Z A gnd gnd n m=1 w=4.0u l=0.4u pd=8.80u ps=8.80u as=4.00p ad=4.00p -.ENDS sram_pinv_8 +* fanouts: [4, 4, 4, 4, 4, 4, 4, 4, 4] +Xdinv0 ++ in dout_1 vdd gnd ++ sram_2_16_1_scn4m_subm_pinv_10 +Xdload_0_0 ++ dout_1 n_0_0 vdd gnd ++ sram_2_16_1_scn4m_subm_pinv_10 +Xdload_0_1 ++ dout_1 n_0_1 vdd gnd ++ sram_2_16_1_scn4m_subm_pinv_10 +Xdload_0_2 ++ dout_1 n_0_2 vdd gnd ++ sram_2_16_1_scn4m_subm_pinv_10 +Xdload_0_3 ++ dout_1 n_0_3 vdd gnd ++ sram_2_16_1_scn4m_subm_pinv_10 +Xdinv1 ++ dout_1 dout_2 vdd gnd ++ sram_2_16_1_scn4m_subm_pinv_10 +Xdload_1_0 ++ dout_2 n_1_0 vdd gnd ++ sram_2_16_1_scn4m_subm_pinv_10 +Xdload_1_1 ++ dout_2 n_1_1 vdd gnd ++ sram_2_16_1_scn4m_subm_pinv_10 +Xdload_1_2 ++ dout_2 n_1_2 vdd gnd ++ sram_2_16_1_scn4m_subm_pinv_10 +Xdload_1_3 ++ dout_2 n_1_3 vdd gnd ++ sram_2_16_1_scn4m_subm_pinv_10 +Xdinv2 ++ dout_2 dout_3 vdd gnd ++ sram_2_16_1_scn4m_subm_pinv_10 +Xdload_2_0 ++ dout_3 n_2_0 vdd gnd ++ sram_2_16_1_scn4m_subm_pinv_10 +Xdload_2_1 ++ dout_3 n_2_1 vdd gnd ++ sram_2_16_1_scn4m_subm_pinv_10 +Xdload_2_2 ++ dout_3 n_2_2 vdd gnd ++ sram_2_16_1_scn4m_subm_pinv_10 +Xdload_2_3 ++ dout_3 n_2_3 vdd gnd ++ sram_2_16_1_scn4m_subm_pinv_10 +Xdinv3 ++ dout_3 dout_4 vdd gnd ++ sram_2_16_1_scn4m_subm_pinv_10 +Xdload_3_0 ++ dout_4 n_3_0 vdd gnd ++ sram_2_16_1_scn4m_subm_pinv_10 +Xdload_3_1 ++ dout_4 n_3_1 vdd gnd ++ sram_2_16_1_scn4m_subm_pinv_10 +Xdload_3_2 ++ dout_4 n_3_2 vdd gnd ++ sram_2_16_1_scn4m_subm_pinv_10 +Xdload_3_3 ++ dout_4 n_3_3 vdd gnd ++ sram_2_16_1_scn4m_subm_pinv_10 +Xdinv4 ++ dout_4 dout_5 vdd gnd ++ sram_2_16_1_scn4m_subm_pinv_10 +Xdload_4_0 ++ dout_5 n_4_0 vdd gnd ++ sram_2_16_1_scn4m_subm_pinv_10 +Xdload_4_1 ++ dout_5 n_4_1 vdd gnd ++ sram_2_16_1_scn4m_subm_pinv_10 +Xdload_4_2 ++ dout_5 n_4_2 vdd gnd ++ sram_2_16_1_scn4m_subm_pinv_10 +Xdload_4_3 ++ dout_5 n_4_3 vdd gnd ++ sram_2_16_1_scn4m_subm_pinv_10 +Xdinv5 ++ dout_5 dout_6 vdd gnd ++ sram_2_16_1_scn4m_subm_pinv_10 +Xdload_5_0 ++ dout_6 n_5_0 vdd gnd ++ sram_2_16_1_scn4m_subm_pinv_10 +Xdload_5_1 ++ dout_6 n_5_1 vdd gnd ++ sram_2_16_1_scn4m_subm_pinv_10 +Xdload_5_2 ++ dout_6 n_5_2 vdd gnd ++ sram_2_16_1_scn4m_subm_pinv_10 +Xdload_5_3 ++ dout_6 n_5_3 vdd gnd ++ sram_2_16_1_scn4m_subm_pinv_10 +Xdinv6 ++ dout_6 dout_7 vdd gnd ++ sram_2_16_1_scn4m_subm_pinv_10 +Xdload_6_0 ++ dout_7 n_6_0 vdd gnd ++ sram_2_16_1_scn4m_subm_pinv_10 +Xdload_6_1 ++ dout_7 n_6_1 vdd gnd ++ sram_2_16_1_scn4m_subm_pinv_10 +Xdload_6_2 ++ dout_7 n_6_2 vdd gnd ++ sram_2_16_1_scn4m_subm_pinv_10 +Xdload_6_3 ++ dout_7 n_6_3 vdd gnd ++ sram_2_16_1_scn4m_subm_pinv_10 +Xdinv7 ++ dout_7 dout_8 vdd gnd ++ sram_2_16_1_scn4m_subm_pinv_10 +Xdload_7_0 ++ dout_8 n_7_0 vdd gnd ++ sram_2_16_1_scn4m_subm_pinv_10 +Xdload_7_1 ++ dout_8 n_7_1 vdd gnd ++ sram_2_16_1_scn4m_subm_pinv_10 +Xdload_7_2 ++ dout_8 n_7_2 vdd gnd ++ sram_2_16_1_scn4m_subm_pinv_10 +Xdload_7_3 ++ dout_8 n_7_3 vdd gnd ++ sram_2_16_1_scn4m_subm_pinv_10 +Xdinv8 ++ dout_8 out vdd gnd ++ sram_2_16_1_scn4m_subm_pinv_10 +Xdload_8_0 ++ out n_8_0 vdd gnd ++ sram_2_16_1_scn4m_subm_pinv_10 +Xdload_8_1 ++ out n_8_1 vdd gnd ++ sram_2_16_1_scn4m_subm_pinv_10 +Xdload_8_2 ++ out n_8_2 vdd gnd ++ sram_2_16_1_scn4m_subm_pinv_10 +Xdload_8_3 ++ out n_8_3 vdd gnd ++ sram_2_16_1_scn4m_subm_pinv_10 +.ENDS sram_2_16_1_scn4m_subm_delay_chain -.SUBCKT sram_pdriver_1 -+ A Z vdd gnd -* INPUT : A -* OUTPUT: Z -* POWER : vdd -* GROUND: gnd -* sizes: [1, 5] -Xbuf_inv1 -+ A Zb1_int vdd gnd -+ sram_pinv_5 -Xbuf_inv2 -+ Zb1_int Z vdd gnd -+ sram_pinv_8 -.ENDS sram_pdriver_1 - -.SUBCKT sram_pdriver_3 -+ A Z vdd gnd -* INPUT : A -* OUTPUT: Z -* POWER : vdd -* GROUND: gnd -* sizes: [1] -Xbuf_inv1 -+ A Z vdd gnd -+ sram_pinv_5 -.ENDS sram_pdriver_3 - -.SUBCKT sram_pand3_0 -+ A B C Z vdd gnd -* INPUT : A -* INPUT : B -* INPUT : C -* OUTPUT: Z -* POWER : vdd -* GROUND: gnd -Xpand3_nand -+ A B C zb_int vdd gnd -+ sram_pnand3_0 -Xpand3_inv -+ zb_int Z vdd gnd -+ sram_pdriver_3 -.ENDS sram_pand3_0 - -.SUBCKT sram_pnand2_1 +.SUBCKT sram_2_16_1_scn4m_subm_pnand2_0 + A B Z vdd gnd * INPUT : A * INPUT : B @@ -1513,23 +1451,131 @@ Mpnand2_pmos1 vdd A Z vdd p m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60 Mpnand2_pmos2 Z B vdd vdd p m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p Mpnand2_nmos1 Z B net1 gnd n m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p Mpnand2_nmos2 net1 A gnd gnd n m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p -.ENDS sram_pnand2_1 +.ENDS sram_2_16_1_scn4m_subm_pnand2_0 -* spice ptx M{0} {1} p m=3 w=6.9u l=0.4u pd=14.60u ps=14.60u as=6.90p ad=6.90p +* spice ptx M{0} {1} p m=3 w=6.4u l=0.4u pd=13.60u ps=13.60u as=6.40p ad=6.40p -* spice ptx M{0} {1} n m=3 w=3.5u l=0.4u pd=7.80u ps=7.80u as=3.50p ad=3.50p +* spice ptx M{0} {1} n m=3 w=3.2u l=0.4u pd=7.20u ps=7.20u as=3.20p ad=3.20p -.SUBCKT sram_pinv_7 +.SUBCKT sram_2_16_1_scn4m_subm_pinv_2 + A Z vdd gnd * INPUT : A * OUTPUT: Z * POWER : vdd * GROUND: gnd -Mpinv_pmos Z A vdd vdd p m=3 w=6.9u l=0.4u pd=14.60u ps=14.60u as=6.90p ad=6.90p -Mpinv_nmos Z A gnd gnd n m=3 w=3.5u l=0.4u pd=7.80u ps=7.80u as=3.50p ad=3.50p -.ENDS sram_pinv_7 +Mpinv_pmos Z A vdd vdd p m=3 w=6.4u l=0.4u pd=13.60u ps=13.60u as=6.40p ad=6.40p +Mpinv_nmos Z A gnd gnd n m=3 w=3.2u l=0.4u pd=7.20u ps=7.20u as=3.20p ad=3.20p +.ENDS sram_2_16_1_scn4m_subm_pinv_2 -.SUBCKT sram_pinv_6 +.SUBCKT sram_2_16_1_scn4m_subm_pdriver ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* sizes: [12] +Xbuf_inv1 ++ A Z vdd gnd ++ sram_2_16_1_scn4m_subm_pinv_2 +.ENDS sram_2_16_1_scn4m_subm_pdriver + +.SUBCKT sram_2_16_1_scn4m_subm_pand2 ++ A B Z vdd gnd +* INPUT : A +* INPUT : B +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +Xpand2_nand ++ A B zb_int vdd gnd ++ sram_2_16_1_scn4m_subm_pnand2_0 +Xpand2_inv ++ zb_int Z vdd gnd ++ sram_2_16_1_scn4m_subm_pdriver +.ENDS sram_2_16_1_scn4m_subm_pand2 + +.SUBCKT sram_2_16_1_scn4m_subm_pdriver_4 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* sizes: [1, 1] +Xbuf_inv1 ++ A Zb1_int vdd gnd ++ sram_2_16_1_scn4m_subm_pinv_5 +Xbuf_inv2 ++ Zb1_int Z vdd gnd ++ sram_2_16_1_scn4m_subm_pinv_5 +.ENDS sram_2_16_1_scn4m_subm_pdriver_4 + +.SUBCKT sram_2_16_1_scn4m_subm_pinv_3 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +Mpinv_pmos Z A vdd vdd p m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p +Mpinv_nmos Z A gnd gnd n m=1 w=0.8u l=0.4u pd=2.40u ps=2.40u as=0.80p ad=0.80p +.ENDS sram_2_16_1_scn4m_subm_pinv_3 + +* spice ptx M{0} {1} n m=2 w=4.0u l=0.4u pd=8.80u ps=8.80u as=4.00p ad=4.00p + +* spice ptx M{0} {1} p m=2 w=8.0u l=0.4u pd=16.80u ps=16.80u as=8.00p ad=8.00p + +.SUBCKT sram_2_16_1_scn4m_subm_pinv_9 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +Mpinv_pmos Z A vdd vdd p m=2 w=8.0u l=0.4u pd=16.80u ps=16.80u as=8.00p ad=8.00p +Mpinv_nmos Z A gnd gnd n m=2 w=4.0u l=0.4u pd=8.80u ps=8.80u as=4.00p ad=4.00p +.ENDS sram_2_16_1_scn4m_subm_pinv_9 + +.SUBCKT sram_2_16_1_scn4m_subm_pdriver_2 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* sizes: [10] +Xbuf_inv1 ++ A Z vdd gnd ++ sram_2_16_1_scn4m_subm_pinv_9 +.ENDS sram_2_16_1_scn4m_subm_pdriver_2 + +.SUBCKT sram_2_16_1_scn4m_subm_pand3 ++ A B C Z vdd gnd +* INPUT : A +* INPUT : B +* INPUT : C +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +Xpand3_nand ++ A B C zb_int vdd gnd ++ sram_2_16_1_scn4m_subm_pnand3_0 +Xpand3_inv ++ zb_int Z vdd gnd ++ sram_2_16_1_scn4m_subm_pdriver_2 +.ENDS sram_2_16_1_scn4m_subm_pand3 + +.SUBCKT sram_2_16_1_scn4m_subm_pinv_0 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +Mpinv_pmos Z A vdd vdd p m=1 w=3.2u l=0.4u pd=7.20u ps=7.20u as=3.20p ad=3.20p +Mpinv_nmos Z A gnd gnd n m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p +.ENDS sram_2_16_1_scn4m_subm_pinv_0 + +* spice ptx M{0} {1} n m=1 w=3.2u l=0.4u pd=7.20u ps=7.20u as=3.20p ad=3.20p + +* spice ptx M{0} {1} p m=1 w=6.4u l=0.4u pd=13.60u ps=13.60u as=6.40p ad=6.40p + +.SUBCKT sram_2_16_1_scn4m_subm_pinv_1 + A Z vdd gnd * INPUT : A * OUTPUT: Z @@ -1537,30 +1583,97 @@ Mpinv_nmos Z A gnd gnd n m=3 w=3.5u l=0.4u pd=7.80u ps=7.80u as=3.50p ad=3.50p * GROUND: gnd Mpinv_pmos Z A vdd vdd p m=1 w=6.4u l=0.4u pd=13.60u ps=13.60u as=6.40p ad=6.40p Mpinv_nmos Z A gnd gnd n m=1 w=3.2u l=0.4u pd=7.20u ps=7.20u as=3.20p ad=3.20p -.ENDS sram_pinv_6 +.ENDS sram_2_16_1_scn4m_subm_pinv_1 -.SUBCKT sram_pdriver_0 +.SUBCKT sram_2_16_1_scn4m_subm_dff_buf_0 ++ D Q Qb clk vdd gnd +* INPUT : D +* OUTPUT: Q +* OUTPUT: Qb +* INPUT : clk +* POWER : vdd +* GROUND: gnd +* inv1: 2 inv2: 4 +Xdff_buf_dff ++ D qint clk vdd gnd ++ dff +Xdff_buf_inv1 ++ qint Qb vdd gnd ++ sram_2_16_1_scn4m_subm_pinv_0 +Xdff_buf_inv2 ++ Qb Q vdd gnd ++ sram_2_16_1_scn4m_subm_pinv_1 +.ENDS sram_2_16_1_scn4m_subm_dff_buf_0 + +.SUBCKT sram_2_16_1_scn4m_subm_dff_buf_array ++ din_0 din_1 dout_0 dout_bar_0 dout_1 dout_bar_1 clk vdd gnd +* INPUT : din_0 +* INPUT : din_1 +* OUTPUT: dout_0 +* OUTPUT: dout_bar_0 +* OUTPUT: dout_1 +* OUTPUT: dout_bar_1 +* INPUT : clk +* POWER : vdd +* GROUND: gnd +* inv1: 2 inv2: 4 +Xdff_r0_c0 ++ din_0 dout_0 dout_bar_0 clk vdd gnd ++ sram_2_16_1_scn4m_subm_dff_buf_0 +Xdff_r1_c0 ++ din_1 dout_1 dout_bar_1 clk vdd gnd ++ sram_2_16_1_scn4m_subm_dff_buf_0 +.ENDS sram_2_16_1_scn4m_subm_dff_buf_array + +* spice ptx M{0} {1} n m=3 w=4.0u l=0.4u pd=8.80u ps=8.80u as=4.00p ad=4.00p + +* spice ptx M{0} {1} p m=3 w=8.0u l=0.4u pd=16.80u ps=16.80u as=8.00p ad=8.00p + +.SUBCKT sram_2_16_1_scn4m_subm_pinv_8 + A Z vdd gnd * INPUT : A * OUTPUT: Z * POWER : vdd * GROUND: gnd -* sizes: [1, 1, 4, 13] +Mpinv_pmos Z A vdd vdd p m=3 w=8.0u l=0.4u pd=16.80u ps=16.80u as=8.00p ad=8.00p +Mpinv_nmos Z A gnd gnd n m=3 w=4.0u l=0.4u pd=8.80u ps=8.80u as=4.00p ad=4.00p +.ENDS sram_2_16_1_scn4m_subm_pinv_8 + +.SUBCKT sram_2_16_1_scn4m_subm_pdriver_0 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* sizes: [1, 2, 5, 15] Xbuf_inv1 + A Zb1_int vdd gnd -+ sram_pinv_5 ++ sram_2_16_1_scn4m_subm_pinv_5 Xbuf_inv2 + Zb1_int Zb2_int vdd gnd -+ sram_pinv_5 ++ sram_2_16_1_scn4m_subm_pinv_6 Xbuf_inv3 + Zb2_int Zb3_int vdd gnd -+ sram_pinv_6 ++ sram_2_16_1_scn4m_subm_pinv_7 Xbuf_inv4 + Zb3_int Z vdd gnd -+ sram_pinv_7 -.ENDS sram_pdriver_0 ++ sram_2_16_1_scn4m_subm_pinv_8 +.ENDS sram_2_16_1_scn4m_subm_pdriver_0 -.SUBCKT sram_control_logic_rw +.SUBCKT sram_2_16_1_scn4m_subm_pnand2_1 ++ A B Z vdd gnd +* INPUT : A +* INPUT : B +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +Mpnand2_pmos1 vdd A Z vdd p m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p +Mpnand2_pmos2 Z B vdd vdd p m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p +Mpnand2_nmos1 Z B net1 gnd n m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p +Mpnand2_nmos2 net1 A gnd gnd n m=1 w=1.6u l=0.4u pd=4.00u ps=4.00u as=1.60p ad=1.60p +.ENDS sram_2_16_1_scn4m_subm_pnand2_1 + +.SUBCKT sram_2_16_1_scn4m_subm_control_logic_rw + csb web clk rbl_bl s_en w_en p_en_bar wl_en clk_buf vdd gnd * INPUT : csb * INPUT : web @@ -1573,62 +1686,50 @@ Xbuf_inv4 * OUTPUT: clk_buf * POWER : vdd * GROUND: gnd -* word_size 1 +* word_size 2 Xctrl_dffs + csb web cs_bar cs we_bar we clk_buf vdd gnd -+ sram_dff_buf_array ++ sram_2_16_1_scn4m_subm_dff_buf_array Xclkbuf + clk clk_buf vdd gnd -+ sram_pdriver_0 ++ sram_2_16_1_scn4m_subm_pdriver_0 Xinv_clk_bar + clk_buf clk_bar vdd gnd -+ sram_pinv_3 ++ sram_2_16_1_scn4m_subm_pinv_3 Xand2_gated_clk_bar + clk_bar cs gated_clk_bar vdd gnd -+ sram_pand2 ++ sram_2_16_1_scn4m_subm_pand2 Xand2_gated_clk_buf + clk_buf cs gated_clk_buf vdd gnd -+ sram_pand2 ++ sram_2_16_1_scn4m_subm_pand2 Xbuf_wl_en + gated_clk_bar wl_en vdd gnd -+ sram_pdriver_1 ++ sram_2_16_1_scn4m_subm_pdriver_1 Xrbl_bl_delay_inv + rbl_bl_delay rbl_bl_delay_bar vdd gnd -+ sram_pinv_3 ++ sram_2_16_1_scn4m_subm_pinv_3 Xw_en_and + we rbl_bl_delay_bar gated_clk_bar w_en vdd gnd -+ sram_pand3 ++ sram_2_16_1_scn4m_subm_pand3 Xbuf_s_en_and + rbl_bl_delay gated_clk_bar we_bar s_en vdd gnd -+ sram_pand3_0 ++ sram_2_16_1_scn4m_subm_pand3_0 Xdelay_chain + rbl_bl rbl_bl_delay vdd gnd -+ sram_delay_chain ++ sram_2_16_1_scn4m_subm_delay_chain Xnand_p_en_bar + gated_clk_buf rbl_bl_delay p_en_bar_unbuf vdd gnd -+ sram_pnand2_1 ++ sram_2_16_1_scn4m_subm_pnand2_1 Xbuf_p_en_bar + p_en_bar_unbuf p_en_bar vdd gnd -+ sram_pdriver_4 -.ENDS sram_control_logic_rw - -.SUBCKT sram_data_dff -+ din_0 dout_0 clk vdd gnd -* INPUT : din_0 -* OUTPUT: dout_0 -* INPUT : clk -* POWER : vdd -* GROUND: gnd -* rows: 1 cols: 1 -Xdff_r0_c0 -+ din_0 dout_0 clk vdd gnd -+ dff -.ENDS sram_data_dff ++ sram_2_16_1_scn4m_subm_pdriver_4 +.ENDS sram_2_16_1_scn4m_subm_control_logic_rw .SUBCKT sram_2_16_1_scn4m_subm -+ din0[0] addr0[0] addr0[1] addr0[2] addr0[3] csb0 web0 clk0 dout0[0] -+ vdd gnd ++ din0[0] din0[1] addr0[0] addr0[1] addr0[2] addr0[3] csb0 web0 clk0 ++ dout0[0] dout0[1] vdd gnd * INPUT : din0[0] +* INPUT : din0[1] * INPUT : addr0[0] * INPUT : addr0[1] * INPUT : addr0[2] @@ -1637,20 +1738,21 @@ Xdff_r0_c0 * INPUT : web0 * INPUT : clk0 * OUTPUT: dout0[0] +* OUTPUT: dout0[1] * POWER : vdd * GROUND: gnd Xbank0 -+ dout0[0] rbl_bl0 bank_din0_0 a0_0 a0_1 a0_2 a0_3 s_en0 p_en_bar0 w_en0 -+ wl_en0 vdd gnd -+ sram_bank ++ dout0[0] dout0[1] rbl_bl0 bank_din0_0 bank_din0_1 a0_0 a0_1 a0_2 a0_3 ++ s_en0 p_en_bar0 w_en0 wl_en0 vdd gnd ++ sram_2_16_1_scn4m_subm_bank Xcontrol0 + csb0 web0 clk0 rbl_bl0 s_en0 w_en0 p_en_bar0 wl_en0 clk_buf0 vdd gnd -+ sram_control_logic_rw ++ sram_2_16_1_scn4m_subm_control_logic_rw Xrow_address0 + addr0[0] addr0[1] addr0[2] addr0[3] a0_0 a0_1 a0_2 a0_3 clk_buf0 vdd + gnd -+ sram_row_addr_dff ++ sram_2_16_1_scn4m_subm_row_addr_dff Xdata_dff0 -+ din0[0] bank_din0_0 clk_buf0 vdd gnd -+ sram_data_dff ++ din0[0] din0[1] bank_din0_0 bank_din0_1 clk_buf0 vdd gnd ++ sram_2_16_1_scn4m_subm_data_dff .ENDS sram_2_16_1_scn4m_subm From b9123571f4713ec7e28016fc709d59128fa4e4f9 Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Tue, 16 May 2023 15:06:49 -0700 Subject: [PATCH 090/130] Fix functional script spice file name and unit test --- compiler/characterizer/functional.py | 15 +++++--- compiler/tests/30_memfunc_test.py | 52 +++++++++++++++------------- 2 files changed, 38 insertions(+), 29 deletions(-) diff --git a/compiler/characterizer/functional.py b/compiler/characterizer/functional.py index 3fe17888..846c6d94 100644 --- a/compiler/characterizer/functional.py +++ b/compiler/characterizer/functional.py @@ -8,6 +8,8 @@ import math import random import collections +from os import path +import shutil from numpy import binary_repr from openram import debug from openram import OPTS @@ -33,6 +35,9 @@ class functional(simulation): if not spfile: # self.sp_file is assigned in base class sram.sp_write(self.sp_file, trim=OPTS.trim_netlist) + # Copy sp file to temp dir + self.temp_spice = path.join(OPTS.openram_temp, "sram.sp") + shutil.copy(self.sp_file, self.temp_spice) if not corner: corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0]) @@ -386,16 +391,16 @@ class functional(simulation): def write_functional_stimulus(self): """ Writes SPICE stimulus. """ self.stim_sp = "functional_stim.sp" - temp_stim = "{0}/{1}".format(self.output_path, self.stim_sp) + temp_stim = path.join(self.output_path, self.stim_sp) self.sf = open(temp_stim, "w") self.sf.write("* Functional test stimulus file for {0}ns period\n\n".format(self.period)) self.meas_sp = "functional_meas.sp" - temp_meas = "{0}/{1}".format(self.output_path, self.meas_sp) + temp_meas = path.join(self.output_path, self.meas_sp) self.mf = open(temp_meas, "w") self.stim = stimuli(self.sf, self.mf, self.corner) # Write include statements - self.stim.write_include(self.sp_file) + self.stim.write_include(self.temp_spice) # Write Vdd/Gnd statements self.sf.write("\n* Global Power Supplies\n") @@ -502,9 +507,11 @@ class functional(simulation): # dout=signal_name, # t_initial=t_initial, # t_final=t_final) - + + self.sf.write(".include {0}\n".format(temp_meas)) self.stim.write_control(self.cycle_times[-1] + self.period) self.sf.close() + self.mf.close() # FIXME: Similar function to delay.py, refactor this def get_bit_name(self): diff --git a/compiler/tests/30_memfunc_test.py b/compiler/tests/30_memfunc_test.py index 5a74d774..30283854 100755 --- a/compiler/tests/30_memfunc_test.py +++ b/compiler/tests/30_memfunc_test.py @@ -6,27 +6,33 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -from asyncio import subprocess +import sys, os, re +import shutil +import getpass import unittest from testutils import * -import sys, os, re, shutil -sys.path.append(os.getenv("OPENRAM_HOME")) -import globals -from globals import OPTS -import debug -import getpass + +import openram +from openram import debug +from openram import OPTS -class openram_front_end_test(openram_test): +class sram_func_test(openram_test): def runTest(self): - OPENRAM_HOME = os.path.abspath(os.environ.get("OPENRAM_HOME")) - config_file = "{}/tests/configs/config_mem_char_func".format(os.getenv("OPENRAM_HOME")) - globals.init_openram(config_file) + global OPTS + out_file = "sram_2_16_1_{0}".format(OPTS.tech_name) + out_path = "{0}/testsram_{1}_{2}_{3}".format(OPTS.openram_temp, OPTS.tech_name, getpass.getuser(), os.getpid()) + OPTS.output_name = out_file + OPTS.output_path = out_path - debug.info(1, "Testing commandline functional simulator script memfunc.py with 2-bit, 16 word SRAM.") - out_file = "testsram" - out_path = "/tmp/testsram_{0}_{1}_{2}".format(OPTS.tech_name, getpass.getuser(), os.getpid()) + OPENRAM_HOME = os.path.abspath(os.environ.get("OPENRAM_HOME")) + config_file = "{}/tests/configs/config_mem_char_func".format(OPENRAM_HOME) + + openram.init_openram(config_file, is_unit_test=False) + sp_file = "{0}/tests/sp_files/{1}.sp".format(OPENRAM_HOME, OPTS.output_name) + + debug.info(1, "Testing commandline functional simulator script sram_char.py with 2-bit, 16 word SRAM.") # make sure we start without the files existing if os.path.exists(out_path): @@ -39,11 +45,6 @@ class openram_front_end_test(openram_test): if e.errno == 17: # errno.EEXIST os.chmod(out_path, 0o0750) - # copy the 2x16 sram spice file into out_path because memfunc.py expects it there - sp_src_file = "{0}/tests/golden/sram_2_16_1_{1}.sp".format(OPENRAM_HOME, OPTS.tech_name) - sp_dst_file = out_path + "/" + OPTS.output_name + ".sp" - shutil.copy(sp_src_file, sp_dst_file) - # specify the same verbosity for the system call options = "" for i in range(OPTS.verbose_level): @@ -54,22 +55,23 @@ class openram_front_end_test(openram_test): if OPTS.tech_name: options += " -t {}".format(OPTS.tech_name) - + options += " -j 2" # Always perform code coverage if OPTS.coverage == 0: debug.warning("Failed to find coverage installation. This can be installed with pip3 install coverage") - exe_name = "{0}/memfunc.py ".format(OPENRAM_HOME) + exe_name = "{0}/../sram_func.py ".format(OPENRAM_HOME) else: - exe_name = "{0}{1}/memfunc.py ".format(OPTS.coverage_exe, OPENRAM_HOME) + exe_name = "{0}{1}/../sram_func.py ".format(OPTS.coverage_exe, OPENRAM_HOME) config_name = "{0}/tests/configs/config_mem_char_func.py".format(OPENRAM_HOME) period_and_cycles = 10 - cmd = "{0} -n -o {1} -p {2} {3} {4} {5} {5} 2>&1 > {6}/output.log".format(exe_name, + cmd = "{0} -n -o {1} -p {2} {3} {4} {5} {6} {6} 2>&1 > {7}/output.log".format(exe_name, out_file, out_path, options, config_name, + sp_file, period_and_cycles, out_path) debug.info(1, cmd) @@ -88,11 +90,11 @@ class openram_front_end_test(openram_test): shutil.rmtree(out_path, ignore_errors=True) self.assertEqual(os.path.exists(out_path), False) - globals.end_openram() + openram.end_openram() # run the test from the command line if __name__ == "__main__": - (OPTS, args) = globals.parse_args() + (OPTS, args) = openram.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) unittest.main(testRunner=debugTestRunner()) From 217b0981a24ab9411276083722eadbf5b77121c7 Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Tue, 16 May 2023 15:07:31 -0700 Subject: [PATCH 091/130] Use subprocess.run instead of subprocess.call --- compiler/characterizer/stimuli.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/characterizer/stimuli.py b/compiler/characterizer/stimuli.py index c2bf3e39..45997b7e 100644 --- a/compiler/characterizer/stimuli.py +++ b/compiler/characterizer/stimuli.py @@ -412,12 +412,12 @@ class stimuli(): from openram import CONDA_HOME cmd = "source {0}/bin/activate && {1} && conda deactivate".format(CONDA_HOME, cmd) debug.info(2, cmd) - retcode = subprocess.call(cmd, stdout=spice_stdout, stderr=spice_stderr, shell=True) + proc = subprocess.run(cmd, stdout=spice_stdout, stderr=spice_stderr, shell=True) spice_stdout.close() spice_stderr.close() - if (retcode > valid_retcode): + if (proc.returncode > valid_retcode): debug.error("Spice simulation error: " + cmd, -1) else: end_time = datetime.datetime.now() From 5cdecd781b371599d77415e5c3c4478d276bb449 Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Tue, 16 May 2023 15:08:21 -0700 Subject: [PATCH 092/130] Update functional script usage tip --- sram_func.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/sram_func.py b/sram_func.py index 3d9fecca..93222f11 100755 --- a/sram_func.py +++ b/sram_func.py @@ -19,16 +19,16 @@ from globals import * # You don't need the next two lines if you're sure that openram package is installed from common import * -make_openram_pacakage() +make_openram_package() import openram (OPTS, args) = openram.parse_args() # Override the usage -USAGE = "Usage: {} [options] \nUse -h for help.\n".format(__file__) +USAGE = "Usage: {} [options] \nUse -h for help.\n".format(__file__) # Check that we are left with a single configuration file as argument. -if len(args) != 3: +if len(args) != 4: print(USAGE) sys.exit(2) @@ -36,10 +36,9 @@ OPTS.top_process = 'memfunc' # Parse argument config_file = args[0] -cycles = int(args[1]) -period = float(args[2]) -sp_file = args[3] -html_file = args[4] +sp_file = args[1] +cycles = int(args[2]) +period = float(args[3]) # These depend on arguments, so don't load them until now. from openram import debug @@ -60,7 +59,6 @@ s = fake_sram(name=OPTS.output_name, num_spare_rows=OPTS.num_spare_rows, num_spare_cols=OPTS.num_spare_cols) -s.parse_html(html_file) s.generate_pins() s.setup_multiport_constants() From 49efff33845b39e3d96066d6c1f290ebd2e74000 Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Tue, 16 May 2023 16:44:58 -0700 Subject: [PATCH 093/130] Added description for stand-alone characterizer --- docs/source/characterization.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/source/characterization.md b/docs/source/characterization.md index 60adc74a..5fdde81b 100644 --- a/docs/source/characterization.md +++ b/docs/source/characterization.md @@ -46,7 +46,8 @@ Measures the timing/power through SPICE simulation: * Testing Support Modules * Other modules are derivatives of the simulation module used in the unit tests - +## Stand-alone Charaterizer +The stand-alone characterizer is a script ([sram_char.py]()sram_char.py) that can be run without generating an SRAM. ## Characterization Options * Characterization by Configuration File From 6841de4a5035ab8b0832985944e5c0c44e0d1a6c Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Tue, 23 May 2023 10:36:49 -0700 Subject: [PATCH 094/130] reflect the changes to sram.py from dev --- compiler/sram.py | 57 ++++++++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 29 deletions(-) diff --git a/compiler/sram.py b/compiler/sram.py index 7acfb3a6..cf1f0971 100644 --- a/compiler/sram.py +++ b/compiler/sram.py @@ -35,34 +35,23 @@ class sram(): if name is None: name = OPTS.output_name - self.name = name - self.config = sram_config - sram_config.setup_multiport_constants() sram_config.set_local_config(self) - self.sp_name = OPTS.output_path + self.name + ".sp" - self.lvs_name = OPTS.output_path + self.name + ".lvs.sp" - self.pex_name = OPTS.output_path + self.name + ".pex.sp" - self.gds_name = OPTS.output_path + self.name + ".gds" - self.lef_name = OPTS.output_path + self.name + ".lef" - self.v_name = OPTS.output_path + self.name + ".v" - # reset the static duplicate name checker for unit tests # in case we create more than one SRAM from openram.base import design design.name_map=[] - self.create() - - def create(self): debug.info(2, "create sram of size {0} with {1} num of words {2} banks".format(self.word_size, self.num_words, self.num_banks)) start_time = datetime.datetime.now() + self.name = name + from openram.modules.sram_1bank import sram_1bank as sram - self.s = sram(self.name, self.config) + self.s = sram(name, sram_config) self.s.create_netlist() if not OPTS.netlist_only: @@ -118,12 +107,13 @@ class sram(): # Save the spice file start_time = datetime.datetime.now() - debug.print_raw("SP: Writing to {0}".format(self.sp_name)) - self.sp_write(self.sp_name) + spname = OPTS.output_path + self.s.name + ".sp" + debug.print_raw("SP: Writing to {0}".format(spname)) + self.sp_write(spname) # Save a functional simulation file with default period functional(self.s, - os.path.basename(self.sp_name), + os.path.basename(spname), cycles=200, output_path=OPTS.output_path) print_time("Spice writing", datetime.datetime.now(), start_time) @@ -131,7 +121,7 @@ class sram(): # Save stimulus and measurement file start_time = datetime.datetime.now() debug.print_raw("DELAY: Writing stimulus...") - d = delay(self.s, self.get_sp_name(), ("TT", 5, 25), output_path=OPTS.output_path) + d = delay(self.s, spname, ("TT", 5, 25), output_path=OPTS.output_path) if (self.s.num_spare_rows == 0): probe_address = "1" * self.s.addr_size else: @@ -150,11 +140,12 @@ class sram(): if not OPTS.netlist_only: # Write the layout start_time = datetime.datetime.now() - debug.print_raw("GDS: Writing to {0}".format(self.gds_name)) - self.gds_write(self.gds_name) + gdsname = OPTS.output_path + self.s.name + ".gds" + debug.print_raw("GDS: Writing to {0}".format(gdsname)) + self.gds_write(gdsname) if OPTS.check_lvsdrc: verify.write_drc_script(cell_name=self.s.name, - gds_name=os.path.basename(self.gds_name), + gds_name=os.path.basename(gdsname), extract=True, final_verification=True, output_path=OPTS.output_path) @@ -162,18 +153,20 @@ class sram(): # Create a LEF physical model start_time = datetime.datetime.now() - debug.print_raw("LEF: Writing to {0}".format(self.lef_name)) - self.lef_write(self.lef_name) + lefname = OPTS.output_path + self.s.name + ".lef" + debug.print_raw("LEF: Writing to {0}".format(lefname)) + self.lef_write(lefname) print_time("LEF", datetime.datetime.now(), start_time) # Save the LVS file start_time = datetime.datetime.now() - debug.print_raw("LVS: Writing to {0}".format(self.lvs_name)) - self.sp_write(self.lvs_name, lvs=True) + lvsname = OPTS.output_path + self.s.name + ".lvs.sp" + debug.print_raw("LVS: Writing to {0}".format(lvsname)) + self.sp_write(lvsname, lvs=True) if not OPTS.netlist_only and OPTS.check_lvsdrc: verify.write_lvs_script(cell_name=self.s.name, - gds_name=os.path.basename(self.gds_name), - sp_name=os.path.basename(self.lvs_name), + gds_name=os.path.basename(gdsname), + sp_name=os.path.basename(lvsname), final_verification=True, output_path=OPTS.output_path) print_time("LVS writing", datetime.datetime.now(), start_time) @@ -182,14 +175,20 @@ class sram(): if OPTS.use_pex: start_time = datetime.datetime.now() # Output the extracted design if requested - verify.run_pex(self.s.name, self.gds_name, self.sp_name, output=self.pex_name) + pexname = OPTS.output_path + self.s.name + ".pex.sp" + spname = OPTS.output_path + self.s.name + ".sp" + verify.run_pex(self.s.name, gdsname, spname, output=pexname) + sp_file = pexname print_time("Extraction", datetime.datetime.now(), start_time) + else: + # Use generated spice file for characterization + sp_file = spname # Characterize the design start_time = datetime.datetime.now() from openram.characterizer import lib debug.print_raw("LIB: Characterizing... ") - lib(out_dir=OPTS.output_path, sram=self.s, sp_file=self.get_sp_name()) + lib(out_dir=OPTS.output_path, sram=self.s, sp_file=sp_file) print_time("Characterization", datetime.datetime.now(), start_time) # Write the config file From e13cc76ac35bc4d674265b4b7f314db2057e008e Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Tue, 23 May 2023 10:58:17 -0700 Subject: [PATCH 095/130] Fix Python 3.11 random change --- compiler/characterizer/functional.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/characterizer/functional.py b/compiler/characterizer/functional.py index 846c6d94..5730b644 100644 --- a/compiler/characterizer/functional.py +++ b/compiler/characterizer/functional.py @@ -374,7 +374,7 @@ class functional(simulation): def gen_addr(self): """ Generates a random address value to write to. """ if self.valid_addresses: - random_value = random.sample(self.valid_addresses, 1)[0] + random_value = random.sample(list(self.valid_addresses), 1)[0] else: random_value = random.randint(0, self.max_address) addr_bits = binary_repr(random_value, self.bank_addr_size) From 15c5e57d77b2e20a5f2863b0fb59bc6ec218c4f6 Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Tue, 23 May 2023 10:58:43 -0700 Subject: [PATCH 096/130] functional should use full sp file path --- compiler/sram.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/sram.py b/compiler/sram.py index cf1f0971..cc269d8f 100644 --- a/compiler/sram.py +++ b/compiler/sram.py @@ -113,7 +113,7 @@ class sram(): # Save a functional simulation file with default period functional(self.s, - os.path.basename(spname), + spname, cycles=200, output_path=OPTS.output_path) print_time("Spice writing", datetime.datetime.now(), start_time) From f16a40af02c3a5e1f18856ea1e8a33ff2b1f5d4e Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Tue, 23 May 2023 13:46:05 -0700 Subject: [PATCH 097/130] Renamed char and func unit tests --- .../tests/{30_memchar_test.py => 30_openram_sram_char_test.py} | 0 .../tests/{30_memfunc_test.py => 30_openram_sram_func_test.py} | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename compiler/tests/{30_memchar_test.py => 30_openram_sram_char_test.py} (100%) rename compiler/tests/{30_memfunc_test.py => 30_openram_sram_func_test.py} (99%) diff --git a/compiler/tests/30_memchar_test.py b/compiler/tests/30_openram_sram_char_test.py similarity index 100% rename from compiler/tests/30_memchar_test.py rename to compiler/tests/30_openram_sram_char_test.py diff --git a/compiler/tests/30_memfunc_test.py b/compiler/tests/30_openram_sram_func_test.py similarity index 99% rename from compiler/tests/30_memfunc_test.py rename to compiler/tests/30_openram_sram_func_test.py index 30283854..3a5d6283 100755 --- a/compiler/tests/30_memfunc_test.py +++ b/compiler/tests/30_openram_sram_func_test.py @@ -55,7 +55,7 @@ class sram_func_test(openram_test): if OPTS.tech_name: options += " -t {}".format(OPTS.tech_name) - + options += " -j 2" # Always perform code coverage From 054b7cd47da28a5bf67cd954be938aac1313a7ec Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Tue, 23 May 2023 13:47:02 -0700 Subject: [PATCH 098/130] Fixed code format --- compiler/characterizer/functional.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/characterizer/functional.py b/compiler/characterizer/functional.py index 5730b644..c5d5d865 100644 --- a/compiler/characterizer/functional.py +++ b/compiler/characterizer/functional.py @@ -506,8 +506,8 @@ class functional(simulation): # self.stim.gen_meas_value(meas_name=measure_name, # dout=signal_name, # t_initial=t_initial, - # t_final=t_final) - + # t_final=t_final + self.sf.write(".include {0}\n".format(temp_meas)) self.stim.write_control(self.cycle_times[-1] + self.period) self.sf.close() From abd18ab832dac146589d6403d3e5be6ec960ee87 Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Tue, 23 May 2023 15:08:06 -0700 Subject: [PATCH 099/130] Moved freepdk sense amp dout pin away from gnd pin --- technology/freepdk45/gds_lib/sense_amp.gds | Bin 17514 -> 17510 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/technology/freepdk45/gds_lib/sense_amp.gds b/technology/freepdk45/gds_lib/sense_amp.gds index 9c59cf9ec7e48b526b3e3452580cc46b05c6c393..51513e1384046b5a0c6d7ea4750655c6c1e6bd82 100644 GIT binary patch delta 358 zcmaFW!T79$QImm@@M#IEyHghP&u`01L0M-3wU|{0|s;foNFmYCf%^m78>_nJ1`IufD#JD$5 zV}Py%8w+wR$QqzH&^R~!2aIeCmOysq)hB0UI9^P=}5H^Z)<V25Jn*`5lXFiRCiXDL^lSodTs{;w+ap&vH7$2mnnnYK;H@ From 071670bef08f2b2dbc1a0e81ce07d18bf1ac8c3a Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Wed, 5 Jul 2023 14:29:51 -0700 Subject: [PATCH 100/130] Removed import global --- sram_char.py | 1 - sram_func.py | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/sram_char.py b/sram_char.py index a6968bf8..52a085cb 100755 --- a/sram_char.py +++ b/sram_char.py @@ -15,7 +15,6 @@ an analytical model or spice simulation is used for characterization. import sys import datetime -from globals import * # You don't need the next two lines if you're sure that openram package is installed from common import * diff --git a/sram_func.py b/sram_func.py index 93222f11..5b7b1569 100755 --- a/sram_func.py +++ b/sram_func.py @@ -15,7 +15,6 @@ number of cycles and period to be simulated. import sys import datetime -from globals import * # You don't need the next two lines if you're sure that openram package is installed from common import * @@ -49,7 +48,7 @@ openram.init_openram(config_file=config_file, is_unit_test=False) openram.print_banner() # Configure the SRAM organization (duplicated from openram.py) -from characterizer.fake_sram import fake_sram +from openram.characterizer.fake_sram import fake_sram s = fake_sram(name=OPTS.output_name, word_size=OPTS.word_size, num_words=OPTS.num_words, From 7220e0a48374a15fe0ec0630d4e7dddc9a332b53 Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Fri, 7 Jul 2023 12:39:19 -0700 Subject: [PATCH 101/130] sim_exe will be found everytime with func and char --- compiler/characterizer/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/characterizer/__init__.py b/compiler/characterizer/__init__.py index b8cb8f2d..9913173e 100644 --- a/compiler/characterizer/__init__.py +++ b/compiler/characterizer/__init__.py @@ -24,7 +24,7 @@ from .fake_sram import * debug.info(1, "Initializing characterizer...") OPTS.spice_exe = "" -if not OPTS.analytical_delay: +if not OPTS.analytical_delay or OPTS.top_process in ["memfunc", "memchar"]: if OPTS.spice_name: # Capitalize Xyce if OPTS.spice_name == "xyce": From 0ad619f04c104238ec3d25f255cfedec2ba2324d Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Mon, 10 Jul 2023 12:32:58 -0700 Subject: [PATCH 102/130] Added bl, sen and cell format options --- compiler/characterizer/delay.py | 43 +++++++++++++-------------------- compiler/options.py | 5 ++++ 2 files changed, 22 insertions(+), 26 deletions(-) diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index 78e57f88..c1259cc0 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -230,8 +230,7 @@ class delay(simulation): bit_col = self.get_data_bit_column_number(probe_address, probe_data) bit_row = self.get_address_row_number(probe_address) if OPTS.top_process == "memchar": - cell_name = self.cell_format.format(self.sram.name, bit_row, bit_col, OPTS.hier_seperator) - #cell_name = "X{0}{3}xbank0{3}xreplica_bitcell_array{3}xbitcell_array{3}xbit_r{1}_c{2}".format(self.sram.name, bit_row, bit_col, OPTS.hier_seperator) + cell_name = self.cell_name.format(bit_row, bit_col) storage_names = ("Q", "Q_bar") else: (cell_name, cell_inst) = self.sram.get_cell_name(self.sram.name, bit_row, bit_col) @@ -1256,31 +1255,23 @@ class delay(simulation): meas_buff.clear() self.read_meas_lists.append(self.sen_path_meas + self.bl_path_meas) - def guess_spice_names(self): + def set_spice_names(self): """This is run in place of set_internal_spice_names function from simulation.py when running stand-alone characterizer.""" - with open(self.sp_file, "r") as file: - bl_prefix = None - br_prefix = None - replica_bitcell_array_name = None - for line in file: - if re.search(r"bl_\d_\d", line): - bl_prefix = "bl_" - br_prefix = "br_" - if re.search(r"bl\d_\d", line): - bl_prefix = "bl" - br_prefix = "br" - if re.search(r"Xreplica_bitcell_array", line): - replica_bitcell_array_name = "replica_bitcell_array" - if bl_prefix and replica_bitcell_array_name: - break - debug.check(bl_prefix, "Could not guess the bitline name.") - self.bl_name = "X{0}{1}xbank0{1}{2}{{}}_{3}".format(self.sram.name, OPTS.hier_seperator, bl_prefix, self.bitline_column) - self.br_name = "X{0}{1}xbank0{1}{2}{{}}_{3}".format(self.sram.name, OPTS.hier_seperator, br_prefix, self.bitline_column) - self.sen_name = "X{0}{1}xbank0{1}s_en".format(self.sram.name, OPTS.hier_seperator) - if not replica_bitcell_array_name: - replica_bitcell_array_name = "bitcell_array" - self.cell_format = "X{{0}}{{3}}xbank0{{3}}xbitcell_array{{3}}x{0}{{3}}xbitcell_array{{3}}xbit_r{{1}}_c{{2}}".format(replica_bitcell_array_name) + self.bl_name = OPTS.bl_format.format(name=self.sram.name, + hier_sep=OPTS.hier_seperator, + row="{}", + col=self.bitline_column) + self.br_name = OPTS.br_format.format(name=self.sram.name, + hier_sep=OPTS.hier_seperator, + row="{}", + col=self.bitline_column) + self.sen_name = OPTS.sen_format.format(name=self.sram.name, + hier_sep=OPTS.hier_seperator) + self.cell_name = OPTS.cell_format.format(name=self.sram.name, + hier_sep=OPTS.hier_seperator, + row="{}", + col="{}") def analysis_init(self, probe_address, probe_data): """Sets values which are dependent on the data address/bit being tested.""" @@ -1288,7 +1279,7 @@ class delay(simulation): self.set_probe(probe_address, probe_data) self.prepare_netlist() if OPTS.top_process == "memchar": - self.guess_spice_names() + self.set_spice_names() self.create_measurement_names() self.create_measurement_objects() self.recover_measurment_objects() diff --git a/compiler/options.py b/compiler/options.py index 1448a321..56526a32 100644 --- a/compiler/options.py +++ b/compiler/options.py @@ -175,6 +175,11 @@ class options(optparse.Values): # Purge the temp directory after a successful # run (doesn't purge on errors, anyhow) + # Bitline, s_en and cell names used in characterizer + bl_format = "X{name}{hier_sep}xbank0{hier_sep}bl_{row}_{col}" + br_format = "X{name}{hier_sep}xbank0{hier_sep}br_{row}_{col}" + sen_format = "X{name}{hier_sep}xbank0{hier_sep}s_en" + cell_format = "X{name}{hier_sep}xbank0{hier_sep}xbitcell_array{hier_sep}xreplica_bitcell_array{hier_sep}xbitcell_array{hier_sep}xbit_r{row}_c{col}" # Route the input/output pins to the perimeter perimeter_pins = True From ed0c93ba550252f10e92ab7fb1f751961448173d Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Mon, 10 Jul 2023 14:05:44 -0700 Subject: [PATCH 103/130] Only add drc errors from compiler --- compiler/characterizer/lib.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/characterizer/lib.py b/compiler/characterizer/lib.py index 296aeaa9..68cc08b1 100644 --- a/compiler/characterizer/lib.py +++ b/compiler/characterizer/lib.py @@ -802,7 +802,8 @@ class lib: # information of checks # run it only the first time - datasheet.write("{0},{1},".format(self.sram.drc_errors, self.sram.lvs_errors)) + if OPTS.top_process != "memchar": + datasheet.write("{0},{1},".format(self.sram.drc_errors, self.sram.lvs_errors)) # write area datasheet.write(str(self.sram.width * self.sram.height) + ',') From 833d4c12a62d0337a3f336543657ab44b89da62c Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Tue, 11 Jul 2023 10:15:26 -0700 Subject: [PATCH 104/130] skip 30_tests for sky130 --- compiler/tests/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compiler/tests/Makefile b/compiler/tests/Makefile index 3ea5d299..b832f9c0 100644 --- a/compiler/tests/Makefile +++ b/compiler/tests/Makefile @@ -161,6 +161,8 @@ BROKEN_STAMPS = \ sky130/30_openram_back_end_test.ok \ sky130/30_openram_front_end_library_test.ok \ sky130/30_openram_front_end_test.ok \ + sky130/30_openram_sram_char_test.ok \ + sky130/30_openram_sram_func_test.ok \ gettech = $(word 1,$(subst /, ,$*)) getfile = $(word 2,$(subst /, ,$*)) From 146efc50700d893d551e4eef8b4cd5a2cff0d46c Mon Sep 17 00:00:00 2001 From: Sam Crow Date: Thu, 13 Jul 2023 16:45:05 -0700 Subject: [PATCH 105/130] implement pin_spice object --- compiler/base/design.py | 2 +- compiler/base/hierarchy_spice.py | 94 ++++++++++++++------------------ compiler/base/lef.py | 2 +- compiler/base/pin_spice.py | 43 +++++++++++++++ 4 files changed, 86 insertions(+), 55 deletions(-) create mode 100644 compiler/base/pin_spice.py diff --git a/compiler/base/design.py b/compiler/base/design.py index 94fd407f..329883c0 100644 --- a/compiler/base/design.py +++ b/compiler/base/design.py @@ -45,7 +45,7 @@ class design(hierarchy_design): "Custom cell pin names do not match spice file:\n{0} vs {1}".format(prop.port_names, self.pins)) self.add_pin_indices(prop.port_indices) self.add_pin_names(prop.port_map) - self.add_pin_types(prop.port_types) + self.update_pin_types(prop.port_types) (width, height) = utils.get_libcell_size(self.cell_name, diff --git a/compiler/base/hierarchy_spice.py b/compiler/base/hierarchy_spice.py index 64dc0b2b..90c65109 100644 --- a/compiler/base/hierarchy_spice.py +++ b/compiler/base/hierarchy_spice.py @@ -17,6 +17,7 @@ from .delay_data import delay_data from .wire_spice_model import wire_spice_model from .power_data import power_data from .logical_effort import convert_relative_c_to_farad, convert_farad_to_relative_c +from .pin_spice import pin_spice class spice(): @@ -49,14 +50,10 @@ class spice(): if not os.path.exists(self.lvs_file): self.lvs_file = self.sp_file - self.valid_signal_types = ["INOUT", "INPUT", "OUTPUT", "BIAS", "POWER", "GROUND"] # Holds subckts/mods for this module self.mods = set() # Holds the pins for this module (in order) self.pins = [] - # The type map of each pin: INPUT, OUTPUT, INOUT, POWER, GROUND - # for each instance, this is the set of nets/nodes that map to the pins for this instance - self.pin_type = {} # An (optional) list of indices to reorder the pins to match the spice. self.pin_indices = [] # THE CONNECTIONS MUST MATCH THE ORDER OF THE PINS (restriction imposed by the @@ -90,106 +87,97 @@ class spice(): def add_pin(self, name, pin_type="INOUT"): """ Adds a pin to the pins list. Default type is INOUT signal. """ - self.pins.append(name) - self.pin_type[name]=pin_type - debug.check(pin_type in self.valid_signal_types, - "Invalid signaltype for {0}: {1}".format(name, - pin_type)) + new_pin = pin_spice(name, pin_type) + debug.check(new_pin not in self.pins, "cannot add duplicate spice pin") + self.pins.append(new_pin) def add_pin_list(self, pin_list, pin_type="INOUT"): """ Adds a pin_list to the pins list """ - # The type list can be a single type for all pins + # The pin type list can be a single type for all pins # or a list that is the same length as the pin list. - if type(pin_type)==str: + if type(pin_type) == str: for pin in pin_list: - debug.check(pin_type in self.valid_signal_types, - "Invalid signaltype for {0}: {1}".format(pin, - pin_type)) self.add_pin(pin, pin_type) elif len(pin_type)==len(pin_list): - for (pin, ptype) in zip(pin_list, pin_type): - debug.check(ptype in self.valid_signal_types, - "Invalid signaltype for {0}: {1}".format(pin, - ptype)) - self.add_pin(pin, ptype) + for (pin, type) in zip(pin_list, pin_type): + self.add_pin(pin, type) else: - debug.error("Mismatch in type and pin list lengths.", -1) + debug.error("Pin type must be a string or list of strings the same length as pin_list", -1) def add_pin_indices(self, index_list): - """ - Add pin indices for all the cell's pins. - """ + """ Add pin indices for all the cell's pins. """ self.pin_indices = index_list def get_ordered_inputs(self, input_list): - """ - Return the inputs reordered to match the pins. - """ + """ Return the inputs reordered to match the pins. """ if not self.pin_indices: return input_list new_list = [input_list[x] for x in self.pin_indices] return new_list - def add_pin_types(self, type_list): - """ - Add pin types for all the cell's pins. - """ - # This only works if self.pins == bitcell.pin_names + def update_pin_types(self, type_list): + """ Change pin types for all the cell's pins. """ if len(type_list) != len(self.pins): debug.error("{} spice subcircuit number of port types does not match number of pins\ \n SPICE names={}\ \n Module names={}\ ".format(self.name, self.pins, type_list), 1) - self.pin_type = {pin: type for pin, type in zip(self.pins, type_list)} + for pin, type in zip(self.pins, type_list): + pin.set_pin_type(type) def get_pin_type(self, name): """ Returns the type of the signal pin. """ - pin_type = self.pin_type[name] - debug.check(pin_type in self.valid_signal_types, - "Invalid signaltype for {0}: {1}".format(name, pin_type)) - return pin_type + for pin in self.pins: + if pin.name == name: + return pin.type + debug.error("Spice pin {} not found".format(name)) def get_pin_dir(self, name): """ Returns the direction of the pin. (Supply/ground are INOUT). """ - if self.pin_type[name] in ["POWER", "GROUND"]: + pin_type = self.get_pin_type(name) + if pin_type in ["POWER", "GROUND"]: return "INOUT" else: - return self.pin_type[name] + return pin_type def get_inputs(self): - """ These use pin types to determine pin lists. These - may be over-ridden by submodules that didn't use pin directions yet.""" + """ + These use pin types to determine pin lists. + Returns names only to maintain historical interface. + """ input_list = [] for pin in self.pins: - if self.pin_type[pin]=="INPUT": - input_list.append(pin) + if pin.type == "INPUT": + input_list.append(pin.name) return input_list def get_outputs(self): - """ These use pin types to determine pin lists. These - may be over-ridden by submodules that didn't use pin directions yet.""" + """ + These use pin types to determine pin lists. + Returns names only to maintain historical interface. + """ output_list = [] for pin in self.pins: - if self.pin_type[pin]=="OUTPUT": - output_list.append(pin) + if pin.type == "OUTPUT": + output_list.append(pin.name) return output_list - def copy_pins(self, other_module, suffix=""): - """ This will copy all of the pins from the other module and add an optional suffix.""" - for pin in other_module.pins: - self.add_pin(pin + suffix, other_module.get_pin_type(pin)) - def get_inouts(self): """ These use pin types to determine pin lists. These may be over-ridden by submodules that didn't use pin directions yet.""" inout_list = [] for pin in self.pins: - if self.pin_type[pin]=="INOUT": - inout_list.append(pin) + if pin.type == "INOUT": + inout_list.append(pin.name) return inout_list + def copy_pins(self, other_module, suffix=""): + """ This will copy all of the pins from the other module and add an optional suffix.""" + for pin in other_module.pins: + self.add_pin(pin.name + suffix, pin.type) + def connect_inst(self, args, check=True): """ Connects the pins of the last instance added diff --git a/compiler/base/lef.py b/compiler/base/lef.py index b138799b..e08f0efc 100644 --- a/compiler/base/lef.py +++ b/compiler/base/lef.py @@ -18,7 +18,7 @@ class lef: """ SRAM LEF Class open GDS file, read pins information, obstruction and write them to LEF file. - This is inherited by the sram_base class. + This is inherited by the sram_1bank class. """ def __init__(self, layers): # LEF db units per micron diff --git a/compiler/base/pin_spice.py b/compiler/base/pin_spice.py new file mode 100644 index 00000000..1754550e --- /dev/null +++ b/compiler/base/pin_spice.py @@ -0,0 +1,43 @@ +# See LICENSE for licensing information. +# +# Copyright (c) 2016-2023 Regents of the University of California and The Board +# of Regents for the Oklahoma Agricultural and Mechanical College +# (acting for and on behalf of Oklahoma State University) +# All rights reserved. +# +from openram import debug + + +class pin_spice: + """ + A class to represent a spice netlist pin. + """ + + valid_pin_types = ["INOUT", "INPUT", "OUTPUT", "POWER", "GROUND"] + + def __init__(self, name, type): + self.name = name + self.set_type(type) + + self._hash = hash(self.name) + + def set_type(self, type): + debug.check(type in pin_spice.valid_pin_types, + "Invalid pin type for {0}: {1}".format(self.name, type)) + self.type = type + + def __str__(self): + """ override print function output """ + return "(pin_name={} type={})".format(self.name, self.type) + + def __repr__(self): + """ override repr function output """ + return self.name + + def __hash__(self): + """ + Implement the hash function for sets etc. + Only hash name since spice does not allow two pins to share a name. + Provides a speedup if pin_spice is used as a key for dicts. + """ + return self._hash From c8c43f75d9b93e6311e92ca13e3accb2ae4d1365 Mon Sep 17 00:00:00 2001 From: Sam Crow Date: Fri, 14 Jul 2023 16:18:10 -0700 Subject: [PATCH 106/130] add spice nets and a way to connect them to pins --- compiler/base/geometry.py | 17 ++++++++-- compiler/base/hierarchy_spice.py | 54 +++++++++++++++----------------- compiler/base/net_spice.py | 51 ++++++++++++++++++++++++++++++ compiler/base/pin_spice.py | 27 +++++++++++++++- 4 files changed, 117 insertions(+), 32 deletions(-) create mode 100644 compiler/base/net_spice.py diff --git a/compiler/base/geometry.py b/compiler/base/geometry.py index 2e33885c..18e1a39b 100644 --- a/compiler/base/geometry.py +++ b/compiler/base/geometry.py @@ -161,8 +161,8 @@ class geometry: class instance(geometry): """ - An instance of an instance/module with a specified location and - rotation + An instance of a module with a specified location, rotation, + spice pins, and spice nets """ def __init__(self, name, mod, offset=[0, 0], mirror="R0", rotate=0): """Initializes an instance to represent a module""" @@ -176,6 +176,14 @@ class instance(geometry): self.rotate = rotate self.offset = vector(offset).snap_to_grid() self.mirror = mirror + + # deepcopy because this instance needs to + # change attributes in these spice objects + self.spice_pins = copy.deepcopy(self.mod.pins) + self.spice_nets = copy.deepcopy(self.mod.nets) + for spice_obj in self.spice_pins + self.spice_nets: + spice_obj.set_inst(self) + if OPTS.netlist_only: self.width = 0 self.height = 0 @@ -274,6 +282,11 @@ class instance(geometry): new_pins.append(p) return new_pins + def connect_spice_pins(self, nets_list): + for i in range(len(self.pins)): + self.pins[i].set_inst_net(nets_list[i]) + nets_list[i].connect_pin(self.pins[i]) + def calculate_transform(self, node): #set up the rotation matrix angle = math.radians(float(node.rotate)) diff --git a/compiler/base/hierarchy_spice.py b/compiler/base/hierarchy_spice.py index 90c65109..3bf2af7f 100644 --- a/compiler/base/hierarchy_spice.py +++ b/compiler/base/hierarchy_spice.py @@ -13,6 +13,8 @@ from pprint import pformat from openram import debug from openram import tech from openram import OPTS + +from compiler.base.net_spice import net_spice from .delay_data import delay_data from .wire_spice_model import wire_spice_model from .power_data import power_data @@ -58,7 +60,8 @@ class spice(): self.pin_indices = [] # THE CONNECTIONS MUST MATCH THE ORDER OF THE PINS (restriction imposed by the # Spice format) - self.conns = [] + # internal nets, which may or may not be connected to pins of the same name + self.nets = [] # If this is set, it will out output subckt or isntances of this (for row/col caps etc.) self.no_instances = False # If we are doing a trimmed netlist, these are the instance that will be filtered @@ -178,16 +181,13 @@ class spice(): for pin in other_module.pins: self.add_pin(pin.name + suffix, pin.type) - def connect_inst(self, args, check=True): + def connect_inst(self, args): """ Connects the pins of the last instance added - It is preferred to use the function with the check to find if - there is a problem. The check option can be set to false - where we dynamically generate groups of connections after a - group of modules are generated. """ - num_pins = len(self.insts[-1].mod.pins) + spice_pins = self.insts[-1].spice_pins + num_pins = len(spice_pins) num_args = len(args) # Order the arguments if the hard cell has a custom port order @@ -195,11 +195,11 @@ class spice(): if (check and num_pins != num_args): if num_pins < num_args: - mod_pins = self.insts[-1].mod.pins + [""] * (num_args - num_pins) + mod_pins = spice_pins + [""] * (num_args - num_pins) arg_pins = ordered_args else: arg_pins = ordered_args + [""] * (num_pins - num_args) - mod_pins = self.insts[-1].mod.pins + mod_pins = spice_pins modpins_string = "\n".join(["{0} -> {1}".format(arg, mod) for (arg, mod) in zip(arg_pins, mod_pins)]) debug.error("Connection mismatch:\nInst ({0}) -> Mod ({1})\n{2}".format(num_args, @@ -207,27 +207,22 @@ class spice(): modpins_string), 1) - self.conns.append(ordered_args) + ordered_nets = self.create_nets(ordered_args) + self.insts[-1].connect_spice_pins(ordered_nets) - # This checks if we don't have enough instance port connections for the number of insts - if check and (len(self.insts)!=len(self.conns)): - insts_string=pformat(self.insts) - conns_string=pformat(self.conns) + # TODO: replace functionality that checked if user forgot to connect an inst before connecting the next - debug.error("{0} : Not all instance pins ({1}) are connected ({2}).".format(self.name, - len(self.insts), - len(self.conns))) - debug.error("Instances: \n" + str(insts_string)) - debug.error("-----") - debug.error("Connections: \n" + str(conns_string), 1) - - def get_conns(self, inst): - """Returns the connections of a given instance.""" - for i in range(len(self.insts)): - if inst is self.insts[i]: - return self.conns[i] - # If not found, returns None - return None + def create_nets(self, names_list): + nets = [] + for name in names_list: + try: + i = self.nets.index(name) + nets.append(self.nets[i]) + except ValueError: + net = net_spice(name) + self.nets.append(net) + nets.append(net) + return nets def sp_read(self): """ @@ -246,6 +241,7 @@ class spice(): subckt = re.compile("^.subckt {}".format(self.cell_name), re.IGNORECASE) subckt_line = list(filter(subckt.search, self.spice))[0] # parses line into ports and remove subckt + # FIXME: needs to use new pins interface self.pins = subckt_line.split(" ")[2:] else: debug.info(4, "no spfile {0}".format(self.sp_file)) @@ -345,7 +341,7 @@ class spice(): # Also write pins as comments for pin in self.pins: - sp.write("* {1:6}: {0} \n".format(pin, self.pin_type[pin])) + sp.write("* {1:6}: {0} \n".format(pin, pin.type)) for line in self.comments: sp.write("* {}\n".format(line)) diff --git a/compiler/base/net_spice.py b/compiler/base/net_spice.py new file mode 100644 index 00000000..d1c24ab6 --- /dev/null +++ b/compiler/base/net_spice.py @@ -0,0 +1,51 @@ +# See LICENSE for licensing information. +# +# Copyright (c) 2016-2023 Regents of the University of California and The Board +# of Regents for the Oklahoma Agricultural and Mechanical College +# (acting for and on behalf of Oklahoma State University) +# All rights reserved. +# +from openram import debug +from .pin_spice import pin_spice + + +class net_spice: + """ + A class to represent a spice net. + pins are all the pins connected to this net. + inst is the instance this net is a part of, if any. + """ + + def __init__(self, name): + self.name = name + self.pins = [] + self.inst = None + + # TODO: evaluate if this makes sense... and works + self._hash = hash(self.name) + + def connect_pin(self, pin): + debug.check(isinstance(pin, pin_spice), "pin must be a pin_spice object") + if pin in self.pins: + debug.warning("pin {} was already connected to net {} ... why was it connected again?".format(pin.name, self.name)) + else: + self.pins.append(pin) + + def __str__(self): + """ override print function output """ + return "(pin_name={} type={})".format(self.name, self.type) + + def __repr__(self): + """ override repr function output """ + return self.name + + def __eq__(self, name): + return (name == self.name) if isinstance(name, str) else super().__eq__(name) + + def __hash__(self): + """ + Implement the hash function for sets etc. + Only hash name since spice does not allow two pins to share a name. + Provides a speedup if pin_spice is used as a key for dicts. + """ + return self._hash diff --git a/compiler/base/pin_spice.py b/compiler/base/pin_spice.py index 1754550e..0d2d2342 100644 --- a/compiler/base/pin_spice.py +++ b/compiler/base/pin_spice.py @@ -6,19 +6,29 @@ # All rights reserved. # from openram import debug +from .net_spice import net_spice class pin_spice: """ A class to represent a spice netlist pin. + mod is the parent module that created this pin. + mod_net is the net object of this pin's parent module. + inst is the instance this pin is a part of, if any. + inst_net is the net object from mod's nets which connects to this pin. """ valid_pin_types = ["INOUT", "INPUT", "OUTPUT", "POWER", "GROUND"] - def __init__(self, name, type): + def __init__(self, name, type, mod): self.name = name self.set_type(type) + self.mod = mod + self.mod_net = None + self.inst = None + self.inst_net = None + # TODO: evaluate if this makes sense... and works self._hash = hash(self.name) def set_type(self, type): @@ -26,6 +36,18 @@ class pin_spice: "Invalid pin type for {0}: {1}".format(self.name, type)) self.type = type + def set_mod_net(self, net): + debug.check(isinstance(net, net_spice), "net must be a net_spice object") + debug.check(net.name == self.name, "module spice net must have same name as spice pin") + self.mod_net = net + + def set_inst(self, inst): + self.inst = inst + + def set_inst_net(self, net): + debug.check(isinstance(net, net_spice), "net must be a net_spice object") + self.inst_net = net + def __str__(self): """ override print function output """ return "(pin_name={} type={})".format(self.name, self.type) @@ -34,6 +56,9 @@ class pin_spice: """ override repr function output """ return self.name + def __eq__(self, name): + return (name == self.name) if isinstance(name, str) else super().__eq__(name) + def __hash__(self): """ Implement the hash function for sets etc. From 7581df22557bffe6997a4d87da770bc2093aa496 Mon Sep 17 00:00:00 2001 From: Sam Crow Date: Mon, 17 Jul 2023 14:32:39 -0700 Subject: [PATCH 107/130] change pins to OrderedDict --- compiler/base/design.py | 6 +-- compiler/base/hierarchy_design.py | 14 +++--- compiler/base/hierarchy_spice.py | 82 +++++++++++++------------------ 3 files changed, 45 insertions(+), 57 deletions(-) diff --git a/compiler/base/design.py b/compiler/base/design.py index 329883c0..fe9b5495 100644 --- a/compiler/base/design.py +++ b/compiler/base/design.py @@ -41,8 +41,8 @@ class design(hierarchy_design): if prop and prop.hard_cell: # The pins get added from the spice file, so just check # that they matched here - debug.check(prop.port_names == self.pins, - "Custom cell pin names do not match spice file:\n{0} vs {1}".format(prop.port_names, self.pins)) + debug.check(prop.port_names == list(self.pins), + "Custom cell pin names do not match spice file:\n{0} vs {1}".format(prop.port_names, list(self.pins))) self.add_pin_indices(prop.port_indices) self.add_pin_names(prop.port_map) self.update_pin_types(prop.port_types) @@ -51,7 +51,7 @@ class design(hierarchy_design): (width, height) = utils.get_libcell_size(self.cell_name, GDS["unit"], layer[prop.boundary_layer]) - self.pin_map = utils.get_libcell_pins(self.pins, + self.pin_map = utils.get_libcell_pins(list(self.pins), self.cell_name, GDS["unit"]) diff --git a/compiler/base/hierarchy_design.py b/compiler/base/hierarchy_design.py index 42c0543d..c34bc5f5 100644 --- a/compiler/base/hierarchy_design.py +++ b/compiler/base/hierarchy_design.py @@ -135,9 +135,9 @@ class hierarchy_design(spice, layout): # Translate port names to external nets if len(port_nets) != len(self.pins): debug.error("Port length mismatch:\nExt nets={}, Ports={}".format(port_nets, - self.pins), + list(self.pins)), 1) - port_dict = {pin: port for pin, port in zip(self.pins, port_nets)} + port_dict = {pin: port for pin, port in zip(list(self.pins), port_nets)} debug.info(3, "Instance name={}".format(inst_name)) for subinst, conns in zip(self.insts, self.conns): if subinst in self.graph_inst_exclude: @@ -153,9 +153,9 @@ class hierarchy_design(spice, layout): # Translate port names to external nets if len(port_nets) != len(self.pins): debug.error("Port length mismatch:\nExt nets={}, Ports={}".format(port_nets, - self.pins), + list(self.pins)), 1) - port_dict = {pin: port for pin, port in zip(self.pins, port_nets)} + port_dict = {pin: port for pin, port in zip(list(self.pins), port_nets)} debug.info(3, "Instance name={}".format(inst_name)) for subinst, conns in zip(self.insts, self.conns): subinst_name = inst_name + "{}x".format(OPTS.hier_seperator) + subinst.name @@ -186,7 +186,7 @@ class hierarchy_design(spice, layout): """ # The final pin names will depend on the spice hierarchy, so # they are passed as an input. - pin_dict = {pin: port for pin, port in zip(self.pins, port_nets)} + pin_dict = {pin: port for pin, port in zip(list(self.pins), port_nets)} input_pins = self.get_inputs() output_pins = self.get_outputs() inout_pins = self.get_inouts() @@ -197,7 +197,7 @@ class hierarchy_design(spice, layout): def __str__(self): """ override print function output """ - pins = ",".join(self.pins) + pins = ",".join(list(self.pins)) insts = [" {}".format(x) for x in self.insts] objs = [" {}".format(x) for x in self.objs] s = "********** design {0} **********".format(self.cell_name) @@ -208,7 +208,7 @@ class hierarchy_design(spice, layout): def __repr__(self): """ override print function output """ - text="( design: " + self.name + " pins=" + str(self.pins) + " " + str(self.width) + "x" + str(self.height) + " )\n" + text="( design: " + self.name + " pins=" + str(list(self.pins)) + " " + str(self.width) + "x" + str(self.height) + " )\n" for i in self.objs: text+=str(i) + ",\n" for i in self.insts: diff --git a/compiler/base/hierarchy_spice.py b/compiler/base/hierarchy_spice.py index 3bf2af7f..914ee2f0 100644 --- a/compiler/base/hierarchy_spice.py +++ b/compiler/base/hierarchy_spice.py @@ -13,13 +13,13 @@ from pprint import pformat from openram import debug from openram import tech from openram import OPTS - -from compiler.base.net_spice import net_spice +from collections import OrderedDict from .delay_data import delay_data from .wire_spice_model import wire_spice_model from .power_data import power_data from .logical_effort import convert_relative_c_to_farad, convert_farad_to_relative_c from .pin_spice import pin_spice +from .net_spice import net_spice class spice(): @@ -55,14 +55,15 @@ class spice(): # Holds subckts/mods for this module self.mods = set() # Holds the pins for this module (in order) - self.pins = [] + # on Python3.7+ regular dictionaries guarantee order too, but we allow use of v3.5+ + self.pins = OrderedDict() # An (optional) list of indices to reorder the pins to match the spice. self.pin_indices = [] # THE CONNECTIONS MUST MATCH THE ORDER OF THE PINS (restriction imposed by the # Spice format) # internal nets, which may or may not be connected to pins of the same name - self.nets = [] - # If this is set, it will out output subckt or isntances of this (for row/col caps etc.) + self.nets = {} + # If this is set, it will not output subckt or instances of this (for row/col caps etc.) self.no_instances = False # If we are doing a trimmed netlist, these are the instance that will be filtered self.trim_insts = set() @@ -90,9 +91,8 @@ class spice(): def add_pin(self, name, pin_type="INOUT"): """ Adds a pin to the pins list. Default type is INOUT signal. """ - new_pin = pin_spice(name, pin_type) - debug.check(new_pin not in self.pins, "cannot add duplicate spice pin") - self.pins.append(new_pin) + debug.check(name not in self.pins, "cannot add duplicate spice pin {}".format(name)) + self.pins[name] = pin_spice(name, pin_type) def add_pin_list(self, pin_list, pin_type="INOUT"): """ Adds a pin_list to the pins list """ @@ -122,20 +122,17 @@ class spice(): def update_pin_types(self, type_list): """ Change pin types for all the cell's pins. """ - if len(type_list) != len(self.pins): - debug.error("{} spice subcircuit number of port types does not match number of pins\ - \n SPICE names={}\ - \n Module names={}\ - ".format(self.name, self.pins, type_list), 1) - for pin, type in zip(self.pins, type_list): + debug.check(len(type_list) == len(self.pins), + "{} spice subcircuit number of port types does not match number of pins\ + \n pin names={}\n port types={}".format(self.name, list(self.pins), type_list)) + for pin, type in zip(self.pins.values(), type_list): pin.set_pin_type(type) def get_pin_type(self, name): """ Returns the type of the signal pin. """ - for pin in self.pins: - if pin.name == name: - return pin.type - debug.error("Spice pin {} not found".format(name)) + pin = self.pins.get(name) + debug.check(pin is not None, "Spice pin {} not found".format(name)) + return pin.type def get_pin_dir(self, name): """ Returns the direction of the pin. (Supply/ground are INOUT). """ @@ -148,10 +145,10 @@ class spice(): def get_inputs(self): """ These use pin types to determine pin lists. - Returns names only to maintain historical interface. + Returns names only, to maintain historical interface. """ input_list = [] - for pin in self.pins: + for pin in self.pins.values(): if pin.type == "INPUT": input_list.append(pin.name) return input_list @@ -159,26 +156,28 @@ class spice(): def get_outputs(self): """ These use pin types to determine pin lists. - Returns names only to maintain historical interface. + Returns names only, to maintain historical interface. """ output_list = [] - for pin in self.pins: + for pin in self.pins.values(): if pin.type == "OUTPUT": output_list.append(pin.name) return output_list def get_inouts(self): - """ These use pin types to determine pin lists. These - may be over-ridden by submodules that didn't use pin directions yet.""" + """ + These use pin types to determine pin lists. + Returns names only, to maintain historical interface. + """ inout_list = [] - for pin in self.pins: + for pin in self.pins.values(): if pin.type == "INOUT": inout_list.append(pin.name) return inout_list def copy_pins(self, other_module, suffix=""): """ This will copy all of the pins from the other module and add an optional suffix.""" - for pin in other_module.pins: + for pin in other_module.pins.values(): self.add_pin(pin.name + suffix, pin.type) def connect_inst(self, args): @@ -186,7 +185,7 @@ class spice(): Connects the pins of the last instance added """ - spice_pins = self.insts[-1].spice_pins + spice_pins = list(self.insts[-1].spice_pins) num_pins = len(spice_pins) num_args = len(args) @@ -241,8 +240,7 @@ class spice(): subckt = re.compile("^.subckt {}".format(self.cell_name), re.IGNORECASE) subckt_line = list(filter(subckt.search, self.spice))[0] # parses line into ports and remove subckt - # FIXME: needs to use new pins interface - self.pins = subckt_line.split(" ")[2:] + self.add_pin_list(subckt_line.split(" ")[2:]) else: debug.info(4, "no spfile {0}".format(self.sp_file)) self.spice = [] @@ -263,10 +261,10 @@ class spice(): subckt_line = list(filter(subckt.search, self.lvs))[0] # parses line into ports and remove subckt lvs_pins = subckt_line.split(" ")[2:] - debug.check(lvs_pins == self.pins, + debug.check(lvs_pins == list(self.pins), "Spice netlists for LVS and simulation have port mismatches:\n{0} (LVS {1})\nvs\n{2} (sim {3})".format(lvs_pins, self.lvs_file, - self.pins, + list(self.pins), self.sp_file)) def check_net_in_spice(self, net_name): @@ -299,6 +297,8 @@ class spice(): return False def sp_write_file(self, sp, usedMODS, lvs=False, trim=False): + # FIXME: this function refers to conns for connections but that no longer exists. + # it should be possible to just query the instances themselves for their connections. """ Recursive spice subcircuit write; Writes the spice subcircuit from the library or the dynamically generated one. @@ -319,29 +319,17 @@ class spice(): if len(self.insts) == 0: return - if self.pins == []: + if len(self.pins) == 0: return # write out the first spice line (the subcircuit) - wrapped_pins = "\n+ ".join(tr.wrap(" ".join(self.pins))) + wrapped_pins = "\n+ ".join(tr.wrap(" ".join(list(self.pins)))) sp.write("\n.SUBCKT {0}\n+ {1}\n".format(self.cell_name, wrapped_pins)) - # write a PININFO line - if False: - pin_info = "*.PININFO" - for pin in self.pins: - if self.pin_type[pin] == "INPUT": - pin_info += " {0}:I".format(pin) - elif self.pin_type[pin] == "OUTPUT": - pin_info += " {0}:O".format(pin) - else: - pin_info += " {0}:B".format(pin) - sp.write(pin_info + "\n") - # Also write pins as comments - for pin in self.pins: - sp.write("* {1:6}: {0} \n".format(pin, pin.type)) + for pin in self.pins.values(): + sp.write("* {1:6}: {0} \n".format(pin.name, pin.type)) for line in self.comments: sp.write("* {}\n".format(line)) From e15feb236148e96d76c2673ff529a179b1d29cbe Mon Sep 17 00:00:00 2001 From: Sam Crow Date: Mon, 17 Jul 2023 15:36:22 -0700 Subject: [PATCH 108/130] change nets list to dictionary --- compiler/base/hierarchy_spice.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/compiler/base/hierarchy_spice.py b/compiler/base/hierarchy_spice.py index 914ee2f0..b03fa4ef 100644 --- a/compiler/base/hierarchy_spice.py +++ b/compiler/base/hierarchy_spice.py @@ -214,13 +214,10 @@ class spice(): def create_nets(self, names_list): nets = [] for name in names_list: - try: - i = self.nets.index(name) - nets.append(self.nets[i]) - except ValueError: - net = net_spice(name) - self.nets.append(net) - nets.append(net) + # setdefault adds to the dict if it doesn't find the net in it already + # then it returns the net it found or created, a net_spice object + net = self.nets.setdefault(name, net_spice(name)) + nets.append(net) return nets def sp_read(self): From d0339a90e63939c75e74a07ded6035b6bc6b023a Mon Sep 17 00:00:00 2001 From: Sam Crow Date: Mon, 17 Jul 2023 15:36:57 -0700 Subject: [PATCH 109/130] change spice_nets and spice_pins to dicts --- compiler/base/geometry.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/compiler/base/geometry.py b/compiler/base/geometry.py index 18e1a39b..29093a2d 100644 --- a/compiler/base/geometry.py +++ b/compiler/base/geometry.py @@ -181,8 +181,10 @@ class instance(geometry): # change attributes in these spice objects self.spice_pins = copy.deepcopy(self.mod.pins) self.spice_nets = copy.deepcopy(self.mod.nets) - for spice_obj in self.spice_pins + self.spice_nets: - spice_obj.set_inst(self) + for pin in self.spice_pins.values(): + pin.set_inst(self) + for net in self.spice_nets.values(): + net.set_inst(self) if OPTS.netlist_only: self.width = 0 From 45b88889e4e03648ac718c15b6066dadb3219b0c Mon Sep 17 00:00:00 2001 From: Sam Crow Date: Mon, 17 Jul 2023 16:04:56 -0700 Subject: [PATCH 110/130] use pin and net objects in connect_inst --- compiler/base/geometry.py | 14 +++++++++++--- compiler/base/hierarchy_spice.py | 2 +- compiler/base/pin_spice.py | 5 ++++- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/compiler/base/geometry.py b/compiler/base/geometry.py index 29093a2d..a8ac89cb 100644 --- a/compiler/base/geometry.py +++ b/compiler/base/geometry.py @@ -285,9 +285,17 @@ class instance(geometry): return new_pins def connect_spice_pins(self, nets_list): - for i in range(len(self.pins)): - self.pins[i].set_inst_net(nets_list[i]) - nets_list[i].connect_pin(self.pins[i]) + """ + add the connection between instance pins and module nets + to both of their respective objects + nets_list must be the same length as self.spice_pins + """ + debug.check(len(self.spice_pins) == len(nets_list), + "must provide list of nets the same length as pin list\ + when connecting an instance") + for i in range(len(self.spice_pins)): + self.spice_pins[i].set_inst_net(nets_list[i]) + nets_list[i].connect_pin(self.spice_pins[i]) def calculate_transform(self, node): #set up the rotation matrix diff --git a/compiler/base/hierarchy_spice.py b/compiler/base/hierarchy_spice.py index b03fa4ef..e0d4f573 100644 --- a/compiler/base/hierarchy_spice.py +++ b/compiler/base/hierarchy_spice.py @@ -192,7 +192,7 @@ class spice(): # Order the arguments if the hard cell has a custom port order ordered_args = self.get_ordered_inputs(args) - if (check and num_pins != num_args): + if (num_pins != num_args): if num_pins < num_args: mod_pins = spice_pins + [""] * (num_args - num_pins) arg_pins = ordered_args diff --git a/compiler/base/pin_spice.py b/compiler/base/pin_spice.py index 0d2d2342..1b101bfd 100644 --- a/compiler/base/pin_spice.py +++ b/compiler/base/pin_spice.py @@ -13,7 +13,7 @@ class pin_spice: """ A class to represent a spice netlist pin. mod is the parent module that created this pin. - mod_net is the net object of this pin's parent module. + mod_net is the net object of this pin's parent module. It must have the same name as the pin. inst is the instance this pin is a part of, if any. inst_net is the net object from mod's nets which connects to this pin. """ @@ -45,6 +45,9 @@ class pin_spice: self.inst = inst def set_inst_net(self, net): + debug.check(self.inst_net is None, + "pin {} is already connected to net {} so it cannot also be connected to net {}\ + ".format(self.name, self.inst_net.name, net.name)) debug.check(isinstance(net, net_spice), "net must be a net_spice object") self.inst_net = net From 478c76c1cae2ae90c33fa7fed7d3d68ef68c656c Mon Sep 17 00:00:00 2001 From: Sam Crow Date: Tue, 18 Jul 2023 10:50:50 -0700 Subject: [PATCH 111/130] get connections from spice objects in instances --- compiler/base/geometry.py | 11 ++++++ compiler/base/hierarchy_design.py | 4 +- compiler/base/hierarchy_spice.py | 63 ++++++++++++++++--------------- 3 files changed, 46 insertions(+), 32 deletions(-) diff --git a/compiler/base/geometry.py b/compiler/base/geometry.py index a8ac89cb..9eedc7f5 100644 --- a/compiler/base/geometry.py +++ b/compiler/base/geometry.py @@ -176,6 +176,8 @@ class instance(geometry): self.rotate = rotate self.offset = vector(offset).snap_to_grid() self.mirror = mirror + # track if the instance's spice pin connections have been made + self.connected = False # deepcopy because this instance needs to # change attributes in these spice objects @@ -290,12 +292,21 @@ class instance(geometry): to both of their respective objects nets_list must be the same length as self.spice_pins """ + debug.check(not self.connected, + "instance {} has already been connected".format(self.name)) debug.check(len(self.spice_pins) == len(nets_list), "must provide list of nets the same length as pin list\ when connecting an instance") for i in range(len(self.spice_pins)): self.spice_pins[i].set_inst_net(nets_list[i]) nets_list[i].connect_pin(self.spice_pins[i]) + self.connected = True + + def get_connections(self): + conns = [] + for pin in self.spice_pins: + conns.append(pin.inst_net.name) + return conns def calculate_transform(self, node): #set up the rotation matrix diff --git a/compiler/base/hierarchy_design.py b/compiler/base/hierarchy_design.py index c34bc5f5..31a1e191 100644 --- a/compiler/base/hierarchy_design.py +++ b/compiler/base/hierarchy_design.py @@ -139,7 +139,7 @@ class hierarchy_design(spice, layout): 1) port_dict = {pin: port for pin, port in zip(list(self.pins), port_nets)} debug.info(3, "Instance name={}".format(inst_name)) - for subinst, conns in zip(self.insts, self.conns): + for subinst, conns in zip(self.insts, self.get_instance_connections()): if subinst in self.graph_inst_exclude: continue subinst_name = inst_name + "{}x".format(OPTS.hier_seperator) + subinst.name @@ -157,7 +157,7 @@ class hierarchy_design(spice, layout): 1) port_dict = {pin: port for pin, port in zip(list(self.pins), port_nets)} debug.info(3, "Instance name={}".format(inst_name)) - for subinst, conns in zip(self.insts, self.conns): + for subinst, conns in zip(self.insts, self.get_instance_connections()): subinst_name = inst_name + "{}x".format(OPTS.hier_seperator) + subinst.name subinst_ports = self.translate_nets(conns, port_dict, inst_name) for si_port, conn in zip(subinst_ports, conns): diff --git a/compiler/base/hierarchy_spice.py b/compiler/base/hierarchy_spice.py index e0d4f573..96357209 100644 --- a/compiler/base/hierarchy_spice.py +++ b/compiler/base/hierarchy_spice.py @@ -209,8 +209,6 @@ class spice(): ordered_nets = self.create_nets(ordered_args) self.insts[-1].connect_spice_pins(ordered_nets) - # TODO: replace functionality that checked if user forgot to connect an inst before connecting the next - def create_nets(self, names_list): nets = [] for name in names_list: @@ -294,8 +292,6 @@ class spice(): return False def sp_write_file(self, sp, usedMODS, lvs=False, trim=False): - # FIXME: this function refers to conns for connections but that no longer exists. - # it should be possible to just query the instances themselves for their connections. """ Recursive spice subcircuit write; Writes the spice subcircuit from the library or the dynamically generated one. @@ -308,11 +304,11 @@ class spice(): # If spice isn't defined, we dynamically generate one. # recursively write the modules - for i in self.mods: - if self.contains(i, usedMODS): + for mod in self.mods: + if self.contains(mod, usedMODS): continue - usedMODS.append(i) - i.sp_write_file(sp, usedMODS, lvs, trim) + usedMODS.append(mod) + mod.sp_write_file(sp, usedMODS, lvs, trim) if len(self.insts) == 0: return @@ -331,43 +327,44 @@ class spice(): for line in self.comments: sp.write("* {}\n".format(line)) - # every instance must have a set of connections, even if it is empty. - if len(self.insts) != len(self.conns): - debug.error("{0} : Not all instance pins ({1}) are connected ({2}).".format(self.cell_name, - len(self.insts), - len(self.conns))) - debug.error("Instances: \n" + str(self.insts)) - debug.error("-----") - debug.error("Connections: \n" + str(self.conns), 1) + # every instance must be connected with the connect_inst function + # TODO: may run into empty pin lists edge case, not sure yet + connected = True + for inst in self.insts: + if inst.connected: + continue + debug.error("Instance {} spice pins not connected".format(str(inst))) + connected = False + debug.check(connected, "{0} : Not all instance spice pins are connected.".format(self.cell_name)) - for i in range(len(self.insts)): + for inst in self.insts: # we don't need to output connections of empty instances. # these are wires and paths - if self.conns[i] == []: + if len(inst.spice_pins) == 0: continue # Instance with no devices in it needs no subckt/instance - if self.insts[i].mod.no_instances: + if inst.mod.no_instances: continue # If this is a trimmed netlist, skip it by adding comment char - if trim and self.insts[i].name in self.trim_insts: + if trim and inst.name in self.trim_insts: sp.write("* ") - if lvs and hasattr(self.insts[i].mod, "lvs_device"): - sp.write(self.insts[i].mod.lvs_device.format(self.insts[i].name, - " ".join(self.conns[i]))) + if lvs and hasattr(inst.mod, "lvs_device"): + sp.write(inst.mod.lvs_device.format(inst.name, + " ".join(inst.get_connections()))) sp.write("\n") - elif hasattr(self.insts[i].mod, "spice_device"): - sp.write(self.insts[i].mod.spice_device.format(self.insts[i].name, - " ".join(self.conns[i]))) + elif hasattr(inst.mod, "spice_device"): + sp.write(inst.mod.spice_device.format(inst.name, + " ".join(inst.get_connections()))) sp.write("\n") else: - wrapped_connections = "\n+ ".join(tr.wrap(" ".join(self.conns[i]))) + wrapped_connections = "\n+ ".join(tr.wrap(" ".join(inst.get_connections()))) - sp.write("X{0}\n+ {1}\n+ {2}\n".format(self.insts[i].name, + sp.write("X{0}\n+ {1}\n+ {2}\n".format(inst.name, wrapped_connections, - self.insts[i].mod.cell_name)) + inst.mod.cell_name)) sp.write(".ENDS {0}\n".format(self.cell_name)) @@ -696,6 +693,12 @@ class spice(): aliases.append(net) return aliases + def get_instance_connections(self): + conns = [] + for inst in self.instances: + conns.append(inst.get_connections()) + return conns + def is_net_alias(self, known_net, net_alias, mod, exclusion_set): """ Checks if the alias_net in input mod is the same as the input net for this mod (self). @@ -708,7 +711,7 @@ class spice(): return True # Check connections of all other subinsts mod_set = set() - for subinst, inst_conns in zip(self.insts, self.conns): + for subinst, inst_conns in zip(self.insts, self.get_instance_connections()): for inst_conn, mod_pin in zip(inst_conns, subinst.mod.pins): if self.is_net_alias_name_check(known_net, inst_conn, net_alias, mod): return True From aa71785bd51f945d4f6ae1b3ed70f2d8b078b18c Mon Sep 17 00:00:00 2001 From: Sam Crow Date: Tue, 18 Jul 2023 11:28:30 -0700 Subject: [PATCH 112/130] fix circular import with pin and net --- compiler/base/hierarchy_spice.py | 106 ++++++++++++++++++++++++++++++- compiler/base/net_spice.py | 51 --------------- compiler/base/pin_spice.py | 71 --------------------- 3 files changed, 104 insertions(+), 124 deletions(-) delete mode 100644 compiler/base/net_spice.py delete mode 100644 compiler/base/pin_spice.py diff --git a/compiler/base/hierarchy_spice.py b/compiler/base/hierarchy_spice.py index 96357209..4803fb65 100644 --- a/compiler/base/hierarchy_spice.py +++ b/compiler/base/hierarchy_spice.py @@ -18,8 +18,6 @@ from .delay_data import delay_data from .wire_spice_model import wire_spice_model from .power_data import power_data from .logical_effort import convert_relative_c_to_farad, convert_farad_to_relative_c -from .pin_spice import pin_spice -from .net_spice import net_spice class spice(): @@ -728,3 +726,107 @@ class spice(): return self == mod and \ child_net.lower() == alias_net.lower() and \ parent_net.lower() == alias_net.lower() + + +class pin_spice(): + """ + A class to represent a spice netlist pin. + mod is the parent module that created this pin. + mod_net is the net object of this pin's parent module. It must have the same name as the pin. + inst is the instance this pin is a part of, if any. + inst_net is the net object from mod's nets which connects to this pin. + """ + + valid_pin_types = ["INOUT", "INPUT", "OUTPUT", "POWER", "GROUND"] + + def __init__(self, name, type, mod): + self.name = name + self.set_type(type) + self.mod = mod + self.mod_net = None + self.inst = None + self.inst_net = None + + # TODO: evaluate if this makes sense... and works + self._hash = hash(self.name) + + def set_type(self, type): + debug.check(type in pin_spice.valid_pin_types, + "Invalid pin type for {0}: {1}".format(self.name, type)) + self.type = type + + def set_mod_net(self, net): + debug.check(isinstance(net, net_spice), "net must be a net_spice object") + debug.check(net.name == self.name, "module spice net must have same name as spice pin") + self.mod_net = net + + def set_inst(self, inst): + self.inst = inst + + def set_inst_net(self, net): + debug.check(self.inst_net is None, + "pin {} is already connected to net {} so it cannot also be connected to net {}\ + ".format(self.name, self.inst_net.name, net.name)) + debug.check(isinstance(net, net_spice), "net must be a net_spice object") + self.inst_net = net + + def __str__(self): + """ override print function output """ + return "(pin_name={} type={})".format(self.name, self.type) + + def __repr__(self): + """ override repr function output """ + return self.name + + def __eq__(self, name): + return (name == self.name) if isinstance(name, str) else super().__eq__(name) + + def __hash__(self): + """ + Implement the hash function for sets etc. + Only hash name since spice does not allow two pins to share a name. + Provides a speedup if pin_spice is used as a key for dicts. + """ + return self._hash + + +class net_spice(): + """ + A class to represent a spice net. + pins are all the pins connected to this net. + inst is the instance this net is a part of, if any. + """ + + def __init__(self, name): + self.name = name + self.pins = [] + self.inst = None + + # TODO: evaluate if this makes sense... and works + self._hash = hash(self.name) + + def connect_pin(self, pin): + debug.check(isinstance(pin, pin_spice), "pin must be a pin_spice object") + if pin in self.pins: + debug.warning("pin {} was already connected to net {} ... why was it connected again?".format(pin.name, self.name)) + else: + self.pins.append(pin) + + def __str__(self): + """ override print function output """ + return "(pin_name={} type={})".format(self.name, self.type) + + def __repr__(self): + """ override repr function output """ + return self.name + + def __eq__(self, name): + return (name == self.name) if isinstance(name, str) else super().__eq__(name) + + def __hash__(self): + """ + Implement the hash function for sets etc. + Only hash name since spice does not allow two pins to share a name. + Provides a speedup if pin_spice is used as a key for dicts. + """ + return self._hash diff --git a/compiler/base/net_spice.py b/compiler/base/net_spice.py deleted file mode 100644 index d1c24ab6..00000000 --- a/compiler/base/net_spice.py +++ /dev/null @@ -1,51 +0,0 @@ -# See LICENSE for licensing information. -# -# Copyright (c) 2016-2023 Regents of the University of California and The Board -# of Regents for the Oklahoma Agricultural and Mechanical College -# (acting for and on behalf of Oklahoma State University) -# All rights reserved. -# -from openram import debug -from .pin_spice import pin_spice - - -class net_spice: - """ - A class to represent a spice net. - pins are all the pins connected to this net. - inst is the instance this net is a part of, if any. - """ - - def __init__(self, name): - self.name = name - self.pins = [] - self.inst = None - - # TODO: evaluate if this makes sense... and works - self._hash = hash(self.name) - - def connect_pin(self, pin): - debug.check(isinstance(pin, pin_spice), "pin must be a pin_spice object") - if pin in self.pins: - debug.warning("pin {} was already connected to net {} ... why was it connected again?".format(pin.name, self.name)) - else: - self.pins.append(pin) - - def __str__(self): - """ override print function output """ - return "(pin_name={} type={})".format(self.name, self.type) - - def __repr__(self): - """ override repr function output """ - return self.name - - def __eq__(self, name): - return (name == self.name) if isinstance(name, str) else super().__eq__(name) - - def __hash__(self): - """ - Implement the hash function for sets etc. - Only hash name since spice does not allow two pins to share a name. - Provides a speedup if pin_spice is used as a key for dicts. - """ - return self._hash diff --git a/compiler/base/pin_spice.py b/compiler/base/pin_spice.py deleted file mode 100644 index 1b101bfd..00000000 --- a/compiler/base/pin_spice.py +++ /dev/null @@ -1,71 +0,0 @@ -# See LICENSE for licensing information. -# -# Copyright (c) 2016-2023 Regents of the University of California and The Board -# of Regents for the Oklahoma Agricultural and Mechanical College -# (acting for and on behalf of Oklahoma State University) -# All rights reserved. -# -from openram import debug -from .net_spice import net_spice - - -class pin_spice: - """ - A class to represent a spice netlist pin. - mod is the parent module that created this pin. - mod_net is the net object of this pin's parent module. It must have the same name as the pin. - inst is the instance this pin is a part of, if any. - inst_net is the net object from mod's nets which connects to this pin. - """ - - valid_pin_types = ["INOUT", "INPUT", "OUTPUT", "POWER", "GROUND"] - - def __init__(self, name, type, mod): - self.name = name - self.set_type(type) - self.mod = mod - self.mod_net = None - self.inst = None - self.inst_net = None - - # TODO: evaluate if this makes sense... and works - self._hash = hash(self.name) - - def set_type(self, type): - debug.check(type in pin_spice.valid_pin_types, - "Invalid pin type for {0}: {1}".format(self.name, type)) - self.type = type - - def set_mod_net(self, net): - debug.check(isinstance(net, net_spice), "net must be a net_spice object") - debug.check(net.name == self.name, "module spice net must have same name as spice pin") - self.mod_net = net - - def set_inst(self, inst): - self.inst = inst - - def set_inst_net(self, net): - debug.check(self.inst_net is None, - "pin {} is already connected to net {} so it cannot also be connected to net {}\ - ".format(self.name, self.inst_net.name, net.name)) - debug.check(isinstance(net, net_spice), "net must be a net_spice object") - self.inst_net = net - - def __str__(self): - """ override print function output """ - return "(pin_name={} type={})".format(self.name, self.type) - - def __repr__(self): - """ override repr function output """ - return self.name - - def __eq__(self, name): - return (name == self.name) if isinstance(name, str) else super().__eq__(name) - - def __hash__(self): - """ - Implement the hash function for sets etc. - Only hash name since spice does not allow two pins to share a name. - Provides a speedup if pin_spice is used as a key for dicts. - """ - return self._hash From 5907cbb3e2904b1d0e2700e023e1246b728d6f8b Mon Sep 17 00:00:00 2001 From: Sam Crow Date: Tue, 18 Jul 2023 16:12:42 -0700 Subject: [PATCH 113/130] remove pins overwrite from contact class --- compiler/base/contact.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/compiler/base/contact.py b/compiler/base/contact.py index 5fe59bcb..84f60d0e 100644 --- a/compiler/base/contact.py +++ b/compiler/base/contact.py @@ -66,8 +66,6 @@ class contact(hierarchy_design): self.offset = vector(0, 0) self.implant_type = implant_type self.well_type = well_type - # Module does not have pins, but has empty pin list. - self.pins = [] self.create_layout() def create_layout(self): From 09aa395174513f750f66bb5bd4b855d78d91d15b Mon Sep 17 00:00:00 2001 From: Sam Crow Date: Tue, 18 Jul 2023 16:13:29 -0700 Subject: [PATCH 114/130] cast pins dict to list --- compiler/modules/column_decoder.py | 2 +- compiler/modules/pbitcell.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/modules/column_decoder.py b/compiler/modules/column_decoder.py index 92149a71..ab80b1c9 100644 --- a/compiler/modules/column_decoder.py +++ b/compiler/modules/column_decoder.py @@ -42,7 +42,7 @@ class column_decoder(design): def create_instances(self): self.column_decoder_inst = self.add_inst(name="column_decoder", mod=self.column_decoder) - self.connect_inst(self.pins) + self.connect_inst(list(self.pins)) def create_layout(self): self.column_decoder_inst.place(vector(0,0)) diff --git a/compiler/modules/pbitcell.py b/compiler/modules/pbitcell.py index 2eab6e28..9c1800bd 100644 --- a/compiler/modules/pbitcell.py +++ b/compiler/modules/pbitcell.py @@ -1212,7 +1212,7 @@ class pbitcell(bitcell_base): if self.dummy_bitcell: return - pin_dict = {pin: port for pin, port in zip(self.pins, port_nets)} + pin_dict = {pin: port for pin, port in zip(list(self.pins), port_nets)} # Edges added wl->bl, wl->br for every port except write ports rw_pin_names = zip(self.r_wl_names, self.r_bl_names, self.r_br_names) From bfabe64f33f9fe230931b7d71edafcf3eed7781f Mon Sep 17 00:00:00 2001 From: Sam Crow Date: Tue, 18 Jul 2023 16:14:38 -0700 Subject: [PATCH 115/130] fix pin/net dictionary deepcopy-ing --- compiler/base/geometry.py | 14 +++++--- compiler/base/hierarchy_layout.py | 3 +- compiler/base/hierarchy_spice.py | 58 ++++++++++++++++++++++++++----- 3 files changed, 61 insertions(+), 14 deletions(-) diff --git a/compiler/base/geometry.py b/compiler/base/geometry.py index 9eedc7f5..d397f7a3 100644 --- a/compiler/base/geometry.py +++ b/compiler/base/geometry.py @@ -292,19 +292,25 @@ class instance(geometry): to both of their respective objects nets_list must be the same length as self.spice_pins """ + if len(nets_list) == 0 and len(self.spice_pins) == 0: + # this is the only valid case to skip the following debug check + # because this with no pins are often connected arbitrarily + self.connected = True + return debug.check(not self.connected, "instance {} has already been connected".format(self.name)) debug.check(len(self.spice_pins) == len(nets_list), "must provide list of nets the same length as pin list\ when connecting an instance") - for i in range(len(self.spice_pins)): - self.spice_pins[i].set_inst_net(nets_list[i]) - nets_list[i].connect_pin(self.spice_pins[i]) + for pin in self.spice_pins.values(): + net = nets_list.pop(0) + pin.set_inst_net(net) + net.connect_pin(pin) self.connected = True def get_connections(self): conns = [] - for pin in self.spice_pins: + for pin in self.spice_pins.values(): conns.append(pin.inst_net.name) return conns diff --git a/compiler/base/hierarchy_layout.py b/compiler/base/hierarchy_layout.py index d33d552d..f9d3e889 100644 --- a/compiler/base/hierarchy_layout.py +++ b/compiler/base/hierarchy_layout.py @@ -629,7 +629,7 @@ class layout(): """ Return a pin list of all pins """ - return self.pins + return list(self.pins) def copy_layout_pin(self, instance, pin_name, new_name="", relative_offset=vector(0, 0)): """ @@ -1523,6 +1523,7 @@ class layout(): """ Return the pin shapes as blockages for non-top-level blocks. """ # FIXME: We don't have a body contact in ptx, so just ignore it for now import copy + # FIXME: this may not work now that self.pins is a dict as defined in hierarchy_spice pin_names = copy.deepcopy(self.pins) if self.name.startswith("pmos") or self.name.startswith("nmos"): pin_names.remove("B") diff --git a/compiler/base/hierarchy_spice.py b/compiler/base/hierarchy_spice.py index 4803fb65..952fa080 100644 --- a/compiler/base/hierarchy_spice.py +++ b/compiler/base/hierarchy_spice.py @@ -90,13 +90,13 @@ class spice(): def add_pin(self, name, pin_type="INOUT"): """ Adds a pin to the pins list. Default type is INOUT signal. """ debug.check(name not in self.pins, "cannot add duplicate spice pin {}".format(name)) - self.pins[name] = pin_spice(name, pin_type) + self.pins[name] = pin_spice(name, pin_type, self) def add_pin_list(self, pin_list, pin_type="INOUT"): """ Adds a pin_list to the pins list """ # The pin type list can be a single type for all pins # or a list that is the same length as the pin list. - if type(pin_type) == str: + if isinstance(pin_type, str): for pin in pin_list: self.add_pin(pin, pin_type) @@ -124,7 +124,7 @@ class spice(): "{} spice subcircuit number of port types does not match number of pins\ \n pin names={}\n port types={}".format(self.name, list(self.pins), type_list)) for pin, type in zip(self.pins.values(), type_list): - pin.set_pin_type(type) + pin.set_type(type) def get_pin_type(self, name): """ Returns the type of the signal pin. """ @@ -212,7 +212,7 @@ class spice(): for name in names_list: # setdefault adds to the dict if it doesn't find the net in it already # then it returns the net it found or created, a net_spice object - net = self.nets.setdefault(name, net_spice(name)) + net = self.nets.setdefault(name, net_spice(name, self)) nets.append(net) return nets @@ -764,9 +764,10 @@ class pin_spice(): self.inst = inst def set_inst_net(self, net): - debug.check(self.inst_net is None, - "pin {} is already connected to net {} so it cannot also be connected to net {}\ - ".format(self.name, self.inst_net.name, net.name)) + if self.inst_net is not None: + debug.error("pin {} is already connected to net {}\ + so it cannot also be connected to net {}\ + ".format(self.name, self.inst_net.name, net.name), 1) debug.check(isinstance(net, net_spice), "net must be a net_spice object") self.inst_net = net @@ -789,6 +790,23 @@ class pin_spice(): """ return self._hash + def __deepcopy__(original, memo): + """ + This function is defined so that instances of modules can make deep + copies of their parent module's pins dictionary. It is only expected + to be called by the instance class __init__ function. Mod and mod_net + should not be deep copies but references to the existing mod and net + objects they refer to in the original. If inst is already defined this + function will throw an error because that means it was called on a pin + from an instance, which is not defined behavior. + """ + debug.check(original.inst is None, + "cannot make a deepcopy of a spice pin from an inst") + pin = pin_spice(original.name, original.type, original.mod) + if original.mod_net is not None: + pin.set_mod_net(original.mod_net) + return pin + class net_spice(): """ @@ -797,9 +815,10 @@ class net_spice(): inst is the instance this net is a part of, if any. """ - def __init__(self, name): + def __init__(self, name, mod): self.name = name self.pins = [] + self.mod = mod self.inst = None # TODO: evaluate if this makes sense... and works @@ -812,9 +831,12 @@ class net_spice(): else: self.pins.append(pin) + def set_inst(self, inst): + self.inst = inst + def __str__(self): """ override print function output """ - return "(pin_name={} type={})".format(self.name, self.type) + return "(net_name={} type={})".format(self.name, self.type) def __repr__(self): """ override repr function output """ @@ -830,3 +852,21 @@ class net_spice(): Provides a speedup if pin_spice is used as a key for dicts. """ return self._hash + + def __deepcopy__(original, memo): + """ + This function is defined so that instances of modules can make deep + copies of their parent module's nets dictionary. It is only expected + to be called by the instance class __init__ function. Mod and mod_net + should not be deep copies but references to the existing mod and net + objects they refer to in the original. If inst is already defined this + function will throw an error because that means it was called on a pin + from an instance, which is not defined behavior. + """ + debug.check(original.inst is None, + "cannot make a deepcopy of a spice net from an inst") + net = net_spice(original.name, original.mod) + if original.pins != []: + # TODO: honestly I'm not sure if this is right but we'll see... + net.pins = original.pins + return net From 2b9e70d318bdc6a2f69c7043512cf890c665a790 Mon Sep 17 00:00:00 2001 From: Sam Crow Date: Wed, 19 Jul 2023 10:51:19 -0700 Subject: [PATCH 116/130] remove line ending whitespace from comment --- compiler/base/geometry.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/base/geometry.py b/compiler/base/geometry.py index d397f7a3..c691db5d 100644 --- a/compiler/base/geometry.py +++ b/compiler/base/geometry.py @@ -179,7 +179,7 @@ class instance(geometry): # track if the instance's spice pin connections have been made self.connected = False - # deepcopy because this instance needs to + # deepcopy because this instance needs to # change attributes in these spice objects self.spice_pins = copy.deepcopy(self.mod.pins) self.spice_nets = copy.deepcopy(self.mod.nets) From 9fa25690ce0a9041457fd8435b483c9c69219e24 Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Wed, 19 Jul 2023 11:35:09 -0700 Subject: [PATCH 117/130] Added pins for spare_cols --- compiler/characterizer/fake_sram.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/compiler/characterizer/fake_sram.py b/compiler/characterizer/fake_sram.py index d1a97c33..07309295 100644 --- a/compiler/characterizer/fake_sram.py +++ b/compiler/characterizer/fake_sram.py @@ -71,11 +71,13 @@ class fake_sram(sram_config): OPTS.num_rw_ports + OPTS.num_r_ports + OPTS.num_w_ports)]) for port in range(OPTS.num_rw_ports): self.pins.extend(['din{0}[{1}]'.format(port, bit) - for bit in range(self.word_size)]) + for bit in range(self.word_size + self.num_spare_cols)]) self.pins.extend(['dout{0}[{1}]'.format(port, bit) - for bit in range(self.word_size)]) + for bit in range(self.word_size + self.num_spare_cols)]) self.pins.extend(['addr{0}[{1}]'.format(port, bit) for bit in range(self.addr_size)]) + self.pins.extend(['spare_wen{0}[{1}]'.format(port, bit) + for bit in range(self.num_spare_cols)]) if self.num_wmasks != 0: self.pins.extend(['wmask{0}[{1}]'.format(port, bit) for bit in range(self.num_wmasks)]) @@ -85,16 +87,18 @@ class fake_sram(sram_config): start_port = OPTS.num_rw_ports for port in range(start_port, start_port + OPTS.num_r_ports): self.pins.extend(['dout{0}[{1}]'.format(port, bit) - for bit in range(self.word_size)]) + for bit in range(self.word_size + self.num_spare_cols)]) self.pins.extend(['addr{0}[{1}]'.format(port, bit) - for bit in range(self.addr_size)]) + for bit in range(self.word_size)]) self.pins.extend(['csb{}'.format(port)]) start_port += OPTS.num_r_ports for port in range(start_port, start_port + OPTS.num_w_ports): self.pins.extend(['din{0}[{1}]'.format(port, bit) - for bit in range(self.word_size)]) + for bit in range(self.word_size + self.num_spare_cols)]) + self.pins.extend(['spare_wen{0}[{1}]'.format(port, bit) + for bit in range(self.num_spare_cols)]) self.pins.extend(['addr{0}[{1}]'.format(port, bit) for bit in range(self.addr_size)]) if self.num_wmasks != 0: From c67fdd8bd82e22b0a48776778609da974a25e6c7 Mon Sep 17 00:00:00 2001 From: Sam Crow Date: Wed, 19 Jul 2023 12:15:21 -0700 Subject: [PATCH 118/130] fix insts typo --- compiler/base/hierarchy_spice.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/base/hierarchy_spice.py b/compiler/base/hierarchy_spice.py index 952fa080..4eeaba93 100644 --- a/compiler/base/hierarchy_spice.py +++ b/compiler/base/hierarchy_spice.py @@ -693,7 +693,7 @@ class spice(): def get_instance_connections(self): conns = [] - for inst in self.instances: + for inst in self.insts: conns.append(inst.get_connections()) return conns From 2ced895b32d4750ee5c1268885d5d01e8ef421c0 Mon Sep 17 00:00:00 2001 From: Sam Crow Date: Wed, 19 Jul 2023 12:15:47 -0700 Subject: [PATCH 119/130] add BIAS pin type back to valid types --- compiler/base/hierarchy_spice.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/base/hierarchy_spice.py b/compiler/base/hierarchy_spice.py index 4eeaba93..acca174f 100644 --- a/compiler/base/hierarchy_spice.py +++ b/compiler/base/hierarchy_spice.py @@ -737,7 +737,7 @@ class pin_spice(): inst_net is the net object from mod's nets which connects to this pin. """ - valid_pin_types = ["INOUT", "INPUT", "OUTPUT", "POWER", "GROUND"] + valid_pin_types = ["INOUT", "INPUT", "OUTPUT", "POWER", "GROUND", "BIAS"] def __init__(self, name, type, mod): self.name = name From 6e3e964c1206fd98cc0fe10c5936064c2769c321 Mon Sep 17 00:00:00 2001 From: Sam Crow Date: Wed, 19 Jul 2023 12:45:41 -0700 Subject: [PATCH 120/130] cleanup net_spice docstrings --- compiler/base/hierarchy_spice.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/compiler/base/hierarchy_spice.py b/compiler/base/hierarchy_spice.py index e8fe532c..2294208e 100644 --- a/compiler/base/hierarchy_spice.py +++ b/compiler/base/hierarchy_spice.py @@ -816,6 +816,7 @@ class pin_spice(): class net_spice(): """ A class to represent a spice net. + mod is the parent module that created this net. pins are all the pins connected to this net. inst is the instance this net is a part of, if any. """ @@ -853,8 +854,9 @@ class net_spice(): def __hash__(self): """ Implement the hash function for sets etc. - Only hash name since spice does not allow two pins to share a name. - Provides a speedup if pin_spice is used as a key for dicts. + Only hash name since spice does not allow two nets to share a name + (on the same level of hierarchy, or rather they will be the same net). + Provides a speedup if net_spice is used as a key for dicts. """ return self._hash @@ -862,10 +864,10 @@ class net_spice(): """ This function is defined so that instances of modules can make deep copies of their parent module's nets dictionary. It is only expected - to be called by the instance class __init__ function. Mod and mod_net - should not be deep copies but references to the existing mod and net - objects they refer to in the original. If inst is already defined this - function will throw an error because that means it was called on a pin + to be called by the instance class __init__ function. Mod + should not be a deep copy but a reference to the existing mod + object it refers to in the original. If inst is already defined this + function will throw an error because that means it was called on a net from an instance, which is not defined behavior. """ debug.check(original.inst is None, From 0b2196a3e4f8a71e39c13a8b1be76c80d521a275 Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Wed, 19 Jul 2023 14:50:49 -0700 Subject: [PATCH 121/130] cleaned logs --- compiler/tests/b3v3_1check.log | 5 ----- compiler/tests/sram_1b_16_1rw_scn4m_subm.log | 2 -- 2 files changed, 7 deletions(-) delete mode 100644 compiler/tests/b3v3_1check.log delete mode 100644 compiler/tests/sram_1b_16_1rw_scn4m_subm.log diff --git a/compiler/tests/b3v3_1check.log b/compiler/tests/b3v3_1check.log deleted file mode 100644 index 6903570b..00000000 --- a/compiler/tests/b3v3_1check.log +++ /dev/null @@ -1,5 +0,0 @@ -BSIM3V3.1 Parameter Check -Model = p -W = 6e-07, L = 8e-07 -Warning: Pd = 0 is less than W. -Warning: Ps = 0 is less than W. diff --git a/compiler/tests/sram_1b_16_1rw_scn4m_subm.log b/compiler/tests/sram_1b_16_1rw_scn4m_subm.log deleted file mode 100644 index 0164bbb4..00000000 --- a/compiler/tests/sram_1b_16_1rw_scn4m_subm.log +++ /dev/null @@ -1,2 +0,0 @@ -ERROR: file magic.py: line 358: sram LVS mismatch (results in /tmp/openram_bugra_14157_temp/sram.lvs.report) - From 6751442d353b39d83434a02bedc9126bfb08f109 Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Wed, 19 Jul 2023 16:09:28 -0700 Subject: [PATCH 122/130] account for spare cols in char --- compiler/characterizer/delay.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index c1259cc0..cbf4f7a6 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -387,7 +387,7 @@ class delay(simulation): self.sf.write("\n* SRAM output loads\n") for port in self.read_ports: - for i in range(self.word_size): + for i in range(self.word_size + self.num_spare_cols): self.sf.write("CD{0}{1} {2}{0}_{1} 0 {3}f\n".format(port, i, self.dout_name, self.load)) def write_delay_stimulus(self): @@ -482,7 +482,7 @@ class delay(simulation): # generate data and addr signals self.sf.write("\n* Generation of data and address signals\n") for write_port in self.write_ports: - for i in range(self.word_size): + for i in range(self.word_size + self.num_spare_cols): self.stim.gen_constant(sig_name="{0}{1}_{2} ".format(self.din_name, write_port, i), v_val=0) for port in self.all_ports: @@ -1409,8 +1409,8 @@ class delay(simulation): inverse_address = self.calculate_inverse_address() # For now, ignore data patterns and write ones or zeros - data_ones = "1" * self.word_size - data_zeros = "0" * self.word_size + data_ones = "1" * (self.word_size + self.num_spare_cols) + data_zeros = "0" * (self.word_size + self.num_spare_cols) wmask_ones = "1" * self.num_wmasks if self.t_current == 0: @@ -1534,7 +1534,7 @@ class delay(simulation): """ Generates the PWL data inputs for a simulation timing test. """ for write_port in self.write_ports: - for i in range(self.word_size): + for i in range(self.word_size + self.num_spare_cols): sig_name="{0}{1}_{2} ".format(self.din_name, write_port, i) self.stim.gen_pwl(sig_name, self.cycle_times, self.data_values[write_port][i], self.period, self.slew, 0.05) From f246e5a521f53af8b2c208a1b6f267a50fc41454 Mon Sep 17 00:00:00 2001 From: vlsida-bot Date: Thu, 20 Jul 2023 01:33:51 +0000 Subject: [PATCH 123/130] Bump version: 1.2.22 -> 1.2.23 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 9a83513a..a93a6f75 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.2.22 +1.2.23 From f800b50813d84fb494d28551e8e97f7b65ed9aef Mon Sep 17 00:00:00 2001 From: mrg Date: Thu, 20 Jul 2023 10:11:49 -0700 Subject: [PATCH 124/130] Fix wrong bit size in fake_sram. --- compiler/characterizer/fake_sram.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/characterizer/fake_sram.py b/compiler/characterizer/fake_sram.py index 07309295..4dfa2f56 100644 --- a/compiler/characterizer/fake_sram.py +++ b/compiler/characterizer/fake_sram.py @@ -89,7 +89,7 @@ class fake_sram(sram_config): self.pins.extend(['dout{0}[{1}]'.format(port, bit) for bit in range(self.word_size + self.num_spare_cols)]) self.pins.extend(['addr{0}[{1}]'.format(port, bit) - for bit in range(self.word_size)]) + for bit in range(self.addr_size)]) self.pins.extend(['csb{}'.format(port)]) From 7aceadf9ba0ed934904e94a5cab131c828909d0a Mon Sep 17 00:00:00 2001 From: vlsida-bot Date: Thu, 20 Jul 2023 18:48:38 +0000 Subject: [PATCH 125/130] Bump version: 1.2.23 -> 1.2.24 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index a93a6f75..95a7a34a 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.2.23 +1.2.24 From 5b1544ad4528bf254c759cb4e976b282624ead41 Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Thu, 20 Jul 2023 15:18:32 -0700 Subject: [PATCH 126/130] Sky130 tests will use 1 spare row and col --- compiler/tests/configs/config_mem_char_func.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/compiler/tests/configs/config_mem_char_func.py b/compiler/tests/configs/config_mem_char_func.py index 767f2c75..8c0b09b9 100644 --- a/compiler/tests/configs/config_mem_char_func.py +++ b/compiler/tests/configs/config_mem_char_func.py @@ -10,6 +10,10 @@ word_size = 2 num_words = 16 tech_name = OPTS.tech_name +if tech_name == "sky130": + num_spare_cols = 1 + num_spare_rows = 1 + output_name = "sram" analytical_delay = False From 93182d525db264ef07bfd07bf25ae4edae73586b Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Thu, 20 Jul 2023 15:20:15 -0700 Subject: [PATCH 127/130] Added sky130 golden spice file --- compiler/tests/golden/sram_2_16_1_sky130.sp | 2400 +++++++++++++++++ compiler/tests/sp_files/sram_2_16_1_sky130.sp | 2400 +++++++++++++++++ 2 files changed, 4800 insertions(+) create mode 100644 compiler/tests/golden/sram_2_16_1_sky130.sp create mode 100644 compiler/tests/sp_files/sram_2_16_1_sky130.sp diff --git a/compiler/tests/golden/sram_2_16_1_sky130.sp b/compiler/tests/golden/sram_2_16_1_sky130.sp new file mode 100644 index 00000000..d68dde96 --- /dev/null +++ b/compiler/tests/golden/sram_2_16_1_sky130.sp @@ -0,0 +1,2400 @@ +************************************************** +* OpenRAM generated memory. +* Words: 16 +* Data bits: 2 +* Banks: 1 +* Column mux: 1:1 +* Trimmed: False +* LVS: False +************************************************** +* Copyright 2020 The SkyWater PDK Authors +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +* SPDX-License-Identifier: Apache-2.0 + +* SPICE3 file created from sky130_fd_bd_sram__openram_dff.ext - technology: EFS8A + +.subckt sky130_fd_bd_sram__openram_dff D Q CLK VDD GND +X1000 a_511_725# a_n8_115# VDD VDD sky130_fd_pr__pfet_01v8 W=3 L=0.15 +X1001 a_353_115# CLK a_11_624# GND sky130_fd_pr__nfet_01v8 W=1 L=0.15 +X1002 a_353_725# a_203_89# a_11_624# VDD sky130_fd_pr__pfet_01v8 W=3 L=0.15 +X1003 a_11_624# a_203_89# a_161_115# GND sky130_fd_pr__nfet_01v8 W=1 L=0.15 +X1004 a_11_624# CLK a_161_725# VDD sky130_fd_pr__pfet_01v8 W=3 L=0.15 +X1005 GND Q a_703_115# GND sky130_fd_pr__nfet_01v8 W=1 L=0.15 +X1006 VDD Q a_703_725# VDD sky130_fd_pr__pfet_01v8 W=3 L=0.15 +X1007 a_203_89# CLK GND GND sky130_fd_pr__nfet_01v8 W=1 L=0.15 +X1008 a_203_89# CLK VDD VDD sky130_fd_pr__pfet_01v8 W=3 L=0.15 +X1009 a_161_115# D GND GND sky130_fd_pr__nfet_01v8 W=1 L=0.15 +X1010 a_161_725# D VDD VDD sky130_fd_pr__pfet_01v8 W=3 L=0.15 +X1011 GND a_11_624# a_n8_115# GND sky130_fd_pr__nfet_01v8 W=1 L=0.15 +X1012 a_703_115# a_203_89# ON GND sky130_fd_pr__nfet_01v8 W=1 L=0.15 +X1013 VDD a_11_624# a_n8_115# VDD sky130_fd_pr__pfet_01v8 W=3 L=0.15 +X1014 a_703_725# CLK ON VDD sky130_fd_pr__pfet_01v8 W=3 L=0.15 +X1015 Q ON VDD VDD sky130_fd_pr__pfet_01v8 W=3 L=0.15 +X1016 Q ON GND GND sky130_fd_pr__nfet_01v8 W=1 L=0.15 +X1017 ON a_203_89# a_511_725# VDD sky130_fd_pr__pfet_01v8 W=3 L=0.15 +X1018 ON CLK a_511_115# GND sky130_fd_pr__nfet_01v8 W=1 L=0.15 +X1019 GND a_n8_115# a_353_115# GND sky130_fd_pr__nfet_01v8 W=1 L=0.15 +X1020 VDD a_n8_115# a_353_725# VDD sky130_fd_pr__pfet_01v8 W=3 L=0.15 +X1021 a_511_115# a_n8_115# GND GND sky130_fd_pr__nfet_01v8 W=1 L=0.15 +.ends + +.SUBCKT sram_2_16_1_sky130_row_addr_dff ++ din_0 din_1 din_2 din_3 din_4 dout_0 dout_1 dout_2 dout_3 dout_4 clk ++ vdd gnd +* INPUT : din_0 +* INPUT : din_1 +* INPUT : din_2 +* INPUT : din_3 +* INPUT : din_4 +* OUTPUT: dout_0 +* OUTPUT: dout_1 +* OUTPUT: dout_2 +* OUTPUT: dout_3 +* OUTPUT: dout_4 +* INPUT : clk +* POWER : vdd +* GROUND: gnd +* rows: 5 cols: 1 +Xdff_r0_c0 ++ din_0 dout_0 CLK VDD GND ++ sky130_fd_bd_sram__openram_dff +Xdff_r1_c0 ++ din_1 dout_1 CLK VDD GND ++ sky130_fd_bd_sram__openram_dff +Xdff_r2_c0 ++ din_2 dout_2 CLK VDD GND ++ sky130_fd_bd_sram__openram_dff +Xdff_r3_c0 ++ din_3 dout_3 CLK VDD GND ++ sky130_fd_bd_sram__openram_dff +Xdff_r4_c0 ++ din_4 dout_4 CLK VDD GND ++ sky130_fd_bd_sram__openram_dff +.ENDS sram_2_16_1_sky130_row_addr_dff + +.SUBCKT sram_2_16_1_sky130_data_dff ++ din_0 din_1 din_2 dout_0 dout_1 dout_2 clk vdd gnd +* INPUT : din_0 +* INPUT : din_1 +* INPUT : din_2 +* OUTPUT: dout_0 +* OUTPUT: dout_1 +* OUTPUT: dout_2 +* INPUT : clk +* POWER : vdd +* GROUND: gnd +* rows: 1 cols: 3 +Xdff_r0_c0 ++ din_0 dout_0 CLK VDD GND ++ sky130_fd_bd_sram__openram_dff +Xdff_r0_c1 ++ din_1 dout_1 CLK VDD GND ++ sky130_fd_bd_sram__openram_dff +Xdff_r0_c2 ++ din_2 dout_2 CLK VDD GND ++ sky130_fd_bd_sram__openram_dff +.ENDS sram_2_16_1_sky130_data_dff + +* spice ptx X{0} {1} sky130_fd_pr__nfet_01v8 m=1 w=0.36 l=0.15 pd=1.02 ps=1.02 as=0.14u ad=0.14u + +* spice ptx X{0} {1} sky130_fd_pr__pfet_01v8 m=1 w=1.12 l=0.15 pd=2.54 ps=2.54 as=0.42u ad=0.42u + +.SUBCKT sram_2_16_1_sky130_pinv_dec ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* size: 1 +Xpinv_pmos Z A vdd vdd sky130_fd_pr__pfet_01v8 m=1 w=1.12 l=0.15 pd=2.54 ps=2.54 as=0.42u ad=0.42u +Xpinv_nmos Z A gnd gnd sky130_fd_pr__nfet_01v8 m=1 w=0.36 l=0.15 pd=1.02 ps=1.02 as=0.14u ad=0.14u +.ENDS sram_2_16_1_sky130_pinv_dec +* Copyright 2020 The SkyWater PDK Authors +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +* SPDX-License-Identifier: Apache-2.0 + +* NGSPICE file created from sky130_fd_bd_sram__openram_sp_nand2_dec.ext - technology: EFS8A + + +* Top level circuit sky130_fd_bd_sram__openram_sp_nand2_dec +.subckt sky130_fd_bd_sram__openram_sp_nand2_dec A B Z VDD GND + +X1001 Z B VDD VDD sky130_fd_pr__pfet_01v8 W=1.12 L=0.15 +X1002 VDD A Z VDD sky130_fd_pr__pfet_01v8 W=1.12 L=0.15 +X1000 Z A a_n722_276# GND sky130_fd_pr__nfet_01v8 W=0.74 L=0.15 +X1003 a_n722_276# B GND GND sky130_fd_pr__nfet_01v8 W=0.74 L=0.15 +.ends + + +.SUBCKT sram_2_16_1_sky130_and2_dec ++ A B Z vdd gnd +* INPUT : A +* INPUT : B +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* size: 1 +Xpand2_dec_nand ++ A B zb_int vdd gnd ++ sky130_fd_bd_sram__openram_sp_nand2_dec +Xpand2_dec_inv ++ zb_int Z vdd gnd ++ sram_2_16_1_sky130_pinv_dec +.ENDS sram_2_16_1_sky130_and2_dec + +.SUBCKT sram_2_16_1_sky130_hierarchical_predecode2x4 ++ in_0 in_1 out_0 out_1 out_2 out_3 vdd gnd +* INPUT : in_0 +* INPUT : in_1 +* OUTPUT: out_0 +* OUTPUT: out_1 +* OUTPUT: out_2 +* OUTPUT: out_3 +* POWER : vdd +* GROUND: gnd +Xpre_inv_0 ++ in_0 inbar_0 vdd gnd ++ sram_2_16_1_sky130_pinv_dec +Xpre_inv_1 ++ in_1 inbar_1 vdd gnd ++ sram_2_16_1_sky130_pinv_dec +XXpre2x4_and_0 ++ inbar_0 inbar_1 out_0 vdd gnd ++ sram_2_16_1_sky130_and2_dec +XXpre2x4_and_1 ++ in_0 inbar_1 out_1 vdd gnd ++ sram_2_16_1_sky130_and2_dec +XXpre2x4_and_2 ++ inbar_0 in_1 out_2 vdd gnd ++ sram_2_16_1_sky130_and2_dec +XXpre2x4_and_3 ++ in_0 in_1 out_3 vdd gnd ++ sram_2_16_1_sky130_and2_dec +.ENDS sram_2_16_1_sky130_hierarchical_predecode2x4 +* Copyright 2020 The SkyWater PDK Authors +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +* SPDX-License-Identifier: Apache-2.0 + +* NGSPICE file created from sky130_fd_bd_sram__openram_sp_nand3_dec.ext - technology: EFS8A + + +* Top level circuit sky130_fd_bd_sram__openram_sp_nand3_dec +.subckt sky130_fd_bd_sram__openram_sp_nand3_dec A B C Z VDD GND + +X1001 Z A a_n346_328# GND sky130_fd_pr__nfet_01v8 W=0.74 L=0.15 +X1002 a_n346_256# C GND GND sky130_fd_pr__nfet_01v8 W=0.74 L=0.15 +X1003 a_n346_328# B a_n346_256# GND sky130_fd_pr__nfet_01v8 W=0.74 L=0.15 +X1000 Z B VDD VDD sky130_fd_pr__pfet_01v8 W=1.12 L=0.15 +X1004 Z A VDD VDD sky130_fd_pr__pfet_01v8 W=1.12 L=0.15 +X1005 Z C VDD VDD sky130_fd_pr__pfet_01v8 W=1.12 L=0.15 +.ends + + +.SUBCKT sram_2_16_1_sky130_and3_dec ++ A B C Z vdd gnd +* INPUT : A +* INPUT : B +* INPUT : C +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* size: 1 +Xpand3_dec_nand ++ A B C zb_int vdd gnd ++ sky130_fd_bd_sram__openram_sp_nand3_dec +Xpand3_dec_inv ++ zb_int Z vdd gnd ++ sram_2_16_1_sky130_pinv_dec +.ENDS sram_2_16_1_sky130_and3_dec + +.SUBCKT sram_2_16_1_sky130_hierarchical_predecode3x8 ++ in_0 in_1 in_2 out_0 out_1 out_2 out_3 out_4 out_5 out_6 out_7 vdd gnd +* INPUT : in_0 +* INPUT : in_1 +* INPUT : in_2 +* OUTPUT: out_0 +* OUTPUT: out_1 +* OUTPUT: out_2 +* OUTPUT: out_3 +* OUTPUT: out_4 +* OUTPUT: out_5 +* OUTPUT: out_6 +* OUTPUT: out_7 +* POWER : vdd +* GROUND: gnd +Xpre_inv_0 ++ in_0 inbar_0 vdd gnd ++ sram_2_16_1_sky130_pinv_dec +Xpre_inv_1 ++ in_1 inbar_1 vdd gnd ++ sram_2_16_1_sky130_pinv_dec +Xpre_inv_2 ++ in_2 inbar_2 vdd gnd ++ sram_2_16_1_sky130_pinv_dec +XXpre3x8_and_0 ++ inbar_0 inbar_1 inbar_2 out_0 vdd gnd ++ sram_2_16_1_sky130_and3_dec +XXpre3x8_and_1 ++ in_0 inbar_1 inbar_2 out_1 vdd gnd ++ sram_2_16_1_sky130_and3_dec +XXpre3x8_and_2 ++ inbar_0 in_1 inbar_2 out_2 vdd gnd ++ sram_2_16_1_sky130_and3_dec +XXpre3x8_and_3 ++ in_0 in_1 inbar_2 out_3 vdd gnd ++ sram_2_16_1_sky130_and3_dec +XXpre3x8_and_4 ++ inbar_0 inbar_1 in_2 out_4 vdd gnd ++ sram_2_16_1_sky130_and3_dec +XXpre3x8_and_5 ++ in_0 inbar_1 in_2 out_5 vdd gnd ++ sram_2_16_1_sky130_and3_dec +XXpre3x8_and_6 ++ inbar_0 in_1 in_2 out_6 vdd gnd ++ sram_2_16_1_sky130_and3_dec +XXpre3x8_and_7 ++ in_0 in_1 in_2 out_7 vdd gnd ++ sram_2_16_1_sky130_and3_dec +.ENDS sram_2_16_1_sky130_hierarchical_predecode3x8 + +.SUBCKT sram_2_16_1_sky130_hierarchical_decoder ++ addr_0 addr_1 addr_2 addr_3 addr_4 decode_0 decode_1 decode_2 decode_3 ++ decode_4 decode_5 decode_6 decode_7 decode_8 decode_9 decode_10 ++ decode_11 decode_12 decode_13 decode_14 decode_15 decode_16 vdd gnd +* INPUT : addr_0 +* INPUT : addr_1 +* INPUT : addr_2 +* INPUT : addr_3 +* INPUT : addr_4 +* OUTPUT: decode_0 +* OUTPUT: decode_1 +* OUTPUT: decode_2 +* OUTPUT: decode_3 +* OUTPUT: decode_4 +* OUTPUT: decode_5 +* OUTPUT: decode_6 +* OUTPUT: decode_7 +* OUTPUT: decode_8 +* OUTPUT: decode_9 +* OUTPUT: decode_10 +* OUTPUT: decode_11 +* OUTPUT: decode_12 +* OUTPUT: decode_13 +* OUTPUT: decode_14 +* OUTPUT: decode_15 +* OUTPUT: decode_16 +* POWER : vdd +* GROUND: gnd +Xpre_0 ++ addr_0 addr_1 out_0 out_1 out_2 out_3 vdd gnd ++ sram_2_16_1_sky130_hierarchical_predecode2x4 +Xpre3x8_0 ++ addr_2 addr_3 addr_4 out_4 out_5 out_6 out_7 out_8 out_9 out_10 out_11 ++ vdd gnd ++ sram_2_16_1_sky130_hierarchical_predecode3x8 +XDEC_AND_0 ++ out_0 out_4 decode_0 vdd gnd ++ sram_2_16_1_sky130_and2_dec +XDEC_AND_4 ++ out_0 out_5 decode_4 vdd gnd ++ sram_2_16_1_sky130_and2_dec +XDEC_AND_8 ++ out_0 out_6 decode_8 vdd gnd ++ sram_2_16_1_sky130_and2_dec +XDEC_AND_12 ++ out_0 out_7 decode_12 vdd gnd ++ sram_2_16_1_sky130_and2_dec +XDEC_AND_16 ++ out_0 out_8 decode_16 vdd gnd ++ sram_2_16_1_sky130_and2_dec +XDEC_AND_1 ++ out_1 out_4 decode_1 vdd gnd ++ sram_2_16_1_sky130_and2_dec +XDEC_AND_5 ++ out_1 out_5 decode_5 vdd gnd ++ sram_2_16_1_sky130_and2_dec +XDEC_AND_9 ++ out_1 out_6 decode_9 vdd gnd ++ sram_2_16_1_sky130_and2_dec +XDEC_AND_13 ++ out_1 out_7 decode_13 vdd gnd ++ sram_2_16_1_sky130_and2_dec +XDEC_AND_2 ++ out_2 out_4 decode_2 vdd gnd ++ sram_2_16_1_sky130_and2_dec +XDEC_AND_6 ++ out_2 out_5 decode_6 vdd gnd ++ sram_2_16_1_sky130_and2_dec +XDEC_AND_10 ++ out_2 out_6 decode_10 vdd gnd ++ sram_2_16_1_sky130_and2_dec +XDEC_AND_14 ++ out_2 out_7 decode_14 vdd gnd ++ sram_2_16_1_sky130_and2_dec +XDEC_AND_3 ++ out_3 out_4 decode_3 vdd gnd ++ sram_2_16_1_sky130_and2_dec +XDEC_AND_7 ++ out_3 out_5 decode_7 vdd gnd ++ sram_2_16_1_sky130_and2_dec +XDEC_AND_11 ++ out_3 out_6 decode_11 vdd gnd ++ sram_2_16_1_sky130_and2_dec +XDEC_AND_15 ++ out_3 out_7 decode_15 vdd gnd ++ sram_2_16_1_sky130_and2_dec +.ENDS sram_2_16_1_sky130_hierarchical_decoder + +.SUBCKT sram_2_16_1_sky130_and2_dec_0 ++ A B Z vdd gnd +* INPUT : A +* INPUT : B +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* size: 1 +Xpand2_dec_nand ++ A B zb_int vdd gnd ++ sky130_fd_bd_sram__openram_sp_nand2_dec +Xpand2_dec_inv ++ zb_int Z vdd gnd ++ sram_2_16_1_sky130_pinv_dec +.ENDS sram_2_16_1_sky130_and2_dec_0 + +.SUBCKT sram_2_16_1_sky130_wordline_driver ++ A B Z vdd gnd +* INPUT : A +* INPUT : B +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* cols: 3 +Xwld_nand ++ A B zb_int vdd gnd ++ sky130_fd_bd_sram__openram_sp_nand2_dec +Xwl_driver ++ zb_int Z vdd gnd ++ sram_2_16_1_sky130_pinv_dec +.ENDS sram_2_16_1_sky130_wordline_driver + +.SUBCKT sram_2_16_1_sky130_wordline_driver_array ++ in_0 in_1 in_2 in_3 in_4 in_5 in_6 in_7 in_8 in_9 in_10 in_11 in_12 ++ in_13 in_14 in_15 in_16 wl_0 wl_1 wl_2 wl_3 wl_4 wl_5 wl_6 wl_7 wl_8 ++ wl_9 wl_10 wl_11 wl_12 wl_13 wl_14 wl_15 wl_16 en vdd gnd +* INPUT : in_0 +* INPUT : in_1 +* INPUT : in_2 +* INPUT : in_3 +* INPUT : in_4 +* INPUT : in_5 +* INPUT : in_6 +* INPUT : in_7 +* INPUT : in_8 +* INPUT : in_9 +* INPUT : in_10 +* INPUT : in_11 +* INPUT : in_12 +* INPUT : in_13 +* INPUT : in_14 +* INPUT : in_15 +* INPUT : in_16 +* OUTPUT: wl_0 +* OUTPUT: wl_1 +* OUTPUT: wl_2 +* OUTPUT: wl_3 +* OUTPUT: wl_4 +* OUTPUT: wl_5 +* OUTPUT: wl_6 +* OUTPUT: wl_7 +* OUTPUT: wl_8 +* OUTPUT: wl_9 +* OUTPUT: wl_10 +* OUTPUT: wl_11 +* OUTPUT: wl_12 +* OUTPUT: wl_13 +* OUTPUT: wl_14 +* OUTPUT: wl_15 +* OUTPUT: wl_16 +* INPUT : en +* POWER : vdd +* GROUND: gnd +* rows: 17 cols: 3 +Xwl_driver_and0 ++ in_0 en wl_0 vdd gnd ++ sram_2_16_1_sky130_wordline_driver +Xwl_driver_and1 ++ in_1 en wl_1 vdd gnd ++ sram_2_16_1_sky130_wordline_driver +Xwl_driver_and2 ++ in_2 en wl_2 vdd gnd ++ sram_2_16_1_sky130_wordline_driver +Xwl_driver_and3 ++ in_3 en wl_3 vdd gnd ++ sram_2_16_1_sky130_wordline_driver +Xwl_driver_and4 ++ in_4 en wl_4 vdd gnd ++ sram_2_16_1_sky130_wordline_driver +Xwl_driver_and5 ++ in_5 en wl_5 vdd gnd ++ sram_2_16_1_sky130_wordline_driver +Xwl_driver_and6 ++ in_6 en wl_6 vdd gnd ++ sram_2_16_1_sky130_wordline_driver +Xwl_driver_and7 ++ in_7 en wl_7 vdd gnd ++ sram_2_16_1_sky130_wordline_driver +Xwl_driver_and8 ++ in_8 en wl_8 vdd gnd ++ sram_2_16_1_sky130_wordline_driver +Xwl_driver_and9 ++ in_9 en wl_9 vdd gnd ++ sram_2_16_1_sky130_wordline_driver +Xwl_driver_and10 ++ in_10 en wl_10 vdd gnd ++ sram_2_16_1_sky130_wordline_driver +Xwl_driver_and11 ++ in_11 en wl_11 vdd gnd ++ sram_2_16_1_sky130_wordline_driver +Xwl_driver_and12 ++ in_12 en wl_12 vdd gnd ++ sram_2_16_1_sky130_wordline_driver +Xwl_driver_and13 ++ in_13 en wl_13 vdd gnd ++ sram_2_16_1_sky130_wordline_driver +Xwl_driver_and14 ++ in_14 en wl_14 vdd gnd ++ sram_2_16_1_sky130_wordline_driver +Xwl_driver_and15 ++ in_15 en wl_15 vdd gnd ++ sram_2_16_1_sky130_wordline_driver +Xwl_driver_and16 ++ in_16 en wl_16 vdd gnd ++ sram_2_16_1_sky130_wordline_driver +.ENDS sram_2_16_1_sky130_wordline_driver_array + +.SUBCKT sram_2_16_1_sky130_port_address ++ addr_0 addr_1 addr_2 addr_3 addr_4 wl_en wl_0 wl_1 wl_2 wl_3 wl_4 wl_5 ++ wl_6 wl_7 wl_8 wl_9 wl_10 wl_11 wl_12 wl_13 wl_14 wl_15 wl_16 rbl_wl ++ vdd gnd +* INPUT : addr_0 +* INPUT : addr_1 +* INPUT : addr_2 +* INPUT : addr_3 +* INPUT : addr_4 +* INPUT : wl_en +* OUTPUT: wl_0 +* OUTPUT: wl_1 +* OUTPUT: wl_2 +* OUTPUT: wl_3 +* OUTPUT: wl_4 +* OUTPUT: wl_5 +* OUTPUT: wl_6 +* OUTPUT: wl_7 +* OUTPUT: wl_8 +* OUTPUT: wl_9 +* OUTPUT: wl_10 +* OUTPUT: wl_11 +* OUTPUT: wl_12 +* OUTPUT: wl_13 +* OUTPUT: wl_14 +* OUTPUT: wl_15 +* OUTPUT: wl_16 +* OUTPUT: rbl_wl +* POWER : vdd +* GROUND: gnd +Xrow_decoder ++ addr_0 addr_1 addr_2 addr_3 addr_4 dec_out_0 dec_out_1 dec_out_2 ++ dec_out_3 dec_out_4 dec_out_5 dec_out_6 dec_out_7 dec_out_8 dec_out_9 ++ dec_out_10 dec_out_11 dec_out_12 dec_out_13 dec_out_14 dec_out_15 ++ dec_out_16 vdd gnd ++ sram_2_16_1_sky130_hierarchical_decoder +Xwordline_driver ++ dec_out_0 dec_out_1 dec_out_2 dec_out_3 dec_out_4 dec_out_5 dec_out_6 ++ dec_out_7 dec_out_8 dec_out_9 dec_out_10 dec_out_11 dec_out_12 ++ dec_out_13 dec_out_14 dec_out_15 dec_out_16 wl_0 wl_1 wl_2 wl_3 wl_4 ++ wl_5 wl_6 wl_7 wl_8 wl_9 wl_10 wl_11 wl_12 wl_13 wl_14 wl_15 wl_16 ++ wl_en vdd gnd ++ sram_2_16_1_sky130_wordline_driver_array +Xrbl_driver ++ wl_en vdd rbl_wl vdd gnd ++ sram_2_16_1_sky130_and2_dec_0 +.ENDS sram_2_16_1_sky130_port_address +* NGSPICE file created from sky130_fd_bd_sram__sram_sp_colenda_cent.ext - technology: sky130A + +.subckt sky130_fd_bd_sram__sram_sp_colenda_cent VPWR VPB VNB +.ends +* NGSPICE file created from sky130_fd_bd_sram__sram_sp_colenda.ext - technology: sky130A + +.subckt sky130_fd_bd_sram__sram_sp_colenda bl vdd gnd br gate vpb vnb +*X0 br gate br vnb sky130_fd_pr__special_nfet_pass w=0.065u l=0.17u +.ends + +* NGSPICE file created from sky130_fd_bd_sram__sram_sp_colenda_p_cent.ext - technology: sky130A + +.subckt sky130_fd_bd_sram__sram_sp_colenda_p_cent VGND VPB VNB +.ends + +.SUBCKT sram_2_16_1_sky130_sky130_col_cap_array_0 ++ fake_bl_0 fake_br_0 fake_bl_1 fake_br_1 fake_bl_2 fake_br_2 vdd gnd ++ gate +* OUTPUT: fake_bl_0 +* OUTPUT: fake_br_0 +* OUTPUT: fake_bl_1 +* OUTPUT: fake_br_1 +* OUTPUT: fake_bl_2 +* OUTPUT: fake_br_2 +* POWER : vdd +* GROUND: gnd +* BIAS : gate +Xrca_bottom_0 ++ fake_bl_0 vdd gnd fake_br_0 gate vdd gnd ++ sky130_fd_bd_sram__sram_sp_colenda +Xrca_bottom_1 ++ vdd vdd gnd ++ sky130_fd_bd_sram__sram_sp_colenda_cent +Xrca_bottom_2 ++ fake_bl_1 vdd gnd fake_br_1 gate vdd gnd ++ sky130_fd_bd_sram__sram_sp_colenda +Xrca_bottom_3 ++ gnd vdd vnb ++ sky130_fd_bd_sram__sram_sp_colenda_p_cent +Xrca_bottom_4 ++ fake_bl_2 vdd gnd fake_br_2 gate vdd gnd ++ sky130_fd_bd_sram__sram_sp_colenda +.ENDS sram_2_16_1_sky130_sky130_col_cap_array_0 +* NGSPICE file created from sky130_fd_bd_sram__sram_sp_wlstrap_p.ext - technology: sky130A + +.subckt sky130_fd_bd_sram__sram_sp_wlstrap_p VGND +.ends +* NGSPICE file created from sky130_fd_bd_sram__openram_sp_cell_opt1a_replica.ext - technology: sky130A + +.subckt sky130_fd_bd_sram__openram_sp_cell_opt1a_replica BL BR VGND VPWR VPB VNB WL +X0 VPWR WL BR VNB sky130_fd_pr__special_nfet_pass ad=4.375e+10p pd=920000u as=1.68e+10p ps=520000u w=140000u l=150000u +X1 Q VPWR VGND VNB sky130_fd_pr__special_nfet_latch ad=1.56e+11p pd=2.38e+06u as=8.08e+10p ps=1.28e+06u w=210000u l=150000u +X2 BL WL Q VNB sky130_fd_pr__special_nfet_pass ad=1.68e+10p pd=520000u as=4.25e+10p ps=920000u w=140000u l=150000u +*X3 Q WL Q VPB sky130_fd_pr__special_pfet_pass ad=3.5e+10p pd=780000u as=0p ps=0u w=70000u l=95000u +*X4 VPWR WL VPWR VPB sky130_fd_pr__special_pfet_pass ad=9.72e+10p pd=1.86e+06u as=0p ps=0u w=70000u l=95000u +X5 VPWR Q VPWR VPB sky130_fd_pr__special_pfet_pass ad=0p pd=0u as=0p ps=0u w=140000u l=150000u +X6 Q VPWR VPWR VPB sky130_fd_pr__special_pfet_pass ad=0p pd=0u as=0p ps=0u w=140000u l=150000u +X7 VGND Q VPWR VNB sky130_fd_pr__special_nfet_latch ad=0p pd=0u as=0p ps=0u w=210000u l=150000u +.ends +* NGSPICE file created from sky130_fd_bd_sram__sram_sp_colend_p_cent.ext - technology: sky130A + +.subckt sky130_fd_bd_sram__sram_sp_colend_p_cent VGND VPB VNB +.ends +* NGSPICE file created from sky130_fd_bd_sram__sram_sp_wlstrapa_p.ext - technology: sky130A + +.subckt sky130_fd_bd_sram__sram_sp_wlstrapa_p VGND +.ends +* NGSPICE file created from sky130_fd_bd_sram__openram_sp_cell_opt1_replica.ext - technology: sky130A + +.subckt sky130_fd_bd_sram__openram_sp_cell_opt1_replica BL BR VGND VPWR VPB VNB WL +X0 VPWR WL BR VNB sky130_fd_pr__special_nfet_pass ad=4.375e+10p pd=920000u as=1.68e+10p ps=520000u w=140000u l=150000u +X1 Q VPWR VGND VNB sky130_fd_pr__special_nfet_latch ad=1.56e+11p pd=2.38e+06u as=8.08e+10p ps=1.28e+06u w=210000u l=150000u +X2 BL WL Q VNB sky130_fd_pr__special_nfet_pass ad=1.68e+10p pd=520000u as=4.25e+10p ps=920000u w=140000u l=150000u +*X3 Q WL Q VPB sky130_fd_pr__special_pfet_pass ad=3.5e+10p pd=780000u as=0p ps=0u w=70000u l=95000u +*X4 VPWR WL VPWR VPB sky130_fd_pr__special_pfet_pass ad=9.72e+10p pd=1.86e+06u as=0p ps=0u w=70000u l=95000u +X5 VPWR Q VPWR VPB sky130_fd_pr__special_pfet_pass ad=0p pd=0u as=0p ps=0u w=140000u l=150000u +X6 Q VPWR VPWR VPB sky130_fd_pr__special_pfet_pass ad=0p pd=0u as=0p ps=0u w=140000u l=150000u +X7 VGND Q VPWR VNB sky130_fd_pr__special_nfet_latch ad=0p pd=0u as=0p ps=0u w=210000u l=150000u +.ends +* NGSPICE file created from sky130_fd_bd_sram__sram_sp_colend.ext - technology: sky130A + +.subckt sky130_fd_bd_sram__sram_sp_colend bl vdd gnd br gate vpb vnb +*X0 br gate br vnb sky130_fd_pr__special_nfet_pass w=0.07u l=0.21u +.ends + + +.SUBCKT sram_2_16_1_sky130_sky130_replica_column ++ bl_0_0 br_0_0 wl_0_1 wl_0_2 wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 wl_0_8 ++ wl_0_9 wl_0_10 wl_0_11 wl_0_12 wl_0_13 wl_0_14 wl_0_15 wl_0_16 wl_0_17 ++ wl_0_18 vdd gnd top_gate bot_gate +* OUTPUT: bl_0_0 +* OUTPUT: br_0_0 +* INPUT : wl_0_1 +* INPUT : wl_0_2 +* INPUT : wl_0_3 +* INPUT : wl_0_4 +* INPUT : wl_0_5 +* INPUT : wl_0_6 +* INPUT : wl_0_7 +* INPUT : wl_0_8 +* INPUT : wl_0_9 +* INPUT : wl_0_10 +* INPUT : wl_0_11 +* INPUT : wl_0_12 +* INPUT : wl_0_13 +* INPUT : wl_0_14 +* INPUT : wl_0_15 +* INPUT : wl_0_16 +* INPUT : wl_0_17 +* INPUT : wl_0_18 +* POWER : vdd +* GROUND: gnd +* INPUT : top_gate +* INPUT : bot_gate +Xrbc_0 ++ bl_0_0 vdd gnd br_0_0 top_gate vdd gnd ++ sky130_fd_bd_sram__sram_sp_colend +Xrbc_0_cap ++ gnd vdd gnd ++ sky130_fd_bd_sram__sram_sp_colend_p_cent +Xrbc_1 ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_1 ++ sky130_fd_bd_sram__openram_sp_cell_opt1_replica +Xrbc_1_strap_p ++ gnd ++ sky130_fd_bd_sram__sram_sp_wlstrap_p +Xrbc_2 ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_2 ++ sky130_fd_bd_sram__openram_sp_cell_opt1a_replica +Xrbc_2_strap ++ vdd ++ sky130_fd_bd_sram__sram_sp_wlstrapa_p +Xrbc_3 ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_3 ++ sky130_fd_bd_sram__openram_sp_cell_opt1_replica +Xrbc_3_strap_p ++ gnd ++ sky130_fd_bd_sram__sram_sp_wlstrap_p +Xrbc_4 ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_4 ++ sky130_fd_bd_sram__openram_sp_cell_opt1a_replica +Xrbc_4_strap ++ vdd ++ sky130_fd_bd_sram__sram_sp_wlstrapa_p +Xrbc_5 ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_5 ++ sky130_fd_bd_sram__openram_sp_cell_opt1_replica +Xrbc_5_strap_p ++ gnd ++ sky130_fd_bd_sram__sram_sp_wlstrap_p +Xrbc_6 ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_6 ++ sky130_fd_bd_sram__openram_sp_cell_opt1a_replica +Xrbc_6_strap ++ vdd ++ sky130_fd_bd_sram__sram_sp_wlstrapa_p +Xrbc_7 ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_7 ++ sky130_fd_bd_sram__openram_sp_cell_opt1_replica +Xrbc_7_strap_p ++ gnd ++ sky130_fd_bd_sram__sram_sp_wlstrap_p +Xrbc_8 ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_8 ++ sky130_fd_bd_sram__openram_sp_cell_opt1a_replica +Xrbc_8_strap ++ vdd ++ sky130_fd_bd_sram__sram_sp_wlstrapa_p +Xrbc_9 ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_9 ++ sky130_fd_bd_sram__openram_sp_cell_opt1_replica +Xrbc_9_strap_p ++ gnd ++ sky130_fd_bd_sram__sram_sp_wlstrap_p +Xrbc_10 ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_10 ++ sky130_fd_bd_sram__openram_sp_cell_opt1a_replica +Xrbc_10_strap ++ vdd ++ sky130_fd_bd_sram__sram_sp_wlstrapa_p +Xrbc_11 ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_11 ++ sky130_fd_bd_sram__openram_sp_cell_opt1_replica +Xrbc_11_strap_p ++ gnd ++ sky130_fd_bd_sram__sram_sp_wlstrap_p +Xrbc_12 ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_12 ++ sky130_fd_bd_sram__openram_sp_cell_opt1a_replica +Xrbc_12_strap ++ vdd ++ sky130_fd_bd_sram__sram_sp_wlstrapa_p +Xrbc_13 ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_13 ++ sky130_fd_bd_sram__openram_sp_cell_opt1_replica +Xrbc_13_strap_p ++ gnd ++ sky130_fd_bd_sram__sram_sp_wlstrap_p +Xrbc_14 ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_14 ++ sky130_fd_bd_sram__openram_sp_cell_opt1a_replica +Xrbc_14_strap ++ vdd ++ sky130_fd_bd_sram__sram_sp_wlstrapa_p +Xrbc_15 ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_15 ++ sky130_fd_bd_sram__openram_sp_cell_opt1_replica +Xrbc_15_strap_p ++ gnd ++ sky130_fd_bd_sram__sram_sp_wlstrap_p +Xrbc_16 ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_16 ++ sky130_fd_bd_sram__openram_sp_cell_opt1a_replica +Xrbc_16_strap ++ vdd ++ sky130_fd_bd_sram__sram_sp_wlstrapa_p +Xrbc_17 ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_17 ++ sky130_fd_bd_sram__openram_sp_cell_opt1_replica +Xrbc_17_strap_p ++ gnd ++ sky130_fd_bd_sram__sram_sp_wlstrap_p +Xrbc_18 ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_18 ++ sky130_fd_bd_sram__openram_sp_cell_opt1a_replica +Xrbc_18_strap ++ vdd ++ sky130_fd_bd_sram__sram_sp_wlstrapa_p +Xrbc_19 ++ bl_0_0 vdd gnd br_0_0 bot_gate vdd gnd ++ sky130_fd_bd_sram__sram_sp_colenda +Xrbc_19_cap ++ gnd vdd gnd ++ sky130_fd_bd_sram__sram_sp_colenda_p_cent +.ENDS sram_2_16_1_sky130_sky130_replica_column +* NGSPICE file created from sky130_fd_bd_sram__sram_sp_colend_cent.ext - technology: sky130A + +.subckt sky130_fd_bd_sram__sram_sp_colend_cent VPWR VPB VNB +.ends + +.SUBCKT sram_2_16_1_sky130_sky130_col_cap_array ++ fake_bl_0 fake_br_0 fake_bl_1 fake_br_1 fake_bl_2 fake_br_2 vdd gnd ++ gate +* OUTPUT: fake_bl_0 +* OUTPUT: fake_br_0 +* OUTPUT: fake_bl_1 +* OUTPUT: fake_br_1 +* OUTPUT: fake_bl_2 +* OUTPUT: fake_br_2 +* POWER : vdd +* GROUND: gnd +* BIAS : gate +Xrca_top_0 ++ fake_bl_0 vdd gnd fake_br_0 gate vdd gnd ++ sky130_fd_bd_sram__sram_sp_colend +Xrca_top_1 ++ vdd vdd gnd ++ sky130_fd_bd_sram__sram_sp_colend_cent +Xrca_top_2 ++ fake_bl_1 vdd gnd fake_br_1 gate vdd gnd ++ sky130_fd_bd_sram__sram_sp_colend +Xrca_top_3 ++ gnd vdd vnb ++ sky130_fd_bd_sram__sram_sp_colend_p_cent +Xrca_top_4 ++ fake_bl_2 vdd gnd fake_br_2 gate vdd gnd ++ sky130_fd_bd_sram__sram_sp_colend +.ENDS sram_2_16_1_sky130_sky130_col_cap_array +* NGSPICE file created from sky130_fd_bd_sram__sram_sp_wlstrapa.ext - technology: sky130A + +.subckt sky130_fd_bd_sram__sram_sp_wlstrapa VPWR +.ends +* NGSPICE file created from sky130_fd_bd_sram__openram_sp_cell_opt1a_dummy.ext - technology: sky130A + +.subckt sky130_fd_bd_sram__openram_sp_cell_opt1a_dummy BL BR VGND VPWR VPB VNB WL +X0 ll WL BR VNB sky130_fd_pr__special_nfet_pass w=0.14 l=0.15 +X1 ul Q_bar_float VGND VNB sky130_fd_pr__special_nfet_latch w=0.21 l=0.15 +X2 BL WL ul VNB sky130_fd_pr__special_nfet_pass w=0.14 l=0.15 +*X3 ur WL ur VPB sky130_fd_pr__special_pfet_pass w=0.07 l=0.095 +*X4 lr WL lr VPB sky130_fd_pr__special_pfet_pass w=0.07 l=0.095 +X5 VPWR Q_float lr VPB sky130_fd_pr__special_pfet_pass w=0.14 l=0.15 +X6 ur Q_bar_float VPWR VPB sky130_fd_pr__special_pfet_pass w=0.14 l=0.15 +X7 VGND Q_float ll VNB sky130_fd_pr__special_nfet_latch w=0.21 l=0.15 +.ends + +.SUBCKT sram_2_16_1_sky130_sky130_dummy_array ++ bl_0_0 br_0_0 bl_0_1 br_0_1 bl_0_2 br_0_2 wl_0_0 vdd gnd +* INOUT : bl_0_0 +* INOUT : br_0_0 +* INOUT : bl_0_1 +* INOUT : br_0_1 +* INOUT : bl_0_2 +* INOUT : br_0_2 +* INPUT : wl_0_0 +* POWER : vdd +* GROUND: gnd +Xrow_0_col_0_bitcell ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_0 ++ sky130_fd_bd_sram__openram_sp_cell_opt1a_dummy +Xrow_0_col_0_wlstrapa ++ vdd ++ sky130_fd_bd_sram__sram_sp_wlstrapa +Xrow_0_col_1_bitcell ++ bl_0_1 br_0_1 gnd vdd vdd gnd wl_0_0 ++ sky130_fd_bd_sram__openram_sp_cell_opt1a_dummy +Xrow_0_col_1_wlstrap_p ++ gnd ++ sky130_fd_bd_sram__sram_sp_wlstrapa_p +Xrow_0_col_2_bitcell ++ bl_0_2 br_0_2 gnd vdd vdd gnd wl_0_0 ++ sky130_fd_bd_sram__openram_sp_cell_opt1a_dummy +.ENDS sram_2_16_1_sky130_sky130_dummy_array +* NGSPICE file created from sky130_fd_bd_sram__sram_sp_cornera.ext - technology: sky130A + +.subckt sky130_fd_bd_sram__sram_sp_cornera VNB VPWR VPB +.ends +* NGSPICE file created from sky130_fd_bd_sram__sram_sp_cornerb.ext - technology: sky130A + +.subckt sky130_fd_bd_sram__sram_sp_cornerb VPWR VPB VNB +.ends +* NGSPICE file created from sky130_fd_bd_sram__sram_sp_rowenda.ext - technology: sky130A + +.subckt sky130_fd_bd_sram__sram_sp_rowenda VPWR WL +.ends +* NGSPICE file created from sky130_fd_bd_sram__sram_sp_rowend.ext - technology: sky130A + +.subckt sky130_fd_bd_sram__sram_sp_rowend VPWR WL +.ends + +.SUBCKT sram_2_16_1_sky130_sky130_row_cap_array_0 ++ wl_0_0 wl_0_1 wl_0_2 wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 wl_0_8 wl_0_9 ++ wl_0_10 wl_0_11 wl_0_12 wl_0_13 wl_0_14 wl_0_15 wl_0_16 wl_0_17 ++ wl_0_18 wl_0_19 vdd gnd +* OUTPUT: wl_0_0 +* OUTPUT: wl_0_1 +* OUTPUT: wl_0_2 +* OUTPUT: wl_0_3 +* OUTPUT: wl_0_4 +* OUTPUT: wl_0_5 +* OUTPUT: wl_0_6 +* OUTPUT: wl_0_7 +* OUTPUT: wl_0_8 +* OUTPUT: wl_0_9 +* OUTPUT: wl_0_10 +* OUTPUT: wl_0_11 +* OUTPUT: wl_0_12 +* OUTPUT: wl_0_13 +* OUTPUT: wl_0_14 +* OUTPUT: wl_0_15 +* OUTPUT: wl_0_16 +* OUTPUT: wl_0_17 +* OUTPUT: wl_0_18 +* OUTPUT: wl_0_19 +* POWER : vdd +* GROUND: gnd +Xrca_0 ++ vdd gnd vdd ++ sky130_fd_bd_sram__sram_sp_cornera +Xrca_1 ++ wl_0_0 vdd ++ sky130_fd_bd_sram__sram_sp_rowenda +Xrca_2 ++ wl_0_1 vdd ++ sky130_fd_bd_sram__sram_sp_rowend +Xrca_3 ++ wl_0_2 vdd ++ sky130_fd_bd_sram__sram_sp_rowenda +Xrca_4 ++ wl_0_3 vdd ++ sky130_fd_bd_sram__sram_sp_rowend +Xrca_5 ++ wl_0_4 vdd ++ sky130_fd_bd_sram__sram_sp_rowenda +Xrca_6 ++ wl_0_5 vdd ++ sky130_fd_bd_sram__sram_sp_rowend +Xrca_7 ++ wl_0_6 vdd ++ sky130_fd_bd_sram__sram_sp_rowenda +Xrca_8 ++ wl_0_7 vdd ++ sky130_fd_bd_sram__sram_sp_rowend +Xrca_9 ++ wl_0_8 vdd ++ sky130_fd_bd_sram__sram_sp_rowenda +Xrca_10 ++ wl_0_9 vdd ++ sky130_fd_bd_sram__sram_sp_rowend +Xrca_11 ++ wl_0_10 vdd ++ sky130_fd_bd_sram__sram_sp_rowenda +Xrca_12 ++ wl_0_11 vdd ++ sky130_fd_bd_sram__sram_sp_rowend +Xrca_13 ++ wl_0_12 vdd ++ sky130_fd_bd_sram__sram_sp_rowenda +Xrca_14 ++ wl_0_13 vdd ++ sky130_fd_bd_sram__sram_sp_rowend +Xrca_15 ++ wl_0_14 vdd ++ sky130_fd_bd_sram__sram_sp_rowenda +Xrca_16 ++ wl_0_15 vdd ++ sky130_fd_bd_sram__sram_sp_rowend +Xrca_17 ++ wl_0_16 vdd ++ sky130_fd_bd_sram__sram_sp_rowenda +Xrca_18 ++ wl_0_17 vdd ++ sky130_fd_bd_sram__sram_sp_rowend +Xrca_19 ++ vdd gnd vdd ++ sky130_fd_bd_sram__sram_sp_cornerb +.ENDS sram_2_16_1_sky130_sky130_row_cap_array_0 +* NGSPICE file created from sky130_fd_bd_sram__sram_sp_cell_opt1a.ext - technology: sky130A + +.subckt sky130_fd_bd_sram__sram_sp_cell_opt1a BL BR VGND VPWR VPB VNB WL +X0 Q_bar WL BR VNB sky130_fd_pr__special_nfet_pass w=0.14 l=0.15 +X1 Q Q_bar VGND VNB sky130_fd_pr__special_nfet_latch w=0.21 l=0.15 +X2 BL WL Q VNB sky130_fd_pr__special_nfet_pass w=0.14 l=0.15 +*X3 Q WL Q VPB sky130_fd_pr__special_pfet_pass w=0.07 l=0.095 +*X4 Q_bar WL Q_bar VPB sky130_fd_pr__special_pfet_pass w=0.07 l=0.095 +X5 VPWR Q Q_bar VPB sky130_fd_pr__special_pfet_pass w=0.14 l=0.15 +X6 Q Q_bar VPWR VPB sky130_fd_pr__special_pfet_pass w=0.14 l=0.15 +X7 VGND Q Q_bar VNB sky130_fd_pr__special_nfet_latch w=0.21 l=0.15 +.ends +* NGSPICE file created from sky130_fd_bd_sram__sram_sp_cell_opt1.ext - technology: sky130A + +.subckt sky130_fd_bd_sram__sram_sp_cell_opt1 BL BR VGND VPWR VPB VNB WL +X0 Q_bar WL BR VNB sky130_fd_pr__special_nfet_pass w=0.14 l=0.15 +X1 Q Q_bar VGND VNB sky130_fd_pr__special_nfet_latch w=0.21 l=0.15 +X2 BL WL Q VNB sky130_fd_pr__special_nfet_pass w=0.14 l=0.15 +*X3 Q WL Q VPB sky130_fd_pr__special_pfet_pass w=0.07 l=0.095 +*X4 Q_bar WL Q_bar VPB sky130_fd_pr__special_pfet_pass w=0.07 l=0.095 +X5 VPWR Q Q_bar VPB sky130_fd_pr__special_pfet_pass w=0.14 l=0.15 +X6 Q Q_bar VPWR VPB sky130_fd_pr__special_pfet_pass w=0.14 l=0.15 +X7 VGND Q Q_bar VNB sky130_fd_pr__special_nfet_latch w=0.21 l=0.15 +.ends +* NGSPICE file created from sky130_fd_bd_sram__sram_sp_wlstrap.ext - technology: sky130A + +.subckt sky130_fd_bd_sram__sram_sp_wlstrap VPWR +.ends + +.SUBCKT sram_2_16_1_sky130_sky130_bitcell_array ++ bl_0_0 br_0_0 bl_0_1 br_0_1 bl_0_2 br_0_2 wl_0_0 wl_0_1 wl_0_2 wl_0_3 ++ wl_0_4 wl_0_5 wl_0_6 wl_0_7 wl_0_8 wl_0_9 wl_0_10 wl_0_11 wl_0_12 ++ wl_0_13 wl_0_14 wl_0_15 wl_0_16 vdd gnd +* INOUT : bl_0_0 +* INOUT : br_0_0 +* INOUT : bl_0_1 +* INOUT : br_0_1 +* INOUT : bl_0_2 +* INOUT : br_0_2 +* INPUT : wl_0_0 +* INPUT : wl_0_1 +* INPUT : wl_0_2 +* INPUT : wl_0_3 +* INPUT : wl_0_4 +* INPUT : wl_0_5 +* INPUT : wl_0_6 +* INPUT : wl_0_7 +* INPUT : wl_0_8 +* INPUT : wl_0_9 +* INPUT : wl_0_10 +* INPUT : wl_0_11 +* INPUT : wl_0_12 +* INPUT : wl_0_13 +* INPUT : wl_0_14 +* INPUT : wl_0_15 +* INPUT : wl_0_16 +* POWER : vdd +* GROUND: gnd +* rows: 17 cols: 3 +Xrow_0_col_0_bitcell ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_0 ++ sky130_fd_bd_sram__sram_sp_cell_opt1 +Xrow_0_col_0_wlstrap ++ vdd ++ sky130_fd_bd_sram__sram_sp_wlstrap +Xrow_0_col_1_bitcell ++ bl_0_1 br_0_1 gnd vdd vdd gnd wl_0_0 ++ sky130_fd_bd_sram__sram_sp_cell_opt1 +Xrow_0_col_1_wlstrap_p ++ gnd ++ sky130_fd_bd_sram__sram_sp_wlstrap_p +Xrow_0_col_2_bitcell ++ bl_0_2 br_0_2 gnd vdd vdd gnd wl_0_0 ++ sky130_fd_bd_sram__sram_sp_cell_opt1 +Xrow_1_col_0_bitcell ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_1 ++ sky130_fd_bd_sram__sram_sp_cell_opt1a +Xrow_1_col_0_wlstrapa ++ vdd ++ sky130_fd_bd_sram__sram_sp_wlstrapa +Xrow_1_col_1_bitcell ++ bl_0_1 br_0_1 gnd vdd vdd gnd wl_0_1 ++ sky130_fd_bd_sram__sram_sp_cell_opt1a +Xrow_1_col_1_wlstrapa_p ++ gnd ++ sky130_fd_bd_sram__sram_sp_wlstrapa_p +Xrow_1_col_2_bitcell ++ bl_0_2 br_0_2 gnd vdd vdd gnd wl_0_1 ++ sky130_fd_bd_sram__sram_sp_cell_opt1a +Xrow_2_col_0_bitcell ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_2 ++ sky130_fd_bd_sram__sram_sp_cell_opt1 +Xrow_2_col_0_wlstrap ++ vdd ++ sky130_fd_bd_sram__sram_sp_wlstrap +Xrow_2_col_1_bitcell ++ bl_0_1 br_0_1 gnd vdd vdd gnd wl_0_2 ++ sky130_fd_bd_sram__sram_sp_cell_opt1 +Xrow_2_col_1_wlstrap_p ++ gnd ++ sky130_fd_bd_sram__sram_sp_wlstrap_p +Xrow_2_col_2_bitcell ++ bl_0_2 br_0_2 gnd vdd vdd gnd wl_0_2 ++ sky130_fd_bd_sram__sram_sp_cell_opt1 +Xrow_3_col_0_bitcell ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_3 ++ sky130_fd_bd_sram__sram_sp_cell_opt1a +Xrow_3_col_0_wlstrapa ++ vdd ++ sky130_fd_bd_sram__sram_sp_wlstrapa +Xrow_3_col_1_bitcell ++ bl_0_1 br_0_1 gnd vdd vdd gnd wl_0_3 ++ sky130_fd_bd_sram__sram_sp_cell_opt1a +Xrow_3_col_1_wlstrapa_p ++ gnd ++ sky130_fd_bd_sram__sram_sp_wlstrapa_p +Xrow_3_col_2_bitcell ++ bl_0_2 br_0_2 gnd vdd vdd gnd wl_0_3 ++ sky130_fd_bd_sram__sram_sp_cell_opt1a +Xrow_4_col_0_bitcell ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_4 ++ sky130_fd_bd_sram__sram_sp_cell_opt1 +Xrow_4_col_0_wlstrap ++ vdd ++ sky130_fd_bd_sram__sram_sp_wlstrap +Xrow_4_col_1_bitcell ++ bl_0_1 br_0_1 gnd vdd vdd gnd wl_0_4 ++ sky130_fd_bd_sram__sram_sp_cell_opt1 +Xrow_4_col_1_wlstrap_p ++ gnd ++ sky130_fd_bd_sram__sram_sp_wlstrap_p +Xrow_4_col_2_bitcell ++ bl_0_2 br_0_2 gnd vdd vdd gnd wl_0_4 ++ sky130_fd_bd_sram__sram_sp_cell_opt1 +Xrow_5_col_0_bitcell ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_5 ++ sky130_fd_bd_sram__sram_sp_cell_opt1a +Xrow_5_col_0_wlstrapa ++ vdd ++ sky130_fd_bd_sram__sram_sp_wlstrapa +Xrow_5_col_1_bitcell ++ bl_0_1 br_0_1 gnd vdd vdd gnd wl_0_5 ++ sky130_fd_bd_sram__sram_sp_cell_opt1a +Xrow_5_col_1_wlstrapa_p ++ gnd ++ sky130_fd_bd_sram__sram_sp_wlstrapa_p +Xrow_5_col_2_bitcell ++ bl_0_2 br_0_2 gnd vdd vdd gnd wl_0_5 ++ sky130_fd_bd_sram__sram_sp_cell_opt1a +Xrow_6_col_0_bitcell ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_6 ++ sky130_fd_bd_sram__sram_sp_cell_opt1 +Xrow_6_col_0_wlstrap ++ vdd ++ sky130_fd_bd_sram__sram_sp_wlstrap +Xrow_6_col_1_bitcell ++ bl_0_1 br_0_1 gnd vdd vdd gnd wl_0_6 ++ sky130_fd_bd_sram__sram_sp_cell_opt1 +Xrow_6_col_1_wlstrap_p ++ gnd ++ sky130_fd_bd_sram__sram_sp_wlstrap_p +Xrow_6_col_2_bitcell ++ bl_0_2 br_0_2 gnd vdd vdd gnd wl_0_6 ++ sky130_fd_bd_sram__sram_sp_cell_opt1 +Xrow_7_col_0_bitcell ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_7 ++ sky130_fd_bd_sram__sram_sp_cell_opt1a +Xrow_7_col_0_wlstrapa ++ vdd ++ sky130_fd_bd_sram__sram_sp_wlstrapa +Xrow_7_col_1_bitcell ++ bl_0_1 br_0_1 gnd vdd vdd gnd wl_0_7 ++ sky130_fd_bd_sram__sram_sp_cell_opt1a +Xrow_7_col_1_wlstrapa_p ++ gnd ++ sky130_fd_bd_sram__sram_sp_wlstrapa_p +Xrow_7_col_2_bitcell ++ bl_0_2 br_0_2 gnd vdd vdd gnd wl_0_7 ++ sky130_fd_bd_sram__sram_sp_cell_opt1a +Xrow_8_col_0_bitcell ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_8 ++ sky130_fd_bd_sram__sram_sp_cell_opt1 +Xrow_8_col_0_wlstrap ++ vdd ++ sky130_fd_bd_sram__sram_sp_wlstrap +Xrow_8_col_1_bitcell ++ bl_0_1 br_0_1 gnd vdd vdd gnd wl_0_8 ++ sky130_fd_bd_sram__sram_sp_cell_opt1 +Xrow_8_col_1_wlstrap_p ++ gnd ++ sky130_fd_bd_sram__sram_sp_wlstrap_p +Xrow_8_col_2_bitcell ++ bl_0_2 br_0_2 gnd vdd vdd gnd wl_0_8 ++ sky130_fd_bd_sram__sram_sp_cell_opt1 +Xrow_9_col_0_bitcell ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_9 ++ sky130_fd_bd_sram__sram_sp_cell_opt1a +Xrow_9_col_0_wlstrapa ++ vdd ++ sky130_fd_bd_sram__sram_sp_wlstrapa +Xrow_9_col_1_bitcell ++ bl_0_1 br_0_1 gnd vdd vdd gnd wl_0_9 ++ sky130_fd_bd_sram__sram_sp_cell_opt1a +Xrow_9_col_1_wlstrapa_p ++ gnd ++ sky130_fd_bd_sram__sram_sp_wlstrapa_p +Xrow_9_col_2_bitcell ++ bl_0_2 br_0_2 gnd vdd vdd gnd wl_0_9 ++ sky130_fd_bd_sram__sram_sp_cell_opt1a +Xrow_10_col_0_bitcell ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_10 ++ sky130_fd_bd_sram__sram_sp_cell_opt1 +Xrow_10_col_0_wlstrap ++ vdd ++ sky130_fd_bd_sram__sram_sp_wlstrap +Xrow_10_col_1_bitcell ++ bl_0_1 br_0_1 gnd vdd vdd gnd wl_0_10 ++ sky130_fd_bd_sram__sram_sp_cell_opt1 +Xrow_10_col_1_wlstrap_p ++ gnd ++ sky130_fd_bd_sram__sram_sp_wlstrap_p +Xrow_10_col_2_bitcell ++ bl_0_2 br_0_2 gnd vdd vdd gnd wl_0_10 ++ sky130_fd_bd_sram__sram_sp_cell_opt1 +Xrow_11_col_0_bitcell ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_11 ++ sky130_fd_bd_sram__sram_sp_cell_opt1a +Xrow_11_col_0_wlstrapa ++ vdd ++ sky130_fd_bd_sram__sram_sp_wlstrapa +Xrow_11_col_1_bitcell ++ bl_0_1 br_0_1 gnd vdd vdd gnd wl_0_11 ++ sky130_fd_bd_sram__sram_sp_cell_opt1a +Xrow_11_col_1_wlstrapa_p ++ gnd ++ sky130_fd_bd_sram__sram_sp_wlstrapa_p +Xrow_11_col_2_bitcell ++ bl_0_2 br_0_2 gnd vdd vdd gnd wl_0_11 ++ sky130_fd_bd_sram__sram_sp_cell_opt1a +Xrow_12_col_0_bitcell ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_12 ++ sky130_fd_bd_sram__sram_sp_cell_opt1 +Xrow_12_col_0_wlstrap ++ vdd ++ sky130_fd_bd_sram__sram_sp_wlstrap +Xrow_12_col_1_bitcell ++ bl_0_1 br_0_1 gnd vdd vdd gnd wl_0_12 ++ sky130_fd_bd_sram__sram_sp_cell_opt1 +Xrow_12_col_1_wlstrap_p ++ gnd ++ sky130_fd_bd_sram__sram_sp_wlstrap_p +Xrow_12_col_2_bitcell ++ bl_0_2 br_0_2 gnd vdd vdd gnd wl_0_12 ++ sky130_fd_bd_sram__sram_sp_cell_opt1 +Xrow_13_col_0_bitcell ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_13 ++ sky130_fd_bd_sram__sram_sp_cell_opt1a +Xrow_13_col_0_wlstrapa ++ vdd ++ sky130_fd_bd_sram__sram_sp_wlstrapa +Xrow_13_col_1_bitcell ++ bl_0_1 br_0_1 gnd vdd vdd gnd wl_0_13 ++ sky130_fd_bd_sram__sram_sp_cell_opt1a +Xrow_13_col_1_wlstrapa_p ++ gnd ++ sky130_fd_bd_sram__sram_sp_wlstrapa_p +Xrow_13_col_2_bitcell ++ bl_0_2 br_0_2 gnd vdd vdd gnd wl_0_13 ++ sky130_fd_bd_sram__sram_sp_cell_opt1a +Xrow_14_col_0_bitcell ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_14 ++ sky130_fd_bd_sram__sram_sp_cell_opt1 +Xrow_14_col_0_wlstrap ++ vdd ++ sky130_fd_bd_sram__sram_sp_wlstrap +Xrow_14_col_1_bitcell ++ bl_0_1 br_0_1 gnd vdd vdd gnd wl_0_14 ++ sky130_fd_bd_sram__sram_sp_cell_opt1 +Xrow_14_col_1_wlstrap_p ++ gnd ++ sky130_fd_bd_sram__sram_sp_wlstrap_p +Xrow_14_col_2_bitcell ++ bl_0_2 br_0_2 gnd vdd vdd gnd wl_0_14 ++ sky130_fd_bd_sram__sram_sp_cell_opt1 +Xrow_15_col_0_bitcell ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_15 ++ sky130_fd_bd_sram__sram_sp_cell_opt1a +Xrow_15_col_0_wlstrapa ++ vdd ++ sky130_fd_bd_sram__sram_sp_wlstrapa +Xrow_15_col_1_bitcell ++ bl_0_1 br_0_1 gnd vdd vdd gnd wl_0_15 ++ sky130_fd_bd_sram__sram_sp_cell_opt1a +Xrow_15_col_1_wlstrapa_p ++ gnd ++ sky130_fd_bd_sram__sram_sp_wlstrapa_p +Xrow_15_col_2_bitcell ++ bl_0_2 br_0_2 gnd vdd vdd gnd wl_0_15 ++ sky130_fd_bd_sram__sram_sp_cell_opt1a +Xrow_16_col_0_bitcell ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_16 ++ sky130_fd_bd_sram__sram_sp_cell_opt1 +Xrow_16_col_0_wlstrap ++ vdd ++ sky130_fd_bd_sram__sram_sp_wlstrap +Xrow_16_col_1_bitcell ++ bl_0_1 br_0_1 gnd vdd vdd gnd wl_0_16 ++ sky130_fd_bd_sram__sram_sp_cell_opt1 +Xrow_16_col_1_wlstrap_p ++ gnd ++ sky130_fd_bd_sram__sram_sp_wlstrap_p +Xrow_16_col_2_bitcell ++ bl_0_2 br_0_2 gnd vdd vdd gnd wl_0_16 ++ sky130_fd_bd_sram__sram_sp_cell_opt1 +.ENDS sram_2_16_1_sky130_sky130_bitcell_array +* NGSPICE file created from sky130_fd_bd_sram__sram_sp_corner.ext - technology: sky130A + +.subckt sky130_fd_bd_sram__sram_sp_corner VPWR VPB VNB +.ends +* NGSPICE file created from sky130_fd_bd_sram__openram_sp_rowenda_replica.ext - technology: sky130A + +.subckt sky130_fd_bd_sram__openram_sp_rowenda_replica VPWR WL +.ends +* NGSPICE file created from sky130_fd_bd_sram__openram_sp_rowend_replica.ext - technology: sky130A + +.subckt sky130_fd_bd_sram__openram_sp_rowend_replica VPWR WL +.ends + +.SUBCKT sram_2_16_1_sky130_sky130_row_cap_array ++ wl_0_0 wl_0_1 wl_0_2 wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 wl_0_8 wl_0_9 ++ wl_0_10 wl_0_11 wl_0_12 wl_0_13 wl_0_14 wl_0_15 wl_0_16 wl_0_17 ++ wl_0_18 wl_0_19 vdd gnd +* OUTPUT: wl_0_0 +* OUTPUT: wl_0_1 +* OUTPUT: wl_0_2 +* OUTPUT: wl_0_3 +* OUTPUT: wl_0_4 +* OUTPUT: wl_0_5 +* OUTPUT: wl_0_6 +* OUTPUT: wl_0_7 +* OUTPUT: wl_0_8 +* OUTPUT: wl_0_9 +* OUTPUT: wl_0_10 +* OUTPUT: wl_0_11 +* OUTPUT: wl_0_12 +* OUTPUT: wl_0_13 +* OUTPUT: wl_0_14 +* OUTPUT: wl_0_15 +* OUTPUT: wl_0_16 +* OUTPUT: wl_0_17 +* OUTPUT: wl_0_18 +* OUTPUT: wl_0_19 +* POWER : vdd +* GROUND: gnd +Xrca_0 ++ vdd gnd vdd ++ sky130_fd_bd_sram__sram_sp_cornera +Xrca_1 ++ wl_0_0 vdd ++ sky130_fd_bd_sram__openram_sp_rowenda_replica +Xrca_2 ++ wl_0_1 vdd ++ sky130_fd_bd_sram__openram_sp_rowend_replica +Xrca_3 ++ wl_0_2 vdd ++ sky130_fd_bd_sram__openram_sp_rowenda_replica +Xrca_4 ++ wl_0_3 vdd ++ sky130_fd_bd_sram__openram_sp_rowend_replica +Xrca_5 ++ wl_0_4 vdd ++ sky130_fd_bd_sram__openram_sp_rowenda_replica +Xrca_6 ++ wl_0_5 vdd ++ sky130_fd_bd_sram__openram_sp_rowend_replica +Xrca_7 ++ wl_0_6 vdd ++ sky130_fd_bd_sram__openram_sp_rowenda_replica +Xrca_8 ++ wl_0_7 vdd ++ sky130_fd_bd_sram__openram_sp_rowend_replica +Xrca_9 ++ wl_0_8 vdd ++ sky130_fd_bd_sram__openram_sp_rowenda_replica +Xrca_10 ++ wl_0_9 vdd ++ sky130_fd_bd_sram__openram_sp_rowend_replica +Xrca_11 ++ wl_0_10 vdd ++ sky130_fd_bd_sram__openram_sp_rowenda_replica +Xrca_12 ++ wl_0_11 vdd ++ sky130_fd_bd_sram__openram_sp_rowend_replica +Xrca_13 ++ wl_0_12 vdd ++ sky130_fd_bd_sram__openram_sp_rowenda_replica +Xrca_14 ++ wl_0_13 vdd ++ sky130_fd_bd_sram__openram_sp_rowend_replica +Xrca_15 ++ wl_0_14 vdd ++ sky130_fd_bd_sram__openram_sp_rowenda_replica +Xrca_16 ++ wl_0_15 vdd ++ sky130_fd_bd_sram__openram_sp_rowend_replica +Xrca_17 ++ wl_0_16 vdd ++ sky130_fd_bd_sram__openram_sp_rowenda_replica +Xrca_18 ++ wl_0_17 vdd ++ sky130_fd_bd_sram__openram_sp_rowend_replica +Xrca_19 ++ vdd gnd vdd ++ sky130_fd_bd_sram__sram_sp_corner +.ENDS sram_2_16_1_sky130_sky130_row_cap_array + +.SUBCKT sram_2_16_1_sky130_sky130_replica_bitcell_array ++ rbl_bl_0_0 rbl_br_0_0 bl_0_0 br_0_0 bl_0_1 br_0_1 bl_0_2 br_0_2 ++ rbl_wl_0_0 wl_0_0 wl_0_1 wl_0_2 wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 ++ wl_0_8 wl_0_9 wl_0_10 wl_0_11 wl_0_12 wl_0_13 wl_0_14 wl_0_15 wl_0_16 ++ vdd gnd +* INOUT : rbl_bl_0_0 +* INOUT : rbl_br_0_0 +* INOUT : bl_0_0 +* INOUT : br_0_0 +* INOUT : bl_0_1 +* INOUT : br_0_1 +* INOUT : bl_0_2 +* INOUT : br_0_2 +* INPUT : rbl_wl_0_0 +* INPUT : wl_0_0 +* INPUT : wl_0_1 +* INPUT : wl_0_2 +* INPUT : wl_0_3 +* INPUT : wl_0_4 +* INPUT : wl_0_5 +* INPUT : wl_0_6 +* INPUT : wl_0_7 +* INPUT : wl_0_8 +* INPUT : wl_0_9 +* INPUT : wl_0_10 +* INPUT : wl_0_11 +* INPUT : wl_0_12 +* INPUT : wl_0_13 +* INPUT : wl_0_14 +* INPUT : wl_0_15 +* INPUT : wl_0_16 +* POWER : vdd +* GROUND: gnd +* rows: 17 cols: 3 +* rbl: [1, 0] left_rbl: [0] right_rbl: [] +Xbitcell_array ++ bl_0_0 br_0_0 bl_0_1 br_0_1 bl_0_2 br_0_2 wl_0_0 wl_0_1 wl_0_2 wl_0_3 ++ wl_0_4 wl_0_5 wl_0_6 wl_0_7 wl_0_8 wl_0_9 wl_0_10 wl_0_11 wl_0_12 ++ wl_0_13 wl_0_14 wl_0_15 wl_0_16 vdd gnd ++ sram_2_16_1_sky130_sky130_bitcell_array +Xreplica_col_0 ++ rbl_bl_0_0 rbl_br_0_0 rbl_wl_0_0 wl_0_0 wl_0_1 wl_0_2 wl_0_3 wl_0_4 ++ wl_0_5 wl_0_6 wl_0_7 wl_0_8 wl_0_9 wl_0_10 wl_0_11 wl_0_12 wl_0_13 ++ wl_0_14 wl_0_15 wl_0_16 vdd gnd gnd gnd ++ sram_2_16_1_sky130_sky130_replica_column +Xdummy_row_0 ++ bl_0_0 br_0_0 bl_0_1 br_0_1 bl_0_2 br_0_2 rbl_wl_0_0 vdd gnd ++ sram_2_16_1_sky130_sky130_dummy_array +Xdummy_row_bot ++ bl_0_0 br_0_0 bl_0_1 br_0_1 bl_0_2 br_0_2 vdd gnd gnd ++ sram_2_16_1_sky130_sky130_col_cap_array_0 +Xdummy_row_top ++ bl_0_0 br_0_0 bl_0_1 br_0_1 bl_0_2 br_0_2 vdd gnd gnd ++ sram_2_16_1_sky130_sky130_col_cap_array +Xdummy_col_left ++ gnd rbl_wl_0_0 wl_0_0 wl_0_1 wl_0_2 wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 ++ wl_0_8 wl_0_9 wl_0_10 wl_0_11 wl_0_12 wl_0_13 wl_0_14 wl_0_15 wl_0_16 ++ gnd vdd gnd ++ sram_2_16_1_sky130_sky130_row_cap_array +Xdummy_col_right ++ gnd rbl_wl_0_0 wl_0_0 wl_0_1 wl_0_2 wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 ++ wl_0_8 wl_0_9 wl_0_10 wl_0_11 wl_0_12 wl_0_13 wl_0_14 wl_0_15 wl_0_16 ++ gnd vdd gnd ++ sram_2_16_1_sky130_sky130_row_cap_array_0 +.ENDS sram_2_16_1_sky130_sky130_replica_bitcell_array + +.SUBCKT sram_2_16_1_sky130_sky130_capped_replica_bitcell_array ++ rbl_bl_0_0 rbl_br_0_0 bl_0_0 br_0_0 bl_0_1 br_0_1 bl_0_2 br_0_2 ++ rbl_wl_0_0 wl_0_0 wl_0_1 wl_0_2 wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 ++ wl_0_8 wl_0_9 wl_0_10 wl_0_11 wl_0_12 wl_0_13 wl_0_14 wl_0_15 wl_0_16 ++ vdd gnd +* INOUT : rbl_bl_0_0 +* INOUT : rbl_br_0_0 +* INOUT : bl_0_0 +* INOUT : br_0_0 +* INOUT : bl_0_1 +* INOUT : br_0_1 +* INOUT : bl_0_2 +* INOUT : br_0_2 +* INPUT : rbl_wl_0_0 +* INPUT : wl_0_0 +* INPUT : wl_0_1 +* INPUT : wl_0_2 +* INPUT : wl_0_3 +* INPUT : wl_0_4 +* INPUT : wl_0_5 +* INPUT : wl_0_6 +* INPUT : wl_0_7 +* INPUT : wl_0_8 +* INPUT : wl_0_9 +* INPUT : wl_0_10 +* INPUT : wl_0_11 +* INPUT : wl_0_12 +* INPUT : wl_0_13 +* INPUT : wl_0_14 +* INPUT : wl_0_15 +* INPUT : wl_0_16 +* POWER : vdd +* GROUND: gnd +* rows: 17 cols: 3 +* rbl: [1, 0] left_rbl: [0] right_rbl: [] +Xreplica_bitcell_array ++ rbl_bl_0_0 rbl_br_0_0 bl_0_0 br_0_0 bl_0_1 br_0_1 bl_0_2 br_0_2 ++ rbl_wl_0_0 wl_0_0 wl_0_1 wl_0_2 wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 ++ wl_0_8 wl_0_9 wl_0_10 wl_0_11 wl_0_12 wl_0_13 wl_0_14 wl_0_15 wl_0_16 ++ vdd gnd ++ sram_2_16_1_sky130_sky130_replica_bitcell_array +.ENDS sram_2_16_1_sky130_sky130_capped_replica_bitcell_array +* Copyright 2020 The SkyWater PDK Authors +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +* SPDX-License-Identifier: Apache-2.0 + +*********************** "sky130_fd_bd_sram__openram_write_driver" ****************************** + +.SUBCKT sky130_fd_bd_sram__openram_write_driver DIN BL BR EN VDD GND + +**** Inverter to conver Data_in to data_in_bar ****** +* din_bar = inv(DIN) +X_1 din_bar DIN GND GND sky130_fd_pr__nfet_01v8 W=0.36 L=0.15 +X_2 din_bar DIN VDD VDD sky130_fd_pr__pfet_01v8 W=0.55 L=0.15 + +**** 2input nand gate follwed by inverter to drive BL ****** +* din_bar_gated = nand(EN, DIN) +X_3 din_bar_gated EN net_7 GND sky130_fd_pr__nfet_01v8 W=0.55 L=0.15 +X_4 net_7 DIN GND GND sky130_fd_pr__nfet_01v8 W=0.55 L=0.15 +X_5 din_bar_gated EN VDD VDD sky130_fd_pr__pfet_01v8 W=0.55 L=0.15 +X_6 din_bar_gated DIN VDD VDD sky130_fd_pr__pfet_01v8 W=0.55 L=0.15 +* din_bar_gated_bar = inv(din_bar_gated) +X_7 din_bar_gated_bar din_bar_gated VDD VDD sky130_fd_pr__pfet_01v8 W=0.55 L=0.15 +X_8 din_bar_gated_bar din_bar_gated GND GND sky130_fd_pr__nfet_01v8 W=0.36 L=0.15 + +**** 2input nand gate follwed by inverter to drive BR****** +* din_gated = nand(EN, din_bar) +X_9 din_gated EN VDD VDD sky130_fd_pr__pfet_01v8 W=0.55 L=0.15 +X_10 din_gated EN net_8 GND sky130_fd_pr__nfet_01v8 W=0.55 L=0.15 +X_11 net_8 din_bar GND GND sky130_fd_pr__nfet_01v8 W=0.55 L=0.15 +X_12 din_gated din_bar VDD VDD sky130_fd_pr__pfet_01v8 W=0.55 L=0.15 +* din_gated_bar = inv(din_gated) +X_13 din_gated_bar din_gated VDD VDD sky130_fd_pr__pfet_01v8 W=0.55 L=0.15 +X_14 din_gated_bar din_gated GND GND sky130_fd_pr__nfet_01v8 W=0.36 L=0.15 + +************************************************ +* pull down with EN enable +X_15 BL din_gated_bar GND GND sky130_fd_pr__nfet_01v8 W=1 L=0.15 +X_16 BR din_bar_gated_bar GND GND sky130_fd_pr__nfet_01v8 W=1 L=0.15 + +.ENDS sky130_fd_bd_sram__openram_write_driver + +.SUBCKT sram_2_16_1_sky130_write_driver_array ++ data_0 data_1 data_2 bl_0 br_0 bl_1 br_1 bl_2 br_2 en_0 en_1 vdd gnd +* INPUT : data_0 +* INPUT : data_1 +* INPUT : data_2 +* OUTPUT: bl_0 +* OUTPUT: br_0 +* OUTPUT: bl_1 +* OUTPUT: br_1 +* OUTPUT: bl_2 +* OUTPUT: br_2 +* INPUT : en_0 +* INPUT : en_1 +* POWER : vdd +* GROUND: gnd +* columns: 2 +* word_size 2 +Xwrite_driver0 ++ data_0 bl_0 br_0 en_0 vdd gnd ++ sky130_fd_bd_sram__openram_write_driver +Xwrite_driver1 ++ data_1 bl_1 br_1 en_0 vdd gnd ++ sky130_fd_bd_sram__openram_write_driver +Xwrite_driver2 ++ data_2 bl_2 br_2 en_1 vdd gnd ++ sky130_fd_bd_sram__openram_write_driver +.ENDS sram_2_16_1_sky130_write_driver_array + +* spice ptx X{0} {1} sky130_fd_pr__pfet_01v8 m=1 w=0.55 l=0.15 pd=1.40 ps=1.40 as=0.21u ad=0.21u + +.SUBCKT sram_2_16_1_sky130_precharge_0 ++ bl br en_bar vdd +* OUTPUT: bl +* OUTPUT: br +* INPUT : en_bar +* POWER : vdd +Xlower_pmos bl en_bar br vdd sky130_fd_pr__pfet_01v8 m=1 w=0.55 l=0.15 pd=1.40 ps=1.40 as=0.21u ad=0.21u +Xupper_pmos1 bl en_bar vdd vdd sky130_fd_pr__pfet_01v8 m=1 w=0.55 l=0.15 pd=1.40 ps=1.40 as=0.21u ad=0.21u +Xupper_pmos2 br en_bar vdd vdd sky130_fd_pr__pfet_01v8 m=1 w=0.55 l=0.15 pd=1.40 ps=1.40 as=0.21u ad=0.21u +.ENDS sram_2_16_1_sky130_precharge_0 + +.SUBCKT sram_2_16_1_sky130_precharge_array ++ bl_0 br_0 bl_1 br_1 bl_2 br_2 bl_3 br_3 en_bar vdd +* OUTPUT: bl_0 +* OUTPUT: br_0 +* OUTPUT: bl_1 +* OUTPUT: br_1 +* OUTPUT: bl_2 +* OUTPUT: br_2 +* OUTPUT: bl_3 +* OUTPUT: br_3 +* INPUT : en_bar +* POWER : vdd +* cols: 4 size: 1 bl: bl br: br +Xpre_column_0 ++ bl_0 br_0 en_bar vdd ++ sram_2_16_1_sky130_precharge_0 +Xpre_column_1 ++ bl_1 br_1 en_bar vdd ++ sram_2_16_1_sky130_precharge_0 +Xpre_column_2 ++ bl_2 br_2 en_bar vdd ++ sram_2_16_1_sky130_precharge_0 +Xpre_column_3 ++ bl_3 br_3 en_bar vdd ++ sram_2_16_1_sky130_precharge_0 +.ENDS sram_2_16_1_sky130_precharge_array +* Copyright 2020 The SkyWater PDK Authors +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +* SPDX-License-Identifier: Apache-2.0 + +*********************** "sky130_fd_bd_sram__openram_sense_amp" ****************************** + +.SUBCKT sky130_fd_bd_sram__openram_sense_amp BL BR DOUT EN VDD GND +X1000 GND EN a_56_432# GND sky130_fd_pr__nfet_01v8 W=0.65 L=0.15 +X1001 a_56_432# dint_bar dint GND sky130_fd_pr__nfet_01v8 W=0.65 L=0.15 +X1002 dint_bar dint a_56_432# GND sky130_fd_pr__nfet_01v8 W=0.65 L=0.15 + +X1003 VDD dint_bar dint VDD sky130_fd_pr__pfet_01v8 W=1.26 L=0.15 +X1004 dint_bar dint VDD VDD sky130_fd_pr__pfet_01v8 W=1.26 L=0.15 + +X1005 BL EN dint VDD sky130_fd_pr__pfet_01v8 W=2 L=0.15 +X1006 dint_bar EN BR VDD sky130_fd_pr__pfet_01v8 W=2 L=0.15 + +X1007 VDD dint_bar DOUT VDD sky130_fd_pr__pfet_01v8 W=1.26 L=0.15 +X1008 DOUT dint_bar GND GND sky130_fd_pr__nfet_01v8 W=0.65 L=0.15 + +.ENDS sky130_fd_bd_sram__openram_sense_amp + +.SUBCKT sram_2_16_1_sky130_sense_amp_array ++ data_0 bl_0 br_0 data_1 bl_1 br_1 data_2 bl_2 br_2 en vdd gnd +* OUTPUT: data_0 +* INPUT : bl_0 +* INPUT : br_0 +* OUTPUT: data_1 +* INPUT : bl_1 +* INPUT : br_1 +* OUTPUT: data_2 +* INPUT : bl_2 +* INPUT : br_2 +* INPUT : en +* POWER : vdd +* GROUND: gnd +* word_size 2 +* words_per_row: 1 +Xsa_d0 ++ bl_0 br_0 data_0 en vdd gnd ++ sky130_fd_bd_sram__openram_sense_amp +Xsa_d1 ++ bl_1 br_1 data_1 en vdd gnd ++ sky130_fd_bd_sram__openram_sense_amp +Xsa_d2 ++ bl_2 br_2 data_2 en vdd gnd ++ sky130_fd_bd_sram__openram_sense_amp +.ENDS sram_2_16_1_sky130_sense_amp_array + +.SUBCKT sram_2_16_1_sky130_port_data ++ rbl_bl rbl_br bl_0 br_0 bl_1 br_1 sparebl_0 sparebr_0 dout_0 dout_1 ++ dout_2 din_0 din_1 din_2 s_en p_en_bar w_en bank_spare_wen0 vdd gnd +* INOUT : rbl_bl +* INOUT : rbl_br +* INOUT : bl_0 +* INOUT : br_0 +* INOUT : bl_1 +* INOUT : br_1 +* INOUT : sparebl_0 +* INOUT : sparebr_0 +* OUTPUT: dout_0 +* OUTPUT: dout_1 +* OUTPUT: dout_2 +* INPUT : din_0 +* INPUT : din_1 +* INPUT : din_2 +* INPUT : s_en +* INPUT : p_en_bar +* INPUT : w_en +* INPUT : bank_spare_wen0 +* POWER : vdd +* GROUND: gnd +Xprecharge_array0 ++ rbl_bl rbl_br bl_0 br_0 bl_1 br_1 sparebl_0 sparebr_0 p_en_bar vdd ++ sram_2_16_1_sky130_precharge_array +Xsense_amp_array0 ++ dout_0 bl_0 br_0 dout_1 bl_1 br_1 dout_2 sparebl_0 sparebr_0 s_en vdd ++ gnd ++ sram_2_16_1_sky130_sense_amp_array +Xwrite_driver_array0 ++ din_0 din_1 din_2 bl_0 br_0 bl_1 br_1 sparebl_0 sparebr_0 w_en ++ bank_spare_wen0 vdd gnd ++ sram_2_16_1_sky130_write_driver_array +.ENDS sram_2_16_1_sky130_port_data + +.SUBCKT sram_2_16_1_sky130_bank ++ dout0_0 dout0_1 dout0_2 rbl_bl_0_0 din0_0 din0_1 din0_2 addr0_0 ++ addr0_1 addr0_2 addr0_3 addr0_4 s_en0 p_en_bar0 w_en0 ++ bank_spare_wen0_0 wl_en0 vdd gnd +* OUTPUT: dout0_0 +* OUTPUT: dout0_1 +* OUTPUT: dout0_2 +* OUTPUT: rbl_bl_0_0 +* INPUT : din0_0 +* INPUT : din0_1 +* INPUT : din0_2 +* INPUT : addr0_0 +* INPUT : addr0_1 +* INPUT : addr0_2 +* INPUT : addr0_3 +* INPUT : addr0_4 +* INPUT : s_en0 +* INPUT : p_en_bar0 +* INPUT : w_en0 +* INPUT : bank_spare_wen0_0 +* INPUT : wl_en0 +* POWER : vdd +* GROUND: gnd +Xbitcell_array ++ rbl_bl_0_0 rbl_br_0_0 bl_0_0 br_0_0 bl_0_1 br_0_1 bl_0_2 br_0_2 ++ rbl_wl0 wl_0_0 wl_0_1 wl_0_2 wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 wl_0_8 ++ wl_0_9 wl_0_10 wl_0_11 wl_0_12 wl_0_13 wl_0_14 wl_0_15 wl_0_16 vdd gnd ++ sram_2_16_1_sky130_sky130_capped_replica_bitcell_array +Xport_data0 ++ rbl_bl_0_0 rbl_br_0_0 bl_0_0 br_0_0 bl_0_1 br_0_1 bl_0_2 br_0_2 ++ dout0_0 dout0_1 dout0_2 din0_0 din0_1 din0_2 s_en0 p_en_bar0 w_en0 ++ bank_spare_wen0_0 vdd gnd ++ sram_2_16_1_sky130_port_data +Xport_address0 ++ addr0_0 addr0_1 addr0_2 addr0_3 addr0_4 wl_en0 wl_0_0 wl_0_1 wl_0_2 ++ wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 wl_0_8 wl_0_9 wl_0_10 wl_0_11 ++ wl_0_12 wl_0_13 wl_0_14 wl_0_15 wl_0_16 rbl_wl0 vdd gnd ++ sram_2_16_1_sky130_port_address +.ENDS sram_2_16_1_sky130_bank + +.SUBCKT sram_2_16_1_sky130_pinv_4 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* size: 1 +Xpinv_pmos Z A vdd vdd sky130_fd_pr__pfet_01v8 m=1 w=1.12 l=0.15 pd=2.54 ps=2.54 as=0.42u ad=0.42u +Xpinv_nmos Z A gnd gnd sky130_fd_pr__nfet_01v8 m=1 w=0.36 l=0.15 pd=1.02 ps=1.02 as=0.14u ad=0.14u +.ENDS sram_2_16_1_sky130_pinv_4 + +* spice ptx X{0} {1} sky130_fd_pr__nfet_01v8 m=3 w=2.0 l=0.15 pd=4.30 ps=4.30 as=0.75u ad=0.75u + +* spice ptx X{0} {1} sky130_fd_pr__pfet_01v8 m=3 w=2.0 l=0.15 pd=4.30 ps=4.30 as=0.75u ad=0.75u + +.SUBCKT sram_2_16_1_sky130_pinv_8 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* size: 5 +Xpinv_pmos Z A vdd vdd sky130_fd_pr__pfet_01v8 m=3 w=2.0 l=0.15 pd=4.30 ps=4.30 as=0.75u ad=0.75u +Xpinv_nmos Z A gnd gnd sky130_fd_pr__nfet_01v8 m=3 w=2.0 l=0.15 pd=4.30 ps=4.30 as=0.75u ad=0.75u +.ENDS sram_2_16_1_sky130_pinv_8 + +.SUBCKT sram_2_16_1_sky130_pdriver_1 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* sizes: [1, 5] +Xbuf_inv1 ++ A Zb1_int vdd gnd ++ sram_2_16_1_sky130_pinv_4 +Xbuf_inv2 ++ Zb1_int Z vdd gnd ++ sram_2_16_1_sky130_pinv_8 +.ENDS sram_2_16_1_sky130_pdriver_1 + +* spice ptx X{0} {1} sky130_fd_pr__nfet_01v8 m=6 w=2.0 l=0.15 pd=4.30 ps=4.30 as=0.75u ad=0.75u + +* spice ptx X{0} {1} sky130_fd_pr__pfet_01v8 m=6 w=2.0 l=0.15 pd=4.30 ps=4.30 as=0.75u ad=0.75u + +.SUBCKT sram_2_16_1_sky130_pinv_9 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* size: 10 +Xpinv_pmos Z A vdd vdd sky130_fd_pr__pfet_01v8 m=6 w=2.0 l=0.15 pd=4.30 ps=4.30 as=0.75u ad=0.75u +Xpinv_nmos Z A gnd gnd sky130_fd_pr__nfet_01v8 m=6 w=2.0 l=0.15 pd=4.30 ps=4.30 as=0.75u ad=0.75u +.ENDS sram_2_16_1_sky130_pinv_9 + +.SUBCKT sram_2_16_1_sky130_pdriver_2 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* sizes: [10] +Xbuf_inv1 ++ A Z vdd gnd ++ sram_2_16_1_sky130_pinv_9 +.ENDS sram_2_16_1_sky130_pdriver_2 + +* spice ptx X{0} {1} sky130_fd_pr__nfet_01v8 m=1 w=0.74 l=0.15 pd=1.78 ps=1.78 as=0.28u ad=0.28u + +* spice ptx X{0} {1} sky130_fd_pr__pfet_01v8 m=1 w=1.12 l=0.15 pd=2.54 ps=2.54 as=0.42u ad=0.42u + +* spice ptx X{0} {1} sky130_fd_pr__nfet_01v8 m=1 w=0.74 l=0.15 pd=1.78 ps=1.78 as=0.28u ad=0.28u + +* spice ptx X{0} {1} sky130_fd_pr__nfet_01v8 m=1 w=0.74 l=0.15 pd=1.78 ps=1.78 as=0.28u ad=0.28u + +.SUBCKT sram_2_16_1_sky130_pnand3 ++ A B C Z vdd gnd +* INPUT : A +* INPUT : B +* INPUT : C +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* size: 1 +Xpnand3_pmos1 vdd A Z vdd sky130_fd_pr__pfet_01v8 m=1 w=1.12 l=0.15 pd=2.54 ps=2.54 as=0.42u ad=0.42u +Xpnand3_pmos2 Z B vdd vdd sky130_fd_pr__pfet_01v8 m=1 w=1.12 l=0.15 pd=2.54 ps=2.54 as=0.42u ad=0.42u +Xpnand3_pmos3 Z C vdd vdd sky130_fd_pr__pfet_01v8 m=1 w=1.12 l=0.15 pd=2.54 ps=2.54 as=0.42u ad=0.42u +Xpnand3_nmos1 Z C net1 gnd sky130_fd_pr__nfet_01v8 m=1 w=0.74 l=0.15 pd=1.78 ps=1.78 as=0.28u ad=0.28u +Xpnand3_nmos2 net1 B net2 gnd sky130_fd_pr__nfet_01v8 m=1 w=0.74 l=0.15 pd=1.78 ps=1.78 as=0.28u ad=0.28u +Xpnand3_nmos3 net2 A gnd gnd sky130_fd_pr__nfet_01v8 m=1 w=0.74 l=0.15 pd=1.78 ps=1.78 as=0.28u ad=0.28u +.ENDS sram_2_16_1_sky130_pnand3 + +.SUBCKT sram_2_16_1_sky130_pand3 ++ A B C Z vdd gnd +* INPUT : A +* INPUT : B +* INPUT : C +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* size: 10 +Xpand3_nand ++ A B C zb_int vdd gnd ++ sram_2_16_1_sky130_pnand3 +Xpand3_inv ++ zb_int Z vdd gnd ++ sram_2_16_1_sky130_pdriver_2 +.ENDS sram_2_16_1_sky130_pand3 + +.SUBCKT sram_2_16_1_sky130_pdriver_4 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* sizes: [1, 1] +Xbuf_inv1 ++ A Zb1_int vdd gnd ++ sram_2_16_1_sky130_pinv_4 +Xbuf_inv2 ++ Zb1_int Z vdd gnd ++ sram_2_16_1_sky130_pinv_4 +.ENDS sram_2_16_1_sky130_pdriver_4 + +.SUBCKT sram_2_16_1_sky130_pnand2_0 ++ A B Z vdd gnd +* INPUT : A +* INPUT : B +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* size: 1 +Xpnand2_pmos1 vdd A Z vdd sky130_fd_pr__pfet_01v8 m=1 w=1.12 l=0.15 pd=2.54 ps=2.54 as=0.42u ad=0.42u +Xpnand2_pmos2 Z B vdd vdd sky130_fd_pr__pfet_01v8 m=1 w=1.12 l=0.15 pd=2.54 ps=2.54 as=0.42u ad=0.42u +Xpnand2_nmos1 Z B net1 gnd sky130_fd_pr__nfet_01v8 m=1 w=0.74 l=0.15 pd=1.78 ps=1.78 as=0.28u ad=0.28u +Xpnand2_nmos2 net1 A gnd gnd sky130_fd_pr__nfet_01v8 m=1 w=0.74 l=0.15 pd=1.78 ps=1.78 as=0.28u ad=0.28u +.ENDS sram_2_16_1_sky130_pnand2_0 + +* spice ptx X{0} {1} sky130_fd_pr__pfet_01v8 m=7 w=2.0 l=0.15 pd=4.30 ps=4.30 as=0.75u ad=0.75u + +* spice ptx X{0} {1} sky130_fd_pr__nfet_01v8 m=7 w=1.68 l=0.15 pd=3.66 ps=3.66 as=0.63u ad=0.63u + +.SUBCKT sram_2_16_1_sky130_pinv_1 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* size: 12 +Xpinv_pmos Z A vdd vdd sky130_fd_pr__pfet_01v8 m=7 w=2.0 l=0.15 pd=4.30 ps=4.30 as=0.75u ad=0.75u +Xpinv_nmos Z A gnd gnd sky130_fd_pr__nfet_01v8 m=7 w=1.68 l=0.15 pd=3.66 ps=3.66 as=0.63u ad=0.63u +.ENDS sram_2_16_1_sky130_pinv_1 + +.SUBCKT sram_2_16_1_sky130_pdriver ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* sizes: [12] +Xbuf_inv1 ++ A Z vdd gnd ++ sram_2_16_1_sky130_pinv_1 +.ENDS sram_2_16_1_sky130_pdriver + +.SUBCKT sram_2_16_1_sky130_pnand2 ++ A B Z vdd gnd +* INPUT : A +* INPUT : B +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* size: 1 +Xpnand2_pmos1 vdd A Z vdd sky130_fd_pr__pfet_01v8 m=1 w=1.12 l=0.15 pd=2.54 ps=2.54 as=0.42u ad=0.42u +Xpnand2_pmos2 Z B vdd vdd sky130_fd_pr__pfet_01v8 m=1 w=1.12 l=0.15 pd=2.54 ps=2.54 as=0.42u ad=0.42u +Xpnand2_nmos1 Z B net1 gnd sky130_fd_pr__nfet_01v8 m=1 w=0.74 l=0.15 pd=1.78 ps=1.78 as=0.28u ad=0.28u +Xpnand2_nmos2 net1 A gnd gnd sky130_fd_pr__nfet_01v8 m=1 w=0.74 l=0.15 pd=1.78 ps=1.78 as=0.28u ad=0.28u +.ENDS sram_2_16_1_sky130_pnand2 + +.SUBCKT sram_2_16_1_sky130_pand2 ++ A B Z vdd gnd +* INPUT : A +* INPUT : B +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* size: 12 +Xpand2_nand ++ A B zb_int vdd gnd ++ sram_2_16_1_sky130_pnand2 +Xpand2_inv ++ zb_int Z vdd gnd ++ sram_2_16_1_sky130_pdriver +.ENDS sram_2_16_1_sky130_pand2 + +* spice ptx X{0} {1} sky130_fd_pr__nfet_01v8 m=10 w=1.68 l=0.15 pd=3.66 ps=3.66 as=0.63u ad=0.63u + +* spice ptx X{0} {1} sky130_fd_pr__pfet_01v8 m=10 w=2.0 l=0.15 pd=4.30 ps=4.30 as=0.75u ad=0.75u + +.SUBCKT sram_2_16_1_sky130_pinv_7 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* size: 17 +Xpinv_pmos Z A vdd vdd sky130_fd_pr__pfet_01v8 m=10 w=2.0 l=0.15 pd=4.30 ps=4.30 as=0.75u ad=0.75u +Xpinv_nmos Z A gnd gnd sky130_fd_pr__nfet_01v8 m=10 w=1.68 l=0.15 pd=3.66 ps=3.66 as=0.63u ad=0.63u +.ENDS sram_2_16_1_sky130_pinv_7 + +* spice ptx X{0} {1} sky130_fd_pr__pfet_01v8 m=4 w=2.0 l=0.15 pd=4.30 ps=4.30 as=0.75u ad=0.75u + +* spice ptx X{0} {1} sky130_fd_pr__nfet_01v8 m=4 w=1.26 l=0.15 pd=2.82 ps=2.82 as=0.47u ad=0.47u + +.SUBCKT sram_2_16_1_sky130_pinv_6 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* size: 6 +Xpinv_pmos Z A vdd vdd sky130_fd_pr__pfet_01v8 m=4 w=2.0 l=0.15 pd=4.30 ps=4.30 as=0.75u ad=0.75u +Xpinv_nmos Z A gnd gnd sky130_fd_pr__nfet_01v8 m=4 w=1.26 l=0.15 pd=2.82 ps=2.82 as=0.47u ad=0.47u +.ENDS sram_2_16_1_sky130_pinv_6 + +* spice ptx X{0} {1} sky130_fd_pr__pfet_01v8 m=2 w=1.26 l=0.15 pd=2.82 ps=2.82 as=0.47u ad=0.47u + +* spice ptx X{0} {1} sky130_fd_pr__nfet_01v8 m=2 w=0.74 l=0.15 pd=1.78 ps=1.78 as=0.28u ad=0.28u + +.SUBCKT sram_2_16_1_sky130_pinv_5 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* size: 2 +Xpinv_pmos Z A vdd vdd sky130_fd_pr__pfet_01v8 m=2 w=1.26 l=0.15 pd=2.82 ps=2.82 as=0.47u ad=0.47u +Xpinv_nmos Z A gnd gnd sky130_fd_pr__nfet_01v8 m=2 w=0.74 l=0.15 pd=1.78 ps=1.78 as=0.28u ad=0.28u +.ENDS sram_2_16_1_sky130_pinv_5 + +.SUBCKT sram_2_16_1_sky130_pdriver_0 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* sizes: [1, 2, 6, 17] +Xbuf_inv1 ++ A Zb1_int vdd gnd ++ sram_2_16_1_sky130_pinv_4 +Xbuf_inv2 ++ Zb1_int Zb2_int vdd gnd ++ sram_2_16_1_sky130_pinv_5 +Xbuf_inv3 ++ Zb2_int Zb3_int vdd gnd ++ sram_2_16_1_sky130_pinv_6 +Xbuf_inv4 ++ Zb3_int Z vdd gnd ++ sram_2_16_1_sky130_pinv_7 +.ENDS sram_2_16_1_sky130_pdriver_0 + +.SUBCKT sram_2_16_1_sky130_pinv_11 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* size: 1 +Xpinv_pmos Z A vdd vdd sky130_fd_pr__pfet_01v8 m=1 w=1.12 l=0.15 pd=2.54 ps=2.54 as=0.42u ad=0.42u +Xpinv_nmos Z A gnd gnd sky130_fd_pr__nfet_01v8 m=1 w=0.36 l=0.15 pd=1.02 ps=1.02 as=0.14u ad=0.14u +.ENDS sram_2_16_1_sky130_pinv_11 + +.SUBCKT sram_2_16_1_sky130_delay_chain ++ in out vdd gnd +* INPUT : in +* OUTPUT: out +* POWER : vdd +* GROUND: gnd +* fanouts: [4, 4, 4, 4, 4, 4, 4, 4, 4] +Xdinv0 ++ in dout_1 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_0_0 ++ dout_1 n_0_0 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_0_1 ++ dout_1 n_0_1 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_0_2 ++ dout_1 n_0_2 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_0_3 ++ dout_1 n_0_3 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdinv1 ++ dout_1 dout_2 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_1_0 ++ dout_2 n_1_0 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_1_1 ++ dout_2 n_1_1 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_1_2 ++ dout_2 n_1_2 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_1_3 ++ dout_2 n_1_3 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdinv2 ++ dout_2 dout_3 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_2_0 ++ dout_3 n_2_0 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_2_1 ++ dout_3 n_2_1 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_2_2 ++ dout_3 n_2_2 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_2_3 ++ dout_3 n_2_3 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdinv3 ++ dout_3 dout_4 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_3_0 ++ dout_4 n_3_0 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_3_1 ++ dout_4 n_3_1 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_3_2 ++ dout_4 n_3_2 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_3_3 ++ dout_4 n_3_3 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdinv4 ++ dout_4 dout_5 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_4_0 ++ dout_5 n_4_0 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_4_1 ++ dout_5 n_4_1 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_4_2 ++ dout_5 n_4_2 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_4_3 ++ dout_5 n_4_3 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdinv5 ++ dout_5 dout_6 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_5_0 ++ dout_6 n_5_0 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_5_1 ++ dout_6 n_5_1 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_5_2 ++ dout_6 n_5_2 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_5_3 ++ dout_6 n_5_3 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdinv6 ++ dout_6 dout_7 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_6_0 ++ dout_7 n_6_0 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_6_1 ++ dout_7 n_6_1 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_6_2 ++ dout_7 n_6_2 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_6_3 ++ dout_7 n_6_3 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdinv7 ++ dout_7 dout_8 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_7_0 ++ dout_8 n_7_0 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_7_1 ++ dout_8 n_7_1 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_7_2 ++ dout_8 n_7_2 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_7_3 ++ dout_8 n_7_3 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdinv8 ++ dout_8 out vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_8_0 ++ out n_8_0 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_8_1 ++ out n_8_1 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_8_2 ++ out n_8_2 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_8_3 ++ out n_8_3 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +.ENDS sram_2_16_1_sky130_delay_chain + +* spice ptx X{0} {1} sky130_fd_pr__pfet_01v8 m=2 w=2.0 l=0.15 pd=4.30 ps=4.30 as=0.75u ad=0.75u + +* spice ptx X{0} {1} sky130_fd_pr__nfet_01v8 m=2 w=1.26 l=0.15 pd=2.82 ps=2.82 as=0.47u ad=0.47u + +.SUBCKT sram_2_16_1_sky130_pinv_10 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* size: 3 +Xpinv_pmos Z A vdd vdd sky130_fd_pr__pfet_01v8 m=2 w=2.0 l=0.15 pd=4.30 ps=4.30 as=0.75u ad=0.75u +Xpinv_nmos Z A gnd gnd sky130_fd_pr__nfet_01v8 m=2 w=1.26 l=0.15 pd=2.82 ps=2.82 as=0.47u ad=0.47u +.ENDS sram_2_16_1_sky130_pinv_10 + +.SUBCKT sram_2_16_1_sky130_pdriver_3 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* sizes: [3] +Xbuf_inv1 ++ A Z vdd gnd ++ sram_2_16_1_sky130_pinv_10 +.ENDS sram_2_16_1_sky130_pdriver_3 + +.SUBCKT sram_2_16_1_sky130_pand3_0 ++ A B C Z vdd gnd +* INPUT : A +* INPUT : B +* INPUT : C +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* size: 3 +Xpand3_nand ++ A B C zb_int vdd gnd ++ sram_2_16_1_sky130_pnand3 +Xpand3_inv ++ zb_int Z vdd gnd ++ sram_2_16_1_sky130_pdriver_3 +.ENDS sram_2_16_1_sky130_pand3_0 + +.SUBCKT sram_2_16_1_sky130_pinv ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* size: 2 +Xpinv_pmos Z A vdd vdd sky130_fd_pr__pfet_01v8 m=2 w=1.26 l=0.15 pd=2.82 ps=2.82 as=0.47u ad=0.47u +Xpinv_nmos Z A gnd gnd sky130_fd_pr__nfet_01v8 m=2 w=0.74 l=0.15 pd=1.78 ps=1.78 as=0.28u ad=0.28u +.ENDS sram_2_16_1_sky130_pinv + +* spice ptx X{0} {1} sky130_fd_pr__nfet_01v8 m=3 w=1.68 l=0.15 pd=3.66 ps=3.66 as=0.63u ad=0.63u + +* spice ptx X{0} {1} sky130_fd_pr__pfet_01v8 m=3 w=1.68 l=0.15 pd=3.66 ps=3.66 as=0.63u ad=0.63u + +.SUBCKT sram_2_16_1_sky130_pinv_0 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* size: 4 +Xpinv_pmos Z A vdd vdd sky130_fd_pr__pfet_01v8 m=3 w=1.68 l=0.15 pd=3.66 ps=3.66 as=0.63u ad=0.63u +Xpinv_nmos Z A gnd gnd sky130_fd_pr__nfet_01v8 m=3 w=1.68 l=0.15 pd=3.66 ps=3.66 as=0.63u ad=0.63u +.ENDS sram_2_16_1_sky130_pinv_0 + +.SUBCKT sram_2_16_1_sky130_dff_buf_0 ++ D Q Qb clk vdd gnd +* INPUT : D +* OUTPUT: Q +* OUTPUT: Qb +* INPUT : clk +* POWER : vdd +* GROUND: gnd +* inv1: 2 inv2: 4 +Xdff_buf_dff ++ D qint clk vdd gnd ++ sky130_fd_bd_sram__openram_dff +Xdff_buf_inv1 ++ qint Qb vdd gnd ++ sram_2_16_1_sky130_pinv +Xdff_buf_inv2 ++ Qb Q vdd gnd ++ sram_2_16_1_sky130_pinv_0 +.ENDS sram_2_16_1_sky130_dff_buf_0 + +.SUBCKT sram_2_16_1_sky130_dff_buf_array ++ din_0 din_1 dout_0 dout_bar_0 dout_1 dout_bar_1 clk vdd gnd +* INPUT : din_0 +* INPUT : din_1 +* OUTPUT: dout_0 +* OUTPUT: dout_bar_0 +* OUTPUT: dout_1 +* OUTPUT: dout_bar_1 +* INPUT : clk +* POWER : vdd +* GROUND: gnd +* rows: 2 cols: 1 +* inv1: 2 inv2: 4 +Xdff_r0_c0 ++ din_0 dout_0 dout_bar_0 clk vdd gnd ++ sram_2_16_1_sky130_dff_buf_0 +Xdff_r1_c0 ++ din_1 dout_1 dout_bar_1 clk vdd gnd ++ sram_2_16_1_sky130_dff_buf_0 +.ENDS sram_2_16_1_sky130_dff_buf_array + +.SUBCKT sram_2_16_1_sky130_pinv_2 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* size: 1 +Xpinv_pmos Z A vdd vdd sky130_fd_pr__pfet_01v8 m=1 w=1.12 l=0.15 pd=2.54 ps=2.54 as=0.42u ad=0.42u +Xpinv_nmos Z A gnd gnd sky130_fd_pr__nfet_01v8 m=1 w=0.36 l=0.15 pd=1.02 ps=1.02 as=0.14u ad=0.14u +.ENDS sram_2_16_1_sky130_pinv_2 + +.SUBCKT sram_2_16_1_sky130_control_logic_rw ++ csb web clk rbl_bl s_en w_en p_en_bar wl_en clk_buf vdd gnd +* INPUT : csb +* INPUT : web +* INPUT : clk +* INPUT : rbl_bl +* OUTPUT: s_en +* OUTPUT: w_en +* OUTPUT: p_en_bar +* OUTPUT: wl_en +* OUTPUT: clk_buf +* POWER : vdd +* GROUND: gnd +* num_rows: 17 +* words_per_row: 1 +* word_size 2 +Xctrl_dffs ++ csb web cs_bar cs we_bar we clk_buf vdd gnd ++ sram_2_16_1_sky130_dff_buf_array +Xclkbuf ++ clk clk_buf vdd gnd ++ sram_2_16_1_sky130_pdriver_0 +Xinv_clk_bar ++ clk_buf clk_bar vdd gnd ++ sram_2_16_1_sky130_pinv_2 +Xand2_gated_clk_bar ++ clk_bar cs gated_clk_bar vdd gnd ++ sram_2_16_1_sky130_pand2 +Xand2_gated_clk_buf ++ clk_buf cs gated_clk_buf vdd gnd ++ sram_2_16_1_sky130_pand2 +Xbuf_wl_en ++ gated_clk_bar wl_en vdd gnd ++ sram_2_16_1_sky130_pdriver_1 +Xrbl_bl_delay_inv ++ rbl_bl_delay rbl_bl_delay_bar vdd gnd ++ sram_2_16_1_sky130_pinv_2 +Xw_en_and ++ we rbl_bl_delay_bar gated_clk_bar w_en vdd gnd ++ sram_2_16_1_sky130_pand3 +Xbuf_s_en_and ++ rbl_bl_delay gated_clk_bar we_bar s_en vdd gnd ++ sram_2_16_1_sky130_pand3_0 +Xdelay_chain ++ rbl_bl rbl_bl_delay vdd gnd ++ sram_2_16_1_sky130_delay_chain +Xnand_p_en_bar ++ gated_clk_buf rbl_bl_delay p_en_bar_unbuf vdd gnd ++ sram_2_16_1_sky130_pnand2_0 +Xbuf_p_en_bar ++ p_en_bar_unbuf p_en_bar vdd gnd ++ sram_2_16_1_sky130_pdriver_4 +.ENDS sram_2_16_1_sky130_control_logic_rw + +.SUBCKT sram_2_16_1_sky130_spare_wen_dff ++ din_0 dout_0 clk vdd gnd +* INPUT : din_0 +* OUTPUT: dout_0 +* INPUT : clk +* POWER : vdd +* GROUND: gnd +* rows: 1 cols: 1 +Xdff_r0_c0 ++ din_0 dout_0 CLK VDD GND ++ sky130_fd_bd_sram__openram_dff +.ENDS sram_2_16_1_sky130_spare_wen_dff + +.SUBCKT sram_2_16_1_sky130 ++ din0[0] din0[1] din0[2] addr0[0] addr0[1] addr0[2] addr0[3] addr0[4] ++ csb0 web0 clk0 spare_wen0 dout0[0] dout0[1] dout0[2] vccd1 vssd1 +* INPUT : din0[0] +* INPUT : din0[1] +* INPUT : din0[2] +* INPUT : addr0[0] +* INPUT : addr0[1] +* INPUT : addr0[2] +* INPUT : addr0[3] +* INPUT : addr0[4] +* INPUT : csb0 +* INPUT : web0 +* INPUT : clk0 +* INPUT : spare_wen0 +* OUTPUT: dout0[0] +* OUTPUT: dout0[1] +* OUTPUT: dout0[2] +* POWER : vccd1 +* GROUND: vssd1 +Xbank0 ++ dout0[0] dout0[1] dout0[2] rbl_bl0 bank_din0_0 bank_din0_1 bank_din0_2 ++ a0_0 a0_1 a0_2 a0_3 a0_4 s_en0 p_en_bar0 w_en0 bank_spare_wen0_0 ++ wl_en0 vccd1 vssd1 ++ sram_2_16_1_sky130_bank +Xcontrol0 ++ csb0 web0 clk0 rbl_bl0 s_en0 w_en0 p_en_bar0 wl_en0 clk_buf0 vccd1 ++ vssd1 ++ sram_2_16_1_sky130_control_logic_rw +Xrow_address0 ++ addr0[0] addr0[1] addr0[2] addr0[3] addr0[4] a0_0 a0_1 a0_2 a0_3 a0_4 ++ clk_buf0 vccd1 vssd1 ++ sram_2_16_1_sky130_row_addr_dff +Xdata_dff0 ++ din0[0] din0[1] din0[2] bank_din0_0 bank_din0_1 bank_din0_2 clk_buf0 ++ vccd1 vssd1 ++ sram_2_16_1_sky130_data_dff +Xspare_wen_dff0 ++ spare_wen0[0] bank_spare_wen0_0 clk_buf0 vccd1 vssd1 ++ sram_2_16_1_sky130_spare_wen_dff +.ENDS sram_2_16_1_sky130 diff --git a/compiler/tests/sp_files/sram_2_16_1_sky130.sp b/compiler/tests/sp_files/sram_2_16_1_sky130.sp new file mode 100644 index 00000000..d68dde96 --- /dev/null +++ b/compiler/tests/sp_files/sram_2_16_1_sky130.sp @@ -0,0 +1,2400 @@ +************************************************** +* OpenRAM generated memory. +* Words: 16 +* Data bits: 2 +* Banks: 1 +* Column mux: 1:1 +* Trimmed: False +* LVS: False +************************************************** +* Copyright 2020 The SkyWater PDK Authors +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +* SPDX-License-Identifier: Apache-2.0 + +* SPICE3 file created from sky130_fd_bd_sram__openram_dff.ext - technology: EFS8A + +.subckt sky130_fd_bd_sram__openram_dff D Q CLK VDD GND +X1000 a_511_725# a_n8_115# VDD VDD sky130_fd_pr__pfet_01v8 W=3 L=0.15 +X1001 a_353_115# CLK a_11_624# GND sky130_fd_pr__nfet_01v8 W=1 L=0.15 +X1002 a_353_725# a_203_89# a_11_624# VDD sky130_fd_pr__pfet_01v8 W=3 L=0.15 +X1003 a_11_624# a_203_89# a_161_115# GND sky130_fd_pr__nfet_01v8 W=1 L=0.15 +X1004 a_11_624# CLK a_161_725# VDD sky130_fd_pr__pfet_01v8 W=3 L=0.15 +X1005 GND Q a_703_115# GND sky130_fd_pr__nfet_01v8 W=1 L=0.15 +X1006 VDD Q a_703_725# VDD sky130_fd_pr__pfet_01v8 W=3 L=0.15 +X1007 a_203_89# CLK GND GND sky130_fd_pr__nfet_01v8 W=1 L=0.15 +X1008 a_203_89# CLK VDD VDD sky130_fd_pr__pfet_01v8 W=3 L=0.15 +X1009 a_161_115# D GND GND sky130_fd_pr__nfet_01v8 W=1 L=0.15 +X1010 a_161_725# D VDD VDD sky130_fd_pr__pfet_01v8 W=3 L=0.15 +X1011 GND a_11_624# a_n8_115# GND sky130_fd_pr__nfet_01v8 W=1 L=0.15 +X1012 a_703_115# a_203_89# ON GND sky130_fd_pr__nfet_01v8 W=1 L=0.15 +X1013 VDD a_11_624# a_n8_115# VDD sky130_fd_pr__pfet_01v8 W=3 L=0.15 +X1014 a_703_725# CLK ON VDD sky130_fd_pr__pfet_01v8 W=3 L=0.15 +X1015 Q ON VDD VDD sky130_fd_pr__pfet_01v8 W=3 L=0.15 +X1016 Q ON GND GND sky130_fd_pr__nfet_01v8 W=1 L=0.15 +X1017 ON a_203_89# a_511_725# VDD sky130_fd_pr__pfet_01v8 W=3 L=0.15 +X1018 ON CLK a_511_115# GND sky130_fd_pr__nfet_01v8 W=1 L=0.15 +X1019 GND a_n8_115# a_353_115# GND sky130_fd_pr__nfet_01v8 W=1 L=0.15 +X1020 VDD a_n8_115# a_353_725# VDD sky130_fd_pr__pfet_01v8 W=3 L=0.15 +X1021 a_511_115# a_n8_115# GND GND sky130_fd_pr__nfet_01v8 W=1 L=0.15 +.ends + +.SUBCKT sram_2_16_1_sky130_row_addr_dff ++ din_0 din_1 din_2 din_3 din_4 dout_0 dout_1 dout_2 dout_3 dout_4 clk ++ vdd gnd +* INPUT : din_0 +* INPUT : din_1 +* INPUT : din_2 +* INPUT : din_3 +* INPUT : din_4 +* OUTPUT: dout_0 +* OUTPUT: dout_1 +* OUTPUT: dout_2 +* OUTPUT: dout_3 +* OUTPUT: dout_4 +* INPUT : clk +* POWER : vdd +* GROUND: gnd +* rows: 5 cols: 1 +Xdff_r0_c0 ++ din_0 dout_0 CLK VDD GND ++ sky130_fd_bd_sram__openram_dff +Xdff_r1_c0 ++ din_1 dout_1 CLK VDD GND ++ sky130_fd_bd_sram__openram_dff +Xdff_r2_c0 ++ din_2 dout_2 CLK VDD GND ++ sky130_fd_bd_sram__openram_dff +Xdff_r3_c0 ++ din_3 dout_3 CLK VDD GND ++ sky130_fd_bd_sram__openram_dff +Xdff_r4_c0 ++ din_4 dout_4 CLK VDD GND ++ sky130_fd_bd_sram__openram_dff +.ENDS sram_2_16_1_sky130_row_addr_dff + +.SUBCKT sram_2_16_1_sky130_data_dff ++ din_0 din_1 din_2 dout_0 dout_1 dout_2 clk vdd gnd +* INPUT : din_0 +* INPUT : din_1 +* INPUT : din_2 +* OUTPUT: dout_0 +* OUTPUT: dout_1 +* OUTPUT: dout_2 +* INPUT : clk +* POWER : vdd +* GROUND: gnd +* rows: 1 cols: 3 +Xdff_r0_c0 ++ din_0 dout_0 CLK VDD GND ++ sky130_fd_bd_sram__openram_dff +Xdff_r0_c1 ++ din_1 dout_1 CLK VDD GND ++ sky130_fd_bd_sram__openram_dff +Xdff_r0_c2 ++ din_2 dout_2 CLK VDD GND ++ sky130_fd_bd_sram__openram_dff +.ENDS sram_2_16_1_sky130_data_dff + +* spice ptx X{0} {1} sky130_fd_pr__nfet_01v8 m=1 w=0.36 l=0.15 pd=1.02 ps=1.02 as=0.14u ad=0.14u + +* spice ptx X{0} {1} sky130_fd_pr__pfet_01v8 m=1 w=1.12 l=0.15 pd=2.54 ps=2.54 as=0.42u ad=0.42u + +.SUBCKT sram_2_16_1_sky130_pinv_dec ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* size: 1 +Xpinv_pmos Z A vdd vdd sky130_fd_pr__pfet_01v8 m=1 w=1.12 l=0.15 pd=2.54 ps=2.54 as=0.42u ad=0.42u +Xpinv_nmos Z A gnd gnd sky130_fd_pr__nfet_01v8 m=1 w=0.36 l=0.15 pd=1.02 ps=1.02 as=0.14u ad=0.14u +.ENDS sram_2_16_1_sky130_pinv_dec +* Copyright 2020 The SkyWater PDK Authors +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +* SPDX-License-Identifier: Apache-2.0 + +* NGSPICE file created from sky130_fd_bd_sram__openram_sp_nand2_dec.ext - technology: EFS8A + + +* Top level circuit sky130_fd_bd_sram__openram_sp_nand2_dec +.subckt sky130_fd_bd_sram__openram_sp_nand2_dec A B Z VDD GND + +X1001 Z B VDD VDD sky130_fd_pr__pfet_01v8 W=1.12 L=0.15 +X1002 VDD A Z VDD sky130_fd_pr__pfet_01v8 W=1.12 L=0.15 +X1000 Z A a_n722_276# GND sky130_fd_pr__nfet_01v8 W=0.74 L=0.15 +X1003 a_n722_276# B GND GND sky130_fd_pr__nfet_01v8 W=0.74 L=0.15 +.ends + + +.SUBCKT sram_2_16_1_sky130_and2_dec ++ A B Z vdd gnd +* INPUT : A +* INPUT : B +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* size: 1 +Xpand2_dec_nand ++ A B zb_int vdd gnd ++ sky130_fd_bd_sram__openram_sp_nand2_dec +Xpand2_dec_inv ++ zb_int Z vdd gnd ++ sram_2_16_1_sky130_pinv_dec +.ENDS sram_2_16_1_sky130_and2_dec + +.SUBCKT sram_2_16_1_sky130_hierarchical_predecode2x4 ++ in_0 in_1 out_0 out_1 out_2 out_3 vdd gnd +* INPUT : in_0 +* INPUT : in_1 +* OUTPUT: out_0 +* OUTPUT: out_1 +* OUTPUT: out_2 +* OUTPUT: out_3 +* POWER : vdd +* GROUND: gnd +Xpre_inv_0 ++ in_0 inbar_0 vdd gnd ++ sram_2_16_1_sky130_pinv_dec +Xpre_inv_1 ++ in_1 inbar_1 vdd gnd ++ sram_2_16_1_sky130_pinv_dec +XXpre2x4_and_0 ++ inbar_0 inbar_1 out_0 vdd gnd ++ sram_2_16_1_sky130_and2_dec +XXpre2x4_and_1 ++ in_0 inbar_1 out_1 vdd gnd ++ sram_2_16_1_sky130_and2_dec +XXpre2x4_and_2 ++ inbar_0 in_1 out_2 vdd gnd ++ sram_2_16_1_sky130_and2_dec +XXpre2x4_and_3 ++ in_0 in_1 out_3 vdd gnd ++ sram_2_16_1_sky130_and2_dec +.ENDS sram_2_16_1_sky130_hierarchical_predecode2x4 +* Copyright 2020 The SkyWater PDK Authors +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +* SPDX-License-Identifier: Apache-2.0 + +* NGSPICE file created from sky130_fd_bd_sram__openram_sp_nand3_dec.ext - technology: EFS8A + + +* Top level circuit sky130_fd_bd_sram__openram_sp_nand3_dec +.subckt sky130_fd_bd_sram__openram_sp_nand3_dec A B C Z VDD GND + +X1001 Z A a_n346_328# GND sky130_fd_pr__nfet_01v8 W=0.74 L=0.15 +X1002 a_n346_256# C GND GND sky130_fd_pr__nfet_01v8 W=0.74 L=0.15 +X1003 a_n346_328# B a_n346_256# GND sky130_fd_pr__nfet_01v8 W=0.74 L=0.15 +X1000 Z B VDD VDD sky130_fd_pr__pfet_01v8 W=1.12 L=0.15 +X1004 Z A VDD VDD sky130_fd_pr__pfet_01v8 W=1.12 L=0.15 +X1005 Z C VDD VDD sky130_fd_pr__pfet_01v8 W=1.12 L=0.15 +.ends + + +.SUBCKT sram_2_16_1_sky130_and3_dec ++ A B C Z vdd gnd +* INPUT : A +* INPUT : B +* INPUT : C +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* size: 1 +Xpand3_dec_nand ++ A B C zb_int vdd gnd ++ sky130_fd_bd_sram__openram_sp_nand3_dec +Xpand3_dec_inv ++ zb_int Z vdd gnd ++ sram_2_16_1_sky130_pinv_dec +.ENDS sram_2_16_1_sky130_and3_dec + +.SUBCKT sram_2_16_1_sky130_hierarchical_predecode3x8 ++ in_0 in_1 in_2 out_0 out_1 out_2 out_3 out_4 out_5 out_6 out_7 vdd gnd +* INPUT : in_0 +* INPUT : in_1 +* INPUT : in_2 +* OUTPUT: out_0 +* OUTPUT: out_1 +* OUTPUT: out_2 +* OUTPUT: out_3 +* OUTPUT: out_4 +* OUTPUT: out_5 +* OUTPUT: out_6 +* OUTPUT: out_7 +* POWER : vdd +* GROUND: gnd +Xpre_inv_0 ++ in_0 inbar_0 vdd gnd ++ sram_2_16_1_sky130_pinv_dec +Xpre_inv_1 ++ in_1 inbar_1 vdd gnd ++ sram_2_16_1_sky130_pinv_dec +Xpre_inv_2 ++ in_2 inbar_2 vdd gnd ++ sram_2_16_1_sky130_pinv_dec +XXpre3x8_and_0 ++ inbar_0 inbar_1 inbar_2 out_0 vdd gnd ++ sram_2_16_1_sky130_and3_dec +XXpre3x8_and_1 ++ in_0 inbar_1 inbar_2 out_1 vdd gnd ++ sram_2_16_1_sky130_and3_dec +XXpre3x8_and_2 ++ inbar_0 in_1 inbar_2 out_2 vdd gnd ++ sram_2_16_1_sky130_and3_dec +XXpre3x8_and_3 ++ in_0 in_1 inbar_2 out_3 vdd gnd ++ sram_2_16_1_sky130_and3_dec +XXpre3x8_and_4 ++ inbar_0 inbar_1 in_2 out_4 vdd gnd ++ sram_2_16_1_sky130_and3_dec +XXpre3x8_and_5 ++ in_0 inbar_1 in_2 out_5 vdd gnd ++ sram_2_16_1_sky130_and3_dec +XXpre3x8_and_6 ++ inbar_0 in_1 in_2 out_6 vdd gnd ++ sram_2_16_1_sky130_and3_dec +XXpre3x8_and_7 ++ in_0 in_1 in_2 out_7 vdd gnd ++ sram_2_16_1_sky130_and3_dec +.ENDS sram_2_16_1_sky130_hierarchical_predecode3x8 + +.SUBCKT sram_2_16_1_sky130_hierarchical_decoder ++ addr_0 addr_1 addr_2 addr_3 addr_4 decode_0 decode_1 decode_2 decode_3 ++ decode_4 decode_5 decode_6 decode_7 decode_8 decode_9 decode_10 ++ decode_11 decode_12 decode_13 decode_14 decode_15 decode_16 vdd gnd +* INPUT : addr_0 +* INPUT : addr_1 +* INPUT : addr_2 +* INPUT : addr_3 +* INPUT : addr_4 +* OUTPUT: decode_0 +* OUTPUT: decode_1 +* OUTPUT: decode_2 +* OUTPUT: decode_3 +* OUTPUT: decode_4 +* OUTPUT: decode_5 +* OUTPUT: decode_6 +* OUTPUT: decode_7 +* OUTPUT: decode_8 +* OUTPUT: decode_9 +* OUTPUT: decode_10 +* OUTPUT: decode_11 +* OUTPUT: decode_12 +* OUTPUT: decode_13 +* OUTPUT: decode_14 +* OUTPUT: decode_15 +* OUTPUT: decode_16 +* POWER : vdd +* GROUND: gnd +Xpre_0 ++ addr_0 addr_1 out_0 out_1 out_2 out_3 vdd gnd ++ sram_2_16_1_sky130_hierarchical_predecode2x4 +Xpre3x8_0 ++ addr_2 addr_3 addr_4 out_4 out_5 out_6 out_7 out_8 out_9 out_10 out_11 ++ vdd gnd ++ sram_2_16_1_sky130_hierarchical_predecode3x8 +XDEC_AND_0 ++ out_0 out_4 decode_0 vdd gnd ++ sram_2_16_1_sky130_and2_dec +XDEC_AND_4 ++ out_0 out_5 decode_4 vdd gnd ++ sram_2_16_1_sky130_and2_dec +XDEC_AND_8 ++ out_0 out_6 decode_8 vdd gnd ++ sram_2_16_1_sky130_and2_dec +XDEC_AND_12 ++ out_0 out_7 decode_12 vdd gnd ++ sram_2_16_1_sky130_and2_dec +XDEC_AND_16 ++ out_0 out_8 decode_16 vdd gnd ++ sram_2_16_1_sky130_and2_dec +XDEC_AND_1 ++ out_1 out_4 decode_1 vdd gnd ++ sram_2_16_1_sky130_and2_dec +XDEC_AND_5 ++ out_1 out_5 decode_5 vdd gnd ++ sram_2_16_1_sky130_and2_dec +XDEC_AND_9 ++ out_1 out_6 decode_9 vdd gnd ++ sram_2_16_1_sky130_and2_dec +XDEC_AND_13 ++ out_1 out_7 decode_13 vdd gnd ++ sram_2_16_1_sky130_and2_dec +XDEC_AND_2 ++ out_2 out_4 decode_2 vdd gnd ++ sram_2_16_1_sky130_and2_dec +XDEC_AND_6 ++ out_2 out_5 decode_6 vdd gnd ++ sram_2_16_1_sky130_and2_dec +XDEC_AND_10 ++ out_2 out_6 decode_10 vdd gnd ++ sram_2_16_1_sky130_and2_dec +XDEC_AND_14 ++ out_2 out_7 decode_14 vdd gnd ++ sram_2_16_1_sky130_and2_dec +XDEC_AND_3 ++ out_3 out_4 decode_3 vdd gnd ++ sram_2_16_1_sky130_and2_dec +XDEC_AND_7 ++ out_3 out_5 decode_7 vdd gnd ++ sram_2_16_1_sky130_and2_dec +XDEC_AND_11 ++ out_3 out_6 decode_11 vdd gnd ++ sram_2_16_1_sky130_and2_dec +XDEC_AND_15 ++ out_3 out_7 decode_15 vdd gnd ++ sram_2_16_1_sky130_and2_dec +.ENDS sram_2_16_1_sky130_hierarchical_decoder + +.SUBCKT sram_2_16_1_sky130_and2_dec_0 ++ A B Z vdd gnd +* INPUT : A +* INPUT : B +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* size: 1 +Xpand2_dec_nand ++ A B zb_int vdd gnd ++ sky130_fd_bd_sram__openram_sp_nand2_dec +Xpand2_dec_inv ++ zb_int Z vdd gnd ++ sram_2_16_1_sky130_pinv_dec +.ENDS sram_2_16_1_sky130_and2_dec_0 + +.SUBCKT sram_2_16_1_sky130_wordline_driver ++ A B Z vdd gnd +* INPUT : A +* INPUT : B +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* cols: 3 +Xwld_nand ++ A B zb_int vdd gnd ++ sky130_fd_bd_sram__openram_sp_nand2_dec +Xwl_driver ++ zb_int Z vdd gnd ++ sram_2_16_1_sky130_pinv_dec +.ENDS sram_2_16_1_sky130_wordline_driver + +.SUBCKT sram_2_16_1_sky130_wordline_driver_array ++ in_0 in_1 in_2 in_3 in_4 in_5 in_6 in_7 in_8 in_9 in_10 in_11 in_12 ++ in_13 in_14 in_15 in_16 wl_0 wl_1 wl_2 wl_3 wl_4 wl_5 wl_6 wl_7 wl_8 ++ wl_9 wl_10 wl_11 wl_12 wl_13 wl_14 wl_15 wl_16 en vdd gnd +* INPUT : in_0 +* INPUT : in_1 +* INPUT : in_2 +* INPUT : in_3 +* INPUT : in_4 +* INPUT : in_5 +* INPUT : in_6 +* INPUT : in_7 +* INPUT : in_8 +* INPUT : in_9 +* INPUT : in_10 +* INPUT : in_11 +* INPUT : in_12 +* INPUT : in_13 +* INPUT : in_14 +* INPUT : in_15 +* INPUT : in_16 +* OUTPUT: wl_0 +* OUTPUT: wl_1 +* OUTPUT: wl_2 +* OUTPUT: wl_3 +* OUTPUT: wl_4 +* OUTPUT: wl_5 +* OUTPUT: wl_6 +* OUTPUT: wl_7 +* OUTPUT: wl_8 +* OUTPUT: wl_9 +* OUTPUT: wl_10 +* OUTPUT: wl_11 +* OUTPUT: wl_12 +* OUTPUT: wl_13 +* OUTPUT: wl_14 +* OUTPUT: wl_15 +* OUTPUT: wl_16 +* INPUT : en +* POWER : vdd +* GROUND: gnd +* rows: 17 cols: 3 +Xwl_driver_and0 ++ in_0 en wl_0 vdd gnd ++ sram_2_16_1_sky130_wordline_driver +Xwl_driver_and1 ++ in_1 en wl_1 vdd gnd ++ sram_2_16_1_sky130_wordline_driver +Xwl_driver_and2 ++ in_2 en wl_2 vdd gnd ++ sram_2_16_1_sky130_wordline_driver +Xwl_driver_and3 ++ in_3 en wl_3 vdd gnd ++ sram_2_16_1_sky130_wordline_driver +Xwl_driver_and4 ++ in_4 en wl_4 vdd gnd ++ sram_2_16_1_sky130_wordline_driver +Xwl_driver_and5 ++ in_5 en wl_5 vdd gnd ++ sram_2_16_1_sky130_wordline_driver +Xwl_driver_and6 ++ in_6 en wl_6 vdd gnd ++ sram_2_16_1_sky130_wordline_driver +Xwl_driver_and7 ++ in_7 en wl_7 vdd gnd ++ sram_2_16_1_sky130_wordline_driver +Xwl_driver_and8 ++ in_8 en wl_8 vdd gnd ++ sram_2_16_1_sky130_wordline_driver +Xwl_driver_and9 ++ in_9 en wl_9 vdd gnd ++ sram_2_16_1_sky130_wordline_driver +Xwl_driver_and10 ++ in_10 en wl_10 vdd gnd ++ sram_2_16_1_sky130_wordline_driver +Xwl_driver_and11 ++ in_11 en wl_11 vdd gnd ++ sram_2_16_1_sky130_wordline_driver +Xwl_driver_and12 ++ in_12 en wl_12 vdd gnd ++ sram_2_16_1_sky130_wordline_driver +Xwl_driver_and13 ++ in_13 en wl_13 vdd gnd ++ sram_2_16_1_sky130_wordline_driver +Xwl_driver_and14 ++ in_14 en wl_14 vdd gnd ++ sram_2_16_1_sky130_wordline_driver +Xwl_driver_and15 ++ in_15 en wl_15 vdd gnd ++ sram_2_16_1_sky130_wordline_driver +Xwl_driver_and16 ++ in_16 en wl_16 vdd gnd ++ sram_2_16_1_sky130_wordline_driver +.ENDS sram_2_16_1_sky130_wordline_driver_array + +.SUBCKT sram_2_16_1_sky130_port_address ++ addr_0 addr_1 addr_2 addr_3 addr_4 wl_en wl_0 wl_1 wl_2 wl_3 wl_4 wl_5 ++ wl_6 wl_7 wl_8 wl_9 wl_10 wl_11 wl_12 wl_13 wl_14 wl_15 wl_16 rbl_wl ++ vdd gnd +* INPUT : addr_0 +* INPUT : addr_1 +* INPUT : addr_2 +* INPUT : addr_3 +* INPUT : addr_4 +* INPUT : wl_en +* OUTPUT: wl_0 +* OUTPUT: wl_1 +* OUTPUT: wl_2 +* OUTPUT: wl_3 +* OUTPUT: wl_4 +* OUTPUT: wl_5 +* OUTPUT: wl_6 +* OUTPUT: wl_7 +* OUTPUT: wl_8 +* OUTPUT: wl_9 +* OUTPUT: wl_10 +* OUTPUT: wl_11 +* OUTPUT: wl_12 +* OUTPUT: wl_13 +* OUTPUT: wl_14 +* OUTPUT: wl_15 +* OUTPUT: wl_16 +* OUTPUT: rbl_wl +* POWER : vdd +* GROUND: gnd +Xrow_decoder ++ addr_0 addr_1 addr_2 addr_3 addr_4 dec_out_0 dec_out_1 dec_out_2 ++ dec_out_3 dec_out_4 dec_out_5 dec_out_6 dec_out_7 dec_out_8 dec_out_9 ++ dec_out_10 dec_out_11 dec_out_12 dec_out_13 dec_out_14 dec_out_15 ++ dec_out_16 vdd gnd ++ sram_2_16_1_sky130_hierarchical_decoder +Xwordline_driver ++ dec_out_0 dec_out_1 dec_out_2 dec_out_3 dec_out_4 dec_out_5 dec_out_6 ++ dec_out_7 dec_out_8 dec_out_9 dec_out_10 dec_out_11 dec_out_12 ++ dec_out_13 dec_out_14 dec_out_15 dec_out_16 wl_0 wl_1 wl_2 wl_3 wl_4 ++ wl_5 wl_6 wl_7 wl_8 wl_9 wl_10 wl_11 wl_12 wl_13 wl_14 wl_15 wl_16 ++ wl_en vdd gnd ++ sram_2_16_1_sky130_wordline_driver_array +Xrbl_driver ++ wl_en vdd rbl_wl vdd gnd ++ sram_2_16_1_sky130_and2_dec_0 +.ENDS sram_2_16_1_sky130_port_address +* NGSPICE file created from sky130_fd_bd_sram__sram_sp_colenda_cent.ext - technology: sky130A + +.subckt sky130_fd_bd_sram__sram_sp_colenda_cent VPWR VPB VNB +.ends +* NGSPICE file created from sky130_fd_bd_sram__sram_sp_colenda.ext - technology: sky130A + +.subckt sky130_fd_bd_sram__sram_sp_colenda bl vdd gnd br gate vpb vnb +*X0 br gate br vnb sky130_fd_pr__special_nfet_pass w=0.065u l=0.17u +.ends + +* NGSPICE file created from sky130_fd_bd_sram__sram_sp_colenda_p_cent.ext - technology: sky130A + +.subckt sky130_fd_bd_sram__sram_sp_colenda_p_cent VGND VPB VNB +.ends + +.SUBCKT sram_2_16_1_sky130_sky130_col_cap_array_0 ++ fake_bl_0 fake_br_0 fake_bl_1 fake_br_1 fake_bl_2 fake_br_2 vdd gnd ++ gate +* OUTPUT: fake_bl_0 +* OUTPUT: fake_br_0 +* OUTPUT: fake_bl_1 +* OUTPUT: fake_br_1 +* OUTPUT: fake_bl_2 +* OUTPUT: fake_br_2 +* POWER : vdd +* GROUND: gnd +* BIAS : gate +Xrca_bottom_0 ++ fake_bl_0 vdd gnd fake_br_0 gate vdd gnd ++ sky130_fd_bd_sram__sram_sp_colenda +Xrca_bottom_1 ++ vdd vdd gnd ++ sky130_fd_bd_sram__sram_sp_colenda_cent +Xrca_bottom_2 ++ fake_bl_1 vdd gnd fake_br_1 gate vdd gnd ++ sky130_fd_bd_sram__sram_sp_colenda +Xrca_bottom_3 ++ gnd vdd vnb ++ sky130_fd_bd_sram__sram_sp_colenda_p_cent +Xrca_bottom_4 ++ fake_bl_2 vdd gnd fake_br_2 gate vdd gnd ++ sky130_fd_bd_sram__sram_sp_colenda +.ENDS sram_2_16_1_sky130_sky130_col_cap_array_0 +* NGSPICE file created from sky130_fd_bd_sram__sram_sp_wlstrap_p.ext - technology: sky130A + +.subckt sky130_fd_bd_sram__sram_sp_wlstrap_p VGND +.ends +* NGSPICE file created from sky130_fd_bd_sram__openram_sp_cell_opt1a_replica.ext - technology: sky130A + +.subckt sky130_fd_bd_sram__openram_sp_cell_opt1a_replica BL BR VGND VPWR VPB VNB WL +X0 VPWR WL BR VNB sky130_fd_pr__special_nfet_pass ad=4.375e+10p pd=920000u as=1.68e+10p ps=520000u w=140000u l=150000u +X1 Q VPWR VGND VNB sky130_fd_pr__special_nfet_latch ad=1.56e+11p pd=2.38e+06u as=8.08e+10p ps=1.28e+06u w=210000u l=150000u +X2 BL WL Q VNB sky130_fd_pr__special_nfet_pass ad=1.68e+10p pd=520000u as=4.25e+10p ps=920000u w=140000u l=150000u +*X3 Q WL Q VPB sky130_fd_pr__special_pfet_pass ad=3.5e+10p pd=780000u as=0p ps=0u w=70000u l=95000u +*X4 VPWR WL VPWR VPB sky130_fd_pr__special_pfet_pass ad=9.72e+10p pd=1.86e+06u as=0p ps=0u w=70000u l=95000u +X5 VPWR Q VPWR VPB sky130_fd_pr__special_pfet_pass ad=0p pd=0u as=0p ps=0u w=140000u l=150000u +X6 Q VPWR VPWR VPB sky130_fd_pr__special_pfet_pass ad=0p pd=0u as=0p ps=0u w=140000u l=150000u +X7 VGND Q VPWR VNB sky130_fd_pr__special_nfet_latch ad=0p pd=0u as=0p ps=0u w=210000u l=150000u +.ends +* NGSPICE file created from sky130_fd_bd_sram__sram_sp_colend_p_cent.ext - technology: sky130A + +.subckt sky130_fd_bd_sram__sram_sp_colend_p_cent VGND VPB VNB +.ends +* NGSPICE file created from sky130_fd_bd_sram__sram_sp_wlstrapa_p.ext - technology: sky130A + +.subckt sky130_fd_bd_sram__sram_sp_wlstrapa_p VGND +.ends +* NGSPICE file created from sky130_fd_bd_sram__openram_sp_cell_opt1_replica.ext - technology: sky130A + +.subckt sky130_fd_bd_sram__openram_sp_cell_opt1_replica BL BR VGND VPWR VPB VNB WL +X0 VPWR WL BR VNB sky130_fd_pr__special_nfet_pass ad=4.375e+10p pd=920000u as=1.68e+10p ps=520000u w=140000u l=150000u +X1 Q VPWR VGND VNB sky130_fd_pr__special_nfet_latch ad=1.56e+11p pd=2.38e+06u as=8.08e+10p ps=1.28e+06u w=210000u l=150000u +X2 BL WL Q VNB sky130_fd_pr__special_nfet_pass ad=1.68e+10p pd=520000u as=4.25e+10p ps=920000u w=140000u l=150000u +*X3 Q WL Q VPB sky130_fd_pr__special_pfet_pass ad=3.5e+10p pd=780000u as=0p ps=0u w=70000u l=95000u +*X4 VPWR WL VPWR VPB sky130_fd_pr__special_pfet_pass ad=9.72e+10p pd=1.86e+06u as=0p ps=0u w=70000u l=95000u +X5 VPWR Q VPWR VPB sky130_fd_pr__special_pfet_pass ad=0p pd=0u as=0p ps=0u w=140000u l=150000u +X6 Q VPWR VPWR VPB sky130_fd_pr__special_pfet_pass ad=0p pd=0u as=0p ps=0u w=140000u l=150000u +X7 VGND Q VPWR VNB sky130_fd_pr__special_nfet_latch ad=0p pd=0u as=0p ps=0u w=210000u l=150000u +.ends +* NGSPICE file created from sky130_fd_bd_sram__sram_sp_colend.ext - technology: sky130A + +.subckt sky130_fd_bd_sram__sram_sp_colend bl vdd gnd br gate vpb vnb +*X0 br gate br vnb sky130_fd_pr__special_nfet_pass w=0.07u l=0.21u +.ends + + +.SUBCKT sram_2_16_1_sky130_sky130_replica_column ++ bl_0_0 br_0_0 wl_0_1 wl_0_2 wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 wl_0_8 ++ wl_0_9 wl_0_10 wl_0_11 wl_0_12 wl_0_13 wl_0_14 wl_0_15 wl_0_16 wl_0_17 ++ wl_0_18 vdd gnd top_gate bot_gate +* OUTPUT: bl_0_0 +* OUTPUT: br_0_0 +* INPUT : wl_0_1 +* INPUT : wl_0_2 +* INPUT : wl_0_3 +* INPUT : wl_0_4 +* INPUT : wl_0_5 +* INPUT : wl_0_6 +* INPUT : wl_0_7 +* INPUT : wl_0_8 +* INPUT : wl_0_9 +* INPUT : wl_0_10 +* INPUT : wl_0_11 +* INPUT : wl_0_12 +* INPUT : wl_0_13 +* INPUT : wl_0_14 +* INPUT : wl_0_15 +* INPUT : wl_0_16 +* INPUT : wl_0_17 +* INPUT : wl_0_18 +* POWER : vdd +* GROUND: gnd +* INPUT : top_gate +* INPUT : bot_gate +Xrbc_0 ++ bl_0_0 vdd gnd br_0_0 top_gate vdd gnd ++ sky130_fd_bd_sram__sram_sp_colend +Xrbc_0_cap ++ gnd vdd gnd ++ sky130_fd_bd_sram__sram_sp_colend_p_cent +Xrbc_1 ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_1 ++ sky130_fd_bd_sram__openram_sp_cell_opt1_replica +Xrbc_1_strap_p ++ gnd ++ sky130_fd_bd_sram__sram_sp_wlstrap_p +Xrbc_2 ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_2 ++ sky130_fd_bd_sram__openram_sp_cell_opt1a_replica +Xrbc_2_strap ++ vdd ++ sky130_fd_bd_sram__sram_sp_wlstrapa_p +Xrbc_3 ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_3 ++ sky130_fd_bd_sram__openram_sp_cell_opt1_replica +Xrbc_3_strap_p ++ gnd ++ sky130_fd_bd_sram__sram_sp_wlstrap_p +Xrbc_4 ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_4 ++ sky130_fd_bd_sram__openram_sp_cell_opt1a_replica +Xrbc_4_strap ++ vdd ++ sky130_fd_bd_sram__sram_sp_wlstrapa_p +Xrbc_5 ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_5 ++ sky130_fd_bd_sram__openram_sp_cell_opt1_replica +Xrbc_5_strap_p ++ gnd ++ sky130_fd_bd_sram__sram_sp_wlstrap_p +Xrbc_6 ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_6 ++ sky130_fd_bd_sram__openram_sp_cell_opt1a_replica +Xrbc_6_strap ++ vdd ++ sky130_fd_bd_sram__sram_sp_wlstrapa_p +Xrbc_7 ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_7 ++ sky130_fd_bd_sram__openram_sp_cell_opt1_replica +Xrbc_7_strap_p ++ gnd ++ sky130_fd_bd_sram__sram_sp_wlstrap_p +Xrbc_8 ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_8 ++ sky130_fd_bd_sram__openram_sp_cell_opt1a_replica +Xrbc_8_strap ++ vdd ++ sky130_fd_bd_sram__sram_sp_wlstrapa_p +Xrbc_9 ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_9 ++ sky130_fd_bd_sram__openram_sp_cell_opt1_replica +Xrbc_9_strap_p ++ gnd ++ sky130_fd_bd_sram__sram_sp_wlstrap_p +Xrbc_10 ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_10 ++ sky130_fd_bd_sram__openram_sp_cell_opt1a_replica +Xrbc_10_strap ++ vdd ++ sky130_fd_bd_sram__sram_sp_wlstrapa_p +Xrbc_11 ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_11 ++ sky130_fd_bd_sram__openram_sp_cell_opt1_replica +Xrbc_11_strap_p ++ gnd ++ sky130_fd_bd_sram__sram_sp_wlstrap_p +Xrbc_12 ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_12 ++ sky130_fd_bd_sram__openram_sp_cell_opt1a_replica +Xrbc_12_strap ++ vdd ++ sky130_fd_bd_sram__sram_sp_wlstrapa_p +Xrbc_13 ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_13 ++ sky130_fd_bd_sram__openram_sp_cell_opt1_replica +Xrbc_13_strap_p ++ gnd ++ sky130_fd_bd_sram__sram_sp_wlstrap_p +Xrbc_14 ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_14 ++ sky130_fd_bd_sram__openram_sp_cell_opt1a_replica +Xrbc_14_strap ++ vdd ++ sky130_fd_bd_sram__sram_sp_wlstrapa_p +Xrbc_15 ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_15 ++ sky130_fd_bd_sram__openram_sp_cell_opt1_replica +Xrbc_15_strap_p ++ gnd ++ sky130_fd_bd_sram__sram_sp_wlstrap_p +Xrbc_16 ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_16 ++ sky130_fd_bd_sram__openram_sp_cell_opt1a_replica +Xrbc_16_strap ++ vdd ++ sky130_fd_bd_sram__sram_sp_wlstrapa_p +Xrbc_17 ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_17 ++ sky130_fd_bd_sram__openram_sp_cell_opt1_replica +Xrbc_17_strap_p ++ gnd ++ sky130_fd_bd_sram__sram_sp_wlstrap_p +Xrbc_18 ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_18 ++ sky130_fd_bd_sram__openram_sp_cell_opt1a_replica +Xrbc_18_strap ++ vdd ++ sky130_fd_bd_sram__sram_sp_wlstrapa_p +Xrbc_19 ++ bl_0_0 vdd gnd br_0_0 bot_gate vdd gnd ++ sky130_fd_bd_sram__sram_sp_colenda +Xrbc_19_cap ++ gnd vdd gnd ++ sky130_fd_bd_sram__sram_sp_colenda_p_cent +.ENDS sram_2_16_1_sky130_sky130_replica_column +* NGSPICE file created from sky130_fd_bd_sram__sram_sp_colend_cent.ext - technology: sky130A + +.subckt sky130_fd_bd_sram__sram_sp_colend_cent VPWR VPB VNB +.ends + +.SUBCKT sram_2_16_1_sky130_sky130_col_cap_array ++ fake_bl_0 fake_br_0 fake_bl_1 fake_br_1 fake_bl_2 fake_br_2 vdd gnd ++ gate +* OUTPUT: fake_bl_0 +* OUTPUT: fake_br_0 +* OUTPUT: fake_bl_1 +* OUTPUT: fake_br_1 +* OUTPUT: fake_bl_2 +* OUTPUT: fake_br_2 +* POWER : vdd +* GROUND: gnd +* BIAS : gate +Xrca_top_0 ++ fake_bl_0 vdd gnd fake_br_0 gate vdd gnd ++ sky130_fd_bd_sram__sram_sp_colend +Xrca_top_1 ++ vdd vdd gnd ++ sky130_fd_bd_sram__sram_sp_colend_cent +Xrca_top_2 ++ fake_bl_1 vdd gnd fake_br_1 gate vdd gnd ++ sky130_fd_bd_sram__sram_sp_colend +Xrca_top_3 ++ gnd vdd vnb ++ sky130_fd_bd_sram__sram_sp_colend_p_cent +Xrca_top_4 ++ fake_bl_2 vdd gnd fake_br_2 gate vdd gnd ++ sky130_fd_bd_sram__sram_sp_colend +.ENDS sram_2_16_1_sky130_sky130_col_cap_array +* NGSPICE file created from sky130_fd_bd_sram__sram_sp_wlstrapa.ext - technology: sky130A + +.subckt sky130_fd_bd_sram__sram_sp_wlstrapa VPWR +.ends +* NGSPICE file created from sky130_fd_bd_sram__openram_sp_cell_opt1a_dummy.ext - technology: sky130A + +.subckt sky130_fd_bd_sram__openram_sp_cell_opt1a_dummy BL BR VGND VPWR VPB VNB WL +X0 ll WL BR VNB sky130_fd_pr__special_nfet_pass w=0.14 l=0.15 +X1 ul Q_bar_float VGND VNB sky130_fd_pr__special_nfet_latch w=0.21 l=0.15 +X2 BL WL ul VNB sky130_fd_pr__special_nfet_pass w=0.14 l=0.15 +*X3 ur WL ur VPB sky130_fd_pr__special_pfet_pass w=0.07 l=0.095 +*X4 lr WL lr VPB sky130_fd_pr__special_pfet_pass w=0.07 l=0.095 +X5 VPWR Q_float lr VPB sky130_fd_pr__special_pfet_pass w=0.14 l=0.15 +X6 ur Q_bar_float VPWR VPB sky130_fd_pr__special_pfet_pass w=0.14 l=0.15 +X7 VGND Q_float ll VNB sky130_fd_pr__special_nfet_latch w=0.21 l=0.15 +.ends + +.SUBCKT sram_2_16_1_sky130_sky130_dummy_array ++ bl_0_0 br_0_0 bl_0_1 br_0_1 bl_0_2 br_0_2 wl_0_0 vdd gnd +* INOUT : bl_0_0 +* INOUT : br_0_0 +* INOUT : bl_0_1 +* INOUT : br_0_1 +* INOUT : bl_0_2 +* INOUT : br_0_2 +* INPUT : wl_0_0 +* POWER : vdd +* GROUND: gnd +Xrow_0_col_0_bitcell ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_0 ++ sky130_fd_bd_sram__openram_sp_cell_opt1a_dummy +Xrow_0_col_0_wlstrapa ++ vdd ++ sky130_fd_bd_sram__sram_sp_wlstrapa +Xrow_0_col_1_bitcell ++ bl_0_1 br_0_1 gnd vdd vdd gnd wl_0_0 ++ sky130_fd_bd_sram__openram_sp_cell_opt1a_dummy +Xrow_0_col_1_wlstrap_p ++ gnd ++ sky130_fd_bd_sram__sram_sp_wlstrapa_p +Xrow_0_col_2_bitcell ++ bl_0_2 br_0_2 gnd vdd vdd gnd wl_0_0 ++ sky130_fd_bd_sram__openram_sp_cell_opt1a_dummy +.ENDS sram_2_16_1_sky130_sky130_dummy_array +* NGSPICE file created from sky130_fd_bd_sram__sram_sp_cornera.ext - technology: sky130A + +.subckt sky130_fd_bd_sram__sram_sp_cornera VNB VPWR VPB +.ends +* NGSPICE file created from sky130_fd_bd_sram__sram_sp_cornerb.ext - technology: sky130A + +.subckt sky130_fd_bd_sram__sram_sp_cornerb VPWR VPB VNB +.ends +* NGSPICE file created from sky130_fd_bd_sram__sram_sp_rowenda.ext - technology: sky130A + +.subckt sky130_fd_bd_sram__sram_sp_rowenda VPWR WL +.ends +* NGSPICE file created from sky130_fd_bd_sram__sram_sp_rowend.ext - technology: sky130A + +.subckt sky130_fd_bd_sram__sram_sp_rowend VPWR WL +.ends + +.SUBCKT sram_2_16_1_sky130_sky130_row_cap_array_0 ++ wl_0_0 wl_0_1 wl_0_2 wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 wl_0_8 wl_0_9 ++ wl_0_10 wl_0_11 wl_0_12 wl_0_13 wl_0_14 wl_0_15 wl_0_16 wl_0_17 ++ wl_0_18 wl_0_19 vdd gnd +* OUTPUT: wl_0_0 +* OUTPUT: wl_0_1 +* OUTPUT: wl_0_2 +* OUTPUT: wl_0_3 +* OUTPUT: wl_0_4 +* OUTPUT: wl_0_5 +* OUTPUT: wl_0_6 +* OUTPUT: wl_0_7 +* OUTPUT: wl_0_8 +* OUTPUT: wl_0_9 +* OUTPUT: wl_0_10 +* OUTPUT: wl_0_11 +* OUTPUT: wl_0_12 +* OUTPUT: wl_0_13 +* OUTPUT: wl_0_14 +* OUTPUT: wl_0_15 +* OUTPUT: wl_0_16 +* OUTPUT: wl_0_17 +* OUTPUT: wl_0_18 +* OUTPUT: wl_0_19 +* POWER : vdd +* GROUND: gnd +Xrca_0 ++ vdd gnd vdd ++ sky130_fd_bd_sram__sram_sp_cornera +Xrca_1 ++ wl_0_0 vdd ++ sky130_fd_bd_sram__sram_sp_rowenda +Xrca_2 ++ wl_0_1 vdd ++ sky130_fd_bd_sram__sram_sp_rowend +Xrca_3 ++ wl_0_2 vdd ++ sky130_fd_bd_sram__sram_sp_rowenda +Xrca_4 ++ wl_0_3 vdd ++ sky130_fd_bd_sram__sram_sp_rowend +Xrca_5 ++ wl_0_4 vdd ++ sky130_fd_bd_sram__sram_sp_rowenda +Xrca_6 ++ wl_0_5 vdd ++ sky130_fd_bd_sram__sram_sp_rowend +Xrca_7 ++ wl_0_6 vdd ++ sky130_fd_bd_sram__sram_sp_rowenda +Xrca_8 ++ wl_0_7 vdd ++ sky130_fd_bd_sram__sram_sp_rowend +Xrca_9 ++ wl_0_8 vdd ++ sky130_fd_bd_sram__sram_sp_rowenda +Xrca_10 ++ wl_0_9 vdd ++ sky130_fd_bd_sram__sram_sp_rowend +Xrca_11 ++ wl_0_10 vdd ++ sky130_fd_bd_sram__sram_sp_rowenda +Xrca_12 ++ wl_0_11 vdd ++ sky130_fd_bd_sram__sram_sp_rowend +Xrca_13 ++ wl_0_12 vdd ++ sky130_fd_bd_sram__sram_sp_rowenda +Xrca_14 ++ wl_0_13 vdd ++ sky130_fd_bd_sram__sram_sp_rowend +Xrca_15 ++ wl_0_14 vdd ++ sky130_fd_bd_sram__sram_sp_rowenda +Xrca_16 ++ wl_0_15 vdd ++ sky130_fd_bd_sram__sram_sp_rowend +Xrca_17 ++ wl_0_16 vdd ++ sky130_fd_bd_sram__sram_sp_rowenda +Xrca_18 ++ wl_0_17 vdd ++ sky130_fd_bd_sram__sram_sp_rowend +Xrca_19 ++ vdd gnd vdd ++ sky130_fd_bd_sram__sram_sp_cornerb +.ENDS sram_2_16_1_sky130_sky130_row_cap_array_0 +* NGSPICE file created from sky130_fd_bd_sram__sram_sp_cell_opt1a.ext - technology: sky130A + +.subckt sky130_fd_bd_sram__sram_sp_cell_opt1a BL BR VGND VPWR VPB VNB WL +X0 Q_bar WL BR VNB sky130_fd_pr__special_nfet_pass w=0.14 l=0.15 +X1 Q Q_bar VGND VNB sky130_fd_pr__special_nfet_latch w=0.21 l=0.15 +X2 BL WL Q VNB sky130_fd_pr__special_nfet_pass w=0.14 l=0.15 +*X3 Q WL Q VPB sky130_fd_pr__special_pfet_pass w=0.07 l=0.095 +*X4 Q_bar WL Q_bar VPB sky130_fd_pr__special_pfet_pass w=0.07 l=0.095 +X5 VPWR Q Q_bar VPB sky130_fd_pr__special_pfet_pass w=0.14 l=0.15 +X6 Q Q_bar VPWR VPB sky130_fd_pr__special_pfet_pass w=0.14 l=0.15 +X7 VGND Q Q_bar VNB sky130_fd_pr__special_nfet_latch w=0.21 l=0.15 +.ends +* NGSPICE file created from sky130_fd_bd_sram__sram_sp_cell_opt1.ext - technology: sky130A + +.subckt sky130_fd_bd_sram__sram_sp_cell_opt1 BL BR VGND VPWR VPB VNB WL +X0 Q_bar WL BR VNB sky130_fd_pr__special_nfet_pass w=0.14 l=0.15 +X1 Q Q_bar VGND VNB sky130_fd_pr__special_nfet_latch w=0.21 l=0.15 +X2 BL WL Q VNB sky130_fd_pr__special_nfet_pass w=0.14 l=0.15 +*X3 Q WL Q VPB sky130_fd_pr__special_pfet_pass w=0.07 l=0.095 +*X4 Q_bar WL Q_bar VPB sky130_fd_pr__special_pfet_pass w=0.07 l=0.095 +X5 VPWR Q Q_bar VPB sky130_fd_pr__special_pfet_pass w=0.14 l=0.15 +X6 Q Q_bar VPWR VPB sky130_fd_pr__special_pfet_pass w=0.14 l=0.15 +X7 VGND Q Q_bar VNB sky130_fd_pr__special_nfet_latch w=0.21 l=0.15 +.ends +* NGSPICE file created from sky130_fd_bd_sram__sram_sp_wlstrap.ext - technology: sky130A + +.subckt sky130_fd_bd_sram__sram_sp_wlstrap VPWR +.ends + +.SUBCKT sram_2_16_1_sky130_sky130_bitcell_array ++ bl_0_0 br_0_0 bl_0_1 br_0_1 bl_0_2 br_0_2 wl_0_0 wl_0_1 wl_0_2 wl_0_3 ++ wl_0_4 wl_0_5 wl_0_6 wl_0_7 wl_0_8 wl_0_9 wl_0_10 wl_0_11 wl_0_12 ++ wl_0_13 wl_0_14 wl_0_15 wl_0_16 vdd gnd +* INOUT : bl_0_0 +* INOUT : br_0_0 +* INOUT : bl_0_1 +* INOUT : br_0_1 +* INOUT : bl_0_2 +* INOUT : br_0_2 +* INPUT : wl_0_0 +* INPUT : wl_0_1 +* INPUT : wl_0_2 +* INPUT : wl_0_3 +* INPUT : wl_0_4 +* INPUT : wl_0_5 +* INPUT : wl_0_6 +* INPUT : wl_0_7 +* INPUT : wl_0_8 +* INPUT : wl_0_9 +* INPUT : wl_0_10 +* INPUT : wl_0_11 +* INPUT : wl_0_12 +* INPUT : wl_0_13 +* INPUT : wl_0_14 +* INPUT : wl_0_15 +* INPUT : wl_0_16 +* POWER : vdd +* GROUND: gnd +* rows: 17 cols: 3 +Xrow_0_col_0_bitcell ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_0 ++ sky130_fd_bd_sram__sram_sp_cell_opt1 +Xrow_0_col_0_wlstrap ++ vdd ++ sky130_fd_bd_sram__sram_sp_wlstrap +Xrow_0_col_1_bitcell ++ bl_0_1 br_0_1 gnd vdd vdd gnd wl_0_0 ++ sky130_fd_bd_sram__sram_sp_cell_opt1 +Xrow_0_col_1_wlstrap_p ++ gnd ++ sky130_fd_bd_sram__sram_sp_wlstrap_p +Xrow_0_col_2_bitcell ++ bl_0_2 br_0_2 gnd vdd vdd gnd wl_0_0 ++ sky130_fd_bd_sram__sram_sp_cell_opt1 +Xrow_1_col_0_bitcell ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_1 ++ sky130_fd_bd_sram__sram_sp_cell_opt1a +Xrow_1_col_0_wlstrapa ++ vdd ++ sky130_fd_bd_sram__sram_sp_wlstrapa +Xrow_1_col_1_bitcell ++ bl_0_1 br_0_1 gnd vdd vdd gnd wl_0_1 ++ sky130_fd_bd_sram__sram_sp_cell_opt1a +Xrow_1_col_1_wlstrapa_p ++ gnd ++ sky130_fd_bd_sram__sram_sp_wlstrapa_p +Xrow_1_col_2_bitcell ++ bl_0_2 br_0_2 gnd vdd vdd gnd wl_0_1 ++ sky130_fd_bd_sram__sram_sp_cell_opt1a +Xrow_2_col_0_bitcell ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_2 ++ sky130_fd_bd_sram__sram_sp_cell_opt1 +Xrow_2_col_0_wlstrap ++ vdd ++ sky130_fd_bd_sram__sram_sp_wlstrap +Xrow_2_col_1_bitcell ++ bl_0_1 br_0_1 gnd vdd vdd gnd wl_0_2 ++ sky130_fd_bd_sram__sram_sp_cell_opt1 +Xrow_2_col_1_wlstrap_p ++ gnd ++ sky130_fd_bd_sram__sram_sp_wlstrap_p +Xrow_2_col_2_bitcell ++ bl_0_2 br_0_2 gnd vdd vdd gnd wl_0_2 ++ sky130_fd_bd_sram__sram_sp_cell_opt1 +Xrow_3_col_0_bitcell ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_3 ++ sky130_fd_bd_sram__sram_sp_cell_opt1a +Xrow_3_col_0_wlstrapa ++ vdd ++ sky130_fd_bd_sram__sram_sp_wlstrapa +Xrow_3_col_1_bitcell ++ bl_0_1 br_0_1 gnd vdd vdd gnd wl_0_3 ++ sky130_fd_bd_sram__sram_sp_cell_opt1a +Xrow_3_col_1_wlstrapa_p ++ gnd ++ sky130_fd_bd_sram__sram_sp_wlstrapa_p +Xrow_3_col_2_bitcell ++ bl_0_2 br_0_2 gnd vdd vdd gnd wl_0_3 ++ sky130_fd_bd_sram__sram_sp_cell_opt1a +Xrow_4_col_0_bitcell ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_4 ++ sky130_fd_bd_sram__sram_sp_cell_opt1 +Xrow_4_col_0_wlstrap ++ vdd ++ sky130_fd_bd_sram__sram_sp_wlstrap +Xrow_4_col_1_bitcell ++ bl_0_1 br_0_1 gnd vdd vdd gnd wl_0_4 ++ sky130_fd_bd_sram__sram_sp_cell_opt1 +Xrow_4_col_1_wlstrap_p ++ gnd ++ sky130_fd_bd_sram__sram_sp_wlstrap_p +Xrow_4_col_2_bitcell ++ bl_0_2 br_0_2 gnd vdd vdd gnd wl_0_4 ++ sky130_fd_bd_sram__sram_sp_cell_opt1 +Xrow_5_col_0_bitcell ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_5 ++ sky130_fd_bd_sram__sram_sp_cell_opt1a +Xrow_5_col_0_wlstrapa ++ vdd ++ sky130_fd_bd_sram__sram_sp_wlstrapa +Xrow_5_col_1_bitcell ++ bl_0_1 br_0_1 gnd vdd vdd gnd wl_0_5 ++ sky130_fd_bd_sram__sram_sp_cell_opt1a +Xrow_5_col_1_wlstrapa_p ++ gnd ++ sky130_fd_bd_sram__sram_sp_wlstrapa_p +Xrow_5_col_2_bitcell ++ bl_0_2 br_0_2 gnd vdd vdd gnd wl_0_5 ++ sky130_fd_bd_sram__sram_sp_cell_opt1a +Xrow_6_col_0_bitcell ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_6 ++ sky130_fd_bd_sram__sram_sp_cell_opt1 +Xrow_6_col_0_wlstrap ++ vdd ++ sky130_fd_bd_sram__sram_sp_wlstrap +Xrow_6_col_1_bitcell ++ bl_0_1 br_0_1 gnd vdd vdd gnd wl_0_6 ++ sky130_fd_bd_sram__sram_sp_cell_opt1 +Xrow_6_col_1_wlstrap_p ++ gnd ++ sky130_fd_bd_sram__sram_sp_wlstrap_p +Xrow_6_col_2_bitcell ++ bl_0_2 br_0_2 gnd vdd vdd gnd wl_0_6 ++ sky130_fd_bd_sram__sram_sp_cell_opt1 +Xrow_7_col_0_bitcell ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_7 ++ sky130_fd_bd_sram__sram_sp_cell_opt1a +Xrow_7_col_0_wlstrapa ++ vdd ++ sky130_fd_bd_sram__sram_sp_wlstrapa +Xrow_7_col_1_bitcell ++ bl_0_1 br_0_1 gnd vdd vdd gnd wl_0_7 ++ sky130_fd_bd_sram__sram_sp_cell_opt1a +Xrow_7_col_1_wlstrapa_p ++ gnd ++ sky130_fd_bd_sram__sram_sp_wlstrapa_p +Xrow_7_col_2_bitcell ++ bl_0_2 br_0_2 gnd vdd vdd gnd wl_0_7 ++ sky130_fd_bd_sram__sram_sp_cell_opt1a +Xrow_8_col_0_bitcell ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_8 ++ sky130_fd_bd_sram__sram_sp_cell_opt1 +Xrow_8_col_0_wlstrap ++ vdd ++ sky130_fd_bd_sram__sram_sp_wlstrap +Xrow_8_col_1_bitcell ++ bl_0_1 br_0_1 gnd vdd vdd gnd wl_0_8 ++ sky130_fd_bd_sram__sram_sp_cell_opt1 +Xrow_8_col_1_wlstrap_p ++ gnd ++ sky130_fd_bd_sram__sram_sp_wlstrap_p +Xrow_8_col_2_bitcell ++ bl_0_2 br_0_2 gnd vdd vdd gnd wl_0_8 ++ sky130_fd_bd_sram__sram_sp_cell_opt1 +Xrow_9_col_0_bitcell ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_9 ++ sky130_fd_bd_sram__sram_sp_cell_opt1a +Xrow_9_col_0_wlstrapa ++ vdd ++ sky130_fd_bd_sram__sram_sp_wlstrapa +Xrow_9_col_1_bitcell ++ bl_0_1 br_0_1 gnd vdd vdd gnd wl_0_9 ++ sky130_fd_bd_sram__sram_sp_cell_opt1a +Xrow_9_col_1_wlstrapa_p ++ gnd ++ sky130_fd_bd_sram__sram_sp_wlstrapa_p +Xrow_9_col_2_bitcell ++ bl_0_2 br_0_2 gnd vdd vdd gnd wl_0_9 ++ sky130_fd_bd_sram__sram_sp_cell_opt1a +Xrow_10_col_0_bitcell ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_10 ++ sky130_fd_bd_sram__sram_sp_cell_opt1 +Xrow_10_col_0_wlstrap ++ vdd ++ sky130_fd_bd_sram__sram_sp_wlstrap +Xrow_10_col_1_bitcell ++ bl_0_1 br_0_1 gnd vdd vdd gnd wl_0_10 ++ sky130_fd_bd_sram__sram_sp_cell_opt1 +Xrow_10_col_1_wlstrap_p ++ gnd ++ sky130_fd_bd_sram__sram_sp_wlstrap_p +Xrow_10_col_2_bitcell ++ bl_0_2 br_0_2 gnd vdd vdd gnd wl_0_10 ++ sky130_fd_bd_sram__sram_sp_cell_opt1 +Xrow_11_col_0_bitcell ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_11 ++ sky130_fd_bd_sram__sram_sp_cell_opt1a +Xrow_11_col_0_wlstrapa ++ vdd ++ sky130_fd_bd_sram__sram_sp_wlstrapa +Xrow_11_col_1_bitcell ++ bl_0_1 br_0_1 gnd vdd vdd gnd wl_0_11 ++ sky130_fd_bd_sram__sram_sp_cell_opt1a +Xrow_11_col_1_wlstrapa_p ++ gnd ++ sky130_fd_bd_sram__sram_sp_wlstrapa_p +Xrow_11_col_2_bitcell ++ bl_0_2 br_0_2 gnd vdd vdd gnd wl_0_11 ++ sky130_fd_bd_sram__sram_sp_cell_opt1a +Xrow_12_col_0_bitcell ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_12 ++ sky130_fd_bd_sram__sram_sp_cell_opt1 +Xrow_12_col_0_wlstrap ++ vdd ++ sky130_fd_bd_sram__sram_sp_wlstrap +Xrow_12_col_1_bitcell ++ bl_0_1 br_0_1 gnd vdd vdd gnd wl_0_12 ++ sky130_fd_bd_sram__sram_sp_cell_opt1 +Xrow_12_col_1_wlstrap_p ++ gnd ++ sky130_fd_bd_sram__sram_sp_wlstrap_p +Xrow_12_col_2_bitcell ++ bl_0_2 br_0_2 gnd vdd vdd gnd wl_0_12 ++ sky130_fd_bd_sram__sram_sp_cell_opt1 +Xrow_13_col_0_bitcell ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_13 ++ sky130_fd_bd_sram__sram_sp_cell_opt1a +Xrow_13_col_0_wlstrapa ++ vdd ++ sky130_fd_bd_sram__sram_sp_wlstrapa +Xrow_13_col_1_bitcell ++ bl_0_1 br_0_1 gnd vdd vdd gnd wl_0_13 ++ sky130_fd_bd_sram__sram_sp_cell_opt1a +Xrow_13_col_1_wlstrapa_p ++ gnd ++ sky130_fd_bd_sram__sram_sp_wlstrapa_p +Xrow_13_col_2_bitcell ++ bl_0_2 br_0_2 gnd vdd vdd gnd wl_0_13 ++ sky130_fd_bd_sram__sram_sp_cell_opt1a +Xrow_14_col_0_bitcell ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_14 ++ sky130_fd_bd_sram__sram_sp_cell_opt1 +Xrow_14_col_0_wlstrap ++ vdd ++ sky130_fd_bd_sram__sram_sp_wlstrap +Xrow_14_col_1_bitcell ++ bl_0_1 br_0_1 gnd vdd vdd gnd wl_0_14 ++ sky130_fd_bd_sram__sram_sp_cell_opt1 +Xrow_14_col_1_wlstrap_p ++ gnd ++ sky130_fd_bd_sram__sram_sp_wlstrap_p +Xrow_14_col_2_bitcell ++ bl_0_2 br_0_2 gnd vdd vdd gnd wl_0_14 ++ sky130_fd_bd_sram__sram_sp_cell_opt1 +Xrow_15_col_0_bitcell ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_15 ++ sky130_fd_bd_sram__sram_sp_cell_opt1a +Xrow_15_col_0_wlstrapa ++ vdd ++ sky130_fd_bd_sram__sram_sp_wlstrapa +Xrow_15_col_1_bitcell ++ bl_0_1 br_0_1 gnd vdd vdd gnd wl_0_15 ++ sky130_fd_bd_sram__sram_sp_cell_opt1a +Xrow_15_col_1_wlstrapa_p ++ gnd ++ sky130_fd_bd_sram__sram_sp_wlstrapa_p +Xrow_15_col_2_bitcell ++ bl_0_2 br_0_2 gnd vdd vdd gnd wl_0_15 ++ sky130_fd_bd_sram__sram_sp_cell_opt1a +Xrow_16_col_0_bitcell ++ bl_0_0 br_0_0 gnd vdd vdd gnd wl_0_16 ++ sky130_fd_bd_sram__sram_sp_cell_opt1 +Xrow_16_col_0_wlstrap ++ vdd ++ sky130_fd_bd_sram__sram_sp_wlstrap +Xrow_16_col_1_bitcell ++ bl_0_1 br_0_1 gnd vdd vdd gnd wl_0_16 ++ sky130_fd_bd_sram__sram_sp_cell_opt1 +Xrow_16_col_1_wlstrap_p ++ gnd ++ sky130_fd_bd_sram__sram_sp_wlstrap_p +Xrow_16_col_2_bitcell ++ bl_0_2 br_0_2 gnd vdd vdd gnd wl_0_16 ++ sky130_fd_bd_sram__sram_sp_cell_opt1 +.ENDS sram_2_16_1_sky130_sky130_bitcell_array +* NGSPICE file created from sky130_fd_bd_sram__sram_sp_corner.ext - technology: sky130A + +.subckt sky130_fd_bd_sram__sram_sp_corner VPWR VPB VNB +.ends +* NGSPICE file created from sky130_fd_bd_sram__openram_sp_rowenda_replica.ext - technology: sky130A + +.subckt sky130_fd_bd_sram__openram_sp_rowenda_replica VPWR WL +.ends +* NGSPICE file created from sky130_fd_bd_sram__openram_sp_rowend_replica.ext - technology: sky130A + +.subckt sky130_fd_bd_sram__openram_sp_rowend_replica VPWR WL +.ends + +.SUBCKT sram_2_16_1_sky130_sky130_row_cap_array ++ wl_0_0 wl_0_1 wl_0_2 wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 wl_0_8 wl_0_9 ++ wl_0_10 wl_0_11 wl_0_12 wl_0_13 wl_0_14 wl_0_15 wl_0_16 wl_0_17 ++ wl_0_18 wl_0_19 vdd gnd +* OUTPUT: wl_0_0 +* OUTPUT: wl_0_1 +* OUTPUT: wl_0_2 +* OUTPUT: wl_0_3 +* OUTPUT: wl_0_4 +* OUTPUT: wl_0_5 +* OUTPUT: wl_0_6 +* OUTPUT: wl_0_7 +* OUTPUT: wl_0_8 +* OUTPUT: wl_0_9 +* OUTPUT: wl_0_10 +* OUTPUT: wl_0_11 +* OUTPUT: wl_0_12 +* OUTPUT: wl_0_13 +* OUTPUT: wl_0_14 +* OUTPUT: wl_0_15 +* OUTPUT: wl_0_16 +* OUTPUT: wl_0_17 +* OUTPUT: wl_0_18 +* OUTPUT: wl_0_19 +* POWER : vdd +* GROUND: gnd +Xrca_0 ++ vdd gnd vdd ++ sky130_fd_bd_sram__sram_sp_cornera +Xrca_1 ++ wl_0_0 vdd ++ sky130_fd_bd_sram__openram_sp_rowenda_replica +Xrca_2 ++ wl_0_1 vdd ++ sky130_fd_bd_sram__openram_sp_rowend_replica +Xrca_3 ++ wl_0_2 vdd ++ sky130_fd_bd_sram__openram_sp_rowenda_replica +Xrca_4 ++ wl_0_3 vdd ++ sky130_fd_bd_sram__openram_sp_rowend_replica +Xrca_5 ++ wl_0_4 vdd ++ sky130_fd_bd_sram__openram_sp_rowenda_replica +Xrca_6 ++ wl_0_5 vdd ++ sky130_fd_bd_sram__openram_sp_rowend_replica +Xrca_7 ++ wl_0_6 vdd ++ sky130_fd_bd_sram__openram_sp_rowenda_replica +Xrca_8 ++ wl_0_7 vdd ++ sky130_fd_bd_sram__openram_sp_rowend_replica +Xrca_9 ++ wl_0_8 vdd ++ sky130_fd_bd_sram__openram_sp_rowenda_replica +Xrca_10 ++ wl_0_9 vdd ++ sky130_fd_bd_sram__openram_sp_rowend_replica +Xrca_11 ++ wl_0_10 vdd ++ sky130_fd_bd_sram__openram_sp_rowenda_replica +Xrca_12 ++ wl_0_11 vdd ++ sky130_fd_bd_sram__openram_sp_rowend_replica +Xrca_13 ++ wl_0_12 vdd ++ sky130_fd_bd_sram__openram_sp_rowenda_replica +Xrca_14 ++ wl_0_13 vdd ++ sky130_fd_bd_sram__openram_sp_rowend_replica +Xrca_15 ++ wl_0_14 vdd ++ sky130_fd_bd_sram__openram_sp_rowenda_replica +Xrca_16 ++ wl_0_15 vdd ++ sky130_fd_bd_sram__openram_sp_rowend_replica +Xrca_17 ++ wl_0_16 vdd ++ sky130_fd_bd_sram__openram_sp_rowenda_replica +Xrca_18 ++ wl_0_17 vdd ++ sky130_fd_bd_sram__openram_sp_rowend_replica +Xrca_19 ++ vdd gnd vdd ++ sky130_fd_bd_sram__sram_sp_corner +.ENDS sram_2_16_1_sky130_sky130_row_cap_array + +.SUBCKT sram_2_16_1_sky130_sky130_replica_bitcell_array ++ rbl_bl_0_0 rbl_br_0_0 bl_0_0 br_0_0 bl_0_1 br_0_1 bl_0_2 br_0_2 ++ rbl_wl_0_0 wl_0_0 wl_0_1 wl_0_2 wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 ++ wl_0_8 wl_0_9 wl_0_10 wl_0_11 wl_0_12 wl_0_13 wl_0_14 wl_0_15 wl_0_16 ++ vdd gnd +* INOUT : rbl_bl_0_0 +* INOUT : rbl_br_0_0 +* INOUT : bl_0_0 +* INOUT : br_0_0 +* INOUT : bl_0_1 +* INOUT : br_0_1 +* INOUT : bl_0_2 +* INOUT : br_0_2 +* INPUT : rbl_wl_0_0 +* INPUT : wl_0_0 +* INPUT : wl_0_1 +* INPUT : wl_0_2 +* INPUT : wl_0_3 +* INPUT : wl_0_4 +* INPUT : wl_0_5 +* INPUT : wl_0_6 +* INPUT : wl_0_7 +* INPUT : wl_0_8 +* INPUT : wl_0_9 +* INPUT : wl_0_10 +* INPUT : wl_0_11 +* INPUT : wl_0_12 +* INPUT : wl_0_13 +* INPUT : wl_0_14 +* INPUT : wl_0_15 +* INPUT : wl_0_16 +* POWER : vdd +* GROUND: gnd +* rows: 17 cols: 3 +* rbl: [1, 0] left_rbl: [0] right_rbl: [] +Xbitcell_array ++ bl_0_0 br_0_0 bl_0_1 br_0_1 bl_0_2 br_0_2 wl_0_0 wl_0_1 wl_0_2 wl_0_3 ++ wl_0_4 wl_0_5 wl_0_6 wl_0_7 wl_0_8 wl_0_9 wl_0_10 wl_0_11 wl_0_12 ++ wl_0_13 wl_0_14 wl_0_15 wl_0_16 vdd gnd ++ sram_2_16_1_sky130_sky130_bitcell_array +Xreplica_col_0 ++ rbl_bl_0_0 rbl_br_0_0 rbl_wl_0_0 wl_0_0 wl_0_1 wl_0_2 wl_0_3 wl_0_4 ++ wl_0_5 wl_0_6 wl_0_7 wl_0_8 wl_0_9 wl_0_10 wl_0_11 wl_0_12 wl_0_13 ++ wl_0_14 wl_0_15 wl_0_16 vdd gnd gnd gnd ++ sram_2_16_1_sky130_sky130_replica_column +Xdummy_row_0 ++ bl_0_0 br_0_0 bl_0_1 br_0_1 bl_0_2 br_0_2 rbl_wl_0_0 vdd gnd ++ sram_2_16_1_sky130_sky130_dummy_array +Xdummy_row_bot ++ bl_0_0 br_0_0 bl_0_1 br_0_1 bl_0_2 br_0_2 vdd gnd gnd ++ sram_2_16_1_sky130_sky130_col_cap_array_0 +Xdummy_row_top ++ bl_0_0 br_0_0 bl_0_1 br_0_1 bl_0_2 br_0_2 vdd gnd gnd ++ sram_2_16_1_sky130_sky130_col_cap_array +Xdummy_col_left ++ gnd rbl_wl_0_0 wl_0_0 wl_0_1 wl_0_2 wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 ++ wl_0_8 wl_0_9 wl_0_10 wl_0_11 wl_0_12 wl_0_13 wl_0_14 wl_0_15 wl_0_16 ++ gnd vdd gnd ++ sram_2_16_1_sky130_sky130_row_cap_array +Xdummy_col_right ++ gnd rbl_wl_0_0 wl_0_0 wl_0_1 wl_0_2 wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 ++ wl_0_8 wl_0_9 wl_0_10 wl_0_11 wl_0_12 wl_0_13 wl_0_14 wl_0_15 wl_0_16 ++ gnd vdd gnd ++ sram_2_16_1_sky130_sky130_row_cap_array_0 +.ENDS sram_2_16_1_sky130_sky130_replica_bitcell_array + +.SUBCKT sram_2_16_1_sky130_sky130_capped_replica_bitcell_array ++ rbl_bl_0_0 rbl_br_0_0 bl_0_0 br_0_0 bl_0_1 br_0_1 bl_0_2 br_0_2 ++ rbl_wl_0_0 wl_0_0 wl_0_1 wl_0_2 wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 ++ wl_0_8 wl_0_9 wl_0_10 wl_0_11 wl_0_12 wl_0_13 wl_0_14 wl_0_15 wl_0_16 ++ vdd gnd +* INOUT : rbl_bl_0_0 +* INOUT : rbl_br_0_0 +* INOUT : bl_0_0 +* INOUT : br_0_0 +* INOUT : bl_0_1 +* INOUT : br_0_1 +* INOUT : bl_0_2 +* INOUT : br_0_2 +* INPUT : rbl_wl_0_0 +* INPUT : wl_0_0 +* INPUT : wl_0_1 +* INPUT : wl_0_2 +* INPUT : wl_0_3 +* INPUT : wl_0_4 +* INPUT : wl_0_5 +* INPUT : wl_0_6 +* INPUT : wl_0_7 +* INPUT : wl_0_8 +* INPUT : wl_0_9 +* INPUT : wl_0_10 +* INPUT : wl_0_11 +* INPUT : wl_0_12 +* INPUT : wl_0_13 +* INPUT : wl_0_14 +* INPUT : wl_0_15 +* INPUT : wl_0_16 +* POWER : vdd +* GROUND: gnd +* rows: 17 cols: 3 +* rbl: [1, 0] left_rbl: [0] right_rbl: [] +Xreplica_bitcell_array ++ rbl_bl_0_0 rbl_br_0_0 bl_0_0 br_0_0 bl_0_1 br_0_1 bl_0_2 br_0_2 ++ rbl_wl_0_0 wl_0_0 wl_0_1 wl_0_2 wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 ++ wl_0_8 wl_0_9 wl_0_10 wl_0_11 wl_0_12 wl_0_13 wl_0_14 wl_0_15 wl_0_16 ++ vdd gnd ++ sram_2_16_1_sky130_sky130_replica_bitcell_array +.ENDS sram_2_16_1_sky130_sky130_capped_replica_bitcell_array +* Copyright 2020 The SkyWater PDK Authors +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +* SPDX-License-Identifier: Apache-2.0 + +*********************** "sky130_fd_bd_sram__openram_write_driver" ****************************** + +.SUBCKT sky130_fd_bd_sram__openram_write_driver DIN BL BR EN VDD GND + +**** Inverter to conver Data_in to data_in_bar ****** +* din_bar = inv(DIN) +X_1 din_bar DIN GND GND sky130_fd_pr__nfet_01v8 W=0.36 L=0.15 +X_2 din_bar DIN VDD VDD sky130_fd_pr__pfet_01v8 W=0.55 L=0.15 + +**** 2input nand gate follwed by inverter to drive BL ****** +* din_bar_gated = nand(EN, DIN) +X_3 din_bar_gated EN net_7 GND sky130_fd_pr__nfet_01v8 W=0.55 L=0.15 +X_4 net_7 DIN GND GND sky130_fd_pr__nfet_01v8 W=0.55 L=0.15 +X_5 din_bar_gated EN VDD VDD sky130_fd_pr__pfet_01v8 W=0.55 L=0.15 +X_6 din_bar_gated DIN VDD VDD sky130_fd_pr__pfet_01v8 W=0.55 L=0.15 +* din_bar_gated_bar = inv(din_bar_gated) +X_7 din_bar_gated_bar din_bar_gated VDD VDD sky130_fd_pr__pfet_01v8 W=0.55 L=0.15 +X_8 din_bar_gated_bar din_bar_gated GND GND sky130_fd_pr__nfet_01v8 W=0.36 L=0.15 + +**** 2input nand gate follwed by inverter to drive BR****** +* din_gated = nand(EN, din_bar) +X_9 din_gated EN VDD VDD sky130_fd_pr__pfet_01v8 W=0.55 L=0.15 +X_10 din_gated EN net_8 GND sky130_fd_pr__nfet_01v8 W=0.55 L=0.15 +X_11 net_8 din_bar GND GND sky130_fd_pr__nfet_01v8 W=0.55 L=0.15 +X_12 din_gated din_bar VDD VDD sky130_fd_pr__pfet_01v8 W=0.55 L=0.15 +* din_gated_bar = inv(din_gated) +X_13 din_gated_bar din_gated VDD VDD sky130_fd_pr__pfet_01v8 W=0.55 L=0.15 +X_14 din_gated_bar din_gated GND GND sky130_fd_pr__nfet_01v8 W=0.36 L=0.15 + +************************************************ +* pull down with EN enable +X_15 BL din_gated_bar GND GND sky130_fd_pr__nfet_01v8 W=1 L=0.15 +X_16 BR din_bar_gated_bar GND GND sky130_fd_pr__nfet_01v8 W=1 L=0.15 + +.ENDS sky130_fd_bd_sram__openram_write_driver + +.SUBCKT sram_2_16_1_sky130_write_driver_array ++ data_0 data_1 data_2 bl_0 br_0 bl_1 br_1 bl_2 br_2 en_0 en_1 vdd gnd +* INPUT : data_0 +* INPUT : data_1 +* INPUT : data_2 +* OUTPUT: bl_0 +* OUTPUT: br_0 +* OUTPUT: bl_1 +* OUTPUT: br_1 +* OUTPUT: bl_2 +* OUTPUT: br_2 +* INPUT : en_0 +* INPUT : en_1 +* POWER : vdd +* GROUND: gnd +* columns: 2 +* word_size 2 +Xwrite_driver0 ++ data_0 bl_0 br_0 en_0 vdd gnd ++ sky130_fd_bd_sram__openram_write_driver +Xwrite_driver1 ++ data_1 bl_1 br_1 en_0 vdd gnd ++ sky130_fd_bd_sram__openram_write_driver +Xwrite_driver2 ++ data_2 bl_2 br_2 en_1 vdd gnd ++ sky130_fd_bd_sram__openram_write_driver +.ENDS sram_2_16_1_sky130_write_driver_array + +* spice ptx X{0} {1} sky130_fd_pr__pfet_01v8 m=1 w=0.55 l=0.15 pd=1.40 ps=1.40 as=0.21u ad=0.21u + +.SUBCKT sram_2_16_1_sky130_precharge_0 ++ bl br en_bar vdd +* OUTPUT: bl +* OUTPUT: br +* INPUT : en_bar +* POWER : vdd +Xlower_pmos bl en_bar br vdd sky130_fd_pr__pfet_01v8 m=1 w=0.55 l=0.15 pd=1.40 ps=1.40 as=0.21u ad=0.21u +Xupper_pmos1 bl en_bar vdd vdd sky130_fd_pr__pfet_01v8 m=1 w=0.55 l=0.15 pd=1.40 ps=1.40 as=0.21u ad=0.21u +Xupper_pmos2 br en_bar vdd vdd sky130_fd_pr__pfet_01v8 m=1 w=0.55 l=0.15 pd=1.40 ps=1.40 as=0.21u ad=0.21u +.ENDS sram_2_16_1_sky130_precharge_0 + +.SUBCKT sram_2_16_1_sky130_precharge_array ++ bl_0 br_0 bl_1 br_1 bl_2 br_2 bl_3 br_3 en_bar vdd +* OUTPUT: bl_0 +* OUTPUT: br_0 +* OUTPUT: bl_1 +* OUTPUT: br_1 +* OUTPUT: bl_2 +* OUTPUT: br_2 +* OUTPUT: bl_3 +* OUTPUT: br_3 +* INPUT : en_bar +* POWER : vdd +* cols: 4 size: 1 bl: bl br: br +Xpre_column_0 ++ bl_0 br_0 en_bar vdd ++ sram_2_16_1_sky130_precharge_0 +Xpre_column_1 ++ bl_1 br_1 en_bar vdd ++ sram_2_16_1_sky130_precharge_0 +Xpre_column_2 ++ bl_2 br_2 en_bar vdd ++ sram_2_16_1_sky130_precharge_0 +Xpre_column_3 ++ bl_3 br_3 en_bar vdd ++ sram_2_16_1_sky130_precharge_0 +.ENDS sram_2_16_1_sky130_precharge_array +* Copyright 2020 The SkyWater PDK Authors +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +* SPDX-License-Identifier: Apache-2.0 + +*********************** "sky130_fd_bd_sram__openram_sense_amp" ****************************** + +.SUBCKT sky130_fd_bd_sram__openram_sense_amp BL BR DOUT EN VDD GND +X1000 GND EN a_56_432# GND sky130_fd_pr__nfet_01v8 W=0.65 L=0.15 +X1001 a_56_432# dint_bar dint GND sky130_fd_pr__nfet_01v8 W=0.65 L=0.15 +X1002 dint_bar dint a_56_432# GND sky130_fd_pr__nfet_01v8 W=0.65 L=0.15 + +X1003 VDD dint_bar dint VDD sky130_fd_pr__pfet_01v8 W=1.26 L=0.15 +X1004 dint_bar dint VDD VDD sky130_fd_pr__pfet_01v8 W=1.26 L=0.15 + +X1005 BL EN dint VDD sky130_fd_pr__pfet_01v8 W=2 L=0.15 +X1006 dint_bar EN BR VDD sky130_fd_pr__pfet_01v8 W=2 L=0.15 + +X1007 VDD dint_bar DOUT VDD sky130_fd_pr__pfet_01v8 W=1.26 L=0.15 +X1008 DOUT dint_bar GND GND sky130_fd_pr__nfet_01v8 W=0.65 L=0.15 + +.ENDS sky130_fd_bd_sram__openram_sense_amp + +.SUBCKT sram_2_16_1_sky130_sense_amp_array ++ data_0 bl_0 br_0 data_1 bl_1 br_1 data_2 bl_2 br_2 en vdd gnd +* OUTPUT: data_0 +* INPUT : bl_0 +* INPUT : br_0 +* OUTPUT: data_1 +* INPUT : bl_1 +* INPUT : br_1 +* OUTPUT: data_2 +* INPUT : bl_2 +* INPUT : br_2 +* INPUT : en +* POWER : vdd +* GROUND: gnd +* word_size 2 +* words_per_row: 1 +Xsa_d0 ++ bl_0 br_0 data_0 en vdd gnd ++ sky130_fd_bd_sram__openram_sense_amp +Xsa_d1 ++ bl_1 br_1 data_1 en vdd gnd ++ sky130_fd_bd_sram__openram_sense_amp +Xsa_d2 ++ bl_2 br_2 data_2 en vdd gnd ++ sky130_fd_bd_sram__openram_sense_amp +.ENDS sram_2_16_1_sky130_sense_amp_array + +.SUBCKT sram_2_16_1_sky130_port_data ++ rbl_bl rbl_br bl_0 br_0 bl_1 br_1 sparebl_0 sparebr_0 dout_0 dout_1 ++ dout_2 din_0 din_1 din_2 s_en p_en_bar w_en bank_spare_wen0 vdd gnd +* INOUT : rbl_bl +* INOUT : rbl_br +* INOUT : bl_0 +* INOUT : br_0 +* INOUT : bl_1 +* INOUT : br_1 +* INOUT : sparebl_0 +* INOUT : sparebr_0 +* OUTPUT: dout_0 +* OUTPUT: dout_1 +* OUTPUT: dout_2 +* INPUT : din_0 +* INPUT : din_1 +* INPUT : din_2 +* INPUT : s_en +* INPUT : p_en_bar +* INPUT : w_en +* INPUT : bank_spare_wen0 +* POWER : vdd +* GROUND: gnd +Xprecharge_array0 ++ rbl_bl rbl_br bl_0 br_0 bl_1 br_1 sparebl_0 sparebr_0 p_en_bar vdd ++ sram_2_16_1_sky130_precharge_array +Xsense_amp_array0 ++ dout_0 bl_0 br_0 dout_1 bl_1 br_1 dout_2 sparebl_0 sparebr_0 s_en vdd ++ gnd ++ sram_2_16_1_sky130_sense_amp_array +Xwrite_driver_array0 ++ din_0 din_1 din_2 bl_0 br_0 bl_1 br_1 sparebl_0 sparebr_0 w_en ++ bank_spare_wen0 vdd gnd ++ sram_2_16_1_sky130_write_driver_array +.ENDS sram_2_16_1_sky130_port_data + +.SUBCKT sram_2_16_1_sky130_bank ++ dout0_0 dout0_1 dout0_2 rbl_bl_0_0 din0_0 din0_1 din0_2 addr0_0 ++ addr0_1 addr0_2 addr0_3 addr0_4 s_en0 p_en_bar0 w_en0 ++ bank_spare_wen0_0 wl_en0 vdd gnd +* OUTPUT: dout0_0 +* OUTPUT: dout0_1 +* OUTPUT: dout0_2 +* OUTPUT: rbl_bl_0_0 +* INPUT : din0_0 +* INPUT : din0_1 +* INPUT : din0_2 +* INPUT : addr0_0 +* INPUT : addr0_1 +* INPUT : addr0_2 +* INPUT : addr0_3 +* INPUT : addr0_4 +* INPUT : s_en0 +* INPUT : p_en_bar0 +* INPUT : w_en0 +* INPUT : bank_spare_wen0_0 +* INPUT : wl_en0 +* POWER : vdd +* GROUND: gnd +Xbitcell_array ++ rbl_bl_0_0 rbl_br_0_0 bl_0_0 br_0_0 bl_0_1 br_0_1 bl_0_2 br_0_2 ++ rbl_wl0 wl_0_0 wl_0_1 wl_0_2 wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 wl_0_8 ++ wl_0_9 wl_0_10 wl_0_11 wl_0_12 wl_0_13 wl_0_14 wl_0_15 wl_0_16 vdd gnd ++ sram_2_16_1_sky130_sky130_capped_replica_bitcell_array +Xport_data0 ++ rbl_bl_0_0 rbl_br_0_0 bl_0_0 br_0_0 bl_0_1 br_0_1 bl_0_2 br_0_2 ++ dout0_0 dout0_1 dout0_2 din0_0 din0_1 din0_2 s_en0 p_en_bar0 w_en0 ++ bank_spare_wen0_0 vdd gnd ++ sram_2_16_1_sky130_port_data +Xport_address0 ++ addr0_0 addr0_1 addr0_2 addr0_3 addr0_4 wl_en0 wl_0_0 wl_0_1 wl_0_2 ++ wl_0_3 wl_0_4 wl_0_5 wl_0_6 wl_0_7 wl_0_8 wl_0_9 wl_0_10 wl_0_11 ++ wl_0_12 wl_0_13 wl_0_14 wl_0_15 wl_0_16 rbl_wl0 vdd gnd ++ sram_2_16_1_sky130_port_address +.ENDS sram_2_16_1_sky130_bank + +.SUBCKT sram_2_16_1_sky130_pinv_4 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* size: 1 +Xpinv_pmos Z A vdd vdd sky130_fd_pr__pfet_01v8 m=1 w=1.12 l=0.15 pd=2.54 ps=2.54 as=0.42u ad=0.42u +Xpinv_nmos Z A gnd gnd sky130_fd_pr__nfet_01v8 m=1 w=0.36 l=0.15 pd=1.02 ps=1.02 as=0.14u ad=0.14u +.ENDS sram_2_16_1_sky130_pinv_4 + +* spice ptx X{0} {1} sky130_fd_pr__nfet_01v8 m=3 w=2.0 l=0.15 pd=4.30 ps=4.30 as=0.75u ad=0.75u + +* spice ptx X{0} {1} sky130_fd_pr__pfet_01v8 m=3 w=2.0 l=0.15 pd=4.30 ps=4.30 as=0.75u ad=0.75u + +.SUBCKT sram_2_16_1_sky130_pinv_8 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* size: 5 +Xpinv_pmos Z A vdd vdd sky130_fd_pr__pfet_01v8 m=3 w=2.0 l=0.15 pd=4.30 ps=4.30 as=0.75u ad=0.75u +Xpinv_nmos Z A gnd gnd sky130_fd_pr__nfet_01v8 m=3 w=2.0 l=0.15 pd=4.30 ps=4.30 as=0.75u ad=0.75u +.ENDS sram_2_16_1_sky130_pinv_8 + +.SUBCKT sram_2_16_1_sky130_pdriver_1 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* sizes: [1, 5] +Xbuf_inv1 ++ A Zb1_int vdd gnd ++ sram_2_16_1_sky130_pinv_4 +Xbuf_inv2 ++ Zb1_int Z vdd gnd ++ sram_2_16_1_sky130_pinv_8 +.ENDS sram_2_16_1_sky130_pdriver_1 + +* spice ptx X{0} {1} sky130_fd_pr__nfet_01v8 m=6 w=2.0 l=0.15 pd=4.30 ps=4.30 as=0.75u ad=0.75u + +* spice ptx X{0} {1} sky130_fd_pr__pfet_01v8 m=6 w=2.0 l=0.15 pd=4.30 ps=4.30 as=0.75u ad=0.75u + +.SUBCKT sram_2_16_1_sky130_pinv_9 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* size: 10 +Xpinv_pmos Z A vdd vdd sky130_fd_pr__pfet_01v8 m=6 w=2.0 l=0.15 pd=4.30 ps=4.30 as=0.75u ad=0.75u +Xpinv_nmos Z A gnd gnd sky130_fd_pr__nfet_01v8 m=6 w=2.0 l=0.15 pd=4.30 ps=4.30 as=0.75u ad=0.75u +.ENDS sram_2_16_1_sky130_pinv_9 + +.SUBCKT sram_2_16_1_sky130_pdriver_2 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* sizes: [10] +Xbuf_inv1 ++ A Z vdd gnd ++ sram_2_16_1_sky130_pinv_9 +.ENDS sram_2_16_1_sky130_pdriver_2 + +* spice ptx X{0} {1} sky130_fd_pr__nfet_01v8 m=1 w=0.74 l=0.15 pd=1.78 ps=1.78 as=0.28u ad=0.28u + +* spice ptx X{0} {1} sky130_fd_pr__pfet_01v8 m=1 w=1.12 l=0.15 pd=2.54 ps=2.54 as=0.42u ad=0.42u + +* spice ptx X{0} {1} sky130_fd_pr__nfet_01v8 m=1 w=0.74 l=0.15 pd=1.78 ps=1.78 as=0.28u ad=0.28u + +* spice ptx X{0} {1} sky130_fd_pr__nfet_01v8 m=1 w=0.74 l=0.15 pd=1.78 ps=1.78 as=0.28u ad=0.28u + +.SUBCKT sram_2_16_1_sky130_pnand3 ++ A B C Z vdd gnd +* INPUT : A +* INPUT : B +* INPUT : C +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* size: 1 +Xpnand3_pmos1 vdd A Z vdd sky130_fd_pr__pfet_01v8 m=1 w=1.12 l=0.15 pd=2.54 ps=2.54 as=0.42u ad=0.42u +Xpnand3_pmos2 Z B vdd vdd sky130_fd_pr__pfet_01v8 m=1 w=1.12 l=0.15 pd=2.54 ps=2.54 as=0.42u ad=0.42u +Xpnand3_pmos3 Z C vdd vdd sky130_fd_pr__pfet_01v8 m=1 w=1.12 l=0.15 pd=2.54 ps=2.54 as=0.42u ad=0.42u +Xpnand3_nmos1 Z C net1 gnd sky130_fd_pr__nfet_01v8 m=1 w=0.74 l=0.15 pd=1.78 ps=1.78 as=0.28u ad=0.28u +Xpnand3_nmos2 net1 B net2 gnd sky130_fd_pr__nfet_01v8 m=1 w=0.74 l=0.15 pd=1.78 ps=1.78 as=0.28u ad=0.28u +Xpnand3_nmos3 net2 A gnd gnd sky130_fd_pr__nfet_01v8 m=1 w=0.74 l=0.15 pd=1.78 ps=1.78 as=0.28u ad=0.28u +.ENDS sram_2_16_1_sky130_pnand3 + +.SUBCKT sram_2_16_1_sky130_pand3 ++ A B C Z vdd gnd +* INPUT : A +* INPUT : B +* INPUT : C +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* size: 10 +Xpand3_nand ++ A B C zb_int vdd gnd ++ sram_2_16_1_sky130_pnand3 +Xpand3_inv ++ zb_int Z vdd gnd ++ sram_2_16_1_sky130_pdriver_2 +.ENDS sram_2_16_1_sky130_pand3 + +.SUBCKT sram_2_16_1_sky130_pdriver_4 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* sizes: [1, 1] +Xbuf_inv1 ++ A Zb1_int vdd gnd ++ sram_2_16_1_sky130_pinv_4 +Xbuf_inv2 ++ Zb1_int Z vdd gnd ++ sram_2_16_1_sky130_pinv_4 +.ENDS sram_2_16_1_sky130_pdriver_4 + +.SUBCKT sram_2_16_1_sky130_pnand2_0 ++ A B Z vdd gnd +* INPUT : A +* INPUT : B +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* size: 1 +Xpnand2_pmos1 vdd A Z vdd sky130_fd_pr__pfet_01v8 m=1 w=1.12 l=0.15 pd=2.54 ps=2.54 as=0.42u ad=0.42u +Xpnand2_pmos2 Z B vdd vdd sky130_fd_pr__pfet_01v8 m=1 w=1.12 l=0.15 pd=2.54 ps=2.54 as=0.42u ad=0.42u +Xpnand2_nmos1 Z B net1 gnd sky130_fd_pr__nfet_01v8 m=1 w=0.74 l=0.15 pd=1.78 ps=1.78 as=0.28u ad=0.28u +Xpnand2_nmos2 net1 A gnd gnd sky130_fd_pr__nfet_01v8 m=1 w=0.74 l=0.15 pd=1.78 ps=1.78 as=0.28u ad=0.28u +.ENDS sram_2_16_1_sky130_pnand2_0 + +* spice ptx X{0} {1} sky130_fd_pr__pfet_01v8 m=7 w=2.0 l=0.15 pd=4.30 ps=4.30 as=0.75u ad=0.75u + +* spice ptx X{0} {1} sky130_fd_pr__nfet_01v8 m=7 w=1.68 l=0.15 pd=3.66 ps=3.66 as=0.63u ad=0.63u + +.SUBCKT sram_2_16_1_sky130_pinv_1 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* size: 12 +Xpinv_pmos Z A vdd vdd sky130_fd_pr__pfet_01v8 m=7 w=2.0 l=0.15 pd=4.30 ps=4.30 as=0.75u ad=0.75u +Xpinv_nmos Z A gnd gnd sky130_fd_pr__nfet_01v8 m=7 w=1.68 l=0.15 pd=3.66 ps=3.66 as=0.63u ad=0.63u +.ENDS sram_2_16_1_sky130_pinv_1 + +.SUBCKT sram_2_16_1_sky130_pdriver ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* sizes: [12] +Xbuf_inv1 ++ A Z vdd gnd ++ sram_2_16_1_sky130_pinv_1 +.ENDS sram_2_16_1_sky130_pdriver + +.SUBCKT sram_2_16_1_sky130_pnand2 ++ A B Z vdd gnd +* INPUT : A +* INPUT : B +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* size: 1 +Xpnand2_pmos1 vdd A Z vdd sky130_fd_pr__pfet_01v8 m=1 w=1.12 l=0.15 pd=2.54 ps=2.54 as=0.42u ad=0.42u +Xpnand2_pmos2 Z B vdd vdd sky130_fd_pr__pfet_01v8 m=1 w=1.12 l=0.15 pd=2.54 ps=2.54 as=0.42u ad=0.42u +Xpnand2_nmos1 Z B net1 gnd sky130_fd_pr__nfet_01v8 m=1 w=0.74 l=0.15 pd=1.78 ps=1.78 as=0.28u ad=0.28u +Xpnand2_nmos2 net1 A gnd gnd sky130_fd_pr__nfet_01v8 m=1 w=0.74 l=0.15 pd=1.78 ps=1.78 as=0.28u ad=0.28u +.ENDS sram_2_16_1_sky130_pnand2 + +.SUBCKT sram_2_16_1_sky130_pand2 ++ A B Z vdd gnd +* INPUT : A +* INPUT : B +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* size: 12 +Xpand2_nand ++ A B zb_int vdd gnd ++ sram_2_16_1_sky130_pnand2 +Xpand2_inv ++ zb_int Z vdd gnd ++ sram_2_16_1_sky130_pdriver +.ENDS sram_2_16_1_sky130_pand2 + +* spice ptx X{0} {1} sky130_fd_pr__nfet_01v8 m=10 w=1.68 l=0.15 pd=3.66 ps=3.66 as=0.63u ad=0.63u + +* spice ptx X{0} {1} sky130_fd_pr__pfet_01v8 m=10 w=2.0 l=0.15 pd=4.30 ps=4.30 as=0.75u ad=0.75u + +.SUBCKT sram_2_16_1_sky130_pinv_7 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* size: 17 +Xpinv_pmos Z A vdd vdd sky130_fd_pr__pfet_01v8 m=10 w=2.0 l=0.15 pd=4.30 ps=4.30 as=0.75u ad=0.75u +Xpinv_nmos Z A gnd gnd sky130_fd_pr__nfet_01v8 m=10 w=1.68 l=0.15 pd=3.66 ps=3.66 as=0.63u ad=0.63u +.ENDS sram_2_16_1_sky130_pinv_7 + +* spice ptx X{0} {1} sky130_fd_pr__pfet_01v8 m=4 w=2.0 l=0.15 pd=4.30 ps=4.30 as=0.75u ad=0.75u + +* spice ptx X{0} {1} sky130_fd_pr__nfet_01v8 m=4 w=1.26 l=0.15 pd=2.82 ps=2.82 as=0.47u ad=0.47u + +.SUBCKT sram_2_16_1_sky130_pinv_6 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* size: 6 +Xpinv_pmos Z A vdd vdd sky130_fd_pr__pfet_01v8 m=4 w=2.0 l=0.15 pd=4.30 ps=4.30 as=0.75u ad=0.75u +Xpinv_nmos Z A gnd gnd sky130_fd_pr__nfet_01v8 m=4 w=1.26 l=0.15 pd=2.82 ps=2.82 as=0.47u ad=0.47u +.ENDS sram_2_16_1_sky130_pinv_6 + +* spice ptx X{0} {1} sky130_fd_pr__pfet_01v8 m=2 w=1.26 l=0.15 pd=2.82 ps=2.82 as=0.47u ad=0.47u + +* spice ptx X{0} {1} sky130_fd_pr__nfet_01v8 m=2 w=0.74 l=0.15 pd=1.78 ps=1.78 as=0.28u ad=0.28u + +.SUBCKT sram_2_16_1_sky130_pinv_5 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* size: 2 +Xpinv_pmos Z A vdd vdd sky130_fd_pr__pfet_01v8 m=2 w=1.26 l=0.15 pd=2.82 ps=2.82 as=0.47u ad=0.47u +Xpinv_nmos Z A gnd gnd sky130_fd_pr__nfet_01v8 m=2 w=0.74 l=0.15 pd=1.78 ps=1.78 as=0.28u ad=0.28u +.ENDS sram_2_16_1_sky130_pinv_5 + +.SUBCKT sram_2_16_1_sky130_pdriver_0 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* sizes: [1, 2, 6, 17] +Xbuf_inv1 ++ A Zb1_int vdd gnd ++ sram_2_16_1_sky130_pinv_4 +Xbuf_inv2 ++ Zb1_int Zb2_int vdd gnd ++ sram_2_16_1_sky130_pinv_5 +Xbuf_inv3 ++ Zb2_int Zb3_int vdd gnd ++ sram_2_16_1_sky130_pinv_6 +Xbuf_inv4 ++ Zb3_int Z vdd gnd ++ sram_2_16_1_sky130_pinv_7 +.ENDS sram_2_16_1_sky130_pdriver_0 + +.SUBCKT sram_2_16_1_sky130_pinv_11 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* size: 1 +Xpinv_pmos Z A vdd vdd sky130_fd_pr__pfet_01v8 m=1 w=1.12 l=0.15 pd=2.54 ps=2.54 as=0.42u ad=0.42u +Xpinv_nmos Z A gnd gnd sky130_fd_pr__nfet_01v8 m=1 w=0.36 l=0.15 pd=1.02 ps=1.02 as=0.14u ad=0.14u +.ENDS sram_2_16_1_sky130_pinv_11 + +.SUBCKT sram_2_16_1_sky130_delay_chain ++ in out vdd gnd +* INPUT : in +* OUTPUT: out +* POWER : vdd +* GROUND: gnd +* fanouts: [4, 4, 4, 4, 4, 4, 4, 4, 4] +Xdinv0 ++ in dout_1 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_0_0 ++ dout_1 n_0_0 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_0_1 ++ dout_1 n_0_1 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_0_2 ++ dout_1 n_0_2 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_0_3 ++ dout_1 n_0_3 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdinv1 ++ dout_1 dout_2 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_1_0 ++ dout_2 n_1_0 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_1_1 ++ dout_2 n_1_1 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_1_2 ++ dout_2 n_1_2 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_1_3 ++ dout_2 n_1_3 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdinv2 ++ dout_2 dout_3 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_2_0 ++ dout_3 n_2_0 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_2_1 ++ dout_3 n_2_1 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_2_2 ++ dout_3 n_2_2 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_2_3 ++ dout_3 n_2_3 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdinv3 ++ dout_3 dout_4 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_3_0 ++ dout_4 n_3_0 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_3_1 ++ dout_4 n_3_1 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_3_2 ++ dout_4 n_3_2 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_3_3 ++ dout_4 n_3_3 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdinv4 ++ dout_4 dout_5 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_4_0 ++ dout_5 n_4_0 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_4_1 ++ dout_5 n_4_1 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_4_2 ++ dout_5 n_4_2 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_4_3 ++ dout_5 n_4_3 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdinv5 ++ dout_5 dout_6 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_5_0 ++ dout_6 n_5_0 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_5_1 ++ dout_6 n_5_1 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_5_2 ++ dout_6 n_5_2 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_5_3 ++ dout_6 n_5_3 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdinv6 ++ dout_6 dout_7 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_6_0 ++ dout_7 n_6_0 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_6_1 ++ dout_7 n_6_1 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_6_2 ++ dout_7 n_6_2 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_6_3 ++ dout_7 n_6_3 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdinv7 ++ dout_7 dout_8 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_7_0 ++ dout_8 n_7_0 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_7_1 ++ dout_8 n_7_1 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_7_2 ++ dout_8 n_7_2 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_7_3 ++ dout_8 n_7_3 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdinv8 ++ dout_8 out vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_8_0 ++ out n_8_0 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_8_1 ++ out n_8_1 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_8_2 ++ out n_8_2 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +Xdload_8_3 ++ out n_8_3 vdd gnd ++ sram_2_16_1_sky130_pinv_11 +.ENDS sram_2_16_1_sky130_delay_chain + +* spice ptx X{0} {1} sky130_fd_pr__pfet_01v8 m=2 w=2.0 l=0.15 pd=4.30 ps=4.30 as=0.75u ad=0.75u + +* spice ptx X{0} {1} sky130_fd_pr__nfet_01v8 m=2 w=1.26 l=0.15 pd=2.82 ps=2.82 as=0.47u ad=0.47u + +.SUBCKT sram_2_16_1_sky130_pinv_10 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* size: 3 +Xpinv_pmos Z A vdd vdd sky130_fd_pr__pfet_01v8 m=2 w=2.0 l=0.15 pd=4.30 ps=4.30 as=0.75u ad=0.75u +Xpinv_nmos Z A gnd gnd sky130_fd_pr__nfet_01v8 m=2 w=1.26 l=0.15 pd=2.82 ps=2.82 as=0.47u ad=0.47u +.ENDS sram_2_16_1_sky130_pinv_10 + +.SUBCKT sram_2_16_1_sky130_pdriver_3 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* sizes: [3] +Xbuf_inv1 ++ A Z vdd gnd ++ sram_2_16_1_sky130_pinv_10 +.ENDS sram_2_16_1_sky130_pdriver_3 + +.SUBCKT sram_2_16_1_sky130_pand3_0 ++ A B C Z vdd gnd +* INPUT : A +* INPUT : B +* INPUT : C +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* size: 3 +Xpand3_nand ++ A B C zb_int vdd gnd ++ sram_2_16_1_sky130_pnand3 +Xpand3_inv ++ zb_int Z vdd gnd ++ sram_2_16_1_sky130_pdriver_3 +.ENDS sram_2_16_1_sky130_pand3_0 + +.SUBCKT sram_2_16_1_sky130_pinv ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* size: 2 +Xpinv_pmos Z A vdd vdd sky130_fd_pr__pfet_01v8 m=2 w=1.26 l=0.15 pd=2.82 ps=2.82 as=0.47u ad=0.47u +Xpinv_nmos Z A gnd gnd sky130_fd_pr__nfet_01v8 m=2 w=0.74 l=0.15 pd=1.78 ps=1.78 as=0.28u ad=0.28u +.ENDS sram_2_16_1_sky130_pinv + +* spice ptx X{0} {1} sky130_fd_pr__nfet_01v8 m=3 w=1.68 l=0.15 pd=3.66 ps=3.66 as=0.63u ad=0.63u + +* spice ptx X{0} {1} sky130_fd_pr__pfet_01v8 m=3 w=1.68 l=0.15 pd=3.66 ps=3.66 as=0.63u ad=0.63u + +.SUBCKT sram_2_16_1_sky130_pinv_0 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* size: 4 +Xpinv_pmos Z A vdd vdd sky130_fd_pr__pfet_01v8 m=3 w=1.68 l=0.15 pd=3.66 ps=3.66 as=0.63u ad=0.63u +Xpinv_nmos Z A gnd gnd sky130_fd_pr__nfet_01v8 m=3 w=1.68 l=0.15 pd=3.66 ps=3.66 as=0.63u ad=0.63u +.ENDS sram_2_16_1_sky130_pinv_0 + +.SUBCKT sram_2_16_1_sky130_dff_buf_0 ++ D Q Qb clk vdd gnd +* INPUT : D +* OUTPUT: Q +* OUTPUT: Qb +* INPUT : clk +* POWER : vdd +* GROUND: gnd +* inv1: 2 inv2: 4 +Xdff_buf_dff ++ D qint clk vdd gnd ++ sky130_fd_bd_sram__openram_dff +Xdff_buf_inv1 ++ qint Qb vdd gnd ++ sram_2_16_1_sky130_pinv +Xdff_buf_inv2 ++ Qb Q vdd gnd ++ sram_2_16_1_sky130_pinv_0 +.ENDS sram_2_16_1_sky130_dff_buf_0 + +.SUBCKT sram_2_16_1_sky130_dff_buf_array ++ din_0 din_1 dout_0 dout_bar_0 dout_1 dout_bar_1 clk vdd gnd +* INPUT : din_0 +* INPUT : din_1 +* OUTPUT: dout_0 +* OUTPUT: dout_bar_0 +* OUTPUT: dout_1 +* OUTPUT: dout_bar_1 +* INPUT : clk +* POWER : vdd +* GROUND: gnd +* rows: 2 cols: 1 +* inv1: 2 inv2: 4 +Xdff_r0_c0 ++ din_0 dout_0 dout_bar_0 clk vdd gnd ++ sram_2_16_1_sky130_dff_buf_0 +Xdff_r1_c0 ++ din_1 dout_1 dout_bar_1 clk vdd gnd ++ sram_2_16_1_sky130_dff_buf_0 +.ENDS sram_2_16_1_sky130_dff_buf_array + +.SUBCKT sram_2_16_1_sky130_pinv_2 ++ A Z vdd gnd +* INPUT : A +* OUTPUT: Z +* POWER : vdd +* GROUND: gnd +* size: 1 +Xpinv_pmos Z A vdd vdd sky130_fd_pr__pfet_01v8 m=1 w=1.12 l=0.15 pd=2.54 ps=2.54 as=0.42u ad=0.42u +Xpinv_nmos Z A gnd gnd sky130_fd_pr__nfet_01v8 m=1 w=0.36 l=0.15 pd=1.02 ps=1.02 as=0.14u ad=0.14u +.ENDS sram_2_16_1_sky130_pinv_2 + +.SUBCKT sram_2_16_1_sky130_control_logic_rw ++ csb web clk rbl_bl s_en w_en p_en_bar wl_en clk_buf vdd gnd +* INPUT : csb +* INPUT : web +* INPUT : clk +* INPUT : rbl_bl +* OUTPUT: s_en +* OUTPUT: w_en +* OUTPUT: p_en_bar +* OUTPUT: wl_en +* OUTPUT: clk_buf +* POWER : vdd +* GROUND: gnd +* num_rows: 17 +* words_per_row: 1 +* word_size 2 +Xctrl_dffs ++ csb web cs_bar cs we_bar we clk_buf vdd gnd ++ sram_2_16_1_sky130_dff_buf_array +Xclkbuf ++ clk clk_buf vdd gnd ++ sram_2_16_1_sky130_pdriver_0 +Xinv_clk_bar ++ clk_buf clk_bar vdd gnd ++ sram_2_16_1_sky130_pinv_2 +Xand2_gated_clk_bar ++ clk_bar cs gated_clk_bar vdd gnd ++ sram_2_16_1_sky130_pand2 +Xand2_gated_clk_buf ++ clk_buf cs gated_clk_buf vdd gnd ++ sram_2_16_1_sky130_pand2 +Xbuf_wl_en ++ gated_clk_bar wl_en vdd gnd ++ sram_2_16_1_sky130_pdriver_1 +Xrbl_bl_delay_inv ++ rbl_bl_delay rbl_bl_delay_bar vdd gnd ++ sram_2_16_1_sky130_pinv_2 +Xw_en_and ++ we rbl_bl_delay_bar gated_clk_bar w_en vdd gnd ++ sram_2_16_1_sky130_pand3 +Xbuf_s_en_and ++ rbl_bl_delay gated_clk_bar we_bar s_en vdd gnd ++ sram_2_16_1_sky130_pand3_0 +Xdelay_chain ++ rbl_bl rbl_bl_delay vdd gnd ++ sram_2_16_1_sky130_delay_chain +Xnand_p_en_bar ++ gated_clk_buf rbl_bl_delay p_en_bar_unbuf vdd gnd ++ sram_2_16_1_sky130_pnand2_0 +Xbuf_p_en_bar ++ p_en_bar_unbuf p_en_bar vdd gnd ++ sram_2_16_1_sky130_pdriver_4 +.ENDS sram_2_16_1_sky130_control_logic_rw + +.SUBCKT sram_2_16_1_sky130_spare_wen_dff ++ din_0 dout_0 clk vdd gnd +* INPUT : din_0 +* OUTPUT: dout_0 +* INPUT : clk +* POWER : vdd +* GROUND: gnd +* rows: 1 cols: 1 +Xdff_r0_c0 ++ din_0 dout_0 CLK VDD GND ++ sky130_fd_bd_sram__openram_dff +.ENDS sram_2_16_1_sky130_spare_wen_dff + +.SUBCKT sram_2_16_1_sky130 ++ din0[0] din0[1] din0[2] addr0[0] addr0[1] addr0[2] addr0[3] addr0[4] ++ csb0 web0 clk0 spare_wen0 dout0[0] dout0[1] dout0[2] vccd1 vssd1 +* INPUT : din0[0] +* INPUT : din0[1] +* INPUT : din0[2] +* INPUT : addr0[0] +* INPUT : addr0[1] +* INPUT : addr0[2] +* INPUT : addr0[3] +* INPUT : addr0[4] +* INPUT : csb0 +* INPUT : web0 +* INPUT : clk0 +* INPUT : spare_wen0 +* OUTPUT: dout0[0] +* OUTPUT: dout0[1] +* OUTPUT: dout0[2] +* POWER : vccd1 +* GROUND: vssd1 +Xbank0 ++ dout0[0] dout0[1] dout0[2] rbl_bl0 bank_din0_0 bank_din0_1 bank_din0_2 ++ a0_0 a0_1 a0_2 a0_3 a0_4 s_en0 p_en_bar0 w_en0 bank_spare_wen0_0 ++ wl_en0 vccd1 vssd1 ++ sram_2_16_1_sky130_bank +Xcontrol0 ++ csb0 web0 clk0 rbl_bl0 s_en0 w_en0 p_en_bar0 wl_en0 clk_buf0 vccd1 ++ vssd1 ++ sram_2_16_1_sky130_control_logic_rw +Xrow_address0 ++ addr0[0] addr0[1] addr0[2] addr0[3] addr0[4] a0_0 a0_1 a0_2 a0_3 a0_4 ++ clk_buf0 vccd1 vssd1 ++ sram_2_16_1_sky130_row_addr_dff +Xdata_dff0 ++ din0[0] din0[1] din0[2] bank_din0_0 bank_din0_1 bank_din0_2 clk_buf0 ++ vccd1 vssd1 ++ sram_2_16_1_sky130_data_dff +Xspare_wen_dff0 ++ spare_wen0[0] bank_spare_wen0_0 clk_buf0 vccd1 vssd1 ++ sram_2_16_1_sky130_spare_wen_dff +.ENDS sram_2_16_1_sky130 From ecd486e050b6243e747bd2e259b53ea768ddcce0 Mon Sep 17 00:00:00 2001 From: vlsida-bot Date: Sat, 22 Jul 2023 02:19:20 +0000 Subject: [PATCH 128/130] Bump version: 1.2.24 -> 1.2.25 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 95a7a34a..8060c02a 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.2.24 +1.2.25 From 1de6b9a0f6400ffd9326dff75da6bfac2708d479 Mon Sep 17 00:00:00 2001 From: Bugra Onal Date: Tue, 25 Jul 2023 13:06:31 -0700 Subject: [PATCH 129/130] Add func random seed as input option and log out --- compiler/characterizer/functional.py | 8 ++++++++ compiler/options.py | 4 ++++ 2 files changed, 12 insertions(+) diff --git a/compiler/characterizer/functional.py b/compiler/characterizer/functional.py index c5d5d865..49dba9da 100644 --- a/compiler/characterizer/functional.py +++ b/compiler/characterizer/functional.py @@ -7,6 +7,7 @@ # import math import random +import time import collections from os import path import shutil @@ -31,6 +32,13 @@ class functional(simulation): # Seed the characterizer with a constant seed for unit tests if OPTS.is_unit_test: random.seed(12345) + elif OPTS.functional_seed: + random.seed(OPTS.functional_seed) + else: + seed = time.time_ns() + random.seed(seed) + debug.info(1, "Random seed for functional simulation: {}".format(seed)) + if not spfile: # self.sp_file is assigned in base class diff --git a/compiler/options.py b/compiler/options.py index 4a5f7dde..5be9b09b 100644 --- a/compiler/options.py +++ b/compiler/options.py @@ -185,6 +185,10 @@ class options(optparse.Values): br_format = "X{name}{hier_sep}xbank0{hier_sep}br_{row}_{col}" sen_format = "X{name}{hier_sep}xbank0{hier_sep}s_en" cell_format = "X{name}{hier_sep}xbank0{hier_sep}xbitcell_array{hier_sep}xreplica_bitcell_array{hier_sep}xbitcell_array{hier_sep}xbit_r{row}_c{col}" + + # Random seed for functional simulation + functional_seed = None + # Route the input/output pins to the perimeter perimeter_pins = True From b1f4f0887e65568d2282d22d0a9ef2dbc2ae2f91 Mon Sep 17 00:00:00 2001 From: vlsida-bot Date: Wed, 26 Jul 2023 01:44:26 +0000 Subject: [PATCH 130/130] Bump version: 1.2.25 -> 1.2.26 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 8060c02a..cba64f43 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.2.25 +1.2.26