1 |
2 |
hmanske |
from pyparsing import *
|
2 |
|
|
import serial
|
3 |
|
|
|
4 |
|
|
#------------------------------------------------------------------------------------------------------
|
5 |
|
|
# CLASS STACK
|
6 |
|
|
#------------------------------------------------------------------------------------------------------
|
7 |
|
|
class Stack(object):
|
8 |
|
|
def __init__(self):
|
9 |
|
|
self.stack = []
|
10 |
|
|
|
11 |
|
|
def push(self, value):
|
12 |
|
|
self.stack.append(value)
|
13 |
|
|
|
14 |
|
|
def pop(self):
|
15 |
|
|
if len(self.stack) == 0:
|
16 |
|
|
return None
|
17 |
|
|
value = self.stack[-1]
|
18 |
|
|
del self.stack[-1]
|
19 |
|
|
return value
|
20 |
|
|
|
21 |
|
|
#------------------------------------------------------------------------------------------------------
|
22 |
|
|
# CLASS PROFILER
|
23 |
|
|
#------------------------------------------------------------------------------------------------------
|
24 |
|
|
class Profiler(object):
|
25 |
|
|
def __init__(self):
|
26 |
|
|
self.steps = 0
|
27 |
|
|
|
28 |
|
|
self.load = 0
|
29 |
|
|
self.store = 0
|
30 |
|
|
self.jumpbranch = 0
|
31 |
|
|
self.flag = 0
|
32 |
|
|
self.alu = 0
|
33 |
|
|
self.movmova = 0
|
34 |
|
|
|
35 |
|
|
self.vload = 0
|
36 |
|
|
self.vstore = 0
|
37 |
|
|
self.valu = 0
|
38 |
|
|
self.vmov = 0
|
39 |
|
|
self.shuffle = 0
|
40 |
|
|
|
41 |
|
|
self.scalar = 0
|
42 |
|
|
self.vector = 0
|
43 |
|
|
self.coopsimul = 0
|
44 |
|
|
|
45 |
|
|
def add(self, irval):
|
46 |
|
|
if irval == None:
|
47 |
|
|
return
|
48 |
|
|
|
49 |
|
|
self.steps = self.steps +1
|
50 |
|
|
|
51 |
|
|
s = False
|
52 |
|
|
v = False
|
53 |
|
|
|
54 |
|
|
#scalar cmd
|
55 |
|
|
if (irval & string.atoi("11100000000000000000000000000000",2)) != 0:
|
56 |
|
|
s = True
|
57 |
|
|
|
58 |
|
|
#vector cmd
|
59 |
|
|
if (irval & string.atoi("00000000000011100000000000000000",2)) != 0:
|
60 |
|
|
v = True
|
61 |
|
|
|
62 |
|
|
if s == True and v == True:
|
63 |
|
|
self.coopsimul = self.coopsimul + 1
|
64 |
|
|
else:
|
65 |
|
|
if s == True:
|
66 |
|
|
self.scalar = self.scalar + 1
|
67 |
|
|
if v == True:
|
68 |
|
|
self.vector = self.vector + 1
|
69 |
|
|
|
70 |
|
|
#alu cmd
|
71 |
|
|
if (irval & string.atoi("11000000000000000000000000000000",2))\
|
72 |
|
|
== string.atoi("01000000000000000000000000000000",2):
|
73 |
|
|
self.alu = self.alu +1
|
74 |
|
|
|
75 |
|
|
#jmp/jcc cmd
|
76 |
|
|
if (irval & string.atoi("11100000000000000000000000000000",2))\
|
77 |
|
|
== string.atoi("00100000000000000000000000000000",2):
|
78 |
|
|
self.jumpbranch = self.jumpbranch +1
|
79 |
|
|
|
80 |
|
|
#flag
|
81 |
|
|
if (irval & string.atoi("11000000000000000000000000000000",2))\
|
82 |
|
|
== string.atoi("11000000000000000000000000000000",2):
|
83 |
|
|
self.flag = self.flag +1
|
84 |
|
|
|
85 |
|
|
#load
|
86 |
|
|
if (irval & string.atoi("11110000000000000000000000000000",2))\
|
87 |
|
|
== string.atoi("10000000000000000000000000000000",2):
|
88 |
|
|
self.load = self.load +1
|
89 |
|
|
|
90 |
|
|
#store
|
91 |
|
|
if (irval & string.atoi("11110000000000000000000000000000",2))\
|
92 |
|
|
== string.atoi("10100000000000000000000000000000",2):
|
93 |
|
|
self.store = self.store +1
|
94 |
|
|
|
95 |
|
|
#vload
|
96 |
|
|
if (irval & string.atoi("11110000000000000000000000000000",2))\
|
97 |
|
|
== string.atoi("10010000000000000000000000000000",2):
|
98 |
|
|
self.vload = self.vload +1
|
99 |
|
|
|
100 |
|
|
#vstore
|
101 |
|
|
if (irval & string.atoi("11111100000000000000000000000000",2))\
|
102 |
|
|
== string.atoi("10110000000000000000000000000000",2):
|
103 |
|
|
self.vstore = self.vstore +1
|
104 |
|
|
|
105 |
|
|
#mov
|
106 |
|
|
if (irval & string.atoi("11111000000000000000000000000000",2))\
|
107 |
|
|
== string.atoi("10111000000000000000000000000000",2):
|
108 |
|
|
self.movmova = self.movmova +1
|
109 |
|
|
|
110 |
|
|
#mova
|
111 |
|
|
if (irval & string.atoi("11111100000000000000000000000000",2))\
|
112 |
|
|
== string.atoi("10110100000000000000000000000000",2):
|
113 |
|
|
self.movmova = self.movmova +1
|
114 |
|
|
|
115 |
|
|
#valu
|
116 |
|
|
if (irval & string.atoi("00000000000011000000000000000000",2))\
|
117 |
|
|
== string.atoi("00000000000001000000000000000000",2):
|
118 |
|
|
self.valu = self.valu +1
|
119 |
|
|
|
120 |
|
|
#vmov
|
121 |
|
|
if (irval & string.atoi("00000000000011100000000000000000",2))\
|
122 |
|
|
== string.atoi("00000000000000100000000000000000",2):
|
123 |
|
|
self.vmov = self.vmov +1
|
124 |
|
|
|
125 |
|
|
#vshuf
|
126 |
|
|
if (irval & string.atoi("00000000000011000000000000000000",2))\
|
127 |
|
|
== string.atoi("00000000000011000000000000000000",2):
|
128 |
|
|
self.shuffle = self.shuffle +1
|
129 |
|
|
|
130 |
|
|
|
131 |
|
|
|
132 |
|
|
def printanalysis(self):
|
133 |
|
|
if self.steps == 0:
|
134 |
|
|
print "No commands since reset"
|
135 |
|
|
return
|
136 |
|
|
|
137 |
|
|
print "Analysis of " + str(self.steps) + " commands is:"
|
138 |
|
|
print " " + "jumps / branches :".ljust(30," ") + str(self.jumpbranch).ljust(10," ") + self.toString(self.jumpbranch)
|
139 |
|
|
print " " + "flag modifications :".ljust(30," ") + str(self.flag).ljust(10," ") + self.toString(self.flag)
|
140 |
|
|
print " " + "scalar load :".ljust(30," ") + str(self.load).ljust(10," ") + self.toString(self.load)
|
141 |
|
|
print " " + "scalar store :".ljust(30," ") + str(self.store).ljust(10," ") + self.toString(self.store)
|
142 |
|
|
print " " + "vector load :".ljust(30," ") + str(self.vload).ljust(10," ")+ self.toString(self.vload)
|
143 |
|
|
print " " + "vector store :".ljust(30," ") + str(self.vstore).ljust(10," ")+ self.toString(self.vstore)
|
144 |
|
|
print " " + "scalar alu :".ljust(30," ") + str(self.alu).ljust(10," ")+ self.toString(self.alu)
|
145 |
|
|
print " " + "vector alu :".ljust(30," ") + str(self.valu).ljust(10," ")+ self.toString(self.valu)
|
146 |
|
|
print " " + "mov / mova :".ljust(30," ") + str(self.movmova).ljust(10," ")+ self.toString(self.movmova)
|
147 |
|
|
print " " + "vmov / vmol / vmor :".ljust(30," ") + str(self.vmov).ljust(10," ")+ self.toString(self.vmov)
|
148 |
|
|
print " " + "shuffle :".ljust(30," ") + str(self.shuffle).ljust(10," ")+ self.toString(self.shuffle)
|
149 |
|
|
print " " + "scalar commands :".ljust(30," ") + str(self.scalar).ljust(10," ")+ self.toString(self.scalar)
|
150 |
|
|
print " " + "vector commands :".ljust(30," ") + str(self.vector).ljust(10," ")+ self.toString(self.vector)
|
151 |
|
|
print " " + "cooperative / simultaneous :".ljust(30," ") + str(self.coopsimul).ljust(10," ")+ self.toString(self.coopsimul)
|
152 |
|
|
|
153 |
|
|
def toString(self, cmd):
|
154 |
|
|
val = float(cmd) * 100.0 / float(self.steps)
|
155 |
|
|
string = ("%.2f" % (val)).rjust(5," ") + " %"
|
156 |
|
|
return string
|
157 |
|
|
|
158 |
|
|
#------------------------------------------------------------------------------------------------------
|
159 |
|
|
# CLASS DEBUGGER
|
160 |
|
|
#------------------------------------------------------------------------------------------------------
|
161 |
|
|
class Debugger(object):
|
162 |
|
|
stack = Stack()
|
163 |
|
|
profiler = Profiler()
|
164 |
|
|
profiling = True
|
165 |
|
|
|
166 |
|
|
def __init__(self, args):
|
167 |
|
|
if len(args) > 3 or len(args) < 2:
|
168 |
|
|
print
|
169 |
|
|
print "usage: python clvpdbg.py portnumber [symboltablefilename]"
|
170 |
|
|
print
|
171 |
|
|
sys.exit(1)
|
172 |
|
|
|
173 |
|
|
if len(args) == 3:
|
174 |
|
|
symbols = self.getSymbols(args[2])
|
175 |
|
|
else:
|
176 |
|
|
symbols = None
|
177 |
|
|
|
178 |
|
|
self.shell(args[1], symbols)
|
179 |
|
|
|
180 |
|
|
def getSymbols(self, filename):
|
181 |
|
|
try:
|
182 |
|
|
file = open (filename,"r")
|
183 |
|
|
|
184 |
|
|
symbols = {}
|
185 |
|
|
|
186 |
|
|
for s in file.readlines():
|
187 |
|
|
x=s.replace("\n","")
|
188 |
|
|
symbols[x.split(":")[1].upper()] = string.atoi(x.split(":")[0])
|
189 |
|
|
|
190 |
|
|
return symbols
|
191 |
|
|
|
192 |
|
|
except IOError:
|
193 |
|
|
print
|
194 |
|
|
print "error: unable to open symboltable file: " + filename
|
195 |
|
|
sys.exit(1)
|
196 |
|
|
|
197 |
|
|
def tointeger(self,s):
|
198 |
|
|
if s[0] == "$":
|
199 |
|
|
return string.atoi(s[1:], base = 16)
|
200 |
|
|
|
201 |
|
|
if s[0] == "%":
|
202 |
|
|
return string.atoi(s[1:], base = 2)
|
203 |
|
|
|
204 |
|
|
return string.atoi(s)
|
205 |
|
|
|
206 |
|
|
def shell(self, portnr, symbols):
|
207 |
|
|
|
208 |
|
|
try:
|
209 |
|
|
self.ser = ser = serial.Serial(string.atoi(portnr), 38400, 8, serial.PARITY_NONE, serial.STOPBITS_ONE, Settings().getTimeout(), 0, 0)
|
210 |
|
|
except serial.SerialException:
|
211 |
|
|
print
|
212 |
|
|
print "An error occured while trying to open the serial port"
|
213 |
|
|
sys.exit(1)
|
214 |
|
|
|
215 |
|
|
print "\nWelcome to the CLVP Debugger !!!\n\nEnter 'help' for a list of commands"
|
216 |
|
|
print
|
217 |
|
|
|
218 |
|
|
self.echo(True)
|
219 |
|
|
|
220 |
|
|
print
|
221 |
|
|
|
222 |
|
|
while(1):
|
223 |
|
|
sys.stdout.write("#")
|
224 |
|
|
line=sys.stdin.readline().upper()
|
225 |
|
|
if line.strip() != "":
|
226 |
|
|
|
227 |
|
|
try:
|
228 |
|
|
cmd = LineParser().parseLine(line)
|
229 |
|
|
|
230 |
|
|
if cmd.command == "QUIT" or cmd.command == "EXIT" or cmd.command == "Q":
|
231 |
|
|
sys.exit(0)
|
232 |
|
|
|
233 |
|
|
elif cmd.command == "HELP":
|
234 |
|
|
length = 23
|
235 |
|
|
print "The following commands are availiable:"
|
236 |
|
|
print " " + "C / CLOCK".ljust(length," ") + "-- generate one clock signal for cpu"
|
237 |
|
|
print " " + "R / RESET".ljust(length," ") + "-- reset cpu and trace stats"
|
238 |
|
|
print " " + "S / STEP [NUMBER]".ljust(length," ") + "-- execute NUMBER instructions"
|
239 |
|
|
print " " + "JUMP ADDRESS".ljust(length," ") + "-- execute until command at ADDRESS"
|
240 |
|
|
print " " + "M / DATA".ljust(length," ") + "-- display data of memory output"
|
241 |
|
|
print " " + "N / ADDR".ljust(length," ") + "-- display memory address line"
|
242 |
|
|
print " " + "A".ljust(length," ") + "-- display value of register A"
|
243 |
|
|
print " " + "X".ljust(length," ") + "-- display value of register X"
|
244 |
|
|
print " " + "Y".ljust(length," ") + "-- display value of register Y "
|
245 |
|
|
print " " + "I / IR".ljust(length," ") + "-- display value of instruction register "
|
246 |
|
|
print " " + "J / IC".ljust(length," ") + "-- display value of instruction counter "
|
247 |
|
|
print " " + "F / FLAGS".ljust(length," ") + "-- display value of various flags and signals"
|
248 |
|
|
print " " + "T / STATUS".ljust(length," ") + "-- display value of all registers"
|
249 |
|
|
print " " + "E / ECHO".ljust(length," ") + "-- test if device is responding"
|
250 |
|
|
print " " + "READ ADDRESS".ljust(length," ") + "-- read memory value at given ADDRESS"
|
251 |
|
|
print " " + "WRITE ADDRESS VALUE".ljust(length," ") + "-- write VALUE to given memory ADDRESS"
|
252 |
|
|
print " " + "DOWNLOAD ADDRESS COUNT".ljust(length," ") + "-- download data from memory into FILE"
|
253 |
|
|
print " " + "UPLOAD ADDRESS".ljust(length," ") + "-- upload data from FILE into memory"
|
254 |
|
|
print " " + "CCSTART ADDRESS".ljust(length," ") + "-- start counting clockticks to reach given ADDRESS"
|
255 |
|
|
print " " + "CCSTOP".ljust(length," ") + "-- aborts counting clockticks"
|
256 |
|
|
print " " + "CCSTATUS".ljust(length," ") + "-- displays clocktick counter status and value"
|
257 |
|
|
print " " + "TRACE [NUMBER]".ljust(length," ") + "-- display IC value of last NUMBER commands"
|
258 |
|
|
print " " + "PROFILE".ljust(length," ") + "-- show analysis of commands since reset"
|
259 |
|
|
print " " + "TOGGLEPROFILING".ljust(length," ") + "-- activate/deaktivate profiling"
|
260 |
|
|
print " " + "SYMBOLS".ljust(length," ") + "-- lists symbols imported from file"
|
261 |
|
|
print " " + "Q / QUIT / EXIT".ljust(length," ") + "-- exit debugger"
|
262 |
|
|
|
263 |
|
|
elif cmd.command == "SYMBOLS":
|
264 |
|
|
if symbols != None:
|
265 |
|
|
print "The following symbols are known:"
|
266 |
|
|
for k,v in sorted(symbols.iteritems()):
|
267 |
|
|
print " 0x" + str(hex(v))[2:].rjust(8,"0").upper() + " : " + k
|
268 |
|
|
else:
|
269 |
|
|
print "No symbol file given"
|
270 |
|
|
|
271 |
|
|
elif cmd.command == "CLOCK" or cmd.command == "C":
|
272 |
|
|
self.clock(True)
|
273 |
|
|
|
274 |
|
|
elif cmd.command == "RESET" or cmd.command == "R":
|
275 |
|
|
self.reset(True)
|
276 |
|
|
self.clock(False)
|
277 |
|
|
|
278 |
|
|
elif cmd.command == "A":
|
279 |
|
|
self.rega(True)
|
280 |
|
|
|
281 |
|
|
elif cmd.command == "X":
|
282 |
|
|
self.regx(True)
|
283 |
|
|
|
284 |
|
|
elif cmd.command == "Y":
|
285 |
|
|
self.regy(True)
|
286 |
|
|
|
287 |
|
|
elif cmd.command == "FLAGS" or cmd.command == "F":
|
288 |
|
|
self.flags(True)
|
289 |
|
|
|
290 |
|
|
elif cmd.command == "IR" or cmd.command == "I":
|
291 |
|
|
self.ir(True)
|
292 |
|
|
|
293 |
|
|
elif cmd.command == "IC" or cmd.command == "J":
|
294 |
|
|
self.ic(True)
|
295 |
|
|
|
296 |
|
|
elif cmd.command == "STEP" or cmd.command == "S":
|
297 |
|
|
if cmd.value != "":
|
298 |
|
|
self.step(self.tointeger(cmd.value), True, self.profiling)
|
299 |
|
|
else:
|
300 |
|
|
self.step(1, True)
|
301 |
|
|
|
302 |
|
|
elif cmd.command == "TRACE":
|
303 |
|
|
if cmd.value != "":
|
304 |
|
|
self.trace(self.tointeger(cmd.value))
|
305 |
|
|
else:
|
306 |
|
|
self.trace(10)
|
307 |
|
|
|
308 |
|
|
elif cmd.command == "PROFILE":
|
309 |
|
|
self.profiler.printanalysis();
|
310 |
|
|
|
311 |
|
|
elif cmd.command == "JUMP":
|
312 |
|
|
try:
|
313 |
|
|
if cmd.value:
|
314 |
|
|
address = self.tointeger(cmd.value)
|
315 |
|
|
else:
|
316 |
|
|
address = symbols[cmd.symbol]
|
317 |
|
|
|
318 |
|
|
self.jump(address, True, self.profiling)
|
319 |
|
|
|
320 |
|
|
except KeyError:
|
321 |
|
|
print "Symbol " + cmd.symbol + " is not known"
|
322 |
|
|
|
323 |
|
|
|
324 |
|
|
elif cmd.command == "WRITE":
|
325 |
|
|
try:
|
326 |
|
|
if cmd.newval_value:
|
327 |
|
|
newval = self.tointeger(cmd.newval_value)
|
328 |
|
|
else:
|
329 |
|
|
newval = symbols[cmd.newval_symbol]
|
330 |
|
|
|
331 |
|
|
try:
|
332 |
|
|
if cmd.value:
|
333 |
|
|
address = self.tointeger(cmd.value)
|
334 |
|
|
else:
|
335 |
|
|
address = symbols[cmd.symbol]
|
336 |
|
|
|
337 |
|
|
self.write(address, newval, True)
|
338 |
|
|
|
339 |
|
|
except KeyError:
|
340 |
|
|
print "Symbol " + cmd.symbol + " is not known"
|
341 |
|
|
|
342 |
|
|
except KeyError:
|
343 |
|
|
print "Symbol " + cmd.newval_symbol + " is not known"
|
344 |
|
|
|
345 |
|
|
|
346 |
|
|
elif cmd.command == "READ":
|
347 |
|
|
try:
|
348 |
|
|
if cmd.value:
|
349 |
|
|
address = self.tointeger(cmd.value)
|
350 |
|
|
else:
|
351 |
|
|
address = symbols[cmd.symbol]
|
352 |
|
|
|
353 |
|
|
self.read(address, True)
|
354 |
|
|
|
355 |
|
|
except KeyError:
|
356 |
|
|
print "Symbol " + cmd.symbol + " is not known"
|
357 |
|
|
|
358 |
|
|
|
359 |
|
|
elif cmd.command == "DOWNLOAD":
|
360 |
|
|
try:
|
361 |
|
|
if cmd.value:
|
362 |
|
|
address = self.tointeger(cmd.value)
|
363 |
|
|
else:
|
364 |
|
|
address = symbols[cmd.symbol]
|
365 |
|
|
|
366 |
|
|
sys.stdout.write("Enter filename: ")
|
367 |
|
|
filename=sys.stdin.readline().lstrip().rstrip()
|
368 |
|
|
|
369 |
|
|
self.download(address, self.tointeger(cmd.count), filename, True)
|
370 |
|
|
|
371 |
|
|
except KeyError:
|
372 |
|
|
print "Symbol " + cmd.symbol + " is not known"
|
373 |
|
|
|
374 |
|
|
elif cmd.command == "UPLOAD":
|
375 |
|
|
try:
|
376 |
|
|
if cmd.value:
|
377 |
|
|
address = self.tointeger(cmd.value)
|
378 |
|
|
else:
|
379 |
|
|
address = symbols[cmd.symbol]
|
380 |
|
|
|
381 |
|
|
sys.stdout.write("Enter filename: ")
|
382 |
|
|
filename=sys.stdin.readline().lstrip().rstrip()
|
383 |
|
|
|
384 |
|
|
self.upload(address, filename, True)
|
385 |
|
|
|
386 |
|
|
except KeyError:
|
387 |
|
|
print "Symbol " + cmd.symbol + " is not known"
|
388 |
|
|
|
389 |
|
|
|
390 |
|
|
elif cmd.command == "CCSTART":
|
391 |
|
|
try:
|
392 |
|
|
if cmd.value:
|
393 |
|
|
address = self.tointeger(cmd.value)
|
394 |
|
|
else:
|
395 |
|
|
address = symbols[cmd.symbol]
|
396 |
|
|
|
397 |
|
|
self.ccstart(address, True)
|
398 |
|
|
|
399 |
|
|
except KeyError:
|
400 |
|
|
print "Symbol " + cmd.symbol + " is not known"
|
401 |
|
|
|
402 |
|
|
elif cmd.command == "CCSTOP":
|
403 |
|
|
self.ccstop(True)
|
404 |
|
|
|
405 |
|
|
elif cmd.command == "CCSTATUS":
|
406 |
|
|
self.ccstatus(True)
|
407 |
|
|
|
408 |
|
|
elif cmd.command == "DATA" or cmd.command == "M":
|
409 |
|
|
self.data(True)
|
410 |
|
|
|
411 |
|
|
elif cmd.command == "ADDR" or cmd.command == "N":
|
412 |
|
|
self.addr(True)
|
413 |
|
|
|
414 |
|
|
elif cmd.command == "STATUS" or cmd.command == "T":
|
415 |
|
|
self.status(True)
|
416 |
|
|
|
417 |
|
|
elif cmd.command == "ECHO" or cmd.command == "E":
|
418 |
|
|
self.echo(True)
|
419 |
|
|
|
420 |
|
|
elif cmd.command == "GO" or cmd.command == "G":
|
421 |
|
|
self.go(True)
|
422 |
|
|
|
423 |
|
|
elif cmd.command == "PAUSE" or cmd.command == "P":
|
424 |
|
|
self.pause(True)
|
425 |
|
|
|
426 |
|
|
elif cmd.command == "TOGGLEPROFILING":
|
427 |
|
|
self.toggleprofiling()
|
428 |
|
|
|
429 |
|
|
except ParseException, err:
|
430 |
|
|
print "Unknown command or incorrect parameters"
|
431 |
|
|
|
432 |
|
|
print
|
433 |
|
|
|
434 |
|
|
def ccstop(self, verbose = True):
|
435 |
|
|
self.ser.write("5")
|
436 |
|
|
if self.ser.read(1) != "5":
|
437 |
|
|
if verbose == True:
|
438 |
|
|
print "Stop clock counter was NOT successful"
|
439 |
|
|
return False
|
440 |
|
|
|
441 |
|
|
if verbose == True:
|
442 |
|
|
print "Clock counter has been stopped"
|
443 |
|
|
return True
|
444 |
|
|
|
445 |
|
|
def ccstart(self, address, verbose = True):
|
446 |
|
|
if self.pause(False) == False:
|
447 |
|
|
if verbose == True:
|
448 |
|
|
print "Enter debugging-mode signal NOT accepted"
|
449 |
|
|
return False
|
450 |
|
|
|
451 |
|
|
if self.put("0", address, 0) == False:
|
452 |
|
|
if verbose == True:
|
453 |
|
|
print "Transmitting address was NOT successful"
|
454 |
|
|
return False
|
455 |
|
|
|
456 |
|
|
self.ser.write("4")
|
457 |
|
|
if self.ser.read(1) != "4":
|
458 |
|
|
if verbose == True:
|
459 |
|
|
print "Start clock counter was NOT successful"
|
460 |
|
|
return False
|
461 |
|
|
|
462 |
|
|
if verbose == True:
|
463 |
|
|
print "Clock counter has been started"
|
464 |
|
|
return True
|
465 |
|
|
|
466 |
|
|
def ccstatus(self, verbose = True):
|
467 |
|
|
self.ser.write("6")
|
468 |
|
|
status = self.ser.read(1)
|
469 |
|
|
|
470 |
|
|
if status != "":
|
471 |
|
|
if ord(status) == 1:
|
472 |
|
|
if verbose == True:
|
473 |
|
|
print "Counting clock cycles is finished"
|
474 |
|
|
else:
|
475 |
|
|
if verbose == True:
|
476 |
|
|
print "Counting clock cycles is NOT finished, yet"
|
477 |
|
|
else:
|
478 |
|
|
if verbose == True:
|
479 |
|
|
print "Request to get status was NOT successful"
|
480 |
|
|
return None
|
481 |
|
|
|
482 |
|
|
return self.get32BitReg("Clock cycles","7", verbose)
|
483 |
|
|
|
484 |
|
|
|
485 |
|
|
def toggleprofiling(self):
|
486 |
|
|
if self.profiling == False:
|
487 |
|
|
self.profiling = True
|
488 |
|
|
print "Profiling now ON"
|
489 |
|
|
else:
|
490 |
|
|
self.profiling = False
|
491 |
|
|
print "Profiling now OFF"
|
492 |
|
|
|
493 |
|
|
def upload(self, address, filename, verbose = True):
|
494 |
|
|
try:
|
495 |
|
|
f=open(filename,"rb")
|
496 |
|
|
|
497 |
|
|
i = 0
|
498 |
|
|
|
499 |
|
|
while f:
|
500 |
|
|
x3 = f.read(1)
|
501 |
|
|
x2 = f.read(1)
|
502 |
|
|
x1 = f.read(1)
|
503 |
|
|
x0 = f.read(1)
|
504 |
|
|
|
505 |
|
|
if x0 == "" or x1 == "" or x2 == "" or x3 == "":
|
506 |
|
|
f.close()
|
507 |
|
|
print "File has been uploaded"
|
508 |
|
|
return True
|
509 |
|
|
|
510 |
|
|
value = ord(x0) + ord(x1) * 256 + ord(x2) * 256 * 256 + ord(x3) * 256 * 256 * 256
|
511 |
|
|
|
512 |
|
|
trys = 0
|
513 |
|
|
done = False
|
514 |
|
|
s = Settings()
|
515 |
|
|
|
516 |
|
|
while trys < s.getRetrys() and done == False:
|
517 |
|
|
if self.write(address + i, value, False) == False:
|
518 |
|
|
trys = trys +1
|
519 |
|
|
else:
|
520 |
|
|
done = True
|
521 |
|
|
|
522 |
|
|
if done == False:
|
523 |
|
|
if verbose == True:
|
524 |
|
|
print "File has NOT been uploaded"
|
525 |
|
|
return False
|
526 |
|
|
|
527 |
|
|
i=i+1
|
528 |
|
|
|
529 |
|
|
except IOError:
|
530 |
|
|
print "File IO-error occured"
|
531 |
|
|
|
532 |
|
|
def download(self, address, count, filename, verbose = True):
|
533 |
|
|
try:
|
534 |
|
|
f=open(filename,"wb")
|
535 |
|
|
|
536 |
|
|
for i in range(count):
|
537 |
|
|
value = self.read(address + i, False)
|
538 |
|
|
|
539 |
|
|
if value == None:
|
540 |
|
|
if verbose == True:
|
541 |
|
|
print "Download was NOT successful"
|
542 |
|
|
return False
|
543 |
|
|
|
544 |
|
|
m = string.atoi("11111111000000000000000000000000",2)
|
545 |
|
|
for j in range(4):
|
546 |
|
|
a = (value & m) >> 8 * (3-j)
|
547 |
|
|
m = m >> 8
|
548 |
|
|
f.write(chr(a))
|
549 |
|
|
|
550 |
|
|
f.close()
|
551 |
|
|
print "Download into file " + filename + " was successful"
|
552 |
|
|
|
553 |
|
|
except IOError:
|
554 |
|
|
print "Unable to write file: " + filename
|
555 |
|
|
|
556 |
|
|
def read(self, address, verbose = True):
|
557 |
|
|
if self.put("0", address, 0) == False:
|
558 |
|
|
if verbose == True:
|
559 |
|
|
print "Transmitting address was NOT successful"
|
560 |
|
|
return None
|
561 |
|
|
|
562 |
|
|
return self.get32BitReg("value","2", verbose)
|
563 |
|
|
|
564 |
|
|
def write(self, address, value, verbose = True):
|
565 |
|
|
if self.put("0", address, 0) == False:
|
566 |
|
|
if verbose == True:
|
567 |
|
|
print "Transmitting address was NOT successful"
|
568 |
|
|
return False
|
569 |
|
|
|
570 |
|
|
if self.put("1", value, 0) == False:
|
571 |
|
|
if verbose == True:
|
572 |
|
|
print "Transmitting data was NOT successful"
|
573 |
|
|
return False
|
574 |
|
|
|
575 |
|
|
self.ser.write("3")
|
576 |
|
|
if self.ser.read(1) != "3":
|
577 |
|
|
if verbose == True:
|
578 |
|
|
print "Write was NOT successful"
|
579 |
|
|
return False
|
580 |
|
|
|
581 |
|
|
else:
|
582 |
|
|
if verbose == True:
|
583 |
|
|
print "Data has been written"
|
584 |
|
|
return True
|
585 |
|
|
|
586 |
|
|
def put(self, command, value, trys):
|
587 |
|
|
err = False
|
588 |
|
|
m = string.atoi("11111111000000000000000000000000",2)
|
589 |
|
|
|
590 |
|
|
self.ser.write(command)
|
591 |
|
|
if self.ser.read(1) != command:
|
592 |
|
|
return False
|
593 |
|
|
|
594 |
|
|
for i in range(4):
|
595 |
|
|
a = (value & m) >> 8 * (3-i)
|
596 |
|
|
m = m >> 8
|
597 |
|
|
self.ser.write(chr(a))
|
598 |
|
|
if ord(self.ser.read(1)) != a:
|
599 |
|
|
err = True
|
600 |
|
|
|
601 |
|
|
if err == True:
|
602 |
|
|
s= Settings()
|
603 |
|
|
if trys == s.getRetrys():
|
604 |
|
|
return False
|
605 |
|
|
return self.put(command, value, trys +1)
|
606 |
|
|
else:
|
607 |
|
|
return True
|
608 |
|
|
|
609 |
|
|
|
610 |
|
|
|
611 |
|
|
|
612 |
|
|
def echo(self, verbose = True):
|
613 |
|
|
self.ser.write("e")
|
614 |
|
|
if self.ser.read(1) == "e":
|
615 |
|
|
if verbose == True:
|
616 |
|
|
print "Device is responding"
|
617 |
|
|
return True
|
618 |
|
|
else:
|
619 |
|
|
if verbose == True:
|
620 |
|
|
print "Device is NOT responding"
|
621 |
|
|
return False
|
622 |
|
|
|
623 |
|
|
def go(self, verbose = True):
|
624 |
|
|
self.ser.write("g")
|
625 |
|
|
if self.ser.read(1) == "g":
|
626 |
|
|
if verbose == True:
|
627 |
|
|
print "System now in free-running-mode"
|
628 |
|
|
return True
|
629 |
|
|
else:
|
630 |
|
|
if verbose == True:
|
631 |
|
|
print "Enter free-running-mode signal NOT accepted"
|
632 |
|
|
return False
|
633 |
|
|
|
634 |
|
|
def pause(self, verbose = True):
|
635 |
|
|
self.ser.write("p")
|
636 |
|
|
if self.ser.read(1) == "p":
|
637 |
|
|
if verbose == True:
|
638 |
|
|
print "System now in debugging-mode"
|
639 |
|
|
return True
|
640 |
|
|
else:
|
641 |
|
|
if verbose == True:
|
642 |
|
|
print "Enter debugging-mode signal NOT accepted"
|
643 |
|
|
return False
|
644 |
|
|
|
645 |
|
|
def clock(self, verbose = True):
|
646 |
|
|
self.ser.write("c")
|
647 |
|
|
clock = self.ser.read(1)
|
648 |
|
|
|
649 |
|
|
try:
|
650 |
|
|
if ord(clock) == 255: #workaround for belkin usb-to-serial-adapter problems ...
|
651 |
|
|
return self.clock (verbose)
|
652 |
|
|
|
653 |
|
|
except TypeError:
|
654 |
|
|
if verbose == True:
|
655 |
|
|
print "Clock signal NOT accepted"
|
656 |
|
|
return False
|
657 |
|
|
|
658 |
|
|
if clock == "c":
|
659 |
|
|
if verbose == True:
|
660 |
|
|
print "Clock signal accepted"
|
661 |
|
|
return True
|
662 |
|
|
else:
|
663 |
|
|
if verbose == True:
|
664 |
|
|
print "Clock signal NOT accepted"
|
665 |
|
|
return False
|
666 |
|
|
|
667 |
|
|
def reset(self, verbose = True):
|
668 |
|
|
|
669 |
|
|
self.ser.write("r")
|
670 |
|
|
if self.ser.read(1) == "r":
|
671 |
|
|
self.stack = Stack();
|
672 |
|
|
self.profiler = Profiler()
|
673 |
|
|
if verbose == True:
|
674 |
|
|
print "Reset signal (CPU, trace, profiler) accepted"
|
675 |
|
|
return True
|
676 |
|
|
else:
|
677 |
|
|
if verbose == True:
|
678 |
|
|
print "Reset signal NOT accepted"
|
679 |
|
|
return False
|
680 |
|
|
|
681 |
|
|
def rega(self, verbose = True):
|
682 |
|
|
return self.get32BitReg("register a","a", verbose)
|
683 |
|
|
|
684 |
|
|
def regx(self, verbose = True):
|
685 |
|
|
return self.get32BitReg("register x","x", verbose)
|
686 |
|
|
|
687 |
|
|
def regy(self, verbose = True):
|
688 |
|
|
return self.get32BitReg("register y","y", verbose)
|
689 |
|
|
|
690 |
|
|
def ic(self, verbose = True):
|
691 |
|
|
return self.get32BitReg("instruction counter","j", verbose)
|
692 |
|
|
|
693 |
|
|
def ir(self, verbose = True):
|
694 |
|
|
return self.get32BitReg("instruction register","i", verbose)
|
695 |
|
|
|
696 |
|
|
def data(self, verbose = True):
|
697 |
|
|
return self.get32BitReg("memory output data","m", verbose)
|
698 |
|
|
|
699 |
|
|
def addr(self, verbose = True):
|
700 |
|
|
return self.get32BitReg("memory address signal","n", verbose)
|
701 |
|
|
|
702 |
|
|
def status(self, verbose = True):
|
703 |
|
|
return self.data(verbose), self.addr(verbose), self.ir(verbose), self.ic(verbose), self.rega(verbose),\
|
704 |
|
|
self.regx(verbose), self.regy(verbose), self.flags(verbose), \
|
705 |
|
|
|
706 |
|
|
def get32BitReg(self, name, command, verbose = True):
|
707 |
|
|
errors = 0
|
708 |
|
|
success = 0
|
709 |
|
|
|
710 |
|
|
while not success and errors < Settings().getRetrys():
|
711 |
|
|
self.ser.write(command)
|
712 |
|
|
x0=self.ser.read(1)
|
713 |
|
|
x1=self.ser.read(1)
|
714 |
|
|
x2=self.ser.read(1)
|
715 |
|
|
x3=self.ser.read(1)
|
716 |
|
|
checksum = self.ser.read(1)
|
717 |
|
|
|
718 |
|
|
if x0 == "" or x1 == "" or x2 == "" or x3 == "" or checksum == "":
|
719 |
|
|
errors = errors + 1
|
720 |
|
|
else:
|
721 |
|
|
if ord(checksum) != ord(x0) ^ ord(x1) ^ ord(x2) ^ ord(x3):
|
722 |
|
|
errors = errors +1
|
723 |
|
|
else:
|
724 |
|
|
success = 1
|
725 |
|
|
|
726 |
|
|
if success:
|
727 |
|
|
x = ord(x0) + 256 * ord(x1) + 256 * 256 * ord(x2) + 256 * 256 * 256 * ord(x3)
|
728 |
|
|
|
729 |
|
|
if verbose == True:
|
730 |
|
|
print name + ": 0x" + hex(ord(x3))[2:].rjust(2,"0").upper() + hex(ord(x2))[2:].rjust(2,"0").upper() \
|
731 |
|
|
+ hex(ord(x1))[2:].rjust(2,"0").upper() + hex(ord(x0))[2:].rjust(2,"0").upper()
|
732 |
|
|
return x
|
733 |
|
|
else:
|
734 |
|
|
print "request to get " + name + " was NOT successful"
|
735 |
|
|
return None
|
736 |
|
|
|
737 |
|
|
def flags(self, verbose = True):
|
738 |
|
|
self.ser.write("f")
|
739 |
|
|
flags = self.ser.read(1)
|
740 |
|
|
|
741 |
|
|
if flags != "":
|
742 |
|
|
ir_ready = int((ord(flags) & string.atoi("10000000",2)) > 0)
|
743 |
|
|
mem_ready = int((ord(flags) & string.atoi("01000000",2)) > 0)
|
744 |
|
|
mem_access = (ord(flags) & string.atoi("00111000",2)) >> 3
|
745 |
|
|
mem_access_0 = int((mem_access & 1) > 0)
|
746 |
|
|
mem_access_1 = int((mem_access & 2) > 0)
|
747 |
|
|
mem_access_2 = int((mem_access & 4) > 0)
|
748 |
|
|
halted = int((ord(flags) & string.atoi("00000100",2)) > 0)
|
749 |
|
|
zero = int((ord(flags) & string.atoi("00000010",2)) > 0)
|
750 |
|
|
carry = int((ord(flags) & string.atoi("00000001",2)) > 0)
|
751 |
|
|
|
752 |
|
|
if verbose == True:
|
753 |
|
|
print "ir_ready: " + str(ir_ready)
|
754 |
|
|
print "mem_ready: " + str(mem_ready)
|
755 |
|
|
print "mem_access: " + str(mem_access_2) + str(mem_access_1) + str(mem_access_0)
|
756 |
|
|
print "halted: " + str(halted)
|
757 |
|
|
print "zero: " + str(zero)
|
758 |
|
|
print "carry: " + str(carry)
|
759 |
|
|
|
760 |
|
|
return ir_ready, mem_ready, mem_access, halted, zero, carry
|
761 |
|
|
else:
|
762 |
|
|
print "Request to get flags was NOT successful"
|
763 |
|
|
return None
|
764 |
|
|
|
765 |
|
|
def step(self, steps, verbose = True, profile = True):
|
766 |
|
|
|
767 |
|
|
ticks = 0
|
768 |
|
|
ic = None
|
769 |
|
|
|
770 |
|
|
for i in range(steps):
|
771 |
|
|
ir_ready = 0
|
772 |
|
|
clocks = 0
|
773 |
|
|
|
774 |
|
|
while(ir_ready == 0):
|
775 |
|
|
if self.clock(False) == False:
|
776 |
|
|
text = "Device is not responding (Clock)"
|
777 |
|
|
if verbose == True:
|
778 |
|
|
print text
|
779 |
|
|
return 0, text, None
|
780 |
|
|
|
781 |
|
|
flags = self.flags(False)
|
782 |
|
|
if flags == None:
|
783 |
|
|
text = "Device is not responding (Flags)"
|
784 |
|
|
if verbose == True:
|
785 |
|
|
print text
|
786 |
|
|
return 0, text, None
|
787 |
|
|
else:
|
788 |
|
|
ir_ready, mem_ready, mem_access, halted, zero, carry = flags
|
789 |
|
|
|
790 |
|
|
clocks = clocks + 1
|
791 |
|
|
|
792 |
|
|
if clocks > Settings().getMaxClocks():
|
793 |
|
|
text = "Exceeded limit of " + str(Settings().getMaxClocks()) + " clock ticks for one command, aborting"
|
794 |
|
|
if verbose == True:
|
795 |
|
|
print text
|
796 |
|
|
return 0, text, None
|
797 |
|
|
|
798 |
|
|
ticks = ticks + clocks
|
799 |
|
|
ic = self.ic(False)
|
800 |
|
|
|
801 |
|
|
if profile == True:
|
802 |
|
|
self.profiler.add(self.ir(False))
|
803 |
|
|
|
804 |
|
|
if self.clock(False) == False:
|
805 |
|
|
text = "Device is not responding (Clock)"
|
806 |
|
|
if verbose == True:
|
807 |
|
|
print text
|
808 |
|
|
return 0, text, None
|
809 |
|
|
|
810 |
|
|
ticks = ticks + 1
|
811 |
|
|
self.stack.push(ic)
|
812 |
|
|
|
813 |
|
|
text = "Stepping "+ str(steps) +" command(s) successfull" + "\n" + "Required "+ str(ticks) + " clock ticks"
|
814 |
|
|
if verbose == True:
|
815 |
|
|
print text
|
816 |
|
|
return ticks, text, ic
|
817 |
|
|
|
818 |
|
|
def jump(self, address, verbose = True, profile = True):
|
819 |
|
|
|
820 |
|
|
ic = 0
|
821 |
|
|
steps = 0
|
822 |
|
|
ticks = 0
|
823 |
|
|
|
824 |
|
|
while(ic != address):
|
825 |
|
|
steps = steps +1
|
826 |
|
|
|
827 |
|
|
clocks, text, ic = self.step(1, False, profile)
|
828 |
|
|
if clocks == 0:
|
829 |
|
|
if verbose == True:
|
830 |
|
|
print "Step " + str(steps) + " was NOT successful"
|
831 |
|
|
print text
|
832 |
|
|
return 0
|
833 |
|
|
|
834 |
|
|
if ic == None:
|
835 |
|
|
if verbose == True:
|
836 |
|
|
print "Device is NOT responding (IC)"
|
837 |
|
|
return 0
|
838 |
|
|
|
839 |
|
|
if steps > Settings().getMaxSteps():
|
840 |
|
|
if verbose == True:
|
841 |
|
|
print "Exceeded limit of " + str(Settings().getMaxSteps()) + " steps, aborting"
|
842 |
|
|
return 0
|
843 |
|
|
|
844 |
|
|
ticks = ticks + clocks
|
845 |
|
|
|
846 |
|
|
if verbose == True:
|
847 |
|
|
print "Instruction counter value after " + str(steps) + " commands reached"
|
848 |
|
|
print "Required " + str(ticks) + " clock ticks"
|
849 |
|
|
return ticks
|
850 |
|
|
|
851 |
|
|
def trace(self,n):
|
852 |
|
|
print "trace of the last " + str(n) +" instruction counter values: "
|
853 |
|
|
|
854 |
|
|
import copy
|
855 |
|
|
newstack = copy.deepcopy(self.stack)
|
856 |
|
|
|
857 |
|
|
val = newstack.pop()
|
858 |
|
|
|
859 |
|
|
x = 0
|
860 |
|
|
|
861 |
|
|
while( val != None and x < n ):
|
862 |
|
|
print "0x" + hex(val)[2:].rjust(8,"0").upper()
|
863 |
|
|
val = newstack.pop()
|
864 |
|
|
x = x + 1
|
865 |
|
|
|
866 |
|
|
#------------------------------------------------------------------------------------------------------
|
867 |
|
|
# CLASS LINEPARSER
|
868 |
|
|
#------------------------------------------------------------------------------------------------------
|
869 |
|
|
class LineParser:
|
870 |
|
|
def parseLine(self,line):
|
871 |
|
|
|
872 |
|
|
expression = Forward()
|
873 |
|
|
|
874 |
|
|
dec_value = Word("0123456789", min=1)
|
875 |
|
|
hex_value = Word("$","ABCDEF0123456789", min=2)
|
876 |
|
|
bin_value = Word("%","10", min=2)
|
877 |
|
|
|
878 |
|
|
value = (dec_value ^ hex_value ^ bin_value).setResultsName("value")
|
879 |
|
|
ident = Word( alphas, alphanums + "_" ).setResultsName("symbol")
|
880 |
|
|
|
881 |
|
|
address = (value ^ ident).setResultsName("address")
|
882 |
|
|
|
883 |
|
|
newval_value = (dec_value ^ hex_value ^ bin_value).setResultsName("newval_value")
|
884 |
|
|
newval_ident = Word( alphas, alphanums + "_" ).setResultsName("newval_symbol")
|
885 |
|
|
newval_address = (newval_value ^ newval_ident).setResultsName("newval_address")
|
886 |
|
|
|
887 |
|
|
count = (dec_value ^ hex_value ^ bin_value).setResultsName("count")
|
888 |
|
|
|
889 |
|
|
cmd_1 = ( Keyword("C") ^ Keyword("CLOCK") ^ Keyword("RESET")^ Keyword("R") ^ Keyword("A") ^ Keyword("X") ^ Keyword("Y") \
|
890 |
|
|
^ Keyword("FLAGS") ^ Keyword("F") ^ Keyword("IR") ^ Keyword("IC") ^ Keyword("ECHO") ^ Keyword("QUIT") \
|
891 |
|
|
^ Keyword("Q") ^ Keyword("STATUS") ^ Keyword("E") ^ Keyword("HELP") ^ Keyword("EXIT") ^ Keyword("I") \
|
892 |
|
|
^ Keyword("J") ^ Keyword("T") ^ Keyword("M") ^Keyword("N") ^ Keyword("ADDR") ^ Keyword("DATA") \
|
893 |
|
|
^ Keyword("GO") ^ Keyword("PAUSE") ^ Keyword("G") ^ Keyword("P") ^ Keyword("SYMBOLS") ^ Keyword("PROFILE")
|
894 |
|
|
^ Keyword("TOGGLEPROFILING")).setResultsName("command")
|
895 |
|
|
|
896 |
|
|
cmd_2 = ((Keyword("STEP") ^ Keyword("S")).setResultsName("command")) ^ ((Keyword("STEP") ^ Keyword("S")).setResultsName("command") + value)
|
897 |
|
|
|
898 |
|
|
cmd_3 = Keyword("JUMP").setResultsName("command") + address
|
899 |
|
|
|
900 |
|
|
cmd_4 = ((Keyword("TRACE")).setResultsName("command")) ^ ((Keyword("TRACE")).setResultsName("command") + value)
|
901 |
|
|
|
902 |
|
|
cmd_5 = (Keyword("WRITE")).setResultsName("command") + address + newval_address
|
903 |
|
|
|
904 |
|
|
cmd_6 = (Keyword("READ")).setResultsName("command") + address
|
905 |
|
|
|
906 |
|
|
cmd_7 = (Keyword("UPLOAD")).setResultsName("command") + address
|
907 |
|
|
|
908 |
|
|
cmd_8 = (Keyword("DOWNLOAD")).setResultsName("command") + address + count
|
909 |
|
|
|
910 |
|
|
cmd_9 = (Keyword("CCSTART")).setResultsName("command") + address
|
911 |
|
|
|
912 |
|
|
cmd_10 = (Keyword("CCSTOP")).setResultsName("command")
|
913 |
|
|
|
914 |
|
|
cmd_11 = (Keyword("CCSTATUS")).setResultsName("command")
|
915 |
|
|
|
916 |
|
|
command = (cmd_1 ^ cmd_2 ^ cmd_3 ^ cmd_4 ^ cmd_5 ^ cmd_6 ^ cmd_7 ^ cmd_8 ^ cmd_9 ^ cmd_10 ^ cmd_11)
|
917 |
|
|
|
918 |
|
|
expression << command + lineEnd
|
919 |
|
|
|
920 |
|
|
result = expression.parseString(line)
|
921 |
|
|
|
922 |
|
|
return result
|
923 |
|
|
|
924 |
|
|
#------------------------------------------------------------------------------------------------------
|
925 |
|
|
# CLASS SETTINGS
|
926 |
|
|
#------------------------------------------------------------------------------------------------------
|
927 |
|
|
class Settings(object):
|
928 |
|
|
def getMaxClocks(self):
|
929 |
|
|
return 100
|
930 |
|
|
|
931 |
|
|
def getMaxSteps(self):
|
932 |
|
|
return 50000
|
933 |
|
|
|
934 |
|
|
def getRetrys(self):
|
935 |
|
|
return 15
|
936 |
|
|
|
937 |
|
|
def getTimeout(self):
|
938 |
|
|
return 0.1
|
939 |
|
|
#------------------------------------------------------------------------------------------------------
|
940 |
|
|
# MAIN PROGRAM
|
941 |
|
|
#------------------------------------------------------------------------------------------------------
|
942 |
|
|
if __name__ == '__main__':
|
943 |
|
|
import sys
|
944 |
|
|
Debugger(sys.argv)
|