提交 35377176 编写于 作者: Z zhanglinjuan

fix bugs in l2cache(turn off prefetcher)

......@@ -41,12 +41,13 @@ EMU_LDFLAGS = -lpthread -lSDL2 -ldl
VERILATOR_FLAGS = --top-module $(SIM_TOP) \
+define+VERILATOR=1 \
+define+PRINTF_COND=1 \
+define+RANDOMIZE_REG_INIT \
--assert --output-split 20000 \
--trace \
+define+RANDOMIZE_REG_INIT \
--assert \
--output-split 5000 \
--output-split-cfuncs 5000 \
-I$(abspath $(BUILD_DIR)) \
--x-assign unique -O3 -CFLAGS "$(EMU_CXXFLAGS)" \
-LDFLAGS "$(EMU_LDFLAGS)"
-LDFLAGS "$(EMU_LDFLAGS)"
EMU_MK := $(BUILD_DIR)/emu-compile/V$(SIM_TOP).mk
EMU_DEPS := $(EMU_VFILES) $(EMU_CXXFILES)
......@@ -72,6 +73,9 @@ endif
emu: $(EMU)
@$(EMU) -i $(IMAGE) $(MAINARGS)
cache:
$(MAKE) emu IMAGE=Makefile
clean:
rm -rf $(BUILD_DIR)
......
......@@ -53,6 +53,7 @@ class SimpleBusReqBundle(val userBits: Int = 0) extends SimpleBusBundle {
def isRead() = !cmd(0) && !cmd(3)
def isWrite() = cmd(0)
def isBurst() = cmd(1)
def isReadBurst() = cmd === SimpleBusCmd.readBurst
def isWriteSingle() = cmd === SimpleBusCmd.write
def isWriteLast() = cmd === SimpleBusCmd.writeLast
def isProbe() = cmd === SimpleBusCmd.probe
......
此差异已折叠。
......@@ -84,7 +84,11 @@ class EXU(implicit val p: NOOPConfig) extends NOOPModule {
io.forward.wb.rfDest := io.in.bits.ctrl.rfDest
io.forward.wb.rfData := Mux(alu.io.out.fire(), aluOut, lsuOut)
io.forward.fuType := io.in.bits.ctrl.fuType
/*
Debug(true) {
printf("[EXU] dmem.req.valid = %d, dmem.req.bits.addr = %x\n", io.dmem.req.valid, io.dmem.req.bits.addr)
}
*/
val isBru = ALUOpType.isBru(fuOpType)
BoringUtils.addSource(alu.io.out.fire() && !isBru, "perfCntCondMaluInstr")
BoringUtils.addSource(alu.io.out.fire() && isBru, "perfCntCondMbruInstr")
......
......@@ -14,6 +14,8 @@ trait HasNOOPParameter {
val HasDiv = true
val HasIcache = true
val HasDcache = true
val HasL2cache = true
val HasPrefetch = false
val AddrBits = 32
val AddrBytes = AddrBits / 8
val DataBits = XLEN
......@@ -42,7 +44,7 @@ class NOOP(implicit val p: NOOPConfig) extends NOOPModule {
val imem = new SimpleBusC
val dmem = new SimpleBusC
val mmio = new SimpleBusUC
// val prefetchReq = Decoupled(new SimpleBusReqBundle)
val prefetchReq = Decoupled(new SimpleBusReqBundle)
})
val ifu = Module(new IFU)
......@@ -73,7 +75,7 @@ class NOOP(implicit val p: NOOPConfig) extends NOOPModule {
when (idu.io.in.valid) { printf("IDU: pc = 0x%x, instr = 0x%x, pnpc = 0x%x\n", idu.io.in.bits.pc, idu.io.in.bits.instr, idu.io.in.bits.pnpc) }
when (isu.io.in.valid) { printf("ISU: pc = 0x%x, pnpc = 0x%x\n", isu.io.in.bits.cf.pc, isu.io.in.bits.cf.pnpc) }
when (exu.io.in.valid) { printf("EXU: pc = 0x%x, pnpc = 0x%x\n", exu.io.in.bits.cf.pc, exu.io.in.bits.cf.pnpc) }
when (wbu.io.in.valid) { printf("WBU: pc = 0x%x\n", wbu.io.in.bits.decode.cf.pc) }
when (wbu.io.in.valid) { printf("WBU: pc = 0x%x\n", wbu.io.in.bits.decode.cf.pc) }
}
isu.io.wb <> wbu.io.wb
......@@ -85,7 +87,7 @@ class NOOP(implicit val p: NOOPConfig) extends NOOPModule {
io.imem <> Cache(ifu.io.imem, mmioXbar.io.in(0), Fill(2, ifu.io.flushVec(0) | ifu.io.bpFlush))(
CacheConfig(ro = true, name = "icache", userBits = AddrBits*2))
io.dmem <> Cache(exu.io.dmem, mmioXbar.io.in(1), "b00".U, enable = HasDcache)(CacheConfig(ro = false, name = "dcache"))
// io.prefetchReq.bits := exu.io.dmem.req.bits
// io.prefetchReq.valid := exu.io.dmem.req.valid
io.prefetchReq.bits := exu.io.dmem.req.bits
io.prefetchReq.valid := exu.io.dmem.req.valid
io.mmio <> mmioXbar.io.out
}
......@@ -194,21 +194,21 @@ class CSR(implicit val p: NOOPConfig) extends NOOPModule with HasCSRConst {
"MmmioInstr" -> (0xb0c, "perfCntCondMmmioInstr" ),
"MicacheHit" -> (0xb0d, "perfCntCondMicacheHit" ),
"MdcacheHit" -> (0xb0e, "perfCntCondMdcacheHit" ),
"MmulInstr" -> (0xb0f, "perfCntCondMmulInstr" ),
"MifuFlush" -> (0xb10, "perfCntCondMifuFlush" ),
"MrawStall" -> (0xb11, "perfCntCondMrawStall" ),
"MexuBusy" -> (0xb12, "perfCntCondMexuBusy" ),
"MbpBRight" -> (0xb13, "MbpBRight" ),
"MbpBWrong" -> (0xb14, "MbpBWrong" ),
"MbpJRight" -> (0xb15, "MbpJRight" ),
"MbpJWrong" -> (0xb16, "MbpJWrong" ),
"MbpIRight" -> (0xb17, "MbpIRight" ),
"MbpIWrong" -> (0xb18, "MbpIWrong" ),
"MbpRRight" -> (0xb19, "MbpRRight" ),
"MbpRWrong" -> (0xb1a, "MbpRWrong" )
"Ml2cacheHit" -> (0xb0f, "perfCntCondMl2cacheHit"),
"MmulInstr" -> (0xb10, "perfCntCondMmulInstr" ),
"MifuFlush" -> (0xb11, "perfCntCondMifuFlush" ),
"MrawStall" -> (0xb12, "perfCntCondMrawStall" ),
"MexuBusy" -> (0xb13, "perfCntCondMexuBusy" ),
"MbpBRight" -> (0xb14, "MbpBRight" ),
"MbpBWrong" -> (0xb15, "MbpBWrong" ),
"MbpJRight" -> (0xb16, "MbpJRight" ),
"MbpJWrong" -> (0xb17, "MbpJWrong" ),
"MbpIRight" -> (0xb18, "MbpIRight" ),
"MbpIWrong" -> (0xb19, "MbpIWrong" ),
"MbpRRight" -> (0xb1a, "MbpRRight" ),
"MbpRWrong" -> (0xb1b, "MbpRWrong" )
)
val perfCntCond = List.fill(0x80)(WireInit(false.B))
val perfCntCond = List.fill(0x80)(WireInit(false.B))
(perfCnts zip perfCntCond).map { case (c, e) => { when (e) { c := c + 1.U } } }
BoringUtils.addSource(WireInit(true.B), "perfCntCondMcycle")
......
......@@ -67,7 +67,7 @@ class LSU extends NOOPModule {
val state = RegInit(s_idle)
switch (state) {
is (s_idle) { when (dmem.req.fire()) { state := Mux(isStore, s_partialLoad, s_wait_resp) } }
is (s_idle) { when (dmem.req.fire()) { state := s_wait_resp } }
is (s_wait_resp) { when (dmem.resp.fire()) { state := Mux(partialLoad, s_partialLoad, s_idle) } }
is (s_partialLoad) { state := s_idle }
}
......@@ -78,7 +78,7 @@ class LSU extends NOOPModule {
dmem.req.valid := valid && (state === s_idle)
dmem.resp.ready := true.B
io.out.valid := Mux(isStore || partialLoad, state === s_partialLoad, dmem.resp.fire() && (state === s_wait_resp))
io.out.valid := Mux(partialLoad, state === s_partialLoad, dmem.resp.fire() && (state === s_wait_resp))
io.in.ready := (state === s_idle)
val rdata = dmem.resp.bits.rdata
......
......@@ -11,107 +11,73 @@ trait HasCoherenceParameter extends HasNOOPParameter {
val supportCoh = HasDcache
}
class CoherenceInterconnect extends Module with HasCoherenceParameter {
class CoherenceManager extends Module with HasCoherenceParameter {
val io = IO(new Bundle {
val in = Flipped(Vec(2, new SimpleBusC))
val out = new SimpleBusUC
val in = Flipped(new SimpleBusUC)
val out = new Bundle {
val mem = new SimpleBusUC
val coh = new SimpleBusUC
}
})
def anotherMaster(thisMaster: UInt) = Mux(thisMaster === 1.U, 0.U, 1.U)
def isDcache() = inputArb.io.chosen === 1.U
// state transition:
// write: s_idle -> s_memWriteResp -> s_idle
// read from Dcache: s_idle -> s_memResp -> s_idle
// read from Icache: s_idle -> s_probeResp -> (hit) s_probeForward -> s_idle
// +> (miss) s_memReadReq -> s_memReadResp -> s_idle
// read: s_idle -> s_probeResp -> (hit) s_probeForward -> s_idle
// +> (miss) s_memReadReq -> s_memReadResp -> s_idle
val s_idle :: s_probeResp :: s_probeForward :: s_memReadReq :: s_memReadResp :: s_memWriteResp :: Nil = Enum(6)
val state = RegInit(s_idle)
val inflight = state =/= s_idle
val inflight = RegInit(false.B)
val inflightSrc = Reg(UInt(1.W)) // 0 - icache, 1 - dcache
val lockWriteFun = ((x: SimpleBusReqBundle) => x.isWrite() && x.isBurst())
val inputArb = Module(new LockingArbiter(chiselTypeOf(io.in(0).mem.req.bits), 2, 8, Some(lockWriteFun)))
(inputArb.io.in zip io.in.map(_.mem.req)).map{ case (arb, in) => arb <> in }
val thisReq = inputArb.io.out
val thisReq = io.in.req
assert(!(thisReq.valid && !thisReq.bits.isRead() && !thisReq.bits.isWrite()))
// when read, we should first probe another master
// when read, we should first probe dcache
val reqLatch = RegEnable(thisReq.bits, !inflight && thisReq.bits.isRead())
io.in.map(_.coh).map { case c => {
io.out.coh match { case c => {
c.req.bits := thisReq.bits
c.req.bits.cmd := SimpleBusCmd.probe
c.resp.ready := true.B
}}
io.out.req.bits := thisReq.bits
io.out.mem.req.bits := thisReq.bits
// bind correct valid and ready signals
io.out.req.valid := false.B
io.out.mem.req.valid := false.B
thisReq.ready := false.B
io.in.map(_.coh.req.valid).map { _ := false.B }
when (if (supportCoh) (thisReq.bits.isWrite() || isDcache()) else true.B) {
io.out.req.valid := thisReq.valid && !inflight
thisReq.ready := io.out.req.ready && !inflight
io.out.coh.req.valid := false.B
when (if (supportCoh) thisReq.bits.isWrite() else true.B) {
io.out.mem.req.valid := thisReq.valid && !inflight
thisReq.ready := io.out.mem.req.ready && !inflight
} .elsewhen (thisReq.bits.isRead()) {
io.in(anotherMaster(inputArb.io.chosen)).coh.req.valid := thisReq.valid && !inflight
thisReq.ready := io.in(anotherMaster(inputArb.io.chosen)).coh.req.ready && !inflight
io.out.coh.req.valid := thisReq.valid && !inflight
thisReq.ready := io.out.coh.req.ready && !inflight
}
io.in.map(_.mem.resp.bits := io.out.resp.bits)
io.in.map(_.mem.resp.valid := false.B)
(io.in(inflightSrc).mem.resp, io.out.resp) match { case (l, r) => {
l.valid := r.valid
r.ready := l.ready
}}
io.in.resp <> io.out.mem.resp
switch (state) {
is (s_idle) {
when (thisReq.fire()) {
inflightSrc := inputArb.io.chosen
when (thisReq.bits.isRead()) {
inflight := true.B
state := Mux(if (supportCoh) isDcache() else true.B, s_memReadResp, s_probeResp)
} .elsewhen (thisReq.bits.isWriteLast()) {
inflight := true.B
state := s_memWriteResp
}
when (thisReq.bits.isRead()) { state := Mux(supportCoh.B, s_probeResp, s_memReadResp) }
.elsewhen (thisReq.bits.isWriteLast()) { state := s_memWriteResp }
}
}
is (s_probeResp) {
when (io.in(anotherMaster(inflightSrc)).coh.resp.fire()) {
state := Mux(io.in(anotherMaster(inflightSrc)).coh.resp.bits.isProbeHit(), s_probeForward, s_memReadReq)
when (io.out.coh.resp.fire()) {
state := Mux(io.out.coh.resp.bits.isProbeHit(), s_probeForward, s_memReadReq)
}
}
is (s_probeForward) {
val thisResp = io.in(inflightSrc).mem.resp
val anotherCohResp = io.in(anotherMaster(inflightSrc)).coh.resp
thisResp.bits := anotherCohResp.bits
thisResp.valid := anotherCohResp.valid
anotherCohResp.ready := thisResp.ready
when (thisResp.fire() && thisResp.bits.isReadLast()) {
inflight := false.B
state := s_idle
}
val thisResp = io.in.resp
thisResp <> io.out.coh.resp
when (thisResp.fire() && thisResp.bits.isReadLast()) { state := s_idle }
}
is (s_memReadReq) {
io.out.req.bits := reqLatch
io.out.req.valid := true.B
when (io.out.req.fire()) { state := s_memReadResp }
}
is (s_memReadResp) {
when (io.out.resp.fire() && io.out.resp.bits.isReadLast()) {
inflight := false.B
state := s_idle
}
}
is (s_memWriteResp) {
when (io.out.resp.fire()) {
inflight := false.B
state := s_idle
}
io.out.mem.req.bits := reqLatch
io.out.mem.req.valid := true.B
when (io.out.mem.req.fire()) { state := s_memReadResp }
}
is (s_memReadResp) { when (io.out.mem.resp.fire() && io.out.mem.resp.bits.isReadLast()) { state := s_idle } }
is (s_memWriteResp) { when (io.out.mem.resp.fire()) { state := s_idle } }
}
}
package system
import noop.{NOOP, NOOPConfig, HasNOOPParameter, Cache, L2Cache, CacheConfig}
import noop.{NOOP, NOOPConfig, HasNOOPParameter, Cache, CacheConfig}
import bus.axi4.{AXI4, AXI4Lite}
import bus.simplebus._
......
package system
import noop.{NOOP, NOOPConfig, Cache, L2Cache, CacheConfig}
import noop._
import bus.axi4.{AXI4, AXI4Lite}
import bus.simplebus._
......@@ -8,7 +8,7 @@ import chisel3._
import chisel3.util._
import chisel3.util.experimental.BoringUtils
class NOOPSoC(implicit val p: NOOPConfig) extends Module {
class NOOPSoC(implicit val p: NOOPConfig) extends NOOPModule {
val io = IO(new Bundle{
val mem = new AXI4
val mmio = (if (p.FPGAPlatform) { new AXI4Lite } else { new SimpleBusUC })
......@@ -17,54 +17,47 @@ class NOOPSoC(implicit val p: NOOPConfig) extends Module {
})
val noop = Module(new NOOP)
val cohMg = Module(new CoherenceInterconnect)
cohMg.io.in(0) <> noop.io.imem
cohMg.io.in(1) <> noop.io.dmem
// add L2 Cache and Dcache Prefetcher
/*
val prefetcher = Module(new Prefetcher)
prefetcher.io.in <> noop.io.prefetchReq
val l2cacheIn = Wire(new SimpleBusUC)
val l2cacheInReqArb = Module(new Arbiter(chiselTypeOf(noop.io.prefetchReq.bits), 2))
l2cacheInReqArb.io.in(0) <> cohMg.io.out.req
l2cacheInReqArb.io.in(1) <> prefetcher.io.out
l2cacheIn.req <> l2cacheInReqArb.io.out
cohMg.io.out.resp <> l2cacheIn.resp
val cohMg = Module(new CoherenceManager)
val xbar = Module(new SimpleBusCrossbarNto1(2))
cohMg.io.in <> noop.io.imem.mem
noop.io.dmem.coh <> cohMg.io.out.coh
xbar.io.in(0) <> cohMg.io.out.mem
xbar.io.in(1) <> noop.io.dmem.mem
val mmioXbar = Module(new SimpleBusCrossbarNto1(2))
val l2cacheOut = Wire(new SimpleBusUC)
l2cacheOut <> Cache(in = l2cacheIn, mmio = mmioXbar.io.in(0), flush = "b00".U, enable = true)(CacheConfig(ro = false, name = "l2cache", cacheLevel = 2))
io.mem <> l2cacheOut.toAXI4()
if (HasL2cache) {
val l2cacheOut = Wire(new SimpleBusC)
if (HasPrefetch) {
val prefetcher = Module(new Prefetcher)
prefetcher.io.in <> noop.io.prefetchReq
val l2cacheIn = Wire(new SimpleBusUC)
val l2cacheInReqArb = Module(new Arbiter(chiselTypeOf(noop.io.prefetchReq.bits), 2))
l2cacheInReqArb.io.in(0) <> xbar.io.out.req
l2cacheInReqArb.io.in(1) <> prefetcher.io.out
l2cacheIn.req <> l2cacheInReqArb.io.out
xbar.io.out.resp <> l2cacheIn.resp
l2cacheOut <> Cache(in = l2cacheIn, mmio = 0.U.asTypeOf(new SimpleBusUC), flush = "b00".U, enable = true)(CacheConfig(ro = false, name = "l2cache", cacheLevel = 2))
} else {
l2cacheOut <> Cache(in = xbar.io.out, mmio = 0.U.asTypeOf(new SimpleBusUC), flush = "b00".U, enable = true)(CacheConfig(ro = false, name = "l2cache", cacheLevel = 2))
}
io.mem <> l2cacheOut.mem.toAXI4()
l2cacheOut.coh.resp.ready := true.B
l2cacheOut.coh.req.valid := false.B
l2cacheOut.coh.req.bits := DontCare
} else {
io.mem <> xbar.io.out.toAXI4()
}
mmioXbar.io.in(1) <> noop.io.mmio
if (p.FPGAPlatform) io.mmio <> mmioXbar.io.out.toAXI4Lite()
else io.mmio <> mmioXbar.io.out
*/
// add L2 Cache
/*
val mmioXbar = Module(new SimpleBusCrossbarNto1(2))
val l2cacheOut = Wire(new SimpleBusUC)
l2cacheOut <> Cache(in = cohMg.io.out, mmio = mmioXbar.io.in(0), flush = "b00".U, enable = true)(CacheConfig(ro = false, name = "l2cache", cacheLevel = 2))
io.mem <> l2cacheOut.toAXI4()
if (!HasPrefetch) {
noop.io.prefetchReq.ready := true.B
}
mmioXbar.io.in(1) <> noop.io.mmio
if (p.FPGAPlatform) io.mmio <> mmioXbar.io.out.toAXI4Lite()
else io.mmio <> mmioXbar.io.out
*/
// no L2 Cache
io.mem <> cohMg.io.out.toAXI4()
noop.io.imem.coh.resp.ready := true.B
noop.io.imem.coh.req.valid := false.B
noop.io.imem.coh.req.bits := DontCare
if (p.FPGAPlatform) io.mmio <> noop.io.mmio.toAXI4Lite()
else io.mmio <> noop.io.mmio
val mtipSync = RegNext(RegNext(io.mtip))
val meipSync = RegNext(RegNext(io.meip))
......
......@@ -12,4 +12,4 @@ object Debug {
object ShowType {
def apply[T: Manifest](t: T) = println(manifest[T])
}
}
package utils
import chisel3._
import chisel3.util._
class LockBundle extends Bundle {
val lock = Input(Bool())
val unlock = Input(Bool())
val holding = Output(Bool())
}
class Lock(n: Int) extends Module {
val io = IO(new Bundle {
val bundle = Vec(n, new LockBundle)
})
val lock = RegInit(0.U(n.W))
val lockReq = VecInit(io.bundle.map(_.lock)).asUInt
val unlockReq = VecInit(io.bundle.map(_.unlock)).asUInt
val lockEmpty = lock === 0.U
val hasLockReq = lockReq =/= 0.U
val lockNext = 1.U << PriorityEncoder(lockReq)
when (lockEmpty && hasLockReq) { lock := lockNext }
val hasUnlockReq = unlockReq =/= 0.U
assert(PopCount(unlockReq) <= 1.U, "only the lock holder can issue unlock request")
assert(!(lockEmpty && hasUnlockReq), "only the lock holder can issue unlock request")
assert((lock & lockReq) === 0.U, "can not issue lock request when holding the lock")
when (!lockEmpty && hasUnlockReq) {
assert(unlockReq === lock, "only the lock holder can issue unlock request")
lock := 0.U
}
val holding = Mux(lockEmpty && hasLockReq, lockNext, lock)
io.bundle.map(_.holding).zip(holding.asBools).map{ case (l, r) => l := r }
assert(PopCount(io.bundle.map(_.holding)) <= 1.U, "there should be only one lock holder")
Debug() {
when (lockEmpty && hasLockReq) { printf("%d: %d acquire lock\n", GTimer(), PriorityEncoder(lockNext)) }
when (!lockEmpty && hasUnlockReq) { printf("%d: %d release lock\n", GTimer(), PriorityEncoder(lock)) }
}
}
......@@ -84,4 +84,33 @@ class SRAMTemplate[T <: Data](gen: T, set: Int, way: Int = 1,
io.r.req.ready := !resetState && (if (singlePort) !wen else true.B)
io.w.req.ready := true.B
Debug(false) {
when (wen) {
printf("%d: SRAMTemplate: write %x to idx = %d\n", GTimer(), wdata.asUInt, setIdx)
}
when (RegNext(realRen)) {
printf("%d: SRAMTemplate: read %x at idx = %d\n", GTimer(), VecInit(rdata).asUInt, RegNext(io.r.req.bits.setIdx))
}
}
}
class SRAMTemplateWithArbiter[T <: Data](nRead: Int, gen: T, set: Int, way: Int = 1,
shouldReset: Boolean = false) extends Module {
val io = IO(new Bundle {
val r = Flipped(Vec(nRead, new SRAMReadBus(gen, set, way)))
val w = Flipped(new SRAMWriteBus(gen, set, way))
})
val ram = Module(new SRAMTemplate(gen, set, way, shouldReset, holdRead = false, singlePort = true))
ram.io.w <> io.w
val readArb = Module(new Arbiter(chiselTypeOf(io.r(0).req.bits), nRead))
readArb.io.in <> io.r.map(_.req)
ram.io.r.req <> readArb.io.out
// latch read results
io.r.map{ case r => {
r.resp.data := HoldUnless(ram.io.r.resp.data, RegNext(r.req.fire()))
}}
}
......@@ -102,7 +102,9 @@ class Emulator {
n --;
if (lastcommit - n > stuck_limit && hascommit) {
eprintf("No instruction commits for %d cycles, maybe get stuck\n", stuck_limit);
eprintf("No instruction commits for %d cycles, maybe get stuck\n"
"(please also check whether a fence.i instruction requires more than %d cycles to flush the icache)\n",
stuck_limit, stuck_limit);
set_abort();
}
......@@ -128,7 +130,23 @@ class Emulator {
}
}
void execute() { execute_cycles(max_cycles); }
void cache_test(uint64_t n) {
while (n > 0) {
single_cycle();
n --;
}
}
void execute() {
//#define CACHE_TEST
#ifdef CACHE_TEST
eprintf(ANSI_COLOR_MAGENTA "This is random test for cache.\n" ANSI_COLOR_RESET);
cache_test(max_cycles);
#else
execute_cycles(max_cycles);
#endif
}
uint64_t get_cycles() const { return cycles; }
uint64_t get_max_cycles() const { return max_cycles; }
};
package top
import noop._
import bus.simplebus._
import device._
import utils._
import chisel3._
import chisel3.util._
import chisel3.util.experimental.BoringUtils
// To run the following cache random test, do the following:
// * uncomment the following class
// * comment the NOOPSimTop class in noop/src/test/scala/top/NOOPSim.scala
// * define the macro CACHE_TEST in noop/src/test/csrc/emu.h:141
// * run 'make cache' under noop/
/*
class NOOPSimTop extends Module {
val io = IO(new Bundle{
val difftest = new DiffTestIO
})
val memBase = 0x80000000L
val cacheSizeKB = 1 // Bytes
val memSizeB = 4096 // Bytes
val NRmemBlock = memSizeB / 8
val printCnt = 100000
val Name = "dcache"
val in = WireInit(0.U.asTypeOf(new SimpleBusUC(userBits = 33)))
val cohIn = WireInit(0.U.asTypeOf(new SimpleBusUC))
val mmioOut = WireInit(0.U.asTypeOf(new SimpleBusUC))
val cacheOut = Cache(in, mmioOut, "b00".U)(CacheConfig(name = Name, totalSize = cacheSizeKB, userBits = 33, ways = 4))
val mem = Module(new AXI4RAM(memByte = memSizeB, useBlackBox = false))
mem.io.in <> cacheOut.mem.toAXI4()
cacheOut.coh <> cohIn
def addrInRange(x: UInt) = (x >= memBase.U) && x < (memBase + memSizeB).U
val perfCntHit = WireInit(false.B)
BoringUtils.addSink(perfCntHit, "perfCntCondM" + Name + "Hit")
val s_init_req :: s_init_resp :: s_test :: Nil = Enum(3)
val state = RegInit(s_init_req)
val initCnt = Counter(NRmemBlock)
switch (state) {
is (s_init_req) {
when (in.req.fire()) { state := s_init_resp }
}
is (s_init_resp) {
when (in.resp.fire()) {
val wrap = initCnt.inc()
state := Mux(wrap, s_test, s_init_req)
when (wrap) {
printf("One '.' for handling %d requests from CPU, and one '@' for handling %d coherence requests\n",
printCnt.U, printCnt.U)
}
}
}
}
val initAddr = memBase.U + initCnt.value * 8.U
val initWmask = 0xff.U
val initCmd = SimpleBusCmd.write
val randBundle = new Bundle {
val isWrite = Bool()
val readyChoose = UInt(2.W)
val wmask = UInt(8.W)
val addr = UInt(log2Up(NRmemBlock).W)
val cohChoose = UInt(1.W)
val cohAddr = UInt(log2Up(NRmemBlock).W)
val cohReadyChoose = UInt(2.W)
}
val rand = LFSR64(true.B).asTypeOf(randBundle)
val randAddr = memBase.U + rand.addr * 8.U
val randWmask = rand.wmask
val randCmd = Mux(rand.isWrite, SimpleBusCmd.write, SimpleBusCmd.read)
val addr = Mux(state === s_test, randAddr, initAddr)
val wmask = Mux(state === s_test, randWmask, initWmask)
val cmd = Mux(state === s_test, randCmd, initCmd)
val wdata = Fill(2, addr)
val user = Cat(addr, Mux(state === s_test, rand.isWrite, true.B))
in.req.bits.apply(addr = addr, size = "b11".U, user = user,
wdata = wdata, wmask = wmask, cmd = cmd)
in.req.valid := (state === s_init_req) || (state === s_test)
in.resp.ready := rand.readyChoose =/= 0.U
val cohInflight = RegInit(false.B)
when (cohIn.resp.fire()) {
val resp = cohIn.resp.bits
val isProbeEnd = resp.isProbeMiss() || (resp.cmd === SimpleBusCmd.readLast)
when (isProbeEnd) { cohInflight := false.B }
}
when (cohIn.req.fire()) { cohInflight := true.B }
cohIn.req.bits.apply(addr = rand.cohAddr * 8.U + memBase.U, size = "b11".U,
wdata = 0.U, wmask = 0.U, cmd = SimpleBusCmd.probe)
cohIn.req.valid := (state === s_test) && rand.cohChoose === 0.U && !cohInflight
cohIn.resp.ready := rand.cohReadyChoose =/= 0.U
when (Counter((state === s_test) && in.resp.fire(), printCnt)._2) { printf(".") }
when (Counter((state === s_test) && cohIn.req.fire(), printCnt)._2) { printf("@") }
Debug(false) {
when (in.req.fire()) { printf(p"${GTimer()},[in.req] ${in.req.bits}\n") }
}
def checkData(addr: UInt, data: UInt): Bool = data === Fill(2, addr)
def checkDataMask(addr: UInt, data: UInt): Bool = {
val mask = "hffffffc0".U
(data & Fill(2, mask)) === Fill(2, addr & mask)
}
assert(!(cacheOut.mem.req.valid && !addrInRange(cacheOut.mem.req.bits.addr)),
"bad addr = %x", cacheOut.mem.req.bits.addr)
// check rdata from cache
when (in.resp.valid && !in.resp.bits.user.get(0)) {
val addr = in.resp.bits.user.get(32,1)
assert(checkData(addr, in.resp.bits.rdata), "%d: bad rdata = %x at addr = %x",
GTimer(), in.resp.bits.rdata, addr)
}
// check wdata to mem
when (cacheOut.mem.req.valid && cacheOut.mem.req.bits.isWrite()) {
val addr = cacheOut.mem.req.bits.addr(31,0)
assert(checkDataMask(addr, cacheOut.mem.req.bits.wdata), "%d: bad wdata = %x at addr = %x",
GTimer(), cacheOut.mem.req.bits.wdata, addr)
}
// check rdata from cohIn
val cohAddr = RegEnable(cohIn.req.bits.addr(31,0), cohIn.req.fire())
when (cohIn.resp.valid) {
val resp = cohIn.resp.bits
val isRead = resp.cmd === SimpleBusCmd.readLast || resp.cmd === SimpleBusCmd.read
val isProbeResp = resp.isProbeHit() || resp.isProbeMiss()
assert(isRead || isProbeResp)
assert(!(isRead && !checkDataMask(cohAddr, cohIn.resp.bits.rdata)), "%d: bad rdata = %x at addr = %x",
GTimer(), cohIn.resp.bits.rdata, cohAddr)
}
// only use to keep consistent with NOOPSimTop
io.difftest := DontCare
dontTouch(io.difftest)
}
*/
......@@ -13,13 +13,10 @@ class SimMMIO extends Module {
})
val devAddrSpace = List(
// (0x40600000L, 0x10L), // uart
(0x40600000L, 0x100L),
// (0x40700000L, 0x10L), // timer
(0x40700000L, 0x100L),
(0x40600000L, 0x10L), // uart
(0x40700000L, 0x10L), // timer
(0x40000000L, 0x400000L), // vmem
// (0x40800000L, 0x8L) // vga ctrl
(0x40800000L, 0x80L)
(0x40800000L, 0x8L) // vga ctrl
)
val xbar = Module(new SimpleBusCrossbar1toN(devAddrSpace))
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册