| #!/usr/bin/env python3 |
| # |
| #------------------------------------------------------------------- |
| # makestub.py |
| # |
| # Read a CDL or SPICE netlist and remove all contents from subcircuits, |
| # leaving only the .SUBCKT ... .ENDS wrapper. Used as a filter, so it |
| # replaces the original file with the modified one. If the original |
| # file is a symbolic link, then it is first unlinked and replaced with |
| # the new contents. |
| # |
| # Use: |
| # |
| # makestub.py <path_to_netlist_file> |
| # |
| #------------------------------------------------------------------- |
| |
| import os |
| import re |
| import sys |
| import stat |
| import textwrap |
| |
| def makeuserwritable(filepath): |
| if os.path.exists(filepath): |
| st = os.stat(filepath) |
| os.chmod(filepath, st.st_mode | stat.S_IWUSR) |
| |
| def generate_stubs(netlist_path, output_path): |
| netlist_dir = os.path.split(netlist_path)[0] |
| netlist_filename = os.path.split(netlist_path)[1] |
| netlist_root = os.path.splitext(netlist_filename)[0] |
| netlist_ext = os.path.splitext(netlist_filename)[1] |
| |
| if not os.path.exists(netlist_path): |
| print('Error: Specified file "' + netlist_path + '" does not exist!') |
| return |
| |
| if output_path == None: |
| output_path = netlist_path |
| |
| with open(netlist_path, 'r') as ifile: |
| spicetext = ifile.read().splitlines() |
| |
| # Remove blank lines and comment lines |
| spicelines = [] |
| for line in spicetext: |
| if len(line) > 0: |
| if line[0] != '*': |
| spicelines.append(line) |
| |
| # Remove line extensions |
| spicetext = '\n'.join(spicelines) |
| spicelines = spicetext.replace('\n+', ' ').splitlines() |
| |
| # SPICE subcircuit definition: |
| subcrex = re.compile(r'[ \t]*\.subckt[ \t]+([^ \t]+)[ \t]+(.*)$', re.IGNORECASE) |
| endsrex = re.compile(r'[ \t]*\.ends[ \t]*', re.IGNORECASE) |
| |
| spiceoutlines = [] |
| |
| insub = False |
| for line in spicelines: |
| if insub: |
| ematch = endsrex.match(line) |
| if ematch: |
| insub = False |
| spiceoutlines.append(line) |
| else: |
| smatch = subcrex.match(line) |
| if smatch: |
| insub = True |
| spiceoutlines.append('') |
| spiceoutlines.append('*----------------------------------------------') |
| spiceoutlines.append('* SPICE stub entry for ' + smatch.group(1) + '.') |
| spiceoutlines.append('*----------------------------------------------') |
| spiceoutlines.append('') |
| spiceoutlines.append(line) |
| |
| if output_path == netlist_path: |
| if os.path.islink(netlist_path): |
| os.unlink(netlist_path) |
| |
| # Re-wrap continuation lines at 100 characters |
| wrappedlines = [] |
| for line in spiceoutlines: |
| wrappedlines.append('\n+ '.join(textwrap.wrap(line, 100))) |
| |
| # Just in case the file in the source repo is not user-writable |
| if os.path.exists(output_path): |
| makeuserwritable(output_path) |
| |
| with open(output_path, 'w') as ofile: |
| for line in wrappedlines: |
| print(line, file=ofile) |
| |
| # If called as main, run generate_stubs |
| |
| if __name__ == '__main__': |
| |
| # Divide up command line into options and arguments |
| options = [] |
| arguments = [] |
| for item in sys.argv[1:]: |
| if item.find('-', 0) == 0: |
| options.append(item) |
| else: |
| arguments.append(item) |
| |
| # Need one argument: path to CDL or SPICE netlist |
| # If two arguments, then 2nd argument is the output file. |
| |
| if len(arguments) == 2: |
| netlist_path = arguments[0] |
| output_path = arguments[1] |
| generate_stubs(netlist_path, output_path) |
| elif len(arguments) != 1: |
| print("Usage: makestub.py <file_path> [<output_path>]") |
| elif len(arguments) == 1: |
| netlist_path = arguments[0] |
| generate_stubs(netlist_path, None) |
| |