From ccd497e4d406e549655bdc340fe8886f03f8bc01 Mon Sep 17 00:00:00 2001 From: zhanglinjuan Date: Fri, 22 Nov 2019 09:44:54 +0800 Subject: [PATCH] add prefetcher into l2cache --- src/main/scala/noop/Cache.scala | 8 ++--- src/main/scala/noop/NOOP.scala | 5 +-- src/main/scala/system/Prefetcher.scala | 42 +++++++++++++++++--------- src/main/scala/system/SoC.scala | 15 +++------ src/main/scala/utils/Debug.scala | 2 +- 5 files changed, 37 insertions(+), 35 deletions(-) diff --git a/src/main/scala/noop/Cache.scala b/src/main/scala/noop/Cache.scala index 4a2c6172a..c465049a5 100644 --- a/src/main/scala/noop/Cache.scala +++ b/src/main/scala/noop/Cache.scala @@ -406,15 +406,15 @@ sealed class CacheStage3(implicit val cacheConfig: CacheConfig) extends CacheMod Mux(hit || req.isWrite(), io.out.fire(), (state === s_wait_resp) && (io.out.fire() || alreadyOutFire)) ) - io.in.ready := io.out.ready && (state === s_idle) && !miss && !probe + io.in.ready := io.out.ready && (state === s_idle && !hitReadBurst) && !miss && !probe io.dataReadRespToL1 := hitReadBurst && (state === s_idle && io.out.ready || state === s_release && state2 === s2_dataOK) assert(!(metaHitWriteBus.req.valid && metaRefillWriteBus.req.valid)) assert(!(dataHitWriteBus.req.valid && dataRefillWriteBus.req.valid)) assert(!(!ro.B && io.flush), "only allow to flush icache") Debug(debug) { - printf("%d: [" + cacheName + " stage3]: in.ready = %d, in.valid = %d, out.valid = %d, out.ready = %d, state = %d, addr = %x, mem.req.valid = %d, mem.req.ready = %d\n\n", - GTimer(), io.in.ready, io.in.valid, io.out.valid, io.out.ready, state, req.addr, io.mem.req.valid, io.mem.req.ready) + printf("%d: [" + cacheName + " stage3]: in.ready = %d, in.valid = %d, out.valid = %d, out.ready = %d, state = %d, cmd = %x, addr = %x, mem.req.valid = %d, mem.req.ready = %d\n\n", + GTimer(), io.in.ready, io.in.valid, io.out.valid, io.out.ready, state, req.cmd, req.addr, io.mem.req.valid, io.mem.req.ready) } } @@ -451,7 +451,7 @@ class Cache(implicit val cacheConfig: CacheConfig) extends CacheModule { io.out.mem <> s3.io.mem io.mmio <> s3.io.mmio - io.in.resp.valid := Mux(s3.io.out.bits.isPrefetch(), false.B, s3.io.out.valid || s3.io.dataReadRespToL1) + io.in.resp.valid := Mux(s3.io.out.valid && s3.io.out.bits.isPrefetch(), false.B, s3.io.out.valid || s3.io.dataReadRespToL1) if (hasCoh) { val cohReq = io.out.coh.req.bits diff --git a/src/main/scala/noop/NOOP.scala b/src/main/scala/noop/NOOP.scala index 8f699a94b..d544fbd75 100644 --- a/src/main/scala/noop/NOOP.scala +++ b/src/main/scala/noop/NOOP.scala @@ -43,8 +43,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 ifu = Module(new IFU) val idu1 = Module(new IDU1) @@ -91,7 +90,5 @@ 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 + 4)) // userBits = AddrBits + BrIdxBits 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.mmio <> mmioXbar.io.out } diff --git a/src/main/scala/system/Prefetcher.scala b/src/main/scala/system/Prefetcher.scala index 3b8db603e..8d2f45b52 100644 --- a/src/main/scala/system/Prefetcher.scala +++ b/src/main/scala/system/Prefetcher.scala @@ -3,6 +3,7 @@ package system import noop.{NOOP, NOOPConfig, HasNOOPParameter, Cache, CacheConfig} import bus.axi4.{AXI4, AXI4Lite} import bus.simplebus._ +import utils._ import chisel3._ import chisel3.util._ @@ -17,19 +18,30 @@ class Prefetcher extends Module with HasPrefetcherParameter { val in = Flipped(Decoupled(new SimpleBusReqBundle)) val out = Decoupled(new SimpleBusReqBundle) }) - /* - io.in.ready := !io.in.valid || io.out.fire() - val lastReq = RegEnable(io.in.bits, io.in.fire()) - val lastAddr = lastReq.addr - io.out.bits := lastReq - io.out.bits.cmd := SimpleBusCmd.prefetch - io.out.bits.addr := lastAddr + Cat(Cat(0.U((TagBits + IndexBits - 1).W), 1.U(1.W)), 0.U(OffsetBits.W)) - io.out.valid := io.in.valid - */ - io.out.bits := io.in.bits - io.out.bits.cmd := SimpleBusCmd.prefetch - // io.out.bits.addr := io.in.bits.addr + Cat(Cat(0.U((TagBits + IndexBits - 1).W), 1.U(1.W)), 0.U(OffsetBits.W)) - io.out.bits.addr := io.in.bits.addr + 64.U(32.W) - io.out.valid := io.in.valid - io.in.ready := !io.in.valid || io.out.fire() + val getNewReq = RegInit(false.B) + val prefetchReq = RegNext(io.in.bits) + prefetchReq.cmd := SimpleBusCmd.prefetch + prefetchReq.addr := io.in.bits.addr + XLEN.U + + val lastReqAddr = (RegEnable(io.in.bits.addr, io.in.fire())) + val thisReqAddr = io.in.bits.addr + val lineMask = Cat(Fill(AddrBits - 6, 1.U(1.W)), 0.U(6.W)) + val neqAddr = (thisReqAddr & lineMask) =/= (lastReqAddr & lineMask) + + when (!getNewReq) { + io.out.bits <> io.in.bits + io.out.valid := io.in.valid + io.in.ready := !io.in.valid || io.out.fire() + getNewReq := io.in.fire() && io.in.bits.isBurst() && neqAddr + }.otherwise { + io.out.bits <> prefetchReq + io.out.valid := true.B + io.in.ready := false.B + getNewReq := !io.out.fire() + } + + Debug() { + printf("%d: [Prefetcher]: in(%d,%d), out(%d,%d), in.bits.addr = %x\n", + GTimer(), io.in.valid, io.in.ready, io.out.valid, io.out.ready, io.in.bits.addr) + } } diff --git a/src/main/scala/system/SoC.scala b/src/main/scala/system/SoC.scala index 175848206..ea007ec8c 100644 --- a/src/main/scala/system/SoC.scala +++ b/src/main/scala/system/SoC.scala @@ -11,7 +11,7 @@ import chisel3.util.experimental.BoringUtils trait HasSoCParameter { val EnableILA = false val HasL2cache = true - val HasPrefetch = false + val HasPrefetch = true } class ILABundle extends Bundle { @@ -44,12 +44,9 @@ class NOOPSoC(implicit val p: NOOPConfig) extends Module with HasSoCParameter { val l2cacheOut = Wire(new SimpleBusC) val l2cacheIn = 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 + prefetcher.io.in <> xbar.io.out.req + l2cacheIn.req <> prefetcher.io.out xbar.io.out.resp <> l2cacheIn.resp l2cacheIn } else xbar.io.out @@ -62,11 +59,7 @@ class NOOPSoC(implicit val p: NOOPConfig) extends Module with HasSoCParameter { } else { io.mem <> xbar.io.out.toAXI4() } - - if (!HasPrefetch) { - noop.io.prefetchReq.ready := true.B - } - + noop.io.imem.coh.resp.ready := true.B noop.io.imem.coh.req.valid := false.B noop.io.imem.coh.req.bits := DontCare diff --git a/src/main/scala/utils/Debug.scala b/src/main/scala/utils/Debug.scala index c53515484..9761cdfd5 100644 --- a/src/main/scala/utils/Debug.scala +++ b/src/main/scala/utils/Debug.scala @@ -7,7 +7,7 @@ import noop.NOOPConfig object Debug { def apply(flag: Boolean = NOOPConfig().EnableDebug, cond: Bool = true.B)(body: => Unit): Any = - if (flag) { when (cond && GTimer() > 739200.U) { body } } + if (flag) { when (cond && GTimer() > 100.U) { body } } } object ShowType { -- GitLab