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
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
self.dec = dec
self.e = Decode2ToExecute1Type()
- self.valid = Signal()
+ self.valid = Signal() # sync signal
def ports(self):
return self.dec.ports() + self.e.ports()
# 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)
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():
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):
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)
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):
# 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)
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
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
--- /dev/null
+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)
+