mirror of
https://github.com/rzzzwilson/pymlac.git
synced 2025-06-10 09:32:41 +00:00
New test code - interpreter
This commit is contained in:
171
pymlac/test_CPU.py
Normal file
171
pymlac/test_CPU.py
Normal file
@@ -0,0 +1,171 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Test pymlac CPU opcodes DIRECTLY.
|
||||
|
||||
Usage: test_CPU.py [<options>] <filename>
|
||||
|
||||
where <filename> is a file of test instructions and
|
||||
<options> is one or more of
|
||||
-h prints this help and stops
|
||||
"""
|
||||
|
||||
# We implement a small interpreter to test the CPU. The test code is read in
|
||||
# from a file:
|
||||
#
|
||||
# # LAW
|
||||
# setreg ac 012345; setreg l 1; setreg pc 0100; setmem 0100 [LAW 0]; RUN; checkcycles 1; checkreg pc 0101; checkreg ac 0
|
||||
# setreg ac 012345; setreg l 0; setmem 0100 [LAW 0]; RUN 0100
|
||||
# checkcycles 1; checkreg pc 0101; checkreg ac 0
|
||||
#
|
||||
# The instructions are delimited by ';' characters. A line beginning with a
|
||||
# TAB character is a continuation of the previous line.
|
||||
# Lines with '#' in column 1 are comments.
|
||||
#
|
||||
# The test instructions are:
|
||||
# setreg <name> <value>
|
||||
# where <name> is one of AC, L or PC, value is any value
|
||||
# (all registers are set to 0 initially)
|
||||
#
|
||||
# setmem <addr> <value>
|
||||
# where <addr> is an address and value is any value OR
|
||||
# [<instruction>] where the value is the assembled opcode
|
||||
#
|
||||
# run [<addr>]
|
||||
# execute one instruction, if optional <addr> is used PC := addr before
|
||||
#
|
||||
# checkcycles <number>
|
||||
# check number of executed cycles is <number>
|
||||
#
|
||||
# checkreg <name> <value>
|
||||
# check register (AC, L or PC) has value <value>
|
||||
#
|
||||
# checkmem <addr> <value>
|
||||
# check that memory at <addr> has <value>
|
||||
#
|
||||
# allreg <value>
|
||||
# sets all registers to <value>
|
||||
# a "allreg 0" is assumed before each test
|
||||
#
|
||||
# allmem <value>
|
||||
# sets all of memory to <value>
|
||||
# a "allmem 0" is assumed before each test
|
||||
#
|
||||
# In addition, all of memory is checked for changed values after execution
|
||||
# except where an explicit "checkmem <addr> <value>" has been performed.
|
||||
# Additionally, registers that aren't explicitly checked are tested to make
|
||||
# sure they didn't change.
|
||||
#
|
||||
# If a test line finds no error, just print the fully assembled test line.
|
||||
# If any errors are found, print line followed by all errors.
|
||||
|
||||
|
||||
import MainCPU
|
||||
import Memory
|
||||
|
||||
|
||||
def setreg(name, value):
|
||||
"""Set register to a value.
|
||||
|
||||
Remember value to check later.
|
||||
"""
|
||||
|
||||
global RegValues
|
||||
|
||||
RegValues[name] = value
|
||||
exec "MainCPU.%s = %07o" % (name, value)
|
||||
|
||||
def setmem(addr, value):
|
||||
"""Set memory location to a value."""
|
||||
|
||||
global MemValues
|
||||
|
||||
MemValues[addr] = value
|
||||
Memory.memory[addr] = value
|
||||
|
||||
|
||||
def allmem(value):
|
||||
"""Set all of memory to a value.
|
||||
|
||||
Remember value to check later.
|
||||
"""
|
||||
|
||||
global MemAllValue
|
||||
|
||||
MemAllValue = value
|
||||
for mem in range(Memory.MAXMEM):
|
||||
Memory.memory[mem] = value
|
||||
|
||||
def allreg(value):
|
||||
"""Set all registers to a value."""
|
||||
|
||||
global RegAllValue
|
||||
|
||||
RegAllValue = value
|
||||
MainCPU.AC = value
|
||||
MainCPU.L = value & 1
|
||||
MainCPU.PC = value
|
||||
|
||||
def execute(test):
|
||||
"""Execute test string in 'test'."""
|
||||
|
||||
global RegValues, MemValues
|
||||
global RegAllValue, MemAllValue
|
||||
|
||||
# set globals
|
||||
RegValues = {}
|
||||
MemValues = {}
|
||||
RegAllValue = {}
|
||||
MemAllValue = {}
|
||||
|
||||
# clear memory and registers to 0 first
|
||||
memset(0)
|
||||
regset(0)
|
||||
|
||||
# interpret the test instructions
|
||||
instructions = test.split(';')
|
||||
for op in instructions:
|
||||
print op
|
||||
|
||||
|
||||
|
||||
|
||||
def main(filename):
|
||||
"""Execute CPU tests from 'filename'."""
|
||||
|
||||
# get all tests from file
|
||||
with open(filename, 'rb') as fd:
|
||||
lines = fd.readlines()
|
||||
|
||||
# read lines, join continued, get complete tests
|
||||
tests = []
|
||||
test = ''
|
||||
for line in lines:
|
||||
line = line[:-1] # strip newline
|
||||
|
||||
if line[0] == '#': # a comment
|
||||
continue
|
||||
|
||||
if line[0] == '\t': # continuation
|
||||
if test:
|
||||
test += '; '
|
||||
test += line[1:]
|
||||
else: # beginning of new test
|
||||
if test:
|
||||
tests.append(test)
|
||||
test = line
|
||||
|
||||
# flush last test
|
||||
if test:
|
||||
tests.append(test)
|
||||
|
||||
# now do each test
|
||||
for test in tests:
|
||||
execute(test)
|
||||
|
||||
|
||||
################################################################################
|
||||
|
||||
if __name__ == '__main__':
|
||||
main('CPU.test')
|
||||
Reference in New Issue
Block a user