1
0
mirror of https://github.com/rzzzwilson/pymlac.git synced 2025-06-10 09:32:41 +00:00
Files
rzzzwilson.pymlac/pymlac/Trace.py
2018-07-25 13:58:57 +07:00

209 lines
4.7 KiB
Python

"""
The Imlac trace stuff.
Simple usage:
import Trace
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()
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
import collections
from Globals import *
import log
log = log.Log('test.log', log.Log.DEBUG)
Tracing = False
TrafeFilename = None
TraceFile = None
CPU = None
DCPU = None
TraceMap = collections.defaultdict(bool)
CPUInst = ''
DCPUInst = ''
CPU_PC = None
DCPU_PC = None
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)
"""
global Tracing, TraceFile, TraceFilename, TraceMap
global CPU, DCPU, CPUInst, DCPUInst
# set internal state
Tracing = True
TraceFilename = filename
try:
os.remove(filename)
except:
pass
TraceFile = open(filename, 'w')
TraceFile.write(f"{PYMLAC_VERSION} trace\n{'-'*97}\n")
CPU = maincpu
DCPU = displaycpu
def start():
"""Prepare trace system for new execution."""
global CPU_PC, DCPU_PC, CPUInst, DCPUInst
CPUInst = ''
DCPUInst = ''
CPU_PC = CPU.PC
DCPU_PC = DCPU.DPC
def set_TraceMap(trace_map):
"""Set the trace address dict mapping."""
global TraceMap
TraceMap = trace_map
log(f'Trace.set_TraceMap: TraceMap={TraceMap}')
def add_CPU(maincpu):
"""Add the main CPU object."""
global CPU
CPU = maincpu
def add_DCPU(dispcpu):
"""Add the display CPU object."""
global DCPU
DCPU = dispcpu
def close():
"""Close trace."""
global TraceFile, Tracing
# TraceFile.close()
TraceFile = None
Tracing = False
#def deimtrace(opcode, code):
# """Trace the DEIM instruction.
#
# opcode DEIM opcode
# code the operation
# """
#
# log(f"deimtrace: Tracing={Tracing}, writing '{opcode} {code}'")
# if Tracing:
# TraceFile.write('%s %s\t' % (opcode, code))
# TraceFile.flush()
def dtrace(ddot, opcode, address=None):
"""Trace the display CPU.
ddot address of instruction being traced
opcode display opcode
address address for the opcode
Places the final trace string into DCPUInst.
"""
global DCPUInst
log(f'Trace.dtrace: ddot={ddot}, opcode={opcode}, address={address}')
# convert an int address to a string
if isinstance(address, int):
address = f'{address:05o}'
if Tracing:
if address is None:
DCPUInst = '%04o %s' % (ddot, opcode)
else:
DCPUInst = '%04o %s %s' % (ddot, opcode, address)
log(f"dtrace: DCPUInst='{DCPUInst}'")
def itrace(dot, opcode, indirect=False, address=None):
"""Main CPU trace.
dot address of instruction being traced
opcode the main CPU opcode
indirect True if instruction was indirect
address address for the instruction (if any)
Places the final trace string in CPUInst.
"""
global CPUInst
log(f'itrace: dot={dot}, opcode={opcode}, indirect={indirect}, address={address}')
log(f'itrace: Tracing={Tracing}, TraceMap[dot]={TraceMap[dot]}')
if Tracing and TraceMap[dot]:
char = '*' if indirect else ''
if address is None:
CPUInst = '%04o %s %s' % (dot, opcode, char)
else:
CPUInst = '%04o %s %s%5.5o' % (dot, opcode, char, address)
log(f"itrace: CPUInst='{CPUInst}'")
#def itraceend(dispon):
# """Trace at the end of one execution cycle.
#
# dispon True if the display was on
#
# Places the final trace string in DCPUInst.
# """
#
# global DCPUInst
#
# DCPUInst = f'L={CPU.L:1.1o} AC={CPU.AC:6.6oi} PC={CPU.PC:6.6o}'
#
# if dispon:
# DCPUInst += ' DX=%5.5o DY=%5.5o' % (DCPU.DX, DCPU.DY)
def end_line():
"""Write the line for this set of I/D instructions."""
registers = f'L={CPU.L:1o} AC={CPU.AC:6o} PC={CPU.PC:6o}'
if DCPU.Running:
registers += f' DX={DCPU.DX:5o} DY={DCPU.DY:5o}'
TraceFile.write('%-25s %-30s%s\n' % (CPUInst, DCPUInst, registers))
def flush():
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}')