From c768206cbcf0b031df53bd39b2bf905820160391 Mon Sep 17 00:00:00 2001 From: Tobias Platen Date: Sat, 20 Feb 2021 10:20:10 +0100 Subject: [PATCH] add mmu rom testcase --- src/soc/fu/mmu/test/test_issuer_mmu_rom.py | 55 +++ src/soc/simple/test/test_runner_mmu_rom.py | 403 +++++++++++++++++++++ 2 files changed, 458 insertions(+) create mode 100644 src/soc/fu/mmu/test/test_issuer_mmu_rom.py create mode 100644 src/soc/simple/test/test_runner_mmu_rom.py diff --git a/src/soc/fu/mmu/test/test_issuer_mmu_rom.py b/src/soc/fu/mmu/test/test_issuer_mmu_rom.py new file mode 100644 index 00000000..f89288c0 --- /dev/null +++ b/src/soc/fu/mmu/test/test_issuer_mmu_rom.py @@ -0,0 +1,55 @@ +from nmigen import Module, Signal +from soc.simple.test.test_runner_mmu_rom import TestRunner +from soc.simulator.program import Program +from soc.config.endian import bigendian +import unittest + +from soc.fu.test.common import ( + TestAccumulatorBase, skip_case, TestCase, ALUHelpers) + +def b(x): + return int.from_bytes(x.to_bytes(8, byteorder='little'), + byteorder='big', signed=False) +default_mem = { 0x10000: # PARTITION_TABLE_2 + # PATB_GR=1 PRTB=0x1000 PRTS=0xb + b(0x800000000100000b), + + 0x30000: # RADIX_ROOT_PTE + # V = 1 L = 0 NLB = 0x400 NLS = 9 + b(0x8000000000040009), + + 0x40000: # RADIX_SECOND_LEVEL + # V = 1 L = 1 SW = 0 RPN = 0 + # R = 1 C = 1 ATT = 0 EAA 0x7 + b(0xc000000000000187), + + 0x1000000: # PROCESS_TABLE_3 + # RTS1 = 0x2 RPDB = 0x300 RTS2 = 0x5 RPDS = 13 + b(0x40000000000300ad), + } + + +class MMUTestCase(TestAccumulatorBase): + # MMU on microwatt handles MTSPR, MFSPR, DCBZ and TLBIE. + # libre-soc has own SPR unit + # other instructions here -> must be load/store + + def case_mmu_ldst(self): + lst = [ + "lhz 3, 0(1)" # load some data + ] + + initial_regs = [0] * 32 + + initial_sprs = {} + self.add_case(Program(lst, bigendian), + initial_regs, initial_sprs) + +rom = None + +if __name__ == "__main__": + unittest.main(exit=False) + suite = unittest.TestSuite() + suite.addTest(TestRunner(MMUTestCase().test_data,default_mem)) + runner = unittest.TextTestRunner() + runner.run(suite) diff --git a/src/soc/simple/test/test_runner_mmu_rom.py b/src/soc/simple/test/test_runner_mmu_rom.py new file mode 100644 index 00000000..8e9d9a44 --- /dev/null +++ b/src/soc/simple/test/test_runner_mmu_rom.py @@ -0,0 +1,403 @@ +"""MMU TestRunner class, runs TestIssuer instructions using a wishbone ROM + +related bugs: + + * https://bugs.libre-soc.org/show_bug.cgi?id=363 +""" +from nmigen import Module, Signal, Cat, ClockSignal + +# 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.sim_tmp_alternative import Simulator, Settle + +from nmutil.formaltest import FHDLTestCase +from nmutil.gtkw import write_gtkw +from nmigen.cli import rtlil +from soc.decoder.isa.caller import special_sprs, SVP64State +from soc.decoder.isa.all import ISA +from soc.config.endian import bigendian + +from soc.decoder.power_decoder import create_pdecode +from soc.decoder.power_decoder2 import PowerDecode2 +from soc.regfile.regfiles import StateRegs + +from soc.simple.issuer import TestIssuerInternal + +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.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): + mem = imem + print("insn before, init mem", mem.depth, mem.width, mem, + len(instructions)) + for i in range(mem.depth): + yield mem._array[i].eq(0) + yield Settle() + startaddr //= 4 # instructions are 32-bit + if mem.width == 32: + mask = ((1 << 32)-1) + for ins in instructions: + if isinstance(ins, tuple): + insn, code = ins + else: + insn, code = ins, '' + insn = insn & 0xffffffff + yield mem._array[startaddr].eq(insn) + yield Settle() + if insn != 0: + print("instr: %06x 0x%x %s" % (4*startaddr, insn, code)) + startaddr += 1 + startaddr = startaddr & mask + return + + # 64 bit + mask = ((1 << 64)-1) + for ins in instructions: + if isinstance(ins, tuple): + insn, code = ins + else: + insn, code = ins, '' + insn = insn & 0xffffffff + msbs = (startaddr >> 1) & mask + val = yield mem._array[msbs] + if insn != 0: + print("before set", hex(4*startaddr), + hex(msbs), hex(val), hex(insn)) + lsb = 1 if (startaddr & 1) else 0 + val = (val | (insn << (lsb*32))) + val = val & mask + yield mem._array[msbs].eq(val) + yield Settle() + if insn != 0: + 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 + + +def set_dmi(dmi, addr, data): + yield dmi.req_i.eq(1) + yield dmi.addr_i.eq(addr) + yield dmi.din.eq(data) + yield dmi.we_i.eq(1) + while True: + ack = yield dmi.ack_o + if ack: + break + yield + yield + yield dmi.req_i.eq(0) + yield dmi.addr_i.eq(0) + yield dmi.din.eq(0) + yield dmi.we_i.eq(0) + yield + + +def get_dmi(dmi, addr): + yield dmi.req_i.eq(1) + yield dmi.addr_i.eq(addr) + yield dmi.din.eq(0) + yield dmi.we_i.eq(0) + while True: + ack = yield dmi.ack_o + if ack: + break + yield + yield # wait one + data = yield dmi.dout # get data after ack valid for 1 cycle + yield dmi.req_i.eq(0) + yield dmi.addr_i.eq(0) + yield dmi.we_i.eq(0) + yield + return data + + +class TestRunner(FHDLTestCase): + def __init__(self, tst_data, rom): + super().__init__("run_all") + self.test_data = tst_data + self.rom = rom + + def run_all(self): + m = Module() + comb = m.d.comb + pc_i = Signal(32) + + pspec = TestMemPspec(ldst_ifacetype='test_bare_wb', + imem_ifacetype='test_bare_wb', + addr_wid=48, + mask_wid=8, + imem_reg_wid=64, + # wb_data_width=32, + use_pll=False, + nocore=False, + xics=False, + gpio=False, + mmu=True, + reg_wid=64) + m.submodules.issuer = issuer = TestIssuerInternal(pspec) + imem = issuer.imem._get_memory() + core = issuer.core + dmi = issuer.dbg.dmi + pdecode2 = issuer.pdecode2 + l0 = core.l0 + + # copy of the decoder for simulator + simdec = create_pdecode() + simdec2 = PowerDecode2(simdec) + m.submodules.simdec2 = simdec2 # pain in the neck + + # run core clock at same rate as test clock + intclk = ClockSignal("coresync") + comb += intclk.eq(ClockSignal()) + + comb += issuer.pc_i.data.eq(pc_i) + + # nmigen Simulation + sim = Simulator(m) + sim.add_clock(1e-6) + + def process(): + + # start in stopped + yield from set_dmi(dmi, DBGCore.CTRL, 1<= len(instructions): + print ("index over, send dmi stop") + # stop at end + yield from set_dmi(dmi, DBGCore.CTRL, 1<