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)