Instruction-level CPU simulator: fix SyntaxWarning on globals.
[trinary.git] / asm / logicCpu.py
blobde4aeefc7da65bd01175659086951956a67511e4
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 CONTINUE = 0
17 TERMINATE = 1
18 cont_exec = CONTINUE
20 # for concurency
21 locked = False
23 TRACE = False
24 DELAY = 1 # second(s)
25 USER_INPUT_THREAD = True # ask for user input?
26 USER_INPUT_INIT = 8 # initialize input to this
28 trit_integer = {"i": -1, "0":0, "1":1}
30 # Lookup a register's name by address
31 register_name = {
32 -1: "IN",
33 0: "OUT",
34 1: "A"
37 # Register contents
38 registers = {
39 "IN": 0,
40 "OUT": 0,
41 "A": 0,
42 "S": 1
45 # Thread that gets input from user
46 class CPUInput (threading.Thread):
47 def run (self):
48 global cont_exec
50 while True:
51 print "Register Status: %s :" % registers,
53 try:
54 user_input = raw_input('Input value for IN:')
55 except EOFError, e:
56 get_lock()
57 cont_exec = TERMINATE
58 release_lock()
59 sys.exit()
61 get_lock()
62 if cont_exec == TERMINATE:
63 sys.exit()
64 release_lock()
66 try:
67 digit = int(user_input)
68 except ValueError, e:
69 print "invalid input: %s (%s)" % (user_input, e)
70 continue
72 if digit >= -4 and digit <= 4:
73 registers["IN"] = digit
74 else:
75 print """invalid input: %s""" % user_input
77 def get_lock():
78 ''' Busy wait lock to avoid race conditions.
79 This function retrieves the lock.
80 '''
81 global locked
83 while locked:
84 a = 1
85 locked = True
87 def release_lock():
88 ''' This function releases the lock.
89 '''
90 global locked
92 locked = False
95 def main():
96 global cont_exec
98 # check arguments
99 if len(sys.argv) < 2 or len(sys.argv) > 2:
100 print """usage: %s program.3
101 input file: program.3 - machine code
102 """ % (sys.argv[0])
103 raise SystemExit
105 if (sys.argv[1])[len(sys.argv[1])-1:] != "3":
106 print """\'%s\' is an invalid filetype""" % sys.argv[1]
107 raise SystemExit
109 # retrieve file
110 codefile = file(sys.argv[1], "rt")
111 tritstream = codefile.readline()
113 # check for errors in file
114 if codefile == []:
115 print """\'%s\' files is empty""" % (sys.argv[1])
116 raise SystemExit
118 for i in tritstream:
119 if not i in trit_integer:
120 print """invalid char \'%s\' in file \'%s\'""" % (i, sys.argv[1])
121 raise SystemExit
123 if len(tritstream) != 9:
124 print """3 instructions must be provided in \'%s\'""" % (sys.argv[1])
125 raise SystemExit
127 # memory, registers, and program counter
128 memory = {}
130 get_lock()
131 registers["PC"] = 0
132 release_lock()
134 # decode instructions from file
135 for i in range(-1, 2):
136 print "%2d: " % (i),
137 memory[i] = Decoder(tritstream)
138 tritstream = tritstream[3:]
140 # start user input thread
141 if USER_INPUT_THREAD:
142 CPUInput().start()
144 get_lock()
145 registers["IN"] = USER_INPUT_INIT
146 release_lock()
148 # execute instructions
149 while True:
151 get_lock()
152 registers["PC"] = Execute(memory)
153 release_lock()
155 get_lock()
156 if cont_exec == TERMINATE:
157 sys.exit()
158 release_lock()
160 if TRACE:
161 get_lock()
162 print registers
163 release_lock()
165 time.sleep(DELAY)
167 def Decoder(tritstream):
168 """ Decode a single instruction.
169 tristream: stream of trits will only process the first 3 trits.
170 return: dictionary containing the operation
172 inst = {"op":trit_integer[tritstream[0]]}
174 # cmp and be
175 if inst["op"] == -1 or inst["op"] == 1:
177 if inst["op"] == -1:
178 print "cmp ",
179 else:
180 print "be ",
182 inst["src1"] = trit_integer[tritstream[1]]
183 print "%2d," % inst["src1"],
184 inst["src2"] = trit_integer[tritstream[2]]
185 print "%2d" % inst["src2"]
187 # lwi
188 elif inst["op"] == 0:
189 print "lwi ",
190 inst["src1"] = trit_integer[tritstream[1]]
191 inst["src2"] = trit_integer[tritstream[2]]
192 inst["immed"] = 3*inst["src1"] + inst["src2"]
193 print "%2d" % inst["immed"]
195 return inst
197 def Execute(memory):
198 """ Execute one instruction.
199 memory: were decoded instructions are stored
200 registers: contains registers and their values
201 returns: new program counter, to be stored in registers["PC"]
204 op = (memory[registers["PC"]])["op"]
206 # cmp
207 if op == -1:
208 src1 = (memory[registers["PC"]])["src1"]
209 src2 = (memory[registers["PC"]])["src2"]
210 if registers[register_name[src1]] < registers[register_name[src2]]:
211 registers["S"] = -1
212 elif registers[register_name[src1]] > registers[register_name[src2]]:
213 registers["S"] = 1
214 else:
215 registers["S"] = 0
216 new_pc = registers["PC"] + 1
217 # lwi
218 elif op == 0:
219 registers["A"] = (memory[registers["PC"]])["immed"]
220 new_pc = registers["PC"] + 1
221 # be
222 elif op == 1:
223 if registers["S"] == 0:
224 new_pc = (memory[registers["PC"]])["src1"]
225 else:
226 new_pc = (memory[registers["PC"]])["src2"]
228 if new_pc > 1:
229 new_pc = -1
231 return new_pc
233 if __name__ == "__main__":
234 main()