File size: 2,724 Bytes
324ecd2 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | import random
import unittest
import torch
from beamboot.large_cpu import LargeCPU, LargeRuntime, encode_event
class LargeCPUEquivalenceTests(unittest.TestCase):
def test_random_programs_against_independent_interpreter(self):
rng = random.Random(2401)
ops = ('LDI', 'ADD', 'SUB', 'LOAD', 'STORE', 'ADDM', 'SUBM', 'OUT')
for _ in range(4):
program = [(rng.choice(ops), rng.randrange(16)) for _ in range(70)] + [('HALT', 0)]
machine = LargeRuntime(LargeCPU(program))
memory, accumulator = [0]*16, 0
for pc, (op, arg) in enumerate(program):
step = machine.step()
if op == 'LDI': accumulator = arg
elif op == 'ADD': accumulator = (accumulator + arg) & 15
elif op == 'SUB': accumulator = (accumulator - arg) & 15
elif op == 'LOAD': accumulator = memory[arg]
elif op == 'STORE': memory[arg] = accumulator
elif op == 'ADDM': accumulator = (accumulator + memory[arg]) & 15
elif op == 'SUBM': accumulator = (accumulator - memory[arg]) & 15
self.assertEqual(step.acc, accumulator)
self.assertEqual(step.pc, pc if op == 'HALT' else pc + 1)
self.assertEqual(step.write, op == 'STORE')
self.assertEqual(step.output, op == 'OUT')
self.assertEqual(step.halt, op == 'HALT')
if step.write: self.assertEqual((step.address, step.value), (arg, accumulator))
def test_branches_and_high_rom_address(self):
program = [('LDI', 3), ('SUB', 1), ('JZ', 40), ('JMP', 1)]
program += [('HALT', 0)] * (40-len(program))
program += [('LDI', 9), ('OUT', 0), ('HALT', 0)]
runtime = LargeRuntime(LargeCPU(program))
trace = []
for _ in range(20):
step = runtime.step(); trace.append(step)
if step.halt: break
self.assertTrue(runtime.halted)
self.assertTrue(any(step.pc == 40 for step in trace))
self.assertEqual([step.acc for step in trace if step.output], [9])
def test_future_event_is_not_visible(self):
model = LargeCPU([('LOAD', 1), ('HALT', 0)])
events = [encode_event(address=i, valid=True) for i in range(16)]
events += [encode_event(position=16), encode_event(address=1, value=14, valid=True, position=17)]
original = torch.tensor([events], dtype=torch.float32)
changed = original.clone(); changed[0, -1, 17:21] = 0
with torch.inference_mode():
one, two = model(original, last_only=False), model(changed, last_only=False)
self.assertTrue(torch.equal(one[:, :-1], two[:, :-1]))
|