Tim Edwards | 55f4d0e | 2020-07-05 15:41:02 -0400 | [diff] [blame] | 1 | #!/usr/bin/env python3 |
| 2 | # |
| 3 | #------------------------------------------------------------------- |
| 4 | # makestub.py |
| 5 | # |
| 6 | # Read a CDL or SPICE netlist and remove all contents from subcircuits, |
| 7 | # leaving only the .SUBCKT ... .ENDS wrapper. Used as a filter, so it |
| 8 | # replaces the original file with the modified one. If the original |
| 9 | # file is a symbolic link, then it is first unlinked and replaced with |
| 10 | # the new contents. |
| 11 | # |
| 12 | # Use: |
| 13 | # |
| 14 | # makestub.py <path_to_netlist_file> |
| 15 | # |
| 16 | #------------------------------------------------------------------- |
| 17 | |
| 18 | import os |
| 19 | import re |
| 20 | import sys |
| 21 | import stat |
| 22 | import textwrap |
| 23 | |
| 24 | def makeuserwritable(filepath): |
| 25 | if os.path.exists(filepath): |
| 26 | st = os.stat(filepath) |
| 27 | os.chmod(filepath, st.st_mode | stat.S_IWUSR) |
| 28 | |
| 29 | def generate_stubs(netlist_path, output_path): |
| 30 | netlist_dir = os.path.split(netlist_path)[0] |
| 31 | netlist_filename = os.path.split(netlist_path)[1] |
| 32 | netlist_root = os.path.splitext(netlist_filename)[0] |
| 33 | netlist_ext = os.path.splitext(netlist_filename)[1] |
| 34 | |
| 35 | if not os.path.exists(netlist_path): |
| 36 | print('Error: Specified file "' + netlist_path + '" does not exist!') |
| 37 | return |
| 38 | |
| 39 | if output_path == None: |
| 40 | output_path = netlist_path |
| 41 | |
| 42 | with open(netlist_path, 'r') as ifile: |
| 43 | spicetext = ifile.read().splitlines() |
| 44 | |
| 45 | # Remove blank lines and comment lines |
| 46 | spicelines = [] |
| 47 | for line in spicetext: |
| 48 | if len(line) > 0: |
| 49 | if line[0] != '*': |
| 50 | spicelines.append(line) |
| 51 | |
| 52 | # Remove line extensions |
| 53 | spicetext = '\n'.join(spicelines) |
| 54 | spicelines = spicetext.replace('\n+', ' ').splitlines() |
| 55 | |
| 56 | # SPICE subcircuit definition: |
| 57 | subcrex = re.compile(r'[ \t]*\.subckt[ \t]+([^ \t]+)[ \t]+(.*)$', re.IGNORECASE) |
| 58 | endsrex = re.compile(r'[ \t]*\.ends[ \t]*', re.IGNORECASE) |
| 59 | |
| 60 | spiceoutlines = [] |
| 61 | |
| 62 | insub = False |
| 63 | for line in spicelines: |
| 64 | if insub: |
| 65 | ematch = endsrex.match(line) |
| 66 | if ematch: |
| 67 | insub = False |
| 68 | spiceoutlines.append(line) |
| 69 | else: |
| 70 | smatch = subcrex.match(line) |
| 71 | if smatch: |
| 72 | insub = True |
| 73 | spiceoutlines.append('') |
| 74 | spiceoutlines.append('*----------------------------------------------') |
| 75 | spiceoutlines.append('* SPICE stub entry for ' + smatch.group(1) + '.') |
| 76 | spiceoutlines.append('*----------------------------------------------') |
| 77 | spiceoutlines.append('') |
| 78 | spiceoutlines.append(line) |
| 79 | |
| 80 | if output_path == netlist_path: |
| 81 | if os.path.islink(netlist_path): |
| 82 | os.unlink(netlist_path) |
| 83 | |
| 84 | # Re-wrap continuation lines at 100 characters |
| 85 | wrappedlines = [] |
| 86 | for line in spiceoutlines: |
| 87 | wrappedlines.append('\n+ '.join(textwrap.wrap(line, 100))) |
| 88 | |
| 89 | # Just in case the file in the source repo is not user-writable |
| 90 | if os.path.exists(output_path): |
| 91 | makeuserwritable(output_path) |
| 92 | |
| 93 | with open(output_path, 'w') as ofile: |
| 94 | for line in wrappedlines: |
| 95 | print(line, file=ofile) |
| 96 | |
| 97 | # If called as main, run generate_stubs |
| 98 | |
| 99 | if __name__ == '__main__': |
| 100 | |
| 101 | # Divide up command line into options and arguments |
| 102 | options = [] |
| 103 | arguments = [] |
| 104 | for item in sys.argv[1:]: |
| 105 | if item.find('-', 0) == 0: |
| 106 | options.append(item) |
| 107 | else: |
| 108 | arguments.append(item) |
| 109 | |
| 110 | # Need one argument: path to CDL or SPICE netlist |
| 111 | # If two arguments, then 2nd argument is the output file. |
| 112 | |
| 113 | if len(arguments) == 2: |
| 114 | netlist_path = arguments[0] |
| 115 | output_path = arguments[1] |
| 116 | generate_stubs(netlist_path, output_path) |
| 117 | elif len(arguments) != 1: |
| 118 | print("Usage: makestub.py <file_path> [<output_path>]") |
| 119 | elif len(arguments) == 1: |
| 120 | netlist_path = arguments[0] |
| 121 | generate_stubs(netlist_path, None) |
| 122 | |