Add memory loads and stores to simulator
authorMichael Nolan <mtnolan2640@gmail.com>
Mon, 23 Mar 2020 14:53:53 +0000 (10:53 -0400)
committerMichael Nolan <mtnolan2640@gmail.com>
Mon, 23 Mar 2020 14:53:53 +0000 (10:53 -0400)
src/soc/simulator/internalop_sim.py
src/soc/simulator/test_sim.py

index 035277b4f7a3ad7c8e7970b05c30ae2c1750cd75..2f435dc7c9f46c064d03300a02a6b3a85b113868 100644 (file)
@@ -2,11 +2,29 @@ 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)
+import math
 
 
 class MemorySim:
-    def __init__(self):
+    def __init__(self, bytes_per_word=8):
         self.mem = {}
+        self.bytes_per_word = bytes_per_word
+        self.word_log2 = math.ceil(math.log2(bytes_per_word))
+
+    # TODO: Implement ld/st of lesser width
+    def ld(self, address):
+        address = address >> self.word_log2
+        if address in self.mem:
+            val = self.mem[address]
+        else:
+            val = 0
+        print("Read {:x} from addr {:x}".format(val, address))
+        return val
+
+    def st(self, address, value):
+        address = address >> self.word_log2
+        print("Writing {:x} to addr {:x}".format(value, address))
+        self.mem[address] = value
 
 
 class RegFile:
@@ -23,6 +41,13 @@ class RegFile:
         print("Read {:x} from reg r{}".format(val, regnum))
         return val
 
+    def assert_gprs(self, gprs):
+        for k,v in list(gprs.items()):
+            reg_val = self.read_reg(k)
+            msg = "reg r{} got {:x}, expecting {:x}".format(
+                k, reg_val, v)
+            assert reg_val == v, msg
+
 
 class InternalOpSimulator:
     def __init__(self):
@@ -36,7 +61,7 @@ class InternalOpSimulator:
         elif internal_op == InternalOp.OP_AND.value:
             return op1 & op2
         else:
-            return 0
+            assert(False, "Not implemented")
 
     def alu_op(self, pdecode2):
         internal_op = yield pdecode2.dec.op.internal_op
@@ -65,7 +90,28 @@ class InternalOpSimulator:
             ro_sel = yield pdecode2.e.write_reg.data
             self.regfile.write_reg(ro_sel, result)
 
+    def mem_op(self, pdecode2):
+        internal_op = yield pdecode2.dec.op.internal_op
+        addr_reg = yield pdecode2.e.read_reg1.data
+        addr = self.regfile.read_reg(addr_reg)
+        
+        imm_ok = yield pdecode2.e.imm_data.ok
+        if imm_ok:
+            imm = yield pdecode2.e.imm_data.data
+            addr += imm
+        if internal_op == InternalOp.OP_STORE.value:
+            val_reg = yield pdecode2.e.read_reg3.data
+            val = self.regfile.read_reg(val_reg)
+            self.mem_sim.st(addr, val)
+        elif internal_op == InternalOp.OP_LOAD.value:
+            dest_reg = yield pdecode2.e.write_reg.data
+            val = self.mem_sim.ld(addr)
+            self.regfile.write_reg(dest_reg, val)
+
+
     def execute_op(self, pdecode2):
         function = yield pdecode2.dec.op.function_unit
         if function == Function.ALU.value:
             yield from self.alu_op(pdecode2)
+        elif function == Function.LDST.value:
+            yield from self.mem_op(pdecode2)
index d26aaf72bc9744dae9a1c6432e06243a15ef9f50..3a5e37b92f1795e885abd82513975527251294ee 100644 (file)
@@ -68,6 +68,26 @@ class DecoderTestCase(FHDLTestCase):
         simulator = InternalOpSimulator()
 
         self.run_tst(gen, simulator)
+        simulator.regfile.assert_gprs(
+            {1: 0x1234,
+             2: 0x5678,
+             3: 0x68ac,
+             4: 0x1230})
+
+    def test_ldst(self):
+        lst = ["addi 1, 0, 0x1234",
+               "addi 2, 0, 0x5678",
+               "stw  1, 0(2)",
+               "lwz  3, 0(2)"]
+        gen = InstrList(lst)
+
+        simulator = InternalOpSimulator()
+
+        self.run_tst(gen, simulator)
+        simulator.regfile.assert_gprs(
+            {1: 0x1234,
+             2: 0x5678,
+             3: 0x1234})
 
 
 if __name__ == "__main__":