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

Still moving toward running

This commit is contained in:
Ross Wilson
2015-06-22 18:51:55 +07:00
parent 4d5496ea33
commit 09030ac2d7
6 changed files with 600 additions and 582 deletions

View File

@@ -54,6 +54,9 @@ class _BufferedCanvas(wx.Panel):
style wxPython style
"""
print('__init__: self=%s' % str(self))
print('__init__: parent=%s' % str(parent))
wx.Panel.__init__(self, parent, id, pos, size, style)
# Bind events

View File

@@ -11,320 +11,289 @@ from Globals import *
import Trace
# display CPU constants
MODE_NORMAL = 0
MODE_DEIM = 1
class DisplayCPU(object):
######
# The Display CPU registers
######
# display CPU constants
MODE_NORMAL = 0
MODE_DEIM = 1
DPC = 0 # display CPU program counter
DRS = [0, 0, 0, 0, 0, 0, 0, 0] # display CPU ???
DRSindex = 0 # display CPU ???
DIB = 0 # display CPU ???
DX = 0 # display CPU draw X register
DY = 0 # display CPU draw Y register
######
# The Display CPU registers
######
# global state variables
Mode = MODE_NORMAL
Running = False
def init():
global Mode, Running
DPC = 0 # display CPU program counter
DRS = [0, 0, 0, 0, 0, 0, 0, 0] # display CPU ???
DRSindex = 0 # display CPU ???
DIB = 0 # display CPU ???
DX = 0 # display CPU draw X register
DY = 0 # display CPU draw Y register
# global state variables
Mode = MODE_NORMAL
Running = False
def DEIMdecode(byte):
"""Decode a DEIM byte"""
result = ''
if byte & 0x80:
if byte & 0x40: result += 'B'
else: result += 'D'
if byte & 0x20: result += '-'
result += '%d' % ((byte >> 3) & 0x03)
if byte & 0x04: result += '-'
result += '%d' % (byte & 0x03)
else:
if byte == 0111: result += 'N'
elif byte == 0151: result += 'R'
elif byte == 0171: result += 'F'
elif byte == 0200: result += 'P'
else: result += 'A%3.3o' % byte
return result
def __init__(self, display, memory):
self.Mode = self.MODE_NORMAL
self.Running = False
def doDEIMByte(byte):
global DPC, DX, DY, DRSindex
global Mode
self.display = display
self.memory = memory
if byte & 0x80: # increment?
prevDX = DX
prevDY = DY
if byte & 0x20:
DX -= (byte & 0x18) >> 3
def DEIMdecode(self, byte):
"""Decode a DEIM byte"""
result = ''
if byte & 0x80:
if byte & 0x40: result += 'B'
else: result += 'D'
if byte & 0x20: result += '-'
result += '%d' % ((byte >> 3) & 0x03)
if byte & 0x04: result += '-'
result += '%d' % (byte & 0x03)
else:
DX += (byte & 0x18) >> 3
if byte & 0x04:
DY -= (byte & 0x03)
else:
DY += (byte & 0x03)
if byte == 0111: result += 'N'
elif byte == 0151: result += 'R'
elif byte == 0171: result += 'F'
elif byte == 0200: result += 'P'
else: result += 'A%3.3o' % byte
return result
def doDEIMByte(self, byte):
if byte & 0x80: # increment?
prevDX = self.DX
prevDY = self.DY
if byte & 0x20:
self.DX -= (byte & 0x18) >> 3
else:
self.DX += (byte & 0x18) >> 3
if byte & 0x04:
self.DY -= (byte & 0x03)
else:
self.DY += (byte & 0x03)
if byte & 0x40:
self.display.draw(prevDX, prevDY, self.DX, self.DY)
else: # micro instructions
if byte & 0x40:
display.draw(prevDX, prevDY, DX, DY)
else: # micro instructions
if byte & 0x40:
Mode = MODE_NORMAL
if byte & 0x20: # DRJM
if DRSindex <= 0:
Trace.comment('\nDRS stack underflow at display address %6.6o'
% (DPC - 1))
illegal()
DRSindex -= 1
DPC = DRS[DRSindex]
if byte & 0x10:
DX += 0x08
if byte & 0x08:
DX &= 0xfff8
if byte & 0x02:
DY += 0x10
if byte & 0x01:
DY &= 0xfff0
self.Mode = self.self.MODE_NORMAL
if byte & 0x20: # DRJM
if self.DRSindex <= 0:
Trace.comment('\nDRS stack underflow at display address %6.6o'
% (self.DPC - 1))
self.illegal()
self.DRSindex -= 1
self.DPC = DRS[DRSindex]
if byte & 0x10:
self.DX += 0x08
if byte & 0x08:
self.DX &= 0xfff8
if byte & 0x02:
self.DY += 0x10
if byte & 0x01:
self.DY &= 0xfff0
def execute_one_instruction():
global DPC
global Mode
def execute_one_instruction(self):
if not self.Running:
Trace.dtrace('')
return 0
if not Running:
Trace.dtrace('')
return 0
instruction = self.memory.get(self.DPC, 0)
self.DPC = MASK_MEM(self.DPC + 1)
instruction = Memory.get(DPC, 0)
DPC = MASK_MEM(DPC + 1)
if self.Mode == self.MODE_DEIM:
Trace.trace(self.DEIMdecode(instruction >> 8) + '\t')
self.doDEIMByte(instruction >> 8)
if self.Mode == self.MODE_DEIM:
Trace.trace(self.DEIMdecode(instruction & 0xff) + '\t')
self.doDEIMByte(instruction & 0xff)
else:
Trace.trace('\t')
return 1
if Mode == MODE_DEIM:
Trace.trace(DEIMdecode(instruction >> 8) + '\t')
doDEIMByte(instruction >> 8)
if Mode == MODE_DEIM:
Trace.trace(DEIMdecode(instruction & 0xff) + '\t')
doDEIMByte(instruction & 0xff)
opcode = instruction >> 12
address = instruction & 007777
if opcode == 000: return self.page00(instruction)
elif opcode == 001: return self.i_DLXA(address)
elif opcode == 002: return self.i_DLYA(address)
elif opcode == 003: return self.i_DEIM(address)
elif opcode == 004: return self.i_DLVH(address)
elif opcode == 005: return self.i_DJMS(address)
elif opcode == 006: return self.i_DJMP(address)
elif opcode == 007: self.illegal(instruction)
else: self.illegal(instruction)
def illegal(self, instruction=None):
if instruction:
Trace.comment('Illegal display instruction (%6.6o) at address %6.6o'
% (instruction, (self.DPC - 1)))
else:
Trace.trace('\t')
Trace.comment('Illegal display instruction at address %6.6o'
% (self.DPC - 1))
sys.exit(0)
def ison(self):
return self.Running
def i_DDXM(self):
self.DX -= 040
Trace.dtrace('DDXM')
def i_DDYM(self):
self.DY -= 040
Trace.dtrace('DDYM')
def i_DEIM(self, address):
self.Mode = self.MODE_DEIM
Trace.deimtrace('DEIM', self.DEIMdecode(address & 0377))
self.doDEIMByte(address & 0377)
return 1
opcode = instruction >> 12
address = instruction & 007777
def i_DHLT(self):
self.Running = False
Trace.dtrace('DHLT')
if opcode == 000: return page00(instruction)
elif opcode == 001: return i_DLXA(address)
elif opcode == 002: return i_DLYA(address)
elif opcode == 003: return i_DEIM(address)
elif opcode == 004: return i_DLVH(address)
elif opcode == 005: return i_DJMS(address)
elif opcode == 006: return i_DJMP(address)
elif opcode == 007: illegal(instruction)
else: illegal(instruction)
def i_DHVC(self):
Trace.dtrace('DHVC')
def illegal(instruction=None):
if instruction:
Trace.comment('Illegal display instruction (%6.6o) at address %6.6o'
% (instruction, (DPC - 1)))
else:
Trace.comment('Illegal display instruction at address %6.6o'
% (DPC - 1))
sys.exit(0)
def i_DIXM(self):
self.DX += 04000
Trace.dtrace('DIXM')
def ison():
return Running
def i_DIYM(self):
self.DY += 04000
Trace.dtrace('DIYM')
def i_DDXM():
global DX
def i_DJMP(self, address):
self.DPC = MASK_MEM(address + (self.DIB << 12))
Trace.dtrace('DJMP', address)
return 1
DX -= 040
Trace.dtrace('DDXM')
def i_DJMS(self, address):
if self.DRSindex >= 8:
Trace.comment('DRS stack overflow at display address %6.6o'
% (self.DPC - 1))
self.illegal()
self.DRS[self.DRSindex] = self.DPC
self.DRSindex += 1
self.DPC = MASK_MEM(address + (self.DIB << 12))
Trace.dtrace('DJMS', address)
return 1
def i_DDYM():
global DY
def i_DLXA(self, address):
self.DX = address
Trace.dtrace('DLXA', address)
return 1
DY -= 040
Trace.dtrace('DDYM')
def i_DLYA(self, address):
self.DY = address
Trace.dtrace('DLYA', address)
return 1
def i_DEIM(address):
global Mode
def i_DLVH(self, word1):
word2 = self.memory.get(self, DPC, 0)
self.DPC = MASK_MEM(self.DPC + 1)
word3 = self.memory.get(self.DPC, 0)
self.DPC = MASK_MEM(self.DPC + 1)
Mode = MODE_DEIM
Trace.deimtrace('DEIM', DEIMdecode(address & 0377))
doDEIMByte(address & 0377)
return 1
dotted = word2 & 040000
beamon = word2 & 020000
negx = word3 & 040000
negy = word3 & 020000
ygtx = word3 & 010000
def i_DHLT():
Running = False
Trace.dtrace('DHLT')
M = word2 & 007777
N = word3 & 007777
def i_DHVC():
Trace.dtrace('DHVC')
prevDX = self.DX
prevDY = self.DY
def i_DIXM():
global DX
if ygtx: # M is y, N is x
if negx:
self.DX -= N
else:
self.DX += N
if negy:
self.DY -= M
else:
self.DY += M
else: # M is x, N is y
if negx:
self.DX -= M
else:
self.DX += M
if negy:
self.DY -= N
else:
self.DY += N
DX += 04000
Trace.dtrace('DIXM')
self.display.draw(prevDX, prevDY, self.DX, self.DY, dotted)
Trace.dtrace('DLVH')
return 3
def i_DIYM():
global DY
def i_DRJM(self):
if self.DRSindex <= 0:
Trace.comment('DRS stack underflow at display address %6.6o'
% (self.DPC - 1))
self.illegal()
self.DRSindex -= 1
self.DPC = self.DRS[self.DRSindex]
Trace.dtrace('DRJM')
return 1 # FIXME check # cycles used
DY += 04000
Trace.dtrace('DIYM')
def i_DSTB(self, block):
self.DIB = block
Trace.dtrace('DSTB\t%d' % block)
def i_DJMP(address):
global DPC, DIB
DPC = MASK_MEM(address + (DIB << 12))
Trace.dtrace('DJMP', address)
return 1
def i_DJMS(address):
global DPC, DRSindex, DIB
if DRSindex >= 8:
Trace.comment('DRS stack overflow at display address %6.6o'
% (DPC - 1))
illegal()
DRS[DRSindex] = DPC
DRSindex += 1
DPC = MASK_MEM(address + (DIB << 12))
Trace.dtrace('DJMS', address)
return 1
def i_DLXA(address):
global DX
DX = address
Trace.dtrace('DLXA', address)
return 1
def i_DLYA(address):
global DY
DY = address
Trace.dtrace('DLYA', address)
return 1
def i_DLVH(word1):
global DPC, DX, DY
word2 = Memory.get(DPC, 0)
DPC = MASK_MEM(DPC + 1)
word3 = Memory.get(DPC, 0)
DPC = MASK_MEM(DPC + 1)
dotted = word2 & 040000
beamon = word2 & 020000
negx = word3 & 040000
negy = word3 & 020000
ygtx = word3 & 010000
M = word2 & 007777
N = word3 & 007777
prevDX = DX
prevDY = DY
if ygtx: # M is y, N is x
if negx:
DX -= N
def i_DSTS(self, scale):
if scale == 0:
self.Scale = 0.5
elif scale == 1:
self.Scale = 1.0
elif scale == 2:
self.Scale = 2.0
elif scale == 3:
self.Scale = 3.0
else:
DX += N
if negy:
DY -= M
self.illegal()
Trace.dtrace('DSTS', scale)
return 1 # FIXME check # cycles used
def page00(self, instruction):
if instruction == 000000: # DHLT
self.i_DHLT()
elif instruction == 004000: # DNOP
Trace.dtrace('DNOP')
elif instruction == 004004: # DSTS 0
self.i_DSTS(0)
elif instruction == 004005: # DSTS 1
self.i_DSTS(1)
elif instruction == 004006: # DSTS 2
self.i_DSTS(2)
elif instruction == 004007: # DSTS 3
self.i_DSTS(3)
elif instruction == 004010: # DSTB 0
self.i_DSTB(0)
elif instruction == 004011: # DSTB 1
self.i_DSTB(1)
elif instruction == 004040: # DRJM
self.i_DRJM()
elif instruction == 004100: # DDYM
self.i_DDYM()
elif instruction == 004200: # DDXM
self.i_DDXM()
elif instruction == 004400: # DIYM
self.i_DIYM()
elif instruction == 005000: # DIXM
self.i_DIXM()
elif instruction == 006000: # DHVC
self.i_DHVC()
else:
DY += M
else: # M is x, N is y
if negx:
DX -= M
else:
DX += M
if negy:
DY -= N
else:
DY += N
self.illegal(instruction)
return 1
display.draw(prevDX, prevDY, DX, DY, dotted)
Trace.dtrace('DLVH')
return 3
def start(self):
self.Running = True
def i_DRJM():
global DPC, DRSindex
if DRSindex <= 0:
Trace.comment('DRS stack underflow at display address %6.6o'
% (DPC - 1))
illegal()
DRSindex -= 1
DPC = DRS[DRSindex]
Trace.dtrace('DRJM')
def i_DSTB(block):
global DIB
DIB = block
Trace.dtrace('DSTB\t%d' % block)
def i_DSTS(scale):
global Scale
if scale == 0:
Scale = 0.5
elif scale == 1:
Scale = 1.0
elif scale == 2:
Scale = 2.0
elif scale == 3:
Scale = 3.0
else:
illegal()
Trace.dtrace('DSTS', scale)
def page00(instruction):
if instruction == 000000: # DHLT
i_DHLT()
elif instruction == 004000: # DNOP
Trace.dtrace('DNOP')
elif instruction == 004004: # DSTS 0
i_DSTS(0)
elif instruction == 004005: # DSTS 1
i_DSTS(1)
elif instruction == 004006: # DSTS 2
i_DSTS(2)
elif instruction == 004007: # DSTS 3
i_DSTS(3)
elif instruction == 004010: # DSTB 0
i_DSTB(0)
elif instruction == 004011: # DSTB 1
i_DSTB(1)
elif instruction == 004040: # DRJM
i_DRJM()
elif instruction == 004100: # DDYM
i_DDYM()
elif instruction == 004200: # DDXM
i_DDXM()
elif instruction == 004400: # DIYM
i_DIYM()
elif instruction == 005000: # DIXM
i_DIXM()
elif instruction == 006000: # DHVC
i_DHVC()
else:
illegal(instruction)
return 1
def start():
global Running
Running = True
def stop():
global Running
Running = False
def stop(self):
self.Running = False

View File

@@ -101,7 +101,7 @@ class Memory(object):
if self.corefile:
try:
loadcore(self.corefile)
self.loadcore(self.corefile)
except IOError:
self.clear_core()
else:

View File

@@ -8,16 +8,16 @@ The Imlac trace stuff.
import time
from Globals import *
import MainCPU
import DisplayCPU
# module-level state variables
tracing = False
tracefile = None
cpu = None
dcpu = None
def init(filename):
global tracing, tracefile
def init(filename, maincpu, displaycpu):
global tracing, tracefile, cpu, dcpu
tracing = True
tracefile = open(filename, 'w')
@@ -25,6 +25,9 @@ def init(filename):
tracing = False
comment = None
cpu = maincpu
dcpu = displaycpu
def close():
import tracing, tracefile
@@ -58,9 +61,9 @@ def itrace(opcode, indirect=False, address=None):
def itraceend(dispon):
if dispon:
trace('L=%1.1o AC=%6.6o DX=%5.5o DY=%6.6o\n' %
(MainCPU.L, MainCPU.AC, DisplayCPU.DX, DisplayCPU.DY))
(cpu.L, cpu.AC, dcpu.DX, dcpu.DY))
else:
trace('L=%1.1o AC=%6.6o\n' % (MainCPU.L, MainCPU.AC))
trace('L=%1.1o AC=%6.6o\n' % (cpu.L, cpu.AC))
def comment(msg):
tracefile.write(msg+'\n')

View File

@@ -169,7 +169,7 @@ class Log(object):
except ValueError:
mod_name = __name__
for (fpath, lnum, mname, _) in frames:
(fname, _) = os.path.basename(fpath).rsplit('.', 1)
fname = os.path.basename(fpath).rsplit('.', 1)[0]
if fname != mod_name:
break

View File

@@ -30,8 +30,9 @@ from threading import *
import wx
import Display
import DisplayCPU
from Globals import *
import Imlac
#import Imlac
import Memory
import Ptr
@@ -251,15 +252,15 @@ def main():
# Initialize the emulator.
boot_rom = 'ptr' # default ROM loader
Imlac.init(0, TRACE_FILENAME, None, None, boot_rom, CORE_FILENAME)
# Imlac.init(0, TRACE_FILENAME, None, None, boot_rom, CORE_FILENAME)
# now perform operations
for (operation, args) in ops:
if operation == 'boot':
Memory.set_ROM(args)
self.memory.set_ROM(args)
Trace.comment('Bootstrap ROM set to %s' % args.upper())
elif operation == 'clear':
Memory.clear_core()
self.memory.clear_core()
Trace.comment('Core cleared')
elif operation == 'load_ptp':
Ptp.mount(args)
@@ -273,29 +274,31 @@ def main():
elif operation == 'run':
MainCPU.PC = args
Trace.comment('Running from address %06o' % args)
if Imlac.tracestart:
Trace.comment('DPC\tDisplay\t\tPC\tMain\t\tRegs')
Trace.comment('------ ------------- ------ -------------- '
# if Imlac.tracestart:
Trace.comment('DPC\tDisplay\t\tPC\tMain\t\tRegs')
Trace.comment('------ ------------- ------ -------------- '
'-----------------------')
Imlac.run()
self.run()
# Imlac.run()
Trace.comment('Imlac halted')
elif operation == 'set':
Trace.comment("Setting memory from file '%s'" % args)
elif operation == 'trace':
if args == 'off':
Imlac.tracestart = None
Imlac.traceend = None
# Imlac.tracestart = None
# Imlac.traceend = None
pass
else:
(start, end) = args
Imlac.tracestart = start
Imlac.traceend = end
tstart = Imlac.tracestart
if tstart is not None:
tstart = '%06o' % tstart
tend = Imlac.traceend
if tend is not None:
tend = '%06o' % tend
Trace.comment('Trace set to (%s, %s)' % (tstart, tend))
# Imlac.tracestart = start
# Imlac.traceend = end
# tstart = Imlac.tracestart
# if tstart is not None:
# tstart = '%06o' % tstart
# tend = Imlac.traceend
# if tend is not None:
# tend = '%06o' % tend
# Trace.comment('Trace set to (%s, %s)' % (tstart, tend))
elif operation == 'ttyin':
TtyIn.mount(args)
Trace.comment("File '%s' mounted on TTYIN" % args)
@@ -306,16 +309,16 @@ def main():
Trace.comment("Viewing memory from file '%s'" % args)
elif operation == 'write':
if args == 'on':
Memory.using_rom = True
self.memory.using_rom = True
elif args == 'off':
Memory.using_rom = False
self.memory.using_rom = False
else:
abort("Invalid view arg: %s" % args)
Trace.comment('ROM write protect set %s' % args.upper())
else:
abort('Invalid internal operation: %s' % operation)
Imlac.close(CORE_FILENAME)
# Imlac.close(CORE_FILENAME)
class Led_1(object):
def __init__(self, parent, label, x, y, off, on):
@@ -364,255 +367,255 @@ class Led_16(object):
mask = mask >> 1
class PymlacFrame(wx.Frame):
"""a frame with two panels"""
WIDTH_SCREEN = 1024
HEIGHT_SCREEN = 1024
WIDTH_CONSOLE = 330 # 400 # 256
HEIGHT_CONSOLE = HEIGHT_SCREEN
SCREEN_COLOUR = (0, 0, 0)
CONSOLE_COLOUR = (255, 223, 169)
PHOSPHOR_COLOUR = '#F0F000' # yellow
#PHOSPHOR_COLOUR = '#40FF40' # green
V_MARGIN = 20
CTL_MARGIN = 15
LED_MARGIN = 5
IMAGE_LED_OFF = 'images/led_off.png'
IMAGE_LED_ON = 'images/led_on.png'
INC = 0.01
def __init__(self, parent=None, id=-1, title=None):
wx.Frame.__init__(self, parent, id, title)
self.make_gui()
self.run()
def make_gui(self):
self.screen = wx.Panel(self,
size=(self.WIDTH_SCREEN, self.HEIGHT_SCREEN),
pos=(0,0))
self.screen.SetBackgroundColour(self.SCREEN_COLOUR)
self.console = wx.Panel(self, style=wx.SIMPLE_BORDER,
size=(self.WIDTH_CONSOLE, self.HEIGHT_SCREEN),
pos=(self.WIDTH_SCREEN,0))
self.console.SetBackgroundColour(self.CONSOLE_COLOUR)
python_png = wx.Image('images/PythonPowered.png',
wx.BITMAP_TYPE_PNG).ConvertToBitmap()
python_height = python_png.GetHeight()
python_width = python_png.GetWidth()
wxpython_png = wx.Image('images/wxPython2.png',
wx.BITMAP_TYPE_PNG).ConvertToBitmap()
wxpython_height = wxpython_png.GetHeight()
wxpython_width = wxpython_png.GetWidth()
h_margin = (self.WIDTH_CONSOLE - wxpython_width - python_width) / 3
png_height = max(python_height, wxpython_height) + self.V_MARGIN
v_margin = (png_height - python_height)/2
python_ypos = self.HEIGHT_CONSOLE - png_height + v_margin
v_margin = (png_height - wxpython_height)/2
wxpython_ypos = self.HEIGHT_CONSOLE - png_height + v_margin
wx.StaticBitmap(self.console, -1, python_png,
pos=(h_margin, python_ypos))
wx.StaticBitmap(self.console, -1, wxpython_png,
pos=(python_width + 2*h_margin, wxpython_ypos))
self.png_height = png_height
led_off = wx.Image('images/led_off.png',
wx.BITMAP_TYPE_PNG).ConvertToBitmap()
led_on = wx.Image('images/led_on.png',
wx.BITMAP_TYPE_PNG).ConvertToBitmap()
y_pos = 8
self.led_l = Led_1(self.console, 'l', self.CTL_MARGIN, y_pos,
led_off, led_on)
self.led_ac = Led_16(self.console, 'ac', 3*self.CTL_MARGIN, y_pos,
led_off, led_on)
y_pos += 35
self.led_pc = Led_16(self.console, 'pc', 3*self.CTL_MARGIN, y_pos,
led_off, led_on)
y_pos = 305
wx.StaticText(self.console, -1, 'ptr', pos=(self.CTL_MARGIN, y_pos))
y_pos += 15
self.txt_ptrFile = wx.TextCtrl(self.console, -1,
pos=(self.CTL_MARGIN, y_pos),
size=(self.WIDTH_CONSOLE-2*self.CTL_MARGIN, 25))
y_pos += 30
wx.StaticText(self.console, -1, 'ptp', pos=(self.CTL_MARGIN, y_pos))
y_pos += 15
self.txt_ptpFile = wx.TextCtrl(self.console, -1,
pos=(self.CTL_MARGIN, y_pos),
size=(self.WIDTH_CONSOLE-2*self.CTL_MARGIN, 25))
y_pos += 15
dc = wx.PaintDC(self.console)
dc.SetPen(wx.Pen('black', 1))
dc.DrawLine(0, self.HEIGHT_CONSOLE - self.png_height,
self.WIDTH_CONSOLE-1, self.HEIGHT_CONSOLE - self.png_height)
for (x, y) in self.led_ac.ticks:
dc.DrawLine(x, y, x, y+5)
first = self.led_ac.ticks[0]
last = self.led_ac.ticks[-1]
(x1, y1) = first
(x2, y2) = last
dc.DrawLine(x1, y2+5, x2, y2+5)
for (x, y) in self.led_pc.ticks:
dc.DrawLine(x, y, x, y+5)
first = self.led_pc.ticks[0]
last = self.led_pc.ticks[-1]
(x1, y1) = first
(x2, y2) = last
dc.DrawLine(x1, y2+5, x2, y2+5)
self.y_offset = 0
self.y_sign = +1
self.Fit()
def run_machine(self, ops):
"""Run the console options."""
for (operation, args) in ops:
if operation == 'boot':
Memory.set_ROM(args)
Trace.comment('Bootstrap ROM set to %s' % args.upper())
self.on_paint()
elif operation == 'clear':
Memory.clear_core()
Trace.comment('Core cleared')
self.on_paint()
elif operation == 'load_ptp':
Ptp.mount(args)
Trace.comment("File '%s' mounted on PTP" % args)
self.on_paint()
elif operation == 'load_ptr':
Ptr.mount(args)
Trace.comment("File '%s' mounted on PTR" % args)
self.on_paint()
elif operation == 'data':
MainCPU.DS = args
Trace.comment('Dataswitch value set to %06o' % args)
self.on_paint()
elif operation == 'run':
MainCPU.PC = args
Trace.comment('Running from address %06o' % args)
if Imlac.tracestart:
Trace.comment('DPC\tDisplay\t\tPC\tMain\t\tRegs')
Trace.comment('------ ------------- ------ -------------- '
'-----------------------')
self.on_paint()
Imlac.run()
self.on_paint()
Trace.comment('Imlac halted')
self.on_paint()
elif operation == 'set':
Trace.comment("Setting memory from file '%s'" % args)
self.on_paint()
elif operation == 'trace':
if args == 'off':
Imlac.tracestart = None
Imlac.traceend = None
else:
(start, end) = args
Imlac.tracestart = start
Imlac.traceend = end
tstart = Imlac.tracestart
if tstart is not None:
tstart = '%06o' % tstart
tend = Imlac.traceend
if tend is not None:
tend = '%06o' % tend
Trace.comment('Trace set to (%s, %s)' % (tstart, tend))
self.on_paint()
elif operation == 'ttyin':
TtyIn.mount(args)
Trace.comment("File '%s' mounted on TTYIN" % args)
self.on_paint()
elif operation == 'ttyout':
TtyOut.mount(args)
Trace.comment("File '%s' mounted on TTYOUT" % args)
self.on_paint()
elif operation == 'view':
Trace.comment("Viewing memory from file '%s'" % args)
self.on_paint()
elif operation == 'write':
if args == 'on':
Memory.using_rom = True
elif args == 'off':
Memory.using_rom = False
else:
abort("Invalid view arg: %s" % args)
Trace.comment('ROM write protect set %s' % args.upper())
self.on_paint()
else:
abort('Invalid internal operation: %s' % operation)
Imlac.close(CORE_FILENAME)
def on_paint(self, event=None):
global count
# establish the painting surface
dc = wx.PaintDC(self.screen)
dc.SetBackground(wx.Brush(self.SCREEN_COLOUR, 1))
dc.SetPen(wx.Pen(self.PHOSPHOR_COLOUR, 1))
dc.Clear()
if self.y_sign > 0:
self.y_offset = self.y_offset + self.INC
if self.y_offset > self.HEIGHT_SCREEN-1:
self.y_sign = -1
self.y_offset = self.HEIGHT_SCREEN-1
else:
self.y_offset = self.y_offset - self.INC
if self.y_offset < 0:
self.y_sign = +1
self.y_offset = 0
dc.DrawLine(0, int(self.y_offset), self.WIDTH_SCREEN-1, int(self.HEIGHT_SCREEN-self.y_offset-1))
dc.DrawLine(0, int(self.HEIGHT_SCREEN-self.y_offset-1), self.WIDTH_SCREEN-1, int(self.y_offset))
dc = wx.PaintDC(self.console)
#dc.SetPen(wx.Pen('black', wx.DOT))
dc.SetPen(wx.Pen('black', 1))
dc.DrawLine(0, self.HEIGHT_CONSOLE - self.png_height,
self.WIDTH_CONSOLE-1, self.HEIGHT_CONSOLE - self.png_height)
for (x, y) in self.led_ac.ticks:
dc.DrawLine(x, y, x, y+5)
first = self.led_ac.ticks[0]
last = self.led_ac.ticks[-1]
(x1, y1) = first
(x2, y2) = last
dc.DrawLine(x1, y2+5, x2, y2+5)
for (x, y) in self.led_pc.ticks:
dc.DrawLine(x, y, x, y+5)
first = self.led_pc.ticks[0]
last = self.led_pc.ticks[-1]
(x1, y1) = first
(x2, y2) = last
dc.DrawLine(x1, y2+5, x2, y2+5)
count += 1
self.led_ac.set_value(count)
pass
#class PymlacFrame(wx.Frame):
# """a frame with two panels"""
#
# WIDTH_SCREEN = 1024
# HEIGHT_SCREEN = 1024
# WIDTH_CONSOLE = 330 # 400 # 256
# HEIGHT_CONSOLE = HEIGHT_SCREEN
#
# SCREEN_COLOUR = (0, 0, 0)
# CONSOLE_COLOUR = (255, 223, 169)
# PHOSPHOR_COLOUR = '#F0F000' # yellow
# #PHOSPHOR_COLOUR = '#40FF40' # green
#
# V_MARGIN = 20
# CTL_MARGIN = 15
# LED_MARGIN = 5
#
# IMAGE_LED_OFF = 'images/led_off.png'
# IMAGE_LED_ON = 'images/led_on.png'
#
# INC = 0.01
#
# def __init__(self, parent=None, id=-1, title=None):
# wx.Frame.__init__(self, parent, id, title)
#
# self.make_gui()
# self.run()
#
# def make_gui(self):
# self.screen = wx.Panel(self,
# size=(self.WIDTH_SCREEN, self.HEIGHT_SCREEN),
# pos=(0,0))
# self.screen.SetBackgroundColour(self.SCREEN_COLOUR)
# self.console = wx.Panel(self, style=wx.SIMPLE_BORDER,
# size=(self.WIDTH_CONSOLE, self.HEIGHT_SCREEN),
# pos=(self.WIDTH_SCREEN,0))
# self.console.SetBackgroundColour(self.CONSOLE_COLOUR)
#
# python_png = wx.Image('images/PythonPowered.png',
# wx.BITMAP_TYPE_PNG).ConvertToBitmap()
# python_height = python_png.GetHeight()
# python_width = python_png.GetWidth()
#
# wxpython_png = wx.Image('images/wxPython2.png',
# wx.BITMAP_TYPE_PNG).ConvertToBitmap()
# wxpython_height = wxpython_png.GetHeight()
# wxpython_width = wxpython_png.GetWidth()
#
# h_margin = (self.WIDTH_CONSOLE - wxpython_width - python_width) / 3
#
# png_height = max(python_height, wxpython_height) + self.V_MARGIN
#
# v_margin = (png_height - python_height)/2
# python_ypos = self.HEIGHT_CONSOLE - png_height + v_margin
# v_margin = (png_height - wxpython_height)/2
# wxpython_ypos = self.HEIGHT_CONSOLE - png_height + v_margin
#
# wx.StaticBitmap(self.console, -1, python_png,
# pos=(h_margin, python_ypos))
# wx.StaticBitmap(self.console, -1, wxpython_png,
# pos=(python_width + 2*h_margin, wxpython_ypos))
#
# self.png_height = png_height
#
# led_off = wx.Image('images/led_off.png',
# wx.BITMAP_TYPE_PNG).ConvertToBitmap()
# led_on = wx.Image('images/led_on.png',
# wx.BITMAP_TYPE_PNG).ConvertToBitmap()
#
# y_pos = 8
# self.led_l = Led_1(self.console, 'l', self.CTL_MARGIN, y_pos,
# led_off, led_on)
# self.led_ac = Led_16(self.console, 'ac', 3*self.CTL_MARGIN, y_pos,
# led_off, led_on)
# y_pos += 35
# self.led_pc = Led_16(self.console, 'pc', 3*self.CTL_MARGIN, y_pos,
# led_off, led_on)
#
#
# y_pos = 305
# wx.StaticText(self.console, -1, 'ptr', pos=(self.CTL_MARGIN, y_pos))
# y_pos += 15
# self.txt_ptrFile = wx.TextCtrl(self.console, -1,
# pos=(self.CTL_MARGIN, y_pos),
# size=(self.WIDTH_CONSOLE-2*self.CTL_MARGIN, 25))
# y_pos += 30
#
# wx.StaticText(self.console, -1, 'ptp', pos=(self.CTL_MARGIN, y_pos))
# y_pos += 15
# self.txt_ptpFile = wx.TextCtrl(self.console, -1,
# pos=(self.CTL_MARGIN, y_pos),
# size=(self.WIDTH_CONSOLE-2*self.CTL_MARGIN, 25))
# y_pos += 15
#
# dc = wx.PaintDC(self.console)
# dc.SetPen(wx.Pen('black', 1))
# dc.DrawLine(0, self.HEIGHT_CONSOLE - self.png_height,
# self.WIDTH_CONSOLE-1, self.HEIGHT_CONSOLE - self.png_height)
#
# for (x, y) in self.led_ac.ticks:
# dc.DrawLine(x, y, x, y+5)
# first = self.led_ac.ticks[0]
# last = self.led_ac.ticks[-1]
# (x1, y1) = first
# (x2, y2) = last
# dc.DrawLine(x1, y2+5, x2, y2+5)
#
# for (x, y) in self.led_pc.ticks:
# dc.DrawLine(x, y, x, y+5)
# first = self.led_pc.ticks[0]
# last = self.led_pc.ticks[-1]
# (x1, y1) = first
# (x2, y2) = last
# dc.DrawLine(x1, y2+5, x2, y2+5)
#
# self.y_offset = 0
# self.y_sign = +1
#
# self.Fit()
#
# def run_machine(self, ops):
# """Run the console options."""
#
# for (operation, args) in ops:
# if operation == 'boot':
# Memory.set_ROM(args)
# Trace.comment('Bootstrap ROM set to %s' % args.upper())
# self.on_paint()
# elif operation == 'clear':
# Memory.clear_core()
# Trace.comment('Core cleared')
# self.on_paint()
# elif operation == 'load_ptp':
# Ptp.mount(args)
# Trace.comment("File '%s' mounted on PTP" % args)
# self.on_paint()
# elif operation == 'load_ptr':
# Ptr.mount(args)
# Trace.comment("File '%s' mounted on PTR" % args)
# self.on_paint()
# elif operation == 'data':
# MainCPU.DS = args
# Trace.comment('Dataswitch value set to %06o' % args)
# self.on_paint()
# elif operation == 'run':
# MainCPU.PC = args
# Trace.comment('Running from address %06o' % args)
# if Imlac.tracestart:
# Trace.comment('DPC\tDisplay\t\tPC\tMain\t\tRegs')
# Trace.comment('------ ------------- ------ -------------- '
# '-----------------------')
# self.on_paint()
# Imlac.run()
# self.on_paint()
# Trace.comment('Imlac halted')
# self.on_paint()
# elif operation == 'set':
# Trace.comment("Setting memory from file '%s'" % args)
# self.on_paint()
# elif operation == 'trace':
# if args == 'off':
# Imlac.tracestart = None
# Imlac.traceend = None
# else:
# (start, end) = args
# Imlac.tracestart = start
# Imlac.traceend = end
# tstart = Imlac.tracestart
# if tstart is not None:
# tstart = '%06o' % tstart
# tend = Imlac.traceend
# if tend is not None:
# tend = '%06o' % tend
# Trace.comment('Trace set to (%s, %s)' % (tstart, tend))
# self.on_paint()
# elif operation == 'ttyin':
# TtyIn.mount(args)
# Trace.comment("File '%s' mounted on TTYIN" % args)
# self.on_paint()
# elif operation == 'ttyout':
# TtyOut.mount(args)
# Trace.comment("File '%s' mounted on TTYOUT" % args)
# self.on_paint()
# elif operation == 'view':
# Trace.comment("Viewing memory from file '%s'" % args)
# self.on_paint()
# elif operation == 'write':
# if args == 'on':
# Memory.using_rom = True
# elif args == 'off':
# Memory.using_rom = False
# else:
# abort("Invalid view arg: %s" % args)
# Trace.comment('ROM write protect set %s' % args.upper())
# self.on_paint()
# else:
# abort('Invalid internal operation: %s' % operation)
#
# Imlac.close(CORE_FILENAME)
#
#
# def on_paint(self, event=None):
# global count
#
# # establish the painting surface
# dc = wx.PaintDC(self.screen)
# dc.SetBackground(wx.Brush(self.SCREEN_COLOUR, 1))
# dc.SetPen(wx.Pen(self.PHOSPHOR_COLOUR, 1))
# dc.Clear()
# if self.y_sign > 0:
# self.y_offset = self.y_offset + self.INC
# if self.y_offset > self.HEIGHT_SCREEN-1:
# self.y_sign = -1
# self.y_offset = self.HEIGHT_SCREEN-1
# else:
# self.y_offset = self.y_offset - self.INC
# if self.y_offset < 0:
# self.y_sign = +1
# self.y_offset = 0
# dc.DrawLine(0, int(self.y_offset), self.WIDTH_SCREEN-1, int(self.HEIGHT_SCREEN-self.y_offset-1))
# dc.DrawLine(0, int(self.HEIGHT_SCREEN-self.y_offset-1), self.WIDTH_SCREEN-1, int(self.y_offset))
#
# dc = wx.PaintDC(self.console)
# #dc.SetPen(wx.Pen('black', wx.DOT))
# dc.SetPen(wx.Pen('black', 1))
# dc.DrawLine(0, self.HEIGHT_CONSOLE - self.png_height,
# self.WIDTH_CONSOLE-1, self.HEIGHT_CONSOLE - self.png_height)
#
# for (x, y) in self.led_ac.ticks:
# dc.DrawLine(x, y, x, y+5)
# first = self.led_ac.ticks[0]
# last = self.led_ac.ticks[-1]
# (x1, y1) = first
# (x2, y2) = last
# dc.DrawLine(x1, y2+5, x2, y2+5)
#
# for (x, y) in self.led_pc.ticks:
# dc.DrawLine(x, y, x, y+5)
# first = self.led_pc.ticks[0]
# last = self.led_pc.ticks[-1]
# (x1, y1) = first
# (x2, y2) = last
# dc.DrawLine(x1, y2+5, x2, y2+5)
#
# count += 1
# self.led_ac.set_value(count)
#
#
# pass
@@ -652,11 +655,15 @@ class _InterpreterEvent(wx.PyCommandEvent):
class InterpreterThread(Thread):
"""Worker Thread Class."""
def __init__(self, parent):
def __init__(self, parent, cpu, dcpu):
"""Init Worker Thread Class."""
Thread.__init__(self)
self.parent = parent
self._want_abort = 0
self.cpu = cpu
self.dcpu = dcpu
# This starts the thread running on creation, but you could
# also make the GUI thread responsible for calling this
self.start()
@@ -679,10 +686,39 @@ class InterpreterThread(Thread):
def run(self):
"""Run the interpreter."""
self.cpu.running = True
while self.execute_once() > 0: pass
self.cpu.running = False
Imlac.run()
self.RaiseInterpreterStop()
def execute_once():
if traceend is None:
if self.cpu.PC == tracestart:
Trace.settrace(True)
else:
Trace.settrace(self.cpu.PC >= tracestart and self.cpu.PC <= traceend)
if self.dcpu.ison():
Trace.trace('%6.6o' % self.dcpu.DPC)
Trace.trace('\t')
instruction_cycles = self.dcpu.execute_one_instruction()
Trace.trace('%6.6o\t' % self.cpu.PC)
instruction_cycles += self.cpu.execute_one_instruction()
Trace.itraceend(self.dcpu.ison())
self.__tick_all(instruction_cycles)
if not self.dcpu.ison() and not self.cpu.running:
return 0
return instruction_cycles
def abort(self):
"""abort worker thread."""
# Method for use by main thread to signal an abort
@@ -744,14 +780,21 @@ class DisplayFrame(wx.Frame):
def run_machine(self):
"""Run the interpreter."""
# FIXME create all devices, build the Imlac machine
self.memory = Memory.Memory(boot_rom=DefaultBootROM, corefile=DefaultCoreFile)
# create device, construct machine
self.kbd = None # Kbd.Kbd()
self.ttyin = None # TtyIn.TtyIn()
self.ttyout = None # TtyOut.TtyOut()
self.memory = Memory.Memory(boot_rom=DefaultBootROM, core=DefaultCoreFile)
self.ptr = Ptr.Ptr()
self.ptp = Ptp.Ptp()
self.display = Display.Display(self.memory)
self.display = Display.Display(self)
self.dcpu = DisplayCPU.DisplayCPU(self.display, self.memory)
self.cpu = MainCPU.MainCPU(self.ptr, self.ptp,
self.display, self.dcpu, self.memory)
self.cpu = MainCPU.MainCPU(self.memory, self.display, self.dcpu,
self.kbd, self.ttyin, self.ttyout,
self.ptr, self.ptp)
Trace.init(TRACE_FILENAME, self.cpu, self.dcpu)
tracestart = traceend = None
# get and execute the operations list
ops = get_options()
@@ -760,66 +803,66 @@ class DisplayFrame(wx.Frame):
time.sleep(1)
if operation == 'boot':
Memory.set_ROM(args)
self.memory.set_ROM(args)
Trace.comment('Bootstrap ROM set to %s' % args.upper())
elif operation == 'clear':
Memory.clear_core()
self.memory.clear_core()
Trace.comment('Core cleared')
elif operation == 'load_ptp':
Ptp.mount(args)
Trace.comment("File '%s' mounted on PTP" % args)
elif operation == 'load_ptr':
Ptr.mount(args)
self.ptr.mount(args)
Trace.comment("File '%s' mounted on PTR" % args)
elif operation == 'data':
MainCPU.DS = args
self.cpu.DS = args
Trace.comment('Dataswitch value set to %06o' % args)
elif operation == 'run':
MainCPU.PC = args
self.cpu.PC = args
Trace.comment('Running from address %06o' % args)
if Imlac.tracestart:
if tracestart:
Trace.comment('DPC\tDisplay\t\tPC\tMain\t\tRegs')
Trace.comment('------ ------------- ------ -------------- '
'-----------------------')
self.interpreter = InterpreterThread(self)
self.interpreter = InterpreterThread(self, self.cpu, self.dcpu)
self.running = True
elif operation == 'set':
Trace.comment("Setting memory from file '%s'" % args)
elif operation == 'trace':
if args == 'off':
Imlac.tracestart = None
Imlac.traceend = None
tracestart = None
traceend = None
else:
(start, end) = args
Imlac.tracestart = start
Imlac.traceend = end
tstart = Imlac.tracestart
tracestart = start
traceend = end
tstart = tracestart
if tstart is not None:
tstart = '%06o' % tstart
tend = Imlac.traceend
tend = traceend
if tend is not None:
tend = '%06o' % tend
Trace.comment('Trace set to (%s, %s)' % (tstart, tend))
elif operation == 'ttyin':
TtyIn.mount(args)
self.ttyin.mount(args)
Trace.comment("File '%s' mounted on TTYIN" % args)
elif operation == 'ttyout':
TtyOut.mount(args)
self.ttyout.mount(args)
Trace.comment("File '%s' mounted on TTYOUT" % args)
elif operation == 'view':
Trace.comment("Viewing memory from file '%s'" % args)
elif operation == 'write':
if args == 'on':
Memory.using_rom = True
self.memory.using_rom = True
elif args == 'off':
Memory.using_rom = False
self.memory.using_rom = False
else:
abort("Invalid view arg: %s" % args)
Trace.comment('ROM write protect set %s' % args.upper())
else:
abort('Invalid internal operation: %s' % operation)
Imlac.close(CORE_FILENAME)
# Imlac.close(CORE_FILENAME)
def excepthook(type, value, tb):
"""Handler for uncaught exceptions."""