Added Harald Pretl's Python script that can convert the sky130.lib.spice
file to extract a single corner and output a valid library file with
only the one corner; this greatly speeds up ngspice, which does not
handle the library file parsing gracefully. Thanks to Harald for the
contribution!
diff --git a/runtime/spice_model_red.py b/runtime/spice_model_red.py
new file mode 100644
index 0000000..e9c235a
--- /dev/null
+++ b/runtime/spice_model_red.py
@@ -0,0 +1,119 @@
+#!/usr/bin/env python3
+#
+# This script traverses SPICE model files (e.g. from SKY130) and
+# extracts only the wanted model section, removes all comments and
+# empty lines, and resolves all includes so that a flat model file
+# results. This should speed up ngspice starts.
+#
+# (c) 2021 Harald Pretl, Johannes Kepler University Linz
+
+import sys,re,os
+
+def process_file(file_in_name, top_file):
+ global is_warning
+ try:
+ f_in = open(file_in_name, 'r')
+ except FileNotFoundError:
+ print('Warning! File ' + file_in_name + ' not found.')
+ is_warning = True
+ return;
+
+ # process_file can be called recursively, so that nested include
+ # files can be traversed
+
+ # write_active indicates whether we are in the right model section; in
+ # include files, it is always true
+
+ if top_file == True:
+ write_active = False
+ else:
+ write_active = True
+
+ for line in f_in:
+ line_trim = (line.lower()).strip()
+
+ if top_file == True:
+ # we assume that .lib statements are only used in the main file
+ if '.lib' in line_trim:
+ if model_section in line_trim:
+ write_active = True
+ else:
+ write_active = False
+
+ if '.endl' == line_trim:
+ write_active = False
+ f_out.write(line)
+
+ if len(line_trim) > 0: # write no empty lines
+ if (line_trim[0] != '*'): # write no comments
+ if (write_active == True):
+ if '.include' in line_trim:
+ # need to save and restore working dir so that nested
+ # includes work
+ current_wd = os.getcwd()
+ newfile = re.findall(r'"(.*?)(?<!\\)"', line_trim)
+ print('Reading ',newfile[0])
+
+ # enter new working dir
+ new_wd = os.path.dirname(newfile[0])
+ if len(new_wd) > 0:
+ try:
+ os.chdir(new_wd)
+ except OSError:
+ print('Warning: Could not enter directory ' + new_wd)
+ is_warning = True
+
+ # traverse into new include file
+ new_file_name = os.path.basename(newfile[0])
+ process_file(new_file_name, False)
+
+ # restore old working dir after return
+ os.chdir(current_wd)
+ else:
+ f_out.write(line)
+
+ f_in.close()
+ return;
+
+# main routine
+
+if len(sys.argv) == 3:
+ model_section = sys.argv[2]
+else:
+ model_section = 'tt'
+
+if (len(sys.argv) == 2) or (len(sys.argv) == 3):
+ infile_name = sys.argv[1]
+ outfile_name = infile_name + '.' + model_section + '.red'
+
+ try:
+ f_out = open(outfile_name, 'w')
+ except OSError:
+ print('Error: Cannot write file ' + outfile_name + '.')
+ sys.exit(2)
+
+ is_warning = False
+ process_file(infile_name, True)
+ f_out.close()
+
+ print()
+ print('Model file ' + outfile_name + ' written.')
+ if is_warning == True:
+ print('There have been warnings! Please check output log.')
+ sys.exit(1)
+ else:
+ sys.exit(0)
+else:
+ print()
+ print('spice_model_red.py SPICE model file reducer')
+ print(' (c) 2021 Harald Pretl, JKU')
+ print()
+ print('Usage: spice_model_red <inputfile> [corner] (default corner = tt)')
+ print()
+ print('Return codes for script automation:')
+ print(' 0 = all OK')
+ print(' 1 = warnings')
+ print(' 2 = errors')
+ print(' 3 = call of script w/o parameters (= showing this message)')
+ print()
+ sys.exit(3)