From 034ea722f47afdf370114ffc4c3a1df3c4ab21a2 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Fri, 15 Sep 2017 18:41:50 -0700 Subject: [PATCH] Report I$ errors --- src/main/scala/rocket/Frontend.scala | 2 ++ src/main/scala/rocket/ICache.scala | 36 +++++++++++++++++++++------- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/src/main/scala/rocket/Frontend.scala b/src/main/scala/rocket/Frontend.scala index c5ac2576..dd102957 100644 --- a/src/main/scala/rocket/Frontend.scala +++ b/src/main/scala/rocket/Frontend.scala @@ -70,6 +70,7 @@ class FrontendBundle(outer: Frontend) extends CoreBundle()(outer.p) val ptw = new TLBPTWIO() val tl_out = outer.masterNode.bundleOut val tl_in = outer.slaveNode.bundleIn + val errors = new ICacheErrors } class FrontendModule(outer: Frontend) extends LazyModuleImp(outer) @@ -286,6 +287,7 @@ class FrontendModule(outer: Frontend) extends LazyModuleImp(outer) // performance events io.cpu.perf := icache.io.perf io.cpu.perf.tlbMiss := io.ptw.req.fire() + io.errors := icache.io.errors def alignPC(pc: UInt) = ~(~pc | (coreInstBytes - 1)) } diff --git a/src/main/scala/rocket/ICache.scala b/src/main/scala/rocket/ICache.scala index a0e2d5e2..d8a07b49 100644 --- a/src/main/scala/rocket/ICache.scala +++ b/src/main/scala/rocket/ICache.scala @@ -36,6 +36,11 @@ class ICacheReq(implicit p: Parameters) extends CoreBundle()(p) with HasL1ICache val addr = UInt(width = vaddrBits) } +class ICacheErrors(implicit p: Parameters) extends CoreBundle()(p) with HasL1ICacheParameters { + val correctable = (cacheParams.tagECC.canDetect || cacheParams.dataECC.canDetect).option(Valid(UInt(width = paddrBits))) + val uncorrectable = (cacheParams.itimAddr.nonEmpty && cacheParams.dataECC.canDetect).option(Valid(UInt(width = paddrBits))) +} + class ICache(val icacheParams: ICacheParams, val hartid: Int)(implicit p: Parameters) extends LazyModule { lazy val module = new ICacheModule(this) val masterNode = TLClientNode(TLClientParameters( @@ -87,6 +92,7 @@ class ICacheBundle(outer: ICache) extends CoreBundle()(outer.p) { val tl_out = outer.masterNode.bundleOut val tl_in = outer.slaveNode.map(_.bundleIn) + val errors = new ICacheErrors val perf = new ICachePerfEvents().asOutput } @@ -116,10 +122,10 @@ class ICacheModule(outer: ICache) extends LazyModuleImp(outer) val scratchpadOn = RegInit(false.B) val scratchpadMax = tl_in.map(tl => Reg(UInt(width = log2Ceil(nSets * (nWays - 1))))) def lineInScratchpad(line: UInt) = scratchpadMax.map(scratchpadOn && line <= _).getOrElse(false.B) - def addrMaybeInScratchpad(addr: UInt) = if (outer.icacheParams.itimAddr.isEmpty) false.B else { - val base = GetPropertyByHartId(p(RocketTilesKey), _.icache.flatMap(_.itimAddr.map(_.U)), io.hartid) - addr >= base && addr < base + outer.size + val scratchpadBase = outer.icacheParams.itimAddr.map { dummy => + GetPropertyByHartId(p(RocketTilesKey), _.icache.flatMap(_.itimAddr.map(_.U)), io.hartid) } + def addrMaybeInScratchpad(addr: UInt) = scratchpadBase.map(base => addr >= base && addr < base + outer.size).getOrElse(false.B) def addrInScratchpad(addr: UInt) = addrMaybeInScratchpad(addr) && lineInScratchpad(addr(untagBits+log2Ceil(nWays)-1, blockOffBits)) def scratchpadWay(addr: UInt) = addr.extract(untagBits+log2Ceil(nWays)-1, untagBits) def scratchpadWayValid(way: UInt) = way < nWays - 1 @@ -248,12 +254,15 @@ class ICacheModule(outer: ICache) extends LazyModuleImp(outer) io.resp.valid := s1_valid && s1_hit case 2 => - val s2_tag_hit = RegEnable(s1_tag_hit, s1_valid || s1_slaveValid) - val s2_dout = RegEnable(s1_dout, s1_valid || s1_slaveValid) + val s1_clk_en = s1_valid || s1_slaveValid + val s2_tag_hit = RegEnable(s1_tag_hit, s1_clk_en) + val s2_hit_way = OHToUInt(s2_tag_hit) + val s2_scratchpad_word_addr = Cat(s2_hit_way, io.s2_vaddr(untagBits-1, log2Ceil(wordBits/8)), UInt(0, log2Ceil(wordBits/8))) + val s2_dout = RegEnable(s1_dout, s1_clk_en) val s2_way_mux = Mux1H(s2_tag_hit, s2_dout) - val s2_tag_disparity = RegEnable(s1_tag_disparity, s1_valid || s1_slaveValid).asUInt.orR - val s2_tl_error = RegEnable(s1_tl_error.asUInt.orR, s1_valid || s1_slaveValid) + val s2_tag_disparity = RegEnable(s1_tag_disparity, s1_clk_en).asUInt.orR + val s2_tl_error = RegEnable(s1_tl_error.asUInt.orR, s1_clk_en) val s2_data_decoded = dECC.decode(s2_way_mux) val s2_disparity = s2_tag_disparity || s2_data_decoded.error when (s2_valid && s2_disparity) { invalidate := true } @@ -263,6 +272,17 @@ class ICacheModule(outer: ICache) extends LazyModuleImp(outer) io.resp.bits.replay := s2_disparity io.resp.valid := s2_valid && s2_hit + val s1_scratchpad_hit = Mux(s1_slaveValid, lineInScratchpad(scratchpadLine(s1s3_slaveAddr)), addrInScratchpad(io.s1_paddr)) + val s2_scratchpad_hit = RegEnable(s1_scratchpad_hit, s1_clk_en) + io.errors.correctable.foreach { c => + c.valid := s2_valid && Mux(s2_scratchpad_hit, s2_data_decoded.correctable, s2_disparity) + c.bits := 0.U + } + io.errors.uncorrectable.foreach { u => + u.valid := s2_valid && s2_scratchpad_hit && s2_data_decoded.uncorrectable + u.bits := scratchpadBase.get + s2_scratchpad_word_addr + } + tl_in.map { tl => val respValid = RegInit(false.B) tl.a.ready := !(tl_out.d.valid || s1_slaveValid || s2_slaveValid || s3_slaveValid || respValid) @@ -290,7 +310,7 @@ class ICacheModule(outer: ICache) extends LazyModuleImp(outer) // a structural hazard on s1s3_slaveData/s1s3_slaveAddress). s3_slaveValid := true s1s3_slaveData := s2_data_decoded.corrected - s1s3_slaveAddr := Cat(OHToUInt(s2_tag_hit), io.s2_vaddr(untagBits-1, log2Ceil(wordBits/8)), s1s3_slaveAddr(log2Ceil(wordBits/8)-1, 0)) + s1s3_slaveAddr := s2_scratchpad_word_addr | s1s3_slaveAddr(log2Ceil(wordBits/8)-1, 0) } respValid := s2_slaveValid || (respValid && !tl.d.ready)