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

Use python3 and trying to get trace working

This commit is contained in:
Ross Wilson
2018-07-23 17:26:56 +07:00
parent e8aaa30362
commit 18d0b80769
32 changed files with 946 additions and 1044 deletions

View File

@@ -640,8 +640,8 @@ def eval_expr(expr):
if 'is not defined' in e.message:
Undefined = e.message[len("name '"):-len("' is not defined")]
msg = "Opcode expression has '%s' undefined" % Undefined
error(msg)
#raise NameError(msg)
#error(msg)
raise NameError(msg)
error("Opcode expression has an error")
return result

View File

@@ -1,5 +1,4 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Test the pyasm functions.
@@ -25,14 +24,14 @@ class TestPyasm(unittest.TestCase):
# define tests: (test, dot, symtable, expected, undefined, raises)
tests = (
('A', 0100, {'A': 1}, 1, None, False),
('.', 0100, {}, 0100, None, False),
('B', 0100, {}, None, 'B', True),
('A', 0o100, {'A': 1}, 1, None, False),
('.', 0o100, {}, 0o100, None, False),
('B', 0o100, {}, None, 'B', True),
('A+1', 0100, {'A': 1}, 2, None, False),
('A+B', 0, {'A': 1, 'B': 2}, 3, None, False),
('A + B', 0, {'A': 1, 'B': 2}, 3, None, False),
('A / B', 0, {'A': 4, 'B': 2}, 2, None, False),
('. + 0100', 0100, {}, 0200, None, False),
('. + 0o100', 0o100, {}, 0o200, None, False),
)
# now run them
@@ -98,7 +97,7 @@ class TestPyasm(unittest.TestCase):
# define tests: (label, address, lnum, expected_symtab, expected_symtabline
tests = (
('A', 1, 2, {'A': 1}, {'A': 2}),
('B', 0100, 5, {'B': 0100}, {'B': 5}),
('B', 0o100, 5, {'B': 0o100}, {'B': 5}),
)
# now run them

View File

