1
0
mirror of https://github.com/rzzzwilson/pymlac.git synced 2025-06-10 09:32:41 +00:00

Working on trace

This commit is contained in:
Ross Wilson
2018-07-25 10:15:42 +07:00
parent 0452a7cf7d
commit 2dfdad6066
5 changed files with 265 additions and 292 deletions

View File

@@ -14,10 +14,6 @@ import sys
from Globals import *
import Trace
trace = Trace.Trace(TRACE_FILENAME)
import log
log = log.Log('test.log', log.Log.DEBUG)
@@ -122,7 +118,7 @@ class DisplayCPU(object):
if byte & 0x20: # DRJM
if self.DRSindex <= 0:
trace.comment('\nDRS stack underflow at display address %6.6o'
Trace.comment('\nDRS stack underflow at display address %6.6o'
% (self.DPC - 1))
self.illegal()
self.DRSindex -= 1
@@ -180,10 +176,10 @@ class DisplayCPU(object):
def illegal(self, instruction=None):
if instruction:
trace.comment('Illegal display instruction (%6.6o) at address %6.6o'
Trace.comment('Illegal display instruction (%6.6o) at address %6.6o'
% (instruction, (self.DPC - 1)))
else:
trace.comment('Illegal display instruction at address %6.6o'
Trace.comment('Illegal display instruction at address %6.6o'
% (self.DPC - 1))
sys.exit(0)
@@ -192,12 +188,12 @@ class DisplayCPU(object):
def i_DDXM(self):
self.DX -= 0o40
tracestr = trace.dtrace(self.dot, 'DDXM', None)
tracestr = Trace.dtrace(self.dot, 'DDXM', None)
return (1, tracestr)
def i_DDYM(self):
self.DY -= 0o40
tracestr = trace.dtrace(self.dot, 'DDYM', None)
tracestr = Trace.dtrace(self.dot, 'DDYM', None)
return (1, tracestr)
def i_DEIM(self, address):
@@ -207,22 +203,22 @@ class DisplayCPU(object):
def i_DHLT(self):
self.Running = False
return (1, trace.dtrace(self.dot, 'DHLT', None))
return (1, Trace.dtrace(self.dot, 'DHLT', None))
def i_DHVC(self):
return (1, trace.dtrace(self.dot, 'DHVC', None))
return (1, Trace.dtrace(self.dot, 'DHVC', None))
def i_DIXM(self):
self.DX += 0o4000
return (1, trace.dtrace(self.dot, 'DIXM', None))
return (1, Trace.dtrace(self.dot, 'DIXM', None))
def i_DIYM(self):
self.DY += 0o4000
return (1, trace.dtrace(self.dot, 'DIYM', None))
return (1, Trace.dtrace(self.dot, 'DIYM', None))
def i_DJMP(self, address):
self.DPC = MASK_MEM(address + (self.DIB << 12))
return (1, trace.dtrace(self.dot, 'DJMP', address))
return (1, Trace.dtrace(self.dot, 'DJMP', address))
def i_DJMS(self, address):
if self.DRSindex >= 8:
@@ -232,15 +228,15 @@ class DisplayCPU(object):
self.DRS[self.DRSindex] = self.DPC
self.DRSindex += 1
self.DPC = MASK_MEM(address + (self.DIB << 12))
return (1, trace.dtrace(self.dot, 'DJMS', address))
return (1, Trace.dtrace(self.dot, 'DJMS', address))
def i_DLXA(self, address):
self.DX = (address & self.BITS10) << 1
return (1, trace.dtrace(self.dot, 'DLXA', address))
return (1, Trace.dtrace(self.dot, 'DLXA', address))
def i_DLYA(self, address):
self.DY = (address & self.BITS10) << 1
return (1, trace.dtrace(self.dot, 'DLXA', address))
return (1, Trace.dtrace(self.dot, 'DLXA', address))
def i_DLVH(self, word1):
word2 = self.memory.get(self, DPC, 0)
@@ -280,7 +276,7 @@ class DisplayCPU(object):
self.DY += N
self.display.draw(prevDX, prevDY, self.DX, self.DY, dotted)
return (3, trace.dtrace(self.dot, 'DLVH', None))
return (3, Trace.dtrace(self.dot, 'DLVH', None))
def i_DRJM(self):
if self.DRSindex <= 0:
@@ -289,12 +285,12 @@ class DisplayCPU(object):
self.illegal()
self.DRSindex -= 1
self.DPC = self.DRS[self.DRSindex]
return (1, trace.dtrace(self.dot, 'DRJM', None)) # FIXME check # cycles used
return (1, Trace.dtrace(self.dot, 'DRJM', None)) # FIXME check # cycles used
def i_DSTB(self, block):
self.DIB = block
trace.dtrace('DSTB\t%d' % block)
return (1, trace.dtrace('DSTB\t%d' % block, None))
Trace.dtrace('DSTB\t%d' % block)
return (1, Trace.dtrace('DSTB\t%d' % block, None))
def i_DSTS(self, scale):
if scale == 0:
@@ -307,14 +303,14 @@ class DisplayCPU(object):
self.Scale = 3.0
else:
self.illegal()
return (1, trace.dtrace('DSTS\t%d' % scale, None)) # FIXME check # cycles used
return (1, Trace.dtrace('DSTS\t%d' % scale, None)) # FIXME check # cycles used
def page00(self, instruction):
if instruction == 0o00000: # DHLT
(cycles, tracestr) = self.i_DHLT()
elif instruction == 0o04000: # DNOP
cycles = 1
tracestr = trace.dtrace('DNOP')
tracestr = Trace.dtrace('DNOP')
elif instruction == 0o04004: # DSTS 0
(cycles, tracestr) = self.i_DSTS(0)
elif instruction == 0o04005: # DSTS 1

View File

@@ -5,14 +5,11 @@ The Imlac main CPU.
import sys
from Globals import *
import Trace
from Globals import *
import log
log = log.Log('test.log', log.Log.DEBUG)
trace = Trace.Trace(TRACE_FILENAME)
class MainCPU(object):
@@ -219,22 +216,22 @@ class MainCPU(object):
tracestr = None
if indirect:
self.AC = (~address+1) & WORDMASK
tracestr = trace.itrace(self.dot, 'LWC', False, address)
tracestr = Trace.itrace(self.dot, 'LWC', False, address)
else:
self.AC = address
tracestr = trace.itrace(self.dot, 'LAW', False, address)
tracestr = Trace.itrace(self.dot, 'LAW', False, address)
return (1, tracestr)
def i_JMP(self, indirect, address, instruction):
eff_address = self.memory.eff_address(address, indirect)
self.PC = eff_address & PCMASK
tracestr = trace.itrace(self.dot, 'JMP', indirect, address)
tracestr = Trace.itrace(self.dot, 'JMP', indirect, address)
return (3, tracestr) if indirect else (2, tracestr)
def i_DAC(self, indirect, address, instruction):
eff_address = self.memory.eff_address(address, indirect)
self.memory.put(self.AC, eff_address, False)
tracestr = trace.itrace(self.dot, 'DAC', indirect, address)
tracestr = Trace.itrace(self.dot, 'DAC', indirect, address)
return (3, tracestr) if indirect else (2, tracestr)
def i_XAM(self, indirect, address, instruction):
@@ -242,7 +239,7 @@ class MainCPU(object):
tmp = self.memory.fetch(eff_address, False)
self.memory.put(self.AC, eff_address, False)
self.AC = tmp
tracestr = trace.itrace(self.dot, 'XAM', indirect, address)
tracestr = Trace.itrace(self.dot, 'XAM', indirect, address)
return (3, tracestr) if indirect else (2, tracestr)
def i_ISZ(self, indirect, address, instruction):
@@ -251,34 +248,34 @@ class MainCPU(object):
self.memory.put(value, eff_address, False)
if value == 0:
self.PC = (self.PC + 1) & WORDMASK
tracestr = trace.itrace(self.dot, 'ISZ', indirect, address)
tracestr = Trace.itrace(self.dot, 'ISZ', indirect, address)
return (3, tracestr) if indirect else (2, tracestr)
def i_JMS(self, indirect, address, instruction):
eff_address = self.memory.eff_address(address, indirect)
self.memory.put(self.PC, eff_address, False)
self.PC = (eff_address + 1) & PCMASK
tracestr = trace.itrace(self.dot, 'JMS', indirect, address)
tracestr = Trace.itrace(self.dot, 'JMS', indirect, address)
return (3, tracestr) if indirect else (2, tracestr)
def i_AND(self, indirect, address, instruction):
self.AC &= self.memory.fetch(address, indirect)
tracestr = trace.itrace(self.dot, 'AND', indirect, address)
tracestr = Trace.itrace(self.dot, 'AND', indirect, address)
return (3, tracestr) if indirect else (2, tracestr)
def i_IOR(self, indirect, address, instruction):
self.AC |= self.memory.fetch(address, indirect)
tracestr = trace.itrace(self.dot, 'IOR', indirect, address)
tracestr = Trace.itrace(self.dot, 'IOR', indirect, address)
return (3, tracestr) if indirect else (2, tracestr)
def i_XOR(self, indirect, address, instruction):
self.AC ^= self.memory.fetch(address, indirect)
tracestr = trace.itrace(self.dot, 'XOR', indirect, address)
tracestr = Trace.itrace(self.dot, 'XOR', indirect, address)
return (3, tracestr) if indirect else (2, tracestr)
def i_LAC(self, indirect, address, instruction):
self.AC = self.memory.fetch(address, indirect)
tracestr = trace.itrace(self.dot, 'LAC', indirect, address)
tracestr = Trace.itrace(self.dot, 'LAC', indirect, address)
return (3, tracestr) if indirect else (2, tracestr)
def i_ADD(self, indirect, address, instruction):
@@ -286,7 +283,7 @@ class MainCPU(object):
if self.AC & OVERFLOWMASK:
self.L = 0 if self.L else 1
self.AC &= WORDMASK
tracestr = trace.itrace(self.dot, 'ADD', indirect, address)
tracestr = Trace.itrace(self.dot, 'ADD', indirect, address)
return (3, tracestr) if indirect else (2, tracestr)
def i_SUB(self, indirect, address, instruction):
@@ -296,14 +293,14 @@ class MainCPU(object):
if self.AC & OVERFLOWMASK:
self.L = 0 if self.L else 1
self.AC &= WORDMASK
tracestr = trace.itrace(self.dot, 'SUB', indirect, address)
tracestr = Trace.itrace(self.dot, 'SUB', indirect, address)
return (3, tracestr) if indirect else (2, tracestr)
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
tracestr = trace.itrace(self.dot, 'SAM', indirect, address)
tracestr = Trace.itrace(self.dot, 'SAM', indirect, address)
return (3, tracestr) if indirect else (2, tracestr)
def microcode(self, instruction):
@@ -345,141 +342,141 @@ class MainCPU(object):
if instruction & k:
combine.append(op)
tracestr = trace.itrace(self.dot, '+'.join(combine), False)
tracestr = Trace.itrace(self.dot, '+'.join(combine), False)
return (1, tracestr)
def i_DLA(self, indirect, address, instruction):
self.displaycpu.DPC = self.AC
tracestr = trace.itrace(self.dot, 'DLA')
tracestr = Trace.itrace(self.dot, 'DLA')
return (1, tracestr)
def i_CTB(self, indirect, address, instruction):
tracestr = trace.itrace(self.dot, 'CTB')
tracestr = Trace.itrace(self.dot, 'CTB')
return (1, tracestr)
def i_DOF(self, indirect, address, instruction):
log('self.displaycpu=%s' % str(self.displaycpu))
self.displaycpu.stop()
tracestr = trace.itrace(self.dot, 'DOF')
tracestr = Trace.itrace(self.dot, 'DOF')
return (1, tracestr)
def i_KRB(self, indirect, address, instruction):
self.AC |= self.kbd.read()
tracestr = trace.itrace(self.dot, 'KRB')
tracestr = Trace.itrace(self.dot, 'KRB')
return (1, tracestr)
def i_KCF(self, indirect, address, instruction):
self.kbd.clear()
tracestr = trace.itrace(self.dot, 'KCF')
tracestr = Trace.itrace(self.dot, 'KCF')
return (1, tracestr)
def i_KRC(self, indirect, address, instruction):
self.AC |= self.kbd.read()
self.kbd.clear()
tracestr = trace.itrace(self.dot, 'KRC')
tracestr = Trace.itrace(self.dot, 'KRC')
return (1, tracestr)
def i_RRB(self, indirect, address, instruction):
self.AC |= self.ttyin.read()
tracestr = trace.itrace(self.dot, 'RRB')
tracestr = Trace.itrace(self.dot, 'RRB')
return (1, tracestr)
def i_RCF(self, indirect, address, instruction):
self.ttyin.clear()
tracestr = trace.itrace(self.dot, 'RCF')
tracestr = Trace.itrace(self.dot, 'RCF')
return (1, tracestr)
def i_RRC(self, indirect, address, instruction):
self.AC |= self.ttyin.read()
self.ttyin.clear()
tracestr = trace.itrace(self.dot, 'RRC')
tracestr = Trace.itrace(self.dot, 'RRC')
return (1, tracestr)
def i_TPR(self, indirect, address, instruction):
self.ttyout.write(self.AC & 0xff)
tracestr = trace.itrace(self.dot, 'TPR')
tracestr = Trace.itrace(self.dot, 'TPR')
return (1, tracestr)
def i_TCF(self, indirect, address, instruction):
self.ttyout.clear()
tracestr = trace.itrace(self.dot, 'TCF')
tracestr = Trace.itrace(self.dot, 'TCF')
return (1, tracestr)
def i_TPC(self, indirect, address, instruction):
self.ttyout.write(self.AC & 0xff)
self.ttyout.clear()
tracestr = trace.itrace(self.dot, 'TPC')
tracestr = Trace.itrace(self.dot, 'TPC')
return (1, tracestr)
def i_HRB(self, indirect, address, instruction):
self.AC |= self.ptrptp.read()
tracestr = trace.itrace(self.dot, 'HRB')
tracestr = Trace.itrace(self.dot, 'HRB')
return (1, tracestr)
def i_HOF(self, indirect, address, instruction):
self.ptrptp.stop()
tracestr = trace.itrace(self.dot, 'HOF')
tracestr = Trace.itrace(self.dot, 'HOF')
return (1, tracestr)
def i_HON(self, indirect, address, instruction):
self.ptrptp.start()
tracestr = trace.itrace(self.dot, 'HON')
tracestr = Trace.itrace(self.dot, 'HON')
return (1, tracestr)
def i_STB(self, indirect, address, instruction):
tracestr = trace.itrace(self.dot, 'STB')
tracestr = Trace.itrace(self.dot, 'STB')
return (1, tracestr)
def i_SCF(self, indirect, address, instruction):
self.Sync40Hz = 0
tracestr = trace.itrace(self.dot, 'SCF')
tracestr = Trace.itrace(self.dot, 'SCF')
return (1, tracestr)
def i_IOS(self, indirect, address, instruction):
tracestr = trace.itrace(self.dot, 'IOS')
tracestr = Trace.itrace(self.dot, 'IOS')
return (1, tracestr)
def i_IOT101(self, indirect, address, instruction):
tracestr = trace.itrace(self.dot, 'IOT101')
tracestr = Trace.itrace(self.dot, 'IOT101')
return (1, tracestr)
def i_IOT111(self, indirect, address, instruction):
tracestr = trace.itrace(self.dot, 'IOT111')
tracestr = Trace.itrace(self.dot, 'IOT111')
return (1, tracestr)
def i_IOT131(self, indirect, address, instruction):
tracestr = trace.itrace(self.dot, 'IOT131')
tracestr = Trace.itrace(self.dot, 'IOT131')
return (1, tracestr)
def i_IOT132(self, indirect, address, instruction):
tracestr = trace.itrace(self.dot, 'IOT132')
tracestr = Trace.itrace(self.dot, 'IOT132')
return (1, tracestr)
def i_IOT134(self, indirect, address, instruction):
tracestr = trace.itrace(self.dot, 'IOT134')
tracestr = Trace.itrace(self.dot, 'IOT134')
return (1, tracestr)
def i_IOT141(self, indirect, address, instruction):
tracestr = trace.itrace(self.dot, 'IOT141')
tracestr = Trace.itrace(self.dot, 'IOT141')
return (1, tracestr)
def i_IOF(self, indirect, address, instruction):
tracestr = trace.itrace(self.dot, 'IOF')
tracestr = Trace.itrace(self.dot, 'IOF')
return (1, tracestr)
def i_ION(self, indirect, address, instruction):
tracestr = trace.itrace(self.dot, 'ION')
tracestr = Trace.itrace(self.dot, 'ION')
return (1, tracestr)
def i_PPC(self, indirect, address, instruction):
self.ptrptp.punch(self.AC & 0xff)
tracestr = trace.itrace(self.dot, 'PPC')
tracestr = Trace.itrace(self.dot, 'PPC')
return (1, tracestr)
def i_PSF(self, indirect, address, instruction):
if self.ptrptp.ready():
self.PC = (self.PC + 1) & WORDMASK
tracestr = trace.itrace(self.dot, 'PSF')
tracestr = Trace.itrace(self.dot, 'PSF')
return (1, tracestr)
def i_RAL1(self, indirect, address, instruction):
@@ -487,7 +484,7 @@ class MainCPU(object):
newac = (self.AC << 1) | self.L
self.L = newl
self.AC = newac & WORDMASK
tracestr = trace.itrace(self.dot, 'RAL', False, 1)
tracestr = Trace.itrace(self.dot, 'RAL', False, 1)
return (1, tracestr)
def i_RAL2(self, indirect, address, instruction):
@@ -499,7 +496,7 @@ class MainCPU(object):
newac = (self.AC << 1) | self.L
self.L = newl
self.AC = newac & WORDMASK
tracestr = trace.itrace(self.dot, 'RAL', False, 2)
tracestr = Trace.itrace(self.dot, 'RAL', False, 2)
return (1, tracestr)
def i_RAL3(self, indirect, address, instruction):
@@ -515,7 +512,7 @@ class MainCPU(object):
newac = (self.AC << 1) | self.L
self.L = newl
self.AC = newac & WORDMASK
tracestr = trace.itrace(self.dot, 'RAL', False, 3)
tracestr = Trace.itrace(self.dot, 'RAL', False, 3)
return (1, tracestr)
def i_RAR1(self, indirect, address, instruction):
@@ -523,7 +520,7 @@ class MainCPU(object):
newac = (self.AC >> 1) | (self.L << 15)
self.L = newl
self.AC = newac & WORDMASK
tracestr = trace.itrace(self.dot, 'RAR', False, 1)
tracestr = Trace.itrace(self.dot, 'RAR', False, 1)
return (1, tracestr)
def i_RAR2(self, indirect, address, instruction):
@@ -535,7 +532,7 @@ class MainCPU(object):
newac = (self.AC >> 1) | (self.L << 15)
self.L = newl
self.AC = newac & WORDMASK
tracestr = trace.itrace(self.dot, 'RAR', False, 2)
tracestr = Trace.itrace(self.dot, 'RAR', False, 2)
return (1, tracestr)
def i_RAR3(self, indirect, address, instruction):
@@ -551,41 +548,41 @@ class MainCPU(object):
newac = (self.AC >> 1) | (self.L << 15)
self.L = newl
self.AC = newac & WORDMASK
tracestr = trace.itrace(self.dot, 'RAR', False, 3)
tracestr = Trace.itrace(self.dot, 'RAR', False, 3)
return (1, tracestr)
def i_SAL1(self, indirect, address, instruction):
high_bit = self.AC & HIGHBITMASK
value = self.AC & 0o37777
self.AC = (value << 1) | high_bit
tracestr = trace.itrace(self.dot, 'SAL', False, 1)
tracestr = Trace.itrace(self.dot, 'SAL', False, 1)
return (1, tracestr)
def i_SAL2(self, indirect, address, instruction):
high_bit = self.AC & HIGHBITMASK
value = self.AC & 0o17777
self.AC = (value << 2) | high_bit
tracestr = trace.itrace(self.dot, 'SAL', False, 2)
tracestr = Trace.itrace(self.dot, 'SAL', False, 2)
return (1, tracestr)
def i_SAL3(self, indirect, address, instruction):
high_bit = self.AC & HIGHBITMASK
value = self.AC & 0o07777
self.AC = (value << 3) | high_bit
tracestr = trace.itrace(self.dot, 'SAL', False, 3)
tracestr = Trace.itrace(self.dot, 'SAL', False, 3)
return (1, tracestr)
def i_SAR1(self, indirect, address, instruction):
high_bit = self.AC & HIGHBITMASK
self.AC = (self.AC >> 1) | high_bit
tracestr = trace.itrace(self.dot, 'SAR', False, 1)
tracestr = Trace.itrace(self.dot, 'SAR', False, 1)
return (1, tracestr)
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
tracestr = trace.itrace(self.dot, 'SAR', False, 2)
tracestr = Trace.itrace(self.dot, 'SAR', False, 2)
return (1, tracestr)
def i_SAR3(self, indirect, address, instruction):
@@ -593,121 +590,121 @@ class MainCPU(object):
self.AC = (self.AC >> 1) | high_bit
self.AC = (self.AC >> 1) | high_bit
self.AC = (self.AC >> 1) | high_bit
tracestr = trace.itrace(self.dot, 'SAR', False, 3)
tracestr = Trace.itrace(self.dot, 'SAR', False, 3)
return (1, tracestr)
def i_DON(self, indirect, address, instruction):
self.display.clear()
self.displaycpu.DRSindex = 0
self.displaycpu.start()
tracestr = trace.itrace(self.dot, 'DON')
tracestr = Trace.itrace(self.dot, 'DON')
return (1, tracestr)
def i_ASZ(self):
if self.AC == 0:
self.PC = (self.PC + 1) & WORDMASK
tracestr = trace.itrace(self.dot, 'ASZ')
tracestr = Trace.itrace(self.dot, 'ASZ')
return (1, tracestr)
def i_ASN(self):
if self.AC != 0:
self.PC = (self.PC + 1) & WORDMASK
tracestr = trace.itrace(self.dot, 'ASN')
tracestr = Trace.itrace(self.dot, 'ASN')
return (1, tracestr)
def i_ASP(self):
if not (self.AC & HIGHBITMASK):
self.PC = (self.PC + 1) & WORDMASK
tracestr = trace.itrace(self.dot, 'ASP')
tracestr = Trace.itrace(self.dot, 'ASP')
return (1, tracestr)
def i_ASM(self):
if (self.AC & HIGHBITMASK):
self.PC = (self.PC + 1) & WORDMASK
tracestr = trace.itrace(self.dot, 'ASM')
tracestr = Trace.itrace(self.dot, 'ASM')
return (1, tracestr)
def i_LSZ(self):
if self.L == 0:
self.PC = (self.PC + 1) & WORDMASK
tracestr = trace.itrace(self.dot, 'LSZ')
tracestr = Trace.itrace(self.dot, 'LSZ')
return (1, tracestr)
def i_LSN(self):
if self.L != 0:
self.PC = (self.PC + 1) & WORDMASK
tracestr = trace.itrace(self.dot, 'LSN')
tracestr = Trace.itrace(self.dot, 'LSN')
return (1, tracestr)
def i_DSF(self):
if self.displaycpu.ison():
self.PC = (self.PC + 1) & WORDMASK
tracestr = trace.itrace(self.dot, 'DSF')
tracestr = Trace.itrace(self.dot, 'DSF')
return (1, tracestr)
def i_DSN(self):
if not self.displaycpu.ison():
self.PC = (self.PC + 1) & WORDMASK
tracestr = trace.itrace(self.dot, 'DSN')
tracestr = Trace.itrace(self.dot, 'DSN')
return (1, tracestr)
def i_KSF(self):
if self.kbd.ready():
self.PC = (self.PC + 1) & WORDMASK
tracestr = trace.itrace(self.dot, 'KSF')
tracestr = Trace.itrace(self.dot, 'KSF')
return (1, tracestr)
def i_KSN(self):
if not self.kbd.ready():
self.PC = (self.PC + 1) & WORDMASK
tracestr = trace.itrace(self.dot, 'KSN')
tracestr = Trace.itrace(self.dot, 'KSN')
return (1, tracestr)
def i_RSF(self):
if self.ttyin.ready():
self.PC = (self.PC + 1) & WORDMASK
tracestr = trace.itrace(self.dot, 'RSF')
tracestr = Trace.itrace(self.dot, 'RSF')
return (1, tracestr)
def i_RSN(self):
if not self.ttyin.ready():
self.PC = (self.PC + 1) & WORDMASK
tracestr = trace.itrace(self.dot, 'RSN')
tracestr = Trace.itrace(self.dot, 'RSN')
return (1, tracestr)
def i_TSF(self):
if self.ttyout.ready():
self.PC = (self.PC + 1) & WORDMASK
tracestr = trace.itrace(self.dot, 'TSF')
tracestr = Trace.itrace(self.dot, 'TSF')
return (1, tracestr)
def i_TSN(self):
if not self.ttyout.ready():
self.PC = (self.PC + 1) & WORDMASK
tracestr = trace.itrace(self.dot, 'TSN')
tracestr = Trace.itrace(self.dot, 'TSN')
return (1, tracestr)
def i_SSF(self):
if self.display.ready(): # skip if 40Hz sync on
self.PC = (self.PC + 1) & WORDMASK
tracestr = trace.itrace(self.dot, 'SSF')
tracestr = Trace.itrace(self.dot, 'SSF')
return (1, tracestr)
def i_SSN(self):
if not self.display.ready():
self.PC = (self.PC + 1) & WORDMASK
tracestr = trace.itrace(self.dot, 'SSN')
tracestr = Trace.itrace(self.dot, 'SSN')
return (1, tracestr)
def i_HSF(self):
if self.ptrptp.ready():
self.PC = (self.PC + 1) & WORDMASK
tracestr = trace.itrace(self.dot, 'HSF')
tracestr = Trace.itrace(self.dot, 'HSF')
return (1, tracestr)
def i_HSN(self):
if not self.ptrptp.ready():
self.PC = (self.PC + 1) & WORDMASK
tracestr = trace.itrace(self.dot, 'HSN')
tracestr = Trace.itrace(self.dot, 'HSN')
return (1, tracestr)

View File

@@ -3,10 +3,18 @@ The Imlac trace stuff.
Simple usage:
import Trace
trace = Trace.Trace('my_log.log', maincpu, dispcpu)
trace.itrace(msg)
Trace.init('my_log.log', maincpu, dispcpu)
Trace.set_trace_map(map)
while running:
Trace.start()
Trace.itrace(inst_str)
Trace.dtrace(inst_str)
Trace.end()
Based on the 'borg' recipe from [http://code.activestate.com/recipes/66531/].
The idea is that trace system will handle formatting and writing trace data to
the trace file and the "main" code will perform the above steps. The
.endtrace() method will grab the register values after the instructions and
format the trace data and write it to the file.
"""
import os
@@ -18,150 +26,189 @@ import log
log = log.Log('test.log', log.Log.DEBUG)
class Trace(object):
Tracing = False
TrafeFilename = None
TraceFile = None
CPU = None
DCPU = None
TraceMap = None
CPUInst = None
DCPUInst = None
CPU_PC = None
DCPU_PC = None
__shared_state = {} # this __dict__ shared by ALL instances
def __init__(self, filename, maincpu=None, displaycpu=None):
"""Initialize the trace:
def init(filename, maincpu=None, displaycpu=None):
"""Initialize the trace:
filename name of the trace file
maincpu the main CPU object (may be added later)
displaycpu the display CPU object (may be added later)
"""
filename name of the trace file
maincpu the main CPU object (may be added later)
displaycpu the display CPU object (may be added later)
"""
# ensure same state as all other instances
self.__dict__ = Trace.__shared_state
global CPU, DCPU, TraceMap, CPUInst, DCPUInst
global TraceFile, TraceFilename
# set internal state
self.tracing = True
self.tracefile = filename
try:
os.remove(filename)
except:
pass
self.tracefile = open(filename, 'wb')
s = bytes('%s trace\n%s\n' % (PYMLAC_VERSION, '-'*60), 'utf-8')
self.tracefile.write(s)
# set internal state
Tracing = True
TraceFilename = filename
try:
os.remove(filename)
except:
pass
TraceFile = open(filename, 'w')
TraceFile.write(f"{PYMLAC_VERSION} trace\n{'-'*60}\n")
self.cpu = maincpu
self.dcpu = displaycpu
CPU = maincpu
DCPU = displaycpu
self.trace_map = collections.defaultdict(bool)
log(f'Trace.__init__: self.tracing={self.tracing}, self.tracefile={self.tracefile}')
TraceMap = collections.defaultdict(bool)
log(f'Trace.init: Tracing={Tracing}, TraceFilename={TraceFilename}')
def set_trace_map(self, trace_map):
"""Set the trace address dict mapping."""
CPUInst = None
DCPUInst = None
self.trace_map = trace_map
log(f'Trace.set_trace_map: self.trace_map={trace_map}')
def start():
"""Prepare trace system for new execution."""
def add_maincpu(self, maincpu):
"""Add the main CPU object."""
global CPU_PC, DCPU_PC, CPUInst, DCPUInst
self.cpu = maincpu
log(f'Trace.add_maincpu: self.cpu={maincpu}')
CPUInst = None
DCPUInst = None
CPU_PC = CPU.PC
DCPU_PC = DCPU.DPC
def add_displaycpu(self, dispcpu):
"""Add the display CPU object."""
def set_TraceMap(trace_map):
"""Set the trace address dict mapping."""
self.dcpu = dispcpu
log(f'Trace.add_displaycpu: self.dcpu={dispcpu}')
global TraceMap
def close(self):
"""Close trace."""
TraceMap = trace_map
log(f'Trace.set_TraceMap: TraceMap={TraceMap}')
self.tracefile.close()
self.tracing = False
self.tracefile = None
self.dcpu = dispcpu
log(f'Trace.close: self.tracing={self.tracing}')
def add_CPU(maincpu):
"""Add the main CPU object."""
def deimtrace(self, opcode, code):
"""Trace the DEIM instruction.
global CPU
opcode DEIM opcode
code the operation
"""
CPU = maincpu
log(f"deimtrace: self.tracing={self.tracing}, writing '{opcode} {code}'")
if self.tracing:
self.tracefile.write('%s\t%s\t' % (opcode, code))
self.tracefile.flush()
def add_DCPU(dispcpu):
"""Add the display CPU object."""
def dtrace(self, ddot, opcode, address=None):
"""Trace the display CPU.
global DCPU
DCPU = dispcpu
ddot address of instruction being traced
opcode display opcode
address address for the opcode
def close():
"""Close trace."""
Returns the trace string or None if not tracing.
"""
global TraceFile, Tracing
log(f'Trace.dtrace: self.tracing={self.tracing}')
result = None
# TraceFile.close()
TraceFile = None
Tracing = False
if self.tracing:
if address is None:
result = '%s: %s\t' % (ddot, opcode)
else:
result = '%04o: %s\t%5.5o' % (ddot, opcode, address)
def deimtrace(opcode, code):
"""Trace the DEIM instruction.
log(f"dtrace: result='{result}'")
return result
opcode DEIM opcode
code the operation
"""
def itrace(self, dot, opcode, indirect=False, address=None):
"""Main CPU trace.
log(f"deimtrace: Tracing={Tracing}, writing '{opcode} {code}'")
if Tracing:
TraceFile.write('%s\t%s\t' % (opcode, code))
TraceFile.flush()
dot address of instruction being traced
opcode the main CPU opcode
indirect True if instruction was indirect
address address for the instruction (if any)
def dtrace(ddot, opcode, address=None):
"""Trace the display CPU.
Returns the trace string or None if not tracing.
"""
ddot address of instruction being traced
opcode display opcode
address address for the opcode
# log(f'Trace.itrace: self.tracing={self.tracing}, self.trace_map={self.trace_map}')
result = None
Returns the trace string or None if not tracing.
"""
if self.tracing and self.trace_map[dot]:
char = '*' if indirect else ''
if address is None:
result = '%04o\t%s\t%s' % (dot, opcode, char)
else:
result = '%04o\t%s\t%s%5.5o' % (dot, opcode, char, address)
log(f'Trace.dtrace: Tracing={Tracing}')
result = None
return result
if Tracing:
if address is None:
result = '%s: %s\t' % (ddot, opcode)
else:
result = '%04o: %s\t%5.5o' % (ddot, opcode, address)
def itraceend(self, dispon):
"""Trace at the end of one execution cycle.
log(f"dtrace: result='{result}'")
DCPUInst = result
return result
dispon True if the display was on
def itrace(dot, opcode, indirect=False, address=None):
"""Main CPU trace.
Returns the trace string.
"""
dot address of instruction being traced
opcode the main CPU opcode
indirect True if instruction was indirect
address address for the instruction (if any)
result = ('L=%1.1o AC=%6.6o PC=%6.6o'
% (self.cpu.L, self.cpu.AC, self.cpu.PC))
Returns the trace string or None if not tracing.
"""
if dispon:
result += ' DX=%5.5o DY=%5.5o' % (self.dcpu.DX, self.dcpu.DY)
result = None
return result
if Tracing and TraceMap[dot]:
char = '*' if indirect else ''
if address is None:
result = '%04o\t%s\t%s' % (dot, opcode, char)
else:
result = '%04o\t%s\t%s%5.5o' % (dot, opcode, char, address)
def flush(self):
self.tracefile.flush()
log(f"itrace: result='{result}'")
CPUInst = result
return result
def comment(self, msg):
"""Write a line to the trace file."""
def itraceend(dispon):
"""Trace at the end of one execution cycle.
msg = bytes(msg+'\n', 'utf-8')
self.tracefile.write(msg)
self.tracefile.flush()
dispon True if the display was on
def settrace(self, new_tracing):
"""Set the trace ON or OFF."""
Returns the trace string.
"""
self.tracing = new_tracing
log(f'Trace.settrace: self.tracing={new_tracing}')
result = ('L=%1.1o AC=%6.6o PC=%6.6o' % (CPU.L, CPU.AC, CPU.PC))
if dispon:
result += ' DX=%5.5o DY=%5.5o' % (DCPU.DX, DCPU.DY)
return result
def end_line():
"""Write the line for this set of I/D instructions."""
registers = ('L=%1.1o AC=%6.6o PC=%6.6o' % (CPU.L, CPU.AC, CPU.PC))
if DCPU.Running:
registers += ' DX=%5.5o DY=%5.5o' % (DCPU.DX, DCPU.DY)
CPUInst = None
DCPUInst = None
#TraceFile.write(f'{CPUInst:-50s}{DCPUInst:-40s} {registers}\n')
TraceFile.write('%-50s %-40s %s\n' % (CPUInst, DCPUInst, registers))
#def flush(self):
# TraceFile.flush()
def comment(msg):
"""Write a line to the trace file."""
TraceFile.write(msg + '\n')
TraceFile.flush()
def settrace(new_tracing):
"""Set the trace ON or OFF."""
global Tracing
Tracing = new_tracing
log(f'Trace.settrace: Tracing={Tracing}')

View File

@@ -1,7 +1,7 @@
#!/usr/bin/env python3
"""
A simulator for an Imlac PDS-1 or PDS-4.
A simulator for an Imlac PDS-1.
Usage: pymlac [ <option> ]*
@@ -50,8 +50,6 @@ import Trace
import log
log = log.Log('test.log', log.Log.DEBUG)
trace = Trace.Trace(TRACE_FILENAME)
def str2int(s):
"""Convert a string to an integer value.
@@ -85,18 +83,27 @@ def usage(msg=None):
def start_running(cpu, dcpu, memory, ptrptp, ttyin):
"""Run the Imlac machine until it stops."""
Trace.init('pymlac.trace', cpu, dcpu)
cpu.running = True
while cpu.running:
Trace.start()
log(f'cpu.PC={cpu.PC}')
(cycles, tracestr) = cpu.execute_one_instruction()
log(f"start_running: cpu.execute_one_instruction returned ({cycles}, '{tracestr}')")
if tracestr:
endstr = trace.itraceend(False)
#Trace.itrace(tracestr)
(dcycles, dtracestr) = dcpu.execute_one_instruction()
log(f"start_running: dcpu.execute_one_instruction returned ({dcycles}, '{dtracestr}')")
#Trace.dtrace(dtracestr)
ptrptp.ptr_tick(cycles)
ptrptp.ptp_tick(cycles)
ttyin.tick(cycles)
Trace.end_line()
Trace.close()
def main():
"""Main function of the simulator. Mostly interpret CLI args."""
@@ -115,8 +122,8 @@ def main():
imlac_display_state = False
# prepare the trace
trace.add_maincpu(imlac_cpu)
trace.add_displaycpu(imlac_dcpu)
Trace.add_CPU(imlac_cpu)
Trace.add_DCPU(imlac_dcpu)
# trace_map defines addresses we are tracing at
# initially, no tracing
@@ -196,7 +203,7 @@ def main():
log('Running from address %06o' % addr_value)
else:
log('Running from current PC %06o' % imlac_cpu.PC)
trace.set_trace_map(trace_map)
Trace.set_TraceMap(trace_map)
start_running(imlac_cpu, imlac_dcpu, imlac_memory, imlac_ptrptp, imlac_ttyin)
elif opt == '-s':
if ndx >= len_sys_argv:

View File

@@ -5,7 +5,6 @@ Usage: test_Display.py [-h]
"""
#import wx
import Display
# if we don't have log.py, don't crash
@@ -17,79 +16,6 @@ except ImportError:
pass
######
# Various demo constants
######
WindowTitleHeight = 22
DefaultAppSize = (600, 600+WindowTitleHeight)
#################################################################################
## The main application frame
#################################################################################
#
#class TestFrame(wx.Frame):
# def __init__(self):
# wx.Frame.__init__(self, None, size=DefaultAppSize,
# title=('Test pymlac display - %s'
# % Display.__version__))
# self.SetMinSize(DefaultAppSize)
# self.panel = wx.Panel(self, wx.ID_ANY)
# self.panel.ClearBackground()
#
# # build the GUI
# box = wx.BoxSizer(wx.VERTICAL)
# self.display = Display.Display(self.panel)
# box.Add(self.display, proportion=1, border=1, flag=wx.EXPAND)
# self.panel.SetSizer(box)
# self.panel.Layout()
# self.Centre()
# self.Show(True)
#
# self.Bind(wx.EVT_SIZE, self.OnSize)
#
# self.lock = False
#
# self.Refresh()
#
# self.display.draw(0, 0, 1024, 1024)
# self.display.draw(1024, 0, 0, 1024)
# self.display.draw(512, 0, 1024, 512)
# self.display.draw(1024, 512, 512, 1024)
# self.display.draw(512, 1024, 0, 512)
# self.display.draw(0, 512, 512, 0)
#
## self.display.draw(0, 0, 1023, 1023)
## self.display.draw(1023, 0, 0, 1023)
## self.display.draw(511, 0, 1023, 511)
## self.display.draw(1023, 511, 511, 1023)
## self.display.draw(511, 1023, 0, 511)
## self.display.draw(0, 511, 511, 0)
#
# for x in (0, 256, 512, 768, 1024):
# self.display.draw(x, 0, x, 1024, dotted=True)
#
# for y in (0, 256, 512, 768, 1024):
# self.display.draw(0, y, 1024, y, dotted=True)
#
## for x in (0, 255, 511, 766, 1023):
## self.display.draw(x, 0, x, 1023, dotted=True)
##
## for y in (0, 255, 511, 766, 1023):
## self.display.draw(0, y, 1023, y, dotted=True)
#
# def OnSize(self, event):
# """Maintain square window."""
#
# if not self.lock:
# self.lock = True
# (w, h) = event.GetSize()
# size = min(w, h)
# self.SetSize((size-WindowTitleHeight, size))
# self.lock = False
#
# event.Skip()
def test():
display = Display.Display()
display.draw(0, 0, 1023, 1023)