5 # 3-trit computer assembler
11 print """usage: %s program.t
12 input file: program.t - assembly code
14 \tprogram.3 - assembled tritstream
15 \tprogram.sp - SPICE file suitable for use with swrom-fast
20 if not sys
.argv
[1].endswith(".t"):
21 print "Input assembly filename must end in .t"
24 asmfile
= file(sys
.argv
[1], "rt")
25 tritstream_filename
= sys
.argv
[1].replace(".t", ".3")
26 tritstream_file
= file(tritstream_filename
, "wt")
27 spice_filename
= sys
.argv
[1].replace(".t", ".sp")
28 spice_file
= file(spice_filename
, "wt")
30 tritstream
= assemble(asmfile
)
31 tritstream_file
.write(tritstream
)
32 spice_file
.write(tospice(tritstream
))
34 def tospice(tritstream
):
35 """Convert tritstream to SPICE source for 3x3 swrom-fast."""
37 # Read down, then across (one instruction per _column_, not row)
46 all_instr
.append(tritstream
[i
*3:i
*3+3])
47 code
[0][i
] = tritstream
[i
*3 + 0]
48 code
[1][i
] = tritstream
[i
*3 + 1]
49 code
[2][i
] = tritstream
[i
*3 + 2]
51 s
= "; swrom-fast include file, generated to by asm/asm.py, for tritstream:\n"
52 for instr
in all_instr
:
53 s
+= "; " + instr
+ "\n"
56 s
+= """; Select a voltage value based on the logic input at A
57 .func choose(A,for_n,for_z,for_p) {if(A<={V_N_max},for_n,if(A>={V_P_min},for_p,for_z))}
67 s
+= ".func program_%s(A) {choose(A," % ({0:"i", 1:0, 2:1}[i
],)
80 s
+= ",".join(voltages
)
84 def assemble(asmfile
):
85 """Return a serialized tritstream of asmfile assembled."""
86 pc
= 0 # PC goes 0, 1, -1 _NOT_ -1, 0, 1 (0 on power-up)
88 opcode_map
= { "lwi": [0], "cmp": [-1], "be": [1] }
89 register_map
= { "in": [-1], "out": [0], "a": [1] }
90 # TODO: balanced trinary conversion routines
105 line
= asmfile
.readline()
115 label
, opcode
, operands
= parse_line(line
)
119 #print [label, opcode, operands]
122 if label
is not None:
125 machine_code
.extend(opcode_map
[opcode
])
127 x
= register_map
.get(op
,
129 literal_map
.get(op
)))
131 print "Bad register, label, or literal: %s" % (op
, )
132 print "Labels: %s" % (labels
,)
135 machine_code
.extend(x
)
137 assert len(machine_code
) == 3, \
138 "Incorrect operand count, instruction trits:: %s" % (machine_code
,)
139 tritstream
.extend(machine_code
)
142 print "Too many instructions, need exactly 3 but pc=%d" % (pc
,)
146 print "Too few instructions, need exactly 3 but pc=%d" % (pc
,)
151 # Execution goes 0, 1, i
152 # but we ordered i, 0, 1.
153 # Arrange the instructions so that the first
154 # instruction written is placed at 0, next at
155 # 1, then the last instruction at i--since
156 # execution begins at 0, this will perserve the order.
157 tritstream_ordered
= (
158 tritstream
[3*2:3*2+3] + # last instruction executed
159 tritstream
[3*0:3*0+3] + # <-- PC starts here (0)
160 tritstream
[3*1:3*1+3] # second instruction executed
163 # Serialize tritstream
165 for t
in tritstream_ordered
:
173 def parse_line(line
):
175 without_comment
= line
.split(";", 1)[0]
176 if len(without_comment
) == 0:
177 return (None, None, None)
179 # Separate label from instruction
180 label_and_instruction
= without_comment
.split(":", 1)
181 if len(label_and_instruction
) > 1:
182 label
, instruction
= label_and_instruction
183 label
= label
.strip()
185 instruction
, = label_and_instruction
188 instruction
= instruction
.strip()
190 # Separate opcode from operands
191 tokens
= instruction
.split()
194 for token
in tokens
[1:]:
195 token
= token
.replace(",", "")
196 operands
.append(token
)
198 return (label
, opcode
, operands
)
200 if __name__
== "__main__":