Merge git://repo.or.cz/trinary
[trinary.git] / asm / logicCpu.py
blobe6df369e3fa5160da5ef322d9c83b474ef326e42
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
15 TRACE = True
16 DELAY = 1 # second(s)
17 USER_INPUT_THREAD = True # ask for user input?
18 USER_INPUT_INIT = 8 # initialize input to this
20 trit_integer = {"i": -1, "0":0, "1":1}
22 # Lookup a register's name by address
23 register_name = {
24 -1: "IN",
25 0: "OUT",
26 1: "A"
29 # Register contents
30 registers = {
31 "IN": 0,
32 "OUT": 0,
33 "A": 0,
34 "S": 1
37 # Thread that gets input from user
38 class CPUInput (threading.Thread):
39 def run (self):
40 while True:
41 print "Register Status: %s :" % registers,
42 user_input = raw_input('Input value for IN:')
44 try:
45 digit = int(user_input)
46 except ValueError, e:
47 print "invalid input: %s (%s)" % (user_input, e)
48 continue
50 if digit >= -4 and digit <= 4:
51 registers["IN"] = digit
52 else:
53 print """invalid input: %s""" % user_input
55 def main():
56 # check arguments
57 if len(sys.argv) < 2 or len(sys.argv) > 2:
58 print """usage: %s program.3
59 input file: program.3 - machine code
60 """ % (sys.argv[0])
61 raise SystemExit
63 if (sys.argv[1])[len(sys.argv[1])-1:] != "3":
64 print """\'%s\' is an invalid filetype""" % sys.argv[1]
65 raise SystemExit
67 # retrieve file
68 codefile = file(sys.argv[1], "rt")
69 tritstream = codefile.readline()
71 # check for errors in file
72 if codefile == []:
73 print """\'%s\' files is empty""" % (sys.argv[1])
74 raise SystemExit
76 for i in tritstream:
77 if not i in trit_integer:
78 print """invalid char \'%s\' in file \'%s\'""" % (i, sys.argv[1])
79 raise SystemExit
81 if len(tritstream) != 9:
82 print """3 instructions must be provided in \'%s\'""" % (sys.argv[1])
83 raise SystemExit
85 # memory, registers, and program counter
86 memory = {}
87 registers["PC"] = 0
89 # decode instructions from file
90 for i in range(-1, 2):
91 print "%2d: " % (i),
92 memory[i] = Decoder(tritstream)
93 tritstream = tritstream[3:]
95 # start user input thread
96 if USER_INPUT_THREAD:
97 CPUInput().start()
98 registers["IN"] = USER_INPUT_INIT
100 # execute instructions
101 while True:
102 registers["PC"] = Execute(memory)
104 if TRACE:
105 print registers
107 time.sleep(DELAY)
109 def Decoder(tritstream):
110 """ Decode a single instruction.
111 tristream: stream of trits will only process the first 3 trits.
112 return: dictionary containing the operation
114 inst = {"op":trit_integer[tritstream[0]]}
116 # cmp and be
117 if inst["op"] == -1 or inst["op"] == 1:
119 if inst["op"] == -1:
120 print "cmp ",
121 else:
122 print "be ",
124 inst["src1"] = trit_integer[tritstream[1]]
125 print "%2d," % inst["src1"],
126 inst["src2"] = trit_integer[tritstream[2]]
127 print "%2d" % inst["src2"]
129 # lwi
130 elif inst["op"] == 0:
131 print "lwi ",
132 inst["src1"] = trit_integer[tritstream[1]]
133 inst["src2"] = trit_integer[tritstream[2]]
134 inst["immed"] = 3*inst["src1"] + inst["src2"]
135 print "%2d" % inst["immed"]
137 return inst
139 def Execute(memory):
140 """ Execute one instruction.
141 memory: were decoded instructions are stored
142 registers: contains registers and their values
143 returns: new program counter, to be stored in registers["PC"]
146 op = (memory[registers["PC"]])["op"]
148 # cmp
149 if op == -1:
150 src1 = (memory[registers["PC"]])["src1"]
151 src2 = (memory[registers["PC"]])["src2"]
152 if registers[register_name[src1]] < registers[register_name[src2]]:
153 registers["S"] = -1
154 elif registers[register_name[src1]] > registers[register_name[src2]]:
155 registers["S"] = 1
156 else:
157 registers["S"] = 0
158 new_pc = registers["PC"] + 1
159 # lwi
160 elif op == 0:
161 registers["A"] = (memory[registers["PC"]])["immed"]
162 new_pc = registers["PC"] + 1
163 # be
164 elif op == 1:
165 if registers["S"] == 0:
166 new_pc = (memory[registers["PC"]])["src1"]
167 else:
168 new_pc = (memory[registers["PC"]])["src2"]
170 if new_pc > 1:
171 new_pc = -1
173 return new_pc
175 if __name__ == "__main__":
176 main()