Additional work on the GF PDK. This includes updating the OSU standard cells for changes made to the repository. Also: SRAM now imported in such a way that the .mag view produced can be extracted and passes LVS. For the SRAM and the standard cells, switching from layout-extracted SPICE to converted CDL from GF. Started a method for building open_pdks from commit numbers pulled from the JSON file "reference" section; this work is unfinished.
diff --git a/Makefile.in b/Makefile.in index e63efb8..348ddd9 100644 --- a/Makefile.in +++ b/Makefile.in
@@ -38,7 +38,9 @@ # # annotate the technology JSON file with the current # commit state of all repositories used by the PDK to -# create a reference set of PDKs. +# create a reference set of PDKs. Can be used with +# the configure --with-reference option to compile +# to sources from a specific set of commits. # #--------------------------------------------------- #
diff --git a/common/foundry_install.py b/common/foundry_install.py index 969908f..bcb17e6 100755 --- a/common/foundry_install.py +++ b/common/foundry_install.py
@@ -128,10 +128,13 @@ # # rename : Followed by "=" and an alternative name. For any # file that is a single entry, change the name of -# the file in the target directory to this (To-do: -# take regexps for multiple files). When used with -# "compile" or "compile-only", this refers to the -# name of the target compiled file. +# the file in the target directory to this. If the +# alternative name is a file extension (optionally +# preceded by '*', as in "rename=*.spice", then all +# input files are renamed with the indicated file +# extension (To-do: take regexps for multiple files). +# When used with "compile" or "compile-only", this +# refers to the name of the target compiled file. # # filter: Followed by "=" and the name of a script. # Each file is passed through the filter script @@ -1008,6 +1011,10 @@ if len(liblist) == 1: destfile = newname + elif newname.startswith('*.'): + destfile = os.path.splitext(libfile)[0] + newname[1:] + elif newname.startswith('.'): + destfile = os.path.splitext(libfile)[0] + newname else: if not do_compile and not do_compile_only: print('Error: rename specified but more than one file found!')
diff --git a/gf180mcu/Makefile.in b/gf180mcu/Makefile.in index 9741d6f..be9cf7b 100644 --- a/gf180mcu/Makefile.in +++ b/gf180mcu/Makefile.in
@@ -157,6 +157,8 @@ GF180MCU_SRAM_PATH = @GF180MCU_FD_IP_SRAM_PATH@ GF180MCU_OSU_SC_PATH = @GF180MCU_OSU_SC_PATH@ +USE_REFERENCE = @USE_REFERENCE@ + # Path to GF180MCU library sources PDK_URL = https://github.com/google OSU_URL = https://github.com/stineje @@ -428,6 +430,8 @@ TOOLS += xcircuit endif +all: $(foreach var, ${VARIANTS}, all-$(var)) + reference: ${TECH}.json # Rewrite the ${TECH}.json file to change the commit values in # "reference" to reflect the state of the system when "make @@ -436,8 +440,6 @@ # tools. ../common/save_commit_refs.py ${COMMIT_DEFS} ${TECH}.json -all: $(foreach var, ${VARIANTS}, all-$(var)) - # Handle prerequisites prerequisites: pr-repo io-repo sc-7t-repo sc-9t-repo sram-repo osu-sc-repo @@ -821,6 +823,8 @@ filter=custom/scripts/fix_related_bias_pins.py \ header=liberty/gf180mcu_fd_sc_mcu9t5v0__tt_025C_5v00.lib \ rename=gf180mcu_fd_sc_mcu9t5v0__tt_025C_5v00 \ + -spice cells/*/*.cdl compile-only \ + filter=custom/scripts/convert_sc_cdl.py \ -gds cells/*/*.gds compile-only \ options=custom/scripts/gds_import_sc.tcl \ filter=custom/scripts/fix_stdcell_gds.py \ @@ -834,6 +838,7 @@ # Create minimum/maximum technology LEF files ./custom/scripts/make_minmax_techlef.py ${EF_FORMAT} -variant=${GF180MCU$*} \ -library=9t5v0 2>&1 | tee -a ${GF180MCU$*}_make.log || true + digital-7t5v0-%: # Install 5V 7-track digital standard cells from vendor files ${STAGE} -source ${GF180MCU_SC_7T5V0_PATH} \ @@ -902,6 +907,8 @@ filter=custom/scripts/fix_related_bias_pins.py \ header=liberty/gf180mcu_fd_sc_mcu7t5v0__tt_025C_5v00.lib \ rename=gf180mcu_fd_sc_mcu7t5v0__tt_025C_5v00 \ + -spice cells/*/*.cdl compile-only \ + filter=custom/scripts/convert_sc_cdl.py \ -gds cells/*/*.gds compile-only \ options=custom/scripts/gds_import_sc.tcl \ filter=custom/scripts/fix_stdcell_gds.py \ @@ -919,34 +926,32 @@ digital-osu-%: # Install OSU 3.3V digital standard cells from vendor files # NOTE: Work in progress (to be completed) - ${STAGE} -source ${GF180MCU_OSU_SC_PATH} \ + ${STAGE} -source ${GF180MCU_OSU_SC_PATH}/gf180mcu_osu_sc_gp9t3v3 \ -target ${STAGING_PATH}/${GF180MCU$*} \ - -techlef lib/9T/tlef/gf180mcu_*_tech.lef \ - rename=gf180mcu_osu_sc_9T.tlef \ - -liberty lib/9T/lib/gf180mcu_9T_TT_3P3_25C*.lib \ - rename=gf180mcu_osu_sc_9T__tt_025C_3v30 \ - -verilog lib/9T/verilog/*.v \ - rename=gf180mcu_osu_sc_9T \ - -lef lib/9T/lef/*.lef \ - -gds lib/9T/*/*.gds compile-only \ - -spice lib/9T/*/*.spice compile-only \ - -xschem lib/9T/*/*.sch \ - -library digital gf180mcu_osu_sc_9T 2>&1 | \ + -techlef ../tlef/gf180mcu_5LM_1TM_9K_9t.tlef \ + rename=gf180mcu_fd_sc_mcu7t5v0__nom.tlef \ + -liberty lib/gf180mcu_osu_sc_gp9t3v3_TT_3P3_25C.ccs.lib \ + rename=gf180mcu_osu_sc_gp9t3v3__tt_025C_3v30 \ + -verilog cells/*/*.v compile-only \ + -lef cells/*/*.lef compile-only \ + -gds cells/*/*.gds compile-only \ + -spice cells/*/*.spice compile-only \ + -xschem cells/*/*.sch \ + -library digital gf180mcu_osu_sc_gp9t3v3 2>&1 | \ tee -a ${GF180MCU$*}_make.log - ${STAGE} -source ${GF180MCU_OSU_SC_PATH} \ + ${STAGE} -source ${GF180MCU_OSU_SC_PATH}/gf180mcu_osu_sc_gp12t3v3 \ -target ${STAGING_PATH}/${GF180MCU$*} \ - -techlef lib/12T/tlef/gf180mcu_*_tech.lef \ - rename=gf180mcu_osu_sc_12T.tlef \ - -liberty lib/12T/lib/gf180mcu_12T_TT_3P3_25C*.lib \ - rename=gf180mcu_osu_sc_12T__tt_025C_3v30 \ - -verilog lib/12T/verilog/*.v \ - rename=gf180mcu_osu_sc_12T \ - -lef lib/12T/lef/*.lef \ - -gds lib/12T/*/*.gds compile-only \ - -spice lib/12T/*/*.spice compile-only \ - -xschem lib/12T/*/*.sch \ - -library digital gf180mcu_osu_sc_12T 2>&1 | \ + -techlef ../tlef/gf180mcu_5LM_1TM_9K_12t.tlef \ + rename=gf180mcu_fd_sc_mcu7t5v0__nom.tlef \ + -liberty lib/gf180mcu_osu_sc_gp12t3v3_TT_25C.ccs.lib \ + rename=gf180mcu_osu_sc_gp12t3v3__tt_025C_3v30 \ + -verilog cells/*/*.v compile-only \ + -lef cells/*/*.lef compile-only \ + -gds cells/*/*.gds compile-only \ + -spice cells/*/*.spice compile-only \ + -xschem cells/*/*.sch \ + -library digital gf180mcu_osu_sc_gp12t3v3 2>&1 | \ tee -a ${GF180MCU$*}_make.log io-%: @@ -976,9 +981,9 @@ -liberty cells/*/*_ff_n40C_5v50.lib compile-only \ header=liberty/gf180mcu_fd_io__ff_n40C_5v50.lib \ rename=gf180mcu_fd_io__ff_n40C_5v50 \ - -liberty cells/*/*_ss_125C_2v50.lib compile-only \ - header=liberty/gf180mcu_fd_io__ss_125C_2v50.lib \ - rename=gf180mcu_fd_io__ss_125C_2v50 \ + -liberty cells/*/*_ss_125C_2v25.lib compile-only \ + header=liberty/gf180mcu_fd_io__ss_125C_2v25.lib \ + rename=gf180mcu_fd_io__ss_125C_2v25 \ -liberty cells/*/*_ss_125C_2v97.lib compile-only \ header=liberty/gf180mcu_fd_io__ss_125C_2v97.lib \ rename=gf180mcu_fd_io__ss_125C_2v97 \ @@ -1010,6 +1015,9 @@ -target ${STAGING_PATH}/${GF180MCU$*} \ -cdl cells/*/*.cdl noconvert \ -liberty cells/*/*.lib \ + -spice cells/*/*.cdl \ + filter=custom/scripts/convert_sram_cdl.py \ + rename=*.spice \ -gds cells/*/*.gds \ options=custom/scripts/gds_import_sram.tcl \ filter=custom/scripts/fix_sram_gds.py \
diff --git a/gf180mcu/custom/scripts/convert_sc_cdl.py b/gf180mcu/custom/scripts/convert_sc_cdl.py new file mode 100755 index 0000000..8a9fcbd --- /dev/null +++ b/gf180mcu/custom/scripts/convert_sc_cdl.py
@@ -0,0 +1,95 @@ +#!/usr/bin/env python3 +# +# convert_sc_cdl.py --- +# +# This script converts the GF CDL for the standard cells to turn them into +# valid SPICE (ngspice) syntax, using regular expression parsing. + +# This script is a filter to be run by setting the name of this script as +# the value to "filter=" for the model install in the sky130 Makefile. + +import re +import os +import sys + +def filter(inname, outname): + + # Read input + try: + with open(inname, 'r') as inFile: + spitext = inFile.read() + # (Don't) unwrap continuation lines + # spilines = spitext.replace('\n+', ' ').splitlines() + spilines = spitext.splitlines() + except: + print('convert_sc_cdl.py: failed to open ' + inname + ' for reading.', file=sys.stderr) + return 1 + + fixedlines = [] + modified = False + + for line in spilines: + fixedline = line + + # 1) Lines starting with M --> change to X + fixedline = re.sub('^M', 'X', fixedline, flags=re.IGNORECASE) + # 2) 5V transistor models --> change to 6V + fixedline = re.sub('_05v0', '_06v0', fixedline, flags=re.IGNORECASE) + # 3) Uppercase diode "d" for consistency + fixedline = re.sub('^d', 'D', fixedline) + # 4) Convert $m to M + fixedline = re.sub('\$m=', 'M=', fixedline, flags=re.IGNORECASE) + # 5) Fix incorrect endcap (endcap does not have VNW VPW) + fixedline = re.sub('endcap VDD VNW VPW', 'endcap VDD', fixedline, flags=re.IGNORECASE) + + if line != fixedline: + modified = True + fixedlines.append(fixedline) + + # Write output + if outname == None: + for i in fixedlines: + print(i) + else: + # If the output is a symbolic link but no modifications have been made, + # then leave it alone. If it was modified, then remove the symbolic + # link before writing. + if os.path.islink(outname): + if not modified: + return 0 + else: + os.unlink(outname) + try: + with open(outname, 'w') as outFile: + for i in fixedlines: + print(i, file=outFile) + except: + print('convert_sc_cdl.py: failed to open ' + outname + ' for writing.', file=sys.stderr) + return 1 + + +if __name__ == '__main__': + + # This script expects to get one or two arguments. One argument is + # mandatory and is the input file. The other argument is optional and + # is the output file. The output file and input file may be the same + # name, in which case the original input is overwritten. + + options = [] + arguments = [] + for item in sys.argv[1:]: + if item.find('-', 0) == 0: + options.append(item[1:]) + else: + arguments.append(item) + + if len(arguments) > 0: + infilename = arguments[0] + + if len(arguments) > 1: + outfilename = arguments[1] + else: + outfilename = None + + result = filter(infilename, outfilename) + sys.exit(result)
diff --git a/gf180mcu/custom/scripts/convert_sram_cdl.py b/gf180mcu/custom/scripts/convert_sram_cdl.py new file mode 100755 index 0000000..b07c09b --- /dev/null +++ b/gf180mcu/custom/scripts/convert_sram_cdl.py
@@ -0,0 +1,95 @@ +#!/usr/bin/env python3 +# +# convert_sram_cdl.py --- +# +# This script converts the GF CDL for the SRAM macros to turn them into valid +# SPICE syntax, using regular expression parsing. + +# This script is a filter to be run by setting the name of this script as +# the value to "filter=" for the model install in the sky130 Makefile. + +import re +import os +import sys + +def filter(inname, outname): + + # Read input + try: + with open(inname, 'r') as inFile: + spitext = inFile.read() + # (Don't) unwrap continuation lines + # spilines = spitext.replace('\n+', ' ').splitlines() + spilines = spitext.splitlines() + except: + print('convert_sram_cdl.py: failed to open ' + inname + ' for reading.', file=sys.stderr) + return 1 + + fixedlines = [] + modified = False + + for line in spilines: + fixedline = line + + # 1) Lines starting with M --> change to X + fixedline = re.sub('^M', 'X', fixedline, flags=re.IGNORECASE) + # 2) 5V transistor models --> change to 6V + fixedline = re.sub('_05v0', '_06v0', fixedline, flags=re.IGNORECASE) + # 3) Remove $X, $Y, $D, and $T parameters + fixedline = re.sub('\$X=-?[0-9]+', '', fixedline, flags=re.IGNORECASE) + fixedline = re.sub('\$Y=-?[0-9]+', '', fixedline, flags=re.IGNORECASE) + fixedline = re.sub('\$D=-?[0-9]+', '', fixedline, flags=re.IGNORECASE) + fixedline = re.sub('\$T=-?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+', '', + fixedline, flags=re.IGNORECASE) + + if line != fixedline: + modified = True + fixedlines.append(fixedline) + + # Write output + if outname == None: + for i in fixedlines: + print(i) + else: + # If the output is a symbolic link but no modifications have been made, + # then leave it alone. If it was modified, then remove the symbolic + # link before writing. + if os.path.islink(outname): + if not modified: + return 0 + else: + os.unlink(outname) + try: + with open(outname, 'w') as outFile: + for i in fixedlines: + print(i, file=outFile) + except: + print('convert_sram_cdl.py: failed to open ' + outname + ' for writing.', file=sys.stderr) + return 1 + + +if __name__ == '__main__': + + # This script expects to get one or two arguments. One argument is + # mandatory and is the input file. The other argument is optional and + # is the output file. The output file and input file may be the same + # name, in which case the original input is overwritten. + + options = [] + arguments = [] + for item in sys.argv[1:]: + if item.find('-', 0) == 0: + options.append(item[1:]) + else: + arguments.append(item) + + if len(arguments) > 0: + infilename = arguments[0] + + if len(arguments) > 1: + outfilename = arguments[1] + else: + outfilename = None + + result = filter(infilename, outfilename) + sys.exit(result)
diff --git a/gf180mcu/custom/scripts/gds_import_sram.tcl b/gf180mcu/custom/scripts/gds_import_sram.tcl index bbb0f15..26b625d 100644 --- a/gf180mcu/custom/scripts/gds_import_sram.tcl +++ b/gf180mcu/custom/scripts/gds_import_sram.tcl
@@ -11,5 +11,18 @@ gds flatglob pmos_1p2* gds flatglob via1_* gds flatglob ypass_gate* +# These additional cells must be flattened to get rid of 3.3V devices +# (DUALGATE drawn into high-level cells) +gds flatglob dcap_103* +gds flatglob din_* +gds flatglob mux821_* +gds flatglob rdummy_* +gds flatglob pmoscap_* +gds flatglob xdec_* +gds flatglob ypredec* +gds flatglob xpredec* +gds flatglob xdec8_* +gds flatglob prexdec_* +gds flatglob xdec32_* # Ensure unique cell names when reading multiple GDS files calma unique true
diff --git a/gf180mcu/magic/gf180mcu.tech b/gf180mcu/magic/gf180mcu.tech index f437eb7..0de72ef 100644 --- a/gf180mcu/magic/gf180mcu.tech +++ b/gf180mcu/magic/gf180mcu.tech
@@ -3429,18 +3429,18 @@ routing mtp MetalTop Metal6 METAL6 METTP mtp mettp MET6 m6 met6 metal6 #endif (METALS6) - cut m2c Via1 VIA1 via1 cont2 via12 + cut m2c Via1 VIA1 via1 cont2 via12 VIA12 #ifdef METALS3 || METALS4 || METALS5 || METALS6 - cut m3c Via2 VIA2 via2 cont3 via23 + cut m3c Via2 VIA2 via2 cont3 via23 VIA23 #endif (METALS3 || METALS4 || METALS5 || METALS6) #ifdef METALS4 || METALS5 || METALS6 - cut via3 Via3 VIA3 via3 cont4 via34 + cut via3 Via3 VIA3 via3 cont4 via34 VIA34 #endif (METALS4 || METALS5 || METALS6) #ifdef METALS5 || METALS6 - cut via4 Via4 VIA4 via4 cont5 via45 + cut via4 Via4 VIA4 via4 cont5 via45 VIA45 #endif (METALS5 || METALS6) #ifdef METALS6 - cut viatp Via5 viatp VIATP VIA5 vtp via5 cont6 via56 + cut viatp Via5 viatp VIATP VIA5 vtp via5 cont6 via56 VIA56 #endif (METALS6) obs obsm1 Metal1
diff --git a/scripts/configure.ac b/scripts/configure.ac index ce8662a..f1852ff 100755 --- a/scripts/configure.ac +++ b/scripts/configure.ac
@@ -275,6 +275,22 @@ AC_MSG_NOTICE([Tools enabled for PDK setup installation: M4_GET_TOOLS()]) +# Check for "--with-reference" +USE_REFERENCE=0 +AC_ARG_WITH( + [reference], + AS_HELP_STRING( + [--with-reference], + [Use PDK JSON file reference commit values for sources @<:@default=no@:>@] + ), [ + pdks_reference=$withval + if test "$withval" == "yes" -o "$withval" == "YES"; then + USE_REFERENCE=1 + fi + ], +) +AC_SUBST(USE_REFERENCE) + # Check for "--with-ef-style" EF_STYLE=0 AC_ARG_WITH( @@ -289,8 +305,8 @@ fi ], ) - AC_SUBST(EF_STYLE) + # Export the list of enabled technologies to the Makefile AC_SUBST(ENABLED_TECHS) # Export the top level directory of open_pdks
diff --git a/scripts/download.sh b/scripts/download.sh index 56af3ea..660c978 100755 --- a/scripts/download.sh +++ b/scripts/download.sh
@@ -5,7 +5,7 @@ # directory, untar it, and remove the tarball file. If the URL is # a repository and not a file, then clone it. # -# Usage: download.sh <url> <target_dir> [<strip>] +# Usage: download.sh <url> <target_dir> [<strip>|<commit>|<tag>] # # where: # @@ -19,6 +19,8 @@ # <strip> is the number of directory levels to strip off the front of the # tarball contents. Defaults to 1 if not specified (only # applicable if <url> points to a tarball). +# <commit> or <tag> is a specific reference commit to clone. If the +# <url> is not a git repository, then this option has no effect. # # Check if <url> points to a tarball or a repository (note: this assumes @@ -68,7 +70,14 @@ if type "git" > /dev/null; then echo "Cloning $1 to $2" - git clone --depth 1 $1 $2 + if [ $# -gt 2 ]; then + # git clone $1 $2 + # git checkout $3 + git clone --branch $3 --single-branch $1 $2 + else + git clone --depth 1 $1 $2 + fi + else echo "ERROR: \"git\" is required to automatically install tools." exit 1
diff --git a/sky130/Makefile.in b/sky130/Makefile.in index a0cfd35..d2336be 100644 --- a/sky130/Makefile.in +++ b/sky130/Makefile.in
@@ -245,6 +245,8 @@ OSU_T15_URL = https://foss-eda-tools.googlesource.com/skywater-pdk/libs/sky130_osu_sc_t15 OSU_T18_URL = https://foss-eda-tools.googlesource.com/skywater-pdk/libs/sky130_osu_sc_t18 +USE_REFERENCE = @USE_REFERENCE@ + # NOTE: Install destination is the git repository of the technology platform. # Once updated in git, the git project can be distributed to all hosts. # @@ -589,6 +591,8 @@ SPIEXT = spice endif +all: $(foreach var, ${VARIANTS}, all-$(var)) + reference: ${TECH}.json # Rewrite the ${TECH}.json file to change the commit values in # "reference" to reflect the state of the system when "make @@ -597,8 +601,6 @@ # tools. ../common/save_commit_refs.py ${COMMIT_DEFS} ${TECH}.json -all: $(foreach var, ${VARIANTS}, all-$(var)) - # Handle prerequisites (fetch and install the PDK and requested libraries) prerequisites: pdk-repo alpha-repo xschem-repo klayout-repo precheck-repo sram-repo osu-t12-repo osu-t15-repo osu-t18-repo