Begin adding backend simulator
authorMichael Nolan <mtnolan2640@gmail.com>
Mon, 23 Mar 2020 14:21:44 +0000 (10:21 -0400)
committerMichael Nolan <mtnolan2640@gmail.com>
Mon, 23 Mar 2020 14:24:21 +0000 (10:24 -0400)
src/soc/simulator/internalop_sim.py [new file with mode: 0644]
src/soc/simulator/test_sim.py [new file with mode: 0644]

diff --git a/src/soc/simulator/internalop_sim.py b/src/soc/simulator/internalop_sim.py
new file mode 100644 (file)
index 0000000..035277b
--- /dev/null
@@ -0,0 +1,71 @@
+from soc.decoder.power_enums import (Function, Form, InternalOp,
+                         In1Sel, In2Sel, In3Sel, OutSel, RC, LdstLen,
+                         CryIn, get_csv, single_bit_flags,
+                         get_signal_name, default_values)
+
+
+class MemorySim:
+    def __init__(self):
+        self.mem = {}
+
+
+class RegFile:
+    def __init__(self):
+        self.regfile = [0] * 32
+        self.sprs = {}
+
+    def write_reg(self, regnum, value):
+        print("Writing {:x} to reg r{}".format(value, regnum))
+        self.regfile[regnum] = value
+
+    def read_reg(self, regnum):
+        val = self.regfile[regnum]
+        print("Read {:x} from reg r{}".format(val, regnum))
+        return val
+
+
+class InternalOpSimulator:
+    def __init__(self):
+        self.mem_sim = MemorySim()
+        self.regfile = RegFile()
+
+    def execute_alu_op(self, op1, op2, internal_op):
+        print(internal_op)
+        if internal_op == InternalOp.OP_ADD.value:
+            return op1 + op2
+        elif internal_op == InternalOp.OP_AND.value:
+            return op1 & op2
+        else:
+            return 0
+
+    def alu_op(self, pdecode2):
+        internal_op = yield pdecode2.dec.op.internal_op
+        operand1 = 0
+        operand2 = 0
+        result = 0
+        r1_ok = yield pdecode2.e.read_reg1.ok
+        r2_ok = yield pdecode2.e.read_reg2.ok
+        r3_ok = yield pdecode2.e.read_reg3.ok
+        imm_ok = yield pdecode2.e.imm_data.ok
+        if r1_ok:
+            r1_sel = yield pdecode2.e.read_reg1.data
+            operand1 = self.regfile.read_reg(r1_sel)
+        elif r3_ok:
+            r3_sel = yield pdecode2.e.read_reg3.data
+            operand1 = self.regfile.read_reg(r3_sel)
+        if r2_ok:
+            r2_sel = yield pdecode2.e.read_reg2.data
+            operand2 = self.regfile.read_reg(r2_sel)
+        if imm_ok:
+            operand2 = yield pdecode2.e.imm_data.data
+
+        result = self.execute_alu_op(operand1, operand2, internal_op)
+        ro_ok = yield pdecode2.e.write_reg.ok
+        if ro_ok:
+            ro_sel = yield pdecode2.e.write_reg.data
+            self.regfile.write_reg(ro_sel, result)
+
+    def execute_op(self, pdecode2):
+        function = yield pdecode2.dec.op.function_unit
+        if function == Function.ALU.value:
+            yield from self.alu_op(pdecode2)
diff --git a/src/soc/simulator/test_sim.py b/src/soc/simulator/test_sim.py
new file mode 100644 (file)
index 0000000..d26aaf7
--- /dev/null
@@ -0,0 +1,74 @@
+from nmigen import Module, Signal
+from nmigen.back.pysim import Simulator, Delay
+from nmigen.test.utils import FHDLTestCase
+import unittest
+from soc.simulator.internalop_sim import InternalOpSimulator
+from soc.decoder.power_decoder import (create_pdecode)
+from soc.decoder.power_enums import (Function, InternalOp,
+                                     In1Sel, In2Sel, In3Sel,
+                                     OutSel, RC, LdstLen, CryIn,
+                                     single_bit_flags, Form, SPR,
+                                     get_signal_name, get_csv)
+from soc.decoder.power_decoder2 import (PowerDecode2)
+from soc.simulator.gas import get_assembled_instruction
+
+
+class Register:
+    def __init__(self, num):
+        self.num = num
+
+
+class InstrList:
+    def __init__(self, lst):
+        self.instrs = [x + "\n" for x in lst]
+
+    def generate_instructions(self):
+        return iter(self.instrs)
+
+
+class DecoderTestCase(FHDLTestCase):
+
+    def run_tst(self, generator, simulator):
+        m = Module()
+        comb = m.d.comb
+        instruction = Signal(32)
+
+        pdecode = create_pdecode()
+
+        m.submodules.pdecode2 = pdecode2 = PowerDecode2(pdecode)
+        comb += pdecode2.dec.raw_opcode_in.eq(instruction)
+        sim = Simulator(m)
+        gen = generator.generate_instructions()
+
+        def process():
+            for ins in gen:
+                print("instr", ins.strip())
+
+                # turn the instruction into binary data (endian'd)
+                ibin = get_assembled_instruction(ins, 0)
+
+                # ask the decoder to decode this binary data (endian'd)
+                yield pdecode2.dec.bigendian.eq(0)  # little / big?
+                yield instruction.eq(ibin)          # raw binary instr.
+                yield Delay(1e-6)
+                yield from simulator.execute_op(pdecode2)
+
+        sim.add_process(process)
+        with sim.write_vcd("simulator.vcd", "simulator.gtkw",
+                           traces=[pdecode2.ports()]):
+            sim.run()
+
+    def test_example(self):
+        lst = ["addi 1, 0, 0x1234",
+               "addi 2, 0, 0x5678",
+               "add  3, 1, 2",
+               "and  4, 1, 2"]
+        gen = InstrList(lst)
+
+        simulator = InternalOpSimulator()
+
+        self.run_tst(gen, simulator)
+
+
+if __name__ == "__main__":
+    unittest.main()