# test case for LOAD / STORE Computation Unit using MMU
-#from nmigen.compat.sim import run_simulation
-from nmigen.sim import Simulator, Delay, Settle
+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.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
-def b(x): # byte-reverse function
- return int.from_bytes(x.to_bytes(8, byteorder='little'),
- byteorder='big', signed=False)
-#FIXME: move to common module
-def wait_for_debug(sig, event, wait=True, test1st=False):
+########################################
+
+def wait_for_debug(sig, reason, wait=True, test1st=False):
v = (yield sig)
- print("wait for", sig, v, wait, test1st)
+ 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)
- yield Display("waiting for "+event)
+ #print("...wait for", sig, v)
if bool(v) == wait:
break
-def load_debug(dut, src1, src2, imm, imm_ok=True, update=False, zero_a=False,
- byterev=True):
- print("LD", src1, src2, imm, imm_ok, update)
- yield dut.oper_i.insn_type.eq(MicrOp.OP_LOAD)
+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.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)
+
+ 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.rd.go_i.eq(0)
- # 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_i.eq(rd)
- yield from wait_for_debug(dut.rd.rel_o,"operands")
- yield dut.rd.go_i.eq(0)
-
- yield from wait_for_debug(dut.adr_rel_o, "adr_rel_o" ,False, test1st=True)
- yield Display("load_debug: done")
+ 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)
- """
- guess: hangs here
-
if update:
- yield from wait_for(dut.wr.rel_o[1])
+ yield from wait_for_debug(dut.wr.rel_o[1],"update")
yield dut.wr.go.eq(0b10)
yield
addr = yield dut.addr_o
yield dut.wr.go.eq(0)
else:
addr = None
+ print("not update ===============")
- yield from wait_for(dut.wr.rel_o[0], test1st=True)
- yield dut.wr.go.eq(1)
+ yield from wait_for_debug(dut.sto_rel_o,"sto_rel_o")
+ yield dut.go_st_i.eq(1)
yield
- data = yield dut.o_data
- print(data)
- yield dut.wr.go.eq(0)
- yield from wait_for(dut.busy_o)
+ 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
- # wait_for(dut.stwd_mem_o)
- return data, addr
- """
-
-# removed
+ return addr
# same thing as soc/src/soc/experiment/test/test_dcbz_pi.py
def ldst_sim(dut):
yield dut.mmu.rin.prtbl.eq(0x1000000) # set process table
- ###yield from dcbz(dut, 4, 0, 3) # EA=7
addr = 0x100e0
- data = 0xf553b658ba7e1f51
+ data = 0xFF #just a single byte for this test
+ #data = 0xf553b658ba7e1f51
yield from store(dut, addr, 0, data, 0)
yield
- yield from load_debug(dut, 4, 0, 2) #FIXME
- """
- ld_data = yield from pi_ld(pi, addr, 8, msr_pr=0)
- assert ld_data == 0xf553b658ba7e1f51
- ld_data = yield from pi_ld(pi, addr, 8, msr_pr=0)
- assert ld_data == 0xf553b658ba7e1f51
- """
+ 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')
- #TODO add wb runner here
+ 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
# use a LoadStore1 here
-
cmpi = ConfigMemoryPortInterface(pspec)
self.cmpi = cmpi
ldst = cmpi.pi
return m
-# FIXME: this is redundant code
-def wb_get(wb, mem):
- """simulator process for getting memory load requests
- """
-
- global stop
- assert(stop==False)
-
- while not stop:
- while True: # wait for dc_valid
- if stop:
- return
- cyc = yield (wb.cyc)
- stb = yield (wb.stb)
- if cyc and stb:
- break
- yield
- addr = (yield wb.adr) << 3
- stop = True # hack for testing
- if addr not in mem:
- print (" WB LOOKUP NO entry @ %x, returning zero" % (addr))
-
- # read or write?
- we = (yield wb.we)
- if we:
- store = (yield wb.dat_w)
- sel = (yield wb.sel)
- data = mem.get(addr, 0)
- # note we assume 8-bit sel, here
- res = 0
- for i in range(8):
- mask = 0xff << (i*8)
- if sel & (1<<i):
- res |= store & mask
- else:
- res |= data & mask
- mem[addr] = res
- print (" DCACHE set %x mask %x data %x" % (addr, sel, res))
- else:
- data = mem.get(addr, 0)
- yield wb.dat_r.eq(data)
- print (" DCACHE get %x data %x" % (addr, data))
-
- yield wb.ack.eq(1)
- yield
- yield wb.ack.eq(0)
- yield
-
def test_scoreboard_regspec_mmu():
-
+
m = Module()
units = {}
sim = Simulator(m)
sim.add_clock(1e-6)
- sim.add_sync_process(wrap(ldst_sim(dut)))
-
- # FIXME: this is redundant code
- 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),
+ dut.mem = pagetables.test1
+ wbget.stop = False
- 0x40000: # RADIX_SECOND_LEVEL
- # V = 1 L = 1 SW = 0 RPN = 0
- # R = 1 C = 1 ATT = 0 EAA 0x7
- b(0xc000000000000183),
-
- 0x1000000: # PROCESS_TABLE_3
- # RTS1 = 0x2 RPDB = 0x300 RTS2 = 0x5 RPDS = 13
- b(0x40000000000300ad),
-
- 0x10004: 0
-
- }
-
- sim.add_sync_process(wrap(wb_get(dut.cmpi.wb_bus(), mem)))
- with sim.write_vcd('test_dcbz_addr_zero.vcd'):
+ 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__':
- #FIXME: avoid using global variables
- global stop
- stop = False
test_scoreboard_regspec_mmu()
- #only one test for now -- test_scoreboard_mmu()
+ test_scoreboard_mmu()