Add test for alu against simulator
authorMichael Nolan <mtnolan2640@gmail.com>
Fri, 8 May 2020 19:55:26 +0000 (15:55 -0400)
committerMichael Nolan <mtnolan2640@gmail.com>
Fri, 8 May 2020 19:55:26 +0000 (15:55 -0400)
src/soc/alu/pipe_data.py
src/soc/alu/test/test_pipe_caller.py [new file with mode: 0644]

index fa48f4ee8b0d750759f509d47df1663278634674..083ca105364119ccab23ee6968566de11d9ef19e 100644 (file)
@@ -11,11 +11,10 @@ class IntegerData:
         self.muxid = self.ctx.muxid
 
     def __iter__(self):
-        yield from self.op
         yield from self.ctx
 
     def eq(self, i):
-        return [self.op.eq(i.op), self.ctx.eq(i.ctx)]
+        return [self.ctx.eq(i.ctx)]
 
 
 class ALUInputData(IntegerData):
@@ -74,6 +73,7 @@ class IntPipeSpec:
         self.id_wid = id_wid
         self.op_wid = op_wid
         self.opkls = lambda _: CompALUOpSubset(name="op")
+        self.stage = None
 
 class ALUPipeSpec(IntPipeSpec):
     def __init__(self, id_wid, op_wid):
diff --git a/src/soc/alu/test/test_pipe_caller.py b/src/soc/alu/test/test_pipe_caller.py
new file mode 100644 (file)
index 0000000..7c069ed
--- /dev/null
@@ -0,0 +1,133 @@
+from nmigen import Module, Signal
+from nmigen.back.pysim import Simulator, Delay
+from nmigen.test.utils import FHDLTestCase
+from nmigen.cli import rtlil
+import unittest
+from soc.decoder.isa.caller import ISACaller
+from soc.decoder.power_decoder import (create_pdecode)
+from soc.decoder.power_decoder2 import (PowerDecode2)
+from soc.decoder.selectable_int import SelectableInt
+from soc.simulator.program import Program
+from soc.decoder.isa.all import ISA
+
+
+from soc.alu.pipeline import ALUBasePipe
+from soc.alu.alu_input_record import CompALUOpSubset
+from soc.alu.pipe_data import ALUPipeSpec
+import random
+
+def get_rec_width(rec):
+    recwidth = 0
+    # Setup random inputs for dut.op
+    for p in rec.ports():
+        width = p.width
+        recwidth += width
+    return recwidth
+
+
+def connect_alu(comb, alu, dec2):
+    op = alu.p.data_i.ctx.op
+
+    comb += op.insn_type.eq(dec2.e.insn_type)
+    comb += op.fn_unit.eq(dec2.e.fn_unit)
+    comb += op.nia.eq(dec2.e.nia)
+    comb += op.lk.eq(dec2.e.lk)
+    comb += op.invert_a.eq(dec2.e.invert_a)
+    comb += op.invert_out.eq(dec2.e.invert_out)
+    comb += op.input_carry.eq(dec2.e.input_carry)
+    comb += op.output_carry.eq(dec2.e.output_carry)
+    comb += op.input_cr.eq(dec2.e.input_cr)
+    comb += op.output_cr.eq(dec2.e.output_cr)
+    comb += op.is_32bit.eq(dec2.e.is_32bit)
+    comb += op.is_signed.eq(dec2.e.is_signed)
+    comb += op.data_len.eq(dec2.e.data_len)
+    comb += op.byte_reverse.eq(dec2.e.byte_reverse)
+    comb += op.sign_extend.eq(dec2.e.sign_extend)
+
+
+
+class ALUTestCase(FHDLTestCase):
+    def run_tst(self, program, initial_regs):
+        m = Module()
+        comb = m.d.comb
+        instruction = Signal(32)
+
+        pdecode = create_pdecode()
+
+        m.submodules.pdecode2 = pdecode2 = PowerDecode2(pdecode)
+
+        rec = CompALUOpSubset()
+
+        pspec = ALUPipeSpec(id_wid=2, op_wid=get_rec_width(rec))
+        m.submodules.alu = alu = ALUBasePipe(pspec)
+
+        connect_alu(comb, alu, pdecode2)
+        comb += alu.p.data_i.a.eq(initial_regs[1])
+        comb += alu.p.data_i.b.eq(initial_regs[2])
+        comb += alu.p.valid_i.eq(1)
+        comb += alu.n.ready_i.eq(1)
+        simulator = ISA(pdecode2, initial_regs)
+        comb += pdecode2.dec.raw_opcode_in.eq(instruction)
+        sim = Simulator(m)
+        gen = program.generate_instructions()
+
+        sim.add_clock(1e-6)
+        def process():
+            instructions = list(zip(gen, program.assembly.splitlines()))
+
+            index = simulator.pc.CIA.value//4
+            while index < len(instructions):
+                ins, code = instructions[index]
+
+                print("0x{:X}".format(ins & 0xffffffff))
+                print(code)
+
+                # ask the decoder to decode this binary data (endian'd)
+                yield pdecode2.dec.bigendian.eq(0)  # little / big?
+                yield instruction.eq(ins)          # raw binary instr.
+                yield 
+                opname = code.split(' ')[0]
+                yield from simulator.call(opname)
+                index = simulator.pc.CIA.value//4
+
+                vld = yield alu.n.valid_o
+                while not vld:
+                    yield
+                    vld = yield alu.n.valid_o
+                yield
+                alu_out = yield alu.n.data_o.o
+                self.assertEqual(simulator.gpr(3), alu_out)
+
+        sim.add_sync_process(process)
+        with sim.write_vcd("simulator.vcd", "simulator.gtkw",
+                           traces=[]):
+            sim.run()
+        return simulator
+
+    def run_tst_program(self, prog, initial_regs=[0] * 32):
+        simulator = self.run_tst(prog, initial_regs)
+        simulator.gpr.dump()
+        return simulator
+
+    def test_rand(self):
+        insns = ["add", "add.", "and", "or", "xor"]
+        for i in range(20):
+            choice = random.choice(insns)
+            lst = [f"{choice} 3, 1, 2"]
+            initial_regs = [0] * 32
+            initial_regs[1] = random.randint(0, (1<<64)-1)
+            initial_regs[2] = random.randint(0, (1<<64)-1)
+            with Program(lst) as program:
+                sim = self.run_tst_program(program, initial_regs)
+
+    def test_ilang(self):
+        rec = CompALUOpSubset()
+
+        pspec = ALUPipeSpec(id_wid=2, op_wid=get_rec_width(rec))
+        alu = ALUBasePipe(pspec)
+        vl = rtlil.convert(alu, ports=[])
+        with open("pipeline.il", "w") as f:
+            f.write(vl)
+
+if __name__ == "__main__":
+    unittest.main()