* https://bugs.libre-soc.org/show_bug.cgi?id=363
"""
from nmigen import Module, Signal, Cat, ClockSignal
+from nmigen.hdl.xfrm import ResetInserter
# NOTE: to use cxxsim, export NMIGEN_SIM_MODE=cxxsim from the shell
# Also, check out the cxxsim nmigen branch, and latest yosys from git
from nmutil.formaltest import FHDLTestCase
from nmutil.gtkw import write_gtkw
from nmigen.cli import rtlil
-from soc.decoder.isa.caller import special_sprs
-from soc.decoder.isa.all import ISA
-from soc.config.endian import bigendian
+from openpower.decoder.isa.caller import special_sprs, SVP64State
+from openpower.decoder.isa.all import ISA
+from openpower.endian import bigendian
-from soc.decoder.power_decoder import create_pdecode
-from soc.decoder.power_decoder2 import PowerDecode2
+from openpower.decoder.power_decoder import create_pdecode
+from openpower.decoder.power_decoder2 import PowerDecode2
+from soc.regfile.regfiles import StateRegs
from soc.simple.issuer import TestIssuerInternal
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,
+from soc.fu.compunits.test.test_compunit import (setup_tst_memory,
check_sim_memory)
from soc.debug.dmi import DBGCore, DBGCtrl, DBGStat
+from nmutil.util import wrap
+from soc.experiment.test.test_mmu_dcache import wb_get
def setup_i_memory(imem, startaddr, instructions):
class TestRunner(FHDLTestCase):
- def __init__(self, tst_data, microwatt_mmu=False):
+ def __init__(self, tst_data, microwatt_mmu=False, rom=None,
+ svp64=True):
super().__init__("run_all")
self.test_data = tst_data
self.microwatt_mmu = microwatt_mmu
+ self.rom = rom
+ self.svp64 = svp64
def run_all(self):
m = Module()
comb = m.d.comb
pc_i = Signal(32)
+ svstate_i = Signal(64)
- pspec = TestMemPspec(ldst_ifacetype='test_bare_wb',
- imem_ifacetype='test_bare_wb',
+ if self.microwatt_mmu:
+ ldst_ifacetype = 'test_mmu_cache_wb'
+ else:
+ ldst_ifacetype = 'test_bare_wb'
+ imem_ifacetype = 'test_bare_wb'
+
+ pspec = TestMemPspec(ldst_ifacetype=ldst_ifacetype,
+ imem_ifacetype=imem_ifacetype,
addr_wid=48,
mask_wid=8,
imem_reg_wid=64,
nocore=False,
xics=False,
gpio=False,
+ regreduce=True,
+ svp64=self.svp64,
mmu=self.microwatt_mmu,
reg_wid=64)
- m.submodules.issuer = issuer = TestIssuerInternal(pspec)
+ #hard_reset = Signal(reset_less=True)
+ issuer = TestIssuerInternal(pspec)
+ # use DMI RESET command instead, this does actually work though
+ #issuer = ResetInserter({'coresync': hard_reset,
+ # 'sync': hard_reset})(issuer)
+ m.submodules.issuer = issuer
imem = issuer.imem._get_memory()
core = issuer.core
dmi = issuer.dbg.dmi
pdecode2 = issuer.pdecode2
l0 = core.l0
+ regreduce_en = pspec.regreduce_en == True
- # copy of the decoder for simulator
- simdec = create_pdecode()
- simdec2 = PowerDecode2(simdec)
+ #simdec = create_pdecode()
+ simdec2 = PowerDecode2(None, regreduce_en=regreduce_en)
m.submodules.simdec2 = simdec2 # pain in the neck
# run core clock at same rate as test clock
comb += intclk.eq(ClockSignal())
comb += issuer.pc_i.data.eq(pc_i)
+ comb += issuer.svstate_i.data.eq(svstate_i)
# nmigen Simulation
sim = Simulator(m)
# start in stopped
yield from set_dmi(dmi, DBGCore.CTRL, 1<<DBGCtrl.STOP)
yield
- yield
# get each test, completely reset the core, and run it
for test in self.test_data:
- # pull a reset
- # yield from set_dmi(dmi, DBGCore.CTRL, 1<<DBGCtrl.RESET)
-
# set up bigendian (TODO: don't do this, use MSR)
yield issuer.core_bigendian_i.eq(bigendian)
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)
- gen = list(program.generate_instructions())
- insncode = program.assembly.splitlines()
- instructions = list(zip(gen, insncode))
-
- # set up the Simulator (which must track TestIssuer exactly)
- sim = ISA(simdec2, test.regs, test.sprs, test.cr, test.mem,
- test.msr,
- initial_insns=gen, respect_pc=True,
- disassembly=insncode,
- bigendian=bigendian,
- initial_svstate=test.svstate)
-
- # establish the TestIssuer context (mem, regs etc)
-
- pc = 0 # start address
- counter = 0 # test to pause/start
-
- yield from setup_i_memory(imem, pc, instructions)
- yield from setup_test_memory(l0, sim)
- yield from setup_regs(pdecode2, core, test)
- # TODO, setup svstate here in core.regs.state regfile
- # https://bugs.libre-soc.org/show_bug.cgi?id=583#c35
-
- yield pc_i.eq(pc)
- yield issuer.pc_i.ok.eq(1)
- yield
-
- print("instructions", instructions)
-
- # run the loop of the instructions on the current test
- index = sim.pc.CIA.value//4
- while index < len(instructions):
- ins, code = instructions[index]
-
- print("instruction: 0x{:X}".format(ins & 0xffffffff))
- print(index, code)
-
- if counter == 0:
- # start the core
- yield
- yield from set_dmi(dmi, DBGCore.CTRL, 1<<DBGCtrl.START)
- yield issuer.pc_i.ok.eq(0) # no change PC after this
- yield
- yield
-
- counter = counter + 1
-
- # wait until executed
- yield from wait_for_busy_hi(core)
- yield from wait_for_busy_clear(core)
-
- # set up simulated instruction (in simdec2)
- try:
- yield from sim.setup_one()
- except KeyError: # indicates instruction not in imem: stop
- break
- yield Settle()
-
- # call simulated operation
- print("sim", code)
- yield from sim.execute_one()
- yield Settle()
- index = sim.pc.CIA.value//4
-
- terminated = yield issuer.dbg.terminated_o
- print("terminated", terminated)
-
- if index >= len(instructions):
- print ("index over, send dmi stop")
- # stop at end
- yield from set_dmi(dmi, DBGCore.CTRL, 1<<DBGCtrl.STOP)
- yield
- yield
-
- # wait one cycle for registers to settle
+ with 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)
+ gen = list(program.generate_instructions())
+ insncode = program.assembly.splitlines()
+ instructions = list(zip(gen, insncode))
+
+ # set up the Simulator (which must track TestIssuer exactly)
+ sim = ISA(simdec2, test.regs, test.sprs, test.cr, test.mem,
+ test.msr,
+ initial_insns=gen, respect_pc=True,
+ disassembly=insncode,
+ bigendian=bigendian,
+ initial_svstate=test.svstate)
+
+ # establish the TestIssuer context (mem, regs etc)
+
+ pc = 0 # start address
+ counter = 0 # test to pause/start
+
+ yield from setup_i_memory(imem, pc, instructions)
+ yield from setup_tst_memory(l0, sim)
+ yield from setup_regs(pdecode2, core, test)
+
+ # set PC and SVSTATE
+ yield pc_i.eq(pc)
+ yield issuer.pc_i.ok.eq(1)
+
+ initial_svstate = test.svstate
+ if isinstance(initial_svstate, int):
+ initial_svstate = SVP64State(initial_svstate)
+ yield svstate_i.eq(initial_svstate.value)
+ yield issuer.svstate_i.ok.eq(1)
yield
- # register check
- yield from check_regs(self, sim, core, test, code)
+ print("instructions", instructions)
- # Memory check
- yield from check_sim_memory(self, l0, sim, code)
-
- terminated = yield issuer.dbg.terminated_o
- print("terminated(2)", terminated)
- if terminated:
- break
+ # run the loop of the instructions on the current test
+ index = sim.pc.CIA.value//4
+ while index < len(instructions):
+ ins, code = instructions[index]
+
+ print("instruction: 0x{:X}".format(ins & 0xffffffff))
+ print(index, code)
+
+ if counter == 0:
+ # start the core
+ yield
+ yield from set_dmi(dmi, DBGCore.CTRL,
+ 1<<DBGCtrl.START)
+ yield issuer.pc_i.ok.eq(0) # no change PC after this
+ yield issuer.svstate_i.ok.eq(0) # ditto
+ yield
+ yield
+
+ counter = counter + 1
+
+ # wait until executed
+ while not (yield issuer.insn_done):
+ yield
+
+ # set up simulated instruction (in simdec2)
+ try:
+ yield from sim.setup_one()
+ except KeyError: # instruction not in imem: stop
+ break
+ yield Settle()
+
+ # call simulated operation
+ print("sim", code)
+ yield from sim.execute_one()
+ yield Settle()
+ index = sim.pc.CIA.value//4
+
+ terminated = yield issuer.dbg.terminated_o
+ print("terminated", terminated)
+
+ if index >= len(instructions):
+ print ("index over, send dmi stop")
+ # stop at end
+ yield from set_dmi(dmi, DBGCore.CTRL,
+ 1<<DBGCtrl.STOP)
+ yield
+ yield
+
+ # register check
+ yield from check_regs(self, sim, core, test, code)
+
+ # Memory check
+ yield from check_sim_memory(self, l0, sim, code)
+
+ terminated = yield issuer.dbg.terminated_o
+ print("terminated(2)", terminated)
+ if terminated:
+ break
# stop at end
yield from set_dmi(dmi, DBGCore.CTRL, 1<<DBGCtrl.STOP)
print("after test %s reg %2d value %x" %
(test.name, int_reg, value))
+ # pull a reset
+ yield from set_dmi(dmi, DBGCore.CTRL, 1<<DBGCtrl.RESET)
+ yield
+
styles = {
'dec': {'base': 'dec'},
- 'bin': {'base': 'bin'}
+ 'bin': {'base': 'bin'},
+ 'closed': {'closed': True}
}
traces = [
'clk',
- {'comment': 'state machines'},
- 'fetch_pc_valid_i', 'fetch_pc_ready_o', 'fetch_fsm_state',
- 'fetch_insn_valid_o', 'fetch_insn_ready_i', 'fsm_state',
+ ('state machines', 'closed', [
+ 'fetch_pc_valid_i', 'fetch_pc_ready_o',
+ 'fetch_fsm_state',
+ 'fetch_insn_valid_o', 'fetch_insn_ready_i',
+ 'pred_insn_valid_i', 'pred_insn_ready_o',
+ 'fetch_predicate_state',
+ 'pred_mask_valid_o', 'pred_mask_ready_i',
+ 'issue_fsm_state',
+ 'exec_insn_valid_i', 'exec_insn_ready_o',
+ 'exec_fsm_state',
+ 'exec_pc_valid_o', 'exec_pc_ready_i',
+ 'insn_done', 'core_stop_o', 'pc_i_ok', 'pc_changed',
+ 'is_last', 'dec2.no_out_vec']),
{'comment': 'fetch and decode'},
- 'cia[63:0]', 'nia[63:0]', 'pc[63:0]', 'raw_insn_i[31:0]',
+ (None, 'dec', [
+ 'cia[63:0]', 'nia[63:0]', 'pc[63:0]',
+ 'cur_pc[63:0]', 'core_core_cia[63:0]']),
+ 'raw_insn_i[31:0]',
'raw_opcode_in[31:0]', 'insn_type',
- {'comment': 'svp64 decoding'},
- 'svp64_rm[23:0]',
- ('dec2.extra[8:0]', 'bin'),
- ('register augmentation', 'dec', [
+ ('svp64 decoding', 'closed', [
+ 'svp64_rm[23:0]', ('dec2.extra[8:0]', 'bin'),
+ 'dec2.sv_rm_dec.mode', 'dec2.sv_rm_dec.predmode',
+ 'dec2.sv_rm_dec.ptype_in',
+ 'dec2.sv_rm_dec.dstpred[2:0]', 'dec2.sv_rm_dec.srcpred[2:0]',
+ 'dstmask[63:0]', 'srcmask[63:0]',
+ 'dregread[4:0]', 'dinvert',
+ 'sregread[4:0]', 'sinvert',
+ 'core.int.pred__addr[4:0]', 'core.int.pred__data_o[63:0]',
+ 'core.int.pred__ren']),
+ ('register augmentation', 'dec', 'closed', [
{'comment': 'v3.0b registers'},
'dec2.dec_o.RT[4:0]',
'dec2.dec_a.RA[4:0]',
{'comment': 'SVP64 registers'},
'dec2.rego[6:0]', 'dec2.reg1[6:0]', 'dec2.reg2[6:0]'
]),
+ {'comment': 'svp64 context'},
+ 'core_core_vl[6:0]', 'core_core_maxvl[6:0]',
+ 'core_core_srcstep[6:0]', 'next_srcstep[6:0]',
+ 'core_core_dststep[6:0]',
{'comment': 'issue and execute'},
'core.core_core_insn_type',
(None, 'dec', [
{'comment': 'instruction memory'},
'imem.sram.rdport.memory(0)[63:0]',
{'comment': 'registers'},
+ # match with soc.regfile.regfiles.IntRegs port names
'core.int.rp_src1.memory(0)[63:0]',
'core.int.rp_src1.memory(1)[63:0]',
'core.int.rp_src1.memory(2)[63:0]',
'core.int.rp_src1.memory(7)[63:0]',
'core.int.rp_src1.memory(9)[63:0]',
'core.int.rp_src1.memory(10)[63:0]',
- 'core.int.rp_src1.memory(13)[63:0]',
+ 'core.int.rp_src1.memory(13)[63:0]'
]
+ # PortInterface module path varies depending on MMU option
+ if self.microwatt_mmu:
+ pi_module = 'core.ldst0'
+ else:
+ pi_module = 'core.fus.ldst0'
+
+ traces += [('ld/st port interface', {'submodule': pi_module}, [
+ 'oper_r__insn_type',
+ 'ldst_port0_is_ld_i',
+ 'ldst_port0_is_st_i',
+ 'ldst_port0_busy_o',
+ 'ldst_port0_addr_i[47:0]',
+ 'ldst_port0_addr_i_ok',
+ 'ldst_port0_addr_ok_o',
+ 'ldst_port0_exc_happened',
+ 'ldst_port0_st_data_i[63:0]',
+ 'ldst_port0_st_data_i_ok',
+ 'ldst_port0_ld_data_o[63:0]',
+ 'ldst_port0_ld_data_o_ok',
+ 'exc_o_happened',
+ 'cancel'
+ ])]
+
if self.microwatt_mmu:
traces += [
{'comment': 'microwatt_mmu'},
'core.fus.mmu0.alu_mmu0.debug0[3:0]',
'core.fus.mmu0.alu_mmu0.mmu.state',
'core.fus.mmu0.alu_mmu0.mmu.pid[31:0]',
- 'core.fus.mmu0.alu_mmu0.mmu.prtbl[63:0]'
+ 'core.fus.mmu0.alu_mmu0.mmu.prtbl[63:0]',
+ {'comment': 'wishbone_memory'},
+ 'core.fus.mmu0.alu_mmu0.dcache.stb',
+ 'core.fus.mmu0.alu_mmu0.dcache.cyc',
+ 'core.fus.mmu0.alu_mmu0.dcache.we',
+ 'core.fus.mmu0.alu_mmu0.dcache.ack',
+ 'core.fus.mmu0.alu_mmu0.dcache.stall,'
]
write_gtkw("issuer_simulator.gtkw",
"issuer_simulator.vcd",
traces, styles, module='top.issuer')
+ # add run of instructions
sim.add_sync_process(process)
+
+ # optionally, if a wishbone-based ROM is passed in, run that as an
+ # extra emulated process
+ if self.rom is not None:
+ dcache = core.fus.fus["mmu0"].alu.dcache
+ default_mem = self.rom
+ sim.add_sync_process(wrap(wb_get(dcache, default_mem, "DCACHE")))
+
with sim.write_vcd("issuer_simulator.vcd"):
sim.run()