5 # Created PADS-PCB netlist file, for FreePCB at http://www.freepcb.com/ ,
6 # or any other PCB layout program that supports the PADS-PCB format.
10 PROGRAM_NAME
= "pads.py"
15 "R": "RC07", # 1/4 W resistor
16 "MDP1403-12K": "14DIP300", # 7 x resistor network, all 12k
17 "V": "1X2HDR-100-40", # header, **with 40 mil holes**
18 "sp3t-1": "SS14MDP2", # NKK switch, in position 1
19 "sp3t-2": "SS14MDP2", # NKK switch, in position 2
20 "sp3t-3": "SS14MDP2", # NKK switch, in position 3
21 #"1N4148": "DO-35", # Diode
22 "D": "DO-35", # All diodes (note: should really be specific!)
25 # TODO: Add bypass capacitor? Might be better done
26 # manually, on back of board, directly between 7 and 14.
28 # TODO: Connect not-connected pins? Probably a good idea but
29 # be careful about shorting something. Could also be done
30 # manually, with copious amounts of solder.
32 # Append/prepend this to all part and net names (note, prefix may
33 # cause problems with footprint mapping, if can't be recognized.)
37 # Append/prepend to all net names
38 NETNAME_SUFFIX
= os
.environ
.get("JC_NETNAME_SUFFIX", "")
41 # If enabled, name resistors numerically R1, R2, ... instead of hierarchically.
42 SERIAL_RESISTORS
= True
43 RESISTOR_SERIAL_START
= int(os
.environ
.get("JC_RESISTOR_SERIAL_START", 0))
45 # If enabled, anything containing Vdd or Vss will be named Vdd or Vss--
46 # effectively disabling hierarchy for these power sources. **Note that if
47 # there are multiple Vdd and Vss, this will cause duplicate parts!**
50 # If enabled, RX$Xflipflop$XX<n>$Xinv$R{P,N} will be mapped to ${P,N}<n>.
51 # Useful for laying out a single dtflop-ms_test, but may cause serious
53 SHORT_DTFLOP_RP_RN
= False
55 # TODO: remove these limitations on FreePCB, so that
56 # USE_SHORT_NAMES and BREAK_LONG_LINES can be turned off!
58 # If true, reference designators and node names will be assigned
59 # sequentially if needed, instead of using their hierarchical name
60 # from the net2 file. Some PCB programs have length limits
61 # on reference designators (FreePCB).
62 USE_SHORT_NAMES
= True
64 # Split long nets over multiple lines.
65 BREAK_LONG_LINES
= True
67 # If not false, nodes with only one connection will have a
68 # testpoint attached, using the given footprint.
69 #NAKED_NODE_FOOTPRINT = "HOLE_100_RND_200"
70 NAKED_NODE_FOOTPRINT
= None
74 print """usage: %s input-filename [output-filename]
76 input-filename A chip-level SPICE netlist (.net2)
77 output-filename PADS-PCB layout netlist (.pads)
79 If output-filename is omitted, input-filename is used but
80 with a .pads extension instead of .net2, or .pads appended.
82 Either filenames can be "-" for stdin or stdout, respectively.
83 """ % (PROGRAM_NAME
, )
86 # MAX_NET_NAME_SIZE and FMAX_PIN_NAME_SIZE from
87 # svn://svn.berlios.de/freepcb/trunk/Shape.h and Netlist.h
88 # (TODO: remove these arbitrary limits in FreePCB)
92 # Names to preserve, if USE_SHORT_NAMES is True.
93 # Would be nice to preserve all/more net names, but
94 # some are just too long and hierarchical.
105 resistor_serial
= RESISTOR_SERIAL_START
109 def shorten(long, is_netname
):
110 global short2long_map
112 short
= UNIVERSAL_PREFIX
+ shorten_2(long, is_netname
) + UNIVERSAL_SUFFIX
114 short
= NETNAME_PREFIX
+ short
+ NETNAME_SUFFIX
116 # Save short -> long for future reference
117 short2long_map
[short
] = long
121 def shorten_2(long, is_netname
):
122 global resistor_serial
130 if long.startswith("R") and SERIAL_RESISTORS
:
132 return "R%d" % (resistor_serial
,)
134 if not USE_SHORT_NAMES
:
137 if SHORT_DTFLOP_RP_RN
and long.startswith("RX$Xflipflop$XX"):
138 short
= long[len("RX$Xflipflop$XX"):][0]
139 if long.endswith("RP"):
141 elif long.endswith("RN"):
144 sys
.stderr
.write("dtflop RP/RN mapping enabled, but not RP/RN!")
148 if len(long) <= MAX_SIZE
:
149 # We got away with it this time.
152 # Resistors are what you have to watch our for
153 if long2short
.has_key(long):
154 short
= long2short
[long]
156 # id = first letter, 'R', etc.
157 # Net names get a prefix of "NX" (for node extended;
158 # the name was too long so it was shortened)
165 #sys.stderr.write("%s\n" % (long,))
166 short
= "%s%d" % (id, next_serial
[id])
167 long2short
[long] = short
172 if len(sys
.argv
) < 2:
174 filename
= sys
.argv
[1]
176 # Redirect stdout to output file
177 if len(sys
.argv
) > 2:
178 output_filename
= sys
.argv
[2]
180 output_filename
= filename
.replace(".net2", ".pads")
181 if output_filename
== filename
:
182 output_filename
= filename
+ ".pads"
183 if output_filename
!= "-":
184 sys
.stdout
= file(output_filename
, "wt")
187 print "*%s*" % (filename
, )
194 infile
= file(filename
, "rt")
195 for line
in infile
.readlines():
204 long_refdesg
= words
[0]
206 refdesg
= shorten(long_refdesg
, is_netname
=False)
209 if refdesg
[0] == 'V':
210 # Voltage sources only have two pins, other arguments
211 # may be PWL or other values (really one argument, but
212 # separated by spaces, so we'll see it as more than one).
213 args
= [args
[0], args
[1]]
216 for i
, long_arg
in enumerate(args
):
217 if long_arg
.startswith("NC_"):
223 #sys.stderr.write("-> %s" % (line,))
224 arg
= shorten(long_arg
, is_netname
=True)
226 if arg
not in nets
.keys():
229 nets
[arg
].append("%s.%s" % (refdesg
, i
+ 1))
234 parts
.append((refdesg
, model
))
237 # Map models to footprints
240 refdesg
, model
= part
241 if footprint_map
.has_key(model
):
242 package
= footprint_map
[model
]
243 elif footprint_map
.has_key(refdesg
[0]):
244 package
= footprint_map
[refdesg
[0]]
246 raise "Part name %s, model %s unknown, couldn't find in map: %s" % (refdesg
, model
, footprint_map
)
247 print "%s %s" % (refdesg
, package
)
249 # Nets with only one node get testpoints for free (also appends to parts list)
250 if NAKED_NODE_FOOTPRINT
:
251 for signal_name
, nodes
in nets
.iteritems():
253 testpoint
= "%s_tp" % (signal_name
,)
254 print "%s %s" % (testpoint
, NAKED_NODE_FOOTPRINT
)
255 nets
[signal_name
].append(testpoint
)
260 for signal
, pins
in nets
.iteritems():
261 print "*SIGNAL* %s" % (signal
,)
266 # Break lines every so many pins
267 # (would be nice if didn't have to do this)
275 # Print a newline at the end for picky layout programs (ExpressPCB)
279 # Save short->long map so that abbreviated part names
280 # (such as R1 or NX1) can be mapped to the full, hierarchical
281 # name for debugging purposes.
282 mapfilename
= filename
.replace(".net2", ".map")
283 if mapfilename
== filename
:
284 mapfilename
= filename
+ ".map"
285 mapfile
= file(mapfilename
, "wt")
286 for short
, long in short2long_map
.items():
287 mapfile
.write("%s,%s\n" % (short
, long))