178 lines
5.4 KiB
Python
Executable file
178 lines
5.4 KiB
Python
Executable file
#! /usr/bin/python3
|
|
|
|
import json
|
|
from machine import PDP1170
|
|
from mmio import MMIO
|
|
from pdptraps import PDPTrap, PDPTraps
|
|
import random
|
|
import sys
|
|
|
|
|
|
class MMIO_wrapper(MMIO):
|
|
def register(self, iofunc, offsetaddr, nwords, *, byte_writes=False, reset=False):
|
|
pass
|
|
|
|
def register_simpleattr(self, obj, attrname, addr, reset=False):
|
|
pass
|
|
|
|
def devicereset_register(self, func):
|
|
pass
|
|
|
|
class PDP1170_wrapper(PDP1170):
|
|
def __init__(self, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
|
|
self.logger.info('')
|
|
|
|
self.reset_mem_transactions_dict()
|
|
|
|
def reset_mem_transactions_dict(self):
|
|
self.mem_transactions = dict()
|
|
self.before = dict()
|
|
|
|
def get_mem_before(self):
|
|
return self.before
|
|
|
|
def get_mem_transactions_dict(self):
|
|
return self.mem_transactions
|
|
|
|
def put(self, physaddr, value):
|
|
self.before[physaddr] = value
|
|
super().physRW(physaddr, value)
|
|
|
|
def physRW(self, physaddr, value=None):
|
|
if value == None: # read
|
|
self.logger.info(f'Read from {physaddr:08o} (phys)')
|
|
if not physaddr in self.mem_transactions and not physaddr in self.before:
|
|
self.before[physaddr] = random.randint(0, 65536)
|
|
return super().physRW(physaddr, self.before[physaddr])
|
|
|
|
self.logger.info(f'Write to {physaddr:08o}: {value:06o} (phys)')
|
|
self.mem_transactions[physaddr] = value
|
|
return super().physRW(physaddr, value)
|
|
|
|
def physRW_N(self, physaddr, nwords, words=None):
|
|
temp_addr = physaddr
|
|
if words == None:
|
|
self.logger.info(f'Read {nwords} words from {physaddr:08o} (phys)')
|
|
for i in range(nwords):
|
|
self.physRW(temp_addr, random.randint(0, 65536))
|
|
temp_addr += 2
|
|
return super().physRW_N(physaddr, nwords)
|
|
|
|
self.logger.info(f'Write {nwords} ({len(words)}) words to {physaddr:08o} (phys)')
|
|
for w in words:
|
|
self.mem_transactions[temp_addr] = w
|
|
temp_addr += 2
|
|
|
|
return super().physRW_N(physaddr, nwords, words=words)
|
|
|
|
class test_generator:
|
|
def _invoke_bp(self, a, i):
|
|
return True
|
|
|
|
def put_registers(self, p, target, tag):
|
|
target[tag] = dict()
|
|
target[tag][0] = dict()
|
|
target[tag][1] = dict()
|
|
for set_ in range(0, 2):
|
|
for reg_ in range(0, 6):
|
|
target[tag][set_][reg_] = p.registerfiles[set_][reg_]
|
|
|
|
target[tag]['sp'] = p.stackpointers
|
|
target[tag]['pc'] = p.r[p.PC]
|
|
|
|
def create_test(self):
|
|
out = { }
|
|
|
|
p = PDP1170_wrapper(loglevel='DEBUG')
|
|
p.ub.mmio = MMIO_wrapper(p)
|
|
|
|
# TODO what is the maximum size of an instruction?
|
|
# non-mmu thus shall be below device range
|
|
addr = random.randint(0, 0o160000 - 8) & ~3
|
|
mem_kv = []
|
|
while True:
|
|
instr = random.randint(0, 65536 - 8)
|
|
if instr != 1: # TODO ignore 'WAIT' instruction
|
|
break
|
|
p.logger.info(f'emulating {instr:06o}')
|
|
mem_kv.append((addr + 0, instr))
|
|
mem_kv.append((addr + 2, random.randint(0, 65536 - 8)))
|
|
mem_kv.append((addr + 4, random.randint(0, 65536 - 8)))
|
|
mem_kv.append((addr + 6, random.randint(0, 65536 - 8)))
|
|
out['memory-before'] = dict()
|
|
for a, v in mem_kv:
|
|
p.put(a, v)
|
|
|
|
try:
|
|
# generate & set PSW
|
|
while True:
|
|
try:
|
|
p.psw = random.randint(0, 65536)
|
|
break
|
|
except PDPTraps.ReservedInstruction as ri:
|
|
pass
|
|
|
|
# generate other registers
|
|
reg_kv = []
|
|
for i in range(7):
|
|
reg_kv.append((i, random.randint(0, 65536)))
|
|
reg_kv.append((7, addr))
|
|
|
|
# set registers
|
|
set_ = (p.psw >> 11) & 1
|
|
for r, v in reg_kv:
|
|
p.registerfiles[set_][r] = v
|
|
p.registerfiles[1 - set_][r] = (~v) & 65535 # make sure it triggers errors
|
|
assert p.registerfiles[set_][r] == p.r[r]
|
|
p.r[6] = p.registerfiles[set_][6]
|
|
p.r[p.PC] = addr
|
|
p._syncregs()
|
|
|
|
self.put_registers(p, out, 'registers-before')
|
|
out['registers-before']['psw'] = p.psw
|
|
|
|
p.run_steps(pc=addr, steps=1)
|
|
|
|
self.put_registers(p, out, 'registers-after')
|
|
out['registers-after']['psw'] = p.psw
|
|
|
|
mb = p.get_mem_before()
|
|
for a in mb:
|
|
out['memory-before'][a] = mb[a]
|
|
|
|
out['memory-after'] = dict()
|
|
mem_transactions = p.get_mem_transactions_dict()
|
|
for a in mem_transactions:
|
|
out['memory-after'][a] = mem_transactions[a]
|
|
# TODO originele geheugeninhouden checken
|
|
|
|
return out
|
|
|
|
except PDPTraps.ReservedInstruction as pri:
|
|
return None
|
|
|
|
except Exception as e:
|
|
# handle PDP11 traps; store them
|
|
print(f'test failed {e}, line number: {e.__traceback__.tb_lineno}')
|
|
return None
|
|
|
|
fh = open(sys.argv[1], 'w')
|
|
|
|
t = test_generator()
|
|
|
|
tests = []
|
|
try:
|
|
for i in range(32768):
|
|
if (i & 63) == 0:
|
|
print(f'{i}\r', end='')
|
|
test = t.create_test()
|
|
if test != None:
|
|
tests.append(test)
|
|
|
|
except KeyboardInterrupt as ki:
|
|
pass
|
|
|
|
fh.write(json.dumps(tests, indent=4))
|
|
fh.close()
|