sort-of got binary execution test working
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Tue, 7 Jul 2020 23:21:48 +0000 (00:21 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Tue, 7 Jul 2020 23:21:56 +0000 (00:21 +0100)
src/soc/bus/test/test_minerva.py
src/soc/decoder/power_decoder2.py
src/soc/simple/core.py
src/soc/simple/issuer.py
src/soc/simple/test/test_issuer.py
src/soc/simple/test/test_microwatt.py [new file with mode: 0644]

index 780fcba73474b195bc22a59c8f9e2ab3f4543d8c..93434d6ef814ad436adef707eaefac3639227bdf 100644 (file)
@@ -11,8 +11,15 @@ class TestSRAMBareLoadStoreUnit(BareLoadStoreUnit):
     def elaborate(self, platform):
         m = super().elaborate(platform)
         comb = m.d.comb
-        # small 16-entry Memory
-        self.mem = memory = Memory(width=self.data_wid, depth=32)
+        # small 32-entry Memory
+        if (hasattr(pspec, "dmem_test_depth") and
+            isinstance(pspec.dmem_test_depth, int)):
+            depth = pspec.dmem_test_depth
+        else:
+            depth = 32
+        print ("TestSRAMBareLoadStoreUnit depth", depth)
+
+        self.mem = memory = Memory(width=self.data_wid, depth=depth)
         m.submodules.sram = sram = SRAM(memory=memory, granularity=8,
                                         features={'cti', 'bte', 'err'})
         dbus = self.dbus
@@ -37,7 +44,7 @@ class TestSRAMBareLoadStoreUnit(BareLoadStoreUnit):
 class TestSRAMBareFetchUnit(BareFetchUnit):
     def __init__(self, pspec):
         super().__init__(pspec)
-        # small 16-entry Memory
+        # default: small 32-entry Memory
         if (hasattr(pspec, "imem_test_depth") and
             isinstance(pspec.imem_test_depth, int)):
             depth = pspec.imem_test_depth
index 612a44d83cbd44ec0b8d4f4f1c851ea91d52cc05..20c40075617bae978113b3fd8259552c3800afc0 100644 (file)
@@ -544,7 +544,7 @@ class PowerDecode2(Elaboratable):
 
         self.dec = dec
         self.e = Decode2ToExecute1Type()
-        self.valid = Signal()
+        self.valid = Signal() # sync signal
 
     def ports(self):
         return self.dec.ports() + self.e.ports()
@@ -587,13 +587,8 @@ class PowerDecode2(Elaboratable):
 
         # set up instruction, pick fn unit
         comb += e.nia.eq(0)    # XXX TODO (or remove? not sure yet)
-        fu = op.function_unit
-        with m.If((fu == Function.NONE) &
-                   (op.internal_op != InternalOp.OP_ATTN)):
-            comb += do.insn_type.eq(InternalOp.OP_ILLEGAL)
-        with m.Else():
-            comb += do.insn_type.eq(op.internal_op)
-        comb += do.fn_unit.eq(fu)
+        comb += do.insn_type.eq(op.internal_op) # no op: defaults to OP_ILLEGAL
+        comb += do.fn_unit.eq(op.function_unit)
 
         # registers a, b, c and out and out2 (LD/ST EA)
         comb += e.read_reg1.eq(dec_a.reg_out)
index 382a8588dac2d35c2ea1945259f4b8b46eedd75c..f5dd58e352d336285c516d559d6bb7e0fd087083 100644 (file)
@@ -126,10 +126,20 @@ class NonProductionCore(Elaboratable):
         can_run = Signal(reset_less=True)
         comb += can_run.eq(self.ivalid_i & ~core_stopped)
 
+        # sigh - need a NOP counter
+        counter = Signal(2)
+        with m.If(counter != 0):
+            sync += counter.eq(counter - 1)
+        comb += self.busy_o.eq(counter != 0)
+
         # check for ATTN: halt if true
         with m.If(self.ivalid_i & (dec2.e.do.insn_type == InternalOp.OP_ATTN)):
             m.d.sync += core_stopped.eq(1)
 
+        with m.Elif(self.ivalid_i & (dec2.e.do.insn_type == InternalOp.OP_NOP)):
+            sync += counter.eq(2)
+            comb += self.busy_o.eq(1)
+
         with m.Else():
             # connect up instructions.  only one is enabled at any given time
             for funame, fu in fus.items():
index 45e6b283325bb6bc3567889930ad606d78ecad78..fc0bbd0bb894e28098b3d74d9df974f8c76ce829 100644 (file)
@@ -24,6 +24,7 @@ from soc.regfile.regfiles import FastRegs
 from soc.simple.core import NonProductionCore
 from soc.config.test.test_loadstore import TestMemPspec
 from soc.config.ifetch import ConfigFetchUnit
+from soc.decoder.power_enums import InternalOp
 
 
 class TestIssuer(Elaboratable):
@@ -75,10 +76,6 @@ class TestIssuer(Elaboratable):
         comb += self.pc_o.eq(cur_pc)
         ilatch = Signal(32)
 
-        # allow debug access to current instruction and pc
-        self._current_insn = current_insn
-        self._cur_pc = cur_pc
-
         # next instruction (+4 on current)
         nia = Signal(64, reset_less=True)
         comb += nia.eq(cur_pc + 4)
@@ -90,6 +87,8 @@ class TestIssuer(Elaboratable):
         core_be_i = core.bigendian_i      # bigendian mode
         core_opcode_i = core.raw_opcode_i # raw opcode
 
+        insn_type = core.pdecode2.e.do.insn_type
+
         # only run if not in halted state
         with m.If(~core.core_terminated_o):
 
@@ -128,16 +127,16 @@ class TestIssuer(Elaboratable):
                         # not busy: instruction fetched
                         insn = self.imem.f_instr_o.word_select(cur_pc[2], 32)
                         comb += current_insn.eq(insn)
-                        comb += core_ivalid_i.eq(1) # say instruction is valid
+                        comb += core_ivalid_i.eq(1) # instruction is valid
                         comb += core_issue_i.eq(1)  # and issued 
-                        comb += core_be_i.eq(0)     # little-endian mode
                         comb += core_opcode_i.eq(current_insn) # actual opcode
                         sync += ilatch.eq(current_insn)
                         m.next = "INSN_ACTIVE" # move to "wait completion" 
 
                 # instruction started: must wait till it finishes
                 with m.State("INSN_ACTIVE"):
-                    comb += core_ivalid_i.eq(1) # say instruction is valid
+                    with m.If(insn_type != InternalOp.OP_NOP):
+                        comb += core_ivalid_i.eq(1) # say instruction is valid
                     comb += core_opcode_i.eq(ilatch) # actual opcode
                     with m.If(self.fast_nia.wen):
                         sync += pc_changed.eq(1)
index f4e4363aad94f8d44f9a336d7a054f8227a85fb3..e0c404faa968746dd4c05916950c698580497ba1 100644 (file)
@@ -52,13 +52,14 @@ def setup_i_memory(imem, startaddr, instructions):
         msbs = (startaddr>>1) & mask
         val = yield mem._array[msbs]
         if insn != 0:
-            print ("before set", hex(startaddr), hex(msbs), hex(val), hex(insn))
+            print ("before set", hex(4*startaddr),
+                                 hex(msbs), hex(val), hex(insn))
         lsb = 1 if (startaddr & 1) else 0
         val = (val | (insn << (lsb*32))) & mask
         yield mem._array[msbs].eq(val)
         yield Settle()
         if insn != 0:
-            print ("after  set", hex(startaddr), hex(msbs), hex(val))
+            print ("after  set", hex(4*startaddr), hex(msbs), hex(val))
             print ("instr: %06x 0x%x %s %08x" % (4*startaddr, insn, code, val))
         startaddr += 1
         startaddr = startaddr & mask
@@ -144,7 +145,8 @@ class TestRunner(FHDLTestCase):
                     yield Settle()
 
                     # wait until executed
-                    yield from wait_for_busy_hi(core)
+                    #yield from wait_for_busy_hi(core)
+                    yield
                     yield from wait_for_busy_clear(core)
 
                     terminated = yield core.core_terminated_o
diff --git a/src/soc/simple/test/test_microwatt.py b/src/soc/simple/test/test_microwatt.py
new file mode 100644 (file)
index 0000000..2cf0521
--- /dev/null
@@ -0,0 +1,150 @@
+from soc.simulator.program import Program
+from soc.fu.test.common import TestCase
+
+import unittest
+
+from nmigen import Module, Signal
+from nmigen.back.pysim import Simulator, Delay, Settle
+from nmutil.formaltest import FHDLTestCase
+
+from soc.simple.issuer import TestIssuer
+
+from soc.config.test.test_loadstore import TestMemPspec
+from soc.simple.test.test_core import (setup_regs, check_regs,
+                                       wait_for_busy_clear,
+                                       wait_for_busy_hi)
+from soc.fu.compunits.test.test_compunit import (setup_test_memory,
+                                                 check_sim_memory)
+
+from soc.simple.test.test_issuer import setup_i_memory
+
+import sys
+sys.setrecursionlimit(10**6)
+
+
+class BinaryTestCase(FHDLTestCase):
+    test_data = []
+
+    def __init__(self, name="general"):
+        super().__init__(name)
+        self.test_name = name
+
+    def test_binary(self):
+        with Program("1.bin") as program:
+            self.run_tst_program(program)
+
+    def run_tst_program(self, prog):
+        initial_regs = [0] * 32
+        tc = TestCase(prog, self.test_name, initial_regs, None, 0,
+                                            None, 0,
+                      do_sim=False)
+        self.test_data.append(tc)
+
+
+class TestRunner(FHDLTestCase):
+    def __init__(self, tst_data):
+        super().__init__("binary_runner")
+        self.test_data = tst_data
+
+    def binary_runner(self):
+        m = Module()
+        comb = m.d.comb
+        go_insn_i = Signal()
+        pc_i = Signal(32)
+
+        pspec = TestMemPspec(ldst_ifacetype='test_bare_wb',
+                             imem_ifacetype='test_bare_wb',
+                             addr_wid=48,
+                             mask_wid=8,
+                             reg_wid=64,
+                             imem_test_depth=32768,
+                             dmem_test_depth=32768)
+        m.submodules.issuer = issuer = TestIssuer(pspec)
+        imem = issuer.imem._get_memory()
+        core = issuer.core
+        pdecode2 = core.pdecode2
+        l0 = core.l0
+
+        comb += issuer.pc_i.data.eq(pc_i)
+        comb += issuer.go_insn_i.eq(go_insn_i)
+
+        # nmigen Simulation
+        sim = Simulator(m)
+        sim.add_clock(1e-6)
+
+        def process():
+
+            for test in self.test_data:
+
+                # get core going
+                yield core.bigendian_i.eq(1)
+                yield core.core_start_i.eq(1)
+                yield
+                yield core.core_start_i.eq(0)
+                yield Settle()
+
+                print(test.name)
+                program = test.program
+                self.subTest(test.name)
+                print ("regs", test.regs)
+                print ("sprs", test.sprs)
+                print ("cr", test.cr)
+                print ("mem", test.mem)
+                print ("msr", test.msr)
+                print ("assem", program.assembly)
+                instructions = list(program.generate_instructions())
+
+                print ("instructions", len(instructions))
+
+                pc = 0 # start of memory
+
+                yield from setup_i_memory(imem, pc, instructions)
+                #yield from setup_test_memory(l0, sim)
+                yield from setup_regs(core, test)
+
+                yield pc_i.eq(pc)
+                yield issuer.pc_i.ok.eq(1)
+
+                while True:
+
+                    # start the instruction
+                    yield go_insn_i.eq(1)
+                    yield
+                    yield issuer.pc_i.ok.eq(0) # don't change PC from now on
+                    yield go_insn_i.eq(0)      # and don't issue a new insn
+                    yield from wait_for_busy_hi(core)
+                    yield Settle()
+
+                    # wait until executed
+                    ins = yield core.raw_opcode_i
+                    pc = yield issuer.pc_o
+                    print("instruction: 0x%x @ %x" % (ins & 0xffffffff, pc))
+                    yield from wait_for_busy_clear(core)
+
+                    terminated = yield core.core_terminated_o
+                    print ("terminated", terminated)
+
+                    terminated = yield core.core_terminated_o
+                    if terminated:
+                        break
+
+            # register check
+            #yield from check_regs(self, sim, core, test, code)
+
+            # Memory check
+            #yield from check_sim_memory(self, l0, sim, code)
+
+        sim.add_sync_process(process)
+        with sim.write_vcd("binary_issuer_simulator.vcd",
+                            traces=[]):
+            sim.run()
+
+
+if __name__ == "__main__":
+    unittest.main(exit=False)
+    suite = unittest.TestSuite()
+    suite.addTest(TestRunner(BinaryTestCase.test_data))
+
+    runner = unittest.TextTestRunner()
+    runner.run(suite)
+