@@ -1,6 +1,3 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
The Imlac display.
@@ -11,7 +8,8 @@ The Imlac dislay X and Y registers are of size 11 bits. The most significant
DLYA) loads the display X (or Y) register from the 10 bits of valu, with bit
10 of the X/Y register being set to 0.
The display is 2048x2048 pixels.
The virtual display is 2048x2048 pixels, but the physical display is
1024x1024 pixels.
"""
@@ -48,9 +46,9 @@ class Display(object):
BackgroundColour = 1
DrawColour = 0
# max coordinates of pymlac display
ScaleMaxX = 2048
ScaleMaxY = 2048
# max coordinates of pymlac physical display
ScaleMaxX = 1024
ScaleMaxY = 1024
def __init__(self):
@@ -73,7 +71,7 @@ class Display(object):
"""Write display array to PPM file."""
self.next_file_num += 1
filename = 'pymlac_%06d.ppm' % self.next_file_num
filename = 'pymlac_%06d.pbm' % self.next_file_num
with open(filename, 'wb') as handle:
# output header data
handle.write(bytes('P1\n', 'utf-8'))
@@ -94,15 +92,52 @@ class Display(object):
x1, y1 start coordinates
x2, y2 end coordinates
dotted True if dotted line, else False (IGNORED)
Algorithm from:
http://csourcecodes.blogspot.com/2016/06/bresenhams-line-drawing-algorithm-generalized-c-program.html
"""
log('Display: drawing (%d,%d) to (%d,%d)' % (x1, y1, x2, y2))
# convert virtual coords to physical
x1 = x1 // 2
y1 = y1 // 2
x2 = x2 // 2
y2 = y2 // 2
# invert the Y axis
y1 = self.ScaleMaxY - y1
y2 = self.ScaleMaxY - y2
# draw the line (Bresenham algorithm)
x = x1
y = y1
dx = abs(x2 - x1)
dy = abs(y2 - y1)
s1 = 1 if x2 > x1 else -1 # sign(x2 - x1)
s2 = 1 if y2 > y1 else -1 # sign(y2 - y1)
swap = False
self.array[(y-1)*self.ScaleMaxX + x - 1] = self.DrawColour
if dy > dx:
(dx, dy) = (dy, dx)
swap = True
p = 2*dy - dx
for i in range(0, dx):
self.array[(y-1)*self.ScaleMaxX + x - 1] = self.DrawColour
while p >= 0:
p = p - 2*dx
if swap:
x += s1
else:
y += s2
p = p + 2*dy
if swap:
y += s2
else:
x += s1
i += 1
# set display flag to "changed"
self.dirty = True
# draw a straight line using Bresenam
self.bresenham(x1, y1, x2, y2)
def clear(self):
"""Clear the display."""
@@ -135,85 +170,19 @@ class Display(object):
if self.dirty:
self.write()
# original algorithm from:
# http://www.idav.ucdavis.edu/education/GraphicsNotes/Bresenhams-Algorithm.pdf
# Let ∆x = x2 x1
# Let ∆y = y2 y1
# Let j = y1
# Let ε = ∆y ∆x
#
# for i = x1 to x21
# illuminate (i, j)
# if (ε ≥ 0)
# j += 1
# ε = ∆x
# end if
# i += 1
# ε += ∆y
# next i
#
# finish
def bresenham(self, x1, y1, x2, y2):
"""Bresenham algorithm to draw from (x1,y1) to (x2,y2)."""
dx = x2 - x1
dy = y2 - y1
# Determine how steep the line is
is_steep = abs(dy) > abs(dx)
# Rotate line
if is_steep:
x1, y1 = y1, x1
x2, y2 = y2, x2
# Swap start and end points if necessary and store swap state
swapped = False
if x1 > x2:
x1, x2 = x2, x1
y1, y2 = y2, y1
swapped = True
# Recalculate differentials
dx = x2 - x1
dy = y2 - y1
# Calculate error
error = int(dx / 2.0)
ystep = 1 if y1 < y2 else -1
# Iterate over bounding box generating points between start and end
y = y1
for x in range(x1, x2 + 1):
(xx, yy) = (y, x) if is_steep else (x, y)
yyy = self.ScaleMaxX - yy
self.array[yyy*self.ScaleMaxX + xx] = self.DrawColour
error -= abs(dy)
if error < 0:
y += ystep
error += dx
if __name__ == '__main__':
"""Test case - draw radial lines."""
d = Display()
d.draw(0, 0, 1023, 1023)
d.draw(255, 0, 1023-255, 1023)
d.draw(511, 0, 1023-511, 1023)
d.draw(767, 0, 1023-767, 1023)
d.draw(1023, 0, 0, 1023)
d.draw(0, 255, 1023, 1023-255)
d.draw(0, 511, 1023, 1023-511)
d.draw(0, 767, 1023, 1023-767)
granularity = 32
for x in range(0, 2048, granularity):
d.draw(x, 0, 1023, 1023)
for y in range(0, 2048, granularity):
d.draw(2048, y, 1023, 1023)
for x in range(2048, 0, -granularity):
d.draw(x, 2048, 1023, 1023)
for y in range(2048, 0, -granularity):
d.draw(0, y, 1023, 1023)
d.clear()
d.draw(0, 0, 1023, 1023)
d.draw(255, 0, 1023-255, 1023)
d.draw(511, 0, 1023-511, 1023)
d.draw(767, 0, 1023-767, 1023)
d.draw(1023, 0, 0, 1023)
d.draw(0, 255, 1023, 1023-255)
d.draw(0, 511, 1023, 1023-511)
d.draw(0, 767, 1023, 1023-767)
d.close()

View File

