Wrote a script to directly translate the GF180MCU I/O library CDL
to SPICE, rather than implementing the rather circular method of
having magic generate SPICE from extracted layout.
diff --git a/VERSION b/VERSION
index 12e7049..92be23d 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.0.373
+1.0.374
diff --git a/gf180mcu/Makefile.in b/gf180mcu/Makefile.in
index 44135eb..9741d6f 100644
--- a/gf180mcu/Makefile.in
+++ b/gf180mcu/Makefile.in
@@ -994,6 +994,8 @@
-liberty cells/*/*_tt_025C_5v00.lib compile-only \
header=liberty/gf180mcu_fd_io__tt_025C_5v00.lib \
rename=gf180mcu_fd_io__tt_025C_5v00 \
+ -spice cells/*/*.cdl compile-only \
+ filter=custom/scripts/convert_io_cdl.py \
-gds cells/*/*_${$*_STACK}.gds compile-only \
options=custom/scripts/gds_import_io.tcl \
-lef cells/*/*_${$*_STACK}.lef \
diff --git a/gf180mcu/custom/scripts/convert_io_cdl.py b/gf180mcu/custom/scripts/convert_io_cdl.py
new file mode 100755
index 0000000..fcbc9b3
--- /dev/null
+++ b/gf180mcu/custom/scripts/convert_io_cdl.py
@@ -0,0 +1,108 @@
+#!/usr/bin/env python3
+#
+# convert_io_cdl.py ---
+#
+# This script converts the GF CDL for the I/O pads to turn it 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_io_cdl.py: failed to open ' + inname + ' for reading.', file=sys.stderr)
+ return 1
+
+ fixedlines = []
+ modified = False
+
+ resrex = re.compile('^R', re.IGNORECASE)
+ caprex = re.compile('^C', re.IGNORECASE)
+
+ for line in spilines:
+ fixedline = line
+ isres = resrex.match(fixedline)
+ iscap = caprex.match(fixedline)
+ # check if resistor or capacitor for parameter name changes
+ # regexp substitutions:
+ # 1) Lines starting with R, C, or M --> change to X
+ fixedline = re.sub('^[RCM]', 'X', fixedline, flags=re.IGNORECASE)
+ # 2) Names in $[...] --> remove the delimiter
+ fixedline = re.sub(' \$\[', ' ', fixedline, flags=re.IGNORECASE)
+ fixedline = re.sub('\] ', ' ', fixedline, flags=re.IGNORECASE)
+ # 3) Remove $SUB=
+ fixedline = re.sub('\$SUB=', '', fixedline, flags=re.IGNORECASE)
+ # 4) Handle $W and $L for resistors
+ if isres:
+ fixedline = re.sub('\$W', 'r_width', fixedline, flags=re.IGNORECASE)
+ fixedline = re.sub('\$L', 'r_length', fixedline, flags=re.IGNORECASE)
+ if iscap:
+ fixedline = re.sub('w=', 'c_width=', fixedline, flags=re.IGNORECASE)
+ fixedline = re.sub('l=', 'c_length=', fixedline, flags=re.IGNORECASE)
+ # 5) Lowercase AREA and PJ
+ fixedline = re.sub('AREA', 'area', fixedline)
+ fixedline = re.sub('PJ', 'pj', fixedline)
+
+ 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_io_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/gf180mcu.json b/gf180mcu/gf180mcu.json
index 60d052e..0b3d151 100644
--- a/gf180mcu/gf180mcu.json
+++ b/gf180mcu/gf180mcu.json
@@ -84,8 +84,8 @@
"magic": "MAGIC_COMMIT"
},
"reference": {
- "open_pdks": "17859a0fb11c75f1be7cbfdd70c947ee4c5ad6f9",
- "magic": "86b4ac3e4c7a2141f37bf4d8760cc69aa2c23bac",
+ "open_pdks": "7c3797bed470ebecf64c8f155fbb7dc3e08d6f48",
+ "magic": "13a1bfcc2e30f063b63fd34be501820b77677bf5",
"gf180mcu_pdk": "a897aa30369d3bcec87d9d50ce9b01f320f854ef",
"gf180mcu_fd_pr": "612c346a3600bec3387e2974c8cdc692215be107",
"gf180mcu_fd_io": "2aeec51ea2824b6cc0b396acfc39f4535f40b23a",