From 31ae56ff39a9b4e39cdb5585dec9fd8b44f2e639 Mon Sep 17 00:00:00 2001 From: mrg Date: Tue, 10 Nov 2020 16:45:00 -0800 Subject: [PATCH 01/31] Simplify to a single DRC/LVS library test. --- compiler/tests/01_library_drc_test.py | 69 ------------------- ...library_lvs_test.py => 01_library_test.py} | 5 +- 2 files changed, 3 insertions(+), 71 deletions(-) delete mode 100755 compiler/tests/01_library_drc_test.py rename compiler/tests/{02_library_lvs_test.py => 01_library_test.py} (95%) diff --git a/compiler/tests/01_library_drc_test.py b/compiler/tests/01_library_drc_test.py deleted file mode 100755 index 53d50386..00000000 --- a/compiler/tests/01_library_drc_test.py +++ /dev/null @@ -1,69 +0,0 @@ -#!/usr/bin/env python3 -# See LICENSE for licensing information. -# -# Copyright (c) 2016-2019 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 -#sys.path.append(os.getenv("OPENRAM_HOME")) -import globals -from globals import OPTS -import debug - -class library_drc_test(openram_test): - - def runTest(self): - config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME")) - globals.init_openram(config_file) - import verify - - (gds_dir, allnames) = setup_files() - drc_errors = 0 - debug.info(1, "\nPerforming DRC on: " + ", ".join(allnames)) - for f in allnames: - gds_name = "{0}/{1}.gds".format(gds_dir, f) - if not os.path.isfile(gds_name): - drc_errors += 1 - debug.error("Missing GDS file: {}".format(gds_name)) - drc_errors += verify.run_drc(f, gds_name) - - # fails if there are any DRC errors on any cells - self.assertEqual(drc_errors, 0) - globals.end_openram() - - -def setup_files(): - gds_dir = OPTS.openram_tech + "/gds_lib" - files = os.listdir(gds_dir) - nametest = re.compile("\.gds$", re.IGNORECASE) - gds_files = list(filter(nametest.search, files)) - - tempnames = gds_files - - # remove the .gds and .sp suffixes - for i in range(len(tempnames)): - gds_files[i] = re.sub('\.gds$', '', tempnames[i]) - - try: - from tech import blackbox_cells - nameset = list(set(tempnames) - set(blackbox_cells)) - except ImportError: - # remove duplicate base names - nameset = set(tempnames) - - allnames = list(nameset) - - return (gds_dir, allnames) - - -# 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/02_library_lvs_test.py b/compiler/tests/01_library_test.py similarity index 95% rename from compiler/tests/02_library_lvs_test.py rename to compiler/tests/01_library_test.py index 353c1f88..dbd25f7c 100755 --- a/compiler/tests/02_library_lvs_test.py +++ b/compiler/tests/01_library_test.py @@ -36,13 +36,14 @@ class library_lvs_test(openram_test): if not os.path.isfile(sp_name): lvs_errors += 1 debug.error("Missing SPICE file {}".format(sp_name)) - drc_errors += verify.run_drc(name, gds_name) + drc_errors += verify.run_drc(name, gds_name, sp_name) lvs_errors += verify.run_lvs(f, gds_name, sp_name) # fail if the error count is not zero - self.assertEqual(drc_errors+lvs_errors, 0) + self.assertEqual(drc_errors + lvs_errors, 0) globals.end_openram() + def setup_files(): gds_dir = OPTS.openram_tech + "/gds_lib" sp_dir = OPTS.openram_tech + "/lvs_lib" From 03dad01e4cefbaae4785243161bdab701e6a888e Mon Sep 17 00:00:00 2001 From: mrg Date: Tue, 10 Nov 2020 17:06:24 -0800 Subject: [PATCH 02/31] Use readspice to define ports from sp netlist in Magic extract. --- compiler/base/hierarchy_design.py | 14 ++-- compiler/tests/testutils.py | 2 +- compiler/verify/calibre.py | 21 ++++-- compiler/verify/magic.py | 115 ++++++++++++++++-------------- compiler/verify/none.py | 10 +-- 5 files changed, 93 insertions(+), 69 deletions(-) diff --git a/compiler/base/hierarchy_design.py b/compiler/base/hierarchy_design.py index 5404838a..17022424 100644 --- a/compiler/base/hierarchy_design.py +++ b/compiler/base/hierarchy_design.py @@ -73,11 +73,11 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout): elif (OPTS.inline_lvsdrc or force_check or final_verification): tempspice = "{0}/{1}.sp".format(OPTS.openram_temp, self.name) - tempgds = "{0}/{1}.gds".format(OPTS.openram_temp, self.name) self.lvs_write(tempspice) + tempgds = "{0}/{1}.gds".format(OPTS.openram_temp, self.name) self.gds_write(tempgds) # Final verification option does not allow nets to be connected by label. - self.drc_errors = verify.run_drc(self.cell_name, tempgds, extract=True, final_verification=final_verification) + self.drc_errors = verify.run_drc(self.cell_name, tempgds, tempspice, extract=True, final_verification=final_verification) self.lvs_errors = verify.run_lvs(self.cell_name, tempgds, tempspice, final_verification=final_verification) # force_check is used to determine decoder height and other things, so we shouldn't fail @@ -105,9 +105,11 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout): if OPTS.netlist_only: return elif (not OPTS.is_unit_test and OPTS.check_lvsdrc and (OPTS.inline_lvsdrc or final_verification)): - tempgds = "{0}/{1}.gds".format(OPTS.openram_temp, self.cell_name) + tempspice = "{0}{1}.sp".format(OPTS.openram_temp, self.name) + self.lvs_write(tempspice) + tempgds = "{0}{1}.gds".format(OPTS.openram_temp, self.cell_name) self.gds_write(tempgds) - num_errors = verify.run_drc(self.cell_name, tempgds, final_verification=final_verification) + num_errors = verify.run_drc(self.cell_name, tempgds, tempspice, final_verification=final_verification) debug.check(num_errors == 0, "DRC failed for {0} with {1} error(s)".format(self.cell_name, num_errors)) @@ -126,9 +128,9 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout): if OPTS.netlist_only: return elif (not OPTS.is_unit_test and OPTS.check_lvsdrc and (OPTS.inline_lvsdrc or final_verification)): - tempspice = "{0}/{1}.sp".format(OPTS.openram_temp, self.cell_name) - tempgds = "{0}/{1}.gds".format(OPTS.openram_temp, self.name) + tempspice = "{0}{1}.sp".format(OPTS.openram_temp, self.cell_name) self.lvs_write(tempspice) + tempgds = "{0}{1}.gds".format(OPTS.openram_temp, self.name) self.gds_write(tempgds) num_errors = verify.run_lvs(self.name, tempgds, tempspice, final_verification=final_verification) debug.check(num_errors == 0, diff --git a/compiler/tests/testutils.py b/compiler/tests/testutils.py index e63b457d..cc76d0c0 100644 --- a/compiler/tests/testutils.py +++ b/compiler/tests/testutils.py @@ -48,7 +48,7 @@ class openram_test(unittest.TestCase): # Run both DRC and LVS even if DRC might fail # Magic can still extract despite DRC failing, so it might be ok in some techs # if we ignore things like minimum metal area of pins - drc_result=verify.run_drc(a.name, tempgds, extract=True, final_verification=final_verification) + drc_result=verify.run_drc(a.name, tempgds, tempspice, extract=True, final_verification=final_verification) # We can still run LVS even if DRC fails in Magic OR Calibre lvs_result=verify.run_lvs(a.name, tempgds, tempspice, final_verification=final_verification) diff --git a/compiler/verify/calibre.py b/compiler/verify/calibre.py index d45cfe09..5e49e6e1 100644 --- a/compiler/verify/calibre.py +++ b/compiler/verify/calibre.py @@ -30,9 +30,13 @@ num_lvs_runs = 0 num_pex_runs = 0 -def write_drc_script(cell_name, gds_name, extract, final_verification, output_path): +def write_drc_script(cell_name, gds_name, extract, final_verification=False, output_path=None): """ Write a Calibre runset file and script to run DRC """ # the runset file contains all the options to run calibre + + if not output_path: + output_path = OPTS.openram_temp + from tech import drc drc_rules = drc["drc_rules"] @@ -68,9 +72,12 @@ def write_drc_script(cell_name, gds_name, extract, final_verification, output_pa return drc_runset -def write_lvs_script(cell_name, gds_name, sp_name, final_verification, output_path): +def write_lvs_script(cell_name, gds_name, sp_name, final_verification=False, output_path=None): """ Write a Calibre runset file and script to run LVS """ + if not output_path: + output_path = OPTS.openram_temp + from tech import drc lvs_rules = drc["lvs_rules"] lvs_runset = { @@ -132,8 +139,12 @@ def write_lvs_script(cell_name, gds_name, sp_name, final_verification, output_pa return lvs_runset -def write_pex_script(cell_name, extract, output, final_verification, output_path): +def write_pex_script(cell_name, extract, output, final_verification=False, output_path=None): """ Write a pex script that can either just extract the netlist or the netlist+parasitics """ + + if not output_path: + output_path = OPTS.openram_temp + if output == None: output = cell_name + ".pex.sp" @@ -142,7 +153,7 @@ def write_pex_script(cell_name, extract, output, final_verification, output_path if not os.path.isfile(output_path + cell_name + ".lvs.report"): gds_name = output_path +"/"+ cell_name + ".gds" sp_name = output_path +"/"+ cell_name + ".sp" - run_drc(cell_name, gds_name) + run_drc(cell_name, gds_name, sp_name) run_lvs(cell_name, gds_name, sp_name) from tech import drc @@ -181,7 +192,7 @@ def write_pex_script(cell_name, extract, output, final_verification, output_path return pex_runset -def run_drc(cell_name, gds_name, extract=False, final_verification=False): +def run_drc(cell_name, gds_name, sp_name, extract=False, final_verification=False): """Run DRC check on a given top-level name which is implemented in gds_name.""" diff --git a/compiler/verify/magic.py b/compiler/verify/magic.py index c2f13cc4..9ab0333f 100644 --- a/compiler/verify/magic.py +++ b/compiler/verify/magic.py @@ -66,7 +66,7 @@ num_pex_runs = 0 # (outfile, errfile, resultsfile) = run_script(cell_name, "filter") -def write_drc_script(cell_name, gds_name, extract, final_verification, output_path): +def write_drc_script(cell_name, gds_name, extract, final_verification, output_path, sp_name=None): """ Write a magic script to perform DRC and optionally extraction. """ global OPTS @@ -102,35 +102,38 @@ def write_drc_script(cell_name, gds_name, extract, final_verification, output_pa f.write("drc catchup\n") f.write("drc count total\n") f.write("drc count\n") - f.write("port makeall\n") + if not sp_name: + f.write("port makeall\n") + else: + f.write("readspice {}\n".format(sp_name)) if not extract: pre = "#" else: pre = "" if final_verification and OPTS.route_supplies: - f.write(pre + "extract unique all\n".format(cell_name)) + f.write(pre + "extract unique all\n") # Hack to work around unit scales in SkyWater if OPTS.tech_name=="sky130": f.write(pre + "extract style ngspice(si)\n") - f.write(pre + "extract\n".format(cell_name)) + f.write(pre + "extract\n") # f.write(pre + "ext2spice hierarchy on\n") # f.write(pre + "ext2spice scale off\n") # lvs exists in 8.2.79, but be backword compatible for now - #f.write(pre+"ext2spice lvs\n") - f.write(pre+"ext2spice hierarchy on\n") - f.write(pre+"ext2spice format ngspice\n") - f.write(pre+"ext2spice cthresh infinite\n") - f.write(pre+"ext2spice rthresh infinite\n") - f.write(pre+"ext2spice renumber off\n") - f.write(pre+"ext2spice scale off\n") - f.write(pre+"ext2spice blackbox on\n") - f.write(pre+"ext2spice subcircuit top on\n") - f.write(pre+"ext2spice global off\n") + # f.write(pre + "ext2spice lvs\n") + f.write(pre + "ext2spice hierarchy on\n") + f.write(pre + "ext2spice format ngspice\n") + f.write(pre + "ext2spice cthresh infinite\n") + f.write(pre + "ext2spice rthresh infinite\n") + f.write(pre + "ext2spice renumber off\n") + f.write(pre + "ext2spice scale off\n") + f.write(pre + "ext2spice blackbox on\n") + f.write(pre + "ext2spice subcircuit top on\n") + f.write(pre + "ext2spice global off\n") # Can choose hspice, ngspice, or spice3, # but they all seem compatible enough. - f.write(pre+"ext2spice format ngspice\n") - f.write(pre+"ext2spice {}\n".format(cell_name)) + f.write(pre + "ext2spice format ngspice\n") + f.write(pre + "ext2spice {}\n".format(cell_name)) f.write("quit -noprompt\n") f.write("EOF\n") @@ -138,7 +141,7 @@ def write_drc_script(cell_name, gds_name, extract, final_verification, output_pa os.system("chmod u+x {}".format(run_file)) -def run_drc(cell_name, gds_name, extract=True, final_verification=False): +def run_drc(cell_name, gds_name, sp_name=None, extract=True, final_verification=False): """Run DRC check on a cell which is implemented in gds_name.""" global num_drc_runs @@ -148,7 +151,7 @@ def run_drc(cell_name, gds_name, extract=True, final_verification=False): if os.path.dirname(gds_name)!=OPTS.openram_temp.rstrip('/'): shutil.copy(gds_name, OPTS.openram_temp) - write_drc_script(cell_name, gds_name, extract, final_verification, OPTS.openram_temp) + write_drc_script(cell_name, gds_name, extract, final_verification, OPTS.openram_temp, sp_name=sp_name) (outfile, errfile, resultsfile) = run_script(cell_name, "drc") @@ -161,7 +164,7 @@ def run_drc(cell_name, gds_name, extract=True, final_verification=False): try: f = open(outfile, "r") except FileNotFoundError: - debug.error("Unable to load DRC results file from {}. Is magic set up?".format(outfile),1) + debug.error("Unable to load DRC results file from {}. Is magic set up?".format(outfile), 1) results = f.readlines() f.close() @@ -172,7 +175,7 @@ def run_drc(cell_name, gds_name, extract=True, final_verification=False): errors = int(re.split(": ", line)[1]) break else: - debug.error("Unable to find the total error line in Magic output.",1) + debug.error("Unable to find the total error line in Magic output.", 1) # always display this summary @@ -180,7 +183,7 @@ def run_drc(cell_name, gds_name, extract=True, final_verification=False): if errors > 0: for line in results: if "error tiles" in line: - debug.info(1,line.rstrip("\n")) + debug.info(1, line.rstrip("\n")) debug.warning(result_str) else: debug.info(1, result_str) @@ -188,11 +191,14 @@ def run_drc(cell_name, gds_name, extract=True, final_verification=False): return errors -def write_lvs_script(cell_name, gds_name, sp_name, final_verification, output_path): +def write_lvs_script(cell_name, gds_name, sp_name, final_verification=False, output_path=None): """ Write a netgen script to perform LVS. """ global OPTS + if not output_path: + output_path = OPTS.openram_temp + setup_file = "setup.tcl" full_setup_file = OPTS.openram_tech + "tech/" + setup_file if os.path.exists(full_setup_file): @@ -214,7 +220,7 @@ def write_lvs_script(cell_name, gds_name, sp_name, final_verification, output_pa os.system("chmod u+x {}".format(run_file)) -def run_lvs(cell_name, gds_name, sp_name, final_verification=False): +def run_lvs(cell_name, gds_name, sp_name, final_verification=False, output_path=None): """Run LVS check on a given top-level name which is implemented in gds_name and sp_name. Final verification will ensure that there are no remaining virtual conections. """ @@ -222,13 +228,16 @@ def run_lvs(cell_name, gds_name, sp_name, final_verification=False): global num_lvs_runs num_lvs_runs += 1 + if not output_path: + output_path = OPTS.openram_temp + # Copy file to local dir if it isn't already - if os.path.dirname(gds_name)!=OPTS.openram_temp.rstrip('/'): - shutil.copy(gds_name, OPTS.openram_temp) - if os.path.dirname(sp_name)!=OPTS.openram_temp.rstrip('/'): - shutil.copy(sp_name, OPTS.openram_temp) + if os.path.dirname(gds_name) != output_path.rstrip('/'): + shutil.copy(gds_name, output_path) + if os.path.dirname(sp_name) != output_path.rstrip('/'): + shutil.copy(sp_name, output_path) - write_lvs_script(cell_name, gds_name, sp_name, final_verification, OPTS.openram_temp) + write_lvs_script(cell_name, gds_name, sp_name, final_verification) (outfile, errfile, resultsfile) = run_script(cell_name, "lvs") @@ -289,13 +298,17 @@ def run_lvs(cell_name, gds_name, sp_name, final_verification=False): return total_errors -def run_pex(name, gds_name, sp_name, output=None, final_verification=False): +def run_pex(name, gds_name, sp_name, output=None, final_verification=False, output_path=None): """Run pex on a given top-level name which is implemented in gds_name and sp_name. """ global num_pex_runs num_pex_runs += 1 - os.chdir(OPTS.openram_temp) + + os.chdir(output_path) + + if not output_path: + output_path = OPTS.openram_temp if output == None: output = name + ".pex.netlist" @@ -311,8 +324,8 @@ def run_pex(name, gds_name, sp_name, output=None, final_verification=False): # the dev old code using batch mode does not run and is split into functions pex_runset = write_script_pex_rule(gds_name, name, output) - errfile = "{0}{1}.pex.err".format(OPTS.openram_temp, name) - outfile = "{0}{1}.pex.out".format(OPTS.openram_temp, name) + errfile = "{0}{1}.pex.err".format(output_path, name) + outfile = "{0}{1}.pex.out".format(output_path, name) script_cmd = "{0} 2> {1} 1> {2}".format(pex_runset, errfile, @@ -387,7 +400,7 @@ def write_batch_pex_rule(gds_name, name, sp_name, output): return file -def write_script_pex_rule(gds_name, cell_name, output): +def write_script_pex_rule(gds_name, cell_name, sp_name, output): global OPTS run_file = OPTS.openram_temp + "run_pex.sh" f = open(run_file, "w") @@ -399,26 +412,24 @@ def write_script_pex_rule(gds_name, cell_name, output): f.write("load {}\n".format(cell_name)) f.write("select top cell\n") f.write("expand\n") - f.write("port makeall\n") - extract = True - if not extract: - pre = "#" + if not sp_name: + f.write("port makeall\n") else: - pre = "" - f.write(pre + "extract\n") - f.write(pre + "ext2sim labels on\n") - f.write(pre + "ext2sim\n") - f.write(pre + "extresist simplify off\n") - f.write(pre + "extresist all\n") - f.write(pre + "ext2spice hierarchy off\n") - f.write(pre + "ext2spice format ngspice\n") - f.write(pre + "ext2spice renumber off\n") - f.write(pre + "ext2spice scale off\n") - f.write(pre + "ext2spice blackbox on\n") - f.write(pre + "ext2spice subcircuit top on\n") - f.write(pre + "ext2spice global off\n") - f.write(pre + "ext2spice extresist on\n") - f.write(pre + "ext2spice {}\n".format(cell_name)) + f.write("readspice {}\n".format(sp_name)) + f.write("extract\n") + f.write("ext2sim labels on\n") + f.write("ext2sim\n") + f.write("extresist simplify off\n") + f.write("extresist all\n") + f.write("ext2spice hierarchy off\n") + f.write("ext2spice format ngspice\n") + f.write("ext2spice renumber off\n") + f.write("ext2spice scale off\n") + f.write("ext2spice blackbox on\n") + f.write("ext2spice subcircuit top on\n") + f.write("ext2spice global off\n") + f.write("ext2spice extresist on\n") + f.write("ext2spice {}\n".format(cell_name)) f.write("quit -noprompt\n") f.write("eof\n") f.write("mv {0}.spice {1}\n".format(cell_name, output)) diff --git a/compiler/verify/none.py b/compiler/verify/none.py index 28a5a47b..bd2fb722 100644 --- a/compiler/verify/none.py +++ b/compiler/verify/none.py @@ -17,11 +17,11 @@ lvs_warned = False pex_warned = False -def write_drc_script(cell_name, gds_name, extract, final_verification, output_path): +def write_drc_script(cell_name, gds_name, extract, final_verification=False, output_path=None): pass -def run_drc(cell_name, gds_name, extract=False, final_verification=False): +def run_drc(cell_name, gds_name, sp_name, extract=False, final_verification=False, output_path=None): global drc_warned if not drc_warned: debug.error("DRC unable to run.", -1) @@ -30,11 +30,11 @@ def run_drc(cell_name, gds_name, extract=False, final_verification=False): return 1 -def write_lvs_script(cell_name, gds_name, sp_name, final_verification, output_path): +def write_lvs_script(cell_name, gds_name, sp_name, final_verification=False, output_path=None): pass -def run_lvs(cell_name, gds_name, sp_name, final_verification=False): +def run_lvs(cell_name, gds_name, sp_name, final_verification=False, output_path=None): global lvs_warned if not lvs_warned: debug.error("LVS unable to run.", -1) @@ -43,7 +43,7 @@ def run_lvs(cell_name, gds_name, sp_name, final_verification=False): return 1 -def run_pex(name, gds_name, sp_name, output=None, final_verification=False): +def run_pex(name, gds_name, sp_name, output=None, final_verification=False, output_path=None): global pex_warned if not pex_warned: debug.error("PEX unable to run.", -1) From 537e862d4877e5aebcf17f0b58a08d4ca1d2bda7 Mon Sep 17 00:00:00 2001 From: mrg Date: Tue, 10 Nov 2020 20:38:41 -0800 Subject: [PATCH 03/31] Add -full to LVS script --- compiler/verify/magic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/verify/magic.py b/compiler/verify/magic.py index 9ab0333f..97c9efb9 100644 --- a/compiler/verify/magic.py +++ b/compiler/verify/magic.py @@ -213,7 +213,7 @@ def write_lvs_script(cell_name, gds_name, sp_name, final_verification=False, out f.write("{} -noconsole << EOF\n".format(OPTS.lvs_exe[1])) # f.write("readnet spice {0}.spice\n".format(cell_name)) # f.write("readnet spice {0}\n".format(sp_name)) - f.write("lvs {{{0}.spice {0}}} {{{1} {0}}} {2} {0}.lvs.report -json\n".format(cell_name, sp_name, setup_file)) + f.write("lvs {{{0}.spice {0}}} {{{1} {0}}} {2} {0}.lvs.report -full -json\n".format(cell_name, sp_name, setup_file)) f.write("quit\n") f.write("EOF\n") f.close() From d3cb22c8c19cb94228be486521f073029661f50d Mon Sep 17 00:00:00 2001 From: mrg Date: Thu, 12 Nov 2020 09:33:48 -0800 Subject: [PATCH 04/31] Fix pin vs module names issue #26 --- 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 d971492e..70011227 100644 --- a/compiler/base/hierarchy_spice.py +++ b/compiler/base/hierarchy_spice.py @@ -104,7 +104,7 @@ class spice(): debug.error("{} spice subcircuit port names do not match pin_names\ \n SPICE names={}\ \n Module names={}\ - ".format(self.name, self.pin_names, self.pins), 1) + ".format(self.name, self.pin, self.pin_names), 1) self.pin_type = {pin: type for pin, type in zip(self.pin_names, type_list)} def get_pin_type(self, name): From d4c4658c77ebe3af427c6181cdab9bfcf7e01bc1 Mon Sep 17 00:00:00 2001 From: mrg Date: Thu, 12 Nov 2020 09:43:08 -0800 Subject: [PATCH 05/31] Clean up invalid routing layer error message --- compiler/base/pin_layout.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/base/pin_layout.py b/compiler/base/pin_layout.py index 31a47671..40e3c2f5 100644 --- a/compiler/base/pin_layout.py +++ b/compiler/base/pin_layout.py @@ -32,7 +32,7 @@ class pin_layout: debug.check(self.height() > 0, "Zero height pin.") # These are the valid pin layers - valid_layers = { x: layer[x] for x in layer_indices.keys()} + valid_layers = {x: layer[x] for x in layer_indices.keys()} # if it's a string, use the name if type(layer_name_pp) == str: @@ -46,7 +46,7 @@ class pin_layout: self._layer = layer_name break else: - debug.error("Couldn't find layer {}".format(layer_name_pp), -1) + debug.error("Layer {} is not a valid routing layer in the tech file.".format(layer_name_pp), -1) self.lpp = layer[self.layer] self._recompute_hash() From a2f29e5edd5c1279f15b2c6837b6f9a43261f6d6 Mon Sep 17 00:00:00 2001 From: mrg Date: Thu, 12 Nov 2020 09:48:08 -0800 Subject: [PATCH 06/31] Fix missing nand4_leakage #97 --- technology/freepdk45/tech/tech.py | 23 ++++++++++++----------- technology/scn4m_subm/tech/tech.py | 23 ++++++++++++----------- 2 files changed, 24 insertions(+), 22 deletions(-) diff --git a/technology/freepdk45/tech/tech.py b/technology/freepdk45/tech/tech.py index 1616e9f9..17a3b278 100644 --- a/technology/freepdk45/tech/tech.py +++ b/technology/freepdk45/tech/tech.py @@ -438,22 +438,23 @@ spice["bitcell_leakage"] = 1 # Leakage power of a single bitcell in nW spice["inv_leakage"] = 1 # Leakage power of inverter in nW spice["nand2_leakage"] = 1 # Leakage power of 2-input nand in nW spice["nand3_leakage"] = 1 # Leakage power of 3-input nand in nW +spice["nand4_leakage"] = 1 # Leakage power of 4-input nand in nW spice["nor2_leakage"] = 1 # Leakage power of 2-input nor in nW spice["dff_leakage"] = 1 # Leakage power of flop in nW spice["default_event_frequency"] = 100 # Default event activity of every gate. MHz -#Parameters related to sense amp enable timing and delay chain/RBL sizing -parameter["le_tau"] = 2.25 #In pico-seconds. -parameter["cap_relative_per_ff"] = 7.5 #Units of Relative Capacitance/ Femto-Farad -parameter["dff_clk_cin"] = 30.6 #relative capacitance -parameter["6tcell_wl_cin"] = 3 #relative capacitance -parameter["min_inv_para_delay"] = 2.4 #Tau delay units -parameter["sa_en_pmos_size"] = 0.72 #micro-meters -parameter["sa_en_nmos_size"] = 0.27 #micro-meters -parameter["sa_inv_pmos_size"] = 0.54 #micro-meters -parameter["sa_inv_nmos_size"] = 0.27 #micro-meters -parameter["bitcell_drain_cap"] = 0.1 #In Femto-Farad, approximation of drain capacitance +# Parameters related to sense amp enable timing and delay chain/RBL sizing +parameter["le_tau"] = 2.25 # In pico-seconds. +parameter["cap_relative_per_ff"] = 7.5 # Units of Relative Capacitance/ Femto-Farad +parameter["dff_clk_cin"] = 30.6 # relative capacitance +parameter["6tcell_wl_cin"] = 3 # relative capacitance +parameter["min_inv_para_delay"] = 2.4 # Tau delay units +parameter["sa_en_pmos_size"] = 0.72 # micro-meters +parameter["sa_en_nmos_size"] = 0.27 # micro-meters +parameter["sa_inv_pmos_size"] = 0.54 # micro-meters +parameter["sa_inv_nmos_size"] = 0.27 # micro-meters +parameter["bitcell_drain_cap"] = 0.1 # In Femto-Farad, approximation of drain capacitance ################################################### # Technology Tool Preferences diff --git a/technology/scn4m_subm/tech/tech.py b/technology/scn4m_subm/tech/tech.py index c7b50272..b1ba6795 100644 --- a/technology/scn4m_subm/tech/tech.py +++ b/technology/scn4m_subm/tech/tech.py @@ -385,22 +385,23 @@ spice["bitcell_leakage"] = 1 # Leakage power of a single bitcell in nW spice["inv_leakage"] = 1 # Leakage power of inverter in nW spice["nand2_leakage"] = 1 # Leakage power of 2-input nand in nW spice["nand3_leakage"] = 1 # Leakage power of 3-input nand in nW +spice["nand4_leakage"] = 1 # Leakage power of 4-input nand in nW spice["nor2_leakage"] = 1 # Leakage power of 2-input nor in nW spice["dff_leakage"] = 1 # Leakage power of flop in nW spice["default_event_frequency"] = 100 # Default event activity of every gate. MHz -#Logical Effort relative values for the Handmade cells -parameter["le_tau"] = 18.17 #In pico-seconds. -parameter["min_inv_para_delay"] = 2.07 #In relative delay units -parameter["cap_relative_per_ff"] = .91 #Units of Relative Capacitance/ Femto-Farad -parameter["dff_clk_cin"] = 27.5 #In relative capacitance units -parameter["6tcell_wl_cin"] = 2 #In relative capacitance units -parameter["sa_en_pmos_size"] = 24*_lambda_ -parameter["sa_en_nmos_size"] = 9*_lambda_ -parameter["sa_inv_pmos_size"] = 18*_lambda_ -parameter["sa_inv_nmos_size"] = 9*_lambda_ -parameter["bitcell_drain_cap"] = 0.2 #In Femto-Farad, approximation of drain capacitance +# Logical Effort relative values for the Handmade cells +parameter["le_tau"] = 18.17 # In pico-seconds. +parameter["min_inv_para_delay"] = 2.07 # In relative delay units +parameter["cap_relative_per_ff"] = .91 # Units of Relative Capacitance/ Femto-Farad +parameter["dff_clk_cin"] = 27.5 # In relative capacitance units +parameter["6tcell_wl_cin"] = 2 # In relative capacitance units +parameter["sa_en_pmos_size"] = 24 * _lambda_ +parameter["sa_en_nmos_size"] = 9 * _lambda_ +parameter["sa_inv_pmos_size"] = 18 * _lambda_ +parameter["sa_inv_nmos_size"] = 9 * _lambda_ +parameter["bitcell_drain_cap"] = 0.2 # In Femto-Farad, approximation of drain capacitance ################################################### # Technology Tool Preferences From 63941a10e1cda830debb445693531c0e4980a935 Mon Sep 17 00:00:00 2001 From: mrg Date: Thu, 12 Nov 2020 10:01:38 -0800 Subject: [PATCH 07/31] Add None as sp_file parameter to local_drc_check --- compiler/tests/testutils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/tests/testutils.py b/compiler/tests/testutils.py index cc76d0c0..d60dde40 100644 --- a/compiler/tests/testutils.py +++ b/compiler/tests/testutils.py @@ -25,7 +25,7 @@ class openram_test(unittest.TestCase): w.gds_write(tempgds) import verify - result=verify.run_drc(w.name, tempgds) + result=verify.run_drc(w.name, tempgds, None) if result != 0: self.fail("DRC failed: {}".format(w.name)) From 190234df58048a67da6c5603218f1957a633d1e4 Mon Sep 17 00:00:00 2001 From: mrg Date: Thu, 12 Nov 2020 12:12:53 -0800 Subject: [PATCH 08/31] Add PININFO to outputs too --- compiler/base/hierarchy_spice.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/compiler/base/hierarchy_spice.py b/compiler/base/hierarchy_spice.py index d971492e..7e09b970 100644 --- a/compiler/base/hierarchy_spice.py +++ b/compiler/base/hierarchy_spice.py @@ -296,6 +296,18 @@ class spice(): sp.write("\n.SUBCKT {0} {1}\n".format(self.cell_name, " ".join(self.pins))) + # write a PININFO line + 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, self.pin_type[pin])) From bdda7c4f5f7bfa7e5df0646493f5d01b671776be Mon Sep 17 00:00:00 2001 From: mrg Date: Thu, 12 Nov 2020 12:38:09 -0800 Subject: [PATCH 09/31] Add bl/br pins to dummy array --- compiler/modules/dummy_array.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/compiler/modules/dummy_array.py b/compiler/modules/dummy_array.py index 51b423ae..0a33e7cc 100644 --- a/compiler/modules/dummy_array.py +++ b/compiler/modules/dummy_array.py @@ -5,7 +5,6 @@ # from bitcell_base_array import bitcell_base_array from sram_factory import factory -from tech import cell_properties as props from globals import OPTS @@ -77,15 +76,17 @@ class dummy_array(bitcell_base_array): for col in range(self.column_size): for port in self.all_ports: bl_pin = self.cell_inst[0, col].get_pin(bitline_names[2 * port]) - self.add_rect(layer=bl_pin.layer, - offset=bl_pin.ll().scale(1, 0), - width=bl_pin.width(), - height=self.height) + self.add_layout_pin(text="bl_{0}_{1}".format(port, col), + layer=bl_pin.layer, + offset=bl_pin.ll().scale(1, 0), + width=bl_pin.width(), + height=self.height) br_pin = self.cell_inst[0, col].get_pin(bitline_names[2 * port + 1]) - self.add_rect(layer=br_pin.layer, - offset=br_pin.ll().scale(1, 0), - width=br_pin.width(), - height=self.height) + self.add_layout_pin(text="br_{0}_{1}".format(port, col), + layer=br_pin.layer, + offset=br_pin.ll().scale(1, 0), + width=br_pin.width(), + height=self.height) wl_names = self.cell.get_all_wl_names() for row in range(self.row_size): From 9eeab1463952310948838c56f5d9f5bf46ec823e Mon Sep 17 00:00:00 2001 From: mrg Date: Thu, 12 Nov 2020 14:33:42 -0800 Subject: [PATCH 10/31] Add comment before pininfo --- 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 7e09b970..81676ec1 100644 --- a/compiler/base/hierarchy_spice.py +++ b/compiler/base/hierarchy_spice.py @@ -297,7 +297,7 @@ class spice(): " ".join(self.pins))) # write a PININFO line - pin_info = ".PININFO" + pin_info = "*.PININFO" for pin in self.pins: if self.pin_type[pin] == "INPUT": pin_info += " {0}:I".format(pin) From e6a7ecae84aea56fed390c801b02a306bdc3ca62 Mon Sep 17 00:00:00 2001 From: mrg Date: Thu, 12 Nov 2020 14:43:57 -0800 Subject: [PATCH 11/31] Fix missing default path in pex --- compiler/verify/magic.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/compiler/verify/magic.py b/compiler/verify/magic.py index 97c9efb9..a8345a96 100644 --- a/compiler/verify/magic.py +++ b/compiler/verify/magic.py @@ -305,6 +305,9 @@ def run_pex(name, gds_name, sp_name, output=None, final_verification=False, outp global num_pex_runs num_pex_runs += 1 + if not output_path: + output_path = OPTS.openram_temp + os.chdir(output_path) if not output_path: @@ -322,7 +325,7 @@ def run_pex(name, gds_name, sp_name, output=None, final_verification=False, outp # pex_fix did run the pex using a script while dev orignial method # use batch mode. # the dev old code using batch mode does not run and is split into functions - pex_runset = write_script_pex_rule(gds_name, name, output) + pex_runset = write_script_pex_rule(gds_name, name, sp_name, output) errfile = "{0}{1}.pex.err".format(output_path, name) outfile = "{0}{1}.pex.out".format(output_path, name) From 198c0faf854a6d41932885b6b8572ed16533e5b2 Mon Sep 17 00:00:00 2001 From: mrg Date: Fri, 13 Nov 2020 07:45:31 -0800 Subject: [PATCH 12/31] Remove special s8 6t names --- compiler/base/custom_cell_properties.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/compiler/base/custom_cell_properties.py b/compiler/base/custom_cell_properties.py index c592665a..8530ee64 100644 --- a/compiler/base/custom_cell_properties.py +++ b/compiler/base/custom_cell_properties.py @@ -50,7 +50,6 @@ class _pgate: class _bitcell: def __init__(self, mirror, cell_s8_6t, cell_6t, cell_1rw1r, cell_1w1r): self.mirror = mirror - self._s8_6t = cell_s8_6t self._6t = cell_6t self._1rw1r = cell_1rw1r self._1w1r = cell_1w1r @@ -58,10 +57,6 @@ class _bitcell: def _default(): axis = _mirror_axis(True, False) - cell_s8_6t = _cell({'bl': 'bl', - 'br': 'br', - 'wl': 'wl'}) - cell_6t = _cell({'bl': 'bl', 'br': 'br', 'wl': 'wl'}) From cf63499e769d3b3f9174f2d47a73aeb40e21d55c Mon Sep 17 00:00:00 2001 From: mrg Date: Fri, 13 Nov 2020 08:09:21 -0800 Subject: [PATCH 13/31] Convert bitcells to 1port and 2port --- compiler/base/custom_cell_properties.py | 9 +-- .../bitcells/{bitcell.py => bitcell_1port.py} | 2 +- .../{bitcell_1w_1r.py => bitcell_2port.py} | 66 ++++++++++-------- ...ell_1rw_1r.py => col_cap_bitcell_2port.py} | 0 ...ummy_bitcell.py => dummy_bitcell_1port.py} | 0 compiler/bitcells/dummy_bitcell_1w_1r.py | 37 ---------- compiler/bitcells/dummy_bitcell_2port.py | 31 ++++++++ ...ca_bitcell.py => replica_bitcell_1port.py} | 0 ...cell_1w_1r.py => replica_bitcell_2port.py} | 42 +++++------ ...ell_1rw_1r.py => row_cap_bitcell_2port.py} | 0 compiler/globals.py | 20 ++---- compiler/options.py | 2 +- technology/freepdk45/gds_lib/cell_1rw_1r.gds | Bin 16384 -> 0 bytes .../gds_lib/{cell_1w_1r.gds => cell_2rw.gds} | Bin 16384 -> 15930 bytes .../freepdk45/gds_lib/dummy_cell_1rw_1r.gds | Bin 16384 -> 0 bytes ...ummy_cell_1w_1r.gds => dummy_cell_2rw.gds} | Bin 16384 -> 15672 bytes .../freepdk45/gds_lib/replica_cell_1rw_1r.gds | Bin 16384 -> 0 bytes ...ca_cell_1w_1r.gds => replica_cell_2rw.gds} | Bin 16384 -> 16002 bytes technology/freepdk45/sp_lib/cell_1rw_1r.sp | 14 ---- .../sp_lib/{cell_1w_1r.sp => cell_2rw.sp} | 2 +- .../freepdk45/sp_lib/dummy_cell_1rw_1r.sp | 14 ---- ...{dummy_cell_1w_1r.sp => dummy_cell_2rw.sp} | 2 +- .../freepdk45/sp_lib/replica_cell_1rw_1r.sp | 14 ---- ...lica_cell_1w_1r.sp => replica_cell_2rw.sp} | 2 +- technology/freepdk45/tech/tech.py | 7 ++ technology/scn4m_subm/gds_lib/cell_1rw_1r.gds | Bin 6330 -> 0 bytes technology/scn4m_subm/gds_lib/cell_1w_1r.gds | Bin 6406 -> 0 bytes technology/scn4m_subm/gds_lib/cell_2rw.gds | Bin 0 -> 6326 bytes .../scn4m_subm/gds_lib/dummy_cell_1rw_1r.gds | Bin 6086 -> 0 bytes .../scn4m_subm/gds_lib/dummy_cell_1w_1r.gds | Bin 6082 -> 0 bytes .../scn4m_subm/gds_lib/dummy_cell_2rw.gds | Bin 0 -> 6082 bytes .../gds_lib/replica_cell_1rw_1r.gds | Bin 6282 -> 0 bytes .../scn4m_subm/gds_lib/replica_cell_1w_1r.gds | Bin 8192 -> 0 bytes .../scn4m_subm/gds_lib/replica_cell_2rw.gds | Bin 0 -> 6278 bytes .../sp_lib/{cell_1rw_1r.sp => cell_2rw.sp} | 2 +- ...dummy_cell_1rw_1r.sp => dummy_cell_2rw.sp} | 2 +- ...ica_cell_1rw_1r.sp => replica_cell_2rw.sp} | 2 +- technology/scn4m_subm/tech/tech.py | 7 ++ 38 files changed, 113 insertions(+), 164 deletions(-) rename compiler/bitcells/{bitcell.py => bitcell_1port.py} (98%) rename compiler/bitcells/{bitcell_1w_1r.py => bitcell_2port.py} (63%) rename compiler/bitcells/{col_cap_bitcell_1rw_1r.py => col_cap_bitcell_2port.py} (100%) rename compiler/bitcells/{dummy_bitcell.py => dummy_bitcell_1port.py} (100%) delete mode 100644 compiler/bitcells/dummy_bitcell_1w_1r.py create mode 100644 compiler/bitcells/dummy_bitcell_2port.py rename compiler/bitcells/{replica_bitcell.py => replica_bitcell_1port.py} (100%) rename compiler/bitcells/{replica_bitcell_1w_1r.py => replica_bitcell_2port.py} (50%) rename compiler/bitcells/{row_cap_bitcell_1rw_1r.py => row_cap_bitcell_2port.py} (100%) delete mode 100644 technology/freepdk45/gds_lib/cell_1rw_1r.gds rename technology/freepdk45/gds_lib/{cell_1w_1r.gds => cell_2rw.gds} (77%) delete mode 100644 technology/freepdk45/gds_lib/dummy_cell_1rw_1r.gds rename technology/freepdk45/gds_lib/{dummy_cell_1w_1r.gds => dummy_cell_2rw.gds} (85%) delete mode 100644 technology/freepdk45/gds_lib/replica_cell_1rw_1r.gds rename technology/freepdk45/gds_lib/{replica_cell_1w_1r.gds => replica_cell_2rw.gds} (77%) delete mode 100644 technology/freepdk45/sp_lib/cell_1rw_1r.sp rename technology/freepdk45/sp_lib/{cell_1w_1r.sp => cell_2rw.sp} (91%) delete mode 100644 technology/freepdk45/sp_lib/dummy_cell_1rw_1r.sp rename technology/freepdk45/sp_lib/{dummy_cell_1w_1r.sp => dummy_cell_2rw.sp} (90%) delete mode 100644 technology/freepdk45/sp_lib/replica_cell_1rw_1r.sp rename technology/freepdk45/sp_lib/{replica_cell_1w_1r.sp => replica_cell_2rw.sp} (89%) delete mode 100644 technology/scn4m_subm/gds_lib/cell_1rw_1r.gds delete mode 100644 technology/scn4m_subm/gds_lib/cell_1w_1r.gds create mode 100644 technology/scn4m_subm/gds_lib/cell_2rw.gds delete mode 100644 technology/scn4m_subm/gds_lib/dummy_cell_1rw_1r.gds delete mode 100644 technology/scn4m_subm/gds_lib/dummy_cell_1w_1r.gds create mode 100644 technology/scn4m_subm/gds_lib/dummy_cell_2rw.gds delete mode 100644 technology/scn4m_subm/gds_lib/replica_cell_1rw_1r.gds delete mode 100644 technology/scn4m_subm/gds_lib/replica_cell_1w_1r.gds create mode 100644 technology/scn4m_subm/gds_lib/replica_cell_2rw.gds rename technology/scn4m_subm/sp_lib/{cell_1rw_1r.sp => cell_2rw.sp} (88%) rename technology/scn4m_subm/sp_lib/{dummy_cell_1rw_1r.sp => dummy_cell_2rw.sp} (88%) rename technology/scn4m_subm/sp_lib/{replica_cell_1rw_1r.sp => replica_cell_2rw.sp} (86%) diff --git a/compiler/base/custom_cell_properties.py b/compiler/base/custom_cell_properties.py index 8530ee64..efff1786 100644 --- a/compiler/base/custom_cell_properties.py +++ b/compiler/base/custom_cell_properties.py @@ -48,7 +48,7 @@ class _pgate: class _bitcell: - def __init__(self, mirror, cell_s8_6t, cell_6t, cell_1rw1r, cell_1w1r): + def __init__(self, mirror, cell_6t, cell_1rw1r, cell_1w1r): self.mirror = mirror self._6t = cell_6t self._1rw1r = cell_1rw1r @@ -75,16 +75,11 @@ class _bitcell: 'wl0': 'wl0', 'wl1': 'wl1'}) - return _bitcell(cell_s8_6t=cell_s8_6t, - cell_6t=cell_6t, + return _bitcell(cell_6t=cell_6t, cell_1rw1r=cell_1rw1r, cell_1w1r=cell_1w1r, mirror=axis) - @property - def cell_s8_6t(self): - return self._s8_6t - @property def cell_6t(self): return self._6t diff --git a/compiler/bitcells/bitcell.py b/compiler/bitcells/bitcell_1port.py similarity index 98% rename from compiler/bitcells/bitcell.py rename to compiler/bitcells/bitcell_1port.py index b2a96356..e1e4bec8 100644 --- a/compiler/bitcells/bitcell.py +++ b/compiler/bitcells/bitcell_1port.py @@ -10,7 +10,7 @@ from tech import cell_properties as props import bitcell_base -class bitcell(bitcell_base.bitcell_base): +class bitcell_1port(bitcell_base.bitcell_base): """ A single bit cell (6T, 8T, etc.) This module implements the single memory cell used in the design. It is a hand-made cell, so diff --git a/compiler/bitcells/bitcell_1w_1r.py b/compiler/bitcells/bitcell_2port.py similarity index 63% rename from compiler/bitcells/bitcell_1w_1r.py rename to compiler/bitcells/bitcell_2port.py index 64a629a2..93642788 100644 --- a/compiler/bitcells/bitcell_1w_1r.py +++ b/compiler/bitcells/bitcell_2port.py @@ -10,7 +10,7 @@ from tech import cell_properties as props import bitcell_base -class bitcell_1w_1r(bitcell_base.bitcell_base): +class bitcell_2port(bitcell_base.bitcell_base): """ A single bit cell (6T, 8T, etc.) This module implements the single memory cell used in the design. It is a hand-made cell, so @@ -18,21 +18,21 @@ class bitcell_1w_1r(bitcell_base.bitcell_base): library. """ - pin_names = [props.bitcell.cell_1w1r.pin.bl0, - props.bitcell.cell_1w1r.pin.br0, - props.bitcell.cell_1w1r.pin.bl1, - props.bitcell.cell_1w1r.pin.br1, - props.bitcell.cell_1w1r.pin.wl0, - props.bitcell.cell_1w1r.pin.wl1, - props.bitcell.cell_1w1r.pin.vdd, - props.bitcell.cell_1w1r.pin.gnd] - type_list = ["OUTPUT", "OUTPUT", "INPUT", "INPUT", + pin_names = [props.bitcell.cell_1rw1r.pin.bl0, + props.bitcell.cell_1rw1r.pin.br0, + props.bitcell.cell_1rw1r.pin.bl1, + props.bitcell.cell_1rw1r.pin.br1, + props.bitcell.cell_1rw1r.pin.wl0, + props.bitcell.cell_1rw1r.pin.wl1, + props.bitcell.cell_1rw1r.pin.vdd, + props.bitcell.cell_1rw1r.pin.gnd] + type_list = ["OUTPUT", "OUTPUT", "OUTPUT", "OUTPUT", "INPUT", "INPUT", "POWER", "GROUND"] storage_nets = ['Q', 'Q_bar'] def __init__(self, name): super().__init__(name) - debug.info(2, "Create bitcell with 1W and 1R Port") + debug.info(2, "Create bitcell with 1RW and 1R Port") self.nets_match = self.do_nets_exist(self.storage_nets) @@ -46,7 +46,7 @@ class bitcell_1w_1r(bitcell_base.bitcell_base): Creates a list of connections in the bitcell, indexed by column and row, for instance use in bitcell_array """ - pin_name = props.bitcell.cell_1w1r.pin + pin_name = props.bitcell.cell_1rw1r.pin bitcell_pins = ["{0}_{1}".format(pin_name.bl0, col), "{0}_{1}".format(pin_name.br0, col), "{0}_{1}".format(pin_name.bl1, col), @@ -59,64 +59,68 @@ class bitcell_1w_1r(bitcell_base.bitcell_base): def get_all_wl_names(self): """ Creates a list of all wordline pin names """ - return [props.bitcell.cell_1w1r.pin.wl0, - props.bitcell.cell_1w1r.pin.wl1] + return [props.bitcell.cell_1rw1r.pin.wl0, + props.bitcell.cell_1rw1r.pin.wl1] def get_all_bitline_names(self): """ Creates a list of all bitline pin names (both bl and br) """ - return [props.bitcell.cell_1w1r.pin.bl0, - props.bitcell.cell_1w1r.pin.br0, - props.bitcell.cell_1w1r.pin.bl1, - props.bitcell.cell_1w1r.pin.br1] + return [props.bitcell.cell_1rw1r.pin.bl0, + props.bitcell.cell_1rw1r.pin.br0, + props.bitcell.cell_1rw1r.pin.bl1, + props.bitcell.cell_1rw1r.pin.br1] def get_all_bl_names(self): """ Creates a list of all bl pins names """ - return [props.bitcell.cell_1w1r.pin.bl0, - props.bitcell.cell_1w1r.pin.bl1] + return [props.bitcell.cell_1rw1r.pin.bl0, + props.bitcell.cell_1rw1r.pin.bl1] def get_all_br_names(self): """ Creates a list of all br pins names """ - return [props.bitcell.cell_1w1r.pin.br0, - props.bitcell.cell_1w1r.pin.br1] + return [props.bitcell.cell_1rw1r.pin.br0, + props.bitcell.cell_1rw1r.pin.br1] def get_read_bl_names(self): """ Creates a list of bl pin names associated with read ports """ - return [props.bitcell.cell_1w1r.pin.bl0, - props.bitcell.cell_1w1r.pin.bl1] + return [props.bitcell.cell_1rw1r.pin.bl0, + props.bitcell.cell_1rw1r.pin.bl1] def get_read_br_names(self): """ Creates a list of br pin names associated with read ports """ - return [props.bitcell.cell_1w1r.pin.br0, - props.bitcell.cell_1w1r.pin.br1] + return [props.bitcell.cell_1rw1r.pin.br0, + props.bitcell.cell_1rw1r.pin.br1] def get_write_bl_names(self): """ Creates a list of bl pin names associated with write ports """ - return [props.bitcell.cell_1w1r.pin.bl0] + return [props.bitcell.cell_1rw1r.pin.bl0] def get_write_br_names(self): """ Creates a list of br pin names asscociated with write ports""" - return [props.bitcell.cell_1w1r.pin.br1] + return [props.bitcell.cell_1rw1r.pin.br1] def get_bl_name(self, port=0): """Get bl name by port""" + debug.check(port < 2, "Two ports for bitcell_2port only.") return self.bl_names[port] def get_br_name(self, port=0): """Get bl name by port""" + debug.check(port < 2, "Two ports for bitcell_2port only.") return self.br_names[port] def get_wl_name(self, port=0): """Get wl name by port""" - debug.check(port < 2, "Two ports for bitcell_1rw_1r only.") + debug.check(port < 2, "Two ports for bitcell_2port only.") return self.wl_names[port] def build_graph(self, graph, inst_name, port_nets): """Adds edges to graph. Multiport bitcell timing graph is too complex to use the add_graph_edges function.""" pin_dict = {pin: port for pin, port in zip(self.pins, port_nets)} - pins = props.bitcell.cell_1w1r.pin # Edges hardcoded here. Essentially wl->bl/br for both ports. # Port 0 edges + pins = props.bitcell.cell_1rw1r.pin + graph.add_edge(pin_dict[pins.wl0], pin_dict[pins.bl0], self) + graph.add_edge(pin_dict[pins.wl0], pin_dict[pins.br0], self) + # Port 1 edges graph.add_edge(pin_dict[pins.wl1], pin_dict[pins.bl1], self) graph.add_edge(pin_dict[pins.wl1], pin_dict[pins.br1], self) - # Port 1 is a write port, so its timing is not considered here. diff --git a/compiler/bitcells/col_cap_bitcell_1rw_1r.py b/compiler/bitcells/col_cap_bitcell_2port.py similarity index 100% rename from compiler/bitcells/col_cap_bitcell_1rw_1r.py rename to compiler/bitcells/col_cap_bitcell_2port.py diff --git a/compiler/bitcells/dummy_bitcell.py b/compiler/bitcells/dummy_bitcell_1port.py similarity index 100% rename from compiler/bitcells/dummy_bitcell.py rename to compiler/bitcells/dummy_bitcell_1port.py diff --git a/compiler/bitcells/dummy_bitcell_1w_1r.py b/compiler/bitcells/dummy_bitcell_1w_1r.py deleted file mode 100644 index 60d87728..00000000 --- a/compiler/bitcells/dummy_bitcell_1w_1r.py +++ /dev/null @@ -1,37 +0,0 @@ -# See LICENSE for licensing information. -# -# Copyright (c) 2016-2019 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 debug -from tech import cell_properties as props -import bitcell_base - - -class dummy_bitcell_1w_1r(bitcell_base.bitcell_base): - """ - A single bit cell which is forced to store a 0. - This module implements the single memory cell used in the design. It - is a hand-made cell, so the layout and netlist should be available in - the technology library. """ - - pin_names = [props.bitcell.cell_1w1r.pin.bl0, - props.bitcell.cell_1w1r.pin.br0, - props.bitcell.cell_1w1r.pin.bl1, - props.bitcell.cell_1w1r.pin.br1, - props.bitcell.cell_1w1r.pin.wl0, - props.bitcell.cell_1w1r.pin.wl1, - props.bitcell.cell_1w1r.pin.vdd, - props.bitcell.cell_1w1r.pin.gnd] - type_list = ["OUTPUT", "OUTPUT", "INPUT", "INPUT", - "INPUT", "INPUT", "POWER", "GROUND"] - - def __init__(self, name): - super().__init__(name) - debug.info(2, "Create dummy bitcell 1w+1r object") - - - - diff --git a/compiler/bitcells/dummy_bitcell_2port.py b/compiler/bitcells/dummy_bitcell_2port.py new file mode 100644 index 00000000..679509db --- /dev/null +++ b/compiler/bitcells/dummy_bitcell_2port.py @@ -0,0 +1,31 @@ +# See LICENSE for licensing information. +# +# Copyright (c) 2016-2019 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 debug +from tech import cell_properties as props +import bitcell_base + + +class dummy_bitcell(bitcell_base.bitcell_base): + """ + A single bit cell (6T, 8T, etc.) This module implements the + single memory cell used in the design. It is a hand-made cell, so + the layout and netlist should be available in the technology + library. + """ + pin_names = [props.bitcell.cell_6t.pin.bl, + props.bitcell.cell_6t.pin.br, + props.bitcell.cell_6t.pin.wl, + props.bitcell.cell_6t.pin.vdd, + props.bitcell.cell_6t.pin.gnd] + type_list = ["OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"] + + def __init__(self, name): + super().__init__(name) + debug.info(2, "Create dummy bitcell") + + diff --git a/compiler/bitcells/replica_bitcell.py b/compiler/bitcells/replica_bitcell_1port.py similarity index 100% rename from compiler/bitcells/replica_bitcell.py rename to compiler/bitcells/replica_bitcell_1port.py diff --git a/compiler/bitcells/replica_bitcell_1w_1r.py b/compiler/bitcells/replica_bitcell_2port.py similarity index 50% rename from compiler/bitcells/replica_bitcell_1w_1r.py rename to compiler/bitcells/replica_bitcell_2port.py index 59fa4676..74e121ee 100644 --- a/compiler/bitcells/replica_bitcell_1w_1r.py +++ b/compiler/bitcells/replica_bitcell_2port.py @@ -12,26 +12,23 @@ from tech import parameter, drc import logical_effort -class replica_bitcell_1w_1r(bitcell_base.bitcell_base): +class replica_bitcell(bitcell_base.bitcell_base): """ - A single bit cell which is forced to store a 0. + A single bit cell (6T, 8T, etc.) This module implements the single memory cell used in the design. It is a hand-made cell, so the layout and netlist should be available in the technology library. """ - pin_names = [props.bitcell.cell_1w1r.pin.bl0, - props.bitcell.cell_1w1r.pin.br0, - props.bitcell.cell_1w1r.pin.bl1, - props.bitcell.cell_1w1r.pin.br1, - props.bitcell.cell_1w1r.pin.wl0, - props.bitcell.cell_1w1r.pin.wl1, - props.bitcell.cell_1w1r.pin.vdd, - props.bitcell.cell_1w1r.pin.gnd] - type_list = ["OUTPUT", "OUTPUT", "INPUT", "INPUT", "INPUT", "INPUT", "POWER", "GROUND"] + pin_names = [props.bitcell.cell_6t.pin.bl, + props.bitcell.cell_6t.pin.br, + props.bitcell.cell_6t.pin.wl, + props.bitcell.cell_6t.pin.vdd, + props.bitcell.cell_6t.pin.gnd] + type_list = ["OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"] def __init__(self, name): super().__init__(name) - debug.info(2, "Create replica bitcell 1w+1r object") + debug.info(2, "Create replica bitcell object") def get_stage_effort(self, load): parasitic_delay = 1 @@ -44,18 +41,17 @@ class replica_bitcell_1w_1r(bitcell_base.bitcell_base): """Return the relative capacitance of the access transistor gates""" # FIXME: This applies to bitline capacitances as well. - # FIXME: sizing is not accurate with the handmade cell. Change once cell widths are fixed. access_tx_cin = parameter["6T_access_size"] / drc["minwidth_tx"] return 2 * access_tx_cin + def analytical_power(self, corner, load): + """Bitcell power in nW. Only characterizes leakage.""" + from tech import spice + leakage = spice["bitcell_leakage"] + dynamic = 0 # FIXME + total_power = self.return_power(dynamic, leakage) + return total_power + def build_graph(self, graph, inst_name, port_nets): - """Adds edges to graph. Multiport bitcell timing graph is too complex - to use the add_graph_edges function.""" - debug.info(1, 'Adding edges for {}'.format(inst_name)) - pin_dict = {pin: port for pin, port in zip(self.pins, port_nets)} - pins = props.bitcell.cell_1w1r.pin - # Edges hardcoded here. Essentially wl->bl/br for the read port. - # Port 1 edges - graph.add_edge(pin_dict[pins.wl1], pin_dict[pins.bl1], self) - graph.add_edge(pin_dict[pins.wl1], pin_dict[pins.br1], self) - # Port 0 is a write port, so its timing is not considered here. + """Adds edges based on inputs/outputs. Overrides base class function.""" + self.add_graph_edges(graph, port_nets) diff --git a/compiler/bitcells/row_cap_bitcell_1rw_1r.py b/compiler/bitcells/row_cap_bitcell_2port.py similarity index 100% rename from compiler/bitcells/row_cap_bitcell_1rw_1r.py rename to compiler/bitcells/row_cap_bitcell_2port.py diff --git a/compiler/globals.py b/compiler/globals.py index c6980d9e..74b578b0 100644 --- a/compiler/globals.py +++ b/compiler/globals.py @@ -214,21 +214,8 @@ def setup_bitcell(): # and the user didn't over-ride the bitcell manually, # figure out the right bitcell to use if OPTS.bitcell == "bitcell": - if (OPTS.num_rw_ports == 1 and OPTS.num_w_ports == 0 and OPTS.num_r_ports == 0): - OPTS.bitcell = "bitcell" - else: - ports = "" - if OPTS.num_rw_ports > 0: - ports += "{}rw_".format(OPTS.num_rw_ports) - if OPTS.num_w_ports > 0: - ports += "{}w_".format(OPTS.num_w_ports) - if OPTS.num_r_ports > 0: - ports += "{}r".format(OPTS.num_r_ports) - - if ports != "": - OPTS.bitcell_suffix = "_" + ports - OPTS.bitcell = "bitcell" + OPTS.bitcell_suffix - + num_ports = OPTS.num_rw_ports + OPTS.num_w_ports + OPTS.num_r_ports + OPTS.bitcell = "bitcell_{}port".format(num_ports) OPTS.dummy_bitcell = "dummy_" + OPTS.bitcell OPTS.replica_bitcell = "replica_" + OPTS.bitcell elif OPTS.bitcell == "pbitcell": @@ -247,7 +234,8 @@ def setup_bitcell(): OPTS.dummy_bitcell = "dummy_pbitcell" OPTS.replica_bitcell = "replica_pbitcell" if not OPTS.is_unit_test: - debug.warning("Using the parameterized bitcell which may have suboptimal density.") + msg = "Didn't find {0}rw {1}w {2}r port bitcell. ".format(OPTS.num_rw_ports, OPTS.num_w_ports, OPTS.num_r_ports) + debug.warning("{} Using the parameterized bitcell which may have suboptimal density.".format(msg)) debug.info(1, "Using bitcell: {}".format(OPTS.bitcell)) diff --git a/compiler/options.py b/compiler/options.py index 89a801b6..cd9726e0 100644 --- a/compiler/options.py +++ b/compiler/options.py @@ -151,7 +151,7 @@ class options(optparse.Values): bitcell_suffix = "" bank_select = "bank_select" bitcell_array = "bitcell_array" - bitcell = "bitcell" + bitcell = "bitcell_1port" buf_dec = "pbuf" column_mux_array = "column_mux_array" control_logic = "control_logic" diff --git a/technology/freepdk45/gds_lib/cell_1rw_1r.gds b/technology/freepdk45/gds_lib/cell_1rw_1r.gds deleted file mode 100644 index 5f3e7213bfd476c5885eac8d75d77077df730c72..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16384 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 delta 786 zcmdm0)6l?J&%nmO1jI6oObkK{JPfQ1!VJ<37C@4TL4tvk!H~g(frp7LB{eOvG^d1t zL4=vrPT|PxrH_NZSt`YdU+`V4z#zj4(<{Wl3)F|KmyeAtIW;FI-mpC0u!w<$gMopK zmkDGe9}@!ugO0#vR@rZ?o2}IycsK7>ZeX7LTj{`LYi7QUov(!^e-Tw=JquLDFj-1W zYI2FN1CmITnBwN$!j?>%OT-SaO#UJbS1BVk*+d$s5-t)26e&RwnFSQtBAo~|`<9I2 zWNVw9lTB=4W<=RqL*-`KDo*}wW4XD+{5Z?zYLf#@lXu%zPBt-jsAp$jU||8dZD2tC Rz*q~nb)fAJg}a2B3;-@1Pk8_U diff --git a/technology/freepdk45/gds_lib/dummy_cell_1rw_1r.gds b/technology/freepdk45/gds_lib/dummy_cell_1rw_1r.gds deleted file mode 100644 index 2ac1a2878c1edd041f7dbfc0da598f385ff98783..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16384 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 diff --git a/technology/freepdk45/gds_lib/dummy_cell_1w_1r.gds b/technology/freepdk45/gds_lib/dummy_cell_2rw.gds similarity index 85% rename from technology/freepdk45/gds_lib/dummy_cell_1w_1r.gds rename to technology/freepdk45/gds_lib/dummy_cell_2rw.gds index fa89439e38db7d4cd8f7d72c5e43a4b43284f11e..f5a4600f1acfe02352e456eeef798d3c3b93b72a 100644 GIT binary patch delta 285 zcmZo@VBAqv&%nmO#1z3G!^p(`gn^rZmw^K)!i~&k;9+7*Nli;E%_(7E5MgGuQ#dkv z>EqycmP#?=7kt;sG03pu)+@xumQtFVTN$66nv)Z6R8-Eu!ok46#>>RO#K6YK#IUik zSZlJ0w!`Kv+73*Uzi274o&kahlclt!ka)AS6*vFZ-N`cfi;=_R5@UzSUyKu>3U3)n zP2OSz(-vin%)5oci!!-2d5fvTWD`@kYEx^dDYHx!CtI8QZsss^VBFkczKIn8Oio`S delta 1065 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 diff --git a/technology/freepdk45/gds_lib/replica_cell_1w_1r.gds b/technology/freepdk45/gds_lib/replica_cell_2rw.gds similarity index 77% rename from technology/freepdk45/gds_lib/replica_cell_1w_1r.gds rename to technology/freepdk45/gds_lib/replica_cell_2rw.gds index 31deb82bf2ebfc1d5563ab59b9a5490571bb60c5..1b2564a4edde04c4198b1d51cfc6371b9bee9972 100644 GIT binary patch delta 379 zcmZo@U~Hlq-pFgZqB3W;||TXFJVJ>Jb;dO0kUzZp49 z{-!4~xyx7wNQ+M9HUXLd;+yD9-ev?d;Es_L5--LWnRf?;7h|G0c`p;+#_mt7lWoNh zOs*9X+I(I(k9l(~n*;CUz1F;&xvV!cO}4eO+-zocoMrM}lgi24On@#o)dthtX4;d@ bOkwuMm;xOR=iM;{nr&Oj#?HXN!omOmkTr!b delta 854 zcmZpwZD?SuXJBJs0%93PCI%q}9tKthVFqai3n0nFAi==NV8kHBz{A9rlA4xSnp48S zAi~UQr*LHU(#OHyER|x!FZixiV31*j=@kN+p@yPYjE$`*wIC-mIWaytH76(Dusq(d zh=GNJfq{*e324V=SJ{88o14`gcsDbvG%!zgRz9$?*;072jhLe3Sq2c`5nyIuVB`a` zY8f~r*~)Va876NNcEeC10aVHXQDMNa`J1pC)8;*54J?ywWKc}vSkAz}1vV+E$bez8 znKaNOR2A&~Ko#vElah*nc9mhOV4MY1F&nG`>>5lJ3_S=HKwG{6Rn*utOs=s-aSO{N z1_oXQkU3>3DL_>=Kvife<^cUZ0i+^552(V-)@}11^W!X=51Sldn#^ohIl0E%p`M+A ZfrSMeRs%xR4~VS@O9$G1UW8MCEC7YeTY&%o diff --git a/technology/freepdk45/sp_lib/cell_1rw_1r.sp b/technology/freepdk45/sp_lib/cell_1rw_1r.sp deleted file mode 100644 index f1c45604..00000000 --- a/technology/freepdk45/sp_lib/cell_1rw_1r.sp +++ /dev/null @@ -1,14 +0,0 @@ - -.SUBCKT cell_1rw_1r bl0 br0 bl1 br1 wl0 wl1 vdd gnd -MM9 RA_to_R_right wl1 br1 gnd NMOS_VTG W=180.0n L=50n m=1 -MM8 RA_to_R_right Q gnd gnd NMOS_VTG W=180.0n L=50n m=1 -MM7 RA_to_R_left Q_bar gnd gnd NMOS_VTG W=180.0n L=50n m=1 -MM6 RA_to_R_left wl1 bl1 gnd NMOS_VTG W=180.0n L=50n m=1 -MM5 Q wl0 bl0 gnd NMOS_VTG W=135.00n L=50n m=1 -MM4 Q_bar wl0 br0 gnd NMOS_VTG W=135.00n L=50n m=1 -MM1 Q Q_bar gnd gnd NMOS_VTG W=205.0n L=50n m=1 -MM0 Q_bar Q gnd gnd NMOS_VTG W=205.0n L=50n m=1 -MM3 Q Q_bar vdd vdd PMOS_VTG W=90n L=50n m=1 -MM2 Q_bar Q vdd vdd PMOS_VTG W=90n L=50n m=1 -.ENDS - diff --git a/technology/freepdk45/sp_lib/cell_1w_1r.sp b/technology/freepdk45/sp_lib/cell_2rw.sp similarity index 91% rename from technology/freepdk45/sp_lib/cell_1w_1r.sp rename to technology/freepdk45/sp_lib/cell_2rw.sp index eb3803b4..a3a6954a 100644 --- a/technology/freepdk45/sp_lib/cell_1w_1r.sp +++ b/technology/freepdk45/sp_lib/cell_2rw.sp @@ -1,5 +1,5 @@ -.SUBCKT cell_1w_1r bl0 br0 bl1 br1 wl0 wl1 vdd gnd +.SUBCKT cell_2rw bl0 br0 bl1 br1 wl0 wl1 vdd gnd MM9 RA_to_R_right wl1 br1 gnd NMOS_VTG W=180.0n L=50n m=1 MM8 RA_to_R_right Q gnd gnd NMOS_VTG W=180.0n L=50n m=1 MM7 RA_to_R_left Q_bar gnd gnd NMOS_VTG W=180.0n L=50n m=1 diff --git a/technology/freepdk45/sp_lib/dummy_cell_1rw_1r.sp b/technology/freepdk45/sp_lib/dummy_cell_1rw_1r.sp deleted file mode 100644 index c3c082ee..00000000 --- a/technology/freepdk45/sp_lib/dummy_cell_1rw_1r.sp +++ /dev/null @@ -1,14 +0,0 @@ - -.SUBCKT dummy_cell_1rw_1r bl0 br0 bl1 br1 wl0 wl1 vdd gnd -MM9 RA_to_R_right wl1 br1_noconn gnd NMOS_VTG W=180.0n L=50n m=1 -MM8 RA_to_R_right Q gnd gnd NMOS_VTG W=180.0n L=50n m=1 -MM7 RA_to_R_left Q_bar gnd gnd NMOS_VTG W=180.0n L=50n m=1 -MM6 RA_to_R_left wl1 bl1_noconn gnd NMOS_VTG W=180.0n L=50n m=1 -MM5 Q wl0 bl0_noconn gnd NMOS_VTG W=135.00n L=50n m=1 -MM4 Q_bar wl0 br0_noconn gnd NMOS_VTG W=135.00n L=50n m=1 -MM1 Q Q_bar gnd gnd NMOS_VTG W=205.0n L=50n m=1 -MM0 Q_bar Q gnd gnd NMOS_VTG W=205.0n L=50n m=1 -MM3 Q Q_bar vdd vdd PMOS_VTG W=90n L=50n m=1 -MM2 Q_bar Q vdd vdd PMOS_VTG W=90n L=50n m=1 -.ENDS - diff --git a/technology/freepdk45/sp_lib/dummy_cell_1w_1r.sp b/technology/freepdk45/sp_lib/dummy_cell_2rw.sp similarity index 90% rename from technology/freepdk45/sp_lib/dummy_cell_1w_1r.sp rename to technology/freepdk45/sp_lib/dummy_cell_2rw.sp index 72d7553f..426ee3ef 100644 --- a/technology/freepdk45/sp_lib/dummy_cell_1w_1r.sp +++ b/technology/freepdk45/sp_lib/dummy_cell_2rw.sp @@ -1,5 +1,5 @@ -.SUBCKT dummy_cell_1w_1r bl0 br0 bl1 br1 wl0 wl1 vdd gnd +.SUBCKT dummy_cell_2rw bl0 br0 bl1 br1 wl0 wl1 vdd gnd MM9 RA_to_R_right wl1 br1_noconn gnd NMOS_VTG W=180.0n L=50n m=1 MM8 RA_to_R_right Q gnd gnd NMOS_VTG W=180.0n L=50n m=1 MM7 RA_to_R_left Q_bar gnd gnd NMOS_VTG W=180.0n L=50n m=1 diff --git a/technology/freepdk45/sp_lib/replica_cell_1rw_1r.sp b/technology/freepdk45/sp_lib/replica_cell_1rw_1r.sp deleted file mode 100644 index d108b7bf..00000000 --- a/technology/freepdk45/sp_lib/replica_cell_1rw_1r.sp +++ /dev/null @@ -1,14 +0,0 @@ - -.SUBCKT replica_cell_1rw_1r bl0 br0 bl1 br1 wl0 wl1 vdd gnd -MM9 RA_to_R_right wl1 br1 gnd NMOS_VTG W=180.0n L=50n m=1 -MM8 RA_to_R_right Q gnd gnd NMOS_VTG W=180.0n L=50n m=1 -MM7 RA_to_R_left vdd gnd gnd NMOS_VTG W=180.0n L=50n m=1 -MM6 RA_to_R_left wl1 bl1 gnd NMOS_VTG W=180.0n L=50n m=1 -MM5 Q wl0 bl0 gnd NMOS_VTG W=135.00n L=50n m=1 -MM4 vdd wl0 br0 gnd NMOS_VTG W=135.00n L=50n m=1 -MM1 Q vdd gnd gnd NMOS_VTG W=205.0n L=50n m=1 -MM0 vdd Q gnd gnd NMOS_VTG W=205.0n L=50n m=1 -MM3 Q vdd vdd vdd PMOS_VTG W=90n L=50n m=1 -MM2 vdd Q vdd vdd PMOS_VTG W=90n L=50n m=1 -.ENDS - diff --git a/technology/freepdk45/sp_lib/replica_cell_1w_1r.sp b/technology/freepdk45/sp_lib/replica_cell_2rw.sp similarity index 89% rename from technology/freepdk45/sp_lib/replica_cell_1w_1r.sp rename to technology/freepdk45/sp_lib/replica_cell_2rw.sp index fd06db8c..97f18252 100644 --- a/technology/freepdk45/sp_lib/replica_cell_1w_1r.sp +++ b/technology/freepdk45/sp_lib/replica_cell_2rw.sp @@ -1,5 +1,5 @@ -.SUBCKT replica_cell_1w_1r bl0 br0 bl1 br1 wl0 wl1 vdd gnd +.SUBCKT replica_cell_2rw bl0 br0 bl1 br1 wl0 wl1 vdd gnd MM9 RA_to_R_right wl1 br1 gnd NMOS_VTG W=180.0n L=50n m=1 MM8 RA_to_R_right Q gnd gnd NMOS_VTG W=180.0n L=50n m=1 MM7 RA_to_R_left vdd gnd gnd NMOS_VTG W=180.0n L=50n m=1 diff --git a/technology/freepdk45/tech/tech.py b/technology/freepdk45/tech/tech.py index 17a3b278..035e8b93 100644 --- a/technology/freepdk45/tech/tech.py +++ b/technology/freepdk45/tech/tech.py @@ -35,6 +35,13 @@ cell_properties.bitcell.mirror.x = True cell_properties.bitcell.mirror.y = False cell_properties.bitcell_power_pin_directions = ("V", "V") +cell_properties.names["bitcell_1port"] = "cell_6t" +cell_properties.names["dummy_bitcell_1port"] = "dummy_cell_6t" +cell_properties.names["replcia_bitcell_1port"] = "replica_cell_6t" +cell_properties.names["bitcell_2port"] = "cell_2rw" +cell_properties.names["dummy_bitcell_2port"] = "dummy_cell_2rw" +cell_properties.names["replica_bitcell_2port"] = "replica_cell_2rw" + ################################################### # Custom cell properties ################################################### diff --git a/technology/scn4m_subm/gds_lib/cell_1rw_1r.gds b/technology/scn4m_subm/gds_lib/cell_1rw_1r.gds deleted file mode 100644 index 71a6dfad712d467bf3ecdd960616c44e1f0af033..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6330 zcmbW5J#bY;7=}Oca|sZV8wDg9&6OXC$WH{`;?c*FSr9dH0vEzKoUGhJP^b zpP7po9G!~uF<6+2hzrAM{nd4PFXH@q&yOA#-BkI^QiT2QPx`5i-=sY*Q@6GMV(nl0 zE8^;-h?84AufK>uH&vecXCD^tnP)xUk%n%n?bLrnzSn;$bxrz$Zc0!6#Gx+nP1->> zrPuxo_4x6u?UwlFr9Vqsru5WLo}2@dHqlM#wf}=UK7HIAMVxrjbL&RwyQ%WjfAppn zlG+&F?RoKw2y|2Bsh{}xiErXVH(UPY=f$`3vL`-tv*o9stX=#j{qVTD^0fa4=Sr;8 zYdvWT-Be#vKkYMi>YDT&-ISjCi9=oDo6J4BDLwU*XX+B$JiJ!&Z%VKI>-G9Mrd)5n zj5w|}YhHV(%}Tl{J@p@a5%K1uh(ot~u4p}?n<`KJ3&Y}D-0g`E-E8@Z&5ycfeczR* z@kcL;@6_#{_|Z+Zk^0Hga+Lg;#6&lxr+)IpSjnGBF3?Tssh>Ctf0X#<@NS83N>BZa zlemoEBrdwyijU{K)+=>QoPikA9lObzZyj)XyA|d*YhRCAuj+ z_0vDjS^OsLpqtWDKmEf;U6XNmTwQtUXP)sfZzl7IZc0!6Z$B-0BWJ{g{LoG5O+WL7 z*W}*qLg`IEV`slG$vZw%dehIiiD}Xfesf~{m+R+`7-x4%zRYvO65Ets#~<_0Jyzf6 zG~a7I-<5`Lsyy}Yk6C{95!!+H(9M<~4?pUf^?g^K#`hUd?syk~JWJ@N^wiHgHa_B* z_|VM>|CKubjMwiCrr#UPiT8(B{OsGzqv?I$oY=p|{8P8eUO)Y^=gKGo-PBo7kAKYn z-p%4;ujI^t_|VOkpLaI$#@TC!_je7lsuFa9w&U#P2d$>%M*YRKRUw%^j z=9TBgZ%R-7K0oX8j&{(^)$#pzEIxUn@4Ty-eD|Q6($n~?8GO9|oA}VpmY;7Fe5^YY zAG+D{(@&lm)|^Q@9#>bM_Mh@I&tm`VF=@x`cI8b!eJ8$2J8l`j2i( zPyKwOX@2+pChee`t@+2pkGdx7hI>=@X?*%g-|HVFhuXS%7XzPvi5=ODy_t(ie17dg|vn!OQbw(tmVQdg^D){HSZz z_g#7F=iH?Z|2s1AqnpxGKl4o9Cf~o%$zNBV`iVo{>i<8GH*~X=ztBalc~(sF$Yn}T z<5Q2dhToidiW*@`ul-l+{U1+V7Z3YBx~cNiPoKHmSBMYYRB`J6xBV9%x~Z|H{`sBK zSJpp$hRhqf*&09di;wqZ)AMe&{LC{K^Ka5`bW?iT|Fb)|%KA0&p_|fc|0nhQ;o)Nb z%?~veE>pMr{`vC%Z=Ihf`2Y7j|NrK_V`D4kmIn{E)kL$N+EcyzckVRm@y<0pD(!9j zM?HNbsJ-uhm}pPyv+tkU;{Us<_swMg#_I9C;d&Es$LjHI(AB%ws>ipF>p3q6HJ+LH E8x&`E!~g&Q diff --git a/technology/scn4m_subm/gds_lib/cell_1w_1r.gds b/technology/scn4m_subm/gds_lib/cell_1w_1r.gds deleted file mode 100644 index 06f79ba5d4a3d86bf948a0040ea1f6fd7fbefb55..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6406 zcmbW5J&aXF7=}OYE_WAPmW%SYvdSudEAq1oLBK*Wu^^$*#DdtcB1Q^g%oZ-?mfBI0 z*lZ^yC8d?2q_ni8q_p&X?wmJg?!|9RJjvbX?mP3&H}lP$nR9LoV-Pd3ylW6!u@Fb} z-zZk&VeE=yL*|z8ME+c7O8OFIR8<@!PBGpFg{}^Xu1N#q#ck zdsw??=Oc#u25~lqi-U+bH=5C3T_;{eoL%er@#CVKDxWEo4^h{I2MUb|8HZmK-> z@4Kmmq&7zPd!GLy0^L-3>L)&a;+y!;&6a=ZdGRg3?1>NEZ29RYYZt#sKRm9kJnjG7 ze2H~pwI^+%o9avIr+vmwU6a0}o6=K1ai~jtletGXrKf)KOkHA|dsj>TP3g6NtzJI| zmFp`nBMxcJnpYo2pqtWD|J;j+w;x69+32~f^@wh&JoPV*if{i;PkiWR%TH`R)HUnx zU3nURh&i4Wau`H4fWiEr-N zDDh3{b^kBa_s@Z~lDjv5@5#Q8ZYsB_|HzLKXEcAT9TOkADLwTcI$F*y{G4HK2c7o1 z^3>0mkKc$`*zU<%KsQyM`uDyn=PZ8CTepKwyIpzeCr{L)pC)mg*RDMEGe_i}xF&On zZc0!6^pA5Ezezjjru5WL|L{@QWE>t>SDyNrXMD_?$vmQ)(o_FCPfOm&8F3*WbW?iM z&%EI^`R;b1^roM&vtO9x9iJ(^>1W);G-(IFIW_)^_5DYTQ`;q9=9y86ZA!1>Px$8_ ztMBug@712~NkcbPp8CgQmY;oub|5}@S`-~@dJPSbXC3I7I>gO37 zA8|~4=;oCFQk{Rs>*og3&kg3(^TTU?_HE|T^uBLS?cWpr!R@lw&%Erpyb^(K>MW?o zKjA-pv-sF6IWr(WbhG8>nT@=0_L}4k-E8IW*zMxu`4KVtn?PwBvTW@}{4@6W^pAw+p4Ge(rhBNxUZg zM>nOXe%{eEzhl2iJLqO>{_*gkuF1OLyQ%MKeELb>>knRZvo-!*s>fV&UYN9nZc0z% zlV5zSUlU)K_c2?3_ASmz=Fj9TKsTkQ@pd%#<^D10Ke{PB^)qHZ z)HUnxU3u!~+@%h`9hvyiP3fthc_weu&tK@|uPaae#366>?+@e+-E8GAbdhWB6_Y%2 znbOnv)MKsTH)o%sMwrrT|K)oB$5YqE!@iGhsyy}6XD;^@;zKu8ocjN5|HX%HYHX>0 zVY~E|^-rH6^M-D=#?SoX<9XTiyqhgQ^UTHkoAevql%Dqg)HbfNeocJnru5qXX+3{< zxR`(QBaMa2)Yq|pq5S@>^Ybvje=qR+H_sjG*J6HYxb;9yH0!B7)%)q*y+%Erxn@>M zd+YyEPwxn7@B1I7+SB^%`=_?}eOLAFPWNx39`75jHx+lH9`6QSz0FoV-hEuJl^6EC e(>G(dH2ktLT2`}mn7yiX=k7O~UClXhHvR$Vczuxo diff --git a/technology/scn4m_subm/gds_lib/cell_2rw.gds b/technology/scn4m_subm/gds_lib/cell_2rw.gds new file mode 100644 index 0000000000000000000000000000000000000000..a45c34e937349dd6945d67a6fedc0debce9c7eab GIT binary patch literal 6326 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 T@S*wLd;U!8VsCsC;#m9(IiO_) literal 0 HcmV?d00001 diff --git a/technology/scn4m_subm/gds_lib/replica_cell_1rw_1r.gds b/technology/scn4m_subm/gds_lib/replica_cell_1rw_1r.gds deleted file mode 100644 index 2697651dcbb09baa6b17a15e84834f363d14a3e7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6282 zcmbW5J#dvp6owD^BR~j=LQFJD6p)DgBruU+p*Ul~42^{aV*?6|IFoUh6hN6$J4$A3 z(n(2~(#oMsX=zEB($e?Iey`u&i)Wqjo4I+ud3WDEyJz?A?oCX@NQ}nffsuF=M`Ah- z$N8A~=l!Be=SL-?aQ4@+rNDC zbu5lI+L`$GcE%c2|ApE=`&Y!3rxEk(J+JLXpqnaB{o_xH_w-KB_oShlYCH8Gk?+l)N?nt_pqtWD zKXIr_e3N$2P3g7&d_8_V%iATsdGXKEmMJ~;lPBlEq)l{FdhP$Xj!z%gmLle!_gueT z`fjQ`^&h>Vg`_rS9`wBMRRp@J^3+d!{KPl$p_?uL!pq`YeAN>ly4mv6Pu4DelYV$y zU3uF7gOerJspX!ug>I@Zsh{>4J9SO^j&4d%{luXz@lEC)-ISjC$uo6{Z601O`8TE4 z{*`+D99OQ_UPYYHnl-OJ(WWKcl%Dzz?nb=*G~&>mo{L(K=%&h3|MX1p9oz1S58Z6} ziOq+)X8qokr}39|i|>OwJ@KQPY9sZNr-dl_Gl_|AN>BadiLsJDlU$&i(o;WirvE7M z&6x)!z9~KRGfv_%ev`Q9W-C6Pb6T&|HTnLbo6^(x^dBGV&%}prw*2H6A9H2mLpNJ~ z;*e|Nn}_a{_@?x_{}=1;&+JOc-5bC4WZy?OmD|++*29Rinm^W#i4WbBp88MBm$M5$ zXPDbTr@gK`^)u#^*CVF3da@SKO_itq!+YhN#m{-`cF<|JD^LC8iF)+YB(C$?m8X8@ zh};v`WG>N7>8YRoan9m5X$Reup8Dw@KI)o`!{h48Q$O>Jk9jkhM|4wq>VNk|$s0K% zF64u5N^km^H@qhAZWl^#`WZX>g-PD=nbMnn#!XCf+R`=sW3x##=R&`p)6{{1n_&ptvs5FfhP^5fw{U9*1g%G3Bh=B#DE zGmmXI?+*jx{~zc7fS+-aYsPOf7wD$+H2;iqf3D;)@u8bT{?&T@g`Tw~t(}#g{O;i~ zRbIz`&41~6@tc=l7QZPy_51v+&pX;dH%|`kzXS2f6Mg5dX7alS-ISijXU*Va-I(~$ z&6b}yta;XqNjvUWSDwbF{Pa%jpB*OcxZSS2>8J0+H)+T1Lg}fW?=0sWUX%W#o6=K1 zzp*qw`+k#l(9PET;o(DFlX>Ue)O#AAe$w~)gBRUwjsJk^@jH|K-lQ#bQ+gVo{NiK% znfSWA@3ZA+-{Gud{!I3AbW?g7pWm#+qW>m+K{utRe%3kOx#vCUKf0;%)X$jtP}i*A zyYke}xk(-V_haHmH>Ib3=9#<=-=EOQUss;`i9_D%{~wSybhDMe&_k~Iu9)PL$CRGN zrygq!zd7~-HNuo$`>)jdH=epK9`v*l-=d6<8bexsYx)Bc~?!d2FWi8J+-HLkM7-T)Z@-Hx>VX* z{f~OOze;jI0>$C5l+T#DSs`uS+{|4&ud%^XF;ttf~Zr|10Y}Mnpi|aWr2Q{9t F_!|d*cV_?q diff --git a/technology/scn4m_subm/gds_lib/replica_cell_1w_1r.gds b/technology/scn4m_subm/gds_lib/replica_cell_1w_1r.gds deleted file mode 100644 index ce6e413b71352cb8fd64512faa68208b349805a4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8192 zcmeI0J8WD<6o!x2_ImAXoOK?41OuBFF~*6#iA)>{FcL*18cIatgxC`T%ET`TeUfB*6Q0kUp@G~`<>bO(eV#I{^`!AzyJE@-A|5I_ka0f(-y}g z@4U^{>$^LTyWc!~u=Q}K+uiCs+3M`tSi`J-x@OB(pRSqNN^8{r`gP@1;s?*nmeCUkk`^W$8pg*}&JNWUz?8^P`<^FR&nyt6Z;Krue>_JKC&d`7Qo)5&m@Wy9mtw$xL zJ3~KlsR!{BUzA?uUwEGU5Z~f)N&H257@vNVD~$s`J}BK8`X?GG2E=n^sU)$B^3YFQ z#tf-X8=`b)=%;sfT@JC7M z&d@*c!tCPD-UsKR&%??4C8aw<|8y()A^tP_CGi*Kp`SXs@#nX6XXtOgNPdX-^8J$d zi}KJ<-WDw7kNV_Klx#!mi3>CVtk{OOk|e(O<+FG_cYe#S=}NL2Gr{jR#71hW@EnDQA%S@CP}d{o{E<>dObEJ3~MHrk=(@8}u7Wuk!QUsRwyp zJU>x-mH*Ad6c3WO{H7m8dDwr-c}{8vk8bJCNV-b#5Cr91QZeg4KX?{mWpUhw_}^Z|b-&%gP#-sW%m?&q7Aa{!d?%;Uf2Up?sA?bh?; z6Qw&tf4+ZFpLHxUhl=vh&o{2V(+AHV(w(8798nJro*$%F`H9bdt$v)@PwheJ&M-bc z_6xPcn#BjDJ1hO18PpDO@j>a%(9d@ddrt2=$n$`QaYO0O(9e69=LD%QAC&G4{nXLT zbEgeadX=Ak6AMybaiMf)7=OfloVOtLS%;!@XXq#I)Pwl=b{3^q`6qq6>^+dZkmn{! zcZTsfqY)btoBoT^ouQw3uRVx<&mN@yL+Q@Y&lq*%&u{5f<7dC39>mKxpD4Y`&vPeF zQ12~KdR6|2OP(Nk zNAsg|H0$$Xpi&tw~FIw z!6NSsbz#u`h|zonid{@q0jD z{unnohUA{{i_)E8e8x>Zh>!7$(g*yv^ZA#px!!jWYmx6E$W@f*@%#MQn(z783-Cj( zqCE8TjP%_x_RbS&J3~MFC>Nyv?5Co1XXwAS zN3C=wz{mSQlyC?N<#*t^O tKOZ0E^N}&@@_o8DH$>^qUOpzAW0^SocbI`;28J0JW?-0sVFvOH{0)*ea`XTI diff --git a/technology/scn4m_subm/gds_lib/replica_cell_2rw.gds b/technology/scn4m_subm/gds_lib/replica_cell_2rw.gds new file mode 100644 index 0000000000000000000000000000000000000000..c520422aaf092b560dba64b7affad4e005496558 GIT binary patch literal 6278 zcmbW5F>D+~6oy~!?DILXoijMb1_OpTB$y;VJ2G)7AV?IE(oj$!ngo)FAXzAKfm6DK zE@dPdcer%vk_x4CNl8KB(j_JDyV;+e-RKR7mDZp2@B8P?yqVqEJ?mMg^QA4F=}i1- z=WN>g*0o{&zb$lnJCB}hfA`?)dk-FMZ{J(r+4a+Gt~>tmr$61i``a(4w>~>s+yD8i zFKlT%ZfCC7Y-eL<*T(v0z3GmvT5qOfW>*JY|Le!a)5MRSo2?GbMCs14S^LNTe%qhi zsU7_IV0PsGYq@{+FS8rZ%;2qKvxTji(w(7y{Au#QxBOf=s!3bb_0WIL<6r&J3=&Tp zqI75Ir+vJTc=C(Vow@&NK7L}Z?58%a|B>>G(w(87x{({w7JV0`J9GaBd4Br3xt#jE zb=z$Iz)Y0x4E@u0d?9%o@Y?5QgU2d{DYG^iT9t4v6RCm73(Pu7`f|GG<6TZHUsHp`Z5gLe>EJMd{AaPu=mtv+gCQ zDBYR+hxz)M^O|p-_yfv$^QqYdU&EqwXXu|eHhcY<_rba3>u~aZP3g|iKQl;vi2wY4 zP5jmM&`*p`{P`)}8TyxxlON)J_kKc$u$W2b(ibZ6)% z|IF_x|KM@TFG_cYe#S>0NM6P-N-yOnX4Tg%2J9@U!v>KKN8e`b$5c z^iqE2ikfTA$jcl;>CP}e{bRp{#LEYzJ3~MHCQjp^4f+kGm;B5-agh09{zT~||C@&? zAEa*iNk6LVVgI?#JgFT#I;A^{e#VNQy7L?nr8|p$#)+SJ)ecH;jejk_|HyS|FXg;E zNOcsYJM;VvfB(7nxo-yF@sqt%lml?fu*{)J&A_ z4ExXfGI0u zYO*I(*Yoi={O{dKeu$rEr-;A09{PDlqfU^zvFD1?OZ9uh`%N6g$NQrwz2xWl&E5;o z@BgRwhsOB-$Nt~&Gj3`OsXgNtr8~p=F>c}@KE^LfZ~52r^=E!;`n+-Q-NQS-DBYRo zf62dgFtXdmi{uxjJ41iIe-h6=BJvEYu7`f=rtg&Y_m}k6_e-PytP$d1`};|H$xnXP zy!yc!!Uv^0i~V0YN`B%OwvrD@cNYE3Ir)hvuPEIa`ngBh^C11kBT9FMe!jJsCrCVg zQMxnq6Qh%P$16%N`RO+~A@Te#N_U3&&$y58O-MZZfhgS>`l&l{5Fg(TqV$q~(#Ol* z2ic36KT*0f%+EI}xgojfzbM@q`dRnd1L^ntLFzx0?hO5mQ78WVlwKM?`z3J@FTeSS z(o25kojO6iH;K|q^&>BJg4B)Q4@Bvu`k5cpo`ZUE?}*Z!Vg2y2_Bh54lV6nX9Qmix z@0b4kn&Lb*B zDbn}qdgy0e5~ua4_k1Yb8Twh59FTsqK1J!y(0^%NB5s7-8mZHgmcXP E26`)abpQYW literal 0 HcmV?d00001 diff --git a/technology/scn4m_subm/sp_lib/cell_1rw_1r.sp b/technology/scn4m_subm/sp_lib/cell_2rw.sp similarity index 88% rename from technology/scn4m_subm/sp_lib/cell_1rw_1r.sp rename to technology/scn4m_subm/sp_lib/cell_2rw.sp index 37f25f75..9984213d 100644 --- a/technology/scn4m_subm/sp_lib/cell_1rw_1r.sp +++ b/technology/scn4m_subm/sp_lib/cell_2rw.sp @@ -1,5 +1,5 @@ -.SUBCKT cell_1rw_1r bl0 br0 bl1 br1 wl0 wl1 vdd gnd +.SUBCKT cell_2rw bl0 br0 bl1 br1 wl0 wl1 vdd gnd MM9 RA_to_R_right wl1 br1 gnd n w=1.2u l=0.4u MM8 RA_to_R_right Q gnd gnd n w=1.2u l=0.4u MM7 RA_to_R_left Q_bar gnd gnd n w=1.2u l=0.4u diff --git a/technology/scn4m_subm/sp_lib/dummy_cell_1rw_1r.sp b/technology/scn4m_subm/sp_lib/dummy_cell_2rw.sp similarity index 88% rename from technology/scn4m_subm/sp_lib/dummy_cell_1rw_1r.sp rename to technology/scn4m_subm/sp_lib/dummy_cell_2rw.sp index 9766a840..e07dac48 100644 --- a/technology/scn4m_subm/sp_lib/dummy_cell_1rw_1r.sp +++ b/technology/scn4m_subm/sp_lib/dummy_cell_2rw.sp @@ -1,5 +1,5 @@ -.SUBCKT dummy_cell_1rw_1r bl0 br0 bl1 br1 wl0 wl1 vdd gnd +.SUBCKT dummy_cell_2rw bl0 br0 bl1 br1 wl0 wl1 vdd gnd MM9 RA_to_R_right wl1 br1_noconn gnd n w=1.2u l=0.4u MM8 RA_to_R_right Q gnd gnd n w=1.2u l=0.4u MM7 RA_to_R_left Q_bar gnd gnd n w=1.2u l=0.4u diff --git a/technology/scn4m_subm/sp_lib/replica_cell_1rw_1r.sp b/technology/scn4m_subm/sp_lib/replica_cell_2rw.sp similarity index 86% rename from technology/scn4m_subm/sp_lib/replica_cell_1rw_1r.sp rename to technology/scn4m_subm/sp_lib/replica_cell_2rw.sp index 94bdb75e..9a00da3e 100644 --- a/technology/scn4m_subm/sp_lib/replica_cell_1rw_1r.sp +++ b/technology/scn4m_subm/sp_lib/replica_cell_2rw.sp @@ -1,5 +1,5 @@ -.SUBCKT replica_cell_1rw_1r bl0 br0 bl1 br1 wl0 wl1 vdd gnd +.SUBCKT replica_cell_2rw bl0 br0 bl1 br1 wl0 wl1 vdd gnd MM9 RA_to_R_right wl1 br1 gnd n w=1.2u l=0.4u MM8 RA_to_R_right Q gnd gnd n w=1.2u l=0.4u MM7 RA_to_R_left vdd gnd gnd n w=1.2u l=0.4u diff --git a/technology/scn4m_subm/tech/tech.py b/technology/scn4m_subm/tech/tech.py index b1ba6795..724e3d50 100644 --- a/technology/scn4m_subm/tech/tech.py +++ b/technology/scn4m_subm/tech/tech.py @@ -33,6 +33,13 @@ cell_properties = cell_properties() cell_properties.bitcell.mirror.x = True cell_properties.bitcell.mirror.y = False +cell_properties.names["bitcell_1port"] = "cell_6t" +cell_properties.names["dummy_bitcell_1port"] = "dummy_cell_6t" +cell_properties.names["replcia_bitcell_1port"] = "replica_cell_6t" +cell_properties.names["bitcell_2port"] = "cell_2rw" +cell_properties.names["dummy_bitcell_2port"] = "dummy_cell_2rw" +cell_properties.names["replica_bitcell_2port"] = "replica_cell_2rw" + ################################################### # Custom cell properties ################################################### From 3567a3e9139e2180102e9446fbe7e23b0cab7407 Mon Sep 17 00:00:00 2001 From: mrg Date: Fri, 13 Nov 2020 08:10:16 -0800 Subject: [PATCH 14/31] Remove 1rw_1r --- compiler/bitcells/bitcell_1rw_1r.py | 126 -------------------- compiler/bitcells/dummy_bitcell_1rw_1r.py | 35 ------ compiler/bitcells/replica_bitcell_1rw_1r.py | 62 ---------- 3 files changed, 223 deletions(-) delete mode 100644 compiler/bitcells/bitcell_1rw_1r.py delete mode 100644 compiler/bitcells/dummy_bitcell_1rw_1r.py delete mode 100644 compiler/bitcells/replica_bitcell_1rw_1r.py diff --git a/compiler/bitcells/bitcell_1rw_1r.py b/compiler/bitcells/bitcell_1rw_1r.py deleted file mode 100644 index 9c1d3425..00000000 --- a/compiler/bitcells/bitcell_1rw_1r.py +++ /dev/null @@ -1,126 +0,0 @@ -# See LICENSE for licensing information. -# -# Copyright (c) 2016-2019 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 debug -from tech import cell_properties as props -import bitcell_base - - -class bitcell_1rw_1r(bitcell_base.bitcell_base): - """ - A single bit cell (6T, 8T, etc.) This module implements the - single memory cell used in the design. It is a hand-made cell, so - the layout and netlist should be available in the technology - library. - """ - - pin_names = [props.bitcell.cell_1rw1r.pin.bl0, - props.bitcell.cell_1rw1r.pin.br0, - props.bitcell.cell_1rw1r.pin.bl1, - props.bitcell.cell_1rw1r.pin.br1, - props.bitcell.cell_1rw1r.pin.wl0, - props.bitcell.cell_1rw1r.pin.wl1, - props.bitcell.cell_1rw1r.pin.vdd, - props.bitcell.cell_1rw1r.pin.gnd] - type_list = ["OUTPUT", "OUTPUT", "OUTPUT", "OUTPUT", - "INPUT", "INPUT", "POWER", "GROUND"] - storage_nets = ['Q', 'Q_bar'] - - def __init__(self, name): - super().__init__(name) - debug.info(2, "Create bitcell with 1RW and 1R Port") - - self.nets_match = self.do_nets_exist(self.storage_nets) - - pin_names = self.pin_names - self.bl_names = [pin_names[0], pin_names[2]] - self.br_names = [pin_names[1], pin_names[3]] - self.wl_names = [pin_names[4], pin_names[5]] - - def get_bitcell_pins(self, col, row): - """ - Creates a list of connections in the bitcell, - indexed by column and row, for instance use in bitcell_array - """ - pin_name = props.bitcell.cell_1rw1r.pin - bitcell_pins = ["{0}_{1}".format(pin_name.bl0, col), - "{0}_{1}".format(pin_name.br0, col), - "{0}_{1}".format(pin_name.bl1, col), - "{0}_{1}".format(pin_name.br1, col), - "{0}_{1}".format(pin_name.wl0, row), - "{0}_{1}".format(pin_name.wl1, row), - "vdd", - "gnd"] - return bitcell_pins - - def get_all_wl_names(self): - """ Creates a list of all wordline pin names """ - return [props.bitcell.cell_1rw1r.pin.wl0, - props.bitcell.cell_1rw1r.pin.wl1] - - def get_all_bitline_names(self): - """ Creates a list of all bitline pin names (both bl and br) """ - return [props.bitcell.cell_1rw1r.pin.bl0, - props.bitcell.cell_1rw1r.pin.br0, - props.bitcell.cell_1rw1r.pin.bl1, - props.bitcell.cell_1rw1r.pin.br1] - - def get_all_bl_names(self): - """ Creates a list of all bl pins names """ - return [props.bitcell.cell_1rw1r.pin.bl0, - props.bitcell.cell_1rw1r.pin.bl1] - - def get_all_br_names(self): - """ Creates a list of all br pins names """ - return [props.bitcell.cell_1rw1r.pin.br0, - props.bitcell.cell_1rw1r.pin.br1] - - def get_read_bl_names(self): - """ Creates a list of bl pin names associated with read ports """ - return [props.bitcell.cell_1rw1r.pin.bl0, - props.bitcell.cell_1rw1r.pin.bl1] - - def get_read_br_names(self): - """ Creates a list of br pin names associated with read ports """ - return [props.bitcell.cell_1rw1r.pin.br0, - props.bitcell.cell_1rw1r.pin.br1] - - def get_write_bl_names(self): - """ Creates a list of bl pin names associated with write ports """ - return [props.bitcell.cell_1rw1r.pin.bl0] - - def get_write_br_names(self): - """ Creates a list of br pin names asscociated with write ports""" - return [props.bitcell.cell_1rw1r.pin.br1] - - def get_bl_name(self, port=0): - """Get bl name by port""" - debug.check(port < 2, "Two ports for bitcell_1rw_1r only.") - return self.bl_names[port] - - def get_br_name(self, port=0): - """Get bl name by port""" - debug.check(port < 2, "Two ports for bitcell_1rw_1r only.") - return self.br_names[port] - - def get_wl_name(self, port=0): - """Get wl name by port""" - debug.check(port < 2, "Two ports for bitcell_1rw_1r only.") - return self.wl_names[port] - - def build_graph(self, graph, inst_name, port_nets): - """Adds edges to graph. Multiport bitcell timing graph is too complex - to use the add_graph_edges function.""" - pin_dict = {pin: port for pin, port in zip(self.pins, port_nets)} - # Edges hardcoded here. Essentially wl->bl/br for both ports. - # Port 0 edges - pins = props.bitcell.cell_1rw1r.pin - graph.add_edge(pin_dict[pins.wl0], pin_dict[pins.bl0], self) - graph.add_edge(pin_dict[pins.wl0], pin_dict[pins.br0], self) - # Port 1 edges - graph.add_edge(pin_dict[pins.wl1], pin_dict[pins.bl1], self) - graph.add_edge(pin_dict[pins.wl1], pin_dict[pins.br1], self) diff --git a/compiler/bitcells/dummy_bitcell_1rw_1r.py b/compiler/bitcells/dummy_bitcell_1rw_1r.py deleted file mode 100644 index 8d8a68d2..00000000 --- a/compiler/bitcells/dummy_bitcell_1rw_1r.py +++ /dev/null @@ -1,35 +0,0 @@ -# See LICENSE for licensing information. -# -# Copyright (c) 2016-2019 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 debug -from tech import cell_properties as props -import bitcell_base - - -class dummy_bitcell_1rw_1r(bitcell_base.bitcell_base): - """ - A single bit cell which is forced to store a 0. - This module implements the single memory cell used in the design. It - is a hand-made cell, so the layout and netlist should be available in - the technology library. """ - - pin_names = [props.bitcell.cell_1rw1r.pin.bl0, - props.bitcell.cell_1rw1r.pin.br0, - props.bitcell.cell_1rw1r.pin.bl1, - props.bitcell.cell_1rw1r.pin.br1, - props.bitcell.cell_1rw1r.pin.wl0, - props.bitcell.cell_1rw1r.pin.wl1, - props.bitcell.cell_1rw1r.pin.vdd, - props.bitcell.cell_1rw1r.pin.gnd] - type_list = ["OUTPUT", "OUTPUT", "OUTPUT", "OUTPUT", - "INPUT", "INPUT", "POWER", "GROUND"] - - def __init__(self, name): - super().__init__(name) - debug.info(2, "Create dummy bitcell 1rw+1r object") - - diff --git a/compiler/bitcells/replica_bitcell_1rw_1r.py b/compiler/bitcells/replica_bitcell_1rw_1r.py deleted file mode 100644 index 9dc9aac9..00000000 --- a/compiler/bitcells/replica_bitcell_1rw_1r.py +++ /dev/null @@ -1,62 +0,0 @@ -# See LICENSE for licensing information. -# -# Copyright (c) 2016-2019 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 debug -import bitcell_base -from tech import cell_properties as props -from tech import parameter, drc -import logical_effort - - -class replica_bitcell_1rw_1r(bitcell_base.bitcell_base): - """ - A single bit cell which is forced to store a 0. - This module implements the single memory cell used in the design. It - is a hand-made cell, so the layout and netlist should be available in - the technology library. """ - - pin_names = [props.bitcell.cell_1rw1r.pin.bl0, - props.bitcell.cell_1rw1r.pin.br0, - props.bitcell.cell_1rw1r.pin.bl1, - props.bitcell.cell_1rw1r.pin.br1, - props.bitcell.cell_1rw1r.pin.wl0, - props.bitcell.cell_1rw1r.pin.wl1, - props.bitcell.cell_1rw1r.pin.vdd, - props.bitcell.cell_1rw1r.pin.gnd] - type_list = ["OUTPUT", "OUTPUT", "OUTPUT", "OUTPUT", "INPUT", "INPUT", "POWER", "GROUND"] - - def __init__(self, name): - super().__init__(name) - debug.info(2, "Create replica bitcell 1rw+1r object") - - def get_stage_effort(self, load): - parasitic_delay = 1 - size = 0.5 # This accounts for bitline being drained thought the access TX and internal node - cin = 3 # Assumes always a minimum sizes inverter. Could be specified in the tech.py file. - read_port_load = 0.5 # min size NMOS gate load - return logical_effort.logical_effort('bitline', size, cin, load + read_port_load, parasitic_delay, False) - - def input_load(self): - """Return the relative capacitance of the access transistor gates""" - - # FIXME: This applies to bitline capacitances as well. - # FIXME: sizing is not accurate with the handmade cell. Change once cell widths are fixed. - access_tx_cin = parameter["6T_access_size"] / drc["minwidth_tx"] - return 2 * access_tx_cin - - def build_graph(self, graph, inst_name, port_nets): - """Adds edges to graph. Multiport bitcell timing graph is too complex - to use the add_graph_edges function.""" - pin_dict = {pin: port for pin, port in zip(self.pins, port_nets)} - pins = props.bitcell.cell_1rw1r.pin - # Edges hardcoded here. Essentially wl->bl/br for both ports. - # Port 0 edges - graph.add_edge(pin_dict[pins.wl0], pin_dict[pins.bl0], self) - graph.add_edge(pin_dict[pins.wl0], pin_dict[pins.br0], self) - # Port 1 edges - graph.add_edge(pin_dict[pins.wl1], pin_dict[pins.bl1], self) - graph.add_edge(pin_dict[pins.wl1], pin_dict[pins.br1], self) From c472a94f1e3b20f60a383772b47fc35b79f39826 Mon Sep 17 00:00:00 2001 From: mrg Date: Fri, 13 Nov 2020 10:07:40 -0800 Subject: [PATCH 15/31] Rework bitcells. Name them 1port and 2port consistently. Allow cell overrides to cell_1rw and cell_2rw or other. Will use 2rw for 1rw/1r, 2rw, 1w/1r, etc. --- compiler/base/custom_cell_properties.py | 67 +++----- compiler/base/hierarchy_spice.py | 2 +- compiler/bitcells/bitcell_1port.py | 24 +-- compiler/bitcells/bitcell_2port.py | 54 +++---- compiler/bitcells/dummy_bitcell_1port.py | 12 +- compiler/bitcells/dummy_bitcell_2port.py | 30 ++-- compiler/bitcells/replica_bitcell_1port.py | 12 +- compiler/bitcells/replica_bitcell_2port.py | 43 ++--- compiler/globals.py | 10 +- compiler/modules/bitcell_array.py | 2 +- compiler/options.py | 3 +- .../gds_lib/{cell_6t.gds => cell_1rw.gds} | Bin 20480 -> 19116 bytes .../{dummy_cell_6t.gds => dummy_cell_1rw.gds} | Bin 20480 -> 18994 bytes ...plica_cell_6t.gds => replica_cell_1rw.gds} | Bin 20480 -> 19124 bytes .../sp_lib/{cell_6t.sp => cell_1rw.sp} | 4 +- .../{dummy_cell_6t.sp => dummy_cell_1rw.sp} | 4 +- ...replica_cell_6t.sp => replica_cell_1rw.sp} | 4 +- technology/freepdk45/tech/tech.py | 6 - technology/scn4m_subm/gds_lib/cell_1rw.gds | Bin 0 -> 5868 bytes technology/scn4m_subm/gds_lib/cell_6t.gds | Bin 5868 -> 0 bytes .../scn4m_subm/gds_lib/dummy_cell_1rw.gds | Bin 0 -> 5544 bytes .../scn4m_subm/gds_lib/dummy_cell_6t.gds | Bin 5544 -> 0 bytes .../scn4m_subm/gds_lib/replica_cell_1rw.gds | Bin 0 -> 5948 bytes .../scn4m_subm/gds_lib/replica_cell_6t.gds | Bin 5948 -> 0 bytes .../mag_lib/{cell_6t.mag => cell_1rw.mag} | 0 technology/scn4m_subm/mag_lib/cell_1w_1r.mag | 146 ----------------- .../mag_lib/{cell_1rw_1r.mag => cell_2rw.mag} | 0 technology/scn4m_subm/mag_lib/cell_6t.ext | 41 ----- technology/scn4m_subm/mag_lib/cell_6t.spice | 15 -- .../{dummy_cell_6t.mag => dummy_cell_1rw.mag} | 0 .../scn4m_subm/mag_lib/dummy_cell_1w_1r.mag | 138 ---------------- ...mmy_cell_1rw_1r.mag => dummy_cell_2rw.mag} | 0 ...plica_cell_6t.mag => replica_cell_1rw.mag} | 0 .../scn4m_subm/mag_lib/replica_cell_1w_1r.mag | 147 ------------------ ...a_cell_1rw_1r.mag => replica_cell_2rw.mag} | 0 .../scn4m_subm/mag_lib/replica_cell_6t.ext | 35 ----- .../scn4m_subm/mag_lib/replica_cell_6t.spice | 16 -- .../sp_lib/{cell_6t.sp => cell_1rw.sp} | 6 +- technology/scn4m_subm/sp_lib/cell_1w_1r.sp | 14 -- .../{dummy_cell_6t.sp => dummy_cell_1rw.sp} | 4 +- .../scn4m_subm/sp_lib/dummy_cell_1w_1r.sp | 14 -- ...replica_cell_6t.sp => replica_cell_1rw.sp} | 6 +- .../scn4m_subm/sp_lib/replica_cell_1w_1r.sp | 14 -- technology/scn4m_subm/sue_lib/cell_6t.sue | 46 ------ technology/scn4m_subm/sue_lib/ms_flop.sue | 84 ---------- .../scn4m_subm/sue_lib/replica_cell_6t.sue | 49 ------ technology/scn4m_subm/sue_lib/sense_amp.sue | 52 ------- technology/scn4m_subm/sue_lib/tri_gate.sue | 37 ----- .../scn4m_subm/sue_lib/write_driver.sue | 44 ------ technology/scn4m_subm/tech/tech.py | 6 - 50 files changed, 139 insertions(+), 1052 deletions(-) rename technology/freepdk45/gds_lib/{cell_6t.gds => cell_1rw.gds} (77%) rename technology/freepdk45/gds_lib/{dummy_cell_6t.gds => dummy_cell_1rw.gds} (75%) rename technology/freepdk45/gds_lib/{replica_cell_6t.gds => replica_cell_1rw.gds} (82%) rename technology/freepdk45/sp_lib/{cell_6t.sp => cell_1rw.sp} (86%) rename technology/freepdk45/sp_lib/{dummy_cell_6t.sp => dummy_cell_1rw.sp} (85%) rename technology/freepdk45/sp_lib/{replica_cell_6t.sp => replica_cell_1rw.sp} (84%) create mode 100644 technology/scn4m_subm/gds_lib/cell_1rw.gds delete mode 100644 technology/scn4m_subm/gds_lib/cell_6t.gds create mode 100644 technology/scn4m_subm/gds_lib/dummy_cell_1rw.gds delete mode 100644 technology/scn4m_subm/gds_lib/dummy_cell_6t.gds create mode 100644 technology/scn4m_subm/gds_lib/replica_cell_1rw.gds delete mode 100644 technology/scn4m_subm/gds_lib/replica_cell_6t.gds rename technology/scn4m_subm/mag_lib/{cell_6t.mag => cell_1rw.mag} (100%) delete mode 100644 technology/scn4m_subm/mag_lib/cell_1w_1r.mag rename technology/scn4m_subm/mag_lib/{cell_1rw_1r.mag => cell_2rw.mag} (100%) delete mode 100644 technology/scn4m_subm/mag_lib/cell_6t.ext delete mode 100644 technology/scn4m_subm/mag_lib/cell_6t.spice rename technology/scn4m_subm/mag_lib/{dummy_cell_6t.mag => dummy_cell_1rw.mag} (100%) delete mode 100644 technology/scn4m_subm/mag_lib/dummy_cell_1w_1r.mag rename technology/scn4m_subm/mag_lib/{dummy_cell_1rw_1r.mag => dummy_cell_2rw.mag} (100%) rename technology/scn4m_subm/mag_lib/{replica_cell_6t.mag => replica_cell_1rw.mag} (100%) delete mode 100644 technology/scn4m_subm/mag_lib/replica_cell_1w_1r.mag rename technology/scn4m_subm/mag_lib/{replica_cell_1rw_1r.mag => replica_cell_2rw.mag} (100%) delete mode 100644 technology/scn4m_subm/mag_lib/replica_cell_6t.ext delete mode 100644 technology/scn4m_subm/mag_lib/replica_cell_6t.spice rename technology/scn4m_subm/sp_lib/{cell_6t.sp => cell_1rw.sp} (63%) delete mode 100644 technology/scn4m_subm/sp_lib/cell_1w_1r.sp rename technology/scn4m_subm/sp_lib/{dummy_cell_6t.sp => dummy_cell_1rw.sp} (72%) delete mode 100644 technology/scn4m_subm/sp_lib/dummy_cell_1w_1r.sp rename technology/scn4m_subm/sp_lib/{replica_cell_6t.sp => replica_cell_1rw.sp} (61%) delete mode 100644 technology/scn4m_subm/sp_lib/replica_cell_1w_1r.sp delete mode 100644 technology/scn4m_subm/sue_lib/cell_6t.sue delete mode 100644 technology/scn4m_subm/sue_lib/ms_flop.sue delete mode 100644 technology/scn4m_subm/sue_lib/replica_cell_6t.sue delete mode 100644 technology/scn4m_subm/sue_lib/sense_amp.sue delete mode 100644 technology/scn4m_subm/sue_lib/tri_gate.sue delete mode 100644 technology/scn4m_subm/sue_lib/write_driver.sue diff --git a/compiler/base/custom_cell_properties.py b/compiler/base/custom_cell_properties.py index efff1786..eafad33a 100644 --- a/compiler/base/custom_cell_properties.py +++ b/compiler/base/custom_cell_properties.py @@ -11,7 +11,7 @@ from globals import OPTS class _pins: def __init__(self, pin_dict): # make the pins elements of the class to allow "." access. - # For example: props.bitcell.cell_6t.pin.bl = "foobar" + # For example: props.bitcell.cell_1port.pin.bl = "foobar" for k, v in pin_dict.items(): self.__dict__[k] = v @@ -48,49 +48,36 @@ class _pgate: class _bitcell: - def __init__(self, mirror, cell_6t, cell_1rw1r, cell_1w1r): + def __init__(self, mirror, cell_1port, cell_2port): self.mirror = mirror - self._6t = cell_6t - self._1rw1r = cell_1rw1r - self._1w1r = cell_1w1r + self._1rw = cell_1port + self._2rw = cell_2port def _default(): axis = _mirror_axis(True, False) - cell_6t = _cell({'bl': 'bl', - 'br': 'br', - 'wl': 'wl'}) + cell_1port = _cell({'bl': 'bl', + 'br': 'br', + 'wl': 'wl'}) - cell_1rw1r = _cell({'bl0': 'bl0', + cell_2port = _cell({'bl0': 'bl0', 'br0': 'br0', 'bl1': 'bl1', 'br1': 'br1', 'wl0': 'wl0', 'wl1': 'wl1'}) - cell_1w1r = _cell({'bl0': 'bl0', - 'br0': 'br0', - 'bl1': 'bl1', - 'br1': 'br1', - 'wl0': 'wl0', - 'wl1': 'wl1'}) - - return _bitcell(cell_6t=cell_6t, - cell_1rw1r=cell_1rw1r, - cell_1w1r=cell_1w1r, + return _bitcell(cell_1port=cell_1port, + cell_2port=cell_2port, mirror=axis) @property - def cell_6t(self): - return self._6t + def cell_1port(self): + return self._1rw @property - def cell_1rw1r(self): - return self._1rw1r - - @property - def cell_1w1r(self): - return self._1w1r + def cell_2port(self): + return self._2rw class _dff: @@ -127,22 +114,18 @@ class cell_properties(): """ def __init__(self): self.names = {} - self.names["bitcell"] = "cell_6t" - self.names["bitcell_1rw_1r"] = "cell_1rw_1r" - self.names["bitcell_1w_1r"] = "cell_1w_1r" - self.names["dummy_bitcell"] = "dummy_cell_6t" - self.names["dummy_bitcell_1rw_1r"] = "dummy_cell_1rw_1r" - self.names["dummy_bitcell_1w_1r"] = "dummy_cell_1w_1r" - self.names["replica_bitcell"] = "replica_cell_6t" - self.names["replica_bitcell_1rw_1r"] = "replica_cell_1rw_1r" - self.names["replica_bitcell_1w_1r"] = "replica_cell_1w_1r" - self.names["col_cap_bitcell_6t"] = "col_cap_cell_6t" - self.names["col_cap_bitcell_1rw_1r"] = "col_cap_cell_1rw_1r" - self.names["col_cap_bitcell_1w_1r"] = "col_cap_cell_1w_1r" - self.names["row_cap_bitcell_6t"] = "row_cap_cell_6t" - self.names["row_cap_bitcell_1rw_1r"] = "row_cap_cell_1rw_1r" - self.names["row_cap_bitcell_1w_1r"] = "row_cap_cell_1w_1r" + self.names["bitcell_1port"] = "cell_1rw" + self.names["bitcell_2port"] = "cell_2rw" + self.names["dummy_bitcell_1port"] = "dummy_cell_1rw" + self.names["dummy_bitcell_2port"] = "dummy_cell_2rw" + self.names["replica_bitcell_1port"] = "replica_cell_1rw" + self.names["replica_bitcell_2port"] = "replica_cell_2rw" + self.names["col_cap_bitcell_1port"] = "col_cap_cell_1rw" + self.names["col_cap_bitcell_2port"] = "col_cap_cell_2rw" + self.names["row_cap_bitcell_1port"] = "row_cap_cell_1rw" + self.names["row_cap_bitcell_2port"] = "row_cap_cell_2rw" + self._bitcell = _bitcell._default() self._ptx = _ptx(model_is_subckt=False, diff --git a/compiler/base/hierarchy_spice.py b/compiler/base/hierarchy_spice.py index 153a11c0..340cf074 100644 --- a/compiler/base/hierarchy_spice.py +++ b/compiler/base/hierarchy_spice.py @@ -104,7 +104,7 @@ class spice(): debug.error("{} spice subcircuit port names do not match pin_names\ \n SPICE names={}\ \n Module names={}\ - ".format(self.name, self.pin, self.pin_names), 1) + ".format(self.name, self.pins, self.pin_names), 1) self.pin_type = {pin: type for pin, type in zip(self.pin_names, type_list)} def get_pin_type(self, name): diff --git a/compiler/bitcells/bitcell_1port.py b/compiler/bitcells/bitcell_1port.py index e1e4bec8..83098c55 100644 --- a/compiler/bitcells/bitcell_1port.py +++ b/compiler/bitcells/bitcell_1port.py @@ -18,11 +18,11 @@ class bitcell_1port(bitcell_base.bitcell_base): library. """ - pin_names = [props.bitcell.cell_6t.pin.bl, - props.bitcell.cell_6t.pin.br, - props.bitcell.cell_6t.pin.wl, - props.bitcell.cell_6t.pin.vdd, - props.bitcell.cell_6t.pin.gnd] + pin_names = [props.bitcell.cell_1port.pin.bl, + props.bitcell.cell_1port.pin.br, + props.bitcell.cell_1port.pin.wl, + props.bitcell.cell_1port.pin.vdd, + props.bitcell.cell_1port.pin.gnd] type_list = ["OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"] storage_nets = ['Q', 'Q_bar'] @@ -34,37 +34,37 @@ class bitcell_1port(bitcell_base.bitcell_base): def get_all_wl_names(self): """ Creates a list of all wordline pin names """ - row_pins = [props.bitcell.cell_6t.pin.wl] + row_pins = [props.bitcell.cell_1port.pin.wl] return row_pins def get_all_bitline_names(self): """ Creates a list of all bitline pin names (both bl and br) """ - pin = props.bitcell.cell_6t.pin + pin = props.bitcell.cell_1port.pin column_pins = [pin.bl, pin.br] return column_pins def get_all_bl_names(self): """ Creates a list of all bl pins names """ - return [props.bitcell.cell_6t.pin.bl] + return [props.bitcell.cell_1port.pin.bl] def get_all_br_names(self): """ Creates a list of all br pins names """ - return [props.bitcell.cell_6t.pin.br] + return [props.bitcell.cell_1port.pin.br] def get_bl_name(self, port=0): """Get bl name""" debug.check(port == 0, "One port for bitcell only.") - return props.bitcell.cell_6t.pin.bl + return props.bitcell.cell_1port.pin.bl def get_br_name(self, port=0): """Get bl name""" debug.check(port == 0, "One port for bitcell only.") - return props.bitcell.cell_6t.pin.br + return props.bitcell.cell_1port.pin.br def get_wl_name(self, port=0): """Get wl name""" debug.check(port == 0, "One port for bitcell only.") - return props.bitcell.cell_6t.pin.wl + return props.bitcell.cell_1port.pin.wl def build_graph(self, graph, inst_name, port_nets): """ diff --git a/compiler/bitcells/bitcell_2port.py b/compiler/bitcells/bitcell_2port.py index 93642788..827a23b0 100644 --- a/compiler/bitcells/bitcell_2port.py +++ b/compiler/bitcells/bitcell_2port.py @@ -18,21 +18,21 @@ class bitcell_2port(bitcell_base.bitcell_base): library. """ - pin_names = [props.bitcell.cell_1rw1r.pin.bl0, - props.bitcell.cell_1rw1r.pin.br0, - props.bitcell.cell_1rw1r.pin.bl1, - props.bitcell.cell_1rw1r.pin.br1, - props.bitcell.cell_1rw1r.pin.wl0, - props.bitcell.cell_1rw1r.pin.wl1, - props.bitcell.cell_1rw1r.pin.vdd, - props.bitcell.cell_1rw1r.pin.gnd] + pin_names = [props.bitcell.cell_2port.pin.bl0, + props.bitcell.cell_2port.pin.br0, + props.bitcell.cell_2port.pin.bl1, + props.bitcell.cell_2port.pin.br1, + props.bitcell.cell_2port.pin.wl0, + props.bitcell.cell_2port.pin.wl1, + props.bitcell.cell_2port.pin.vdd, + props.bitcell.cell_2port.pin.gnd] type_list = ["OUTPUT", "OUTPUT", "OUTPUT", "OUTPUT", "INPUT", "INPUT", "POWER", "GROUND"] storage_nets = ['Q', 'Q_bar'] def __init__(self, name): super().__init__(name) - debug.info(2, "Create bitcell with 1RW and 1R Port") + debug.info(2, "Create bitcell with 2 ports") self.nets_match = self.do_nets_exist(self.storage_nets) @@ -46,7 +46,7 @@ class bitcell_2port(bitcell_base.bitcell_base): Creates a list of connections in the bitcell, indexed by column and row, for instance use in bitcell_array """ - pin_name = props.bitcell.cell_1rw1r.pin + pin_name = props.bitcell.cell_2port.pin bitcell_pins = ["{0}_{1}".format(pin_name.bl0, col), "{0}_{1}".format(pin_name.br0, col), "{0}_{1}".format(pin_name.bl1, col), @@ -59,43 +59,43 @@ class bitcell_2port(bitcell_base.bitcell_base): def get_all_wl_names(self): """ Creates a list of all wordline pin names """ - return [props.bitcell.cell_1rw1r.pin.wl0, - props.bitcell.cell_1rw1r.pin.wl1] + return [props.bitcell.cell_2port.pin.wl0, + props.bitcell.cell_2port.pin.wl1] def get_all_bitline_names(self): """ Creates a list of all bitline pin names (both bl and br) """ - return [props.bitcell.cell_1rw1r.pin.bl0, - props.bitcell.cell_1rw1r.pin.br0, - props.bitcell.cell_1rw1r.pin.bl1, - props.bitcell.cell_1rw1r.pin.br1] + return [props.bitcell.cell_2port.pin.bl0, + props.bitcell.cell_2port.pin.br0, + props.bitcell.cell_2port.pin.bl1, + props.bitcell.cell_2port.pin.br1] def get_all_bl_names(self): """ Creates a list of all bl pins names """ - return [props.bitcell.cell_1rw1r.pin.bl0, - props.bitcell.cell_1rw1r.pin.bl1] + return [props.bitcell.cell_2port.pin.bl0, + props.bitcell.cell_2port.pin.bl1] def get_all_br_names(self): """ Creates a list of all br pins names """ - return [props.bitcell.cell_1rw1r.pin.br0, - props.bitcell.cell_1rw1r.pin.br1] + return [props.bitcell.cell_2port.pin.br0, + props.bitcell.cell_2port.pin.br1] def get_read_bl_names(self): """ Creates a list of bl pin names associated with read ports """ - return [props.bitcell.cell_1rw1r.pin.bl0, - props.bitcell.cell_1rw1r.pin.bl1] + return [props.bitcell.cell_2port.pin.bl0, + props.bitcell.cell_2port.pin.bl1] def get_read_br_names(self): """ Creates a list of br pin names associated with read ports """ - return [props.bitcell.cell_1rw1r.pin.br0, - props.bitcell.cell_1rw1r.pin.br1] + return [props.bitcell.cell_2port.pin.br0, + props.bitcell.cell_2port.pin.br1] def get_write_bl_names(self): """ Creates a list of bl pin names associated with write ports """ - return [props.bitcell.cell_1rw1r.pin.bl0] + return [props.bitcell.cell_2port.pin.bl0] def get_write_br_names(self): """ Creates a list of br pin names asscociated with write ports""" - return [props.bitcell.cell_1rw1r.pin.br1] + return [props.bitcell.cell_2port.pin.br1] def get_bl_name(self, port=0): """Get bl name by port""" @@ -118,7 +118,7 @@ class bitcell_2port(bitcell_base.bitcell_base): pin_dict = {pin: port for pin, port in zip(self.pins, port_nets)} # Edges hardcoded here. Essentially wl->bl/br for both ports. # Port 0 edges - pins = props.bitcell.cell_1rw1r.pin + pins = props.bitcell.cell_2port.pin graph.add_edge(pin_dict[pins.wl0], pin_dict[pins.bl0], self) graph.add_edge(pin_dict[pins.wl0], pin_dict[pins.br0], self) # Port 1 edges diff --git a/compiler/bitcells/dummy_bitcell_1port.py b/compiler/bitcells/dummy_bitcell_1port.py index 679509db..5b54ff04 100644 --- a/compiler/bitcells/dummy_bitcell_1port.py +++ b/compiler/bitcells/dummy_bitcell_1port.py @@ -10,18 +10,18 @@ from tech import cell_properties as props import bitcell_base -class dummy_bitcell(bitcell_base.bitcell_base): +class dummy_bitcell_1port(bitcell_base.bitcell_base): """ A single bit cell (6T, 8T, etc.) This module implements the single memory cell used in the design. It is a hand-made cell, so the layout and netlist should be available in the technology library. """ - pin_names = [props.bitcell.cell_6t.pin.bl, - props.bitcell.cell_6t.pin.br, - props.bitcell.cell_6t.pin.wl, - props.bitcell.cell_6t.pin.vdd, - props.bitcell.cell_6t.pin.gnd] + pin_names = [props.bitcell.cell_1port.pin.bl, + props.bitcell.cell_1port.pin.br, + props.bitcell.cell_1port.pin.wl, + props.bitcell.cell_1port.pin.vdd, + props.bitcell.cell_1port.pin.gnd] type_list = ["OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"] def __init__(self, name): diff --git a/compiler/bitcells/dummy_bitcell_2port.py b/compiler/bitcells/dummy_bitcell_2port.py index 679509db..64ca08fb 100644 --- a/compiler/bitcells/dummy_bitcell_2port.py +++ b/compiler/bitcells/dummy_bitcell_2port.py @@ -10,22 +10,26 @@ from tech import cell_properties as props import bitcell_base -class dummy_bitcell(bitcell_base.bitcell_base): +class dummy_bitcell_2port(bitcell_base.bitcell_base): """ - A single bit cell (6T, 8T, etc.) This module implements the - single memory cell used in the design. It is a hand-made cell, so - the layout and netlist should be available in the technology - library. - """ - pin_names = [props.bitcell.cell_6t.pin.bl, - props.bitcell.cell_6t.pin.br, - props.bitcell.cell_6t.pin.wl, - props.bitcell.cell_6t.pin.vdd, - props.bitcell.cell_6t.pin.gnd] - type_list = ["OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"] + A single bit cell which is forced to store a 0. + This module implements the single memory cell used in the design. It + is a hand-made cell, so the layout and netlist should be available in + the technology library. """ + + pin_names = [props.bitcell.cell_2port.pin.bl0, + props.bitcell.cell_2port.pin.br0, + props.bitcell.cell_2port.pin.bl1, + props.bitcell.cell_2port.pin.br1, + props.bitcell.cell_2port.pin.wl0, + props.bitcell.cell_2port.pin.wl1, + props.bitcell.cell_2port.pin.vdd, + props.bitcell.cell_2port.pin.gnd] + type_list = ["OUTPUT", "OUTPUT", "OUTPUT", "OUTPUT", + "INPUT", "INPUT", "POWER", "GROUND"] def __init__(self, name): super().__init__(name) - debug.info(2, "Create dummy bitcell") + debug.info(2, "Create dummy bitcell 2 port object") diff --git a/compiler/bitcells/replica_bitcell_1port.py b/compiler/bitcells/replica_bitcell_1port.py index 74e121ee..92b74c24 100644 --- a/compiler/bitcells/replica_bitcell_1port.py +++ b/compiler/bitcells/replica_bitcell_1port.py @@ -12,18 +12,18 @@ from tech import parameter, drc import logical_effort -class replica_bitcell(bitcell_base.bitcell_base): +class replica_bitcell_1port(bitcell_base.bitcell_base): """ A single bit cell (6T, 8T, etc.) This module implements the single memory cell used in the design. It is a hand-made cell, so the layout and netlist should be available in the technology library. """ - pin_names = [props.bitcell.cell_6t.pin.bl, - props.bitcell.cell_6t.pin.br, - props.bitcell.cell_6t.pin.wl, - props.bitcell.cell_6t.pin.vdd, - props.bitcell.cell_6t.pin.gnd] + pin_names = [props.bitcell.cell_1port.pin.bl, + props.bitcell.cell_1port.pin.br, + props.bitcell.cell_1port.pin.wl, + props.bitcell.cell_1port.pin.vdd, + props.bitcell.cell_1port.pin.gnd] type_list = ["OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"] def __init__(self, name): diff --git a/compiler/bitcells/replica_bitcell_2port.py b/compiler/bitcells/replica_bitcell_2port.py index 74e121ee..bc95ba25 100644 --- a/compiler/bitcells/replica_bitcell_2port.py +++ b/compiler/bitcells/replica_bitcell_2port.py @@ -12,23 +12,26 @@ from tech import parameter, drc import logical_effort -class replica_bitcell(bitcell_base.bitcell_base): +class replica_bitcell_2port(bitcell_base.bitcell_base): """ - A single bit cell (6T, 8T, etc.) + A single bit cell which is forced to store a 0. This module implements the single memory cell used in the design. It is a hand-made cell, so the layout and netlist should be available in the technology library. """ - pin_names = [props.bitcell.cell_6t.pin.bl, - props.bitcell.cell_6t.pin.br, - props.bitcell.cell_6t.pin.wl, - props.bitcell.cell_6t.pin.vdd, - props.bitcell.cell_6t.pin.gnd] - type_list = ["OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"] + pin_names = [props.bitcell.cell_2port.pin.bl0, + props.bitcell.cell_2port.pin.br0, + props.bitcell.cell_2port.pin.bl1, + props.bitcell.cell_2port.pin.br1, + props.bitcell.cell_2port.pin.wl0, + props.bitcell.cell_2port.pin.wl1, + props.bitcell.cell_2port.pin.vdd, + props.bitcell.cell_2port.pin.gnd] + type_list = ["OUTPUT", "OUTPUT", "OUTPUT", "OUTPUT", "INPUT", "INPUT", "POWER", "GROUND"] def __init__(self, name): super().__init__(name) - debug.info(2, "Create replica bitcell object") + debug.info(2, "Create replica bitcell 2 port object") def get_stage_effort(self, load): parasitic_delay = 1 @@ -41,17 +44,19 @@ class replica_bitcell(bitcell_base.bitcell_base): """Return the relative capacitance of the access transistor gates""" # FIXME: This applies to bitline capacitances as well. + # FIXME: sizing is not accurate with the handmade cell. Change once cell widths are fixed. access_tx_cin = parameter["6T_access_size"] / drc["minwidth_tx"] return 2 * access_tx_cin - def analytical_power(self, corner, load): - """Bitcell power in nW. Only characterizes leakage.""" - from tech import spice - leakage = spice["bitcell_leakage"] - dynamic = 0 # FIXME - total_power = self.return_power(dynamic, leakage) - return total_power - def build_graph(self, graph, inst_name, port_nets): - """Adds edges based on inputs/outputs. Overrides base class function.""" - self.add_graph_edges(graph, port_nets) + """Adds edges to graph. Multiport bitcell timing graph is too complex + to use the add_graph_edges function.""" + pin_dict = {pin: port for pin, port in zip(self.pins, port_nets)} + pins = props.bitcell.cell_2port.pin + # Edges hardcoded here. Essentially wl->bl/br for both ports. + # Port 0 edges + graph.add_edge(pin_dict[pins.wl0], pin_dict[pins.bl0], self) + graph.add_edge(pin_dict[pins.wl0], pin_dict[pins.br0], self) + # Port 1 edges + graph.add_edge(pin_dict[pins.wl1], pin_dict[pins.bl1], self) + graph.add_edge(pin_dict[pins.wl1], pin_dict[pins.br1], self) diff --git a/compiler/globals.py b/compiler/globals.py index 74b578b0..8c6d7fd5 100644 --- a/compiler/globals.py +++ b/compiler/globals.py @@ -213,15 +213,15 @@ def setup_bitcell(): # If we have non-1rw ports, # and the user didn't over-ride the bitcell manually, # figure out the right bitcell to use - if OPTS.bitcell == "bitcell": + if OPTS.bitcell == "pbitcell": + OPTS.bitcell = "pbitcell" + OPTS.dummy_bitcell = "dummy_pbitcell" + OPTS.replica_bitcell = "replica_pbitcell" + else: num_ports = OPTS.num_rw_ports + OPTS.num_w_ports + OPTS.num_r_ports OPTS.bitcell = "bitcell_{}port".format(num_ports) OPTS.dummy_bitcell = "dummy_" + OPTS.bitcell OPTS.replica_bitcell = "replica_" + OPTS.bitcell - elif OPTS.bitcell == "pbitcell": - OPTS.bitcell = "pbitcell" - OPTS.dummy_bitcell = "dummy_pbitcell" - OPTS.replica_bitcell = "replica_pbitcell" # See if bitcell exists try: diff --git a/compiler/modules/bitcell_array.py b/compiler/modules/bitcell_array.py index 10abe1e2..5a181ba7 100644 --- a/compiler/modules/bitcell_array.py +++ b/compiler/modules/bitcell_array.py @@ -62,7 +62,7 @@ class bitcell_array(bitcell_base_array): for row in range(self.row_size): name = "bit_r{0}_c{1}".format(row, col) self.cell_inst[row, col]=self.add_inst(name=name, - mod=self.cell) + mod=self.cell) self.connect_inst(self.get_bitcell_pins(row, col)) def analytical_power(self, corner, load): diff --git a/compiler/options.py b/compiler/options.py index cd9726e0..5679b79e 100644 --- a/compiler/options.py +++ b/compiler/options.py @@ -148,10 +148,9 @@ class options(optparse.Values): # These are the default modules that can be over-riden - bitcell_suffix = "" bank_select = "bank_select" bitcell_array = "bitcell_array" - bitcell = "bitcell_1port" + bitcell = "bitcell" buf_dec = "pbuf" column_mux_array = "column_mux_array" control_logic = "control_logic" diff --git a/technology/freepdk45/gds_lib/cell_6t.gds b/technology/freepdk45/gds_lib/cell_1rw.gds similarity index 77% rename from technology/freepdk45/gds_lib/cell_6t.gds rename to technology/freepdk45/gds_lib/cell_1rw.gds index 17b6202840bbfeed1fc7d699d9377cf6f057322c..38e53e27872bed4854cc2320d02e6eb82977cffc 100644 GIT binary patch delta 209 zcmZozz_?~AqXGjP0~1pOgA5}R`x6Fk23`hE215oe1bd=_q+y$-QjGWo-!+>UWLR-1 zW8h-oVPi{9&B=*3EGplabx3D&j%LJU7fq|lby{qbne^6AHrACAJ9FmDDGml60p|bz z|IcAyU{qsZlVmHO9B(bX`Jdhz?#Zt#MJ88S>r7syr^pIcJNbg16f)1s8Y(VeZ3$)h MS<7!;YyF=O0LZRD8~^|S delta 1566 zcmZ28m9b#~qXGjP0}~L-FfuXlF>o{RGVm~PF-R~70oj~D%rQ|x((s$5QjGWo-!+>U zWLP1}*no;e8H^ChfP5Y{w&c{DoOrVmhK*T=bSCHMDT<$E00ABW=Kufy&tYI-RAXS1 zWGm0vtfuSBIC-O$6f0Q4>lMAgZH!rhh hFAe%?Se>D6DG6V)X{l(GN^8jwuEolG% diff --git a/technology/freepdk45/gds_lib/dummy_cell_6t.gds b/technology/freepdk45/gds_lib/dummy_cell_1rw.gds similarity index 75% rename from technology/freepdk45/gds_lib/dummy_cell_6t.gds rename to technology/freepdk45/gds_lib/dummy_cell_1rw.gds index c6575122439eefaec9ad0a42202d113e796a15b4..28dd8124a44d4eec113c66a142d330e2a175f8e2 100644 GIT binary patch delta 260 zcmZozz_@7&V?6^K0~1pOgA5}R`x6Fk23`hE1_K6NWHtj26I)7ZT4HHV2?K)&Gpn7# zk=aWh2iI6C#fV?CI%)3Ha;eX zjrE&#CKqW&O!m^Wn#`oPb+VrCFDrzi=Q zV&D;AW?*1?z`(#Yje$dwtt=&lVe%?Hb*RQ`R@P9Kn6;%ik`Bfi2B6&xY?5qAIh&VR H_wWG#ALvN+ delta 1750 zcmdlqg|T4)V?6^K0}~L-FfuXlF>o{RGVm~PF-R~7Gq5u-14WF0vOG*|DXD3Rr8y-G z3?j^|b_z#kFMS;R%~B~w{DSYA6$~=05WQ?bouWV;$a;m?*iuS!b1UPMQ*(0S&44Db za4;~i@iKvI`Q>sbaMm^?#IesZN|;N&jd_mj6FF<$W`Pd?2;Mj; diff --git a/technology/freepdk45/gds_lib/replica_cell_6t.gds b/technology/freepdk45/gds_lib/replica_cell_1rw.gds similarity index 82% rename from technology/freepdk45/gds_lib/replica_cell_6t.gds rename to technology/freepdk45/gds_lib/replica_cell_1rw.gds index f2fe91974439e0cf98c77571fd57bb8fa9f15c3c..67c9bdf7f050b4179bb908ce413dd244f37f6bb4 100644 GIT binary patch delta 235 zcmZozz_?{9V?6^K0~1pOgA5}R`x6Fk23`hE215o}WHtj26I)7ZT4HHV2?K)&Gpn7# zk=aWh2iI6C#fV?)PkJMf}j{x)k|Nj>o{RGVm~PF-R~70oj~D%)`LXz{A9rlA4xSnp48S zAi~UQr*LHU(#OHyER|x!FZixm!63s5(aQ$ZDav4kqF02Cttho1Co?%QJ~=ffC*BNb z1`7uR0~;?B$X>q5`x&`6c4bLVF40qDJ<9+DlV|D4Z~iS^DKvSLp2Or#RxsfkR+dl& zV%CYGFK!(6Tr@t`Tcpd=Ptv77| diff --git a/technology/freepdk45/sp_lib/cell_6t.sp b/technology/freepdk45/sp_lib/cell_1rw.sp similarity index 86% rename from technology/freepdk45/sp_lib/cell_6t.sp rename to technology/freepdk45/sp_lib/cell_1rw.sp index b39427d7..7fdba85a 100644 --- a/technology/freepdk45/sp_lib/cell_6t.sp +++ b/technology/freepdk45/sp_lib/cell_1rw.sp @@ -1,5 +1,5 @@ -.SUBCKT cell_6t bl br wl vdd gnd +.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 @@ -11,5 +11,5 @@ 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_6t +.ENDS cell_1rw diff --git a/technology/freepdk45/sp_lib/dummy_cell_6t.sp b/technology/freepdk45/sp_lib/dummy_cell_1rw.sp similarity index 85% rename from technology/freepdk45/sp_lib/dummy_cell_6t.sp rename to technology/freepdk45/sp_lib/dummy_cell_1rw.sp index 6e192049..9181645a 100644 --- a/technology/freepdk45/sp_lib/dummy_cell_6t.sp +++ b/technology/freepdk45/sp_lib/dummy_cell_1rw.sp @@ -1,5 +1,5 @@ -.SUBCKT dummy_cell_6t bl br wl vdd gnd +.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 @@ -11,5 +11,5 @@ 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 cell_6t +.ENDS cell_1rw diff --git a/technology/freepdk45/sp_lib/replica_cell_6t.sp b/technology/freepdk45/sp_lib/replica_cell_1rw.sp similarity index 84% rename from technology/freepdk45/sp_lib/replica_cell_6t.sp rename to technology/freepdk45/sp_lib/replica_cell_1rw.sp index dd29028a..284b1c0a 100644 --- a/technology/freepdk45/sp_lib/replica_cell_6t.sp +++ b/technology/freepdk45/sp_lib/replica_cell_1rw.sp @@ -1,5 +1,5 @@ -.SUBCKT replica_cell_6t bl br wl vdd gnd +.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 @@ -11,5 +11,5 @@ 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_6t +.ENDS cell_1rw diff --git a/technology/freepdk45/tech/tech.py b/technology/freepdk45/tech/tech.py index 035e8b93..46b7c2a5 100644 --- a/technology/freepdk45/tech/tech.py +++ b/technology/freepdk45/tech/tech.py @@ -35,12 +35,6 @@ cell_properties.bitcell.mirror.x = True cell_properties.bitcell.mirror.y = False cell_properties.bitcell_power_pin_directions = ("V", "V") -cell_properties.names["bitcell_1port"] = "cell_6t" -cell_properties.names["dummy_bitcell_1port"] = "dummy_cell_6t" -cell_properties.names["replcia_bitcell_1port"] = "replica_cell_6t" -cell_properties.names["bitcell_2port"] = "cell_2rw" -cell_properties.names["dummy_bitcell_2port"] = "dummy_cell_2rw" -cell_properties.names["replica_bitcell_2port"] = "replica_cell_2rw" ################################################### # Custom cell properties diff --git a/technology/scn4m_subm/gds_lib/cell_1rw.gds b/technology/scn4m_subm/gds_lib/cell_1rw.gds new file mode 100644 index 0000000000000000000000000000000000000000..92523dc1bf8eb78f321678c9b2b1d2bce034067a GIT binary patch literal 5868 zcmb7|J#1V>6oqfr_U^{9%^GYIlLc=SL7c=P4oDChFcL*1njodHXaXS!7Z!>vL{g>< zUCKx_?r`ZcWh#`?Wl9$mDP4kuSnl`kJG>uf2C!s(tMlf}ow;*o=IvV7I-N}$p6K*` zvr{%}C+)IL*FW1#r~A#f+uOH3_`z&pV(Q~hfBNwAUw=9J=(8tRc7OizrVXbu-fnoW z?%cD4jcZ~W;5QGD1G`U<@bba zn4NeO^mc_`lU7Jwev!O(pNT8ezV>I?SlA-FG^4QwQj*T9z|Sn;f9{40H`#5;+DC$R)e)e(RAA7~TpICEIy6?$Ee6y2Z z#h!!ssDF{YTs}|wsXN+3#?Aai>CUX5IO>O-LgZPLqN>BSE?~8{)`e4t9 z(iacYEIkGL}rg0DV}y(>!hHA&`={li{^tQ~t_l;h)r!)cN&jmP z!w>N+65auQjKA&;Lc~&ZM6X{&xXNAW@F&a9s^A3yC`KT*0f>7TtGH3MgS z{g|&vEtSuc{-wRRb0B$V{Y2uI&lCQ*_j>;R>F@YO?G8s3rTd)f{wwwRXRLT&vF?M4 z(w#{^?;WfcWUS;}lC7 z%%6Kll-`3rMKR{kNNeU%=o(`(w=?waR-YdqwZW(uDvToF$C_T6S+%L@aW%rMCXJY=kH-fY$zSu9n zS9@(F{AQE;@jV6dTMl=Y$oH4>dD2ggXb16;H&MF2|IGL!|NYF@f2m`B-R%< zxqELrM)|Tatyn{kKkcn<-Tr!~Y}t>f@3&7)v+C4j*K%q?>HeWU z>zdym?9(oYuXhlBD4oZ(U;P?>R)|vy;%B#u(w#{^6-t&NKC&)KcP9P+XVs49FXEd2 z5ua5izUXqHJCgC)E&M^oP1TChorS+#Y0qC(HMH?H=r4D_`~FU*9lvD#mv+?G>Ms5L vcqi8%xqat4b$Gj3t&P!f{*mos z5;xuHvdb=68I~+rvSit%CdTpn=Dd%0=hb^-;!B!e`QH7`x%b>Z?^5ep%i1M3r}^^D(a_F4GIk6-;jr$5#Ej6dR2C-RG@cS9Fl&-kNm_*8dzdN*{j;lEPX&uqoa zE)C3vo?l$w3|(|R&7b&V&0lyN>qlHY3|(}+=x6US_u_@eiW_u2<2QTltMIY@@k9E7 zE|&bPFWNDFarH3PpXhovKYsEu2O@D4w|bxTQ-6Hq7xANuu4nvFpOY`5e&ULSF1nua zM;?6S7s;Le}hc5d2Y<|XxpKqwhc+ka?pK-Qd#`wjV2Qhxp^=y8|iI4G% z_|V0?KgP*EWBlUkTIizd+5F5KzT*cqS6xFFOMd1EKm8T)p^GIyb;d{iMSSRD-XG&U z^;?WzT;2*@bUizM^57%CxV#nl#fJZ#bpJ3%qh8Fn$bAT1bUn>~#LwK%dJK^`iVI!O z`th8b=7rB97uhf1mXawxh4CANmZrOQDOU z@lzkZUHC-eRCSxMaep{cf4rQNB5@QKx}NPn?>YOKKan_{a&{(ch>3tLgfuk9g(>HOY%E`unV( z`vvnw{YCnWE;iE}7GH)~a-ALyd%>H1B^AN67FQa|zBgV06SGycfK+SAy+~vzo_qq*f{@_`uV=`T$~;BUt}EUqU+iG z^pkev7wHGO=z7slUheNAaTFJp^0UsEcg_xx`9l{=^UrsNu~SEpJ(PZbT+j4B)){k6 ze)0H0=%VWxzgcJB&mH&j?GpLh4Z7%h)=$m!{~i$^y4di)-#ov}ANG%^b4zqR&7b(A zpZHiWB7b+F|Dx+zKQ-r^VBd-O&_&m?e%1=(Wc`Tv&_&m?{{L6M$YcJHpGW@>B|q~4 z{mJHMo$|1Lcp&{o7yZ}N|8YHk{-%2PTM-Xj+nfCQivF*OzwagTzn}X2oocz(AGD*L z&sA@w``!0<3+;&eU)r&6Jio{L>24_=bM@8@>#lU~?BsjL2~xGXH`U6|uzC#C+3z?W m>;81CsaEuC_>xwiPmgn|73Yo5;heX+edp_YRm)jt$Nm8{G4UG! diff --git a/technology/scn4m_subm/gds_lib/dummy_cell_1rw.gds b/technology/scn4m_subm/gds_lib/dummy_cell_1rw.gds new file mode 100644 index 0000000000000000000000000000000000000000..b27e5e02cfdbd73de293b701c0f8564a311a46e9 GIT binary patch literal 5544 zcma)=J#1V>6oqeg?cGgcFY92NI9c#U5yVLx;(!F90V7dFqDetv(FB1JDI63K~&b{;VX4iVw>1^5fNT>gs z9k+QqYM1O({j;6u^tQjhb?e6)Uwyr^bK|}5%oe+|AAbDP`=9>$%fSbqJh{C4^XH%0 zcsA2RuinFzJ9lknVAh-O*ahniJ7%^%>Q1MBJ~cbN68qP5zghn|?SlA-FG^4QHE+RF4xqP1Vv+igQ88`Wh(w$j9anuhr#|Ne7#!vle2k{YKl%DoS z-Iw-*^ueAHr7!KL$4^^-UU>LSd{KJZA93gI2TweWy(>!hIZ4)!{li{^%pH4QlYe7Ws?PTl>E;f6N#A72-Soq@whkpE;u) z#7`cg^qimi(+=XJ{-X4>Kk{DQ3!c0h`HRw*_tNzzu0Jp0<0HN(z2$$qzJHjj$sp#8 z_crT6lV#=0RcV;7}6lYZu#cP^woeo?wJ>!)VwhdqN2 zN_Qsxqnj~y$Q^+7Ba&PBJn5(YysNZl@Z*EhomoF^)eq+=J}BLp^>gOqr#ALkBr;vB-qo)M+D{8y^+$Gn{z1$FNgrMK?Chy1#ya$n~D zB}#AI-)jC?E8O!~tGYLf(sO?1opul(b1q8H`MK-S4l-_PCQ8rw8TT9asytXj_@H!W zef`w(kGc=b`qQ5JiPC*dCHxVWIoCKiH}UKIL~os+wfNy<&y?+oanm2;m+nl)=e^B& z3(1@Mi_)D*|H$_Y=Ov^)eo=bs{B4Y%doz0$GG2`vN_QsXGj4p4c*GZ_|5yIRQ9s<9 z@j>ai_^dn549L8({zU1y`R9Bm*O#6D(w&L?b#4b~PkeDuey{blk?=>|`JO=i`7MQa zhA6%D{h={`)QWZxA9WL@%RlFj{P!#OFL%t3+)+2Yem?hBdUtmkqkOl0%9&NC9J`ED z4odeA^(3#Fk4t!vEgm*wofY;^3` dvelhN4L+*Y02x$&9=rIJNUWZOzwc?x*gv&(*nR*2 literal 0 HcmV?d00001 diff --git a/technology/scn4m_subm/gds_lib/dummy_cell_6t.gds b/technology/scn4m_subm/gds_lib/dummy_cell_6t.gds deleted file mode 100644 index 4a950a68e7a0b661fd22c3569bc807591b6364d8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5544 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 xq?X@-Wgi%4e> -rect 0 46 54 75 -<< pwell >> -rect 0 0 54 46 -<< ntransistor >> -rect 14 33 16 37 -rect 22 29 24 37 -rect 30 29 32 37 -rect 38 33 40 37 -rect 14 17 16 23 -rect 22 17 24 23 -rect 30 17 32 23 -rect 38 17 40 23 -<< ptransistor >> -rect 22 54 24 57 -rect 30 54 32 57 -<< ndiffusion >> -rect 13 33 14 37 -rect 16 33 17 37 -rect 21 33 22 37 -rect 17 29 22 33 -rect 24 29 25 37 -rect 29 29 30 37 -rect 32 33 33 37 -rect 37 33 38 37 -rect 40 33 41 37 -rect 32 29 37 33 -rect 9 21 14 23 -rect 13 17 14 21 -rect 16 17 22 23 -rect 24 17 25 23 -rect 29 17 30 23 -rect 32 17 38 23 -rect 40 21 45 23 -rect 40 17 41 21 -<< pdiffusion >> -rect 21 54 22 57 -rect 24 54 25 57 -rect 29 54 30 57 -rect 32 54 33 57 -<< ndcontact >> -rect 9 33 13 37 -rect 17 33 21 37 -rect 25 29 29 37 -rect 33 33 37 37 -rect 41 33 45 37 -rect 9 17 13 21 -rect 25 17 29 23 -rect 41 17 45 21 -<< pdcontact >> -rect 17 54 21 58 -rect 25 54 29 58 -rect 33 54 37 58 -<< psubstratepcontact >> -rect 25 9 29 13 -<< nsubstratencontact >> -rect 25 68 29 72 -<< polysilicon >> -rect 22 57 24 60 -rect 30 57 32 60 -rect 22 44 24 54 -rect 30 51 32 54 -rect 31 47 32 51 -rect 14 37 16 44 -rect 22 40 23 44 -rect 22 37 24 40 -rect 30 37 32 47 -rect 38 37 40 44 -rect 14 31 16 33 -rect 38 31 40 33 -rect 14 23 16 24 -rect 22 23 24 29 -rect 30 23 32 29 -rect 38 23 40 24 -rect 14 15 16 17 -rect 22 15 24 17 -rect 30 15 32 17 -rect 38 15 40 17 -<< polycontact >> -rect 27 47 31 51 -rect 10 40 14 44 -rect 23 40 27 44 -rect 40 40 44 44 -rect 12 24 16 28 -rect 38 24 42 28 -<< metal1 >> -rect 0 68 25 72 -rect 29 68 54 72 -rect 0 61 54 65 -rect 10 44 14 61 -rect 17 51 20 54 -rect 17 47 27 51 -rect 17 37 20 47 -rect 34 44 37 54 -rect 27 40 37 44 -rect 40 44 44 61 -rect 34 37 37 40 -rect 6 33 9 37 -rect 45 33 48 37 -rect 25 23 29 29 -rect 25 13 29 17 -rect 0 9 25 13 -rect 29 9 54 13 -rect 0 2 16 6 -rect 20 2 34 6 -rect 38 2 54 6 -<< m2contact >> -rect 25 68 29 72 -rect 25 54 29 58 -rect 2 33 6 37 -rect 48 33 52 37 -rect 16 24 20 28 -rect 34 24 38 28 -rect 9 17 13 21 -rect 41 17 45 21 -rect 16 2 20 6 -rect 34 2 38 6 -<< metal2 >> -rect 2 37 6 72 -rect 2 0 6 33 -rect 9 21 13 72 -rect 25 58 29 68 -rect 9 0 13 17 -rect 16 6 20 24 -rect 34 6 38 24 -rect 41 21 45 72 -rect 41 0 45 17 -rect 48 37 52 72 -rect 48 0 52 33 -<< comment >> -rect 0 0 54 70 -<< labels >> -rlabel metal1 19 63 19 63 1 wl0 -rlabel metal1 19 70 19 70 5 vdd -rlabel metal1 27 4 27 4 1 wl1 -rlabel psubstratepcontact 27 11 27 11 1 gnd -rlabel metal2 4 7 4 7 2 bl0 -rlabel metal2 11 7 11 7 1 bl1 -rlabel metal2 43 7 43 7 1 br1 -rlabel metal2 50 7 50 7 8 br0 -rlabel polycontact 29 49 29 49 1 Q -rlabel polycontact 25 42 25 42 1 Q_bar -<< end >> diff --git a/technology/scn4m_subm/mag_lib/cell_1rw_1r.mag b/technology/scn4m_subm/mag_lib/cell_2rw.mag similarity index 100% rename from technology/scn4m_subm/mag_lib/cell_1rw_1r.mag rename to technology/scn4m_subm/mag_lib/cell_2rw.mag diff --git a/technology/scn4m_subm/mag_lib/cell_6t.ext b/technology/scn4m_subm/mag_lib/cell_6t.ext deleted file mode 100644 index 79f3c8b4..00000000 --- a/technology/scn4m_subm/mag_lib/cell_6t.ext +++ /dev/null @@ -1,41 +0,0 @@ -timestamp 1536091415 -version 8.2 -tech scmos -style TSMC0.35um(tsmc35)from:t11c -scale 1000 1 5 -resistclasses 3700 2800 1018000 1018000 1 6000 6000 80 70 80 40 -node "comment_0_0#" 0 0 0 0 bb 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -node "br" 6 -1.43219e-14 96 -8 ndc 320 72 0 0 0 0 0 0 0 0 0 0 0 0 512 96 3456 464 0 0 0 0 -node "bl" 6 -8.88178e-16 40 -8 ndc 320 72 0 0 0 0 0 0 0 0 0 0 0 0 512 96 3200 432 0 0 0 0 -node "wl" 115 -2.89546e-13 -8 12 p 0 0 0 0 0 0 0 0 0 0 1536 360 0 0 2496 344 0 0 0 0 0 0 -node "a_36_40#" 140 -3.51719e-13 36 40 ndif 960 144 304 72 0 0 0 0 0 0 1984 424 0 0 2048 288 0 0 0 0 0 0 -node "a_28_32#" 160 -8.06466e-13 28 32 p 960 144 304 72 0 0 0 0 0 0 2000 456 0 0 1920 272 0 0 0 0 0 0 -node "gnd" 41 -27.888 -32 -32 pw 1792 240 512 128 0 0 0 0 29600 696 0 0 0 0 2688 400 6400 864 0 0 0 0 -equiv "gnd" "gnd" -node "vdd" 2340 2596 -32 116 nw 256 64 800 176 17600 576 0 0 0 0 0 0 0 0 3456 464 256 64 0 0 0 0 -cap "wl" "bl" 189.768 -cap "a_36_40#" "br" 17.59 -cap "wl" "br" 189.768 -cap "vdd" "bl" 135.015 -cap "bl" "br" 27.492 -cap "vdd" "br" 117.084 -cap "gnd" "a_28_32#" 880.405 -cap "gnd" "a_36_40#" 401.284 -cap "a_28_32#" "a_36_40#" 272.793 -cap "gnd" "wl" 1198.41 -cap "gnd" "bl" 712.11 -cap "a_28_32#" "wl" 108.364 -cap "vdd" "gnd" 510.12 -cap "gnd" "br" 698.471 -cap "a_36_40#" "wl" 108.364 -cap "a_28_32#" "bl" 104.205 -cap "vdd" "a_28_32#" 430.812 -cap "a_36_40#" "bl" 29.396 -cap "a_28_32#" "br" 308.488 -cap "vdd" "a_36_40#" 709.108 -fet nfet 96 12 97 13 128 48 "gnd" "wl" 16 0 "br" 16 0 "a_28_32#" 16 0 -fet nfet 40 12 41 13 128 48 "gnd" "wl" 16 0 "bl" 16 0 "a_36_40#" 16 0 -fet nfet 116 40 117 41 256 80 "gnd" "a_36_40#" 16 0 "a_28_32#" 32 0 "gnd" 32 0 -fet nfet 28 40 29 41 256 80 "gnd" "a_28_32#" 16 0 "gnd" 32 0 "a_36_40#" 32 0 -fet pfet 108 148 109 149 192 56 "vdd" "a_36_40#" 32 0 "a_28_32#" 12 0 "vdd" 12 0 -fet pfet 28 148 29 149 192 56 "vdd" "a_28_32#" 32 0 "vdd" 12 0 "a_36_40#" 12 0 diff --git a/technology/scn4m_subm/mag_lib/cell_6t.spice b/technology/scn4m_subm/mag_lib/cell_6t.spice deleted file mode 100644 index 31eec08a..00000000 --- a/technology/scn4m_subm/mag_lib/cell_6t.spice +++ /dev/null @@ -1,15 +0,0 @@ -* SPICE3 file created from cell_6t.ext - technology: scmos - -M1000 a_36_40# a_28_32# vdd vdd pfet w=0.6u l=0.8u -+ ad=0.76p pd=3.6u as=2p ps=8.8u -M1001 vdd a_36_40# a_28_32# vdd pfet w=0.6u l=0.8u -+ ad=0p pd=0u as=0.76p ps=3.6u -M1002 a_36_40# a_28_32# gnd gnd nfet w=1.6u l=0.4u -+ ad=2.4p pd=7.2u as=4.48p ps=12u -M1003 gnd a_36_40# a_28_32# gnd nfet w=1.6u l=0.4u -+ ad=0p pd=0u as=2.4p ps=7.2u -M1004 a_36_40# wl bl gnd nfet w=0.8u l=0.4u -+ ad=0p pd=0u as=0.8p ps=3.6u -M1005 a_28_32# wl br gnd nfet w=0.8u l=0.4u -+ ad=0p pd=0u as=0.8p ps=3.6u -C0 vdd 0 2.60fF diff --git a/technology/scn4m_subm/mag_lib/dummy_cell_6t.mag b/technology/scn4m_subm/mag_lib/dummy_cell_1rw.mag similarity index 100% rename from technology/scn4m_subm/mag_lib/dummy_cell_6t.mag rename to technology/scn4m_subm/mag_lib/dummy_cell_1rw.mag diff --git a/technology/scn4m_subm/mag_lib/dummy_cell_1w_1r.mag b/technology/scn4m_subm/mag_lib/dummy_cell_1w_1r.mag deleted file mode 100644 index 1931485f..00000000 --- a/technology/scn4m_subm/mag_lib/dummy_cell_1w_1r.mag +++ /dev/null @@ -1,138 +0,0 @@ -magic -tech scmos -timestamp 1577067400 -<< nwell >> -rect 0 46 54 75 -<< pwell >> -rect 0 0 54 46 -<< ntransistor >> -rect 14 33 16 37 -rect 22 29 24 37 -rect 30 29 32 37 -rect 38 33 40 37 -rect 14 17 16 23 -rect 22 17 24 23 -rect 30 17 32 23 -rect 38 17 40 23 -<< ptransistor >> -rect 22 54 24 57 -rect 30 54 32 57 -<< ndiffusion >> -rect 13 33 14 37 -rect 16 33 17 37 -rect 21 33 22 37 -rect 17 29 22 33 -rect 24 29 25 37 -rect 29 29 30 37 -rect 32 33 33 37 -rect 37 33 38 37 -rect 40 33 41 37 -rect 32 29 37 33 -rect 9 21 14 23 -rect 13 17 14 21 -rect 16 17 22 23 -rect 24 17 25 23 -rect 29 17 30 23 -rect 32 17 38 23 -rect 40 21 45 23 -rect 40 17 41 21 -<< pdiffusion >> -rect 21 54 22 57 -rect 24 54 25 57 -rect 29 54 30 57 -rect 32 54 33 57 -<< ndcontact >> -rect 9 33 13 37 -rect 17 33 21 37 -rect 25 29 29 37 -rect 33 33 37 37 -rect 41 33 45 37 -rect 9 17 13 21 -rect 25 17 29 23 -rect 41 17 45 21 -<< pdcontact >> -rect 17 54 21 58 -rect 25 54 29 58 -rect 33 54 37 58 -<< psubstratepcontact >> -rect 25 9 29 13 -<< nsubstratencontact >> -rect 25 68 29 72 -<< polysilicon >> -rect 22 57 24 60 -rect 30 57 32 60 -rect 22 44 24 54 -rect 30 51 32 54 -rect 31 47 32 51 -rect 14 37 16 44 -rect 22 40 23 44 -rect 22 37 24 40 -rect 30 37 32 47 -rect 38 37 40 44 -rect 14 31 16 33 -rect 38 31 40 33 -rect 14 23 16 24 -rect 22 23 24 29 -rect 30 23 32 29 -rect 38 23 40 24 -rect 14 15 16 17 -rect 22 15 24 17 -rect 30 15 32 17 -rect 38 15 40 17 -<< polycontact >> -rect 27 47 31 51 -rect 10 40 14 44 -rect 23 40 27 44 -rect 40 40 44 44 -rect 12 24 16 28 -rect 38 24 42 28 -<< metal1 >> -rect 0 68 25 72 -rect 29 68 54 72 -rect 0 61 54 65 -rect 10 44 14 61 -rect 17 51 20 54 -rect 17 47 27 51 -rect 17 37 20 47 -rect 34 44 37 54 -rect 27 40 37 44 -rect 40 44 44 61 -rect 34 37 37 40 -rect 2 33 9 37 -rect 45 33 52 37 -rect 25 23 29 29 -rect 25 13 29 17 -rect 0 9 25 13 -rect 29 9 54 13 -rect 0 2 16 6 -rect 20 2 34 6 -rect 38 2 54 6 -<< m2contact >> -rect 25 68 29 72 -rect 25 54 29 58 -rect 16 24 20 28 -rect 34 24 38 28 -rect 16 2 20 6 -rect 34 2 38 6 -<< metal2 >> -rect 2 0 6 72 -rect 9 0 13 72 -rect 25 58 29 68 -rect 16 6 20 24 -rect 34 6 38 24 -rect 41 0 45 72 -rect 48 0 52 72 -<< comment >> -rect 0 0 54 70 -<< labels >> -rlabel metal1 19 63 19 63 1 wl0 -rlabel metal1 19 70 19 70 5 vdd -rlabel metal1 27 4 27 4 1 wl1 -rlabel psubstratepcontact 27 11 27 11 1 gnd -rlabel metal2 4 7 4 7 2 bl0 -rlabel metal2 11 7 11 7 1 bl1 -rlabel metal2 43 7 43 7 1 br1 -rlabel metal2 50 7 50 7 8 br0 -rlabel polycontact 29 49 29 49 1 Q -rlabel polycontact 25 42 25 42 1 Q_bar -<< end >> diff --git a/technology/scn4m_subm/mag_lib/dummy_cell_1rw_1r.mag b/technology/scn4m_subm/mag_lib/dummy_cell_2rw.mag similarity index 100% rename from technology/scn4m_subm/mag_lib/dummy_cell_1rw_1r.mag rename to technology/scn4m_subm/mag_lib/dummy_cell_2rw.mag diff --git a/technology/scn4m_subm/mag_lib/replica_cell_6t.mag b/technology/scn4m_subm/mag_lib/replica_cell_1rw.mag similarity index 100% rename from technology/scn4m_subm/mag_lib/replica_cell_6t.mag rename to technology/scn4m_subm/mag_lib/replica_cell_1rw.mag diff --git a/technology/scn4m_subm/mag_lib/replica_cell_1w_1r.mag b/technology/scn4m_subm/mag_lib/replica_cell_1w_1r.mag deleted file mode 100644 index 61add325..00000000 --- a/technology/scn4m_subm/mag_lib/replica_cell_1w_1r.mag +++ /dev/null @@ -1,147 +0,0 @@ -magic -tech scmos -timestamp 1577067446 -<< nwell >> -rect 0 46 54 75 -<< pwell >> -rect 0 0 54 46 -<< ntransistor >> -rect 14 33 16 37 -rect 22 29 24 37 -rect 30 29 32 37 -rect 38 33 40 37 -rect 14 17 16 23 -rect 22 17 24 23 -rect 30 17 32 23 -rect 38 17 40 23 -<< ptransistor >> -rect 22 54 24 57 -rect 30 54 32 57 -<< ndiffusion >> -rect 13 33 14 37 -rect 16 33 17 37 -rect 21 33 22 37 -rect 17 29 22 33 -rect 24 29 25 37 -rect 29 29 30 37 -rect 32 33 33 37 -rect 37 33 38 37 -rect 40 33 41 37 -rect 32 29 37 33 -rect 9 21 14 23 -rect 13 17 14 21 -rect 16 17 22 23 -rect 24 17 25 23 -rect 29 17 30 23 -rect 32 17 38 23 -rect 40 21 45 23 -rect 40 17 41 21 -<< pdiffusion >> -rect 21 54 22 57 -rect 24 54 25 57 -rect 29 54 30 57 -rect 32 54 33 57 -<< ndcontact >> -rect 9 33 13 37 -rect 17 33 21 37 -rect 25 29 29 37 -rect 33 33 37 37 -rect 41 33 45 37 -rect 9 17 13 21 -rect 25 17 29 23 -rect 41 17 45 21 -<< pdcontact >> -rect 17 54 21 58 -rect 25 54 29 58 -rect 33 54 37 58 -<< psubstratepcontact >> -rect 25 9 29 13 -<< nsubstratencontact >> -rect 25 68 29 72 -<< polysilicon >> -rect 22 57 24 60 -rect 30 57 32 60 -rect 22 44 24 54 -rect 30 51 32 54 -rect 31 47 32 51 -rect 14 37 16 44 -rect 22 40 23 44 -rect 22 37 24 40 -rect 30 37 32 47 -rect 38 37 40 44 -rect 14 31 16 33 -rect 38 31 40 33 -rect 14 23 16 24 -rect 22 23 24 29 -rect 30 23 32 29 -rect 38 23 40 24 -rect 14 15 16 17 -rect 22 15 24 17 -rect 30 15 32 17 -rect 38 15 40 17 -<< polycontact >> -rect 27 47 31 51 -rect 10 40 14 44 -rect 23 40 27 44 -rect 40 40 44 44 -rect 12 24 16 28 -rect 38 24 42 28 -<< metal1 >> -rect 0 68 25 72 -rect 29 68 54 72 -rect 0 61 54 65 -rect 10 44 14 61 -rect 29 54 33 58 -rect 17 51 20 54 -rect 17 47 27 51 -rect 17 37 20 47 -rect 34 44 37 54 -rect 27 40 37 44 -rect 40 44 44 61 -rect 34 37 37 40 -rect 6 33 9 37 -rect 45 33 48 37 -rect 25 23 29 29 -rect 25 13 29 17 -rect 0 9 25 13 -rect 29 9 54 13 -rect 0 2 16 6 -rect 20 2 34 6 -rect 38 2 54 6 -<< m2contact >> -rect 25 68 29 72 -rect 25 54 29 58 -rect 2 33 6 37 -rect 48 33 52 37 -rect 16 24 20 28 -rect 34 24 38 28 -rect 9 17 13 21 -rect 41 17 45 21 -rect 16 2 20 6 -rect 34 2 38 6 -<< metal2 >> -rect 2 37 6 72 -rect 2 0 6 33 -rect 9 21 13 72 -rect 25 58 29 68 -rect 9 0 13 17 -rect 16 6 20 24 -rect 34 6 38 24 -rect 41 21 45 72 -rect 41 0 45 17 -rect 48 37 52 72 -rect 48 0 52 33 -<< comment >> -rect 0 0 54 70 -<< labels >> -rlabel metal1 19 63 19 63 1 wl0 -rlabel metal1 19 70 19 70 5 vdd -rlabel metal1 27 4 27 4 1 wl1 -rlabel psubstratepcontact 27 11 27 11 1 gnd -rlabel metal2 4 7 4 7 2 bl0 -rlabel metal2 11 7 11 7 1 bl1 -rlabel metal2 43 7 43 7 1 br1 -rlabel metal2 50 7 50 7 8 br0 -rlabel polycontact 29 49 29 49 1 Q -rlabel polycontact 25 42 25 42 1 Q_bar -<< end >> diff --git a/technology/scn4m_subm/mag_lib/replica_cell_1rw_1r.mag b/technology/scn4m_subm/mag_lib/replica_cell_2rw.mag similarity index 100% rename from technology/scn4m_subm/mag_lib/replica_cell_1rw_1r.mag rename to technology/scn4m_subm/mag_lib/replica_cell_2rw.mag diff --git a/technology/scn4m_subm/mag_lib/replica_cell_6t.ext b/technology/scn4m_subm/mag_lib/replica_cell_6t.ext deleted file mode 100644 index 726cd738..00000000 --- a/technology/scn4m_subm/mag_lib/replica_cell_6t.ext +++ /dev/null @@ -1,35 +0,0 @@ -timestamp 1541443051 -version 8.2 -tech scmos -style TSMC0.35um(tsmc35)from:t11c -scale 1000 1 5 -resistclasses 3700 2800 1018000 1018000 1 6000 6000 80 70 80 40 -node "comment_0_0#" 0 0 0 0 bb 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -node "br" 6 1.40998e-14 96 -8 ndc 320 72 0 0 0 0 0 0 0 0 0 0 0 0 512 96 3456 464 0 0 0 0 -node "bl" 6 -8.88178e-16 40 -8 ndc 320 72 0 0 0 0 0 0 0 0 0 0 0 0 512 96 3200 432 0 0 0 0 -node "wl" 115 -2.89546e-13 -8 12 p 0 0 0 0 0 0 0 0 0 0 1536 360 0 0 2496 344 0 0 0 0 0 0 -node "a_36_40#" 140 -3.51719e-13 36 40 ndif 960 144 304 72 0 0 0 0 0 0 1984 424 0 0 2048 288 0 0 0 0 0 0 -node "gnd" 41 -27.888 -32 -32 pw 1792 240 512 128 0 0 0 0 29600 696 0 0 0 0 2688 400 6400 864 0 0 0 0 -equiv "gnd" "gnd" -node "vdd" 2517 2596 -32 116 nw 1216 208 1104 248 17600 576 0 0 0 0 2000 456 0 0 5632 736 256 64 0 0 0 0 -cap "vdd" "br" 442.06 -cap "bl" "wl" 189.768 -cap "gnd" "br" 698.471 -cap "bl" "a_36_40#" 29.396 -cap "wl" "a_36_40#" 108.364 -cap "bl" "vdd" 239.22 -cap "bl" "gnd" 712.11 -cap "wl" "vdd" 108.364 -cap "wl" "gnd" 1198.41 -cap "bl" "br" 27.492 -cap "a_36_40#" "vdd" 981.901 -cap "wl" "br" 189.768 -cap "a_36_40#" "gnd" 401.284 -cap "vdd" "gnd" 1390.52 -cap "a_36_40#" "br" 17.59 -fet nfet 96 12 97 13 128 48 "gnd" "wl" 16 0 "br" 16 0 "vdd" 16 0 -fet nfet 40 12 41 13 128 48 "gnd" "wl" 16 0 "bl" 16 0 "a_36_40#" 16 0 -fet nfet 116 40 117 41 256 80 "gnd" "a_36_40#" 16 0 "vdd" 32 0 "gnd" 32 0 -fet nfet 28 40 29 41 256 80 "gnd" "vdd" 16 0 "gnd" 32 0 "a_36_40#" 32 0 -fet pfet 108 148 109 149 192 56 "vdd" "a_36_40#" 32 0 "vdd" 24 0 -fet pfet 28 148 29 149 192 56 "vdd" "vdd" 32 0 "vdd" 12 0 "a_36_40#" 12 0 diff --git a/technology/scn4m_subm/mag_lib/replica_cell_6t.spice b/technology/scn4m_subm/mag_lib/replica_cell_6t.spice deleted file mode 100644 index bb64476f..00000000 --- a/technology/scn4m_subm/mag_lib/replica_cell_6t.spice +++ /dev/null @@ -1,16 +0,0 @@ -* SPICE3 file created from replica_cell_6t.ext - technology: scmos - -M1000 a_36_40# vdd vdd vdd pfet w=0.6u l=0.8u -+ ad=0.76p pd=3.6u as=2.76p ps=12.4u -** SOURCE/DRAIN TIED -M1001 vdd a_36_40# vdd vdd pfet w=0.8u l=0.6u -+ ad=0p pd=0u as=0p ps=0u -M1002 a_36_40# vdd gnd gnd nfet w=1.6u l=0.4u -+ ad=2.4p pd=7.2u as=4.48p ps=12u -M1003 gnd a_36_40# vdd gnd nfet w=1.6u l=0.4u -+ ad=0p pd=0u as=3.04p ps=10.4u -M1004 a_36_40# wl bl gnd nfet w=0.8u l=0.4u -+ ad=0p pd=0u as=0.8p ps=3.6u -M1005 vdd wl br gnd nfet w=0.8u l=0.4u -+ ad=0p pd=0u as=0.8p ps=3.6u -C0 vdd 0 2.60fF diff --git a/technology/scn4m_subm/sp_lib/cell_6t.sp b/technology/scn4m_subm/sp_lib/cell_1rw.sp similarity index 63% rename from technology/scn4m_subm/sp_lib/cell_6t.sp rename to technology/scn4m_subm/sp_lib/cell_1rw.sp index dc724007..fafbe7ef 100644 --- a/technology/scn4m_subm/sp_lib/cell_6t.sp +++ b/technology/scn4m_subm/sp_lib/cell_1rw.sp @@ -1,7 +1,7 @@ -*********************** "cell_6t" ****************************** -.SUBCKT cell_6t bl br wl vdd gnd -* SPICE3 file created from cell_6t.ext - technology: scmos +*********************** "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 diff --git a/technology/scn4m_subm/sp_lib/cell_1w_1r.sp b/technology/scn4m_subm/sp_lib/cell_1w_1r.sp deleted file mode 100644 index b40f589a..00000000 --- a/technology/scn4m_subm/sp_lib/cell_1w_1r.sp +++ /dev/null @@ -1,14 +0,0 @@ - -.SUBCKT cell_1w_1r bl0 br0 bl1 br1 wl0 wl1 vdd gnd -MM9 RA_to_R_right wl1 br1 gnd n w=1.2u l=0.4u -MM8 RA_to_R_right Q gnd gnd n w=1.2u l=0.4u -MM7 RA_to_R_left Q_bar gnd gnd n w=1.2u l=0.4u -MM6 RA_to_R_left wl1 bl1 gnd n w=1.2u l=0.4u -MM5 Q wl0 bl0 gnd n w=0.8u l=0.4u -MM4 Q_bar wl0 br0 gnd n w=0.8u l=0.4u -MM1 Q Q_bar gnd gnd n w=1.6u l=0.4u -MM0 Q_bar Q gnd gnd n w=1.6u l=0.4u -MM3 Q Q_bar vdd vdd p w=0.6u l=0.4u -MM2 Q_bar Q vdd vdd p w=0.6u l=0.4u -.ENDS - diff --git a/technology/scn4m_subm/sp_lib/dummy_cell_6t.sp b/technology/scn4m_subm/sp_lib/dummy_cell_1rw.sp similarity index 72% rename from technology/scn4m_subm/sp_lib/dummy_cell_6t.sp rename to technology/scn4m_subm/sp_lib/dummy_cell_1rw.sp index c5b6ff9d..c487b572 100644 --- a/technology/scn4m_subm/sp_lib/dummy_cell_6t.sp +++ b/technology/scn4m_subm/sp_lib/dummy_cell_1rw.sp @@ -1,6 +1,6 @@ -*********************** "dummy_cell_6t" ****************************** -.SUBCKT dummy_cell_6t bl br wl vdd gnd +*********************** "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 diff --git a/technology/scn4m_subm/sp_lib/dummy_cell_1w_1r.sp b/technology/scn4m_subm/sp_lib/dummy_cell_1w_1r.sp deleted file mode 100644 index f5424998..00000000 --- a/technology/scn4m_subm/sp_lib/dummy_cell_1w_1r.sp +++ /dev/null @@ -1,14 +0,0 @@ - -.SUBCKT dummy_cell_1w_1r bl0 br0 bl1 br1 wl0 wl1 vdd gnd -MM9 RA_to_R_right wl1 br1_noconn gnd n w=1.2u l=0.4u -MM8 RA_to_R_right Q gnd gnd n w=1.2u l=0.4u -MM7 RA_to_R_left Q_bar gnd gnd n w=1.2u l=0.4u -MM6 RA_to_R_left wl1 bl1_noconn gnd n w=1.2u l=0.4u -MM5 Q wl0 bl0_noconn gnd n w=0.8u l=0.4u -MM4 Q_bar wl0 br0_noconn gnd n w=0.8u l=0.4u -MM1 Q Q_bar gnd gnd n w=1.6u l=0.4u -MM0 Q_bar Q gnd gnd n w=1.6u l=0.4u -MM3 Q Q_bar vdd vdd p w=0.6u l=0.4u -MM2 Q_bar Q vdd vdd p w=0.6u l=0.4u -.ENDS - diff --git a/technology/scn4m_subm/sp_lib/replica_cell_6t.sp b/technology/scn4m_subm/sp_lib/replica_cell_1rw.sp similarity index 61% rename from technology/scn4m_subm/sp_lib/replica_cell_6t.sp rename to technology/scn4m_subm/sp_lib/replica_cell_1rw.sp index a9d41398..f453477a 100644 --- a/technology/scn4m_subm/sp_lib/replica_cell_6t.sp +++ b/technology/scn4m_subm/sp_lib/replica_cell_1rw.sp @@ -1,7 +1,7 @@ -*********************** "cell_6t" ****************************** -.SUBCKT replica_cell_6t bl br wl vdd gnd -* SPICE3 file created from cell_6t.ext - technology: scmos +*********************** "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 diff --git a/technology/scn4m_subm/sp_lib/replica_cell_1w_1r.sp b/technology/scn4m_subm/sp_lib/replica_cell_1w_1r.sp deleted file mode 100644 index 6c2d3c1b..00000000 --- a/technology/scn4m_subm/sp_lib/replica_cell_1w_1r.sp +++ /dev/null @@ -1,14 +0,0 @@ - -.SUBCKT replica_cell_1w_1r bl0 br0 bl1 br1 wl0 wl1 vdd gnd -MM9 RA_to_R_right wl1 br1 gnd n w=1.2u l=0.4u -MM8 RA_to_R_right Q gnd gnd n w=1.2u l=0.4u -MM7 RA_to_R_left vdd gnd gnd n w=1.2u l=0.4u -MM6 RA_to_R_left wl1 bl1 gnd n w=1.2u l=0.4u -MM5 Q wl0 bl0 gnd n w=0.8u l=0.4u -MM4 vdd wl0 br0 gnd n w=0.8u l=0.4u -MM1 Q vdd gnd gnd n w=1.6u l=0.4u -MM0 vdd Q gnd gnd n w=1.6u l=0.4u -MM3 Q vdd vdd vdd p w=0.6u l=0.4u -MM2 vdd Q vdd vdd p w=0.6u l=0.4u -.ENDS - diff --git a/technology/scn4m_subm/sue_lib/cell_6t.sue b/technology/scn4m_subm/sue_lib/cell_6t.sue deleted file mode 100644 index 427b1d05..00000000 --- a/technology/scn4m_subm/sue_lib/cell_6t.sue +++ /dev/null @@ -1,46 +0,0 @@ -# SUE version MMI_SUE5.0.7 - -proc SCHEMATIC_cell_6t {} { - make inout -name BL -origin {190 360} - make inout -name BR -origin {830 360} - make input -name WL -origin {240 120} - make global -orient RXY -name vdd -origin {520 160} - make global -name gnd -origin {510 600} - make pmos -orient RY -W 0.9u -L 1.2u -origin {630 230} - make pmos -orient RXY -W 0.9u -L 1.2u -origin {400 230} - make nmos -orient R90 -W 1.2 -L 0.6u -origin {740 360} - make nmos -orient R90X -W 1.2 -L 0.6u -origin {270 360} - make nmos -W 2.4u -L 0.6u -origin {630 490} - make nmos -orient RX -W 2.4u -L 0.6u -origin {400 490} - make_wire 630 550 630 530 - make_wire 400 530 400 550 - make_wire 400 190 400 170 - make_wire 630 170 630 190 - make_wire 400 360 400 270 - make_wire 310 360 400 360 - make_wire 630 360 630 450 - make_wire 630 360 700 360 - make_wire 270 300 270 120 - make_wire 270 120 740 120 - make_wire 740 120 740 300 - make_wire 230 360 190 360 - make_wire 780 360 830 360 - make_wire 510 550 400 550 - make_wire 510 550 630 550 - make_wire 510 550 510 600 - make_wire 520 170 400 170 - make_wire 520 170 630 170 - make_wire 520 160 520 170 - make_wire 240 120 270 120 - make_wire 460 290 630 290 - make_wire 460 290 460 490 - make_wire 460 290 460 230 - make_wire 630 290 630 360 - make_wire 630 290 630 270 - make_wire 570 420 400 420 - make_wire 570 420 570 490 - make_wire 570 420 570 230 - make_wire 400 420 400 360 - make_wire 400 420 400 450 -} - diff --git a/technology/scn4m_subm/sue_lib/ms_flop.sue b/technology/scn4m_subm/sue_lib/ms_flop.sue deleted file mode 100644 index 85cc8e03..00000000 --- a/technology/scn4m_subm/sue_lib/ms_flop.sue +++ /dev/null @@ -1,84 +0,0 @@ -# SUE version MMI_SUE5.0.7 - -proc SCHEMATIC_ms_flop {} { - make pmos -orient R90X -W 1.8u -L 0.6u -origin {40 250} - make nmos -orient R270 -W 0.9u -L 0.6u -origin {40 380} - make inverter -WP 1.8u -LP 0.6u -WN 0.9u -LN 0.6u -origin {-270 540} - make inverter -WP 1.8u -LP 0.6u -WN 0.9u -LN 0.6u -origin {310 310} - make inverter -orient RX -WP 1.8u -LP 0.6u -WN 0.9u -LN 0.6u -origin {430 730} - make pmos -orient R90X -W 1.8u -L 0.6u -origin {190 670} - make nmos -orient R270 -W 0.9u -L 0.6u -origin {190 780} - make input -name clk -origin {-380 540} - make input -name din -origin {-370 320} - make pmos -orient R90X -W 1.8u -L 0.6u -origin {720 250} - make nmos -orient R270 -W 0.9u -L 0.6u -origin {720 380} - make inverter -WP 1.8u -LP 0.6u -WN 0.9u -LN 0.6u -origin {990 310} - make pmos -orient R90X -W 1.8u -L 0.6u -origin {870 670} - make nmos -orient R270 -W 0.9u -L 0.6u -origin {870 780} - make inverter -WP 1.8u -LP 0.6u -WN 0.9u -LN 0.6u -origin {620 540} - make output -name dout -origin {1410 310} - make output -name dout_bar -origin {1430 930} - make inverter -orient RX -WP 1.8u -LP 0.6u -WN 0.9u -LN 0.6u -origin {1110 730} - make_wire -330 160 40 160 - make_wire 40 160 40 190 - make_wire -370 320 0 320 - make_wire 360 310 480 310 - make_wire 460 730 480 730 - make_wire 230 730 380 730 - make_wire 100 310 100 720 - make_wire 100 720 150 720 - make_wire 100 310 80 310 - make_wire 100 310 280 310 - make_wire 0 250 0 320 - make_wire 0 320 0 380 - make_wire 80 250 80 310 - make_wire 80 310 80 380 - make_wire 40 440 40 540 - make_wire -330 840 190 840 - make_wire 230 670 230 730 - make_wire 230 730 230 780 - make_wire 150 670 150 720 - make_wire 150 720 150 780 - make_wire 190 540 190 610 - make_wire -330 540 -330 840 - make_wire -220 540 40 540 - make_wire 40 540 190 540 - make_wire -380 540 -330 540 - make_wire -330 540 -300 540 - make_wire -330 540 -330 160 - make_wire 720 160 720 190 - make_wire 1140 730 1160 730 - make_wire 780 310 780 720 - make_wire 780 720 830 720 - make_wire 780 310 760 310 - make_wire 780 310 960 310 - make_wire 680 320 680 380 - make_wire 760 250 760 310 - make_wire 760 310 760 380 - make_wire 720 440 720 540 - make_wire 910 670 910 730 - make_wire 910 730 910 780 - make_wire 830 670 830 720 - make_wire 830 720 830 780 - make_wire 870 540 870 610 - make_wire 720 540 870 540 - make_wire 670 540 720 540 - make_wire 480 310 480 730 - make_wire 1160 310 1160 730 - make_wire 530 540 530 160 - make_wire 530 160 720 160 - make_wire 530 540 190 540 - make_wire 530 540 590 540 - make_wire 530 540 530 840 - make_wire 530 840 870 840 - make_wire 680 310 480 310 - make_wire 680 310 680 250 - make_wire 680 310 680 320 - make_wire 950 730 910 730 - make_wire 950 730 1060 730 - make_wire 1040 310 1160 310 - make_wire 1160 310 1410 310 - make_wire 950 930 1430 930 - make_wire 950 730 950 930 -} - diff --git a/technology/scn4m_subm/sue_lib/replica_cell_6t.sue b/technology/scn4m_subm/sue_lib/replica_cell_6t.sue deleted file mode 100644 index 56e72056..00000000 --- a/technology/scn4m_subm/sue_lib/replica_cell_6t.sue +++ /dev/null @@ -1,49 +0,0 @@ -# SUE version MMI_SUE5.0.7 - -proc SCHEMATIC_replica_cell_6t {} { - make inout -name BL -origin {190 360} - make inout -name BR -origin {830 360} - make input -name WL -origin {240 120} - make global -orient RXY -name vdd -origin {520 160} - make global -name gnd -origin {510 600} - make pmos -orient RY -W 0.9u -L 1.2u -origin {630 230} - make pmos -orient RXY -W 0.9u -L 1.2u -origin {400 230} - make nmos -orient R90 -W 1.2 -L 0.6u -origin {740 360} - make nmos -orient R90X -W 1.2 -L 0.6u -origin {270 360} - make nmos -W 2.4u -L 0.6u -origin {630 490} - make nmos -orient RX -W 2.4u -L 0.6u -origin {400 490} - make_wire 630 550 630 530 - make_wire 400 530 400 550 - make_wire 400 190 400 170 - make_wire 630 170 630 190 - make_wire 400 360 400 270 - make_wire 630 360 630 450 - make_wire 630 360 700 360 - make_wire 270 300 270 120 - make_wire 270 120 740 120 - make_wire 740 120 740 300 - make_wire 230 360 190 360 - make_wire 780 360 830 360 - make_wire 510 550 400 550 - make_wire 510 550 630 550 - make_wire 510 550 510 600 - make_wire 520 170 400 170 - make_wire 520 170 630 170 - make_wire 520 160 520 170 - make_wire 240 120 270 120 - make_wire 460 290 630 290 - make_wire 460 290 460 490 - make_wire 460 290 460 230 - make_wire 630 290 630 360 - make_wire 630 290 630 270 - make_wire 570 420 400 420 - make_wire 570 420 570 490 - make_wire 570 420 570 230 - make_wire 400 420 400 360 - make_wire 400 420 400 450 - make_wire 320 360 320 550 - make_wire 320 550 400 550 - make_wire 320 360 310 360 - make_wire 320 360 400 360 -} - diff --git a/technology/scn4m_subm/sue_lib/sense_amp.sue b/technology/scn4m_subm/sue_lib/sense_amp.sue deleted file mode 100644 index 4d29e11a..00000000 --- a/technology/scn4m_subm/sue_lib/sense_amp.sue +++ /dev/null @@ -1,52 +0,0 @@ -# SUE version MMI_SUE5.0.7 - -proc SCHEMATIC_sense_amp {} { - make inout -name BL -origin {260 10} - make global -orient RXY -name vdd -origin {490 170} - make global -name gnd -origin {480 660} - make input -name sclk -origin {180 610} - make nmos -W 3.9u -L 0.6u -origin {600 500} - make nmos -orient RX -W 3.9u -L 0.6u -origin {370 500} - make pmos -orient RY -W 3u -L 0.6u -origin {600 240} - make pmos -orient RXY -W 3u -L 0.6u -origin {370 240} - make nmos -W 3.9u -L 0.6u -origin {480 610} - make inout -name BR -origin {710 20} - make pmos -W 3.9u -L 0.6u -origin {710 90} - make pmos -orient RX -W 3.9u -L 0.6u -origin {260 90} - make output -orient RXY -name dout -origin {110 370} - make_wire 600 560 600 540 - make_wire 370 540 370 560 - make_wire 370 200 370 180 - make_wire 600 180 600 200 - make_wire 490 180 370 180 - make_wire 490 180 600 180 - make_wire 490 170 490 180 - make_wire 430 300 600 300 - make_wire 430 300 430 500 - make_wire 430 300 430 240 - make_wire 600 300 600 280 - make_wire 540 430 370 430 - make_wire 540 430 540 500 - make_wire 540 430 540 240 - make_wire 370 430 370 460 - make_wire 480 560 600 560 - make_wire 480 560 370 560 - make_wire 480 560 480 570 - make_wire 480 650 480 660 - make_wire 420 610 180 610 - make_wire 650 90 320 90 - make_wire 600 360 710 360 - make_wire 710 360 710 130 - make_wire 600 360 600 300 - make_wire 600 360 600 460 - make_wire 370 370 260 370 - make_wire 260 370 260 130 - make_wire 370 370 370 430 - make_wire 370 370 370 280 - make_wire 260 10 260 50 - make_wire 710 20 710 50 - make_wire 320 90 180 90 - make_wire 180 90 180 610 - make_wire 110 370 260 370 -} - diff --git a/technology/scn4m_subm/sue_lib/tri_gate.sue b/technology/scn4m_subm/sue_lib/tri_gate.sue deleted file mode 100644 index d296171f..00000000 --- a/technology/scn4m_subm/sue_lib/tri_gate.sue +++ /dev/null @@ -1,37 +0,0 @@ -# SUE version MMI_SUE5.0.7 - -proc SCHEMATIC_tri_gate {} { - make global -orient RXY -name vdd -origin {630 150} - make global -name gnd -origin {630 570} - make input -name tri_in -origin {320 340} - make output -name tri_out -origin {690 360} - make input -name en -origin {570 410} - make input -name en_bar -origin {570 310} - make nmos -W 1.2u -L 0.6u -origin {630 490} - make nmos -W 1.2u -L 0.6u -origin {630 410} - make pmos -orient RY -W 2.4u -L 0.6u -origin {630 310} - make pmos -orient RY -W 2.4u -L 0.6u -origin {630 230} - make pmos -orient RY -W 2.4u -L 0.6u -origin {380 290} - make nmos -W 1.2u -L 0.6u -origin {380 400} - make_wire 570 490 470 490 - make_wire 470 230 570 230 - make_wire 630 550 380 550 - make_wire 380 550 380 440 - make_wire 630 550 630 570 - make_wire 630 550 630 530 - make_wire 630 170 380 170 - make_wire 380 170 380 250 - make_wire 630 170 630 190 - make_wire 630 170 630 150 - make_wire 320 340 320 400 - make_wire 320 340 320 290 - make_wire 380 340 470 340 - make_wire 380 340 380 330 - make_wire 380 340 380 360 - make_wire 470 340 470 490 - make_wire 470 340 470 230 - make_wire 630 360 630 350 - make_wire 630 360 630 370 - make_wire 630 360 690 360 -} - diff --git a/technology/scn4m_subm/sue_lib/write_driver.sue b/technology/scn4m_subm/sue_lib/write_driver.sue deleted file mode 100644 index de3909a7..00000000 --- a/technology/scn4m_subm/sue_lib/write_driver.sue +++ /dev/null @@ -1,44 +0,0 @@ -# SUE version MMI_SUE5.0.7 - -proc SCHEMATIC_write_driver {} { - make inout -name BL -origin {550 260} - make inout -name BR -origin {830 250} - make inverter -WP 2.1u -LP 0.6u -WN 1.2u -LN 0.6u -origin {280 520} - make nand2 -WP 2.1u -WN 2.1u -origin {90 360} - make inverter -WP 2.1u -LP 0.6u -WN 1.2u -LN 0.6u -origin {270 360} - make nmos -W 3.6u -L 0.6u -origin {830 410} - make nmos -W 3.6u -L 0.6u -origin {710 610} - make global -name gnd -origin {710 690} - make nand2 -WP 2.1u -WN 2.1u -origin {90 520} - make nmos -W 3.6u -L 0.6u -origin {550 410} - make input -name wen -origin {-290 340} - make input -name din -origin {-290 380} - make inverter -WP 2.1u -LP 0.6u -WN 1.2u -LN 0.6u -origin {-80 540} - make_wire 160 360 240 360 - make_wire 830 250 830 370 - make_wire 550 260 550 370 - make_wire 550 450 550 560 - make_wire 550 560 710 560 - make_wire 710 560 710 570 - make_wire 710 560 830 560 - make_wire 830 560 830 450 - make_wire 710 650 710 690 - make_wire 250 520 160 520 - make_wire 770 410 770 520 - make_wire 770 520 330 520 - make_wire 320 360 490 360 - make_wire 490 360 490 410 - make_wire -180 380 -290 380 - make_wire -180 380 70 380 - make_wire -180 540 -110 540 - make_wire -180 380 -180 540 - make_wire -30 540 70 540 - make_wire 20 340 20 500 - make_wire 20 500 70 500 - make_wire 20 340 70 340 - make_wire -240 340 -240 610 - make_wire -240 610 650 610 - make_wire -240 340 20 340 - make_wire -240 340 -290 340 -} - diff --git a/technology/scn4m_subm/tech/tech.py b/technology/scn4m_subm/tech/tech.py index 724e3d50..e6a54e6e 100644 --- a/technology/scn4m_subm/tech/tech.py +++ b/technology/scn4m_subm/tech/tech.py @@ -33,12 +33,6 @@ cell_properties = cell_properties() cell_properties.bitcell.mirror.x = True cell_properties.bitcell.mirror.y = False -cell_properties.names["bitcell_1port"] = "cell_6t" -cell_properties.names["dummy_bitcell_1port"] = "dummy_cell_6t" -cell_properties.names["replcia_bitcell_1port"] = "replica_cell_6t" -cell_properties.names["bitcell_2port"] = "cell_2rw" -cell_properties.names["dummy_bitcell_2port"] = "dummy_cell_2rw" -cell_properties.names["replica_bitcell_2port"] = "replica_cell_2rw" ################################################### # Custom cell properties From 802143012240bdc23c90f71a3965982b88bba249 Mon Sep 17 00:00:00 2001 From: mrg Date: Fri, 13 Nov 2020 15:55:55 -0800 Subject: [PATCH 16/31] Fix pbitcell erros --- compiler/base/custom_cell_properties.py | 208 ++++++++++----------- compiler/base/design.py | 26 ++- compiler/base/hierarchy_spice.py | 9 +- compiler/bitcells/bitcell_1port.py | 26 +-- compiler/bitcells/bitcell_2port.py | 59 +++--- compiler/bitcells/bitcell_base.py | 17 +- compiler/bitcells/dummy_bitcell_1port.py | 9 +- compiler/bitcells/dummy_bitcell_2port.py | 13 +- compiler/bitcells/pbitcell.py | 4 +- compiler/bitcells/replica_bitcell_1port.py | 9 +- compiler/bitcells/replica_bitcell_2port.py | 12 +- compiler/custom/dff.py | 29 +-- compiler/custom/inv_dec.py | 22 +-- compiler/custom/nand2_dec.py | 20 +- compiler/custom/nand3_dec.py | 20 +- compiler/custom/nand4_dec.py | 22 +-- compiler/custom/sense_amp.py | 24 +-- compiler/custom/tri_gate.py | 22 +-- compiler/custom/write_driver.py | 27 +-- compiler/modules/bitcell_base_array.py | 5 +- compiler/modules/col_cap_array.py | 9 +- compiler/modules/control_logic.py | 3 - compiler/modules/dff_array.py | 2 +- compiler/modules/dff_buf.py | 38 ++-- compiler/modules/dff_buf_array.py | 9 +- compiler/modules/precharge_array.py | 5 +- compiler/modules/replica_bitcell_array.py | 40 +--- compiler/modules/replica_column.py | 30 +-- compiler/modules/sense_amp_array.py | 6 +- compiler/modules/write_driver_array.py | 5 +- technology/freepdk45/tech/tech.py | 3 - technology/scn4m_subm/tech/tech.py | 3 - 32 files changed, 236 insertions(+), 500 deletions(-) diff --git a/compiler/base/custom_cell_properties.py b/compiler/base/custom_cell_properties.py index eafad33a..5c5947d9 100644 --- a/compiler/base/custom_cell_properties.py +++ b/compiler/base/custom_cell_properties.py @@ -5,9 +5,49 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -from globals import OPTS +class _cell: + def __init__(self, port_order, port_types, port_map=None, hard_cell=True, boundary_layer="boundary"): + # Specifies if this is a hard (i.e. GDS) cell + self._hard_cell = hard_cell + # Specifies the order in the spice modules + self._port_order = port_order + # Specifies the port directions + self._port_types = port_types + # Specifies a map from OpenRAM names to cell names + # by default it is 1:1 + if not port_map: + port_map = {} + for pin in port_order: + port_map[pin] = pin + self._pins = _pins(port_map) + else: + self._pins = _pins(port_map) + self._port_names = [getattr(self._pins, x) for x in self._port_order] + self._boundary_layer = boundary_layer + + @property + def pin(self): + return self._pins + + @property + def hard_cell(self): + return self._hard_cell + + @property + def port_names(self): + return self._port_names + + @property + def port_types(self): + return self._port_types + + @property + def boundary_layer(self): + return self._boundary_layer + + class _pins: def __init__(self, pin_dict): # make the pins elements of the class to allow "." access. @@ -16,20 +56,6 @@ class _pins: self.__dict__[k] = v -class _cell: - def __init__(self, pin_dict): - pin_dict.update(self._default_power_pins()) - self._pins = _pins(pin_dict) - - @property - def pin(self): - return self._pins - - def _default_power_pins(self): - return {'vdd': 'vdd', - 'gnd': 'gnd'} - - class _mirror_axis: def __init__(self, x, y): self.x = x @@ -47,65 +73,38 @@ class _pgate: self.add_implants = add_implants -class _bitcell: - def __init__(self, mirror, cell_1port, cell_2port): - self.mirror = mirror - self._1rw = cell_1port - self._2rw = cell_2port +class _bitcell(_cell): + def __init__(self, port_order, port_types, port_map=None, storage_nets=["Q", "Q_bar"], mirror=None, end_caps=False): + super().__init__(port_order, port_types, port_map) - def _default(): - axis = _mirror_axis(True, False) - - cell_1port = _cell({'bl': 'bl', - 'br': 'br', - 'wl': 'wl'}) - - cell_2port = _cell({'bl0': 'bl0', - 'br0': 'br0', - 'bl1': 'bl1', - 'br1': 'br1', - 'wl0': 'wl0', - 'wl1': 'wl1'}) - - return _bitcell(cell_1port=cell_1port, - cell_2port=cell_2port, - mirror=axis) + self._end_caps = end_caps + + if not mirror: + self._mirror = _mirror_axis(True, False) + else: + self._mirror = mirror + self._storage_nets = storage_nets + @property - def cell_1port(self): - return self._1rw - + def end_caps(self): + return self._end_caps + @property - def cell_2port(self): - return self._2rw + def mirror(self): + return self._mirror + + @property + def storage_nets(self): + return self._storage_nets - -class _dff: - def __init__(self, use_custom_ports, custom_port_list, custom_type_list, clk_pin): - self.use_custom_ports = use_custom_ports - self.custom_port_list = custom_port_list - self.custom_type_list = custom_type_list + +class _dff(_cell): + def __init__(self, clk_pin, port_order, port_types, port_map=None, hard_cell=True): + super().__init__(port_order, port_types, port_map, hard_cell) self.clk_pin = clk_pin - -class _dff_buff: - def __init__(self, use_custom_ports, custom_buff_ports, add_body_contacts): - self.use_custom_ports = use_custom_ports - self.buf_ports = custom_buff_ports - self.add_body_contacts = add_body_contacts - - -class _dff_buff_array: - def __init__(self, use_custom_ports, add_body_contacts): - self.use_custom_ports = use_custom_ports - self.add_body_contacts = add_body_contacts - - -class _bitcell_array: - def __init__(self, use_custom_cell_arrangement): - self.use_custom_cell_arrangement = use_custom_cell_arrangement - - + class cell_properties(): """ This contains meta information about the custom designed cells. For @@ -125,41 +124,41 @@ class cell_properties(): self.names["col_cap_bitcell_2port"] = "col_cap_cell_2rw" self.names["row_cap_bitcell_1port"] = "row_cap_cell_1rw" self.names["row_cap_bitcell_2port"] = "row_cap_cell_2rw" - - self._bitcell = _bitcell._default() self._ptx = _ptx(model_is_subckt=False, bin_spice_models=False) self._pgate = _pgate(add_implants=False) - self._dff = _dff(use_custom_ports=False, - custom_port_list=["D", "Q", "clk", "vdd", "gnd"], - custom_type_list=["INPUT", "OUTPUT", "INPUT", "POWER", "GROUND"], - clk_pin="clk") + self._nand2_dec = _cell(["A", "B", "Z", "vdd", "gnd"], + ["INPUT", "INPUT", "OUTPUT", "POWER", "GROUND"]) + + self._nand2_dec = _cell(["A", "B", "C", "Z", "vdd", "gnd"], + ["INPUT", "INPUT", "INPUT", "OUTPUT", "POWER", "GROUND"]) + + self._nand2_dec = _cell(["A", "B", "C", "D", "Z", "vdd", "gnd"], + ["INPUT", "INPUT", "INPUT", "INPUT", "OUTPUT", "POWER", "GROUND"]) + + self._dff = _dff("clk", + ["D", "Q", "clk", "vdd", "gnd"], + ["INPUT", "OUTPUT", "INPUT", "POWER", "GROUND"]) - self._dff_buff = _dff_buff(use_custom_ports=False, - custom_buff_ports=["D", "qint", "clk", "vdd", "gnd"], - add_body_contacts=False) + self._dff_buf = _dff("clk", + ["D", "Q", "Qb", "clk", "vdd", "gnd"], + ["INPUT", "OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"], + hard_cell=False) + + self._write_driver = _cell(['din', 'bl', 'br', 'en', 'vdd', 'gnd'], + ["INPUT", "OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"]) - self._dff_buff_array = _dff_buff_array(use_custom_ports=False, - add_body_contacts=False) + self._sense_amp = _cell(['bl', 'br', 'dout', 'en', 'vdd', 'gnd'], + ["INPUT", "INPUT", "OUTPUT", "INPUT", "POWER", "GROUND"]) - self._write_driver = _cell({'din': 'din', - 'bl': 'bl', - 'br': 'br', - 'en': 'en'}) + self._bitcell_1port = _bitcell(["bl", "br", "wl", "vdd", "gnd"], + ["OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"]) - self._sense_amp = _cell({'bl': 'bl', - 'br': 'br', - 'dout': 'dout', - 'en': 'en'}) - - self._bitcell_array = _bitcell_array(use_custom_cell_arrangement=[]) - - @property - def bitcell(self): - return self._bitcell + self._bitcell_2port = _bitcell(["bl0", "br0", "bl1", "br1", "wl0", "wl1", "vdd", "gnd"], + ["OUTPUT", "OUTPUT", "OUTPUT", "OUTPUT", "INPUT", "INPUT", "POWER", "GROUND"]) @property def ptx(self): @@ -174,13 +173,9 @@ class cell_properties(): return self._dff @property - def dff_buff(self): - return self._dff_buff - - @property - def dff_buff_array(self): - return self._dff_buff_array - + def dff_buf(self): + return self._dff_buf + @property def write_driver(self): return self._write_driver @@ -190,13 +185,10 @@ class cell_properties(): return self._sense_amp @property - def bitcell_array(self): - return self._bitcell_array + def bitcell_1port(self): + return self._bitcell_1port + + @property + def bitcell_2port(self): + return self._bitcell_2port - def compare_ports(self, port_list): - use_custom_arrangement = False - for ports in port_list: - if ports == "{}R_{}W_{}RW".format(OPTS.num_r_ports, OPTS.num_w_ports, OPTS.num_rw_ports): - use_custom_arrangement = True - break - return use_custom_arrangement diff --git a/compiler/base/design.py b/compiler/base/design.py index 93169f6a..98c03981 100644 --- a/compiler/base/design.py +++ b/compiler/base/design.py @@ -6,8 +6,9 @@ # All rights reserved. # from hierarchy_design import hierarchy_design -from utils import round_to_grid +import utils import contact +from tech import GDS, layer from tech import preferred_directions from tech import cell_properties as props from globals import OPTS @@ -31,6 +32,26 @@ class design(hierarchy_design): cell_name = name super().__init__(name, cell_name) + # This means it is a custom cell... + if hasattr(props, name): + prop = getattr(props, name) + if prop.hard_cell: + # The pins get added from the spice file + 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)) + self.add_pin_types(prop.port_types) + + (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.cell_name, + GDS["unit"]) + + self.width = width + self.height = height + self.setup_multiport_constants() def check_pins(self): @@ -232,8 +253,7 @@ class design(hierarchy_design): #print(contact1) pitch = contact_width + layer_space - return round_to_grid(pitch) - + return utils.round_to_grid(pitch) def setup_multiport_constants(self): """ diff --git a/compiler/base/hierarchy_spice.py b/compiler/base/hierarchy_spice.py index 340cf074..60d80513 100644 --- a/compiler/base/hierarchy_spice.py +++ b/compiler/base/hierarchy_spice.py @@ -78,6 +78,7 @@ class spice(): """ Adds a pin_list to the pins list """ # The 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: for pin in pin_list: debug.check(pin_type in self.valid_signal_types, @@ -100,12 +101,12 @@ class spice(): Typically, should only be used for handmade cells. """ # This only works if self.pins == bitcell.pin_names - if self.pin_names != self.pins: - debug.error("{} spice subcircuit port names do not match pin_names\ + 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, self.pin_names), 1) - self.pin_type = {pin: type for pin, type in zip(self.pin_names, type_list)} + ".format(self.name, self.pins, type_list), 1) + self.pin_type = {pin: type for pin, type in zip(self.pins, type_list)} def get_pin_type(self, name): """ Returns the type of the signal pin. """ diff --git a/compiler/bitcells/bitcell_1port.py b/compiler/bitcells/bitcell_1port.py index 83098c55..e8f330f1 100644 --- a/compiler/bitcells/bitcell_1port.py +++ b/compiler/bitcells/bitcell_1port.py @@ -18,53 +18,43 @@ class bitcell_1port(bitcell_base.bitcell_base): library. """ - pin_names = [props.bitcell.cell_1port.pin.bl, - props.bitcell.cell_1port.pin.br, - props.bitcell.cell_1port.pin.wl, - props.bitcell.cell_1port.pin.vdd, - props.bitcell.cell_1port.pin.gnd] - type_list = ["OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"] - storage_nets = ['Q', 'Q_bar'] - def __init__(self, name): - super().__init__(name) + super().__init__(name, props.bitcell_1port) debug.info(2, "Create bitcell") - self.nets_match = self.do_nets_exist(self.storage_nets) - def get_all_wl_names(self): """ Creates a list of all wordline pin names """ - row_pins = [props.bitcell.cell_1port.pin.wl] + row_pins = [props.bitcell_1port.pin.wl] return row_pins def get_all_bitline_names(self): """ Creates a list of all bitline pin names (both bl and br) """ - pin = props.bitcell.cell_1port.pin + pin = props.bitcell_1port.pin column_pins = [pin.bl, pin.br] return column_pins def get_all_bl_names(self): """ Creates a list of all bl pins names """ - return [props.bitcell.cell_1port.pin.bl] + return [props.bitcell_1port.pin.bl] def get_all_br_names(self): """ Creates a list of all br pins names """ - return [props.bitcell.cell_1port.pin.br] + return [props.bitcell_1port.pin.br] def get_bl_name(self, port=0): """Get bl name""" debug.check(port == 0, "One port for bitcell only.") - return props.bitcell.cell_1port.pin.bl + return props.bitcell_1port.pin.bl def get_br_name(self, port=0): """Get bl name""" debug.check(port == 0, "One port for bitcell only.") - return props.bitcell.cell_1port.pin.br + return props.bitcell_1port.pin.br def get_wl_name(self, port=0): """Get wl name""" debug.check(port == 0, "One port for bitcell only.") - return props.bitcell.cell_1port.pin.wl + return props.bitcell_1port.pin.wl def build_graph(self, graph, inst_name, port_nets): """ diff --git a/compiler/bitcells/bitcell_2port.py b/compiler/bitcells/bitcell_2port.py index 827a23b0..2293cb71 100644 --- a/compiler/bitcells/bitcell_2port.py +++ b/compiler/bitcells/bitcell_2port.py @@ -18,35 +18,20 @@ class bitcell_2port(bitcell_base.bitcell_base): library. """ - pin_names = [props.bitcell.cell_2port.pin.bl0, - props.bitcell.cell_2port.pin.br0, - props.bitcell.cell_2port.pin.bl1, - props.bitcell.cell_2port.pin.br1, - props.bitcell.cell_2port.pin.wl0, - props.bitcell.cell_2port.pin.wl1, - props.bitcell.cell_2port.pin.vdd, - props.bitcell.cell_2port.pin.gnd] - type_list = ["OUTPUT", "OUTPUT", "OUTPUT", "OUTPUT", - "INPUT", "INPUT", "POWER", "GROUND"] - storage_nets = ['Q', 'Q_bar'] - def __init__(self, name): - super().__init__(name) + super().__init__(name, props.bitcell_2port) debug.info(2, "Create bitcell with 2 ports") - self.nets_match = self.do_nets_exist(self.storage_nets) - - pin_names = self.pin_names - self.bl_names = [pin_names[0], pin_names[2]] - self.br_names = [pin_names[1], pin_names[3]] - self.wl_names = [pin_names[4], pin_names[5]] + self.bl_names = [props.bitcell_2port.pin.bl0, props.bitcell_2port.pin.bl1] + self.br_names = [props.bitcell_2port.pin.br0, props.bitcell_2port.pin.br1] + self.wl_names = [props.bitcell_2port.pin.wl0, props.bitcell_2port.pin.wl1] def get_bitcell_pins(self, col, row): """ Creates a list of connections in the bitcell, indexed by column and row, for instance use in bitcell_array """ - pin_name = props.bitcell.cell_2port.pin + pin_name = props.bitcell_2port.pin bitcell_pins = ["{0}_{1}".format(pin_name.bl0, col), "{0}_{1}".format(pin_name.br0, col), "{0}_{1}".format(pin_name.bl1, col), @@ -59,43 +44,43 @@ class bitcell_2port(bitcell_base.bitcell_base): def get_all_wl_names(self): """ Creates a list of all wordline pin names """ - return [props.bitcell.cell_2port.pin.wl0, - props.bitcell.cell_2port.pin.wl1] + return [props.bitcell_2port.pin.wl0, + props.bitcell_2port.pin.wl1] def get_all_bitline_names(self): """ Creates a list of all bitline pin names (both bl and br) """ - return [props.bitcell.cell_2port.pin.bl0, - props.bitcell.cell_2port.pin.br0, - props.bitcell.cell_2port.pin.bl1, - props.bitcell.cell_2port.pin.br1] + return [props.bitcell_2port.pin.bl0, + props.bitcell_2port.pin.br0, + props.bitcell_2port.pin.bl1, + props.bitcell_2port.pin.br1] def get_all_bl_names(self): """ Creates a list of all bl pins names """ - return [props.bitcell.cell_2port.pin.bl0, - props.bitcell.cell_2port.pin.bl1] + return [props.bitcell_2port.pin.bl0, + props.bitcell_2port.pin.bl1] def get_all_br_names(self): """ Creates a list of all br pins names """ - return [props.bitcell.cell_2port.pin.br0, - props.bitcell.cell_2port.pin.br1] + return [props.bitcell_2port.pin.br0, + props.bitcell_2port.pin.br1] def get_read_bl_names(self): """ Creates a list of bl pin names associated with read ports """ - return [props.bitcell.cell_2port.pin.bl0, - props.bitcell.cell_2port.pin.bl1] + return [props.bitcell_2port.pin.bl0, + props.bitcell_2port.pin.bl1] def get_read_br_names(self): """ Creates a list of br pin names associated with read ports """ - return [props.bitcell.cell_2port.pin.br0, - props.bitcell.cell_2port.pin.br1] + return [props.bitcell_2port.pin.br0, + props.bitcell_2port.pin.br1] def get_write_bl_names(self): """ Creates a list of bl pin names associated with write ports """ - return [props.bitcell.cell_2port.pin.bl0] + return [props.bitcell_2port.pin.bl0] def get_write_br_names(self): """ Creates a list of br pin names asscociated with write ports""" - return [props.bitcell.cell_2port.pin.br1] + return [props.bitcell_2port.pin.br1] def get_bl_name(self, port=0): """Get bl name by port""" @@ -118,7 +103,7 @@ class bitcell_2port(bitcell_base.bitcell_base): pin_dict = {pin: port for pin, port in zip(self.pins, port_nets)} # Edges hardcoded here. Essentially wl->bl/br for both ports. # Port 0 edges - pins = props.bitcell.cell_2port.pin + pins = props.bitcell_2port.pin graph.add_edge(pin_dict[pins.wl0], pin_dict[pins.bl0], self) graph.add_edge(pin_dict[pins.wl0], pin_dict[pins.br0], self) # Port 1 edges diff --git a/compiler/bitcells/bitcell_base.py b/compiler/bitcells/bitcell_base.py index 5ae468b2..0e821774 100644 --- a/compiler/bitcells/bitcell_base.py +++ b/compiler/bitcells/bitcell_base.py @@ -18,19 +18,22 @@ class bitcell_base(design.design): """ Base bitcell parameters to be over-riden. """ - cell_size_layer = "boundary" - - def __init__(self, name, hard_cell=True): + def __init__(self, name, prop=None): design.design.__init__(self, name) - if hard_cell: + if prop: + self.pins = prop.port_names + self.add_pin_types(prop.port_types) + self.nets_match = self.do_nets_exist(prop.storage_nets) + self.mirror = prop.mirror + self.end_caps = prop.end_caps + (self.width, self.height) = utils.get_libcell_size(self.cell_name, GDS["unit"], - layer[self.cell_size_layer]) - self.pin_map = utils.get_libcell_pins(self.pin_names, + layer[prop.boundary_layer]) + self.pin_map = utils.get_libcell_pins(self.pins, self.cell_name, GDS["unit"]) - self.add_pin_types(self.type_list) def get_stage_effort(self, load): parasitic_delay = 1 diff --git a/compiler/bitcells/dummy_bitcell_1port.py b/compiler/bitcells/dummy_bitcell_1port.py index 5b54ff04..c6f98536 100644 --- a/compiler/bitcells/dummy_bitcell_1port.py +++ b/compiler/bitcells/dummy_bitcell_1port.py @@ -17,15 +17,8 @@ class dummy_bitcell_1port(bitcell_base.bitcell_base): the layout and netlist should be available in the technology library. """ - pin_names = [props.bitcell.cell_1port.pin.bl, - props.bitcell.cell_1port.pin.br, - props.bitcell.cell_1port.pin.wl, - props.bitcell.cell_1port.pin.vdd, - props.bitcell.cell_1port.pin.gnd] - type_list = ["OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"] - def __init__(self, name): - super().__init__(name) + super().__init__(name, props.bitcell_1port) debug.info(2, "Create dummy bitcell") diff --git a/compiler/bitcells/dummy_bitcell_2port.py b/compiler/bitcells/dummy_bitcell_2port.py index 64ca08fb..4d6d5c49 100644 --- a/compiler/bitcells/dummy_bitcell_2port.py +++ b/compiler/bitcells/dummy_bitcell_2port.py @@ -17,19 +17,8 @@ class dummy_bitcell_2port(bitcell_base.bitcell_base): is a hand-made cell, so the layout and netlist should be available in the technology library. """ - pin_names = [props.bitcell.cell_2port.pin.bl0, - props.bitcell.cell_2port.pin.br0, - props.bitcell.cell_2port.pin.bl1, - props.bitcell.cell_2port.pin.br1, - props.bitcell.cell_2port.pin.wl0, - props.bitcell.cell_2port.pin.wl1, - props.bitcell.cell_2port.pin.vdd, - props.bitcell.cell_2port.pin.gnd] - type_list = ["OUTPUT", "OUTPUT", "OUTPUT", "OUTPUT", - "INPUT", "INPUT", "POWER", "GROUND"] - def __init__(self, name): - super().__init__(name) + super().__init__(name, props.bitcel_2port) debug.info(2, "Create dummy bitcell 2 port object") diff --git a/compiler/bitcells/pbitcell.py b/compiler/bitcells/pbitcell.py index 120bb48e..61360e99 100644 --- a/compiler/bitcells/pbitcell.py +++ b/compiler/bitcells/pbitcell.py @@ -8,6 +8,7 @@ import contact import debug from tech import drc, parameter, layer +from tech import cell_properties as props from vector import vector from ptx import ptx from globals import OPTS @@ -29,8 +30,9 @@ class pbitcell(bitcell_base.bitcell_base): self.replica_bitcell = replica_bitcell self.dummy_bitcell = dummy_bitcell + self.mirror = props.bitcell_1port.mirror - bitcell_base.bitcell_base.__init__(self, name, hard_cell=False) + bitcell_base.bitcell_base.__init__(self, name) fmt_str = "{0} rw ports, {1} w ports and {2} r ports" info_string = fmt_str.format(self.num_rw_ports, self.num_w_ports, diff --git a/compiler/bitcells/replica_bitcell_1port.py b/compiler/bitcells/replica_bitcell_1port.py index 92b74c24..1f2826ec 100644 --- a/compiler/bitcells/replica_bitcell_1port.py +++ b/compiler/bitcells/replica_bitcell_1port.py @@ -19,15 +19,8 @@ class replica_bitcell_1port(bitcell_base.bitcell_base): is a hand-made cell, so the layout and netlist should be available in the technology library. """ - pin_names = [props.bitcell.cell_1port.pin.bl, - props.bitcell.cell_1port.pin.br, - props.bitcell.cell_1port.pin.wl, - props.bitcell.cell_1port.pin.vdd, - props.bitcell.cell_1port.pin.gnd] - type_list = ["OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"] - def __init__(self, name): - super().__init__(name) + super().__init__(name, props.bitcell_1port) debug.info(2, "Create replica bitcell object") def get_stage_effort(self, load): diff --git a/compiler/bitcells/replica_bitcell_2port.py b/compiler/bitcells/replica_bitcell_2port.py index bc95ba25..d5922b80 100644 --- a/compiler/bitcells/replica_bitcell_2port.py +++ b/compiler/bitcells/replica_bitcell_2port.py @@ -19,18 +19,8 @@ class replica_bitcell_2port(bitcell_base.bitcell_base): is a hand-made cell, so the layout and netlist should be available in the technology library. """ - pin_names = [props.bitcell.cell_2port.pin.bl0, - props.bitcell.cell_2port.pin.br0, - props.bitcell.cell_2port.pin.bl1, - props.bitcell.cell_2port.pin.br1, - props.bitcell.cell_2port.pin.wl0, - props.bitcell.cell_2port.pin.wl1, - props.bitcell.cell_2port.pin.vdd, - props.bitcell.cell_2port.pin.gnd] - type_list = ["OUTPUT", "OUTPUT", "OUTPUT", "OUTPUT", "INPUT", "INPUT", "POWER", "GROUND"] - def __init__(self, name): - super().__init__(name) + super().__init__(name, props.bitcell_2port) debug.info(2, "Create replica bitcell 2 port object") def get_stage_effort(self, load): diff --git a/compiler/custom/dff.py b/compiler/custom/dff.py index 38e3bd75..36000ac5 100644 --- a/compiler/custom/dff.py +++ b/compiler/custom/dff.py @@ -6,40 +6,19 @@ # All rights reserved. # import design -from tech import GDS, layer, spice +from tech import spice from tech import cell_properties as props -import utils class dff(design.design): """ Memory address flip-flop """ - if not props.dff.use_custom_ports: - pin_names = ["D", "Q", "clk", "vdd", "gnd"] - type_list = ["INPUT", "OUTPUT", "INPUT", "POWER", "GROUND"] - clk_pin = "clk" - else: - pin_names = props.dff.custom_port_list - type_list = props.dff.custom_type_list - clk_pin = props.dff.clk_pin - cell_size_layer = "boundary" def __init__(self, name="dff"): super().__init__(name) - (width, height) = utils.get_libcell_size(self.cell_name, - GDS["unit"], - layer[self.cell_size_layer]) - - pin_map = utils.get_libcell_pins(self.pin_names, - self.cell_name, - GDS["unit"]) - - self.width = width - self.height = height - self.pin_map = pin_map - self.add_pin_types(self.type_list) + self.clk_pin = props.dff.clk_pin def analytical_power(self, corner, load): """Returns dynamic and leakage power. Results in nW""" @@ -54,9 +33,9 @@ class dff(design.design): def calculate_effective_capacitance(self, load): """Computes effective capacitance. Results in fF""" c_load = load - c_para = spice["dff_out_cap"]#ff + c_para = spice["dff_out_cap"] # ff transition_prob = 0.5 - return transition_prob*(c_load + c_para) + return transition_prob * (c_load + c_para) def build_graph(self, graph, inst_name, port_nets): """Adds edges based on inputs/outputs. Overrides base class function.""" diff --git a/compiler/custom/inv_dec.py b/compiler/custom/inv_dec.py index b150a38e..be4099aa 100644 --- a/compiler/custom/inv_dec.py +++ b/compiler/custom/inv_dec.py @@ -6,9 +6,8 @@ # All rights reserved. # import design -from tech import GDS, layer, spice, parameter import logical_effort -import utils +from tech import spice, parameter class inv_dec(design.design): @@ -16,26 +15,9 @@ class inv_dec(design.design): INV for address decoders. """ - pin_names = ["A", "Z", "vdd", "gnd"] - type_list = ["INPUT", "OUTPUT", "POWER", "GROUND"] - cell_size_layer = "boundary" - def __init__(self, name="inv_dec", height=None): super().__init__(name) - (width, height) = utils.get_libcell_size(self.cell_name, - GDS["unit"], - layer[self.cell_size_layer]) - - pin_map = utils.get_libcell_pins(self.pin_names, - self.cell_name, - GDS["unit"]) - - self.width = width - self.height = height - self.pin_map = pin_map - self.add_pin_types(self.type_list) - def analytical_power(self, corner, load): """Returns dynamic and leakage power. Results in nW""" c_eff = self.calculate_effective_capacitance(load) @@ -52,7 +34,7 @@ class inv_dec(design.design): # In fF c_para = spice["min_tx_drain_c"] * (self.nmos_size / parameter["min_tx_size"]) - return transition_prob * (c_load + c_para) + return 0.5 * (c_load + c_para) def input_load(self): """ diff --git a/compiler/custom/nand2_dec.py b/compiler/custom/nand2_dec.py index efec63b6..2ea07ed6 100644 --- a/compiler/custom/nand2_dec.py +++ b/compiler/custom/nand2_dec.py @@ -6,9 +6,8 @@ # All rights reserved. # import design -from tech import GDS, layer, spice, parameter, drc +from tech import spice, parameter, drc import logical_effort -import utils class nand2_dec(design.design): @@ -16,26 +15,9 @@ class nand2_dec(design.design): 2-input NAND decoder for address decoders. """ - pin_names = ["A", "B", "Z", "vdd", "gnd"] - type_list = ["INPUT", "INPUT", "OUTPUT", "POWER", "GROUND"] - cell_size_layer = "boundary" - def __init__(self, name="nand2_dec", height=None): super().__init__(name) - (width, height) = utils.get_libcell_size(self.cell_name, - GDS["unit"], - layer[self.cell_size_layer]) - - pin_map = utils.get_libcell_pins(self.pin_names, - self.cell_name, - GDS["unit"]) - - self.width = width - self.height = height - self.pin_map = pin_map - self.add_pin_types(self.type_list) - # FIXME: For now... size = 1 self.size = size diff --git a/compiler/custom/nand3_dec.py b/compiler/custom/nand3_dec.py index 3fc2b949..d362e2d6 100644 --- a/compiler/custom/nand3_dec.py +++ b/compiler/custom/nand3_dec.py @@ -6,9 +6,8 @@ # All rights reserved. # import design -from tech import GDS, layer, spice, parameter, drc +from tech import spice, parameter, drc import logical_effort -import utils class nand3_dec(design.design): @@ -16,26 +15,9 @@ class nand3_dec(design.design): 3-input NAND decoder for address decoders. """ - pin_names = ["A", "B", "C", "Z", "vdd", "gnd"] - type_list = ["INPUT", "INPUT", "INPUT", "OUTPUT", "POWER", "GROUND"] - cell_size_layer = "boundary" - def __init__(self, name="nand3_dec", height=None): super().__init__(name) - (width, height) = utils.get_libcell_size(self.cell_name, - GDS["unit"], - layer[self.cell_size_layer]) - - pin_map = utils.get_libcell_pins(self.pin_names, - self.cell_name, - GDS["unit"]) - - self.width = width - self.height = height - self.pin_map = pin_map - self.add_pin_types(self.type_list) - # FIXME: For now... size = 1 self.size = size diff --git a/compiler/custom/nand4_dec.py b/compiler/custom/nand4_dec.py index abcfd2f3..0df86845 100644 --- a/compiler/custom/nand4_dec.py +++ b/compiler/custom/nand4_dec.py @@ -6,36 +6,18 @@ # All rights reserved. # import design -from tech import GDS, layer, spice, parameter, drc +from tech import spice, parameter, drc import logical_effort -import utils class nand4_dec(design.design): """ - 2-input NAND decoder for address decoders. + 4-input NAND decoder for address decoders. """ - pin_names = ["A", "B", "C", "D", "Z", "vdd", "gnd"] - type_list = ["INPUT", "INPUT", "INPUT", "INPUT", "OUTPUT", "POWER", "GROUND"] - cell_size_layer = "boundary" - def __init__(self, name="nand4_dec", height=None): super().__init__(name) - (width, height) = utils.get_libcell_size(self.cell_name, - GDS["unit"], - layer[self.cell_size_layer]) - - pin_map = utils.get_libcell_pins(self.pin_names, - self.cell_name, - GDS["unit"]) - - self.width = width - self.height = height - self.pin_map = pin_map - self.add_pin_types(self.type_list) - # FIXME: For now... size = 1 self.size = size diff --git a/compiler/custom/sense_amp.py b/compiler/custom/sense_amp.py index 4e84b7fe..61ab39a5 100644 --- a/compiler/custom/sense_amp.py +++ b/compiler/custom/sense_amp.py @@ -7,8 +7,7 @@ # import design import debug -import utils -from tech import GDS, layer, parameter, drc +from tech import parameter, drc from tech import cell_properties as props import logical_effort @@ -20,32 +19,11 @@ class sense_amp(design.design): the technology library. Sense amplifier to read a pair of bit-lines. """ - pin_names = [props.sense_amp.pin.bl, - props.sense_amp.pin.br, - props.sense_amp.pin.dout, - props.sense_amp.pin.en, - props.sense_amp.pin.vdd, - props.sense_amp.pin.gnd] - type_list = ["INPUT", "INPUT", "OUTPUT", "INPUT", "POWER", "GROUND"] - cell_size_layer = "boundary" def __init__(self, name="sense_amp"): super().__init__(name) debug.info(2, "Create sense_amp") - (width, height) = utils.get_libcell_size(self.cell_name, - GDS["unit"], - layer[self.cell_size_layer]) - - pin_map = utils.get_libcell_pins(self.pin_names, - self.cell_name, - GDS["unit"]) - - self.width = width - self.height = height - self.pin_map = pin_map - self.add_pin_types(self.type_list) - def get_bl_names(self): return props.sense_amp.pin.bl diff --git a/compiler/custom/tri_gate.py b/compiler/custom/tri_gate.py index 476cc886..6be58104 100644 --- a/compiler/custom/tri_gate.py +++ b/compiler/custom/tri_gate.py @@ -7,8 +7,7 @@ # import debug import design -import utils -from tech import GDS, layer +from tech import spice class tri_gate(design.design): @@ -18,10 +17,6 @@ class tri_gate(design.design): netlist should be available in the technology library. """ - pin_names = ["in", "out", "en", "en_bar", "vdd", "gnd"] - type_list = ["INPUT", "OUTPUT", "INPUT", "INPUT", "POWER", "GROUND"] - cell_size_layer = "boundary" - unique_id = 1 def __init__(self, name=""): @@ -31,19 +26,6 @@ class tri_gate(design.design): super().__init__(self, name) debug.info(2, "Create tri_gate") - (width, height) = utils.get_libcell_size(self.cell_name, - GDS["unit"], - layer[self.cell_size_layer]) - - pin_map = utils.get_libcell_pins(self.pin_names, - self.cell_name, - GDS["unit"]) - - self.width = width - self.height = height - self.pin_map = pin_map - self.add_pin_types(self.type_list) - def analytical_power(self, corner, load): """Returns dynamic and leakage power. Results in nW""" #Power in this module currently not defined. Returns 0 nW (leakage and dynamic). @@ -51,7 +33,7 @@ class tri_gate(design.design): return total_power def get_cin(self): - return 9*spice["min_tx_gate_c"] + return 9 * spice["min_tx_gate_c"] def build_graph(self, graph, inst_name, port_nets): """Adds edges based on inputs/outputs. Overrides base class function.""" diff --git a/compiler/custom/write_driver.py b/compiler/custom/write_driver.py index 41375ab3..bcef46e1 100644 --- a/compiler/custom/write_driver.py +++ b/compiler/custom/write_driver.py @@ -7,8 +7,6 @@ # import debug import design -import utils -from tech import GDS, layer from tech import cell_properties as props @@ -20,33 +18,10 @@ class write_driver(design.design): the technology library. """ - pin_names = [props.write_driver.pin.din, - props.write_driver.pin.bl, - props.write_driver.pin.br, - props.write_driver.pin.en, - props.write_driver.pin.vdd, - props.write_driver.pin.gnd] - - type_list = ["INPUT", "OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"] - cell_size_layer = "boundary" - def __init__(self, name): super().__init__(name) debug.info(2, "Create write_driver") - (width, height) = utils.get_libcell_size(self.cell_name, - GDS["unit"], - layer[self.cell_size_layer]) - - pin_map = utils.get_libcell_pins(self.pin_names, - self.cell_name, - GDS["unit"]) - - self.width = width - self.height = height - self.pin_map = pin_map - self.add_pin_types(self.type_list) - def get_bl_names(self): return props.write_driver.pin.bl @@ -64,7 +39,7 @@ class write_driver(design.design): def get_w_en_cin(self): """Get the relative capacitance of a single input""" # This is approximated from SCMOS. It has roughly 5 3x transistor gates. - return 5*3 + return 5 * 3 def build_graph(self, graph, inst_name, port_nets): """Adds edges based on inputs/outputs. Overrides base class function.""" diff --git a/compiler/modules/bitcell_base_array.py b/compiler/modules/bitcell_base_array.py index b1ee88a4..95e8a4ec 100644 --- a/compiler/modules/bitcell_base_array.py +++ b/compiler/modules/bitcell_base_array.py @@ -7,7 +7,6 @@ # import debug import design -from tech import cell_properties from sram_factory import factory from globals import OPTS @@ -174,7 +173,7 @@ class bitcell_base_array(design.design): tempx = xoffset dir_y = False # If we mirror the current cell on the y axis adjust the x position - if cell_properties.bitcell.mirror.y and (col + col_offset) % 2: + if self.cell.mirror.y and (col + col_offset) % 2: tempx = xoffset + self.cell.width dir_y = True return (tempx, dir_y) @@ -183,7 +182,7 @@ class bitcell_base_array(design.design): tempy = yoffset dir_x = False # If we mirror the current cell on the x axis adjust the y position - if cell_properties.bitcell.mirror.x and (row + row_offset) % 2: + if self.cell.mirror.x and (row + row_offset) % 2: tempy = yoffset + self.cell.height dir_x = True return (tempy, dir_x) diff --git a/compiler/modules/col_cap_array.py b/compiler/modules/col_cap_array.py index ffbf6413..6bc77805 100644 --- a/compiler/modules/col_cap_array.py +++ b/compiler/modules/col_cap_array.py @@ -26,12 +26,9 @@ class col_cap_array(bitcell_base_array): def create_netlist(self): """ Create and connect the netlist """ # This will create a default set of bitline/wordline names - try: - end_caps_enabled = cell_properties.bitcell.end_caps - except AttributeError: - end_caps_enabled = False + self.cell = factory.create(module_type=OPTS.bitcell) - if not end_caps_enabled: + if not self.cell.end_caps: self.create_all_wordline_names() self.create_all_bitline_names() @@ -51,8 +48,6 @@ class col_cap_array(bitcell_base_array): self.dummy_cell = factory.create(module_type="col_cap_{}".format(OPTS.bitcell)) self.add_mod(self.dummy_cell) - self.cell = factory.create(module_type=OPTS.bitcell) - def create_instances(self): """ Create the module instances used in this design """ self.cell_inst = {} diff --git a/compiler/modules/control_logic.py b/compiler/modules/control_logic.py index b0620a38..0402eba3 100644 --- a/compiler/modules/control_logic.py +++ b/compiler/modules/control_logic.py @@ -662,9 +662,6 @@ class control_logic(design.design): self.ctrl_dff_inst=self.add_inst(name="ctrl_dffs", mod=self.ctrl_dff_array) inst_pins = self.input_list + self.dff_output_list + ["clk_buf"] + self.supply_list - if props.dff_buff_array.add_body_contacts: - inst_pins.append("vpb") - inst_pins.append("vnb") self.connect_inst(inst_pins) def place_dffs(self): diff --git a/compiler/modules/dff_array.py b/compiler/modules/dff_array.py index 0cbe8fe5..a2ea7eeb 100644 --- a/compiler/modules/dff_array.py +++ b/compiler/modules/dff_array.py @@ -70,7 +70,7 @@ class dff_array(design.design): mod=self.dff) instance_ports = [self.get_din_name(row, col), self.get_dout_name(row, col)] - for port in self.dff.pin_names: + for port in self.dff.pins: if port != 'D' and port != 'Q': instance_ports.append(port) self.connect_inst(instance_ports) diff --git a/compiler/modules/dff_buf.py b/compiler/modules/dff_buf.py index b218a9bb..a650214e 100644 --- a/compiler/modules/dff_buf.py +++ b/compiler/modules/dff_buf.py @@ -72,30 +72,22 @@ class dff_buf(design.design): self.add_mod(self.inv2) def add_pins(self): - self.add_pin("D", "INPUT") - self.add_pin("Q", "OUTPUT") - self.add_pin("Qb", "OUTPUT") - self.add_pin("clk", "INPUT") - self.add_pin("vdd", "POWER") - self.add_pin("gnd", "GROUND") - - if props.dff_buff.add_body_contacts: - self.add_pin("vpb", "INPUT") - self.add_pin("vpn", "INPUT") + self.add_pin_list(props.dff_buf.port_names, + props.dff_buf.port_types) def create_instances(self): self.dff_inst=self.add_inst(name="dff_buf_dff", mod=self.dff) - self.connect_inst(["D", "qint", "clk", "vdd", "gnd"]) + self.connect_inst([props.dff_buf.pin.D, "qint", props.dff_buf.pin.clk, props.dff_buf.pin.vdd, props.dff_buf.pin.gnd]) self.inv1_inst=self.add_inst(name="dff_buf_inv1", mod=self.inv1) - self.connect_inst(["qint", "Qb", "vdd", "gnd"]) + self.connect_inst(["qint", "Qb", props.dff_buf.pin.vdd, props.dff_buf.pin.gnd]) self.inv2_inst=self.add_inst(name="dff_buf_inv2", mod=self.inv2) - self.connect_inst(["Qb", "Q", "vdd", "gnd"]) + self.connect_inst(["Qb", props.dff_buf.pin.Q, props.dff_buf.pin.vdd, props.dff_buf.pin.gnd]) def place_instances(self): # Add the DFF @@ -129,7 +121,7 @@ class dff_buf(design.design): self.route_layer = "m1" # Route dff q to inv1 a - q_pin = self.dff_inst.get_pin("Q") + q_pin = self.dff_inst.get_pin(props.dff.pin.Q) a1_pin = self.inv1_inst.get_pin("A") mid1 = vector(a1_pin.cx(), q_pin.cy()) self.add_path(q_pin.layer, [q_pin.center(), mid1, a1_pin.center()], width=q_pin.height()) @@ -146,30 +138,30 @@ class dff_buf(design.design): def add_layout_pins(self): # Continous vdd rail along with label. - vdd_pin=self.dff_inst.get_pin("vdd") - self.add_layout_pin(text="vdd", + vdd_pin=self.dff_inst.get_pin(props.dff.pin.vdd) + self.add_layout_pin(text=props.dff_buf.pin.vdd, layer=vdd_pin.layer, offset=vdd_pin.ll(), width=self.width, height=vdd_pin.height()) # Continous gnd rail along with label. - gnd_pin=self.dff_inst.get_pin("gnd") - self.add_layout_pin(text="gnd", + gnd_pin=self.dff_inst.get_pin(props.dff.pin.gnd) + self.add_layout_pin(text=props.dff_buf.pin.gnd, layer=gnd_pin.layer, offset=gnd_pin.ll(), width=self.width, height=vdd_pin.height()) - clk_pin = self.dff_inst.get_pin("clk") - self.add_layout_pin(text="clk", + clk_pin = self.dff_inst.get_pin(props.dff.pin.clk) + self.add_layout_pin(text=props.dff_buf.pin.clk, layer=clk_pin.layer, offset=clk_pin.ll(), width=clk_pin.width(), height=clk_pin.height()) - din_pin = self.dff_inst.get_pin("D") - self.add_layout_pin(text="D", + din_pin = self.dff_inst.get_pin(props.dff_buf.pin.D) + self.add_layout_pin(text=props.dff_buf.pin.D, layer=din_pin.layer, offset=din_pin.ll(), width=din_pin.width(), @@ -178,7 +170,7 @@ class dff_buf(design.design): dout_pin = self.inv2_inst.get_pin("Z") mid_pos = dout_pin.center() + vector(self.m2_nonpref_pitch, 0) q_pos = mid_pos - vector(0, 2 * self.m2_nonpref_pitch) - self.add_layout_pin_rect_center(text="Q", + self.add_layout_pin_rect_center(text=props.dff_buf.pin.Q, layer="m2", offset=q_pos) self.add_path(self.route_layer, [dout_pin.center(), mid_pos, q_pos]) diff --git a/compiler/modules/dff_buf_array.py b/compiler/modules/dff_buf_array.py index 2d885ccc..dacc5451 100644 --- a/compiler/modules/dff_buf_array.py +++ b/compiler/modules/dff_buf_array.py @@ -65,10 +65,6 @@ class dff_buf_array(design.design): self.add_pin("vdd", "POWER") self.add_pin("gnd", "GROUND") - if props.dff_buff_array.add_body_contacts: - self.add_pin("vpb", "INPUT") - self.add_pin("vnb", "INPUT") - def add_modules(self): self.dff = factory.create(module_type="dff_buf", inv1_size=self.inv1_size, @@ -88,9 +84,6 @@ class dff_buf_array(design.design): "clk", "vdd", "gnd"] - if props.dff_buff_array.add_body_contacts: - inst_ports.append("vpb") - inst_ports.append("vnb") self.connect_inst(inst_ports) def place_dff_array(self): @@ -155,7 +148,7 @@ class dff_buf_array(design.design): def route_supplies(self): for row in range(self.rows): - vdd0_pin=self.dff_insts[row, 0].get_pin("vdd") + vdd0_pin=self.dff_insts[row, 0].get_pin(props.dff.pin.vdd) vddn_pin=self.dff_insts[row, self.columns - 1].get_pin("vdd") self.add_path(vdd0_pin.layer, [vdd0_pin.lc(), vddn_pin.rc()], width=vdd0_pin.height()) diff --git a/compiler/modules/precharge_array.py b/compiler/modules/precharge_array.py index a9cf2824..590dadce 100644 --- a/compiler/modules/precharge_array.py +++ b/compiler/modules/precharge_array.py @@ -10,7 +10,6 @@ import debug from vector import vector from sram_factory import factory from globals import OPTS -from tech import cell_properties class precharge_array(design.design): @@ -79,6 +78,8 @@ class precharge_array(design.design): bitcell_br=self.bitcell_br) self.add_mod(self.pc_cell) + self.cell = factory.create(module_type=OPTS.bitcell) + def add_layout_pins(self): en_pin = self.pc_cell.get_pin("en_bar") @@ -120,7 +121,7 @@ class precharge_array(design.design): self.offsets = [n * self.pc_cell.width for n in range(self.columns)] for i, xoffset in enumerate(self.offsets): - if cell_properties.bitcell.mirror.y and (i + self.column_offset) % 2: + if self.cell.mirror.y and (i + self.column_offset) % 2: mirror = "MY" tempx = xoffset + self.pc_cell.width else: diff --git a/compiler/modules/replica_bitcell_array.py b/compiler/modules/replica_bitcell_array.py index cc6373db..ebfd06ba 100644 --- a/compiler/modules/replica_bitcell_array.py +++ b/compiler/modules/replica_bitcell_array.py @@ -63,13 +63,8 @@ class replica_bitcell_array(bitcell_base_array): # Two dummy cols plus replica if we add the column self.extra_cols = len(self.left_rbl) + len(self.right_rbl) - - try: - end_caps_enabled = cell_properties.bitcell.end_caps - except AttributeError: - end_caps_enabled = False # If we aren't using row/col caps, then we need to use the bitcell - if not end_caps_enabled: + if not self.cell.end_caps: self.extra_rows += 2 self.extra_cols += 2 @@ -144,10 +139,6 @@ class replica_bitcell_array(bitcell_base_array): column_offset=column_offset, replica_bit=replica_bit) self.add_mod(self.replica_columns[port]) - try: - end_caps_enabled = cell_properties.bitcell.end_caps - except AttributeError: - end_caps_enabled = False # Dummy row self.dummy_row = factory.create(module_type="dummy_array", @@ -159,7 +150,7 @@ class replica_bitcell_array(bitcell_base_array): self.add_mod(self.dummy_row) # Dummy Row or Col Cap, depending on bitcell array properties - col_cap_module_type = ("col_cap_array" if end_caps_enabled else "dummy_array") + col_cap_module_type = ("col_cap_array" if self.cell.end_caps else "dummy_array") self.col_cap_top = factory.create(module_type=col_cap_module_type, cols=self.column_size, rows=1, @@ -179,7 +170,7 @@ class replica_bitcell_array(bitcell_base_array): self.add_mod(self.col_cap_bottom) # Dummy Col or Row Cap, depending on bitcell array properties - row_cap_module_type = ("row_cap_array" if end_caps_enabled else "dummy_array") + row_cap_module_type = ("row_cap_array" if self.cell.end_caps else "dummy_array") self.row_cap_left = factory.create(module_type=row_cap_module_type, cols=1, @@ -240,11 +231,6 @@ class replica_bitcell_array(bitcell_base_array): self.add_pin_list(self.rbl_bitline_names[port], "INOUT") def add_wordline_pins(self): - try: - end_caps_enabled = cell_properties.bitcell.end_caps - except AttributeError: - end_caps_enabled = False - # Wordlines to ground self.gnd_wordline_names = [] @@ -385,14 +371,10 @@ class replica_bitcell_array(bitcell_base_array): def add_replica_columns(self): """ Add replica columns on left and right of array """ - try: - end_caps_enabled = cell_properties.bitcell.end_caps - except AttributeError: - end_caps_enabled = False # Grow from left to right, toward the array for bit, port in enumerate(self.left_rbl): - if not end_caps_enabled: + if not self.cell.end_caps: offset = self.bitcell_offset.scale(-len(self.left_rbl) + bit, -self.rbl[0] - 1) + self.strap_offset.scale(-len(self.left_rbl) + bit, 0) + self.unused_offset else: offset = self.bitcell_offset.scale(-len(self.left_rbl) + bit, -self.rbl[0] - (self.col_end_offset.y/self.cell.height)) + self.strap_offset.scale(-len(self.left_rbl) + bit, 0) + self.unused_offset @@ -400,7 +382,7 @@ class replica_bitcell_array(bitcell_base_array): self.replica_col_insts[bit].place(offset) # Grow to the right of the bitcell array, array outward for bit, port in enumerate(self.right_rbl): - if not end_caps_enabled: + if not self.cell.end_caps: offset = self.bitcell_array_inst.lr() + self.bitcell_offset.scale(bit, -self.rbl[0] - 1) + self.strap_offset.scale(bit, -self.rbl[0] - 1) else: offset = self.bitcell_array_inst.lr() + self.bitcell_offset.scale(bit, -self.rbl[0] - (self.col_end_offset.y/self.cell.height)) + self.strap_offset.scale(bit, -self.rbl[0] - 1) @@ -422,15 +404,11 @@ class replica_bitcell_array(bitcell_base_array): def add_end_caps(self): """ Add dummy cells or end caps around the array """ - try: - end_caps_enabled = cell_properties.bitcell.end_caps - except AttributeError: - end_caps_enabled = False # FIXME: These depend on the array size itself # Far top dummy row (first row above array is NOT flipped) flip_dummy = self.rbl[1] % 2 - if not end_caps_enabled: + if not self.cell.end_caps: dummy_row_offset = self.bitcell_offset.scale(0, self.rbl[1] + flip_dummy) + self.bitcell_array_inst.ul() else: dummy_row_offset = self.bitcell_offset.scale(0, self.rbl[1] + flip_dummy) + self.bitcell_array_inst.ul() @@ -440,7 +418,7 @@ class replica_bitcell_array(bitcell_base_array): # FIXME: These depend on the array size itself # Far bottom dummy row (first row below array IS flipped) flip_dummy = (self.rbl[0] + 1) % 2 - if not end_caps_enabled: + if not self.cell.end_caps: dummy_row_offset = self.bitcell_offset.scale(0, -self.rbl[0] - 1 + flip_dummy) + self.unused_offset else: dummy_row_offset = self.bitcell_offset.scale(0, -self.rbl[0] - (self.col_end_offset.y/self.cell.height) + flip_dummy) + self.unused_offset @@ -448,7 +426,7 @@ class replica_bitcell_array(bitcell_base_array): mirror="MX" if flip_dummy else "R0") # Far left dummy col # Shifted down by the number of left RBLs even if we aren't adding replica column to this bitcell array - if not end_caps_enabled: + if not self.cell.end_caps: dummy_col_offset = self.bitcell_offset.scale(-len(self.left_rbl) - 1, -self.rbl[0] - 1) + self.unused_offset else: dummy_col_offset = self.bitcell_offset.scale(-(len(self.left_rbl)*(1+self.strap_offset.x/self.cell.width)) - (self.row_end_offset.x/self.cell.width), -len(self.left_rbl) - (self.col_end_offset.y/self.cell.height)) @@ -456,7 +434,7 @@ class replica_bitcell_array(bitcell_base_array): self.dummy_col_insts[0].place(offset=dummy_col_offset) # Far right dummy col # Shifted down by the number of left RBLs even if we aren't adding replica column to this bitcell array - if not end_caps_enabled: + if not self.cell.end_caps: dummy_col_offset = self.bitcell_offset.scale(len(self.right_rbl), -self.rbl[0] - 1) + self.bitcell_array_inst.lr() else: dummy_col_offset = self.bitcell_offset.scale(len(self.right_rbl)*(1+self.strap_offset.x/self.cell.width), -self.rbl[0] - (self.col_end_offset.y/self.cell.height)) + self.bitcell_array_inst.lr() diff --git a/compiler/modules/replica_column.py b/compiler/modules/replica_column.py index ad6e63dc..1fbe60fb 100644 --- a/compiler/modules/replica_column.py +++ b/compiler/modules/replica_column.py @@ -5,7 +5,7 @@ # import debug from bitcell_base_array import bitcell_base_array -from tech import cell_properties +from tech import cell_properties as props from sram_factory import factory from vector import vector from globals import OPTS @@ -30,11 +30,9 @@ class replica_column(bitcell_base_array): self.replica_bit = replica_bit # left, right, regular rows plus top/bottom dummy cells self.total_size = self.left_rbl + rows + self.right_rbl - try: - if not cell_properties.bitcell.end_caps: - self.total_size += 2 - except AttributeError: - self.total_size += 2 + + # For end caps + self.total_size += 2 self.column_offset = column_offset @@ -82,20 +80,17 @@ class replica_column(bitcell_base_array): self.dummy_cell = factory.create(module_type=OPTS.dummy_bitcell) self.add_mod(self.dummy_cell) try: - edge_module_type = ("col_cap" if cell_properties.bitcell.end_caps else "dummy") + edge_module_type = ("col_cap" if self.cell.end_caps else "dummy") except AttributeError: edge_module_type = "dummy" self.edge_cell = factory.create(module_type=edge_module_type + "_" + OPTS.bitcell) self.add_mod(self.edge_cell) + # Used for pin names only self.cell = factory.create(module_type=OPTS.bitcell) def create_instances(self): self.cell_inst = {} - try: - end_caps_enabled = cell_properties.bitcell.end_caps - except AttributeError: - end_caps_enabled = False for row in range(self.total_size): name="rbc_{0}".format(row) @@ -113,7 +108,7 @@ class replica_column(bitcell_base_array): elif (row == 0 or row == self.total_size - 1): self.cell_inst[row]=self.add_inst(name=name, mod=self.edge_cell) - if end_caps_enabled: + if self.cell.end_caps: self.connect_inst(self.get_bitcell_pins_col_cap(row, 0)) else: self.connect_inst(self.get_bitcell_pins(row, 0)) @@ -131,13 +126,13 @@ class replica_column(bitcell_base_array): # column that needs to be flipped. dir_y = False xoffset = 0 - if cell_properties.bitcell.mirror.y and self.column_offset % 2: + if self.replica_cell.mirror.y and self.column_offset % 2: dir_y = True xoffset = self.replica_cell.width for row in range(self.total_size): # name = "bit_r{0}_{1}".format(row, "rbl") - dir_x = cell_properties.bitcell.mirror.x and (row + rbl_offset) % 2 + dir_x = self.replica_cell.mirror.x and (row + rbl_offset) % 2 offset = vector(xoffset, self.cell.height * (row + (row + rbl_offset) % 2)) @@ -169,12 +164,7 @@ class replica_column(bitcell_base_array): width=bl_pin.width(), height=self.height) - try: - end_caps_enabled = cell_properties.bitcell.end_caps - except AttributeError: - end_caps_enabled = False - - if end_caps_enabled: + if self.cell.end_caps: row_range_max = self.total_size - 1 row_range_min = 1 else: diff --git a/compiler/modules/sense_amp_array.py b/compiler/modules/sense_amp_array.py index ce4e6911..d3ab94a5 100644 --- a/compiler/modules/sense_amp_array.py +++ b/compiler/modules/sense_amp_array.py @@ -10,7 +10,6 @@ from vector import vector from sram_factory import factory import debug from globals import OPTS -from tech import cell_properties class sense_amp_array(design.design): @@ -92,7 +91,6 @@ class sense_amp_array(design.design): def add_modules(self): self.amp = factory.create(module_type="sense_amp") - self.add_mod(self.amp) # This is just used for measurements, @@ -122,7 +120,7 @@ class sense_amp_array(design.design): self.offsets.append(i * self.bitcell.width) for i, xoffset in enumerate(self.offsets[0:self.num_cols:self.words_per_row]): - if cell_properties.bitcell.mirror.y and (i * self.words_per_row + self.column_offset) % 2: + if self.bitcell.mirror.y and (i * self.words_per_row + self.column_offset) % 2: mirror = "MY" xoffset = xoffset + self.amp_spacing else: @@ -134,7 +132,7 @@ class sense_amp_array(design.design): # place spare sense amps (will share the same enable as regular sense amps) for i, xoffset in enumerate(self.offsets[self.num_cols:]): index = self.word_size + i - if cell_properties.bitcell.mirror.y and (index + self.column_offset) % 2: + if self.bitcell.mirror.y and (index + self.column_offset) % 2: mirror = "MY" xoffset = xoffset + self.amp_width else: diff --git a/compiler/modules/write_driver_array.py b/compiler/modules/write_driver_array.py index aa0a4e29..afd21de5 100644 --- a/compiler/modules/write_driver_array.py +++ b/compiler/modules/write_driver_array.py @@ -12,7 +12,6 @@ from tech import drc from sram_factory import factory from vector import vector from globals import OPTS -from tech import cell_properties class write_driver_array(design.design): @@ -161,7 +160,7 @@ class write_driver_array(design.design): self.offsets.append(i * self.driver_spacing) for i, xoffset in enumerate(self.offsets[0:self.columns:self.words_per_row]): - if cell_properties.bitcell.mirror.y and (i * self.words_per_row + self.column_offset) % 2: + if self.bitcell.mirror.y and (i * self.words_per_row + self.column_offset) % 2: mirror = "MY" xoffset = xoffset + self.driver.width else: @@ -174,7 +173,7 @@ class write_driver_array(design.design): for i, xoffset in enumerate(self.offsets[self.columns:]): index = self.word_size + i - if cell_properties.bitcell.mirror.y and (index + self.column_offset) % 2: + if self.bitcell.mirror.y and (index + self.column_offset) % 2: mirror = "MY" xoffset = xoffset + self.driver.width else: diff --git a/technology/freepdk45/tech/tech.py b/technology/freepdk45/tech/tech.py index 46b7c2a5..436d2ff4 100644 --- a/technology/freepdk45/tech/tech.py +++ b/technology/freepdk45/tech/tech.py @@ -31,11 +31,8 @@ tech_modules = module_type() # Custom cell properties ################################################### cell_properties = cell_properties() -cell_properties.bitcell.mirror.x = True -cell_properties.bitcell.mirror.y = False cell_properties.bitcell_power_pin_directions = ("V", "V") - ################################################### # Custom cell properties ################################################### diff --git a/technology/scn4m_subm/tech/tech.py b/technology/scn4m_subm/tech/tech.py index e6a54e6e..6591fbbc 100644 --- a/technology/scn4m_subm/tech/tech.py +++ b/technology/scn4m_subm/tech/tech.py @@ -30,9 +30,6 @@ tech_modules = module_type() # Custom cell properties ################################################### cell_properties = cell_properties() -cell_properties.bitcell.mirror.x = True -cell_properties.bitcell.mirror.y = False - ################################################### # Custom cell properties From 620e271562a483ad3b5450f409e9df8396b94885 Mon Sep 17 00:00:00 2001 From: mrg Date: Fri, 13 Nov 2020 16:04:07 -0800 Subject: [PATCH 17/31] Fix various typos and errors --- compiler/bitcells/dummy_bitcell_2port.py | 2 +- compiler/bitcells/pbitcell.py | 1 + compiler/modules/column_mux_array.py | 5 +++-- compiler/modules/replica_column.py | 4 ++-- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/compiler/bitcells/dummy_bitcell_2port.py b/compiler/bitcells/dummy_bitcell_2port.py index 4d6d5c49..14b0ce96 100644 --- a/compiler/bitcells/dummy_bitcell_2port.py +++ b/compiler/bitcells/dummy_bitcell_2port.py @@ -18,7 +18,7 @@ class dummy_bitcell_2port(bitcell_base.bitcell_base): the technology library. """ def __init__(self, name): - super().__init__(name, props.bitcel_2port) + super().__init__(name, props.bitcell_2port) debug.info(2, "Create dummy bitcell 2 port object") diff --git a/compiler/bitcells/pbitcell.py b/compiler/bitcells/pbitcell.py index 61360e99..c5ac8cb6 100644 --- a/compiler/bitcells/pbitcell.py +++ b/compiler/bitcells/pbitcell.py @@ -31,6 +31,7 @@ class pbitcell(bitcell_base.bitcell_base): self.replica_bitcell = replica_bitcell self.dummy_bitcell = dummy_bitcell self.mirror = props.bitcell_1port.mirror + self.end_caps = props.bitcell_1port.end_caps bitcell_base.bitcell_base.__init__(self, name) fmt_str = "{0} rw ports, {1} w ports and {2} r ports" diff --git a/compiler/modules/column_mux_array.py b/compiler/modules/column_mux_array.py index 2f1ee56e..55d67eee 100644 --- a/compiler/modules/column_mux_array.py +++ b/compiler/modules/column_mux_array.py @@ -11,7 +11,6 @@ from tech import layer, preferred_directions from vector import vector from sram_factory import factory from globals import OPTS -from tech import cell_properties as cell_props from tech import layer_properties as layer_props @@ -99,6 +98,8 @@ class column_mux_array(design.design): bitcell_br=self.bitcell_br) self.add_mod(self.mux) + self.cell = factory.create(module_type=OPTS.bitcell) + def setup_layout_constants(self): self.column_addr_size = int(self.words_per_row / 2) self.width = self.columns * self.mux.width @@ -128,7 +129,7 @@ class column_mux_array(design.design): # For every column, add a pass gate for col_num, xoffset in enumerate(self.offsets[0:self.columns]): - if cell_props.bitcell.mirror.y and (col_num + self.column_offset) % 2: + if self.cell.mirror.y and (col_num + self.column_offset) % 2: mirror = "MY" xoffset = xoffset + self.mux.width else: diff --git a/compiler/modules/replica_column.py b/compiler/modules/replica_column.py index 1fbe60fb..eac98054 100644 --- a/compiler/modules/replica_column.py +++ b/compiler/modules/replica_column.py @@ -126,13 +126,13 @@ class replica_column(bitcell_base_array): # column that needs to be flipped. dir_y = False xoffset = 0 - if self.replica_cell.mirror.y and self.column_offset % 2: + if self.cell.mirror.y and self.column_offset % 2: dir_y = True xoffset = self.replica_cell.width for row in range(self.total_size): # name = "bit_r{0}_{1}".format(row, "rbl") - dir_x = self.replica_cell.mirror.x and (row + rbl_offset) % 2 + dir_x = self.cell.mirror.x and (row + rbl_offset) % 2 offset = vector(xoffset, self.cell.height * (row + (row + rbl_offset) % 2)) From 01d191da40ac597e0e62e003b3d6cc8a34c46c34 Mon Sep 17 00:00:00 2001 From: mrg Date: Fri, 13 Nov 2020 16:23:27 -0800 Subject: [PATCH 18/31] clk_pin is redundant in DFFs --- compiler/base/custom_cell_properties.py | 30 ++++++++----------------- compiler/base/design.py | 4 ++-- compiler/bitcells/bitcell_base.py | 2 +- compiler/custom/dff.py | 2 +- compiler/modules/dff_buf.py | 2 +- 5 files changed, 14 insertions(+), 26 deletions(-) diff --git a/compiler/base/custom_cell_properties.py b/compiler/base/custom_cell_properties.py index 5c5947d9..7f41d7ef 100644 --- a/compiler/base/custom_cell_properties.py +++ b/compiler/base/custom_cell_properties.py @@ -20,11 +20,8 @@ class _cell: port_map = {} for pin in port_order: port_map[pin] = pin - self._pins = _pins(port_map) - else: - self._pins = _pins(port_map) + self._pins = _pins(port_map) - self._port_names = [getattr(self._pins, x) for x in self._port_order] self._boundary_layer = boundary_layer @property @@ -35,9 +32,8 @@ class _cell: def hard_cell(self): return self._hard_cell - @property def port_names(self): - return self._port_names + return [getattr(self._pins, x) for x in self._port_order] @property def port_types(self): @@ -98,13 +94,7 @@ class _bitcell(_cell): def storage_nets(self): return self._storage_nets - -class _dff(_cell): - def __init__(self, clk_pin, port_order, port_types, port_map=None, hard_cell=True): - super().__init__(port_order, port_types, port_map, hard_cell) - self.clk_pin = clk_pin - - + class cell_properties(): """ This contains meta information about the custom designed cells. For @@ -139,14 +129,12 @@ class cell_properties(): self._nand2_dec = _cell(["A", "B", "C", "D", "Z", "vdd", "gnd"], ["INPUT", "INPUT", "INPUT", "INPUT", "OUTPUT", "POWER", "GROUND"]) - self._dff = _dff("clk", - ["D", "Q", "clk", "vdd", "gnd"], - ["INPUT", "OUTPUT", "INPUT", "POWER", "GROUND"]) + self._dff = _cell(["D", "Q", "clk", "vdd", "gnd"], + ["INPUT", "OUTPUT", "INPUT", "POWER", "GROUND"]) - self._dff_buf = _dff("clk", - ["D", "Q", "Qb", "clk", "vdd", "gnd"], - ["INPUT", "OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"], - hard_cell=False) + self._dff_buf = _cell(["D", "Q", "Qb", "clk", "vdd", "gnd"], + ["INPUT", "OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"], + hard_cell=False) self._write_driver = _cell(['din', 'bl', 'br', 'en', 'vdd', 'gnd'], ["INPUT", "OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"]) @@ -155,7 +143,7 @@ class cell_properties(): ["INPUT", "INPUT", "OUTPUT", "INPUT", "POWER", "GROUND"]) self._bitcell_1port = _bitcell(["bl", "br", "wl", "vdd", "gnd"], - ["OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"]) + ["OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND<"]) self._bitcell_2port = _bitcell(["bl0", "br0", "bl1", "br1", "wl0", "wl1", "vdd", "gnd"], ["OUTPUT", "OUTPUT", "OUTPUT", "OUTPUT", "INPUT", "INPUT", "POWER", "GROUND"]) diff --git a/compiler/base/design.py b/compiler/base/design.py index 98c03981..c0729ef6 100644 --- a/compiler/base/design.py +++ b/compiler/base/design.py @@ -37,8 +37,8 @@ class design(hierarchy_design): prop = getattr(props, name) if prop.hard_cell: # The pins get added from the spice file - 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() == self.pins, + "Custom cell pin names do not match spice file:\n{0} vs {1}".format(prop.port_names(), self.pins)) self.add_pin_types(prop.port_types) (width, height) = utils.get_libcell_size(self.cell_name, diff --git a/compiler/bitcells/bitcell_base.py b/compiler/bitcells/bitcell_base.py index 0e821774..dc4198c4 100644 --- a/compiler/bitcells/bitcell_base.py +++ b/compiler/bitcells/bitcell_base.py @@ -22,7 +22,7 @@ class bitcell_base(design.design): design.design.__init__(self, name) if prop: - self.pins = prop.port_names + self.pins = prop.port_names() self.add_pin_types(prop.port_types) self.nets_match = self.do_nets_exist(prop.storage_nets) self.mirror = prop.mirror diff --git a/compiler/custom/dff.py b/compiler/custom/dff.py index 36000ac5..2a73b1e8 100644 --- a/compiler/custom/dff.py +++ b/compiler/custom/dff.py @@ -18,7 +18,7 @@ class dff(design.design): def __init__(self, name="dff"): super().__init__(name) - self.clk_pin = props.dff.clk_pin + self.clk_pin = props.dff.pin.clk def analytical_power(self, corner, load): """Returns dynamic and leakage power. Results in nW""" diff --git a/compiler/modules/dff_buf.py b/compiler/modules/dff_buf.py index a650214e..6f168a74 100644 --- a/compiler/modules/dff_buf.py +++ b/compiler/modules/dff_buf.py @@ -72,7 +72,7 @@ class dff_buf(design.design): self.add_mod(self.inv2) def add_pins(self): - self.add_pin_list(props.dff_buf.port_names, + self.add_pin_list(props.dff_buf.port_names(), props.dff_buf.port_types) def create_instances(self): From a2b17a271cc2d918af09e10cd877185908768ffb Mon Sep 17 00:00:00 2001 From: mrg Date: Fri, 13 Nov 2020 16:41:02 -0800 Subject: [PATCH 19/31] Port type order generated on the fly --- compiler/base/custom_cell_properties.py | 11 ++++------- compiler/base/design.py | 2 +- compiler/bitcells/bitcell_base.py | 2 +- compiler/modules/dff_buf.py | 2 +- 4 files changed, 7 insertions(+), 10 deletions(-) diff --git a/compiler/base/custom_cell_properties.py b/compiler/base/custom_cell_properties.py index 7f41d7ef..0a8f4eb6 100644 --- a/compiler/base/custom_cell_properties.py +++ b/compiler/base/custom_cell_properties.py @@ -13,13 +13,11 @@ class _cell: # Specifies the order in the spice modules self._port_order = port_order # Specifies the port directions - self._port_types = port_types + self._port_types = {x: y for (x, y) in zip(port_order, port_types)} # Specifies a map from OpenRAM names to cell names # by default it is 1:1 if not port_map: - port_map = {} - for pin in port_order: - port_map[pin] = pin + port_map = {x: x for x in port_order} self._pins = _pins(port_map) self._boundary_layer = boundary_layer @@ -35,9 +33,8 @@ class _cell: def port_names(self): return [getattr(self._pins, x) for x in self._port_order] - @property def port_types(self): - return self._port_types + return [self._port_types[x] for x in self._port_order] @property def boundary_layer(self): @@ -143,7 +140,7 @@ class cell_properties(): ["INPUT", "INPUT", "OUTPUT", "INPUT", "POWER", "GROUND"]) self._bitcell_1port = _bitcell(["bl", "br", "wl", "vdd", "gnd"], - ["OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND<"]) + ["OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"]) self._bitcell_2port = _bitcell(["bl0", "br0", "bl1", "br1", "wl0", "wl1", "vdd", "gnd"], ["OUTPUT", "OUTPUT", "OUTPUT", "OUTPUT", "INPUT", "INPUT", "POWER", "GROUND"]) diff --git a/compiler/base/design.py b/compiler/base/design.py index c0729ef6..e4e8f7ea 100644 --- a/compiler/base/design.py +++ b/compiler/base/design.py @@ -39,7 +39,7 @@ class design(hierarchy_design): # The pins get added from the spice file 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)) - self.add_pin_types(prop.port_types) + self.add_pin_types(prop.port_types()) (width, height) = utils.get_libcell_size(self.cell_name, GDS["unit"], diff --git a/compiler/bitcells/bitcell_base.py b/compiler/bitcells/bitcell_base.py index dc4198c4..3f23d1e3 100644 --- a/compiler/bitcells/bitcell_base.py +++ b/compiler/bitcells/bitcell_base.py @@ -23,7 +23,7 @@ class bitcell_base(design.design): if prop: self.pins = prop.port_names() - self.add_pin_types(prop.port_types) + self.add_pin_types(prop.port_types()) self.nets_match = self.do_nets_exist(prop.storage_nets) self.mirror = prop.mirror self.end_caps = prop.end_caps diff --git a/compiler/modules/dff_buf.py b/compiler/modules/dff_buf.py index 6f168a74..6d35a24f 100644 --- a/compiler/modules/dff_buf.py +++ b/compiler/modules/dff_buf.py @@ -73,7 +73,7 @@ class dff_buf(design.design): def add_pins(self): self.add_pin_list(props.dff_buf.port_names(), - props.dff_buf.port_types) + props.dff_buf.port_types()) def create_instances(self): self.dff_inst=self.add_inst(name="dff_buf_dff", From b4342ac5278b107f361f8bc7af1a2c5f14746058 Mon Sep 17 00:00:00 2001 From: mrg Date: Fri, 13 Nov 2020 17:29:20 -0800 Subject: [PATCH 20/31] More cleanup --- compiler/base/custom_cell_properties.py | 20 ++++---------------- compiler/bitcells/bitcell_base.py | 1 + compiler/custom/dff.py | 3 --- compiler/custom/sense_amp.py | 2 +- 4 files changed, 6 insertions(+), 20 deletions(-) diff --git a/compiler/base/custom_cell_properties.py b/compiler/base/custom_cell_properties.py index 0a8f4eb6..ada35ed8 100644 --- a/compiler/base/custom_cell_properties.py +++ b/compiler/base/custom_cell_properties.py @@ -70,26 +70,14 @@ class _bitcell(_cell): def __init__(self, port_order, port_types, port_map=None, storage_nets=["Q", "Q_bar"], mirror=None, end_caps=False): super().__init__(port_order, port_types, port_map) - self._end_caps = end_caps + self.end_caps = end_caps if not mirror: - self._mirror = _mirror_axis(True, False) + self.mirror = _mirror_axis(True, False) else: - self._mirror = mirror + self.mirror = mirror - self._storage_nets = storage_nets - - @property - def end_caps(self): - return self._end_caps - - @property - def mirror(self): - return self._mirror - - @property - def storage_nets(self): - return self._storage_nets + self.storage_nets = storage_nets class cell_properties(): diff --git a/compiler/bitcells/bitcell_base.py b/compiler/bitcells/bitcell_base.py index 3f23d1e3..c3110146 100644 --- a/compiler/bitcells/bitcell_base.py +++ b/compiler/bitcells/bitcell_base.py @@ -24,6 +24,7 @@ class bitcell_base(design.design): if prop: self.pins = prop.port_names() self.add_pin_types(prop.port_types()) + self.storage_nets = prop.storage_nets self.nets_match = self.do_nets_exist(prop.storage_nets) self.mirror = prop.mirror self.end_caps = prop.end_caps diff --git a/compiler/custom/dff.py b/compiler/custom/dff.py index 2a73b1e8..62af01ff 100644 --- a/compiler/custom/dff.py +++ b/compiler/custom/dff.py @@ -7,7 +7,6 @@ # import design from tech import spice -from tech import cell_properties as props class dff(design.design): @@ -18,8 +17,6 @@ class dff(design.design): def __init__(self, name="dff"): super().__init__(name) - self.clk_pin = props.dff.pin.clk - def analytical_power(self, corner, load): """Returns dynamic and leakage power. Results in nW""" c_eff = self.calculate_effective_capacitance(load) diff --git a/compiler/custom/sense_amp.py b/compiler/custom/sense_amp.py index 61ab39a5..592feb57 100644 --- a/compiler/custom/sense_amp.py +++ b/compiler/custom/sense_amp.py @@ -67,7 +67,7 @@ class sense_amp(design.design): """Returns name used for enable net""" # FIXME: A better programmatic solution to designate pins enable_name = self.en_name - debug.check(enable_name in self.pin_names, "Enable name {} not found in pin list".format(enable_name)) + debug.check(enable_name in self.pins, "Enable name {} not found in pin list".format(enable_name)) return enable_name def build_graph(self, graph, inst_name, port_nets): From e9420d57c269118c3f2c930490b2418cc2d6dc78 Mon Sep 17 00:00:00 2001 From: mrg Date: Fri, 13 Nov 2020 19:04:26 -0800 Subject: [PATCH 21/31] Fix missing attributes --- compiler/bitcells/replica_bitcell_2port.py | 2 +- compiler/modules/dff_array.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/compiler/bitcells/replica_bitcell_2port.py b/compiler/bitcells/replica_bitcell_2port.py index d5922b80..3c7225e7 100644 --- a/compiler/bitcells/replica_bitcell_2port.py +++ b/compiler/bitcells/replica_bitcell_2port.py @@ -42,7 +42,7 @@ class replica_bitcell_2port(bitcell_base.bitcell_base): """Adds edges to graph. Multiport bitcell timing graph is too complex to use the add_graph_edges function.""" pin_dict = {pin: port for pin, port in zip(self.pins, port_nets)} - pins = props.bitcell.cell_2port.pin + pins = props.bitcell_2port.pin # Edges hardcoded here. Essentially wl->bl/br for both ports. # Port 0 edges graph.add_edge(pin_dict[pins.wl0], pin_dict[pins.bl0], self) diff --git a/compiler/modules/dff_array.py b/compiler/modules/dff_array.py index a2ea7eeb..ba72b7fa 100644 --- a/compiler/modules/dff_array.py +++ b/compiler/modules/dff_array.py @@ -7,6 +7,7 @@ # import debug import design +from tech import custom_properties as props from vector import vector from sram_factory import factory from globals import OPTS @@ -137,7 +138,7 @@ class dff_array(design.design): height=dout_pin.height()) # Create vertical spines to a single horizontal rail - clk_pin = self.dff_insts[0, 0].get_pin(self.dff.clk_pin) + clk_pin = self.dff_insts[0, 0].get_pin(props.dff.pin.clk) clk_ypos = 2 * self.m3_pitch + self.m3_width debug.check(clk_pin.layer == "m2", "DFF clk pin not on metal2") self.add_layout_pin_segment_center(text="clk", From 1624d50ca9c82dabdc4b667c57aadc23910360c0 Mon Sep 17 00:00:00 2001 From: mrg Date: Fri, 13 Nov 2020 20:35:19 -0800 Subject: [PATCH 22/31] Fix props bug again. --- compiler/modules/dff_array.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/modules/dff_array.py b/compiler/modules/dff_array.py index ba72b7fa..6b708552 100644 --- a/compiler/modules/dff_array.py +++ b/compiler/modules/dff_array.py @@ -7,7 +7,7 @@ # import debug import design -from tech import custom_properties as props +from tech import cell_properties as props from vector import vector from sram_factory import factory from globals import OPTS @@ -146,7 +146,7 @@ class dff_array(design.design): start=vector(0, clk_ypos), end=vector(self.width, clk_ypos)) for col in range(self.columns): - clk_pin = self.dff_insts[0, col].get_pin(self.dff.clk_pin) + clk_pin = self.dff_insts[0, col].get_pin(props.dff.pin.clk) # Make a vertical strip for each column self.add_rect(layer="m2", offset=clk_pin.ll().scale(1, 0), From 2f994b8c0adf6fe3fc0063d47c04a15a066a5f16 Mon Sep 17 00:00:00 2001 From: mrg Date: Sat, 14 Nov 2020 07:15:27 -0800 Subject: [PATCH 23/31] Change custom cells to use set_ports setter --- compiler/base/custom_cell_properties.py | 31 ++++++++++++++------- compiler/base/design.py | 6 ++-- compiler/bitcells/bitcell_base.py | 4 +-- compiler/modules/dff_buf.py | 4 +-- compiler/tests/30_openram_back_end_test.py | 8 +++--- compiler/tests/30_openram_front_end_test.py | 8 +++--- 6 files changed, 36 insertions(+), 25 deletions(-) diff --git a/compiler/base/custom_cell_properties.py b/compiler/base/custom_cell_properties.py index ada35ed8..dbe62bd0 100644 --- a/compiler/base/custom_cell_properties.py +++ b/compiler/base/custom_cell_properties.py @@ -10,18 +10,27 @@ class _cell: def __init__(self, port_order, port_types, port_map=None, hard_cell=True, boundary_layer="boundary"): # Specifies if this is a hard (i.e. GDS) cell self._hard_cell = hard_cell - # Specifies the order in the spice modules - self._port_order = port_order + self._boundary_layer = boundary_layer # Specifies the port directions - self._port_types = {x: y for (x, y) in zip(port_order, port_types)} + self._port_types_map = {x: y for (x, y) in zip(port_order, port_types)} # Specifies a map from OpenRAM names to cell names # by default it is 1:1 if not port_map: port_map = {x: x for x in port_order} + + self.set_ports(port_order, port_map) + + def set_ports(self, + port_order, + port_map): + # Update mapping of names self._pins = _pins(port_map) - - self._boundary_layer = boundary_layer - + self._port_order = port_order + # Update ordered name list + self._port_names = [getattr(self._pins, x) for x in self._port_order] + # Update ordered type list + self._port_types = [self._port_types_map[x] for x in port_order] + @property def pin(self): return self._pins @@ -29,12 +38,14 @@ class _cell: @property def hard_cell(self): return self._hard_cell - - def port_names(self): - return [getattr(self._pins, x) for x in self._port_order] + @property + def port_names(self): + return self._port_names + + @property def port_types(self): - return [self._port_types[x] for x in self._port_order] + return self._port_types @property def boundary_layer(self): diff --git a/compiler/base/design.py b/compiler/base/design.py index e4e8f7ea..98c03981 100644 --- a/compiler/base/design.py +++ b/compiler/base/design.py @@ -37,9 +37,9 @@ class design(hierarchy_design): prop = getattr(props, name) if prop.hard_cell: # The pins get added from the spice file - 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)) - self.add_pin_types(prop.port_types()) + 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)) + self.add_pin_types(prop.port_types) (width, height) = utils.get_libcell_size(self.cell_name, GDS["unit"], diff --git a/compiler/bitcells/bitcell_base.py b/compiler/bitcells/bitcell_base.py index c3110146..6adc2f48 100644 --- a/compiler/bitcells/bitcell_base.py +++ b/compiler/bitcells/bitcell_base.py @@ -22,8 +22,8 @@ class bitcell_base(design.design): design.design.__init__(self, name) if prop: - self.pins = prop.port_names() - self.add_pin_types(prop.port_types()) + self.pins = prop.port_names + self.add_pin_types(prop.port_types) self.storage_nets = prop.storage_nets self.nets_match = self.do_nets_exist(prop.storage_nets) self.mirror = prop.mirror diff --git a/compiler/modules/dff_buf.py b/compiler/modules/dff_buf.py index 6d35a24f..a650214e 100644 --- a/compiler/modules/dff_buf.py +++ b/compiler/modules/dff_buf.py @@ -72,8 +72,8 @@ class dff_buf(design.design): self.add_mod(self.inv2) def add_pins(self): - self.add_pin_list(props.dff_buf.port_names(), - props.dff_buf.port_types()) + self.add_pin_list(props.dff_buf.port_names, + props.dff_buf.port_types) def create_instances(self): self.dff_inst=self.add_inst(name="dff_buf_dff", diff --git a/compiler/tests/30_openram_back_end_test.py b/compiler/tests/30_openram_back_end_test.py index 5df0b55a..342d44b6 100755 --- a/compiler/tests/30_openram_back_end_test.py +++ b/compiler/tests/30_openram_back_end_test.py @@ -8,14 +8,14 @@ # import unittest from testutils import * -import sys, os,re,shutil +import sys, os, re, shutil sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS -from sram_factory import factory import debug import getpass + class openram_back_end_test(openram_test): def runTest(self): @@ -25,12 +25,12 @@ class openram_back_end_test(openram_test): debug.info(1, "Testing top-level back-end openram.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()) + 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) + self.assertEqual(os.path.exists(out_path), False) try: os.makedirs(out_path, 0o0750) diff --git a/compiler/tests/30_openram_front_end_test.py b/compiler/tests/30_openram_front_end_test.py index befbe850..71d3a98e 100755 --- a/compiler/tests/30_openram_front_end_test.py +++ b/compiler/tests/30_openram_front_end_test.py @@ -8,14 +8,14 @@ # import unittest from testutils import * -import sys, os,re,shutil +import sys, os, re, shutil sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS -from sram_factory import factory import debug import getpass + class openram_front_end_test(openram_test): def runTest(self): @@ -25,12 +25,12 @@ class openram_front_end_test(openram_test): debug.info(1, "Testing top-level front-end openram.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()) + 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) + self.assertEqual(os.path.exists(out_path), False) try: os.makedirs(out_path, 0o0750) From e4bc2c4914d66dc6ec43ea4a39e8254bf4566bd5 Mon Sep 17 00:00:00 2001 From: mrg Date: Sat, 14 Nov 2020 08:08:42 -0800 Subject: [PATCH 24/31] Update property settings with getters/setters --- compiler/base/custom_cell_properties.py | 59 +++++++++++++++++++--- compiler/base/design.py | 33 ++++++------ compiler/bitcells/bitcell_1port.py | 2 +- compiler/bitcells/bitcell_2port.py | 2 +- compiler/bitcells/bitcell_base.py | 17 ++----- compiler/bitcells/col_cap_bitcell_2port.py | 14 ++--- compiler/bitcells/dummy_bitcell_1port.py | 2 +- compiler/bitcells/dummy_bitcell_2port.py | 2 +- compiler/bitcells/replica_bitcell_1port.py | 2 +- compiler/bitcells/replica_bitcell_2port.py | 2 +- compiler/bitcells/row_cap_bitcell_2port.py | 9 +--- compiler/custom/dff.py | 3 +- compiler/custom/inv_dec.py | 3 +- compiler/custom/nand2_dec.py | 3 +- compiler/custom/nand3_dec.py | 3 +- compiler/custom/nand4_dec.py | 3 +- compiler/custom/sense_amp.py | 2 +- compiler/custom/write_driver.py | 2 +- 18 files changed, 94 insertions(+), 69 deletions(-) diff --git a/compiler/base/custom_cell_properties.py b/compiler/base/custom_cell_properties.py index dbe62bd0..2fab7a2a 100644 --- a/compiler/base/custom_cell_properties.py +++ b/compiler/base/custom_cell_properties.py @@ -18,16 +18,13 @@ class _cell: if not port_map: port_map = {x: x for x in port_order} - self.set_ports(port_order, port_map) - - def set_ports(self, - port_order, - port_map): # Update mapping of names self._pins = _pins(port_map) self._port_order = port_order + # Update ordered name list self._port_names = [getattr(self._pins, x) for x in self._port_order] + # Update ordered type list self._port_types = [self._port_types_map[x] for x in port_order] @@ -43,6 +40,29 @@ class _cell: def port_names(self): return self._port_names + @property + def port_order(self): + return self._port_order + + @port_order.setter + def port_order(self, x): + self._port_order = x + # Update ordered name list in the new order + self._port_names = [getattr(self._pins, x) for x in self._port_order] + # Update ordered type list in the new order + self._port_types = [self._port_types_map[x] for x in self._port_order] + + @property + def port_map(self): + return self._port_map + + @port_map.setter + def port_map(self, x): + self._port_map = x + self._pins = _pins(x) + # Update ordered name list to use the new names + self._port_names = [getattr(self._pins, x) for x in self._port_order] + @property def port_types(self): return self._port_types @@ -50,7 +70,11 @@ class _cell: @property def boundary_layer(self): return self._boundary_layer - + + @boundary_layer.setter + def boundary_layer(self, x): + self._boundary_layer = x + class _pins: def __init__(self, pin_dict): @@ -116,13 +140,16 @@ class cell_properties(): self._pgate = _pgate(add_implants=False) + self._inv_dec = _cell(["A", "Z", "vdd", "gnd"], + ["INPUT", "OUTPUT", "POWER", "GROUND"]) + self._nand2_dec = _cell(["A", "B", "Z", "vdd", "gnd"], ["INPUT", "INPUT", "OUTPUT", "POWER", "GROUND"]) - self._nand2_dec = _cell(["A", "B", "C", "Z", "vdd", "gnd"], + self._nand3_dec = _cell(["A", "B", "C", "Z", "vdd", "gnd"], ["INPUT", "INPUT", "INPUT", "OUTPUT", "POWER", "GROUND"]) - self._nand2_dec = _cell(["A", "B", "C", "D", "Z", "vdd", "gnd"], + self._nand4_dec = _cell(["A", "B", "C", "D", "Z", "vdd", "gnd"], ["INPUT", "INPUT", "INPUT", "INPUT", "OUTPUT", "POWER", "GROUND"]) self._dff = _cell(["D", "Q", "clk", "vdd", "gnd"], @@ -152,6 +179,22 @@ class cell_properties(): def pgate(self): return self._pgate + @property + def inv_dec(self): + return self._inv_dec + + @property + def nand2_dec(self): + return self._nand2_dec + + @property + def nand3_dec(self): + return self._nand3_dec + + @property + def nand4_dec(self): + return self._nand4_dec + @property def dff(self): return self._dff diff --git a/compiler/base/design.py b/compiler/base/design.py index 98c03981..8b2fe826 100644 --- a/compiler/base/design.py +++ b/compiler/base/design.py @@ -22,7 +22,7 @@ class design(hierarchy_design): some DRC/layer constants and analytical models for other modules to reuse. """ - def __init__(self, name, cell_name=None): + def __init__(self, name, cell_name=None, prop=None): # This allows us to use different GDS/spice circuits for hard cells instead of the default ones # Except bitcell names are generated automatically by the globals.py setup_bitcells routines # depending on the number of ports. @@ -32,25 +32,24 @@ class design(hierarchy_design): cell_name = name super().__init__(name, cell_name) - # This means it is a custom cell... - if hasattr(props, name): - prop = getattr(props, name) - if prop.hard_cell: - # The pins get added from the spice file - 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)) - self.add_pin_types(prop.port_types) + # This means it is a custom cell. + # It could have properties and not be a hard cell too (e.g. dff_buf) + if prop and prop.hard_cell: + # The pins get added from the spice file + 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)) + self.add_pin_types(prop.port_types) - (width, height) = utils.get_libcell_size(self.cell_name, - GDS["unit"], - layer[prop.boundary_layer]) + (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.cell_name, - GDS["unit"]) + self.pin_map = utils.get_libcell_pins(self.pins, + self.cell_name, + GDS["unit"]) - self.width = width - self.height = height + self.width = width + self.height = height self.setup_multiport_constants() diff --git a/compiler/bitcells/bitcell_1port.py b/compiler/bitcells/bitcell_1port.py index e8f330f1..947b9435 100644 --- a/compiler/bitcells/bitcell_1port.py +++ b/compiler/bitcells/bitcell_1port.py @@ -19,7 +19,7 @@ class bitcell_1port(bitcell_base.bitcell_base): """ def __init__(self, name): - super().__init__(name, props.bitcell_1port) + super().__init__(name, prop=props.bitcell_1port) debug.info(2, "Create bitcell") def get_all_wl_names(self): diff --git a/compiler/bitcells/bitcell_2port.py b/compiler/bitcells/bitcell_2port.py index 2293cb71..a99f8219 100644 --- a/compiler/bitcells/bitcell_2port.py +++ b/compiler/bitcells/bitcell_2port.py @@ -19,7 +19,7 @@ class bitcell_2port(bitcell_base.bitcell_base): """ def __init__(self, name): - super().__init__(name, props.bitcell_2port) + super().__init__(name, prop=props.bitcell_2port) debug.info(2, "Create bitcell with 2 ports") self.bl_names = [props.bitcell_2port.pin.bl0, props.bitcell_2port.pin.bl1] diff --git a/compiler/bitcells/bitcell_base.py b/compiler/bitcells/bitcell_base.py index 6adc2f48..40e0a02e 100644 --- a/compiler/bitcells/bitcell_base.py +++ b/compiler/bitcells/bitcell_base.py @@ -8,34 +8,25 @@ import debug import design -import utils from globals import OPTS import logical_effort -from tech import GDS, parameter, drc, layer +from tech import parameter, drc, layer class bitcell_base(design.design): """ Base bitcell parameters to be over-riden. """ - def __init__(self, name, prop=None): - design.design.__init__(self, name) + def __init__(self, name, cell_name=None, prop=None): + design.design.__init__(self, name, cell_name, prop) + # Set the bitcell specific properties if prop: - self.pins = prop.port_names - self.add_pin_types(prop.port_types) self.storage_nets = prop.storage_nets self.nets_match = self.do_nets_exist(prop.storage_nets) self.mirror = prop.mirror self.end_caps = prop.end_caps - (self.width, self.height) = utils.get_libcell_size(self.cell_name, - GDS["unit"], - layer[prop.boundary_layer]) - self.pin_map = utils.get_libcell_pins(self.pins, - self.cell_name, - GDS["unit"]) - def get_stage_effort(self, load): parasitic_delay = 1 # This accounts for bitline being drained diff --git a/compiler/bitcells/col_cap_bitcell_2port.py b/compiler/bitcells/col_cap_bitcell_2port.py index 910e25ea..dc3954b0 100644 --- a/compiler/bitcells/col_cap_bitcell_2port.py +++ b/compiler/bitcells/col_cap_bitcell_2port.py @@ -10,21 +10,13 @@ from tech import cell_properties as props import bitcell_base -class col_cap_bitcell_1rw_1r(bitcell_base.bitcell_base): +class col_cap_bitcell_2port(bitcell_base.bitcell_base): """ Column end cap cell. """ - pin_names = [props.bitcell.cell_1rw1r.pin.bl0, - props.bitcell.cell_1rw1r.pin.br0, - props.bitcell.cell_1rw1r.pin.bl1, - props.bitcell.cell_1rw1r.pin.br1, - props.bitcell.cell_1rw1r.pin.vdd] - type_list = ["OUTPUT", "OUTPUT", "OUTPUT", "OUTPUT", - "POWER", "GROUND"] - def __init__(self, name="col_cap_cell_1rw_1r"): - bitcell_base.bitcell_base.__init__(self, name) - debug.info(2, "Create col_cap bitcell 1rw+1r object") + bitcell_base.bitcell_base.__init__(self, name, prop=props.bitcell_2port) + debug.info(2, "Create col_cap bitcell 2 port object") self.no_instances = True diff --git a/compiler/bitcells/dummy_bitcell_1port.py b/compiler/bitcells/dummy_bitcell_1port.py index c6f98536..2ff836c1 100644 --- a/compiler/bitcells/dummy_bitcell_1port.py +++ b/compiler/bitcells/dummy_bitcell_1port.py @@ -18,7 +18,7 @@ class dummy_bitcell_1port(bitcell_base.bitcell_base): library. """ def __init__(self, name): - super().__init__(name, props.bitcell_1port) + super().__init__(name, prop=props.bitcell_1port) debug.info(2, "Create dummy bitcell") diff --git a/compiler/bitcells/dummy_bitcell_2port.py b/compiler/bitcells/dummy_bitcell_2port.py index 14b0ce96..5ed56f09 100644 --- a/compiler/bitcells/dummy_bitcell_2port.py +++ b/compiler/bitcells/dummy_bitcell_2port.py @@ -18,7 +18,7 @@ class dummy_bitcell_2port(bitcell_base.bitcell_base): the technology library. """ def __init__(self, name): - super().__init__(name, props.bitcell_2port) + super().__init__(name, prop=props.bitcell_2port) debug.info(2, "Create dummy bitcell 2 port object") diff --git a/compiler/bitcells/replica_bitcell_1port.py b/compiler/bitcells/replica_bitcell_1port.py index 1f2826ec..58087b97 100644 --- a/compiler/bitcells/replica_bitcell_1port.py +++ b/compiler/bitcells/replica_bitcell_1port.py @@ -20,7 +20,7 @@ class replica_bitcell_1port(bitcell_base.bitcell_base): the technology library. """ def __init__(self, name): - super().__init__(name, props.bitcell_1port) + super().__init__(name, prop=props.bitcell_1port) debug.info(2, "Create replica bitcell object") def get_stage_effort(self, load): diff --git a/compiler/bitcells/replica_bitcell_2port.py b/compiler/bitcells/replica_bitcell_2port.py index 3c7225e7..2a3fbb48 100644 --- a/compiler/bitcells/replica_bitcell_2port.py +++ b/compiler/bitcells/replica_bitcell_2port.py @@ -20,7 +20,7 @@ class replica_bitcell_2port(bitcell_base.bitcell_base): the technology library. """ def __init__(self, name): - super().__init__(name, props.bitcell_2port) + super().__init__(name, prop=props.bitcell_2port) debug.info(2, "Create replica bitcell 2 port object") def get_stage_effort(self, load): diff --git a/compiler/bitcells/row_cap_bitcell_2port.py b/compiler/bitcells/row_cap_bitcell_2port.py index 6d6dfe16..cdc49318 100644 --- a/compiler/bitcells/row_cap_bitcell_2port.py +++ b/compiler/bitcells/row_cap_bitcell_2port.py @@ -10,18 +10,13 @@ from tech import cell_properties as props import bitcell_base -class row_cap_bitcell_1rw_1r(bitcell_base.bitcell_base): +class row_cap_bitcell_2port(bitcell_base.bitcell_base): """ Row end cap cell. """ - pin_names = [props.bitcell.cell_1rw1r.pin.wl0, - props.bitcell.cell_1rw1r.pin.wl1, - props.bitcell.cell_1rw1r.pin.gnd] - type_list = ["INPUT", "INPUT", "GROUND"] - def __init__(self, name="row_cap_cell_1rw_1r"): - bitcell_base.bitcell_base.__init__(self, name) + bitcell_base.bitcell_base.__init__(self, name, prop=props.bitcell_2port) debug.info(2, "Create row_cap bitcell 1rw+1r object") self.no_instances = True diff --git a/compiler/custom/dff.py b/compiler/custom/dff.py index 62af01ff..b0c2b5a8 100644 --- a/compiler/custom/dff.py +++ b/compiler/custom/dff.py @@ -6,6 +6,7 @@ # All rights reserved. # import design +from tech import cell_properties as props from tech import spice @@ -15,7 +16,7 @@ class dff(design.design): """ def __init__(self, name="dff"): - super().__init__(name) + super().__init__(name, prop=props.dff) def analytical_power(self, corner, load): """Returns dynamic and leakage power. Results in nW""" diff --git a/compiler/custom/inv_dec.py b/compiler/custom/inv_dec.py index be4099aa..a1bb0c83 100644 --- a/compiler/custom/inv_dec.py +++ b/compiler/custom/inv_dec.py @@ -7,6 +7,7 @@ # import design import logical_effort +from tech import cell_properties as props from tech import spice, parameter @@ -16,7 +17,7 @@ class inv_dec(design.design): """ def __init__(self, name="inv_dec", height=None): - super().__init__(name) + super().__init__(name, prop=props.inv_dec) def analytical_power(self, corner, load): """Returns dynamic and leakage power. Results in nW""" diff --git a/compiler/custom/nand2_dec.py b/compiler/custom/nand2_dec.py index 2ea07ed6..b5c48a15 100644 --- a/compiler/custom/nand2_dec.py +++ b/compiler/custom/nand2_dec.py @@ -7,6 +7,7 @@ # import design from tech import spice, parameter, drc +from tech import cell_properties as props import logical_effort @@ -16,7 +17,7 @@ class nand2_dec(design.design): """ def __init__(self, name="nand2_dec", height=None): - super().__init__(name) + super().__init__(name, prop=props.nand2_dec) # FIXME: For now... size = 1 diff --git a/compiler/custom/nand3_dec.py b/compiler/custom/nand3_dec.py index d362e2d6..2713fde9 100644 --- a/compiler/custom/nand3_dec.py +++ b/compiler/custom/nand3_dec.py @@ -7,6 +7,7 @@ # import design from tech import spice, parameter, drc +from tech import cell_properties as props import logical_effort @@ -16,7 +17,7 @@ class nand3_dec(design.design): """ def __init__(self, name="nand3_dec", height=None): - super().__init__(name) + super().__init__(name, prop=props.nand3_dec) # FIXME: For now... size = 1 diff --git a/compiler/custom/nand4_dec.py b/compiler/custom/nand4_dec.py index 0df86845..5fab2d36 100644 --- a/compiler/custom/nand4_dec.py +++ b/compiler/custom/nand4_dec.py @@ -7,6 +7,7 @@ # import design from tech import spice, parameter, drc +from tech import cell_properties as props import logical_effort @@ -16,7 +17,7 @@ class nand4_dec(design.design): """ def __init__(self, name="nand4_dec", height=None): - super().__init__(name) + super().__init__(name, prop=props.nand4_dec) # FIXME: For now... size = 1 diff --git a/compiler/custom/sense_amp.py b/compiler/custom/sense_amp.py index 592feb57..4376bf85 100644 --- a/compiler/custom/sense_amp.py +++ b/compiler/custom/sense_amp.py @@ -21,7 +21,7 @@ class sense_amp(design.design): """ def __init__(self, name="sense_amp"): - super().__init__(name) + super().__init__(name, prop=props.sense_amp) debug.info(2, "Create sense_amp") def get_bl_names(self): diff --git a/compiler/custom/write_driver.py b/compiler/custom/write_driver.py index bcef46e1..c30501c9 100644 --- a/compiler/custom/write_driver.py +++ b/compiler/custom/write_driver.py @@ -19,7 +19,7 @@ class write_driver(design.design): """ def __init__(self, name): - super().__init__(name) + super().__init__(name, prop=props.write_driver) debug.info(2, "Create write_driver") def get_bl_names(self): From 7512aa6e7046e021db9d65e72d5b0d9912502f70 Mon Sep 17 00:00:00 2001 From: mrg Date: Mon, 16 Nov 2020 08:59:25 -0800 Subject: [PATCH 25/31] Skip test 50 which is too slow --- compiler/tests/50_riscv_phys_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/tests/50_riscv_phys_test.py b/compiler/tests/50_riscv_phys_test.py index 5f3d7d59..9b202b9e 100755 --- a/compiler/tests/50_riscv_phys_test.py +++ b/compiler/tests/50_riscv_phys_test.py @@ -16,7 +16,7 @@ from sram_factory import factory import debug -#@unittest.skip("SKIPPING 50_riscv_phys_test") +@unittest.skip("SKIPPING 50_riscv_phys_test") class riscv_phys_test(openram_test): def runTest(self): From 93e94e26ec2d7fe3a0d0ac5248eb3e6d013bd038 Mon Sep 17 00:00:00 2001 From: mrg Date: Mon, 16 Nov 2020 10:14:37 -0800 Subject: [PATCH 26/31] Get vdd/gnd from properties if it is defined. --- compiler/base/hierarchy_design.py | 2 -- compiler/base/hierarchy_layout.py | 3 +++ compiler/base/hierarchy_spice.py | 2 +- compiler/bitcells/bitcell_base.py | 3 +++ compiler/modules/bitcell_base_array.py | 6 +++--- 5 files changed, 10 insertions(+), 6 deletions(-) diff --git a/compiler/base/hierarchy_design.py b/compiler/base/hierarchy_design.py index 17022424..0a08c995 100644 --- a/compiler/base/hierarchy_design.py +++ b/compiler/base/hierarchy_design.py @@ -40,8 +40,6 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout): self.drc_errors = "skipped" self.lvs_errors = "skipped" - self.name = name - self.cell_name = cell_name hierarchy_spice.spice.__init__(self, name, cell_name) hierarchy_layout.layout.__init__(self, name, cell_name) self.init_graph_params() diff --git a/compiler/base/hierarchy_layout.py b/compiler/base/hierarchy_layout.py index 67482f61..a4e121f7 100644 --- a/compiler/base/hierarchy_layout.py +++ b/compiler/base/hierarchy_layout.py @@ -32,8 +32,10 @@ class layout(): """ def __init__(self, name, cell_name): + # This gets set in both spice and layout so either can be called first. self.name = name self.cell_name = cell_name + self.width = None self.height = None self.bounding_box = None @@ -43,6 +45,7 @@ class layout(): self.pin_map = {} # Holds name->pin_layout map for all pins self.visited = [] # List of modules we have already visited self.is_library_cell = False # Flag for library cells + self.gds_read() try: diff --git a/compiler/base/hierarchy_spice.py b/compiler/base/hierarchy_spice.py index 60d80513..ab3bd5c3 100644 --- a/compiler/base/hierarchy_spice.py +++ b/compiler/base/hierarchy_spice.py @@ -28,6 +28,7 @@ class spice(): """ def __init__(self, name, cell_name): + # This gets set in both spice and layout so either can be called first. self.name = name self.cell_name = cell_name @@ -78,7 +79,6 @@ class spice(): """ Adds a pin_list to the pins list """ # The 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: for pin in pin_list: debug.check(pin_type in self.valid_signal_types, diff --git a/compiler/bitcells/bitcell_base.py b/compiler/bitcells/bitcell_base.py index 40e0a02e..6ab81320 100644 --- a/compiler/bitcells/bitcell_base.py +++ b/compiler/bitcells/bitcell_base.py @@ -26,6 +26,9 @@ class bitcell_base(design.design): self.nets_match = self.do_nets_exist(prop.storage_nets) self.mirror = prop.mirror self.end_caps = prop.end_caps + self.supplies = [prop.pin.vdd, prop.pin.gnd] + else: + self.supplies = ["vdd", "gnd"] def get_stage_effort(self, load): parasitic_delay = 1 diff --git a/compiler/modules/bitcell_base_array.py b/compiler/modules/bitcell_base_array.py index 95e8a4ec..088308f9 100644 --- a/compiler/modules/bitcell_base_array.py +++ b/compiler/modules/bitcell_base_array.py @@ -35,10 +35,10 @@ class bitcell_base_array(design.design): self.rbl_wordline_names = [[] for port in self.all_ports] self.all_rbl_wordline_names = [] - # The supply pin namesn - self.bitcell_supplies = ["vdd", "gnd"] + # The supply pin names + self.bitcell_supplies = self.cell.supplies # If the technology needs renaming of the supplies - self.supplies = self.bitcell_supplies + self.supplies = ["vdd", "gnd"] def create_all_bitline_names(self): for col in range(self.column_size): From 1d729e8f02643f50a3a84a8453d7a9aad23d5d9d Mon Sep 17 00:00:00 2001 From: mrg Date: Mon, 16 Nov 2020 11:04:03 -0800 Subject: [PATCH 27/31] Move pin name mapping to layout class. --- compiler/base/custom_cell_properties.py | 14 +++--- compiler/base/design.py | 4 +- compiler/base/hierarchy_layout.py | 50 ++++++++++++++++------ compiler/bitcells/bitcell_1port.py | 16 +++---- compiler/bitcells/bitcell_2port.py | 43 ++++++++----------- compiler/bitcells/bitcell_base.py | 5 +-- compiler/bitcells/replica_bitcell_2port.py | 9 ++-- compiler/custom/sense_amp.py | 8 ++-- compiler/custom/write_driver.py | 8 ++-- compiler/modules/control_logic.py | 1 - compiler/modules/dff_array.py | 5 +-- compiler/modules/dff_buf.py | 27 ++++++------ compiler/modules/dff_buf_array.py | 3 +- 13 files changed, 101 insertions(+), 92 deletions(-) diff --git a/compiler/base/custom_cell_properties.py b/compiler/base/custom_cell_properties.py index 2fab7a2a..d45bad10 100644 --- a/compiler/base/custom_cell_properties.py +++ b/compiler/base/custom_cell_properties.py @@ -8,30 +8,28 @@ class _cell: def __init__(self, port_order, port_types, port_map=None, hard_cell=True, boundary_layer="boundary"): + # Specifies if this is a hard (i.e. GDS) cell self._hard_cell = hard_cell self._boundary_layer = boundary_layer + # Specifies the port directions self._port_types_map = {x: y for (x, y) in zip(port_order, port_types)} + # Specifies a map from OpenRAM names to cell names # by default it is 1:1 if not port_map: - port_map = {x: x for x in port_order} + self._port_map = {x: x for x in port_order} # Update mapping of names - self._pins = _pins(port_map) self._port_order = port_order # Update ordered name list - self._port_names = [getattr(self._pins, x) for x in self._port_order] + self._port_names = [self._port_map[x] for x in self._port_order] # Update ordered type list - self._port_types = [self._port_types_map[x] for x in port_order] + self._port_types = [self._port_types_map[x] for x in self._port_order] - @property - def pin(self): - return self._pins - @property def hard_cell(self): return self._hard_cell diff --git a/compiler/base/design.py b/compiler/base/design.py index 8b2fe826..f90ea12c 100644 --- a/compiler/base/design.py +++ b/compiler/base/design.py @@ -35,9 +35,11 @@ class design(hierarchy_design): # This means it is a custom cell. # It could have properties and not be a hard cell too (e.g. dff_buf) if prop and prop.hard_cell: - # The pins get added from the spice file + # 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)) + self.add_pin_names(prop.port_map) self.add_pin_types(prop.port_types) (width, height) = utils.get_libcell_size(self.cell_name, diff --git a/compiler/base/hierarchy_layout.py b/compiler/base/hierarchy_layout.py index a4e121f7..516b3988 100644 --- a/compiler/base/hierarchy_layout.py +++ b/compiler/base/hierarchy_layout.py @@ -39,12 +39,21 @@ class layout(): self.width = None self.height = None self.bounding_box = None - self.insts = [] # Holds module/cell layout instances - self.inst_names = set() # Set of names to check for duplicates - self.objs = [] # Holds all other objects (labels, geometries, etc) - self.pin_map = {} # Holds name->pin_layout map for all pins - self.visited = [] # List of modules we have already visited - self.is_library_cell = False # Flag for library cells + # Holds module/cell layout instances + self.insts = [] + # Set of names to check for duplicates + self.inst_names = set() + # Holds all other objects (labels, geometries, etc) + self.objs = [] + # This is a mapping of internal pin names to cell pin names + # If the key is not found, the internal pin names is assumed + self.pin_names = {} + # Holds name->pin_layout map for all pins + self.pin_map = {} + # List of modules we have already visited + self.visited = [] + # Flag for library cells + self.is_library_cell = False self.gds_read() @@ -54,8 +63,13 @@ class layout(): except ImportError: self.pwr_grid_layer = "m3" - - + def add_pin_names(self, pin_dict): + """ + Create a mapping from internal pin names to external pin names. + """ + self.pin_names = pin_dict + + ############################################################ # GDS layout ############################################################ @@ -311,23 +325,33 @@ class layout(): """ Return the pin or list of pins """ + if text in self.pin_names: + name = self.pin_names[text] + else: + name = text + try: - if len(self.pin_map[text]) > 1: + if len(self.pin_map[name]) > 1: debug.error("Should use a pin iterator since more than one pin {}".format(text), -1) # If we have one pin, return it and not the list. # Otherwise, should use get_pins() - any_pin = next(iter(self.pin_map[text])) + any_pin = next(iter(self.pin_map[name])) return any_pin except Exception: self.gds_write("missing_pin.gds") - debug.error("No pin found with name {0} on {1}. Saved as missing_pin.gds.".format(text, self.cell_name), -1) + debug.error("No pin found with name {0} on {1}. Saved as missing_pin.gds.".format(name, self.cell_name), -1) def get_pins(self, text): """ Return a pin list (instead of a single pin) """ - if text in self.pin_map.keys(): - return self.pin_map[text] + if text in self.pin_names: + name = self.pin_names[text] + else: + name = text + + if name in self.pin_map.keys(): + return self.pin_map[name] else: return set() diff --git a/compiler/bitcells/bitcell_1port.py b/compiler/bitcells/bitcell_1port.py index 947b9435..f3ff4d10 100644 --- a/compiler/bitcells/bitcell_1port.py +++ b/compiler/bitcells/bitcell_1port.py @@ -24,37 +24,35 @@ class bitcell_1port(bitcell_base.bitcell_base): def get_all_wl_names(self): """ Creates a list of all wordline pin names """ - row_pins = [props.bitcell_1port.pin.wl] + row_pins = ["wl"] return row_pins def get_all_bitline_names(self): """ Creates a list of all bitline pin names (both bl and br) """ - pin = props.bitcell_1port.pin - column_pins = [pin.bl, pin.br] - return column_pins + return ["bl", "br"] def get_all_bl_names(self): """ Creates a list of all bl pins names """ - return [props.bitcell_1port.pin.bl] + return ["bl"] def get_all_br_names(self): """ Creates a list of all br pins names """ - return [props.bitcell_1port.pin.br] + return ["br"] def get_bl_name(self, port=0): """Get bl name""" debug.check(port == 0, "One port for bitcell only.") - return props.bitcell_1port.pin.bl + return "bl" def get_br_name(self, port=0): """Get bl name""" debug.check(port == 0, "One port for bitcell only.") - return props.bitcell_1port.pin.br + return "br" def get_wl_name(self, port=0): """Get wl name""" debug.check(port == 0, "One port for bitcell only.") - return props.bitcell_1port.pin.wl + return "wl" def build_graph(self, graph, inst_name, port_nets): """ diff --git a/compiler/bitcells/bitcell_2port.py b/compiler/bitcells/bitcell_2port.py index a99f8219..4833d7c3 100644 --- a/compiler/bitcells/bitcell_2port.py +++ b/compiler/bitcells/bitcell_2port.py @@ -22,65 +22,56 @@ class bitcell_2port(bitcell_base.bitcell_base): super().__init__(name, prop=props.bitcell_2port) debug.info(2, "Create bitcell with 2 ports") - self.bl_names = [props.bitcell_2port.pin.bl0, props.bitcell_2port.pin.bl1] - self.br_names = [props.bitcell_2port.pin.br0, props.bitcell_2port.pin.br1] - self.wl_names = [props.bitcell_2port.pin.wl0, props.bitcell_2port.pin.wl1] + self.bl_names = ["bl0", "bl1"] + self.br_names = ["br0", "br1"] + self.wl_names = ["wl0", "wl1"] def get_bitcell_pins(self, col, row): """ Creates a list of connections in the bitcell, indexed by column and row, for instance use in bitcell_array """ - pin_name = props.bitcell_2port.pin - bitcell_pins = ["{0}_{1}".format(pin_name.bl0, col), - "{0}_{1}".format(pin_name.br0, col), - "{0}_{1}".format(pin_name.bl1, col), - "{0}_{1}".format(pin_name.br1, col), - "{0}_{1}".format(pin_name.wl0, row), - "{0}_{1}".format(pin_name.wl1, row), + bitcell_pins = ["bl0_{0}".format(col), + "br0_{0}".format(col), + "bl1_{0}".format(col), + "br1_{0}".format(col), + "wl0_{0}".format(row), + "wl1_{0}".format(row), "vdd", "gnd"] return bitcell_pins def get_all_wl_names(self): """ Creates a list of all wordline pin names """ - return [props.bitcell_2port.pin.wl0, - props.bitcell_2port.pin.wl1] + return self.wl_names def get_all_bitline_names(self): """ Creates a list of all bitline pin names (both bl and br) """ - return [props.bitcell_2port.pin.bl0, - props.bitcell_2port.pin.br0, - props.bitcell_2port.pin.bl1, - props.bitcell_2port.pin.br1] + return ["bl0", "br0", "bl1", "br1"] def get_all_bl_names(self): """ Creates a list of all bl pins names """ - return [props.bitcell_2port.pin.bl0, - props.bitcell_2port.pin.bl1] + return ["bl0", "bl1"] def get_all_br_names(self): """ Creates a list of all br pins names """ - return [props.bitcell_2port.pin.br0, - props.bitcell_2port.pin.br1] + return ["br0", "br1"] def get_read_bl_names(self): """ Creates a list of bl pin names associated with read ports """ - return [props.bitcell_2port.pin.bl0, - props.bitcell_2port.pin.bl1] + return ["bl0", "bl1"] def get_read_br_names(self): """ Creates a list of br pin names associated with read ports """ - return [props.bitcell_2port.pin.br0, - props.bitcell_2port.pin.br1] + return ["br0", "br1"] def get_write_bl_names(self): """ Creates a list of bl pin names associated with write ports """ - return [props.bitcell_2port.pin.bl0] + return ["bl0"] def get_write_br_names(self): """ Creates a list of br pin names asscociated with write ports""" - return [props.bitcell_2port.pin.br1] + return ["br1"] def get_bl_name(self, port=0): """Get bl name by port""" diff --git a/compiler/bitcells/bitcell_base.py b/compiler/bitcells/bitcell_base.py index 6ab81320..09f33482 100644 --- a/compiler/bitcells/bitcell_base.py +++ b/compiler/bitcells/bitcell_base.py @@ -26,9 +26,8 @@ class bitcell_base(design.design): self.nets_match = self.do_nets_exist(prop.storage_nets) self.mirror = prop.mirror self.end_caps = prop.end_caps - self.supplies = [prop.pin.vdd, prop.pin.gnd] - else: - self.supplies = ["vdd", "gnd"] + + self.supplies = ["vdd", "gnd"] def get_stage_effort(self, load): parasitic_delay = 1 diff --git a/compiler/bitcells/replica_bitcell_2port.py b/compiler/bitcells/replica_bitcell_2port.py index 2a3fbb48..0709ca10 100644 --- a/compiler/bitcells/replica_bitcell_2port.py +++ b/compiler/bitcells/replica_bitcell_2port.py @@ -42,11 +42,10 @@ class replica_bitcell_2port(bitcell_base.bitcell_base): """Adds edges to graph. Multiport bitcell timing graph is too complex to use the add_graph_edges function.""" pin_dict = {pin: port for pin, port in zip(self.pins, port_nets)} - pins = props.bitcell_2port.pin # Edges hardcoded here. Essentially wl->bl/br for both ports. # Port 0 edges - graph.add_edge(pin_dict[pins.wl0], pin_dict[pins.bl0], self) - graph.add_edge(pin_dict[pins.wl0], pin_dict[pins.br0], self) + graph.add_edge(pin_dict["wl0"], pin_dict["bl0"], self) + graph.add_edge(pin_dict["wl0"], pin_dict["br0"], self) # Port 1 edges - graph.add_edge(pin_dict[pins.wl1], pin_dict[pins.bl1], self) - graph.add_edge(pin_dict[pins.wl1], pin_dict[pins.br1], self) + graph.add_edge(pin_dict["wl1"], pin_dict["bl1"], self) + graph.add_edge(pin_dict["wl1"], pin_dict["br1"], self) diff --git a/compiler/custom/sense_amp.py b/compiler/custom/sense_amp.py index 4376bf85..10156e2c 100644 --- a/compiler/custom/sense_amp.py +++ b/compiler/custom/sense_amp.py @@ -25,18 +25,18 @@ class sense_amp(design.design): debug.info(2, "Create sense_amp") def get_bl_names(self): - return props.sense_amp.pin.bl + return "bl" def get_br_names(self): - return props.sense_amp.pin.br + return "br" @property def dout_name(self): - return props.sense_amp.pin.dout + return "dout" @property def en_name(self): - return props.sense_amp.pin.en + return "en" def get_cin(self): diff --git a/compiler/custom/write_driver.py b/compiler/custom/write_driver.py index c30501c9..755fdb03 100644 --- a/compiler/custom/write_driver.py +++ b/compiler/custom/write_driver.py @@ -23,18 +23,18 @@ class write_driver(design.design): debug.info(2, "Create write_driver") def get_bl_names(self): - return props.write_driver.pin.bl + return "bl" def get_br_names(self): - return props.write_driver.pin.br + return "br" @property def din_name(self): - return props.write_driver.pin.din + return "din" @property def en_name(self): - return props.write_driver.pin.en + return "en" def get_w_en_cin(self): """Get the relative capacitance of a single input""" diff --git a/compiler/modules/control_logic.py b/compiler/modules/control_logic.py index 0402eba3..cbef7dfb 100644 --- a/compiler/modules/control_logic.py +++ b/compiler/modules/control_logic.py @@ -6,7 +6,6 @@ # All rights reserved. # import design -from tech import cell_properties as props import debug from sram_factory import factory import math diff --git a/compiler/modules/dff_array.py b/compiler/modules/dff_array.py index 6b708552..82746a06 100644 --- a/compiler/modules/dff_array.py +++ b/compiler/modules/dff_array.py @@ -7,7 +7,6 @@ # import debug import design -from tech import cell_properties as props from vector import vector from sram_factory import factory from globals import OPTS @@ -138,7 +137,7 @@ class dff_array(design.design): height=dout_pin.height()) # Create vertical spines to a single horizontal rail - clk_pin = self.dff_insts[0, 0].get_pin(props.dff.pin.clk) + clk_pin = self.dff_insts[0, 0].get_pin("clk") clk_ypos = 2 * self.m3_pitch + self.m3_width debug.check(clk_pin.layer == "m2", "DFF clk pin not on metal2") self.add_layout_pin_segment_center(text="clk", @@ -146,7 +145,7 @@ class dff_array(design.design): start=vector(0, clk_ypos), end=vector(self.width, clk_ypos)) for col in range(self.columns): - clk_pin = self.dff_insts[0, col].get_pin(props.dff.pin.clk) + clk_pin = self.dff_insts[0, col].get_pin("clk") # Make a vertical strip for each column self.add_rect(layer="m2", offset=clk_pin.ll().scale(1, 0), diff --git a/compiler/modules/dff_buf.py b/compiler/modules/dff_buf.py index a650214e..aea98ea5 100644 --- a/compiler/modules/dff_buf.py +++ b/compiler/modules/dff_buf.py @@ -72,6 +72,7 @@ class dff_buf(design.design): self.add_mod(self.inv2) def add_pins(self): + self.add_pin_names(props.dff_buf.port_map) self.add_pin_list(props.dff_buf.port_names, props.dff_buf.port_types) @@ -79,15 +80,15 @@ class dff_buf(design.design): self.dff_inst=self.add_inst(name="dff_buf_dff", mod=self.dff) - self.connect_inst([props.dff_buf.pin.D, "qint", props.dff_buf.pin.clk, props.dff_buf.pin.vdd, props.dff_buf.pin.gnd]) + self.connect_inst(["D", "qint", "clk", "vdd", "gnd"]) self.inv1_inst=self.add_inst(name="dff_buf_inv1", mod=self.inv1) - self.connect_inst(["qint", "Qb", props.dff_buf.pin.vdd, props.dff_buf.pin.gnd]) + self.connect_inst(["qint", "Qb", "vdd", "gnd"]) self.inv2_inst=self.add_inst(name="dff_buf_inv2", mod=self.inv2) - self.connect_inst(["Qb", props.dff_buf.pin.Q, props.dff_buf.pin.vdd, props.dff_buf.pin.gnd]) + self.connect_inst(["Qb", "Q", "vdd", "gnd"]) def place_instances(self): # Add the DFF @@ -121,7 +122,7 @@ class dff_buf(design.design): self.route_layer = "m1" # Route dff q to inv1 a - q_pin = self.dff_inst.get_pin(props.dff.pin.Q) + q_pin = self.dff_inst.get_pin("Q") a1_pin = self.inv1_inst.get_pin("A") mid1 = vector(a1_pin.cx(), q_pin.cy()) self.add_path(q_pin.layer, [q_pin.center(), mid1, a1_pin.center()], width=q_pin.height()) @@ -138,30 +139,30 @@ class dff_buf(design.design): def add_layout_pins(self): # Continous vdd rail along with label. - vdd_pin=self.dff_inst.get_pin(props.dff.pin.vdd) - self.add_layout_pin(text=props.dff_buf.pin.vdd, + vdd_pin=self.dff_inst.get_pin("vdd") + self.add_layout_pin(text="vdd", layer=vdd_pin.layer, offset=vdd_pin.ll(), width=self.width, height=vdd_pin.height()) # Continous gnd rail along with label. - gnd_pin=self.dff_inst.get_pin(props.dff.pin.gnd) - self.add_layout_pin(text=props.dff_buf.pin.gnd, + gnd_pin=self.dff_inst.get_pin("gnd") + self.add_layout_pin(text="gnd", layer=gnd_pin.layer, offset=gnd_pin.ll(), width=self.width, height=vdd_pin.height()) - clk_pin = self.dff_inst.get_pin(props.dff.pin.clk) - self.add_layout_pin(text=props.dff_buf.pin.clk, + clk_pin = self.dff_inst.get_pin("clk") + self.add_layout_pin(text="clk", layer=clk_pin.layer, offset=clk_pin.ll(), width=clk_pin.width(), height=clk_pin.height()) - din_pin = self.dff_inst.get_pin(props.dff_buf.pin.D) - self.add_layout_pin(text=props.dff_buf.pin.D, + din_pin = self.dff_inst.get_pin("D") + self.add_layout_pin(text="D", layer=din_pin.layer, offset=din_pin.ll(), width=din_pin.width(), @@ -170,7 +171,7 @@ class dff_buf(design.design): dout_pin = self.inv2_inst.get_pin("Z") mid_pos = dout_pin.center() + vector(self.m2_nonpref_pitch, 0) q_pos = mid_pos - vector(0, 2 * self.m2_nonpref_pitch) - self.add_layout_pin_rect_center(text=props.dff_buf.pin.Q, + self.add_layout_pin_rect_center(text="Q", layer="m2", offset=q_pos) self.add_path(self.route_layer, [dout_pin.center(), mid_pos, q_pos]) diff --git a/compiler/modules/dff_buf_array.py b/compiler/modules/dff_buf_array.py index dacc5451..ea811e76 100644 --- a/compiler/modules/dff_buf_array.py +++ b/compiler/modules/dff_buf_array.py @@ -7,7 +7,6 @@ # import debug import design -from tech import cell_properties as props from vector import vector from globals import OPTS from sram_factory import factory @@ -148,7 +147,7 @@ class dff_buf_array(design.design): def route_supplies(self): for row in range(self.rows): - vdd0_pin=self.dff_insts[row, 0].get_pin(props.dff.pin.vdd) + vdd0_pin=self.dff_insts[row, 0].get_pin("vdd") vddn_pin=self.dff_insts[row, self.columns - 1].get_pin("vdd") self.add_path(vdd0_pin.layer, [vdd0_pin.lc(), vddn_pin.rc()], width=vdd0_pin.height()) From 86799ae3ff18e8e2777b238c32b326aca54c78b9 Mon Sep 17 00:00:00 2001 From: mrg Date: Mon, 16 Nov 2020 13:42:42 -0800 Subject: [PATCH 28/31] Small bug fixes related to new name mapping. --- compiler/base/custom_cell_properties.py | 27 +++++++----- compiler/base/geometry.py | 48 ++++++++++------------ compiler/base/hierarchy_layout.py | 2 +- compiler/base/hierarchy_spice.py | 3 +- compiler/bitcells/bitcell_2port.py | 9 ++-- compiler/bitcells/col_cap_bitcell_2port.py | 4 +- compiler/bitcells/row_cap_bitcell_2port.py | 6 +-- compiler/modules/col_cap_array.py | 15 +++---- compiler/modules/dff_buf.py | 6 +-- compiler/modules/replica_column.py | 13 +++--- compiler/modules/row_cap_array.py | 6 +-- 11 files changed, 68 insertions(+), 71 deletions(-) diff --git a/compiler/base/custom_cell_properties.py b/compiler/base/custom_cell_properties.py index d45bad10..e7e2253b 100644 --- a/compiler/base/custom_cell_properties.py +++ b/compiler/base/custom_cell_properties.py @@ -46,7 +46,7 @@ class _cell: def port_order(self, x): self._port_order = x # Update ordered name list in the new order - self._port_names = [getattr(self._pins, x) for x in self._port_order] + self._port_names = [self._port_map[x] for x in self._port_order] # Update ordered type list in the new order self._port_types = [self._port_types_map[x] for x in self._port_order] @@ -57,9 +57,8 @@ class _cell: @port_map.setter def port_map(self, x): self._port_map = x - self._pins = _pins(x) # Update ordered name list to use the new names - self._port_names = [getattr(self._pins, x) for x in self._port_order] + self._port_names = [self.port_map[x] for x in self._port_order] @property def port_types(self): @@ -153,10 +152,6 @@ class cell_properties(): self._dff = _cell(["D", "Q", "clk", "vdd", "gnd"], ["INPUT", "OUTPUT", "INPUT", "POWER", "GROUND"]) - self._dff_buf = _cell(["D", "Q", "Qb", "clk", "vdd", "gnd"], - ["INPUT", "OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"], - hard_cell=False) - self._write_driver = _cell(['din', 'bl', 'br', 'en', 'vdd', 'gnd'], ["INPUT", "OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"]) @@ -169,6 +164,12 @@ class cell_properties(): self._bitcell_2port = _bitcell(["bl0", "br0", "bl1", "br1", "wl0", "wl1", "vdd", "gnd"], ["OUTPUT", "OUTPUT", "OUTPUT", "OUTPUT", "INPUT", "INPUT", "POWER", "GROUND"]) + self._col_cap_2port = _bitcell(["bl0", "br0", "bl1", "br1", "vdd"], + ["OUTPUT", "OUTPUT", "OUTPUT", "OUTPUT", "POWER"]) + + self._row_cap_2port = _bitcell(["wl0", "wl1", "gnd"], + ["INPUT", "INPUT", "POWER", "GROUND"]) + @property def ptx(self): return self._ptx @@ -197,10 +198,6 @@ class cell_properties(): def dff(self): return self._dff - @property - def dff_buf(self): - return self._dff_buf - @property def write_driver(self): return self._write_driver @@ -217,3 +214,11 @@ class cell_properties(): def bitcell_2port(self): return self._bitcell_2port + @property + def col_cap_2port(self): + return self._col_cap_2port + + @property + def row_cap_2port(self): + return self._row_cap_2port + diff --git a/compiler/base/geometry.py b/compiler/base/geometry.py index c8f6036f..6d39a7dd 100644 --- a/compiler/base/geometry.py +++ b/compiler/base/geometry.py @@ -275,16 +275,16 @@ class instance(geometry): def calculate_transform(self, node): #set up the rotation matrix angle = math.radians(float(node.rotate)) - mRotate = np.array([[math.cos(angle),-math.sin(angle),0.0], - [math.sin(angle),math.cos(angle),0.0], - [0.0,0.0,1.0]]) + mRotate = np.array([[math.cos(angle), -math.sin(angle), 0.0], + [math.sin(angle), math.cos(angle), 0.0], + [0.0, 0.0, 1.0]]) #set up translation matrix translateX = float(node.offset[0]) translateY = float(node.offset[1]) - mTranslate = np.array([[1.0,0.0,translateX], - [0.0,1.0,translateY], - [0.0,0.0,1.0]]) + mTranslate = np.array([[1.0, 0.0, translateX], + [0.0, 1.0, translateY], + [0.0, 0.0, 1.0]]) #set up the scale matrix (handles mirror X) scaleX = 1.0 @@ -292,27 +292,27 @@ class instance(geometry): scaleY = -1.0 else: scaleY = 1.0 - mScale = np.array([[scaleX,0.0,0.0], - [0.0,scaleY,0.0], - [0.0,0.0,1.0]]) + mScale = np.array([[scaleX, 0.0, 0.0], + [0.0, scaleY, 0.0], + [0.0, 0.0, 1.0]]) return (mRotate, mScale, mTranslate) def apply_transform(self, mtransforms, uVector, vVector, origin): - origin = np.dot(mtransforms[0], origin) #rotate - uVector = np.dot(mtransforms[0], uVector) #rotate - vVector = np.dot(mtransforms[0], vVector) #rotate - origin = np.dot(mtransforms[1], origin) #scale - uVector = np.dot(mtransforms[1], uVector) #scale - vVector = np.dot(mtransforms[1], vVector) #scale + origin = np.dot(mtransforms[0], origin) # rotate + uVector = np.dot(mtransforms[0], uVector) # rotate + vVector = np.dot(mtransforms[0], vVector) # rotate + origin = np.dot(mtransforms[1], origin) # scale + uVector = np.dot(mtransforms[1], uVector) # scale + vVector = np.dot(mtransforms[1], vVector) # scale origin = np.dot(mtransforms[2], origin) return(uVector, vVector, origin) def apply_path_transform(self, path): - uVector = np.array([[1.0],[0.0],[0.0]]) - vVector = np.array([[0.0],[1.0],[0.0]]) - origin = np.array([[0.0],[0.0],[1.0]]) + uVector = np.array([[1.0], [0.0], [0.0]]) + vVector = np.array([[0.0], [1.0], [0.0]]) + origin = np.array([[0.0], [0.0], [1.0]]) while(path): instance = path.pop(-1) @@ -330,7 +330,7 @@ class instance(geometry): bl_offsets = [] # bl to cell offset br_offsets = [] # br to cell offset bl_meta = [] # bl offset metadata (row,col,name) - br_meta = [] #br offset metadata (row,col,name) + br_meta = [] # br offset metadata (row,col,name) def walk_subtree(node): path.append(node) @@ -338,8 +338,6 @@ class instance(geometry): if node.mod.name == cell_name: cell_paths.append(copy.copy(path)) - inst_name = path[-1].name - # get the row and col names from the path row = int(path[-1].name.split('_')[-2][1:]) col = int(path[-1].name.split('_')[-1][1:]) @@ -370,17 +368,15 @@ class instance(geometry): for pair in range(len(normalized_bl_offsets)): normalized_bl_offsets[pair] = (normalized_bl_offsets[pair][0], - -1 * normalized_bl_offsets[pair][1]) + -1 * normalized_bl_offsets[pair][1]) for pair in range(len(normalized_br_offsets)): normalized_br_offsets[pair] = (normalized_br_offsets[pair][0], - -1 * normalized_br_offsets[pair][1]) - + -1 * normalized_br_offsets[pair][1]) Q_offsets.append([Q_x, Q_y]) Q_bar_offsets.append([Q_bar_x, Q_bar_y]) - bl_offsets.append(normalized_bl_offsets) br_offsets.append(normalized_br_offsets) @@ -428,7 +424,7 @@ class path(geometry): def gds_write_file(self, new_layout): """Writes the path to GDS""" - debug.info(4, "writing path (" + str(self.layerNumber) + "): " + self.coordinates) + debug.info(4, "writing path (" + str(self.layerNumber) + "): " + self.coordinates) new_layout.addPath(layerNumber=self.layerNumber, purposeNumber=self.layerPurpose, coordinates=self.coordinates, diff --git a/compiler/base/hierarchy_layout.py b/compiler/base/hierarchy_layout.py index 516b3988..d2313d99 100644 --- a/compiler/base/hierarchy_layout.py +++ b/compiler/base/hierarchy_layout.py @@ -373,7 +373,7 @@ class layout(): for pin in pins: if new_name == "": - new_name = pin.name + new_name = pin_name self.add_layout_pin(new_name, pin.layer, pin.ll(), diff --git a/compiler/base/hierarchy_spice.py b/compiler/base/hierarchy_spice.py index ab3bd5c3..9e2a3e41 100644 --- a/compiler/base/hierarchy_spice.py +++ b/compiler/base/hierarchy_spice.py @@ -239,7 +239,8 @@ 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, "LVS and spice file pin mismatch.") + debug.check(lvs_pins == self.pins, + "Spice netlists for LVS and simulation have port mismatches: {0} (LVS) vs {1} (sim)".format(lvs_pins, self.pins)) def check_net_in_spice(self, net_name): """Checks if a net name exists in the current. Intended to be check nets in hand-made cells.""" diff --git a/compiler/bitcells/bitcell_2port.py b/compiler/bitcells/bitcell_2port.py index 4833d7c3..87db10be 100644 --- a/compiler/bitcells/bitcell_2port.py +++ b/compiler/bitcells/bitcell_2port.py @@ -94,9 +94,8 @@ class bitcell_2port(bitcell_base.bitcell_base): pin_dict = {pin: port for pin, port in zip(self.pins, port_nets)} # Edges hardcoded here. Essentially wl->bl/br for both ports. # Port 0 edges - pins = props.bitcell_2port.pin - graph.add_edge(pin_dict[pins.wl0], pin_dict[pins.bl0], self) - graph.add_edge(pin_dict[pins.wl0], pin_dict[pins.br0], self) + graph.add_edge(pin_dict["wl0"], pin_dict["bl0"], self) + graph.add_edge(pin_dict["wl0"], pin_dict["br0"], self) # Port 1 edges - graph.add_edge(pin_dict[pins.wl1], pin_dict[pins.bl1], self) - graph.add_edge(pin_dict[pins.wl1], pin_dict[pins.br1], self) + graph.add_edge(pin_dict["wl1"], pin_dict["bl1"], self) + graph.add_edge(pin_dict["wl1"], pin_dict["br1"], self) diff --git a/compiler/bitcells/col_cap_bitcell_2port.py b/compiler/bitcells/col_cap_bitcell_2port.py index dc3954b0..d18d0762 100644 --- a/compiler/bitcells/col_cap_bitcell_2port.py +++ b/compiler/bitcells/col_cap_bitcell_2port.py @@ -15,8 +15,8 @@ class col_cap_bitcell_2port(bitcell_base.bitcell_base): Column end cap cell. """ - def __init__(self, name="col_cap_cell_1rw_1r"): - bitcell_base.bitcell_base.__init__(self, name, prop=props.bitcell_2port) + def __init__(self, name="col_cap_bitcell_2port"): + bitcell_base.bitcell_base.__init__(self, name, prop=props.col_cap_2port) debug.info(2, "Create col_cap bitcell 2 port object") self.no_instances = True diff --git a/compiler/bitcells/row_cap_bitcell_2port.py b/compiler/bitcells/row_cap_bitcell_2port.py index cdc49318..2edee57c 100644 --- a/compiler/bitcells/row_cap_bitcell_2port.py +++ b/compiler/bitcells/row_cap_bitcell_2port.py @@ -15,8 +15,8 @@ class row_cap_bitcell_2port(bitcell_base.bitcell_base): Row end cap cell. """ - def __init__(self, name="row_cap_cell_1rw_1r"): - bitcell_base.bitcell_base.__init__(self, name, prop=props.bitcell_2port) - debug.info(2, "Create row_cap bitcell 1rw+1r object") + def __init__(self, name="row_cap_bitcell_2port"): + bitcell_base.bitcell_base.__init__(self, name, prop=props.row_cap_2port) + debug.info(2, "Create row_cap bitcell 2 port object") self.no_instances = True diff --git a/compiler/modules/col_cap_array.py b/compiler/modules/col_cap_array.py index 6bc77805..71a59cf8 100644 --- a/compiler/modules/col_cap_array.py +++ b/compiler/modules/col_cap_array.py @@ -6,7 +6,6 @@ from bitcell_base_array import bitcell_base_array from sram_factory import factory from globals import OPTS -from tech import cell_properties class col_cap_array(bitcell_base_array): @@ -65,16 +64,14 @@ class col_cap_array(bitcell_base_array): """ if len(self.all_ports) == 1: - pin_name = cell_properties.bitcell.cell_6t.pin - bitcell_pins = ["{0}_{1}".format(pin_name.bl0, col), - "{0}_{1}".format(pin_name.br0, col), + bitcell_pins = ["bl0_{0}".format(col), + "br0_{0}".format(col), "vdd"] else: - pin_name = cell_properties.bitcell.cell_1rw1r.pin - bitcell_pins = ["{0}_{1}".format(pin_name.bl0, col), - "{0}_{1}".format(pin_name.br0, col), - "{0}_{1}".format(pin_name.bl1, col), - "{0}_{1}".format(pin_name.br1, col), + bitcell_pins = ["bl0_{0}".format(col), + "br0_{0}".format(col), + "bl1_{0}".format(col), + "br1_{0}".format(col), "vdd"] return bitcell_pins diff --git a/compiler/modules/dff_buf.py b/compiler/modules/dff_buf.py index aea98ea5..58d26007 100644 --- a/compiler/modules/dff_buf.py +++ b/compiler/modules/dff_buf.py @@ -8,7 +8,6 @@ import debug import design from tech import layer -from tech import cell_properties as props from vector import vector from globals import OPTS from sram_factory import factory @@ -72,9 +71,8 @@ class dff_buf(design.design): self.add_mod(self.inv2) def add_pins(self): - self.add_pin_names(props.dff_buf.port_map) - self.add_pin_list(props.dff_buf.port_names, - props.dff_buf.port_types) + self.add_pin_list(["D", "Q", "Qb", "clk", "vdd", "gnd"], + ["INPUT", "OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"]) def create_instances(self): self.dff_inst=self.add_inst(name="dff_buf_dff", diff --git a/compiler/modules/replica_column.py b/compiler/modules/replica_column.py index eac98054..f7e0c0fb 100644 --- a/compiler/modules/replica_column.py +++ b/compiler/modules/replica_column.py @@ -5,7 +5,6 @@ # import debug from bitcell_base_array import bitcell_base_array -from tech import cell_properties as props from sram_factory import factory from vector import vector from globals import OPTS @@ -31,8 +30,15 @@ class replica_column(bitcell_base_array): # left, right, regular rows plus top/bottom dummy cells self.total_size = self.left_rbl + rows + self.right_rbl + # Used for pin names and properties + self.cell = factory.create(module_type=OPTS.bitcell) + # For end caps - self.total_size += 2 + try: + if not self.cell.end_caps: + self.total_size += 2 + except AttributeError: + self.total_size += 2 self.column_offset = column_offset @@ -86,9 +92,6 @@ class replica_column(bitcell_base_array): self.edge_cell = factory.create(module_type=edge_module_type + "_" + OPTS.bitcell) self.add_mod(self.edge_cell) - # Used for pin names only - self.cell = factory.create(module_type=OPTS.bitcell) - def create_instances(self): self.cell_inst = {} diff --git a/compiler/modules/row_cap_array.py b/compiler/modules/row_cap_array.py index 1995b45c..97776eee 100644 --- a/compiler/modules/row_cap_array.py +++ b/compiler/modules/row_cap_array.py @@ -6,7 +6,6 @@ from bitcell_base_array import bitcell_base_array from sram_factory import factory from globals import OPTS -from tech import cell_properties class row_cap_array(bitcell_base_array): @@ -61,9 +60,8 @@ class row_cap_array(bitcell_base_array): indexed by column and row, for instance use in bitcell_array """ - pin_name = cell_properties.bitcell.cell_1rw1r.pin - bitcell_pins = ["{0}_{1}".format(pin_name.wl0, row), - "{0}_{1}".format(pin_name.wl1, row), + bitcell_pins = ["wl0_{0}".format(row), + "wl1_{0}".format(row), "gnd"] return bitcell_pins From 902b92223fb734eb3ca014cb6798d032874703fc Mon Sep 17 00:00:00 2001 From: mrg Date: Mon, 16 Nov 2020 13:57:31 -0800 Subject: [PATCH 29/31] Small fix for finding pin names in timing graph. --- compiler/bitcells/bitcell_2port.py | 2 +- compiler/bitcells/replica_bitcell_2port.py | 2 +- compiler/custom/sense_amp.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/bitcells/bitcell_2port.py b/compiler/bitcells/bitcell_2port.py index 87db10be..6a9f0b6f 100644 --- a/compiler/bitcells/bitcell_2port.py +++ b/compiler/bitcells/bitcell_2port.py @@ -91,7 +91,7 @@ class bitcell_2port(bitcell_base.bitcell_base): def build_graph(self, graph, inst_name, port_nets): """Adds edges to graph. Multiport bitcell timing graph is too complex to use the add_graph_edges function.""" - pin_dict = {pin: port for pin, port in zip(self.pins, port_nets)} + pin_dict = {pin: port for pin, port in zip(self.pin_names, port_nets)} # Edges hardcoded here. Essentially wl->bl/br for both ports. # Port 0 edges graph.add_edge(pin_dict["wl0"], pin_dict["bl0"], self) diff --git a/compiler/bitcells/replica_bitcell_2port.py b/compiler/bitcells/replica_bitcell_2port.py index 0709ca10..710a18d7 100644 --- a/compiler/bitcells/replica_bitcell_2port.py +++ b/compiler/bitcells/replica_bitcell_2port.py @@ -41,7 +41,7 @@ class replica_bitcell_2port(bitcell_base.bitcell_base): def build_graph(self, graph, inst_name, port_nets): """Adds edges to graph. Multiport bitcell timing graph is too complex to use the add_graph_edges function.""" - pin_dict = {pin: port for pin, port in zip(self.pins, port_nets)} + pin_dict = {pin: port for pin, port in zip(self.pin_names, port_nets)} # Edges hardcoded here. Essentially wl->bl/br for both ports. # Port 0 edges graph.add_edge(pin_dict["wl0"], pin_dict["bl0"], self) diff --git a/compiler/custom/sense_amp.py b/compiler/custom/sense_amp.py index 10156e2c..d57bdaac 100644 --- a/compiler/custom/sense_amp.py +++ b/compiler/custom/sense_amp.py @@ -67,7 +67,7 @@ class sense_amp(design.design): """Returns name used for enable net""" # FIXME: A better programmatic solution to designate pins enable_name = self.en_name - debug.check(enable_name in self.pins, "Enable name {} not found in pin list".format(enable_name)) + debug.check(enable_name in self.pin_names, "Enable name {} not found in pin list".format(enable_name)) return enable_name def build_graph(self, graph, inst_name, port_nets): From 80333ffacbab685b5e096dd12f2124ebd2fc823c Mon Sep 17 00:00:00 2001 From: mrg Date: Tue, 17 Nov 2020 09:44:03 -0800 Subject: [PATCH 30/31] Fix setup/hold characterization to use custom cell and pin names/orders. --- compiler/characterizer/setup_hold.py | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/compiler/characterizer/setup_hold.py b/compiler/characterizer/setup_hold.py index f3b9541c..9ce5a899 100644 --- a/compiler/characterizer/setup_hold.py +++ b/compiler/characterizer/setup_hold.py @@ -5,13 +5,12 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -import sys import tech from .stimuli import * import debug from .charutils import * -import dff from globals import OPTS +from sram_factory import factory class setup_hold(): @@ -22,9 +21,8 @@ class setup_hold(): def __init__(self, corner): # This must match the spice model order - self.pins = ["data", "dout", "clk", "vdd", "gnd"] - self.model_name = "dff" - self.model_location = OPTS.openram_tech + "sp_lib/dff.sp" + self.dff = factory.create(module_type=OPTS.dff) + self.period = tech.spice["feasible_period"] debug.info(2, "Feasible period from technology file: {0} ".format(self.period)) @@ -50,8 +48,8 @@ class setup_hold(): # instantiate the master-slave d-flip-flop self.sf.write("\n* Instantiation of the Master-Slave D-flip-flop\n") - self.stim.inst_model(pins=self.pins, - model_name=self.model_name) + self.stim.inst_model(pins=self.dff.get_ordered_inputs(self.dff.pins), + model_name=self.dff.cell_name) self.write_data(mode=mode, target_time=target_time, @@ -71,7 +69,7 @@ class setup_hold(): self.sf.write("\n* Stimulus for setup/hold: data {0} period {1}n\n".format(correct_value, self.period)) # include files in stimulus file - self.stim.write_include(self.model_location) + self.stim.write_include(self.dff.sp_file) # add vdd/gnd statements self.sf.write("\n* Global Power Supplies\n") @@ -94,7 +92,7 @@ class setup_hold(): start_value = incorrect_value end_value = correct_value - self.stim.gen_pwl(sig_name="data", + self.stim.gen_pwl(sig_name="D", clk_times=[0, self.period, target_time], data_values=[init_value, start_value, end_value], period=target_time, @@ -136,7 +134,7 @@ class setup_hold(): self.sf.write("\n* Measure statements for pass/fail verification\n") trig_name = "clk" - targ_name = "dout" + targ_name = "Q" trig_val = targ_val = 0.5 * self.vdd_voltage # Start triggers right before the clock edge at 2*period self.stim.gen_meas_delay(meas_name="clk2q_delay", @@ -149,7 +147,7 @@ class setup_hold(): trig_td=1.9 * self.period, targ_td=1.9 * self.period) - targ_name = "data" + targ_name = "D" # Start triggers right after initialize value is returned to normal # at one period self.stim.gen_meas_delay(meas_name="setup_hold_time", From baae28194bea5c5e7aa689ae85c2ee7d8920da5e Mon Sep 17 00:00:00 2001 From: mrg Date: Tue, 17 Nov 2020 11:12:59 -0800 Subject: [PATCH 31/31] Add custom cell custom port order code. Update setup/hold to use it. --- compiler/base/custom_cell_properties.py | 10 +++++ compiler/base/design.py | 1 + compiler/base/hierarchy_layout.py | 50 ++++++++++++++++--------- compiler/base/hierarchy_spice.py | 41 ++++++++++++++++---- compiler/base/verilog.py | 7 +++- compiler/characterizer/setup_hold.py | 2 +- 6 files changed, 83 insertions(+), 28 deletions(-) diff --git a/compiler/base/custom_cell_properties.py b/compiler/base/custom_cell_properties.py index e7e2253b..2407f9c2 100644 --- a/compiler/base/custom_cell_properties.py +++ b/compiler/base/custom_cell_properties.py @@ -22,7 +22,11 @@ class _cell: self._port_map = {x: x for x in port_order} # Update mapping of names + self._original_port_order = port_order self._port_order = port_order + + # Create an index array + self._port_indices = [self._port_order.index(x) for x in self._original_port_order] # Update ordered name list self._port_names = [self._port_map[x] for x in self._port_order] @@ -49,7 +53,13 @@ class _cell: self._port_names = [self._port_map[x] for x in self._port_order] # Update ordered type list in the new order self._port_types = [self._port_types_map[x] for x in self._port_order] + # Update the index array + self._port_indices = [self._port_order.index(x) for x in self._original_port_order] + @property + def port_indices(self): + return self._port_indices + @property def port_map(self): return self._port_map diff --git a/compiler/base/design.py b/compiler/base/design.py index f90ea12c..2c3ba2ea 100644 --- a/compiler/base/design.py +++ b/compiler/base/design.py @@ -39,6 +39,7 @@ class design(hierarchy_design): # 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)) + self.add_pin_indices(prop.port_indices) self.add_pin_names(prop.port_map) self.add_pin_types(prop.port_types) diff --git a/compiler/base/hierarchy_layout.py b/compiler/base/hierarchy_layout.py index d2313d99..4e473397 100644 --- a/compiler/base/hierarchy_layout.py +++ b/compiler/base/hierarchy_layout.py @@ -62,14 +62,7 @@ class layout(): self.pwr_grid_layer = power_grid[0] except ImportError: self.pwr_grid_layer = "m3" - - def add_pin_names(self, pin_dict): - """ - Create a mapping from internal pin names to external pin names. - """ - self.pin_names = pin_dict - - + ############################################################ # GDS layout ############################################################ @@ -325,11 +318,8 @@ class layout(): """ Return the pin or list of pins """ - if text in self.pin_names: - name = self.pin_names[text] - else: - name = text - + name = self.get_pin_name(text) + try: if len(self.pin_map[name]) > 1: debug.error("Should use a pin iterator since more than one pin {}".format(text), -1) @@ -345,16 +335,42 @@ class layout(): """ Return a pin list (instead of a single pin) """ - if text in self.pin_names: - name = self.pin_names[text] - else: - name = text + name = self.get_pin_name(text) if name in self.pin_map.keys(): return self.pin_map[name] else: return set() + def add_pin_names(self, pin_dict): + """ + Create a mapping from internal pin names to external pin names. + """ + self.pin_names = pin_dict + + self.original_pin_names = {y: x for (x, y) in self.pin_names.items()} + + def get_pin_name(self, text): + """ Return the custom cell pin name """ + + if text in self.pin_names: + return self.pin_names[text] + else: + return text + + def get_original_pin_names(self): + """ Return the internal cell pin name """ + + # This uses the hierarchy_spice pins (in order) + return [self.get_original_pin_name(x) for x in self.pins] + + def get_original_pin_name(self, text): + """ Return the internal cell pin names in custom port order """ + if text in self.original_pin_names: + return self.original_pin_names[text] + else: + return text + def get_pin_names(self): """ Return a pin list of all pins diff --git a/compiler/base/hierarchy_spice.py b/compiler/base/hierarchy_spice.py index 9e2a3e41..a51b9575 100644 --- a/compiler/base/hierarchy_spice.py +++ b/compiler/base/hierarchy_spice.py @@ -35,11 +35,13 @@ class spice(): self.valid_signal_types = ["INOUT", "INPUT", "OUTPUT", "POWER", "GROUND"] # Holds subckts/mods for this module self.mods = [] - # Holds the pins for this module + # 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 # Spice format) self.conns = [] @@ -95,10 +97,25 @@ class spice(): else: debug.error("Mismatch in type and pin list lengths.", -1) + def add_pin_indices(self, index_list): + """ + 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. + """ + 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. - Typically, should only be used for handmade cells. """ # This only works if self.pins == bitcell.pin_names if len(type_list) != len(self.pins): @@ -107,7 +124,7 @@ class spice(): \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)} - + def get_pin_type(self, name): """ Returns the type of the signal pin. """ pin_type = self.pin_type[name] @@ -159,19 +176,26 @@ class spice(): self.mods.append(mod) def connect_inst(self, args, check=True): - """Connects the pins of the last instance added + """ + 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.""" + group of modules are generated. + """ + num_pins = len(self.insts[-1].mod.pins) num_args = len(args) + + # 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: mod_pins = self.insts[-1].mod.pins + [""] * (num_args - num_pins) - arg_pins = args + arg_pins = ordered_args else: - arg_pins = args + [""] * (num_pins - num_args) + arg_pins = ordered_args + [""] * (num_pins - num_args) mod_pins = self.insts[-1].mod.pins modpins_string = "\n".join(["{0} -> {1}".format(arg, mod) for (arg, mod) in zip(arg_pins, mod_pins)]) @@ -180,8 +204,9 @@ class spice(): modpins_string), 1) - self.conns.append(args) + self.conns.append(ordered_args) + # 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) diff --git a/compiler/base/verilog.py b/compiler/base/verilog.py index 636e3bd6..f5ef9107 100644 --- a/compiler/base/verilog.py +++ b/compiler/base/verilog.py @@ -5,9 +5,9 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -import debug import math + class verilog: """ Create a behavioral Verilog file for simulation. @@ -16,7 +16,7 @@ class verilog: def __init__(self): pass - def verilog_write(self,verilog_name): + def verilog_write(self, verilog_name): """ Write a behavioral Verilog model. """ self.vf = open(verilog_name, "w") @@ -220,6 +220,9 @@ class verilog: self.vf.write(" dout{0} <= #(DELAY) mem[addr{0}_reg];\n".format(port)) self.vf.write(" end\n") + self.vf.write(" always @(csb{0})\n".format(port)) + self.vf.write(" dout{0} = 0)\n".format(port)) + def add_address_check(self, wport, rport): """ Output a warning if the two addresses match """ # If the rport is actually reading... and addresses match. diff --git a/compiler/characterizer/setup_hold.py b/compiler/characterizer/setup_hold.py index 9ce5a899..688e6535 100644 --- a/compiler/characterizer/setup_hold.py +++ b/compiler/characterizer/setup_hold.py @@ -48,7 +48,7 @@ class setup_hold(): # instantiate the master-slave d-flip-flop self.sf.write("\n* Instantiation of the Master-Slave D-flip-flop\n") - self.stim.inst_model(pins=self.dff.get_ordered_inputs(self.dff.pins), + self.stim.inst_model(pins=self.dff.get_original_pin_names(), model_name=self.dff.cell_name) self.write_data(mode=mode,