# test case for LOAD / STORE Computation Unit using MMU
-from nmigen.compat.sim import run_simulation
+from nmigen.sim import Simulator, Delay, Settle, Tick
from nmigen.cli import verilog, rtlil
from nmigen import Module, Signal, Mux, Cat, Elaboratable, Array, Repl
from nmigen.hdl.rec import Record, Layout
from nmutil.latch import SRLatch, latchregister
from nmutil.byterev import byte_reverse
from nmutil.extend import exts
+from nmutil.util import wrap
from soc.fu.regspec import RegSpecAPI
from openpower.decoder.power_enums import MicrOp, Function, LDSTMode
from soc.experiment.compalu_multi import go_record, CompUnitRecord
from soc.experiment.l0_cache import PortInterface
from soc.experiment.pimem import LDSTException
-from soc.experiment.compldst_multi import LDSTCompUnit
+from soc.experiment.compldst_multi import LDSTCompUnit, load, store
from soc.config.test.test_loadstore import TestMemPspec
from soc.experiment.mmu import MMU
+from nmutil.util import Display
+
+from soc.config.loadstore import ConfigMemoryPortInterface
+from soc.experiment.test import pagetables
+from openpower.test.wb_get import wb_get
+from openpower.test import wb_get as wbget
+
########################################
-# copied from compldst_multi.py
-# for debugging -- remove once done
-def load_part(dut, src1, src2, imm, imm_ok=True, update=False, zero_a=False,
- byterev=True):
- print("LD_part", src1, src2, imm, imm_ok, update)
- yield dut.oper_i.insn_type.eq(MicrOp.OP_LOAD)
+
+def wait_for_debug(sig, reason, wait=True, test1st=False):
+ v = (yield sig)
+ cnt = 0
+ print("wait for", reason, sig, v, wait, test1st)
+ if test1st and bool(v) == wait:
+ return
+ while True:
+ cnt = cnt + 1
+ if cnt > 15:
+ raise(Exception(reason))
+ break
+ yield
+ v = (yield sig)
+ #print("...wait for", sig, v)
+ if bool(v) == wait:
+ break
+
+def store_debug(dut, src1, src2, src3, imm, imm_ok=True, update=False,
+ byterev=True,dcbz=False):
+ print("cut here ======================================")
+ print("ST", src1, src2, src3, imm, imm_ok, update)
+ if dcbz:
+ yield dut.oper_i.insn_type.eq(MicrOp.OP_DCBZ)
+ else:
+ yield dut.oper_i.insn_type.eq(MicrOp.OP_STORE)
yield dut.oper_i.data_len.eq(2) # half-word
yield dut.oper_i.byte_reverse.eq(byterev)
yield dut.src1_i.eq(src1)
yield dut.src2_i.eq(src2)
- yield dut.oper_i.zero_a.eq(zero_a)
- yield dut.oper_i.imm_data.imm.eq(imm)
+ yield dut.src3_i.eq(src3)
+ yield dut.oper_i.imm_data.data.eq(imm)
yield dut.oper_i.imm_data.ok.eq(imm_ok)
+ #guess: this one was removed -- yield dut.oper_i.update.eq(update)
yield dut.issue_i.eq(1)
yield
yield dut.issue_i.eq(0)
- yield
- # set up read-operand flags
- rd = 0b00
- if not imm_ok: # no immediate means RB register needs to be read
- rd |= 0b10
- if not zero_a: # no zero-a means RA needs to be read
- rd |= 0b01
-
- # wait for the operands (RA, RB, or both)
- if rd:
- yield dut.rd.go.eq(rd)
- yield from wait_for(dut.rd.rel_o)
- yield dut.rd.go.eq(0)
-
-# if RA = 0 then b <- 0 RA needs to be read if RA = 0
-# else b <-(RA)
-# EA <- b + (RB) RB needs to be read
-# verify that EA is correct first
-def dcbz(dut, ra, zero_a, rb):
- print("LD_part", ra, zero_a, rb)
- yield dut.oper_i.insn_type.eq(MicrOp.OP_DCBZ)
- yield dut.src1_i.eq(ra)
- yield dut.src2_i.eq(rb)
- yield dut.oper_i.zero_a.eq(zero_a)
- yield dut.issue_i.eq(1)
+ if imm_ok:
+ active_rel = 0b101
+ else:
+ active_rel = 0b111
+ if dcbz:
+ active_rel = 0b001 # may be wrong, verify
+
+ # wait for all active rel signals to come up
+ cnt = 0
+ while True:
+ rel = yield dut.rd.rel_o # guess: wrong in dcbz case
+ cnt = cnt + 1
+ print("waitActiveRel",cnt)
+ if cnt > 10:
+ raise(Exception("Error1"))
+ print("rel EQ active_rel ?",rel,active_rel)
+ if rel == active_rel:
+ break
+ yield
+ yield dut.rd.go_i.eq(active_rel)
yield
- yield dut.issue_i.eq(0)
+ yield dut.rd.go_i.eq(0)
+
+ yield from wait_for_debug(dut.adr_rel_o, "addr valid",False, test1st=True)
+ # yield from wait_for(dut.adr_rel_o)
+ # yield dut.ad.go.eq(1)
+ # yield
+ # yield dut.ad.go.eq(0)
+
+ if update:
+ yield from wait_for_debug(dut.wr.rel_o[1],"update")
+ yield dut.wr.go.eq(0b10)
+ yield
+ addr = yield dut.addr_o
+ print("addr", addr)
+ yield dut.wr.go.eq(0)
+ else:
+ addr = None
+ print("not update ===============")
+
+ yield from wait_for_debug(dut.sto_rel_o,"sto_rel_o")
+ yield dut.go_st_i.eq(1)
yield
+ yield dut.go_st_i.eq(0)
+ yield from wait_for_debug(dut.busy_o,"not_busy" ,False)
+ ###wait_for(dut.stwd_mem_o)
+ yield
+ return addr
-
+# same thing as soc/src/soc/experiment/test/test_dcbz_pi.py
def ldst_sim(dut):
- yield from dcbz(dut, 4, 0, 3) # EA=7
- #yield from load_part(dut, 4, 0, 2)
+ yield dut.mmu.rin.prtbl.eq(0x1000000) # set process table
+ addr = 0x100e0
+ data = 0xFF #just a single byte for this test
+ #data = 0xf553b658ba7e1f51
+
+ yield from store(dut, addr, 0, data, 0)
+ yield
+ ld_data, data_ok, ld_addr = yield from load(dut, addr, 0, 0)
+ print(data,data_ok,ld_addr)
+ assert(ld_data==data)
yield
-########################################
+ data = 0
+
+ print("doing dcbz/store with data 0 .....")
+ yield from store_debug(dut, addr, 0, data, 0, dcbz=True) #hangs
+ ld_data, data_ok, ld_addr = yield from load(dut, addr, 0, 0)
+ print(data,data_ok,ld_addr)
+ print("ld_data is")
+ print(ld_data)
+ assert(ld_data==data)
+ print("dzbz test passed")
+ wbget.stop = True # stop simulation
+
+########################################
class TestLDSTCompUnitMMU(LDSTCompUnit):
def __init__(self, rwid, pspec):
- from soc.experiment.l0_cache import TstL0CacheBuffer
- self.l0 = l0 = TstL0CacheBuffer(pspec)
- pi = l0.l0.dports[0]
- LDSTCompUnit.__init__(self, pi, rwid, 4)
+ # use a LoadStore1 here
+ cmpi = ConfigMemoryPortInterface(pspec)
+ self.cmpi = cmpi
+ ldst = cmpi.pi
+ self.l0 = ldst
+
+ self.mmu = MMU()
+ LDSTCompUnit.__init__(self, ldst.pi, rwid, 4)
def elaborate(self, platform):
m = LDSTCompUnit.elaborate(self, platform)
m.submodules.l0 = self.l0
+ m.submodules.mmu = self.mmu
# link addr-go direct to rel
m.d.comb += self.ad.go_i.eq(self.ad.rel_o)
+
+ # link mmu and dcache together
+ dcache = self.l0.dcache
+ mmu = self.mmu
+ m.d.comb += dcache.m_in.eq(mmu.d_out) # MMUToDCacheType
+ m.d.comb += mmu.d_in.eq(dcache.m_out) # DCacheToMMUType
+
return m
def test_scoreboard_mmu():
+ m = Module()
+
units = {}
pspec = TestMemPspec(ldst_ifacetype='mmu_cache_wb',
imem_ifacetype='bare_wb',
units=units)
dut = TestLDSTCompUnitMMU(16,pspec)
- vl = rtlil.convert(dut, ports=dut.ports())
- with open("test_ldst_comp_mmu1.il", "w") as f:
- f.write(vl)
- run_simulation(dut, ldst_sim(dut), vcd_name='test_ldst_comp.vcd')
+ m.submodules.dut = dut
+
+ sim = Simulator(m)
+ sim.add_clock(1e-6)
+
+ dut.mem = pagetables.test1
+ wbget.stop = False
+
+ sim.add_sync_process(wrap(ldst_sim(dut)))
+ sim.add_sync_process(wrap(wb_get(dut.cmpi.wb_bus(), dut.mem)))
+ with sim.write_vcd('test_scoreboard_mmu.vcd'):
+ sim.run()
########################################
class TestLDSTCompUnitRegSpecMMU(LDSTCompUnit):
def __init__(self, pspec):
- from soc.experiment.l0_cache import TstL0CacheBuffer
from soc.fu.ldst.pipe_data import LDSTPipeSpec
regspec = LDSTPipeSpec.regspec
- self.l0 = l0 = TstL0CacheBuffer(pspec)
+
+ # use a LoadStore1 here
+ cmpi = ConfigMemoryPortInterface(pspec)
+ self.cmpi = cmpi
+ ldst = cmpi.pi
+ self.l0 = ldst
+
self.mmu = MMU()
- pi = l0.l0.dports[0]
- LDSTCompUnit.__init__(self, pi, regspec, 4)
+ LDSTCompUnit.__init__(self, ldst.pi, regspec, 4)
def elaborate(self, platform):
m = LDSTCompUnit.elaborate(self, platform)
m.d.comb += self.ad.go_i.eq(self.ad.rel_o)
# link mmu and dcache together
- dcache = self.l0.pimem.dcache
+ dcache = self.l0.dcache
mmu = self.mmu
m.d.comb += dcache.m_in.eq(mmu.d_out) # MMUToDCacheType
m.d.comb += mmu.d_in.eq(dcache.m_out) # DCacheToMMUType
-
return m
-
def test_scoreboard_regspec_mmu():
+ m = Module()
+
units = {}
pspec = TestMemPspec(ldst_ifacetype='mmu_cache_wb',
imem_ifacetype='bare_wb',
dut = TestLDSTCompUnitRegSpecMMU(pspec)
- # TODO: setup pagetables for MMU
+ m.submodules.dut = dut
- vl = rtlil.convert(dut, ports=dut.ports())
- with open("test_ldst_comp_mmu2.il", "w") as f:
- f.write(vl)
+ sim = Simulator(m)
+ sim.add_clock(1e-6)
- run_simulation(dut, ldst_sim(dut), vcd_name='test_ldst_regspec.vcd')
+ dut.mem = pagetables.test1
+ wbget.stop = False
+ sim.add_sync_process(wrap(ldst_sim(dut)))
+ sim.add_sync_process(wrap(wb_get(dut.cmpi.wb_bus(), dut.mem)))
+ with sim.write_vcd('test_scoreboard_regspec_mmu.vcd'):
+ sim.run()
if __name__ == '__main__':
test_scoreboard_regspec_mmu()
- #only one test for now -- test_scoreboard_mmu()
+ test_scoreboard_mmu()