From c8909597f03c0fa578d53c412b03fa14b6db3a79 Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Wed, 8 Jul 2020 00:21:48 +0100 Subject: [PATCH] sort-of got binary execution test working --- src/soc/bus/test/test_minerva.py | 13 ++- src/soc/decoder/power_decoder2.py | 11 +- src/soc/simple/core.py | 10 ++ src/soc/simple/issuer.py | 13 ++- src/soc/simple/test/test_issuer.py | 8 +- src/soc/simple/test/test_microwatt.py | 150 ++++++++++++++++++++++++++ 6 files changed, 184 insertions(+), 21 deletions(-) create mode 100644 src/soc/simple/test/test_microwatt.py diff --git a/src/soc/bus/test/test_minerva.py b/src/soc/bus/test/test_minerva.py index 780fcba7..93434d6e 100644 --- a/src/soc/bus/test/test_minerva.py +++ b/src/soc/bus/test/test_minerva.py @@ -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 diff --git a/src/soc/decoder/power_decoder2.py b/src/soc/decoder/power_decoder2.py index 612a44d8..20c40075 100644 --- a/src/soc/decoder/power_decoder2.py +++ b/src/soc/decoder/power_decoder2.py @@ -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) diff --git a/src/soc/simple/core.py b/src/soc/simple/core.py index 382a8588..f5dd58e3 100644 --- a/src/soc/simple/core.py +++ b/src/soc/simple/core.py @@ -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(): diff --git a/src/soc/simple/issuer.py b/src/soc/simple/issuer.py index 45e6b283..fc0bbd0b 100644 --- a/src/soc/simple/issuer.py +++ b/src/soc/simple/issuer.py @@ -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) diff --git a/src/soc/simple/test/test_issuer.py b/src/soc/simple/test/test_issuer.py index f4e4363a..e0c404fa 100644 --- a/src/soc/simple/test/test_issuer.py +++ b/src/soc/simple/test/test_issuer.py @@ -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 index 00000000..2cf0521a --- /dev/null +++ b/src/soc/simple/test/test_microwatt.py @@ -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) + -- 2.30.2