blob: a5334d78cef7aa3558915c802b618c156e361076 [file] [log] [blame]
Tim Edwards55f4d0e2020-07-05 15:41:02 -04001#!/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
18import os
19import re
20import sys
21import stat
22import textwrap
23
24def makeuserwritable(filepath):
25 if os.path.exists(filepath):
26 st = os.stat(filepath)
27 os.chmod(filepath, st.st_mode | stat.S_IWUSR)
28
29def 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
99if __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