@@ -1,5 +1,3 @@
#!/usr/bin/python
"""
The Imlac display CPU.
@@ -131,24 +129,24 @@ class DisplayCPU(object):
self.DPC = self.DRS[self.DRSindex]
if byte & 0x10: # inc X MSB
log('**** inc X MSB: before .DX=%d' % self.DX)
log(f'**** inc X MSB: before .DX={self.DX:06o}')
self.DX += (1 << LSBBITS)
log('**** inc X MSB: after .DX=%d' % self.DX)
log(f'**** inc X MSB: after .DX={self.DX:06o}')
if byte & 0x08: # clear X LSB
log('**** clear X LSB: before .DX=%d' % self.DX)
log(f'**** clear X LSB: before .DX={self.DX:06o}')
self.DX &= MSBMASK
log('**** clear X LSB: after .DX=%d' % self.DX)
log(f'**** clear X LSB: after .DX={self.DX:06o}')
if byte & 0x02: # inc Y MSB
log('**** inc Y MSB: before .DY=%d' % self.DY)
log(f'**** inc Y MSB: before .DY={self.DY:06o}')
self.DY += (1 << LSBBITS)
log('**** inc Y MSB: after .DY=%d' % self.DY)
log(f'**** inc Y MSB: after .DY={self.DY:06o}')
if byte & 0x01: # clear Y LSB
log('**** clear Y LSB: before .DY=%d' % self.DY)
log(f'**** clear Y LSB: before .DY={self.DY:06o}')
self.DY &= MSBMASK
log('**** clear Y LSB: after .DY=%d' % self.DY)
log(f'**** clear Y LSB: after .DY={self.DY:06o}')
return trace

View File

@@ -1,5 +1,3 @@
#!/usr/bin/python
"""
Globals used throughout the emulator.
"""

View File

@@ -1,6 +1,3 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
A simulator for an Imlac PDS-1 or PDS-4.
@@ -48,6 +45,9 @@ import TtyIn
import TtyOut
import Trace
import log
log = log.Log('test.log', log.Log.DEBUG)
class Imlac(object):
"""The Imlac object - contains all devices."""
@@ -100,15 +100,18 @@ class Imlac(object):
Trace.settrace(MainCPU.PC >= self.tracestart
and MainCPU.PC <= self.traceend)
log(f'execute_once: self.dcpu.ison() returns {self.dcpu.ison()}')
if self.dcpu.ison():
Trace.trace('%6.6o' % DisplayCPU.DPC)
Trace.trace('\t')
instruction_cycles = self.dcpu.execute_one_instruction()
(instruction_cycles, dtrace_str) = self.dcpu.execute_one_instruction()
log(f"execute_once: at {DisplayCPU.PC:6.6o}, returned cycles {instruction_cycles} and dtrace_str='{dtrace_str}'")
Trace.trace('%6.6o\t' % MainCPU.PC)
instruction_cycles += self.cpu.execute_one_instruction()
(instruction_cycles, trace_str) += self.cpu.execute_one_instruction()
log(f"execute_once: at {MainCPU.PC:6.6o}, returned cycles {instruction_cycles} and trace_str='{trace_str}'")
Trace.itraceend(DisplayCPU.ison())

View File

@@ -1,5 +1,3 @@
# !/usr/bin/python
"""
Emulate the Keyboard (KBD).

View File

@@ -1,5 +1,3 @@
#!/usr/bin/python
"""
The Imlac main CPU.
"""

View File

@@ -36,3 +36,5 @@ lst: $(TESTS)
clean:
rm -Rf *.pyc *~ *.out test_*.ptp *.lst test_*.trace _#*#_.* CPU.test.trace.* test.ptr
rm -f test.log *.pbm pymlac.trace

View File

@@ -1,5 +1,3 @@
#!/usr/bin/python
"""
Emulate the Imlac Memory.
"""

View File

@@ -1,7 +1,6 @@
#!/usr/bin/python
################################################################################
# The Imlac panel.
################################################################################
"""
The Imlac panel.
"""
import os

View File

@@ -1,6 +1,3 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
Emulate the imlac Paper Tape Reader/Punch (PTR/PTP).
@@ -86,7 +83,7 @@ class PtrPtp(object):
self.device_motor_on = False
self.device_filename = fname
self.device_open_file = open(self.device_filename, 'rb')
print('Opening PTR file: %s' % fname)
log('Opening PTR file: %s' % fname)
self.device_ready = False
self.device_cycle_count = self.PtrNotReadyCycles
self.ptr_at_eof = False

View File

