Code review logicCpu: simplify cont_exec (change to terminate_now, boolean), spelling.
[trinary.git] / asm / logicCpu.py
blob45f634b14df70ef02fd7cae0b9fcbdf9396aef7e
1 #!env python
2 # Created:20080415
3 # By Antonio Chavez
5 # 3-trit Computer Simulator
6 # usage: logicCpu program.3
7 # This program simulates the hardware of the 3 trit computer we are
8 # developing. Input to the program is a ".3" file which should contain
9 # three encoded instructions to simulate on the first line. Once started,
10 # the user may interactively change the "IN" register at any time.
11 # Execution begins with instruction at program counter 0.
13 import sys, os, threading, time, signal
15 # for safe termination
16 terminate_now = False
18 # for concurrency
19 locked = False
21 TRACE = True
22 DELAY = 1 # second(s)
23 USER_INPUT_THREAD = True # ask for user input?
24 USER_INPUT_INIT = 8 # initialize input to this
26 trit_integer = {"i": -1, "0":0, "1":1}
28 # Lookup a register's name by address
29 register_name = {
30 -1: "IN",
31 0: "OUT",
32 1: "A"
35 # Register contents
36 registers = {
37 "IN": 0,
38 "OUT": 0,
39 "A": 0,
40 "S": 1
43 # Thread that gets input from user
44 class CPUInput (threading.Thread):
45 def run (self):
46 global terminate_now
48 while True:
49 print "Register Status: %s :" % registers,
51 try:
52 user_input = raw_input('Input value for IN:')
53 except EOFError, e:
54 get_lock()
55 terminate_now = True
56 release_lock()
57 sys.exit()
59 get_lock()
60 if terminate_now:
61 sys.exit()
62 release_lock()
64 try:
65 digit = int(user_input)
66 except ValueError, e:
67 print "invalid input: %s (%s)" % (user_input, e)
68 continue
70 if digit >= -4 and digit <= 4:
71 registers["IN"] = digit
72 else:
73 print """invalid input: %s""" % user_input
75 def get_lock():
76 ''' Busy wait lock to avoid race conditions.
77 This function retrieves the lock.
78 '''
79 global locked
81 while locked:
82 a = 1
83 locked = True
85 def release_lock():
86 ''' This function releases the lock.
87 '''
88 global locked
90 locked = False
93 def main():
94 global terminate_now
96 # check arguments
97 if len(sys.argv) < 2 or len(sys.argv) > 2:
98 print """usage: %s program.3
99 input file: program.3 - machine code
100 """ % (sys.argv[0])
101 raise SystemExit
103 if (sys.argv[1])[len(sys.argv[1])-1:] != "3":
104 print """\'%s\' is an invalid filetype""" % sys.argv[1]
105 raise SystemExit
107 # retrieve file
108 codefile = file(sys.argv[1], "rt")
109 tritstream = codefile.readline()
111 # check for errors in file
112 if codefile == []:
113 print """\'%s\' files is empty""" % (sys.argv[1])
114 raise SystemExit
116 for i in tritstream:
117 if not i in trit_integer:
118 print """invalid char \'%s\' in file \'%s\'""" % (i, sys.argv[1])
119 raise SystemExit
121 if len(tritstream) != 9:
122 print """3 instructions must be provided in \'%s\'""" % (sys.argv[1])
123 raise SystemExit
125 # memory, registers, and program counter
126 memory = {}
128 get_lock()
129 registers["PC"] = 0
130 release_lock()
132 # decode instructions from file
133 for i in range(-1, 2):
134 print "%2d: " % (i),
135 memory[i] = Decoder(tritstream)
136 tritstream = tritstream[3:]
138 # start user input thread
139 if USER_INPUT_THREAD:
140 CPUInput().start()
142 get_lock()
143 registers["IN"] = USER_INPUT_INIT
144 release_lock()
146 print "Press Ctrl-D to terminate"
147 # execute instructions
148 while True:
150 get_lock()
151 registers["PC"] = Execute(memory)
152 release_lock()
154 get_lock()
155 if terminate_now:
156 sys.exit()
157 release_lock()
159 if TRACE:
160 get_lock()
161 print registers
162 release_lock()
164 time.sleep(DELAY)
166 def Decoder(tritstream):
167 """ Decode a single instruction.
168 tristream: stream of trits will only process the first 3 trits.
169 return: dictionary containing the operation
171 inst = {"op":trit_integer[tritstream[0]]}
173 # cmp and be
174 if inst["op"] == -1 or inst["op"] == 1:
176 if inst["op"] == -1:
177 print "cmp ",
178 else:
179 print "be ",
181 inst["src1"] = trit_integer[tritstream[1]]
182 print "%2d," % inst["src1"],
183 inst["src2"] = trit_integer[tritstream[2]]
184 print "%2d" % inst["src2"]
186 # lwi
187 elif inst["op"] == 0:
188 print "lwi ",
189 inst["src1"] = trit_integer[tritstream[1]]
190 inst["src2"] = trit_integer[tritstream[2]]
191 inst["immed"] = 3*inst["src1"] + inst["src2"]
192 print "%2d" % inst["immed"]
194 return inst
196 def Execute(memory):
197 """ Execute one instruction.
198 memory: were decoded instructions are stored
199 registers: contains registers and their values
200 returns: new program counter, to be stored in registers["PC"]
203 op = (memory[registers["PC"]])["op"]
205 # cmp
206 if op == -1:
207 src1 = (memory[registers["PC"]])["src1"]
208 src2 = (memory[registers["PC"]])["src2"]
209 if registers[register_name[src1]] < registers[register_name[src2]]:
210 registers["S"] = -1
211 elif registers[register_name[src1]] > registers[register_name[src2]]:
212 registers["S"] = 1
213 else:
214 registers["S"] = 0
215 new_pc = registers["PC"] + 1
216 # lwi
217 elif op == 0:
218 registers["A"] = (memory[registers["PC"]])["immed"]
219 new_pc = registers["PC"] + 1
220 # be
221 elif op == 1:
222 if registers["S"] == 0:
223 new_pc = (memory[registers["PC"]])["src1"]
224 else:
225 new_pc = (memory[registers["PC"]])["src2"]
227 if new_pc > 1:
228 new_pc = -1
230 return new_pc
232 if __name__ == "__main__":
233 main()