Make assign_part() into a function, and make not-connected node names unique.
[trinary.git] / bb.py
blob185826be37d6efb18b87808bcbd77f72db054f72
1 #!/usr/bin/env python
2 # Created:20080411
3 # By Jeff Connelly
5 # Breadboard/circuit pin layout program
7 import copy
8 import types
10 import tg
11 import tinv
13 def combine_dicts(dict1, dict2):
14 """Combine two dictionaries; dict2 takes priority over dict1."""
15 ret = copy.deepcopy(dict1)
16 ret.update(dict2)
17 return ret
19 def read_netlist(filename):
20 """Read a SPICE input deck, returning subcircuit nodes and definitions."""
22 f = file(filename, "rt")
23 subckt_nodes = {}
24 subckt_defns = {}
25 name = None
26 while True:
27 line = f.readline()
28 if len(line) == 0:
29 break
31 line = line.strip()
33 if line.startswith(".subckt"):
34 words = line.split()
35 name = words[1]
36 nodes = words[2:]
38 subckt_nodes[name] = nodes
39 elif line.startswith(".ends"):
40 name = None
41 else:
42 if name is not None:
43 if not subckt_defns.has_key(name):
44 subckt_defns[name] = []
45 subckt_defns[name].append(line)
47 return subckt_nodes, subckt_defns
49 subckt_nodes, subckt_defns = read_netlist("../code/circuits/mux3-1_test.net")
51 print subckt_nodes
52 print subckt_defns
54 def rewrite_subckt(subckt_defns, s):
55 """Partially rewrite subcircuit 's', using rules from a module of the same name.
57 Removes parts in mod.parts_consumed, keeps parts in mod.parts_kept.
59 Does not generate any new parts."""
61 mod = globals()[s]
62 lines = []
63 for line in subckt_defns[s]:
64 words = line.split()
65 name = words[0]
66 args = words[1:]
68 if name in mod.parts_consumed:
69 # Skip this line
70 pass
71 elif name in mod.parts_kept:
72 lines.append(line)
73 else:
74 raise "Subcircuit %s defined in module %s has parts consumed list: %s and parts kept list: %s, but the name '%s' is in neither. Add it to either." % (s, name, mod.parts_consumed, mod.parts_kept, name)
76 # Map node positions in arguments list (subckt invocation, X..), to node names
77 pos2node = {}
78 for i in range(0, len(mod.nodes)):
79 pos2node[mod.nodes[i]] = i
81 # Rewrite
82 subckt_defns[s] = lines
84 return mod, subckt_defns, pos2node
86 def assign_part(chips, mod):
87 # Store new pin assignments
88 assignments = {}
89 for p in mod.parts_generated:
90 assignments[p] = {}
92 # TODO: choose next available component in part, instead of always 0
93 for node, pin in combine_dicts(mod.global_pins, mod.pins[0]).iteritems():
94 if type(pin) == types.TupleType:
95 part, pin = pin
96 else:
97 part = None
99 print "* %s -> %s:%s" % (node, part, pin)
101 if part is not None:
102 assignments[part][pin] = node
104 for part in assignments:
105 print "* --%s--" % (part,)
106 for pin in range(1, max(assignments[part].keys()) + 1):
107 node = assignments[part].get(pin, "NC__%s_%s_%s_%s" % (mod.__name__, part, len(chips), pin))
109 print "* ", (pin,node)
111 mod, subckt_defns, pos2node = rewrite_subckt(subckt_defns, "tinv")
112 chips = {}
113 chips = assign_part(chips, mod)
116 # sti
117 line = "XX1 IN NC_01 OUT NC_02 tinv"