@@ -1,24 +1,22 @@
#!/usr/bin/python
"""
Class to emulate the Imlac Registers (main cpu and display cpu).
"""
class Regs(object):
DS = 0100000 # data switches
DS = 0100000 # data switches
PC = 040 # main CPU program counter
L = 0 # main CPU link register
AC = 0 # main CPU accumulator
Sync40Hz = 1 # main CPU 40Hz flag register
PC = 040 # main CPU program counter
L = 0 # main CPU link register
AC = 0 # main CPU accumulator
Sync40Hz = 1 # main CPU 40Hz flag register
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
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
def clearSync40Hz(self):
"""Clear the 40Hz flag register."""

View File

@@ -1,5 +1,3 @@
#!/usr/bin/python
"""
The Imlac trace stuff.
@@ -16,6 +14,9 @@ import collections
from Globals import *
import log
log = log.Log('test.log', log.Log.DEBUG)
class Trace(object):
@@ -47,25 +48,25 @@ class Trace(object):
self.dcpu = displaycpu
self.trace_map = collections.defaultdict(bool)
# print('Trace.__init__: self.tracing=%s, self.tracefile=%s' % (str(self.tracing), str(self.tracefile)))
log(f'Trace.__init__: self.tracing={self.tracing}, self.tracefile={self.tracefile}')
def set_trace_map(self, trace_map):
"""Set the trace address dict mapping."""
self.trace_map = trace_map
# print('Trace.set_trace_map: self.trace_map=%s' % str(trace_map))
log(f'Trace.set_trace_map: self.trace_map={trace_map}')
def add_maincpu(self, maincpu):
"""Add the main CPU object."""
self.cpu = maincpu
# print('Trace.add_maincpu: self.cpu=%s' % str(maincpu))
log(f'Trace.add_maincpu: self.cpu={maincpu}')
def add_displaycpu(self, dispcpu):
"""Add the display CPU object."""
self.dcpu = dispcpu
# print('Trace.add_displaycpu: self.dcpu=%s' % str(dispcpu))
log(f'Trace.add_displaycpu: self.dcpu={dispcpu}')
def close(self):
"""Close trace."""
@@ -74,7 +75,7 @@ class Trace(object):
self.tracing = False
self.tracefile = None
self.dcpu = dispcpu
# print('Trace.close: self.tracing=%s' % str(self.tracing))
log(f'Trace.close: self.tracing={self.tracing}')
def deimtrace(self, opcode, code):
"""Trace the DEIM instruction.
@@ -83,6 +84,7 @@ class Trace(object):
code the operation
"""
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()
@@ -97,6 +99,7 @@ class Trace(object):
Returns the trace string or None if not tracing.
"""
log(f'Trace.dtrace: self.tracing={self.tracing}')
result = None
if self.tracing:
@@ -105,6 +108,7 @@ class Trace(object):
else:
result = '%04o: %s\t%5.5o' % (ddot, opcode, address)
log(f"dtrace: result='{result}'")
return result
def itrace(self, dot, opcode, indirect=False, address=None):
@@ -118,7 +122,7 @@ class Trace(object):
Returns the trace string or None if not tracing.
"""
# print('Trace.itrace: self.tracing=%s, self.trace_map=%s' % (str(self.tracing), str(self.trace_map)))
# log(f'Trace.itrace: self.tracing={self.tracing}, self.trace_map={self.trace_map}')
result = None
if self.tracing and self.trace_map[dot]:
@@ -160,4 +164,4 @@ class Trace(object):
"""Set the trace ON or OFF."""
self.tracing = new_tracing
# print('Trace.settrace: self.tracing=%s' % str(new_tracing))
log(f'Trace.settrace: self.tracing={new_tracing}')

View File

@@ -1,5 +1,3 @@
#!/usr/bin/python
"""
Emulate the Input TTY device (TTYIN).
"""

View File

@@ -1,5 +1,3 @@
#!/usr/bin/python
"""
Emulate the Output TTY (TTYOUT).
"""

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,3 @@
#!/usr/bin/env python
"""A 'floatslider' widget for ELoss.
As the wxPython slider widget works only with integers, we need

View File

@@ -1,6 +1,3 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
The 'led16' widget.

View File

