Factor out instruction generation and testing from simulation
authorMichael Nolan <mtnolan2640@gmail.com>
Thu, 19 Mar 2020 17:38:44 +0000 (13:38 -0400)
committerMichael Nolan <mtnolan2640@gmail.com>
Thu, 19 Mar 2020 17:38:44 +0000 (13:38 -0400)
src/soc/decoder/test/test_decoder_gas.py

index 8dd81ef29dbb6ab2ecec424754383e0593c9cba1..b5c3eed31e1143173e4d095bf112463fc5c001cc 100644 (file)
@@ -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__":