From a5c48fb43e6b1e7052dcac9bbd1bb4ef5814f654 Mon Sep 17 00:00:00 2001 From: Ross Wilson Date: Thu, 25 Feb 2016 14:56:55 +0700 Subject: [PATCH] Getting Imlac machine running, test loading --- pymlac/MainCPU.py | 298 ++++++++++++++++++++++---------------------- pymlac/Memory.py | 1 + pymlac/Trace.py | 20 ++- pymlac/dumpmem.test | 2 +- pymlac/pymlac | 128 ++++++++++++++----- pymlac/test_CPU.py | 11 +- 6 files changed, 274 insertions(+), 186 deletions(-) diff --git a/pymlac/MainCPU.py b/pymlac/MainCPU.py index bad9cef..e44cb13 100644 --- a/pymlac/MainCPU.py +++ b/pymlac/MainCPU.py @@ -169,7 +169,7 @@ class MainCPU(object): return self.BlockBase | address def execute_one_instruction(self): - """Execute one MAIN instruction, return # cycles used""" + """Execute one MAIN instruction, return # cycles used and if traced.""" if not self.running: return 0 @@ -187,6 +187,7 @@ class MainCPU(object): return self.main_decode.get(opcode, self.illegal)(indirect, address, instruction) + def illegal(self, indirect, address, instruction): """Handle an illegal instruction.""" @@ -208,33 +209,34 @@ class MainCPU(object): instruction) def i_LAW_LWC(self, indirect, address, instruction): + traced = False if indirect: self.AC = ~address & WORDMASK - trace.itrace('LWC', False, address) + traced = trace.itrace('LWC', False, address) else: self.AC = address - trace.itrace('LAW', False, address) - return 1 + traced = trace.itrace('LAW', False, address) + return (1, traced) def i_JMP(self, indirect, address, instruction): address = self.memory.eff_address(address, indirect) self.PC = address & PCMASK - trace.itrace('JMP', indirect, address) - return 3 if indirect else 2 + traced = trace.itrace('JMP', indirect, address) + return (3, traced) if indirect else (2, traced) def i_DAC(self, indirect, address, instruction): address = self.memory.eff_address(address, indirect) self.memory.put(self.AC, address, False) - trace.itrace('DAC', indirect, address) - return 3 if indirect else 2 + traced = trace.itrace('DAC', indirect, address) + return (3, traced) if indirect else (2, traced) def i_XAM(self, indirect, address, instruction): address = self.memory.eff_address(address, indirect) tmp = self.memory.fetch(address, False) self.memory.put(self.AC, address, False) self.AC = tmp - trace.itrace('XAM', indirect, address) - return 3 if indirect else 2 + traced = trace.itrace('XAM', indirect, address) + return (3, traced) if indirect else (2, traced) def i_ISZ(self, indirect, address, instruction): address = self.memory.eff_address(address, indirect) @@ -242,43 +244,43 @@ class MainCPU(object): self.memory.put(value, address, False) if value == 0: self.PC = (self.PC + 1) & WORDMASK - trace.itrace('ISZ', indirect, address) - return 3 if indirect else 2 + traced = trace.itrace('ISZ', indirect, address) + return (3, traced) if indirect else (2, traced) def i_JMS(self, indirect, address, instruction): address = self.memory.eff_address(address, indirect) self.memory.put(self.PC, address, False) self.PC = (address + 1) & PCMASK - trace.itrace('JMS', indirect, address) - return 3 if indirect else 2 + traced = trace.itrace('JMS', indirect, address) + return (3, traced) if indirect else (2, traced) def i_AND(self, indirect, address, instruction): self.AC &= self.memory.fetch(address, indirect) - trace.itrace('AND', indirect, address) - return 3 if indirect else 2 + traced = trace.itrace('AND', indirect, address) + return (3, traced) if indirect else (2, traced) def i_IOR(self, indirect, address, instruction): self.AC |= self.memory.fetch(address, indirect) - trace.itrace('IOR', indirect, address) - return 3 if indirect else 2 + traced = trace.itrace('IOR', indirect, address) + return (3, traced) if indirect else (2, traced) def i_XOR(self, indirect, address, instruction): self.AC ^= self.memory.fetch(address, indirect) - trace.itrace('XOR', indirect, address) - return 3 if indirect else 2 + traced = trace.itrace('XOR', indirect, address) + return (3, traced) if indirect else (2, traced) def i_LAC(self, indirect, address, instruction): self.AC = self.memory.fetch(address, indirect) - trace.itrace('LAC', indirect, address) - return 3 if indirect else 2 + traced = trace.itrace('LAC', indirect, address) + return (3, traced) if indirect else (2, traced) def i_ADD(self, indirect, address, instruction): self.AC += self.memory.fetch(self.BLOCKADDR(address), indirect) if self.AC & OVERFLOWMASK: self.L = (~self.L) & 01 self.AC &= WORDMASK - trace.itrace('ADD', indirect, address) - return 3 if indirect else 2 + traced = trace.itrace('ADD', indirect, address) + return (3, traced) if indirect else (2, traced) def i_SUB(self, indirect, address, instruction): addit = self.memory.fetch(self.BLOCKADDR(address), indirect) @@ -287,15 +289,15 @@ class MainCPU(object): if self.AC & OVERFLOWMASK: self.L = ~self.L self.AC &= WORDMASK - trace.itrace('SUB', indirect, address) - return 3 if indirect else 2 + traced = trace.itrace('SUB', indirect, address) + return (3, traced) if indirect else (2, traced) def i_SAM(self, indirect, address, instruction): samaddr = self.BLOCKADDR(address) if self.AC == self.memory.fetch(samaddr, indirect): self.PC = (self.PC + 1) & PCMASK - trace.itrace('SAM', indirect, address) - return 3 if indirect else 2 + traced = trace.itrace('SAM', indirect, address) + return (3, traced) if indirect else (2, traced) def microcode(self, instruction): # T1 @@ -336,149 +338,149 @@ class MainCPU(object): if instruction & k: combine.append(op) - trace.itrace('+'.join(combine), False) - return 1 + traced = trace.itrace('+'.join(combine), False) + return (1, traced) def i_DLA(self, indirect, address, instruction): self.displaycpu.DPC = self.AC - trace.itrace('DLA') - return 1 + traced = trace.itrace('DLA') + return (1, traced) def i_CTB(self, indirect, address, instruction): - trace.itrace('CTB') - return 1 + traced = trace.itrace('CTB') + return (1, traced) def i_DOF(self, indirect, address, instruction): self.displaycpu.stop() - trace.itrace('DOF') - return 1 + traced = trace.itrace('DOF') + return (1, traced) def i_KRB(self, indirect, address, instruction): self.AC |= self.kbd.read() - trace.itrace('KRB') - return 1 + traced = trace.itrace('KRB') + return (1, traced) def i_KCF(self, indirect, address, instruction): self.kbd.clear() - trace.itrace('KCF') - return 1 + traced = trace.itrace('KCF') + return (1, traced) def i_KRC(self, indirect, address, instruction): self.AC |= self.kbd.read() self.kbd.clear() - trace.itrace('KRC') - return 1 + traced = trace.itrace('KRC') + return (1, traced) def i_RRB(self, indirect, address, instruction): self.AC |= self.ttyin.read() - trace.itrace('RRB') - return 1 + traced = trace.itrace('RRB') + return (1, traced) def i_RCF(self, indirect, address, instruction): self.ttyin.clear() - trace.itrace('RCF') - return 1 + traced = trace.itrace('RCF') + return (1, traced) def i_RRC(self, indirect, address, instruction): self.AC |= self.ttyin.read() self.ttyin.clear() - trace.itrace('RRC') - return 1 + traced = trace.itrace('RRC') + return (1, traced) def i_TPR(self, indirect, address, instruction): self.ttyout.write(self.AC & 0xff) - trace.itrace('TPR') - return 1 + traced = trace.itrace('TPR') + return (1, traced) def i_TCF(self, indirect, address, instruction): self.ttyout.clear() - trace.itrace('TCF') - return 1 + traced = trace.itrace('TCF') + return (1, traced) def i_TPC(self, indirect, address, instruction): self.ttyout.write(self.AC & 0xff) self.ttyout.clear() - trace.itrace('TPC') - return 1 + traced = trace.itrace('TPC') + return (1, traced) def i_HRB(self, indirect, address, instruction): self.AC |= self.ptrptp.read() - trace.itrace('HRB') - return 1 + traced = trace.itrace('HRB') + return (1, traced) def i_HOF(self, indirect, address, instruction): self.ptrptp.stop() - trace.itrace('HOF') - return 1 + traced = trace.itrace('HOF') + return (1, traced) def i_HON(self, indirect, address, instruction): self.ptrptp.start() - trace.itrace('HON') - return 1 + traced = trace.itrace('HON') + return (1, traced) def i_STB(self, indirect, address, instruction): - trace.itrace('STB') - return 1 + traced = trace.itrace('STB') + return (1, traced) def i_SCF(self, indirect, address, instruction): self.Sync40Hz = 0 - trace.itrace('SCF') - return 1 + traced = trace.itrace('SCF') + return (1, traced) def i_IOS(self, indirect, address, instruction): - trace.itrace('IOS') - return 1 + traced = trace.itrace('IOS') + return (1, traced) def i_IOT101(self, indirect, address, instruction): - trace.itrace('IOT101') - return 1 + traced = trace.itrace('IOT101') + return (1, traced) def i_IOT111(self, indirect, address, instruction): - trace.itrace('IOT111') - return 1 + traced = trace.itrace('IOT111') + return (1, traced) def i_IOT131(self, indirect, address, instruction): - trace.itrace('IOT131') - return 1 + traced = trace.itrace('IOT131') + return (1, traced) def i_IOT132(self, indirect, address, instruction): - trace.itrace('IOT132') - return 1 + traced = trace.itrace('IOT132') + return (1, traced) def i_IOT134(self, indirect, address, instruction): - trace.itrace('IOT134') - return 1 + traced = trace.itrace('IOT134') + return (1, traced) def i_IOT141(self, indirect, address, instruction): - trace.itrace('IOT141') - return 1 + traced = trace.itrace('IOT141') + return (1, traced) def i_IOF(self, indirect, address, instruction): - trace.itrace('IOF') - return 1 + traced = trace.itrace('IOF') + return (1, traced) def i_ION(self, indirect, address, instruction): - trace.itrace('ION') - return 1 + traced = trace.itrace('ION') + return (1, traced) def i_PPC(self, indirect, address, instruction): self.ptrptp.punch(self.AC & 0xff) - trace.itrace('PPC') - return 1 + traced = trace.itrace('PPC') + return (1, traced) def i_PSF(self, indirect, address, instruction): if self.ptrptp.ready(): self.PC = (self.PC + 1) & WORDMASK - trace.itrace('PSF') - return 1 + traced = trace.itrace('PSF') + return (1, traced) def i_RAL1(self, indirect, address, instruction): newl = self.AC >> 15 newac = (self.AC << 1) | self.L self.L = newl self.AC = newac & WORDMASK - trace.itrace('RAL', False, 1) - return 1 + traced = trace.itrace('RAL', False, 1) + return (1, traced) def i_RAL2(self, indirect, address, instruction): newl = self.AC >> 15 @@ -489,8 +491,8 @@ class MainCPU(object): newac = (self.AC << 1) | self.L self.L = newl self.AC = newac & WORDMASK - trace.itrace('RAL', False, 2) - return 1 + traced = trace.itrace('RAL', False, 2) + return (1, traced) def i_RAL3(self, indirect, address, instruction): newl = self.AC >> 15 @@ -505,16 +507,16 @@ class MainCPU(object): newac = (self.AC << 1) | self.L self.L = newl self.AC = newac & WORDMASK - trace.itrace('RAL', False, 3) - return 1 + traced = trace.itrace('RAL', False, 3) + return (1, traced) def i_RAR1(self, indirect, address, instruction): newl = self.AC & 1 newac = (self.AC >> 1) | (self.L << 15) self.L = newl self.AC = newac & WORDMASK - trace.itrace('RAR', False, 1) - return 1 + traced = trace.itrace('RAR', False, 1) + return (1, traced) def i_RAR2(self, indirect, address, instruction): newl = self.AC & 1 @@ -525,8 +527,8 @@ class MainCPU(object): newac = (self.AC >> 1) | (self.L << 15) self.L = newl self.AC = newac & WORDMASK - trace.itrace('RAR', False, 2) - return 1 + traced = trace.itrace('RAR', False, 2) + return (1, traced) def i_RAR3(self, indirect, address, instruction): newl = self.AC & 1 @@ -541,162 +543,162 @@ class MainCPU(object): newac = (self.AC >> 1) | (self.L << 15) self.L = newl self.AC = newac & WORDMASK - trace.itrace('RAR', False, 3) - return 1 + traced = trace.itrace('RAR', False, 3) + return (1, traced) def i_SAL1(self, indirect, address, instruction): high_bit = self.AC & HIGHBITMASK value = self.AC & 037777 self.AC = (value << 1) | high_bit - trace.itrace('SAL', False, 1) - return 1 + traced = trace.itrace('SAL', False, 1) + return (1, traced) def i_SAL2(self, indirect, address, instruction): high_bit = self.AC & HIGHBITMASK value = self.AC & 017777 self.AC = (value << 2) | high_bit - trace.itrace('SAL', False, 2) - return 1 + traced = trace.itrace('SAL', False, 2) + return (1, traced) def i_SAL3(self, indirect, address, instruction): high_bit = self.AC & HIGHBITMASK value = self.AC & 007777 self.AC = (value << 3) | high_bit - trace.itrace('SAL', False, 3) - return 1 + traced = trace.itrace('SAL', False, 3) + return (1, traced) def i_SAR1(self, indirect, address, instruction): high_bit = self.AC & HIGHBITMASK self.AC = (self.AC >> 1) | high_bit - trace.itrace('SAR', False, 1) - return 1 + traced = trace.itrace('SAR', False, 1) + return (1, traced) def i_SAR2(self, indirect, address, instruction): high_bit = self.AC & HIGHBITMASK self.AC = (self.AC >> 1) | high_bit self.AC = (self.AC >> 1) | high_bit - trace.itrace('SAR', False, 2) - return 1 + traced = trace.itrace('SAR', False, 2) + return (1, traced) def i_SAR3(self, indirect, address, instruction): high_bit = self.AC & HIGHBITMASK self.AC = (self.AC >> 1) | high_bit self.AC = (self.AC >> 1) | high_bit self.AC = (self.AC >> 1) | high_bit - trace.itrace('SAR', False, 3) - return 1 + traced = trace.itrace('SAR', False, 3) + return (1, traced) def i_DON(self, indirect, address, instruction): self.displaycpu.DRSindex = 0 self.displaycpu.start() - trace.itrace('DON') - return 1 + traced = trace.itrace('DON') + return (1, traced) def i_ASZ(self): if self.AC == 0: self.PC = (self.PC + 1) & WORDMASK - trace.itrace('ASZ') - return 1 + traced = trace.itrace('ASZ') + return (1, traced) def i_ASN(self): if self.AC != 0: self.PC = (self.PC + 1) & WORDMASK - trace.itrace('ASN') - return 1 + traced = trace.itrace('ASN') + return (1, traced) def i_ASP(self): if not (self.AC & HIGHBITMASK): self.PC = (self.PC + 1) & WORDMASK - trace.itrace('ASP') - return 1 + traced = trace.itrace('ASP') + return (1, traced) def i_ASM(self): if (self.AC & HIGHBITMASK): self.PC = (self.PC + 1) & WORDMASK - trace.itrace('ASM') - return 1 + traced = trace.itrace('ASM') + return (1, traced) def i_LSZ(self): if self.L == 0: self.PC = (self.PC + 1) & WORDMASK - trace.itrace('LSZ') - return 1 + traced = trace.itrace('LSZ') + return (1, traced) def i_LSN(self): if self.L != 0: self.PC = (self.PC + 1) & WORDMASK - trace.itrace('LSN') - return 1 + traced = trace.itrace('LSN') + return (1, traced) def i_DSF(self): if self.displaycpu.ison(): self.PC = (self.PC + 1) & WORDMASK - trace.itrace('DSF') - return 1 + traced = trace.itrace('DSF') + return (1, traced) def i_DSN(self): if not self.displaycpu.ison(): self.PC = (self.PC + 1) & WORDMASK - trace.itrace('DSN') - return 1 + traced = trace.itrace('DSN') + return (1, traced) def i_KSF(self): if self.kbd.ready(): self.PC = (self.PC + 1) & WORDMASK - trace.itrace('KSF') - return 1 + traced = trace.itrace('KSF') + return (1, traced) def i_KSN(self): if not self.kbd.ready(): self.PC = (self.PC + 1) & WORDMASK - trace.itrace('KSN') - return 1 + traced = trace.itrace('KSN') + return (1, traced) def i_RSF(self): if self.ttyin.ready(): self.PC = (self.PC + 1) & WORDMASK - trace.itrace('RSF') - return 1 + traced = trace.itrace('RSF') + return (1, traced) def i_RSN(self): if not self.ttyin.ready(): self.PC = (self.PC + 1) & WORDMASK - trace.itrace('RSN') - return 1 + traced = trace.itrace('RSN') + return (1, traced) def i_TSF(self): if self.ttyout.ready(): self.PC = (self.PC + 1) & WORDMASK - trace.itrace('TSF') - return 1 + traced = trace.itrace('TSF') + return (1, traced) def i_TSN(self): if not self.ttyout.ready(): self.PC = (self.PC + 1) & WORDMASK - trace.itrace('TSN') - return 1 + traced = trace.itrace('TSN') + return (1, traced) def i_SSF(self): if self.display.ready(): # skip if 40Hz sync on self.PC = (self.PC + 1) & WORDMASK - trace.itrace('SSF') - return 1 + traced = trace.itrace('SSF') + return (1, traced) def i_SSN(self): if not self.display.ready(): self.PC = (self.PC + 1) & WORDMASK - trace.itrace('SSN') - return 1 + traced = trace.itrace('SSN') + return (1, traced) def i_HSF(self): if self.ptrptp.ready(): self.PC = (self.PC + 1) & WORDMASK - trace.itrace('HSF') - return 1 + traced = trace.itrace('HSF') + return (1, traced) def i_HSN(self): if not self.ptrptp.ready(): self.PC = (self.PC + 1) & WORDMASK - trace.itrace('HSN') - return 1 + traced = trace.itrace('HSN') + return (1, traced) diff --git a/pymlac/Memory.py b/pymlac/Memory.py index 7ba0c57..9fbcdb8 100644 --- a/pymlac/Memory.py +++ b/pymlac/Memory.py @@ -263,6 +263,7 @@ class Memory(object): try: self.memory[address] = MASK_16(value) + print('Memory: setting address %06o to %06o' % (address, MASK_16(value))) except IndexError: raise RuntimeError('Bad address: %06o (max mem=%06o, ADDRMASK=%06o)' % (address, len(self.memory), ADDRMASK)) diff --git a/pymlac/Trace.py b/pymlac/Trace.py index 1c1f484..8a62d91 100644 --- a/pymlac/Trace.py +++ b/pymlac/Trace.py @@ -12,6 +12,7 @@ Based on the 'borg' recipe from [http://code.activestate.com/recipes/66531/]. """ import os +import collections from Globals import * @@ -44,6 +45,13 @@ class Trace(object): self.cpu = maincpu self.dcpu = displaycpu + self.trace_map = collections.defaultdict(bool) + + def set_trace_map(self, trace_map): + """Set the trace address dict mapping.""" + + self.trace_map = trace_map + def add_maincpu(self, maincpu): """Add the main CPU object.""" @@ -91,16 +99,24 @@ class Trace(object): opcode the main CPU opcode indirect True if instruction was indirect - adress address for the instruction (if any) + address address for the instruction (if any) + + Returns True if tracing, else False. """ - if self.tracing: +# print('itrace: self.cpu.PC=%06o, self.trace_map[self.cpu.PC]=%s' +# % (self.cpu.PC-1, str(self.trace_map[self.cpu.PC-1]))) + + if self.tracing and self.trace_map[self.cpu.PC-1]: char = '*' if indirect else '' if address is None: self.tracefile.write('%s\t%s\t' % (opcode, char)) else: self.tracefile.write('%s\t%s%5.5o\t' % (opcode, char, address)) self.tracefile.flush() + return True + + return False def itraceend(self, dispon): """Trace at the end of one execution cycle. diff --git a/pymlac/dumpmem.test b/pymlac/dumpmem.test index 2d09ce5..fc14a6a 100644 --- a/pymlac/dumpmem.test +++ b/pymlac/dumpmem.test @@ -1,2 +1,2 @@ # test of loading simple code and dumping memory -bootrom ptr; mount ptr dumpmem_test.ptp; setreg pc 040; rununtil 0; dumpmem dumpmem_test.dump +bootrom ptr; mount ptr dumpmem_test.ptp; setreg pc 040; trace 040,077; rununtil 0; dumpmem dumpmem_test.dump diff --git a/pymlac/pymlac b/pymlac/pymlac index c81f1a7..a9d4d04 100755 --- a/pymlac/pymlac +++ b/pymlac/pymlac @@ -22,10 +22,10 @@ required. The options are: -ptr loads a file on to the papertape reader device -r (
| pc) executes from
or the current PC contents -s sets memory adress values from - -t ( [,] | off) controls the execution trace: - -t 0100 trace from address 0100 (octal) - -t 0100,200 trace from 0100 octal to 200 decimal - -t off turns trace off + -t ([:] | off) controls the execution trace: + -t 0100,0200 trace from 0100 octal to 200 decimal + -t 0100,0200:0210,0300 trace from 0100 to 0200 and 0210 to 0300 + -t off turns trace off -ttyin loads a file on to the teletype reader device -ttyout loads a file on to the teletype writer device -v views contents of memory addresses from file @@ -36,10 +36,21 @@ required. The options are: import sys import getopt +import collections + +from Globals import * +import MainCPU +import Memory +import PtrPtp +import TtyIn +import TtyOut +import Trace + +trace = Trace.Trace(TRACE_FILENAME) def str2int(s): - """Convert a strinf to an integer value. + """Convert a string to an integer value. s the string to convert @@ -47,8 +58,16 @@ def str2int(s): None is returned if the string cannot be converted. """ - return None + base = 10 + if s[0] == '0': + base = 8 + try: + value = int(s, base=base) + except: + return None + + return value def usage(msg=None): if msg: @@ -58,13 +77,40 @@ def usage(msg=None): print(__doc__) +def start_running(cpu, memory, ptrptp): + """Run the Imlac machine until it stops.""" + + cpu.running = True + while cpu.running: + (cycles, traced) = cpu.execute_one_instruction() + if traced: + trace.itraceend(False) + ptrptp.ptr_tick(cycles) + ptrptp.ptp_tick(cycles) + def main(): """Main function of the simulator. Mostly interpret CLI args.""" + # prepare the Imlac machine + imlac_memory = Memory.Memory() + imlac_ptrptp = PtrPtp.PtrPtp() + imlac_ttyin = TtyIn.TtyIn() + imlac_ttyout = TtyOut.TtyOut() + imlac_cpu = MainCPU.MainCPU(imlac_memory, None, None, + None, imlac_ttyin, imlac_ttyout, imlac_ptrptp) + imlac_cpu.running = True + imlac_display_state = False + + # prepare the trace + trace.add_maincpu(imlac_cpu) + print('sys.argv=%s' % str(sys.argv)) - len_sys_argv = len(sys.argv) + # trace_map defines addresses we are tracing at + # initially, no tracing + trace_map = collections.defaultdict(bool) + len_sys_argv = len(sys.argv) ndx = 1 while ndx < len_sys_argv: opt = sys.argv[ndx] @@ -80,23 +126,28 @@ def main(): dev = sys.argv[ndx].lower() ndx += 1 if dev == 'ptr': - set_bootrom('PTR') +# set_bootrom('PTR') + imlac_memory.set_ROM('ptr') elif dev == 'tty': - set_bootrom('TTYIN') +# set_bootrom('TTYIN') + imlac_memory.set_ROM('tty') elif dev == 'none': - set_bootrom(None) +# set_bootrom(None) + imlac_memory.set_ROM(None) else: usage("-b option must be followed by 'ptr', 'tty' or 'none'") sys.exit(10) elif opt == '-c': - clear_core() +# clear_core() + imlac_memory.clear_core() elif opt == '-cf': if ndx >= len_sys_argv: usage("'-cf' option needs a following filename") sys.exit(10) filename = sys.argv[ndx] ndx += 1 - set_core_file(filename) +# set_core_file(filename) + imlac_memory.set_corefile(filename) elif opt == '-d': if ndx >= len_sys_argv: usage("'-d' option needs a following data switch value") @@ -106,7 +157,8 @@ def main(): if value is None: usage("The '-d' option must be followed by a decimal or octal value") sys.exit(10) - set_data_switch(value) +# set_data_switch(value) + imlac_cpu.DS = value elif opt == '-h': usage() sys.exit(0) @@ -116,14 +168,16 @@ def main(): sys.exit(10) filename = sys.argv[ndx] ndx += 1 - set_ptp_filename(filename) +# set_ptp_filename(filename) + imlac_ptrptp.ptp_mount(filename) elif opt == '-ptr': if ndx >= len_sys_argv: usage("'-ptr' option needs a following PTR filename") sys.exit(10) filename = sys.argv[ndx] ndx += 1 - set_ptr_filename(filename) +# set_ptr_filename(filename) + imlac_ptrptp.ptr_mount(filename) elif opt == '-r': if ndx >= len_sys_argv: usage("'-r' option needs a following address or 'pc'") @@ -135,8 +189,10 @@ def main(): if addr_value is None: usage("'-r' option needs a following address or 'pc'") sys.exit(10) - set_pc(addr_value) - start_running() +# set_pc(addr_value) + imlac_cpu.PC = addr_value + trace.set_trace_map(trace_map) + start_running(imlac_cpu, imlac_memory, imlac_ptrptp) elif opt == '-s': if ndx >= len_sys_argv: usage("'-s' option needs a following data filename") @@ -146,39 +202,44 @@ def main(): set_mem_from_file(filename) elif opt == '-t': if ndx >= len_sys_argv: - usage("'-t' option needs a following address range or 'off'") + usage("'-t' option needs following address ranges or 'off'") sys.exit(10) r = sys.argv[ndx] ndx += 1 if r == 'off': - set_trace_off() + trace_map = collections.defaultdict(bool) else: - if ',' in r: - rr = r.split(',') - if len(rr) != 2: - usage("'-r' option may be followed by only two addresses") + trace_map = collections.defaultdict(bool) + print('r=%s' % r) + for rng in r.split(':'): + print('rng=%s' % rng) + be = rng.split(',') + print('be=%s' % str(be)) + if len(be) != 2: + usage("'-r' ranges must have form 'begin,end'") sys.exit(10) - (start, stop) = rr - start_addr = str2int(start) - stop_addr = str2int(stop) - else: - start_addr = str2int(r) - stop_addr = None - set_trace_on(star_addr, stop_addr) + (begin, end) = be + begin = str2int(begin) + end = str2int(end) + print('begin=%s, end=%s' % (str(begin), str(end))) + for addr in range(begin, end+1): + trace_map[addr] = True elif opt == '-ttyin': if ndx >= len_sys_argv: usage("'-ttyin' option needs a following data filename") sys.exit(10) filename = sys.argv[ndx] ndx += 1 - set_tty_in(filename) +# set_tty_in(filename) + imlac_ttyin.mount(filename) elif opt == '-ttyout': if ndx >= len_sys_argv: usage("'-ttyout' option needs a following data filename") sys.exit(10) filename = sys.argv[ndx] ndx += 1 - set_tty_out(filename) +# set_tty_out(filename) + imlac_ttyout.mount(filename) elif opt == '-v': if ndx >= len_sys_argv: usage("'-v' option needs a following address filename") @@ -199,7 +260,8 @@ def main(): else: usage("'-v' option needs a following 'on' or 'off'") sys.exit(10) - set_rom_write(state) +# set_rom_write(state) + imlac_memory.set_ROM_writable(state) if __name__ == '__main__': diff --git a/pymlac/test_CPU.py b/pymlac/test_CPU.py index e5ba9d8..2ac2d8f 100644 --- a/pymlac/test_CPU.py +++ b/pymlac/test_CPU.py @@ -12,6 +12,7 @@ where is a file of test instructions and """ import time +import collections # We implement a small interpreter to test the CPU. # The DSL is documented here: [github.com/rzzzwilson/pymlac]. @@ -146,6 +147,7 @@ class TestCPU(object): # dismount # checkfile # dumpmem file begin,end +# cmpmem file def setreg(self, name, value): """Set register to a value. @@ -387,7 +389,7 @@ class TestCPU(object): else: return 'mount: bad device: %s' % device - def dismount(self, device): + def dismount(self, device, ignore): """Dismount a file from a device. device name of device @@ -441,6 +443,9 @@ class TestCPU(object): with open(filename, 'wb') as handle: json.dump(mem, handle) + def cmpmem(self, filename, ignore): + pass + # end of DSL primitives def check_all_mem(self): @@ -597,7 +602,9 @@ class TestCPU(object): elif opcode == 'checkfile': r = self.checkfile(fld1, fld2) elif opcode == 'dumpmem': - r = self.checkfile(fld1, fld2) + r = self.dumpmem(fld1, fld2) + elif opcode == 'cmpmem': + r = self.cmpmem(fld1, fld2) else: print("Unrecognized opcode '%s' in: %s" % (opcode, test)) raise Exception("Unrecognized opcode '%s' in: %s" % (opcode, test))