|
|
|
from riscemu.colors import FMT_ERROR, FMT_NONE, FMT_BOLD, FMT_GREEN
|
|
|
|
from riscemu.instructions import InstructionSet
|
|
|
|
from riscemu.types import Instruction, CPU
|
|
|
|
from riscemu.decoder import RISCV_REGS
|
|
|
|
|
|
|
|
FMT_SUCCESS = FMT_GREEN + FMT_BOLD
|
|
|
|
|
|
|
|
|
|
|
|
def assert_equals(ins: Instruction, cpu: CPU):
|
|
|
|
a, b = (get_arg_from_ins(ins, i, cpu) for i in (0, 2))
|
|
|
|
return a == b
|
|
|
|
|
|
|
|
|
|
|
|
def assert_equals_mem(ins: Instruction, cpu: CPU):
|
|
|
|
a, b = (get_arg_from_ins(ins, i, cpu) for i in (0, 2))
|
|
|
|
a = cpu.mmu.read_int(a)
|
|
|
|
return a == b
|
|
|
|
|
|
|
|
|
|
|
|
def assert_in(ins: Instruction, cpu: CPU):
|
|
|
|
a = get_arg_from_ins(ins, 0, cpu)
|
|
|
|
others = [get_arg_from_ins(ins, i, cpu) for i in range(2, len(ins.args))]
|
|
|
|
return a in others
|
|
|
|
|
|
|
|
|
|
|
|
def _not(func):
|
|
|
|
def test(ins: Instruction, cpu: CPU):
|
|
|
|
return not func(ins, cpu)
|
|
|
|
|
|
|
|
return test
|
|
|
|
|
|
|
|
|
|
|
|
def get_arg_from_ins(ins: Instruction, num: int, cpu: CPU):
|
|
|
|
a = ins.args[num]
|
|
|
|
if a in RISCV_REGS:
|
|
|
|
return cpu.regs.get(a)
|
|
|
|
return ins.get_imm(num)
|
|
|
|
|
|
|
|
|
|
|
|
assert_ops = {
|
|
|
|
"==": assert_equals,
|
|
|
|
"!=": _not(assert_equals),
|
|
|
|
"in": assert_in,
|
|
|
|
"not_in": _not(assert_in),
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
class Z_test(InstructionSet):
|
|
|
|
def __init__(self, cpu: "CPU"):
|
|
|
|
print(
|
|
|
|
"[Test] loading testing ISA, this is only meant for running testcases and is not part of the RISC-V ISA!"
|
|
|
|
)
|
|
|
|
self.failed = False
|
|
|
|
super().__init__(cpu)
|
|
|
|
|
|
|
|
def instruction_assert(self, ins: Instruction):
|
|
|
|
if len(ins.args) < 3:
|
|
|
|
print(
|
|
|
|
FMT_ERROR + "[Test] Unknown assert statement: {}".format(ins) + FMT_NONE
|
|
|
|
)
|
|
|
|
return
|
|
|
|
op = ins.args[1]
|
|
|
|
if op not in assert_ops:
|
|
|
|
print(
|
|
|
|
FMT_ERROR
|
|
|
|
+ "[Test] Unknown operation statement: {} in {}".format(op, ins)
|
|
|
|
+ FMT_NONE
|
|
|
|
)
|
|
|
|
return
|
|
|
|
|
|
|
|
if assert_ops[op](ins, self.cpu):
|
|
|
|
print(FMT_SUCCESS + "[TestCase] 🟢 passed assertion {}".format(ins))
|
|
|
|
else:
|
|
|
|
print(FMT_ERROR + "[TestCase] 🔴 failed assertion {}".format(ins))
|
|
|
|
self.cpu.halted = True
|
|
|
|
self.failed = True
|
|
|
|
|
|
|
|
def instruction_fail(self, ins: Instruction):
|
|
|
|
print(FMT_ERROR + "[TestCase] 🔴 reached fail instruction! {}".format(ins))
|
|
|
|
self.cpu.halted = True
|
|
|
|
self.failed = True
|