Merge branch 'master' into xcircuit-3.10
[xcircuit.git] / lib / python / flatspice.py
blob89d6263f2409ac5956c695909422ca4419a55d6b
1 # flatspice.py
2 #-----------------------------------------------------------
3 # Python script which writes a SPICE-format netlist.
4 # Replaces the code formerly in "netlist.c" (deprecated).
5 # Python scripting is now the preferred method for handling
6 # netlist output formats.
7 #-----------------------------------------------------------
9 # Select the device string corresponding to the given prefix.
10 # Return the body of the string, or an empty string if the prefix doesn't match.
12 def select(sstr, prefix):
13 ltext = ''
14 if sstr.startswith(prefix):
15 ltext += sstr[len(prefix) + 1:]
16 return ltext
18 # Generate an ASCII string from an xcircuit string (list)
20 def textprint(slist, params):
21 ltext = ''
22 is_symbol = 0
23 is_iso = 0
24 for x in slist:
25 try:
26 f = x.keys()[0]
27 except AttributeError: # must be a string
28 if x == 'Return':
29 ltext += '\n'
30 elif x == 'Underline':
31 ltext += '_'
32 elif x == 'Overline':
33 ltext += '!'
34 else: # is a dictionary; will have only one key
35 if f == 'Font':
36 lfont = x[x.keys()[0]]
37 if lfont.startswith('Symbol'):
38 is_symbol = 1
39 else:
40 is_symbol = 0
41 if lfont.endswith('ISO'):
42 is_iso = 1
43 else:
44 is_iso = 0
45 elif f == 'Parameter':
46 ltext += textprint(params[x[x.keys()[0]]], [])
47 else: # text: SPICE translates "mu" to "u"
48 for y in x[x.keys()[0]]:
49 if is_symbol:
50 if y == 'f':
51 ltext += 'phi'
52 elif y == 'm':
53 ltext += 'u'
54 else:
55 ltext += y
56 else:
57 if ord(y) == 181:
58 ltext += 'u'
59 elif ord(y) > 127:
60 ltext += '/' + str(ord(y))
61 else:
62 ltext += y
63 return ltext
66 # Flatten the netlist and write to the output
68 def recurseflat(outfile, ckt, clist):
69 try:
70 v = ckt['calls'] # calls to subcircuits
71 except KeyError: # A bottom-level circuit element
72 pass
73 else:
74 for y in v:
75 for z in clist:
76 if z['name'] == y['name']:
77 # copy the object and substitute net names into subcircuit ports
78 lobj = z
79 lobj['ports'] = y['ports']
80 recurseflat(outfile, lobj, clist)
81 break;
82 try:
83 w = ckt['devices']
84 except KeyError:
85 pass
86 else:
87 for y in w:
88 for u in y:
89 lstr = select(textprint(u, []), 'spice')
90 if lstr <> '':
91 outfile.write('device: ' + lstr + '\n')
93 # Top of the flattened-circuit writing routine
95 def writespiceflat():
96 p=netlist()
97 g=p['globals']
98 c=p['circuit']
99 l=len(c)
100 top=c[l-1]
101 topname=top['name']
102 topname += '.spc'
103 try:
104 outfile=open(topname, 'w')
105 except IOError:
106 return
108 # print header line
110 outfile.write('*SPICE flattened circuit "' + topname + '"')
111 outfile.write(' from XCircuit v' + str(xc_version))
112 outfile.write(' (Python script "flatspice.py")\n')
114 # print global variables
116 for x in g: # 'globals' is a list of strings
117 outfile.write('.GLOBAL ' + textprint(x, []) + '\n')
118 outfile.write('\n')
120 recurseflat(outfile, top, c)
121 outfile.write('.end\n')
122 outfile.close()
124 # Key binding and menu button for the spice netlist output
125 # bind('Alt_F', 'writespiceflat')
126 newbutton('Netlist', 'Write Flattened Spice', 'writespiceflat')