KEK/json/produce-json2.py
2024-04-12 18:04:03 +02:00

218 lines
6.5 KiB
Python
Executable file

#! /usr/bin/python3
import copy
import json
from machine import PDP1170
from mmio import MMIO
from op4 import op4_dispatch_table
import os
from pdptraps import PDPTrap, PDPTraps
import random
import sys
ignore_traps = True
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, 65535)
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, 65535))
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)
def simple_run_1(self, pc):
thisPC = pc
self.r[self.PC] = (thisPC + 2) & 0o177777 # "could" wrap
try:
inst = self.mmu.wordRW(thisPC)
op4_dispatch_table[inst >> 12](self, inst)
return True
except PDPTrap as trap:
return False
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'] = copy.deepcopy(p.stackpointers)
target[tag]['pc'] = p.r[p.PC]
def create_test(self, instr, psw):
try:
out = { }
p = PDP1170_wrapper(loglevel='ERROR')
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) & ~1
mem_kv = []
if instr == 1: # TODO ignore 'WAIT' instruction
return None
p.logger.info(f'emulating {instr:06o}')
mem_kv.append((addr + 0, instr))
mem_kv.append((addr + 2, random.randint(0, 65535 - 8) & ~1))
mem_kv.append((addr + 4, random.randint(0, 65535 - 8) & ~1))
mem_kv.append((addr + 6, random.randint(0, 65535 - 8) & ~1))
out['memory-before'] = dict()
for a, v in mem_kv:
p.put(a, v)
p.psw = psw
# generate other registers
reg_kv = []
for i in range(7):
reg_kv.append((i, random.randint(0, 65535) & ~1))
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
# run instruction
p.run_steps(pc=addr, steps=1)
#if p.simple_run_1(addr) == False:
# return None
#if (p.straps or p.issues) and ignore_traps:
if p.straps and ignore_traps:
return None
p._syncregs()
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()
# verify original values
for a, v in mem_kv:
if not a in mem_transactions:
mem_transactions[a] = v
for a in mem_transactions:
out['memory-after'][a] = mem_transactions[a]
out['mmr0-after'] = p.mmu.MMR0
p.mmu._MMR1commit()
out['mmr1-after'] = p.mmu.MMR1
out['mmr2-after'] = p.mmu.MMR2
out['mmr3-after'] = p.mmu.MMR3
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
stop = False
while True:
psw = random.randint(0, 65535) & 0o174377
name = f'/data/data/temp2/0008-{psw:06o}.json'
if os.path.isfile(name):
print(f'skipping {name}')
continue
print(name)
fh = open(name, 'w')
t = test_generator()
tests = []
try:
for lb in range(65535):
if (lb & 63) == 0:
print(f'{lb} {len(tests)}\r', end='')
test = t.create_test(lb, psw)
if test != None:
tests.append(test)
except KeyboardInterrupt as ki:
stop = True
fh.write(json.dumps(tests, indent=4))
fh.close()
if stop:
break