From fb8af060f836cbdf99d9f6fb264b6f2c717c74f5 Mon Sep 17 00:00:00 2001 From: good-circle Date: Thu, 17 Sep 2026 23:22:17 +0800 Subject: [PATCH] CSR: skip minstret on traps Page-fault, misaligned, illegal, and interrupt-killed instructions were counted as retired. minstret only counts retired instructions. Gate the WBU/ROB retire source from raiseExceptionIntr, pipelined through commit. --- src/main/scala/nutcore/Bundle.scala | 2 ++ src/main/scala/nutcore/backend/fu/CSR.scala | 2 ++ src/main/scala/nutcore/backend/ooo/Backend.scala | 5 +++++ src/main/scala/nutcore/backend/ooo/EP.scala | 1 + src/main/scala/nutcore/backend/ooo/ROB.scala | 10 ++++++++-- src/main/scala/nutcore/backend/seq/EXU.scala | 1 + src/main/scala/nutcore/backend/seq/WBU.scala | 2 +- 7 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/main/scala/nutcore/Bundle.scala b/src/main/scala/nutcore/Bundle.scala index e638ae3cb..b5861dbd6 100644 --- a/src/main/scala/nutcore/Bundle.scala +++ b/src/main/scala/nutcore/Bundle.scala @@ -84,6 +84,7 @@ class CommitIO extends NutCoreBundle { val decode = new DecodeIO val isMMIO = Output(Bool()) val intrNO = Output(UInt(XLEN.W)) + val exception = Output(Bool()) // trap taken: do not retire / minstret val commits = Output(Vec(FuType.num, UInt(XLEN.W))) } @@ -94,6 +95,7 @@ class OOCommitIO extends NutCoreBundle with HasBackendConst{ val commits = Output(UInt(XLEN.W)) val prfidx = Output(UInt(prfAddrWidth.W)) //also as robidx val exception = Output(Bool()) + val trapped = Output(Bool()) // CSR took exception/interrupt: do not minstret val store = Output(Bool()) val brMask = Output(UInt(checkpointSize.W)) } diff --git a/src/main/scala/nutcore/backend/fu/CSR.scala b/src/main/scala/nutcore/backend/fu/CSR.scala index cd90c1c0a..4b25c6aa1 100644 --- a/src/main/scala/nutcore/backend/fu/CSR.scala +++ b/src/main/scala/nutcore/backend/fu/CSR.scala @@ -182,6 +182,7 @@ class CSRIO extends FunctionUnitIO { // for exception check val instrValid = Input(Bool()) val isBackendException = Input(Bool()) + val raiseExceptionIntr = Output(Bool()) // for differential testing val intrNO = Output(UInt(XLEN.W)) val imemMMU = Flipped(new MMUIO) @@ -654,6 +655,7 @@ class CSR(implicit val p: NutCoreConfig) extends NutCoreModule with HasCSRConst{ io.intrNO := Mux(raiseIntr, causeNO, 0.U) val raiseExceptionIntr = (raiseException || raiseIntr) && io.instrValid + io.raiseExceptionIntr := raiseExceptionIntr val retTarget = Wire(UInt(VAddrBits.W)) val trapTarget = Wire(UInt(VAddrBits.W)) io.redirect.valid := (valid && func === CSROpType.jmp) || raiseExceptionIntr || resetSatp diff --git a/src/main/scala/nutcore/backend/ooo/Backend.scala b/src/main/scala/nutcore/backend/ooo/Backend.scala index ac9ef6e5d..02940fa62 100644 --- a/src/main/scala/nutcore/backend/ooo/Backend.scala +++ b/src/main/scala/nutcore/backend/ooo/Backend.scala @@ -330,6 +330,7 @@ class Backend_ooo(implicit val p: NutCoreConfig) extends NutCoreModule with HasR brucommit.brMask := brurs.io.out.bits.brMask brucommit.decode.cf.redirect := bru.io.redirect brucommit.exception := false.B + brucommit.trapped := false.B brucommit.store := false.B bruDelayer.io.in.bits := brucommit @@ -391,6 +392,7 @@ class Backend_ooo(implicit val p: NutCoreConfig) extends NutCoreModule with HasR lsucommit.commits := lsuOut lsucommit.prfidx := lsu.io.uopOut.prfDest lsucommit.exception := lsu.io.exceptionVec.asUInt.orR + lsucommit.trapped := false.B lsucommit.store := lsu.io.commitStoreToCDB lsucommit.brMask := DontCare // FIXIT: gen lsucommit in LSU // fix exceptionVec @@ -423,6 +425,7 @@ class Backend_ooo(implicit val p: NutCoreConfig) extends NutCoreModule with HasR mducommit.decode.cf.redirect.valid := false.B mducommit.decode.cf.redirect.rtype := DontCare mducommit.exception := false.B + mducommit.trapped := false.B mducommit.store := false.B mducommit.brMask := mdurs.io.out.bits.brMask mdurs.io.commit.get := mdu.io.out.valid @@ -460,6 +463,7 @@ class Backend_ooo(implicit val p: NutCoreConfig) extends NutCoreModule with HasR csrcommit.prfidx := csrUop.prfDest csrcommit.decode.cf.redirect := csr.io.redirect csrcommit.exception := false.B + csrcommit.trapped := csr.io.raiseExceptionIntr csrcommit.store := false.B csrcommit.brMask := DontCare //FIXIT // fix wen @@ -488,6 +492,7 @@ class Backend_ooo(implicit val p: NutCoreConfig) extends NutCoreModule with HasR moucommit.prfidx := csrrs.io.out.bits.prfDest moucommit.decode.cf.redirect := mou.io.redirect moucommit.exception := false.B + moucommit.trapped := false.B moucommit.store := false.B moucommit.brMask := DontCare //FIXIT diff --git a/src/main/scala/nutcore/backend/ooo/EP.scala b/src/main/scala/nutcore/backend/ooo/EP.scala index 94293f9c4..75c385e9e 100644 --- a/src/main/scala/nutcore/backend/ooo/EP.scala +++ b/src/main/scala/nutcore/backend/ooo/EP.scala @@ -27,6 +27,7 @@ class ExecutionPipeline extends NutCoreModule { io.out.bits.isMMIO := false.B io.out.bits.intrNO := 0.U io.out.bits.exception := false.B + io.out.bits.trapped := false.B io.out.bits.store := false.B } diff --git a/src/main/scala/nutcore/backend/ooo/ROB.scala b/src/main/scala/nutcore/backend/ooo/ROB.scala index 4effc7788..5fca219b1 100644 --- a/src/main/scala/nutcore/backend/ooo/ROB.scala +++ b/src/main/scala/nutcore/backend/ooo/ROB.scala @@ -82,6 +82,7 @@ class ROB(implicit val p: NutCoreConfig) extends NutCoreModule with HasInstrType val canceled = Reg(Vec(robSize, Vec(robWidth, Bool()))) // for debug val redirect = Reg(Vec(robSize, Vec(robWidth, new RedirectIO))) val exception = Reg(Vec(robSize, Vec(robWidth, Bool()))) // Backend exception + val trapped = Reg(Vec(robSize, Vec(robWidth, Bool()))) // CSR exception/interrupt: not retired val isMMIO = Reg(Vec(robSize, Vec(robWidth, Bool()))) val intrNO = Reg(Vec(robSize, Vec(robWidth, UInt(XLEN.W)))) val prf = Mem(robSize * robWidth, UInt(XLEN.W)) @@ -186,6 +187,7 @@ class ROB(implicit val p: NutCoreConfig) extends NutCoreModule with HasInstrType redirect(index)(bank) := io.cdb(k).bits.decode.cf.redirect redirect(index)(bank).valid := io.cdb(k).bits.decode.cf.redirect.valid exception(index)(bank) := io.cdb(k).bits.exception + trapped(index)(bank) := io.cdb(k).bits.trapped // Update wen // In several cases, FU will invalidate rfWen store(index)(bank) := io.cdb(k).bits.store @@ -394,6 +396,7 @@ class ROB(implicit val p: NutCoreConfig) extends NutCoreModule with HasInstrType canceled(ringBufferHead)(i) := false.B redirect(ringBufferHead)(i).valid := false.B exception(ringBufferHead)(i) := false.B + trapped(ringBufferHead)(i) := false.B when(io.in(i).valid && io.in(i).bits.ctrl.rfWen && io.in(i).bits.ctrl.rfDest =/= 0.U){ rmtMap(io.in(i).bits.ctrl.rfDest) := Cat(ringBufferHead, i.U) rmtValid(io.in(i).bits.ctrl.rfDest) := true.B @@ -492,8 +495,11 @@ class ROB(implicit val p: NutCoreConfig) extends NutCoreModule with HasInstrType } val retireMultiTerms = retireATerm && valid(ringBufferTail)(0) && valid(ringBufferTail)(1) && !instRedirect(0) - BoringUtils.addSource(retireATerm, "perfCntCondMinstret") - BoringUtils.addSource(retireMultiTerms, "perfCntCondMultiCommit") + val minstret0 = retireATerm && valid(ringBufferTail)(0) && !trapped(ringBufferTail)(0) + val minstret1 = Mux(valid(ringBufferTail)(0), retireMultiTerms, retireATerm) && + valid(ringBufferTail)(1) && !trapped(ringBufferTail)(1) + BoringUtils.addSource(WireInit(minstret0 || minstret1), "perfCntCondMinstret") + BoringUtils.addSource(WireInit(minstret0 && minstret1), "perfCntCondMultiCommit") if (!p.FPGAPlatform || p.FPGADifftest) { for (i <- 0 until RetireWidth) { diff --git a/src/main/scala/nutcore/backend/seq/EXU.scala b/src/main/scala/nutcore/backend/seq/EXU.scala index 428ba0470..7bb2ec3ba 100644 --- a/src/main/scala/nutcore/backend/seq/EXU.scala +++ b/src/main/scala/nutcore/backend/seq/EXU.scala @@ -73,6 +73,7 @@ class EXU(implicit val p: NutCoreConfig) extends NutCoreModule { csr.io.instrValid := io.in.valid && !io.flush csr.io.isBackendException := false.B io.out.bits.intrNO := csr.io.intrNO + io.out.bits.exception := csr.io.raiseExceptionIntr csr.io.isBackendException := false.B csr.io.out.ready := true.B diff --git a/src/main/scala/nutcore/backend/seq/WBU.scala b/src/main/scala/nutcore/backend/seq/WBU.scala index 3cdaf8bb1..fe1999e7c 100644 --- a/src/main/scala/nutcore/backend/seq/WBU.scala +++ b/src/main/scala/nutcore/backend/seq/WBU.scala @@ -41,7 +41,7 @@ class WBU(implicit val p: NutCoreConfig) extends NutCoreModule{ Debug(io.in.valid, "[COMMIT] pc = 0x%x inst %x wen %x wdst %x wdata %x mmio %x intrNO %x\n", io.in.bits.decode.cf.pc, io.in.bits.decode.cf.instr, io.wb.rfWen, io.wb.rfDest, io.wb.rfData, io.in.bits.isMMIO, io.in.bits.intrNO) val falseWire = WireInit(false.B) // make BoringUtils.addSource happy - BoringUtils.addSource(io.in.valid, "perfCntCondMinstret") + BoringUtils.addSource(WireInit(io.in.valid && !io.in.bits.exception), "perfCntCondMinstret") BoringUtils.addSource(falseWire, "perfCntCondMultiCommit") if (!p.FPGAPlatform || p.FPGADifftest) {