@@ -1,5 +1,3 @@
#!/usr/bin/env python
"""
A simple logger.

View File

@@ -1,5 +1,4 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
A simulator for an Imlac PDS-1 or PDS-4.
@@ -88,9 +87,11 @@ def start_running(cpu, dcpu, memory, ptrptp, ttyin):
cpu.running = True
while cpu.running:
(cycles, tracestr) = cpu.execute_one_instruction()
log(f"start_running: cpu.execute_one_instruction returned ({cycles}, '{tracestr}')")
if tracestr:
endstr = trace.itraceend(False)
dcpu.execute_one_instruction()
(dcycles, dtracestr) = dcpu.execute_one_instruction()
log(f"start_running: dcpu.execute_one_instruction returned ({dcycles}, '{dtracestr}')")
ptrptp.ptr_tick(cycles)
ptrptp.ptp_tick(cycles)
ttyin.tick(cycles)

View File

@@ -1,6 +1,3 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
A display widget for the pymlac interpreter.
"""

View File

@@ -1,57 +1,57 @@
org 0100
org 0100
dof ; turn display off
wdoff dsn ;
jmp wdoff ; wait until display off
w40hz ssf ;
jmp w40hz ; wait for 40Hz synch
scf ;
law hello ; start display
dla ;
don ;
jmp wdoff ;
dof ; turn display off
wdoff dsn ;
jmp wdoff ; wait until display off
w40hz ssf ;
jmp w40hz ; wait for 40Hz synch
scf ;
law hello ; start display
dla ;
don ;
jmp wdoff ;
hbit data 0100000
hbit data 0100000
hello dlxa 0400
dlya 0400
dsts 2
dhvc
djms h
djms e
djms l
djms l
djms o
dhlt
hello dlxa 0400
dlya 0400
dsts 2
dhvc
djms upperh
djms uppere
djms upperl
djms upperl
djms uppero
dhlt
h inc e,b03
inc 03,02
inc d30,30
inc b0-3,0-3
inc 0-2,d03
inc 01,b-30
inc -30,f
upperh inc e,b03 ; H
inc 03,02 ;
inc d0-3,0-1 ;
inc b30,30 ;
inc Y,b03 ;
inc 03,02 ;
inc Y,f ;
e inc e,b03
inc 03,02
inc 30,30
inc d-1-3,-1-1
inc b-30,-10
inc d0-3,0-1
inc b30,30
inc f,f
uppere inc e,b03 ; E
inc 03,02 ;
inc 30,30 ;
inc d-1-2,-1-2 ;
inc b-20,-20 ;
inc d0-2,0-2 ;
inc b30,30 ;
inc f,f ;
l inc e,b03
inc 03,02
inc a1,p
inc 30,30
inc f,f
upperl inc e,b03 ; L
inc 03,02 ;
inc Y,b30 ;
inc 30,f ;
o inc e,d02
inc b03,23
inc 20,2-3
inc 0-3,-2-2
inc -20,-22
inc f,f
uppero inc e,d10 ; O
inc b20,20 ;
inc 13,02 ;
inc -13,-20 ;
inc -20,-1-3 ;
inc 0-2,1-3 ;
inc f,f ;
end
end

View File

@@ -1,7 +1,6 @@
#!/usr/bin/python
################################################################################
# Dumps statistics from 'pymlac' run.
################################################################################
"""
Dumps statistics from 'pymlac' run.
"""
import pstats

View File

@@ -1,5 +1,3 @@
#!/usr/bin/env python
import time
import collections
import threading

View File

@@ -1,6 +1,3 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Test pymlac CPU opcodes DIRECTLY.

View File

@@ -1,6 +1,3 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Test the pymlac display widget.
@@ -129,7 +126,7 @@ if __name__ == '__main__':
msg += '\nUncaught exception:\n'
msg += ''.join(traceback.format_exception(type, value, tb))
msg += '=' * 80 + '\n'
print msg
print(msg)
sys.exit(1)
# plug our handler into the python system

View File

@@ -1,6 +1,3 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Test the pymlac keyboard emulation.

View File

@@ -1,6 +1,3 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Test the pymlac Memory object DIRECTLY.

View File

@@ -1,6 +1,3 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Test the pymlac papertape reader code.

View File

@@ -1,6 +1,3 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Test the pymlac TTY input device.

View File

@@ -1,6 +1,3 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Test the pymlac TTY output device.