From 9b828a2640f564bd72de71d3d881ed2d7de1bdbf Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Wed, 20 Sep 2017 15:15:21 -0700 Subject: [PATCH 1/3] Only look at error signal on last beat --- src/main/scala/rocket/ICache.scala | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/scala/rocket/ICache.scala b/src/main/scala/rocket/ICache.scala index d8a07b49..ce66c642 100644 --- a/src/main/scala/rocket/ICache.scala +++ b/src/main/scala/rocket/ICache.scala @@ -177,15 +177,13 @@ class ICacheModule(outer: ICache) extends LazyModuleImp(outer) val icache_tag_array = SeqMem(nSets, Vec(nWays, UInt(width = tECC.width(1 + tagBits)))) val tag_rdata = icache_tag_array.read(s0_vaddr(untagBits-1,blockOffBits), !refill_done && s0_valid) val accruedRefillError = Reg(Bool()) - val refillError = tl_out.d.bits.error || (refill_cnt > 0 && accruedRefillError) when (refill_done) { - val enc_tag = tECC.encode(Cat(refillError, refill_tag)) + val enc_tag = tECC.encode(Cat(tl_out.d.bits.error, refill_tag)) icache_tag_array.write(refill_idx, Vec.fill(nWays)(enc_tag), Seq.tabulate(nWays)(repl_way === _)) } val vb_array = Reg(init=Bits(0, nSets*nWays)) when (refill_one_beat) { - accruedRefillError := refillError // clear bit when refill starts so hit-under-miss doesn't fetch bad data vb_array := vb_array.bitSet(Cat(repl_way, refill_idx), refill_done && !invalidated) } From 6bc20942b5c5e500e1ac13d469fee4a0237f814f Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Wed, 20 Sep 2017 17:01:08 -0700 Subject: [PATCH 2/3] Don't cache TL error responses; report access exceptions --- src/main/scala/rocket/DCache.scala | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/main/scala/rocket/DCache.scala b/src/main/scala/rocket/DCache.scala index d703914e..cbeb1a4e 100644 --- a/src/main/scala/rocket/DCache.scala +++ b/src/main/scala/rocket/DCache.scala @@ -203,7 +203,8 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) { val s1_all_data_ways = Vec(data.io.resp :+ dummyEncodeData(tl_out.d.bits.data)) val s1_mask = Mux(s1_req.cmd === M_PWR, io.cpu.s1_data.mask, new StoreGen(s1_req.typ, s1_req.addr, UInt(0), wordBytes).mask) - val s2_valid = Reg(next=s1_valid_masked && !s1_sfence, init=Bool(false)) && !io.cpu.s2_xcpt.asUInt.orR + val s2_valid_pre_xcpt = Reg(next=s1_valid_masked && !s1_sfence, init=Bool(false)) + val s2_valid = s2_valid_pre_xcpt && !io.cpu.s2_xcpt.asUInt.orR val s2_probe = Reg(next=s1_probe, init=Bool(false)) val releaseInFlight = s1_probe || s2_probe || release_state =/= s_ready val s2_valid_masked = s2_valid && Reg(next = !s1_nack) @@ -286,15 +287,19 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) { metaArb.io.in(2).bits.data.coh := Mux(s2_valid_hit, s2_new_hit_state, ClientMetadata.onReset) metaArb.io.in(2).bits.data.tag := s2_req.addr >> untagBits - // load reservations + // load reservations and TL error reporting val s2_lr = Bool(usingAtomics && !usingDataScratchpad) && s2_req.cmd === M_XLR val s2_sc = Bool(usingAtomics && !usingDataScratchpad) && s2_req.cmd === M_XSC val lrscCount = Reg(init=UInt(0)) + val tl_error_valid = RegInit(false.B) val lrscValid = lrscCount > lrscBackoff val lrscAddr = Reg(UInt()) - val s2_sc_fail = s2_sc && !(lrscValid && lrscAddr === (s2_req.addr >> blockOffBits)) - when (s2_valid_hit && s2_lr) { - lrscCount := lrscCycles - 1 + val lrscAddrMatch = lrscAddr === (s2_req.addr >> blockOffBits) + val s2_sc_fail = s2_sc && !(lrscValid && lrscAddrMatch) + val s2_tl_error = tl_error_valid && lrscAddrMatch + when (s2_valid_hit && s2_lr && !cached_grant_wait || s2_valid_cached_miss) { + tl_error_valid := false + lrscCount := Mux(s2_hit, lrscCycles - 1, 0.U) lrscAddr := s2_req.addr >> blockOffBits } when (lrscCount > 0) { lrscCount := lrscCount - 1 } @@ -436,6 +441,7 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) { grantInProgress := true assert(cached_grant_wait, "A GrantData was unexpected by the dcache.") when(d_last) { + tl_error_valid := tl_out.d.bits.error cached_grant_wait := false grantInProgress := false blockProbeAfterGrantCount := blockProbeAfterGrantCycles - 1 @@ -487,7 +493,7 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) { // ignore backpressure from metaArb, which can only be caused by tag ECC // errors on hit-under-miss. failing to write the new tag will leave the // line invalid, so we'll simply request the line again later. - metaArb.io.in(3).valid := grantIsCached && d_done + metaArb.io.in(3).valid := grantIsCached && d_done && !tl_out.d.bits.error metaArb.io.in(3).bits.write := true metaArb.io.in(3).bits.way_en := s2_victim_way metaArb.io.in(3).bits.addr := Cat(io.cpu.req.bits.addr >> untagBits, s2_req.addr(idxMSB, 0)) @@ -614,6 +620,11 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) { val s1_xcpt_valid = tlb.io.req.valid && !s1_nack val s1_xcpt = tlb.io.resp io.cpu.s2_xcpt := Mux(RegNext(s1_xcpt_valid), RegEnable(s1_xcpt, s1_valid_not_nacked), 0.U.asTypeOf(s1_xcpt)) + when (s2_valid_pre_xcpt && s2_tl_error) { + assert(!s2_valid_hit && !s2_uncached) + when (s2_write) { io.cpu.s2_xcpt.ae.st := true } + when (s2_read) { io.cpu.s2_xcpt.ae.ld := true } + } if (usingDataScratchpad) { require(!usingVM) // therefore, req.phys means this is a slave-port access From 88c782cc70437543fa697b94f69199510b744acf Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Wed, 20 Sep 2017 17:15:00 -0700 Subject: [PATCH 3/3] Report D$ uncorrectable errors on C channel --- src/main/scala/rocket/DCache.scala | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/main/scala/rocket/DCache.scala b/src/main/scala/rocket/DCache.scala index cbeb1a4e..f38a0394 100644 --- a/src/main/scala/rocket/DCache.scala +++ b/src/main/scala/rocket/DCache.scala @@ -528,6 +528,8 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) { val s1_release_data_valid = Reg(next = dataArb.io.in(2).fire()) val s2_release_data_valid = Reg(next = s1_release_data_valid && !releaseRejected) val releaseDataBeat = Cat(UInt(0), c_count) + Mux(releaseRejected, UInt(0), s1_release_data_valid + Cat(UInt(0), s2_release_data_valid)) + val writeback_data_error = s2_data_decoded.map(_.error).reduce(_||_) + val writeback_data_uncorrectable = s2_data_decoded.map(_.uncorrectable).reduce(_||_) val nackResponseMessage = edge.ProbeAck(b = probe_bits, reportPermissions = TLPermissions.NtoN) val cleanReleaseMessage = edge.ProbeAck(b = probe_bits, reportPermissions = s2_report_param) @@ -595,6 +597,12 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) { } tl_out_c.bits.address := probe_bits.address tl_out_c.bits.data := s2_data_corrected + tl_out_c.bits.error := inWriteback && { + val accrued = Reg(Bool()) + val next = writeback_data_uncorrectable || (accrued && !c_first) + when (tl_out_c.fire()) { accrued := next } + next + } dataArb.io.in(2).valid := inWriteback && releaseDataBeat < refillCycles dataArb.io.in(2).bits.write := false @@ -728,8 +736,8 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) { { val (data_error, data_error_uncorrectable, data_error_addr) = if (usingDataScratchpad) (s2_valid_data_error, s2_data_error_uncorrectable, s2_req.addr) else { - (tl_out_c.valid && edge.hasData(tl_out_c.bits) && s2_data_decoded.map(_.error).reduce(_||_), - s2_data_decoded.map(_.uncorrectable).reduce(_||_), + (tl_out_c.fire() && inWriteback && writeback_data_error, + writeback_data_uncorrectable, tl_out_c.bits.address) } val error_addr =