From 1144f8a2396ae261bb9b7ed11071e4f87faf74c3 Mon Sep 17 00:00:00 2001 From: Michael Nolan Date: Thu, 19 Mar 2020 13:38:44 -0400 Subject: [PATCH] Factor out instruction generation and testing from simulation --- src/soc/decoder/test/test_decoder_gas.py | 81 +++++++++++++----------- 1 file changed, 44 insertions(+), 37 deletions(-) diff --git a/src/soc/decoder/test/test_decoder_gas.py b/src/soc/decoder/test/test_decoder_gas.py index 8dd81ef2..b5c3eed3 100644 --- a/src/soc/decoder/test/test_decoder_gas.py +++ b/src/soc/decoder/test/test_decoder_gas.py @@ -14,32 +14,51 @@ import subprocess import struct import random -ops = { - InternalOp.OP_ADD: "add", - InternalOp.OP_AND: "and", - InternalOp.OP_OR: "or"} class Register: def __init__(self, num): self.num = num +class RegRegOp: + def __init__(self): + self.ops = { + InternalOp.OP_ADD: "add", + InternalOp.OP_AND: "and", + InternalOp.OP_OR: "or"} + self.opcode = random.choice(list(self.ops.keys())) + self.r1 = Register(random.randrange(32)) + self.r2 = Register(random.randrange(32)) + self.r3 = Register(random.randrange(32)) + + def generate_instruction(self): + opcodestr = self.ops[self.opcode] + string = "{} {}, {}, {}\n".format(opcodestr, + self.r1.num, + self.r2.num, + self.r3.num) + return string -class DecoderTestCase(FHDLTestCase): - def generate_opcode_string(self, internalop, r1, r2, op3): - opcodestr = ops[internalop] - if isinstance(op3, Register): - immstring = "" - op3str = op3.num + def check(self, pdecode2): + r1sel = yield pdecode2.e.write_reg.data + r3sel = yield pdecode2.e.read_reg2.data + + # For some reason r2 gets decoded either in read_reg1 + # or read_reg3 + form = yield pdecode2.dec.op.form + if form == Form.X.value: + r2sel = yield pdecode2.e.read_reg3.data else: - immstring = "i" - op3str = str(op3) - string = "{}{} {}, {}, {}\n".format(opcodestr, - immstring, - r1.num, - r2.num, - op3str) - return string + r2sel = yield pdecode2.e.read_reg1.data + assert(r1sel == self.r1.num) + assert(r3sel == self.r3.num) + assert(r2sel == self.r2.num) + + opc_out = yield pdecode2.dec.op.internal_op + assert(opc_out == self.opcode.value) + + +class DecoderTestCase(FHDLTestCase): def get_assembled_instruction(self, instruction): with tempfile.NamedTemporaryFile(suffix=".o") as outfile: @@ -59,7 +78,8 @@ class DecoderTestCase(FHDLTestCase): binary = struct.unpack('>i', binfile.read(4))[0] return binary - def test_decoder(self): + def run_tst(self, kls): + random.seed(1) m = Module() comb = m.d.comb instruction = Signal(32) @@ -73,13 +93,9 @@ class DecoderTestCase(FHDLTestCase): def process(): for i in range(10): - opcode = random.choice(list(ops.keys())) - r1 = Register(random.randrange(32)) - r2 = Register(random.randrange(32)) - r3 = Register(random.randrange(32)) + checker = kls() - instruction_str = self.generate_opcode_string( - opcode, r1, r2, r3) + instruction_str = checker.generate_instruction() print("instr", instruction_str.strip()) instruction_bin = self.get_assembled_instruction( instruction_str) @@ -88,23 +104,14 @@ class DecoderTestCase(FHDLTestCase): yield instruction.eq(instruction_bin) yield Delay(1e-6) - r1sel = yield pdecode2.e.write_reg.data - r3sel = yield pdecode2.e.read_reg2.data + checker.check(pdecode2) - # For some reason r2 gets decoded either in read_reg1 - # or read_reg3 - form = yield pdecode2.dec.op.form - if form == Form.X.value: - r2sel = yield pdecode2.e.read_reg3.data - else: - r2sel = yield pdecode2.e.read_reg1.data - assert(r1sel == r1.num) - assert(r3sel == r3.num) - assert(r2sel == r2.num) sim.add_process(process) with sim.write_vcd("gas.vcd", "gas.gtkw", traces=[pdecode2.ports()]): sim.run() + def test_reg_reg(self): + self.run_tst(RegRegOp) if __name__ == "__main__": -- 2.30.2