From da07c924bfeeda41120cc179f186c7aa1b8bc9eb Mon Sep 17 00:00:00 2001 From: ecall73 Date: Thu, 28 May 2026 14:30:23 +0800 Subject: [PATCH] feat(pmu): integrate CUTEPMU AME perf counters --- src/main/scala/cutewrapper/XSCuteTop.scala | 1 + src/main/scala/xiangshan/XSCore.scala | 18 +++ src/main/scala/xiangshan/XSTile.scala | 17 ++- src/main/scala/xiangshan/backend/fu/CSR.scala | 4 + .../backend/fu/NewCSR/CSRPermitModule.scala | 59 +++++++- .../backend/fu/NewCSR/HypervisorLevel.scala | 7 +- .../backend/fu/NewCSR/MachineLevel.scala | 83 ++++++++++- .../xiangshan/backend/fu/NewCSR/NewCSR.scala | 131 +++++++++++++++++- .../backend/fu/NewCSR/SupervisorLevel.scala | 30 +++- .../backend/fu/NewCSR/Unprivileged.scala | 64 ++++++++- .../xiangshan/backend/fu/util/CSRConst.scala | 17 +++ 11 files changed, 414 insertions(+), 17 deletions(-) diff --git a/src/main/scala/cutewrapper/XSCuteTop.scala b/src/main/scala/cutewrapper/XSCuteTop.scala index 8d9002f1a42..59cdd364bba 100644 --- a/src/main/scala/cutewrapper/XSCuteTop.scala +++ b/src/main/scala/cutewrapper/XSCuteTop.scala @@ -22,6 +22,7 @@ class XSCuteTopImpl(wrapper: XSCuteTop) extends LazyModuleImp(wrapper) { val matrix_data_in = wrapper.cute_tl.module.io.matrix_data_in.cloneType }) io.ctrl2top <> cute.io.ctrl2top + io.perf <> cute.io.perf wrapper.cute_tl.module.io.matrix_data_in <> io.matrix_data_in wrapper.cute_tl.module.io.mmu <> cute.io.mmu2llc io.mmu2llc := DontCare diff --git a/src/main/scala/xiangshan/XSCore.scala b/src/main/scala/xiangshan/XSCore.scala index 2aebce35d1e..15157a8299c 100644 --- a/src/main/scala/xiangshan/XSCore.scala +++ b/src/main/scala/xiangshan/XSCore.scala @@ -36,6 +36,7 @@ import xiangshan.backend.trace.TraceCoreInterface import xiangshan.mem._ import xiangshan.cache.mmu._ import xiangshan.cache.mmu.TlbRequestIO +import cute.{AmePerfFromCSRIO, AmePerfToCoreIO} import scala.collection.mutable.ListBuffer abstract class XSModule(implicit val p: Parameters) extends Module @@ -119,6 +120,8 @@ class XSCoreImp(outer: XSCoreBase) extends LazyModuleImp(outer) val dft_reset = Option.when(hasDFT)(Input(new DFTResetSignals())) val amuCtrl = Option.when(HasMatrixExtension)(Decoupled(new AmuCtrlIO)) val amuRelease = Option.when(HasMatrixExtension)(Flipped(Decoupled(new AmuReleaseIO2XS))) + val ameToCUTE = Option.when(HasMatrixExtension)(Output(new AmePerfFromCSRIO)) + val ameFromCUTE = Option.when(HasMatrixExtension)(Input(new AmePerfToCoreIO)) }) dontTouch(io.l2_flush_done) @@ -206,8 +209,23 @@ class XSCoreImp(outer: XSCoreBase) extends LazyModuleImp(outer) backend.io.perf.perfEventsBackend := DontCare backend.io.perf.retiredInstr := DontCare backend.io.perf.ctrlInfo := DontCare + backend.io.perf.perfEventsAme.foreach(_.value := 0.U) + backend.io.perf.fixedPerfAme.foreach(_.value := 0.U) backend.io.mem.storeDebugInfo <> memBlock.io.mem_to_ooo.storeDebugInfo + + if (HasMatrixExtension) { + val enableAme = p(MatAccKey) == MatAcc.CUTE + io.ameToCUTE.get.csrW.valid := false.B + io.ameToCUTE.get.csrW.bits.addr := 0.U + io.ameToCUTE.get.csrW.bits.data := 0.U + + when(enableAme.B) { + io.ameToCUTE.get.csrW := backend.io.csrCustomCtrl.distribute_csr.w + backend.io.perf.perfEventsAme := io.ameFromCUTE.get.perfEventsAme + backend.io.perf.fixedPerfAme := io.ameFromCUTE.get.fixedPerfAme + } + } if (HasMatrixExtension) { val amuCtrlArbiter = Module(new Arbiter(new AmuCtrlIO, CommitWidth)) diff --git a/src/main/scala/xiangshan/XSTile.scala b/src/main/scala/xiangshan/XSTile.scala index 60519385b41..576c65ca6bf 100644 --- a/src/main/scala/xiangshan/XSTile.scala +++ b/src/main/scala/xiangshan/XSTile.scala @@ -33,7 +33,7 @@ import coupledL2.tl2chi.PortIO import xiangshan.backend.trace.TraceCoreInterface import xiangshan.backend.fu.matrix._ import xiangshan.backend.fu.matrix.Bundles._ -import cute.XSCute +import cute.{AmePerfToCoreIO, XSCute} object MatAcc extends Enumeration { type MatAcc = Value @@ -258,10 +258,25 @@ class XSTile()(implicit p: Parameters) extends LazyModule val matrix_data_out = l2top.module.io.matrixDataOut512L2 cute.module.io.matrix_data_in <> matrix_data_out + core.module.io.ameToCUTE.foreach { toCUTE => + cute.module.io.cute.perf.fromCSR <> toCUTE + } + core.module.io.ameFromCUTE.foreach { fromCUTE => + fromCUTE <> cute.module.io.cute.perf.toCore + } cute.module.io.hartId := io.hartId } + if (HasMatrixExtension && cuteOpt.isEmpty) { + core.module.io.ameToCUTE.foreach { toCUTE => + toCUTE.csrW.valid := false.B + toCUTE.csrW.bits.addr := 0.U + toCUTE.csrW.bits.data := 0.U + } + core.module.io.ameFromCUTE.foreach(_ := 0.U.asTypeOf(new AmePerfToCoreIO)) + } + if (!HasMatrixExtension) { l2top.module.io.matrixDataOut512L2 := DontCare l2top.module.io.matrixDataOut512L2.foreach(_.ready := false.B) diff --git a/src/main/scala/xiangshan/backend/fu/CSR.scala b/src/main/scala/xiangshan/backend/fu/CSR.scala index 80f407f6c4a..fd500a1c320 100644 --- a/src/main/scala/xiangshan/backend/fu/CSR.scala +++ b/src/main/scala/xiangshan/backend/fu/CSR.scala @@ -36,6 +36,7 @@ import utils.MathUtils.{BigIntGenMask, BigIntNot} import xiangshan.backend.trace._ import freechips.rocketchip.rocket.CSRs import system.HasSoCParameter +import cute.{CuteParamsKey, PerfEventAme} class FpuCsrIO extends Bundle { val fflags = Output(Valid(UInt(5.W))) @@ -70,10 +71,13 @@ class MpuCsrIO(implicit p: Parameters) extends XSBundle { } class PerfCounterIO(implicit p: Parameters) extends XSBundle { + private val ameCounterNum = if (HasMatrixExtension && p(MatAccKey) == MatAcc.CUTE) p(CuteParamsKey).AmeCounterNum else 29 val perfEventsFrontend = Vec(numCSRPCntFrontend, new PerfEvent) val perfEventsBackend = Vec(numCSRPCntCtrl, new PerfEvent) val perfEventsLsu = Vec(numCSRPCntLsu, new PerfEvent) val perfEventsHc = Vec(numPCntHc * coreParams.L2NBanks + 1, new PerfEvent) + val perfEventsAme = Vec(ameCounterNum, new PerfEventAme) + val fixedPerfAme = Vec(2, new PerfEventAme) val retiredInstr = UInt(7.W) val frontendInfo = new Bundle { val ibufFull = Bool() diff --git a/src/main/scala/xiangshan/backend/fu/NewCSR/CSRPermitModule.scala b/src/main/scala/xiangshan/backend/fu/NewCSR/CSRPermitModule.scala index 2fc34e951db..4f0e1348c83 100644 --- a/src/main/scala/xiangshan/backend/fu/NewCSR/CSRPermitModule.scala +++ b/src/main/scala/xiangshan/backend/fu/NewCSR/CSRPermitModule.scala @@ -7,6 +7,7 @@ import freechips.rocketchip.rocket.CSRs import xiangshan.backend.fu.NewCSR.CSRBundles.{Counteren, PrivState} import xiangshan.backend.fu.NewCSR.CSRDefines._ import org.chipsalliance.cde.config.Parameters +import xiangshan.backend.fu.util.CSRConst._ import system.HasSoCParameter class CSRPermitModule(implicit p: Parameters) extends Module { @@ -186,6 +187,8 @@ class MLevelPermitModule extends Module { private val tvm = io.in.status.tvm private val mcounteren = io.in.xcounteren.mcounteren + private val ameMcounteren = io.in.xcounteren.ameMcounteren + private val ameScounteren = io.in.xcounteren.ameScounteren private val mstateen0 = io.in.xstateen.mstateen0 private val mstateen1 = io.in.xstateen.mstateen1 @@ -211,6 +214,7 @@ class MLevelPermitModule extends Module { private val csrIsRO = addr(11, 10) === "b11".U private val csrIsHPM = addr >= CSRs.cycle.U && addr <= CSRs.hpmcounter31.U + private val csrIsAmeURO = addr === AmeCycle.U || addr === AmeInstret.U || (addr >= AmeHpmcounter3.U && addr <= AmeHpmcounter31.U) private val csrIsFp = Seq(CSRs.fflags, CSRs.frm, CSRs.fcsr).map(_.U === addr).reduce(_ || _) private val csrIsVec = Seq(CSRs.vstart, CSRs.vxsat, CSRs.vxrm, CSRs.vcsr, CSRs.vtype).map(_.U === addr).reduce(_ || _) private val csrIsWritableVec = Seq(CSRs.vstart, CSRs.vxsat, CSRs.vxrm, CSRs.vcsr).map(_.U === addr).reduce(_ || _) @@ -218,6 +222,7 @@ class MLevelPermitModule extends Module { private val csrIsWritableMatrix = Seq(CSRs.xmcsr, CSRs.xmxrm, CSRs.xmsat, CSRs.xmfflags, CSRs.xmfrm, CSRs.xmsaten).map(_.U === addr).reduce(_ || _) private val counterAddr = addr(4, 0) // 32 counters + private val ameCounterAddr = Mux(addr === AmeCycle.U, 0.U, Mux(addr === AmeInstret.U, 2.U, addr(4, 0))) private val rwIllegal = csrIsRO && wen @@ -234,6 +239,11 @@ class MLevelPermitModule extends Module { private val rwStimecmp_EX_II = !privState.isModeM && (!mcounterenTM || !menvcfgSTCE) && (addr === CSRs.vstimecmp.U || addr === CSRs.stimecmp.U) private val accessHPM_EX_II = csrIsHPM && !privState.isModeM && !mcounteren(counterAddr) + private val accessAmeURO_EX_II = csrIsAmeURO && ( + privState.isModeHS && !ameMcounteren(ameCounterAddr) || + privState.isModeHU && (!ameMcounteren(ameCounterAddr) || !ameScounteren(ameCounterAddr)) + ) + private val accessAmeScountovf_EX_II = addr === AmeScountovf.U && privState.isModeHU private val rwSatp_EX_II = privState.isModeHS && tvm && (addr === CSRs.satp.U || addr === CSRs.hgatp.U) @@ -294,7 +304,17 @@ class MLevelPermitModule extends Module { // [0x800, 0x8ff], [0xcc0, 0xcff] private val csrIsUCustom = (addr(11, 8) === "b1000".U) || (addr(11, 6) === "b110011".U) private val allCustom = csrIsHVSCustom || csrIsSCustom || csrIsUCustom - private val accessCustom_EX_II = allCustom && !privState.isModeM && !mstateen0.C.asBool + private val csrIsAmeCounterCSR = ( + addr === AmeMcounteren.U || addr === AmeScounteren.U || addr === AmeHcounteren.U || + addr === AmeMcountinhibit.U || + (addr >= AmeMhpmevent3.U && addr <= AmeMhpmevent31.U) || + (addr >= AmeMhpmcounter3.U && addr <= AmeMhpmcounter31.U) || + addr === AmeMcycle.U || addr === AmeMinstret.U || + addr === AmeCycle.U || addr === AmeInstret.U || + (addr >= AmeHpmcounter3.U && addr <= AmeHpmcounter31.U) || + addr === AmeScountovf.U + ) + private val accessCustom_EX_II = allCustom && !csrIsAmeCounterCSR && !privState.isModeM && !mstateen0.C.asBool private val xstateControlAccess_EX_II = accessStateen_EX_II || accessEnvcfg_EX_II || accessIND_EX_II || accessAIA_EX_II || accessTopie_EX_II || accessContext_EX_II || accessCustom_EX_II @@ -303,7 +323,7 @@ class MLevelPermitModule extends Module { */ io.out.mLevelPermit_EX_II := rwIllegal || fpVecMatrix_EX_II || rwStimecmp_EX_II || - accessHPM_EX_II || rwSatp_EX_II || rwStopei_EX_II || xstateControlAccess_EX_II + accessHPM_EX_II || accessAmeURO_EX_II || accessAmeScountovf_EX_II || rwSatp_EX_II || rwStopei_EX_II || xstateControlAccess_EX_II io.out.hasLegalWriteFcsr := wen && csrIsFp && !fsEffectiveOff io.out.hasLegalWriteVcsr := wen && csrIsWritableVec && !vsEffectiveOff io.out.hasLegalWriteMcsr := wen && csrIsWritableMatrix && !msEffectiveOff @@ -337,7 +357,8 @@ class SLevelPermitModule extends Module { private val accessHPM_EX_II = csrIsHPM && privState.isModeHU && !scounteren(counterAddr) private val csrIsUCustom = (addr(11, 8) === "b1000".U) || (addr(11, 6) === "b110011".U) - private val accessCustom_EX_II = csrIsUCustom && privState.isModeHU && !sstateen0.C.asBool + private val csrIsAmeURO = addr === AmeCycle.U || addr === AmeInstret.U || (addr >= AmeHpmcounter3.U && addr <= AmeHpmcounter31.U) + private val accessCustom_EX_II = csrIsUCustom && !csrIsAmeURO && privState.isModeHU && !sstateen0.C.asBool io.out.sLevelPermit_EX_II := accessHPM_EX_II || accessCustom_EX_II } @@ -417,9 +438,12 @@ class VirtualLevelPermitModule(implicit val p: Parameters) extends Module with H io.in.status.vgein, ) - private val (hcounteren, scounteren) = ( + private val (hcounteren, scounteren, ameMcounteren, ameHcounteren, ameScounteren) = ( io.in.xcounteren.hcounteren, io.in.xcounteren.scounteren, + io.in.xcounteren.ameMcounteren, + io.in.xcounteren.ameHcounteren, + io.in.xcounteren.ameScounteren, ) private val hcounterenTM = hcounteren(1) @@ -439,7 +463,9 @@ class VirtualLevelPermitModule(implicit val p: Parameters) extends Module with H private val hvictlVTI = io.in.aia.hvictlVTI private val csrIsHPM = addr >= CSRs.cycle.U && addr <= CSRs.hpmcounter31.U + private val csrIsAmeURO = addr === AmeCycle.U || addr === AmeInstret.U || (addr >= AmeHpmcounter3.U && addr <= AmeHpmcounter31.U) private val counterAddr = addr(4, 0) // 32 counters + private val ameCounterAddr = Mux(addr === AmeCycle.U, 0.U, Mux(addr === AmeInstret.U, 2.U, addr(4, 0))) private val rwSatp_EX_VI = privState.isModeVS && vtvm && (addr === CSRs.satp.U) @@ -455,6 +481,11 @@ class VirtualLevelPermitModule(implicit val p: Parameters) extends Module with H privState.isModeVS && !hcounteren(counterAddr) || privState.isModeVU && (!hcounteren(counterAddr) || !scounteren(counterAddr)) ) + private val accessAmeURO_EX_VI = csrIsAmeURO && ( + privState.isModeVS && (!ameMcounteren(ameCounterAddr) || !ameHcounteren(ameCounterAddr)) || + privState.isModeVU && (!ameMcounteren(ameCounterAddr) || !ameHcounteren(ameCounterAddr) || !ameScounteren(ameCounterAddr)) + ) + private val accessAmeScountovf_EX_VI = addr === AmeScountovf.U && privState.isModeVU /** * Sm/Ssstateen begin @@ -496,14 +527,25 @@ class VirtualLevelPermitModule(implicit val p: Parameters) extends Module with H private val csrIsSCustom = (addr(11, 10) =/= "b00".U) && (addr(9, 8) === "b01".U) && (addr(7, 6) === "b11".U) // [0x800, 0x8ff], [0xcc0, 0xcff] private val csrIsUCustom = (addr(11, 8) === "b1000".U) || (addr(11, 6) === "b110011".U) - private val accessCustom_EX_VI = (csrIsSCustom || csrIsUCustom) && privState.isVirtual && !hstateen0.C.asBool || - csrIsUCustom && privState.isModeVU && hstateen0.C.asBool && !sstateen0.C.asBool + private val csrIsAmeCounterCSR = ( + addr === AmeMcounteren.U || addr === AmeScounteren.U || addr === AmeHcounteren.U || + addr === AmeMcountinhibit.U || + (addr >= AmeMhpmevent3.U && addr <= AmeMhpmevent31.U) || + (addr >= AmeMhpmcounter3.U && addr <= AmeMhpmcounter31.U) || + addr === AmeMcycle.U || addr === AmeMinstret.U || + addr === AmeCycle.U || addr === AmeInstret.U || + (addr >= AmeHpmcounter3.U && addr <= AmeHpmcounter31.U) || + addr === AmeScountovf.U + ) + private val accessCustom_EX_VI = (csrIsSCustom || csrIsUCustom) && !csrIsAmeCounterCSR && privState.isVirtual && !hstateen0.C.asBool || + csrIsUCustom && !csrIsAmeCounterCSR && privState.isModeVU && hstateen0.C.asBool && !sstateen0.C.asBool private val xstateControlAccess_EX_VI = accessStateen_EX_VI || accessEnvcfg_EX_VI || accessIND_EX_VI || accessAIA_EX_VI || accessTopie_EX_VI || accessContext_EX_VI || accessCustom_EX_VI io.out.virtualLevelPermit_EX_II := rwVStopei_EX_II - io.out.virtualLevelPermit_EX_VI := rwSatp_EX_VI || rwStopei_EX_VI || rwSip_Sie_EX_VI || rwStimecmp_EX_VI || accessHPM_EX_VI || xstateControlAccess_EX_VI + io.out.virtualLevelPermit_EX_VI := rwSatp_EX_VI || rwStopei_EX_VI || rwSip_Sie_EX_VI || rwStimecmp_EX_VI || + accessHPM_EX_VI || accessAmeURO_EX_VI || accessAmeScountovf_EX_VI || xstateControlAccess_EX_VI } class IndirectCSRPermitModule extends Module { @@ -620,6 +662,9 @@ class xcounterenIO extends Bundle { // Accessing PMC from **HU level** will trap EX_II, if s[x]=0 // Accessing PMC from **VU level** will trap EX_VI, if m[x]=1 && h[x]=1 && s[x]=0 val scounteren = UInt(32.W) + val ameMcounteren = UInt(32.W) + val ameHcounteren = UInt(32.W) + val ameScounteren = UInt(32.W) } class xenvcfgIO extends Bundle { diff --git a/src/main/scala/xiangshan/backend/fu/NewCSR/HypervisorLevel.scala b/src/main/scala/xiangshan/backend/fu/NewCSR/HypervisorLevel.scala index 5e30fdd2dca..db99c8c85e7 100644 --- a/src/main/scala/xiangshan/backend/fu/NewCSR/HypervisorLevel.scala +++ b/src/main/scala/xiangshan/backend/fu/NewCSR/HypervisorLevel.scala @@ -12,6 +12,7 @@ import xiangshan.backend.fu.NewCSR.CSREnumTypeImplicitCast._ import xiangshan.backend.fu.NewCSR.CSREvents.{SretEventSinkBundle, TrapEntryHSEventSinkBundle} import xiangshan.backend.fu.NewCSR.CSRFunc._ import xiangshan.backend.fu.NewCSR.ChiselRecordForField._ +import xiangshan.backend.fu.util.CSRConst._ import system.HasSoCParameter import scala.collection.immutable.SeqMap @@ -61,6 +62,10 @@ trait HypervisorLevel { self: NewCSR => val hcounteren = Module(new CSRModule("Hcounteren", new Counteren)) .setAddr(CSRs.hcounteren) + val ameHcounteren = if (enableAme) Some( + Module(new CSRModule("AmeHcounteren", new Counteren)).setAddr(AmeHcounteren) + ) else None + val hgeie = Module(new CSRModule("Hgeie", new HgeieBundle)) .setAddr(CSRs.hgeie) @@ -217,7 +222,7 @@ trait HypervisorLevel { self: NewCSR => hstateen2, hstateen3, hcontext, - ) + ) ++ ameHcounteren.toSeq val hypervisorCSRMap: SeqMap[Int, (CSRAddrWriteBundle[_], UInt)] = SeqMap.from( hypervisorCSRMods.map(csr => (csr.addr -> (csr.w -> csr.rdata))).iterator diff --git a/src/main/scala/xiangshan/backend/fu/NewCSR/MachineLevel.scala b/src/main/scala/xiangshan/backend/fu/NewCSR/MachineLevel.scala index 98a2d19e197..3f1cccea430 100644 --- a/src/main/scala/xiangshan/backend/fu/NewCSR/MachineLevel.scala +++ b/src/main/scala/xiangshan/backend/fu/NewCSR/MachineLevel.scala @@ -127,6 +127,10 @@ trait MachineLevel { self: NewCSR => val mcounteren = Module(new CSRModule("Mcounteren", new Counteren)) .setAddr(CSRs.mcounteren) + val ameMcounteren = if (enableAme) Some( + Module(new CSRModule("AmeMcounteren", new Counteren)).setAddr(AmeMcounteren) + ) else None + val mvien = Module(new CSRModule("Mvien", new MvienBundle)) .setAddr(CSRs.mvien) @@ -187,6 +191,10 @@ trait MachineLevel { self: NewCSR => val mcountinhibit = Module(new CSRModule("Mcountinhibit", new McountinhibitBundle)) .setAddr(CSRs.mcountinhibit) + val ameMcountinhibit = if (enableAme) Some( + Module(new CSRModule("AmeMcountinhibit", new McountinhibitBundle)).setAddr(AmeMcountinhibit) + ) else None + val mhpmevents: Seq[CSRModule[_]] = (3 to 0x1F).map(num => Module(new CSRModule(s"Mhpmevent", new MhpmeventBundle) with HasOfFromPerfCntBundle { when(wen){ @@ -198,6 +206,16 @@ trait MachineLevel { self: NewCSR => .setAddr(CSRs.mhpmevent3 - 3 + num).suggestName(s"Mhpmevent$num") ) + val ameMhpmevents: Seq[CSRModule[_]] = if (enableAme) (0 until ameCounterNum).map(idx => + Module(new CSRModule(s"AmeMhpmevent${idx + 3}", new MhpmeventBundle) with HasOfFromPerfCntBundle { + when(wen){ + reg.OF := wdata.OF + }.elsewhen(ofFromPerfCnt) { + reg.OF := ofFromPerfCnt + } + }).setAddr(AmeMhpmevent3 + idx) + ) else Seq.empty + val mscratch = Module(new CSRModule("Mscratch")) .setAddr(CSRs.mscratch) @@ -336,6 +354,18 @@ trait MachineLevel { self: NewCSR => } }).setAddr(CSRs.mcycle) + val ameMcycle = if (enableAme) Some( + Module(new CSRModule("AmeMcycle") with HasAmeFixedPerfBundle { + when(w.wen) { + reg := w.wdata + }.elsewhen(!this.ameMcountinhibit.CY.asUInt.asBool && perf =/= 0.U) { + reg := reg.ALL.asUInt + perf + }.otherwise { + reg := reg + } + }).setAddr(AmeMcycle) + ) else None + val minstret = Module(new CSRModule("Minstret") with HasMachineCounterControlBundle with HasRobCommitBundle { when(w.wen) { @@ -347,6 +377,18 @@ trait MachineLevel { self: NewCSR => } }).setAddr(CSRs.minstret) + val ameMinstret = if (enableAme) Some( + Module(new CSRModule("AmeMinstret") with HasAmeFixedPerfBundle { + when(w.wen) { + reg := w.wdata + }.elsewhen(!this.ameMcountinhibit.IR.asUInt.asBool && perf =/= 0.U) { + reg := reg.ALL.asUInt + perf + }.otherwise { + reg := reg + } + }).setAddr(AmeMinstret) + ) else None + val mhpmcounters: Seq[CSRModule[_]] = (3 to 0x1F).map(num => Module(new CSRModule(s"Mhpmcounter$num", new MhpmcounterBundle) with HasMachineCounterControlBundle with HasPerfCounterBundle { val countingInhibit = this.mcountinhibit.asUInt(num) | !countingEn @@ -364,6 +406,22 @@ trait MachineLevel { self: NewCSR => }).setAddr(CSRs.mhpmcounter3 - 3 + num) ) + val ameMhpmcounters: Seq[CSRModule[_]] = if (enableAme) (0 until ameCounterNum).map(idx => + Module(new CSRModule(s"AmeMhpmcounter${idx + 3}", new MhpmcounterBundle) with HasAmePerfCounterBundle { + private val counterBit = idx + 3 + val countingInhibit = this.ameMcountinhibit.asUInt(counterBit) | !countingEn + val counterAdd = this.reg.ALL.asUInt +& perf + when (this.w.wen) { + this.reg := this.w.wdata + }.elsewhen (perf =/= 0.U && !countingInhibit) { + this.reg := counterAdd.tail(1) + }.otherwise { + this.reg := this.reg + } + toMhpmeventOF := !countingInhibit & counterAdd.head(1) + }).setAddr(AmeMhpmcounter3 + idx) + ) else Seq.empty + // JEDEC JEP106 Manufacturer ID: // Bank 17 (16 continuations), Offset 0x6F (111) val mvendorid = Module(new CSRModule("Mvendorid", new MvendoridBundle)) @@ -471,7 +529,14 @@ trait MachineLevel { self: NewCSR => mnstatus, mnscratch, mcontext, - ) ++ mhpmevents ++ mhpmcounters ++ (if (HasBitmapCheck) Seq(mbmc.get) else Seq()) + ) ++ mhpmevents ++ mhpmcounters ++ + ameMcounteren.toSeq ++ + ameMcountinhibit.toSeq ++ + ameMcycle.toSeq ++ + ameMinstret.toSeq ++ + ameMhpmevents ++ + ameMhpmcounters ++ + (if (HasBitmapCheck) Seq(mbmc.get) else Seq()) val machineLevelCSRMap: SeqMap[Int, (CSRAddrWriteBundle[_], UInt)] = SeqMap.from( @@ -831,6 +896,10 @@ trait HasMachineCounterControlBundle { self: CSRModule[_] => val mcountinhibit = IO(Input(new McountinhibitBundle)) } +trait HasAmeMachineCounterControlBundle { self: CSRModule[_] => + val ameMcountinhibit = IO(Input(new McountinhibitBundle)) +} + trait HasRobCommitBundle { self: CSRModule[_] => val robCommit = IO(Input(new RobCommitCSR)) val writeFCSR = IO(Input(Bool())) @@ -849,6 +918,18 @@ trait HasPerfCounterBundle { self: CSRModule[_] => val toMhpmeventOF = IO(Output(Bool())) } +trait HasAmePerfCounterBundle { self: CSRModule[_] => + val countingEn = IO(Input(Bool())) + val perf = IO(Input(UInt(8.W))) + val toMhpmeventOF = IO(Output(Bool())) + val ameMcountinhibit = IO(Input(new McountinhibitBundle)) +} + +trait HasAmeFixedPerfBundle { self: CSRModule[_] => + val perf = IO(Input(UInt(8.W))) + val ameMcountinhibit = IO(Input(new McountinhibitBundle)) +} + trait HasPerfEventBundle { self: CSRModule[_] => val perfEvents = IO(Input(Vec(perfCntNum, UInt(XLEN.W)))) } diff --git a/src/main/scala/xiangshan/backend/fu/NewCSR/NewCSR.scala b/src/main/scala/xiangshan/backend/fu/NewCSR/NewCSR.scala index 682d7a84d18..8684c1595cc 100644 --- a/src/main/scala/xiangshan/backend/fu/NewCSR/NewCSR.scala +++ b/src/main/scala/xiangshan/backend/fu/NewCSR/NewCSR.scala @@ -21,6 +21,7 @@ import xiangshan.backend.fu.PerfCounterIO import xiangshan.backend.fu.util.CSRConst import xiangshan.ExceptionNO._ import xiangshan.backend.trace._ +import cute.CuteParamsKey import scala.collection.immutable.SeqMap @@ -119,6 +120,10 @@ class NewCSR(implicit val p: Parameters) extends Module with IpIeAliasConnect { + // Use defs to avoid trait/class initialization-order hazards when traits consume AME knobs. + def enableAme: Boolean = HasMatrixExtension && p(MatAccKey) == MatAcc.CUTE + def ameCounterNum: Int = if (enableAme) p(CuteParamsKey).AmeCounterNum else 29 + import CSRConfig._ val io = IO(new Bundle { @@ -503,6 +508,15 @@ class NewCSR(implicit val p: Parameters) extends Module permitMod.io.in.xcounteren.mcounteren := mcounteren.rdata permitMod.io.in.xcounteren.hcounteren := hcounteren.rdata permitMod.io.in.xcounteren.scounteren := scounteren.rdata + if (enableAme) { + permitMod.io.in.xcounteren.ameMcounteren := ameMcounteren.get.rdata + permitMod.io.in.xcounteren.ameHcounteren := ameHcounteren.get.rdata + permitMod.io.in.xcounteren.ameScounteren := ameScounteren.get.rdata + } else { + permitMod.io.in.xcounteren.ameMcounteren := 0.U + permitMod.io.in.xcounteren.ameHcounteren := 0.U + permitMod.io.in.xcounteren.ameScounteren := 0.U + } permitMod.io.in.xstateen.mstateen0 := mstateen0.rdata permitMod.io.in.xstateen.mstateen1 := mstateen1.rdata @@ -606,6 +620,15 @@ class NewCSR(implicit val p: Parameters) extends Module m.mcountinhibit := mcountinhibit.regOut case _ => } + mod match { + case m: HasAmeMachineCounterControlBundle => + if (enableAme) { + m.ameMcountinhibit := ameMcountinhibit.get.regOut + } else { + m.ameMcountinhibit := 0.U.asTypeOf(new McountinhibitBundle) + } + case _ => + } mod match { case m: HasExternalInterruptBundle => m.platformIRP := this.platformIRP @@ -733,6 +756,22 @@ class NewCSR(implicit val p: Parameters) extends Module } case _ => } + mod match { + case m: HasAmeMHPMSink => + m.mHPM.cycle := 0.U + m.mHPM.instret := 0.U + val ameHpmCnt = Wire(Vec(perfCntNum, UInt(XLEN.W))) + ameHpmCnt.foreach(_ := 0.U) + if (enableAme) { + m.mHPM.cycle := ameMcycle.get.rdata + m.mHPM.instret := ameMinstret.get.rdata + for (i <- 0 until ameCounterNum) { + ameHpmCnt(i) := ameMhpmcounters(i).rdata + } + } + m.mHPM.hpmcounters := ameHpmCnt + case _ => + } mod match { case m: HasMachineEnvBundle => m.menvcfg := menvcfg.regOut @@ -782,6 +821,49 @@ class NewCSR(implicit val p: Parameters) extends Module m.hcounteren := hcounteren.rdata case _ => } + mod match { + case m: HasAmeMhpmeventOfBundle => + val ameOfVec = Wire(UInt(perfCntNum.W)) + if (enableAme) { + ameOfVec := VecInit(ameMhpmevents.map { event => + val mhpmevent = Wire(new MhpmeventBundle) + mhpmevent := event.rdata + mhpmevent.OF.asBool + }).asUInt + } else { + ameOfVec := 0.U + } + m.ameOfVec := ameOfVec + m.privState := privState + if (enableAme) { + m.ameMcounteren := ameMcounteren.get.rdata + m.ameHcounteren := ameHcounteren.get.rdata + } else { + m.ameMcounteren := 0.U.asTypeOf(new CSRBundles.Counteren) + m.ameHcounteren := 0.U.asTypeOf(new CSRBundles.Counteren) + } + case _ => + } + mod match { + case m: HasAmeFixedPerfBundle => + if (enableAme) { + m.ameMcountinhibit := ameMcountinhibit.get.regOut + } else { + m.ameMcountinhibit := 0.U.asTypeOf(new McountinhibitBundle) + } + val fixedPerf = Mux(mod.addr.U === CSRConst.AmeMcycle.U, io.perf.fixedPerfAme(0).value, io.perf.fixedPerfAme(1).value) + m.perf := Mux(enableAme.B, fixedPerf, 0.U(8.W)) + case _ => + } + mod match { + case m: HasAmePerfCounterBundle => + if (enableAme) { + m.ameMcountinhibit := ameMcountinhibit.get.regOut + } else { + m.ameMcountinhibit := 0.U.asTypeOf(new McountinhibitBundle) + } + case _ => + } mod match { case m: HasStateenBundle => m.fromMstateen0 := mstateen0.regOut @@ -957,6 +1039,19 @@ class NewCSR(implicit val p: Parameters) extends Module val addrInPerfCnt = (wenLegal || ren) && ( (addr >= CSRs.mcycle.U) && (addr <= CSRs.mhpmcounter31.U) || (addr >= CSRs.cycle.U) && (addr <= CSRs.hpmcounter31.U) + ) || (wenLegal || ren) && enableAme.B && ( + (addr === CSRConst.AmeMcycle.U) || + (addr === CSRConst.AmeMinstret.U) || + (addr >= CSRConst.AmeMhpmcounter3.U && addr <= CSRConst.AmeMhpmcounter31.U) || + (addr >= CSRConst.AmeMhpmevent3.U && addr <= CSRConst.AmeMhpmevent31.U) || + (addr === CSRConst.AmeMcountinhibit.U) || + (addr === CSRConst.AmeMcounteren.U) || + (addr === CSRConst.AmeScounteren.U) || + (addr === CSRConst.AmeHcounteren.U) || + (addr === CSRConst.AmeCycle.U) || + (addr === CSRConst.AmeInstret.U) || + (addr >= CSRConst.AmeHpmcounter3.U && addr <= CSRConst.AmeHpmcounter31.U) || + (addr === CSRConst.AmeScountovf.U) ) || ren && ( (addr === CSRs.vstopi.U) || (addr === CSRs.vstopei.U) || @@ -1351,7 +1446,41 @@ class NewCSR(implicit val p: Parameters) extends Module (privState.isModeVU && !mhpmevent.VUINH) } - val lcofiReq = lcofiReqVec.asUInt.orR + val ameLcofiReq = if (enableAme) { + val ameCountingEn = RegInit(0.U.asTypeOf(Vec(ameCounterNum, Bool()))) + val ameOfFromPerfCntVec = Wire(Vec(ameCounterNum, Bool())) + val ameLcofiReqVec = Wire(Vec(ameCounterNum, Bool())) + for (i <- 0 until ameCounterNum) { + ameMhpmcounters(i) match { + case m: HasAmePerfCounterBundle => + m.countingEn := ameCountingEn(i) + m.perf := io.perf.perfEventsAme(i).value + ameOfFromPerfCntVec(i) := m.toMhpmeventOF + case _ => + } + + ameMhpmevents(i) match { + case m: HasOfFromPerfCntBundle => + m.ofFromPerfCnt := ameOfFromPerfCntVec(i) + case _ => + } + + val ameMhpmevent = Wire(new MhpmeventBundle) + ameMhpmevent := ameMhpmevents(i).rdata + ameLcofiReqVec(i) := ameOfFromPerfCntVec(i) && !ameMhpmevent.OF.asBool + + ameCountingEn(i) := (privState.isModeM && !ameMhpmevent.MINH) || + (privState.isModeHS && !ameMhpmevent.SINH) || + (privState.isModeHU && !ameMhpmevent.UINH) || + (privState.isModeVS && !ameMhpmevent.VSINH) || + (privState.isModeVU && !ameMhpmevent.VUINH) + } + ameLcofiReqVec.asUInt.orR + } else { + false.B + } + + val lcofiReq = lcofiReqVec.asUInt.orR || ameLcofiReq mip match { case m: HasLocalInterruptReqBundle => m.lcofiReq := lcofiReq diff --git a/src/main/scala/xiangshan/backend/fu/NewCSR/SupervisorLevel.scala b/src/main/scala/xiangshan/backend/fu/NewCSR/SupervisorLevel.scala index 71baad9d1c2..412741ac2c9 100644 --- a/src/main/scala/xiangshan/backend/fu/NewCSR/SupervisorLevel.scala +++ b/src/main/scala/xiangshan/backend/fu/NewCSR/SupervisorLevel.scala @@ -14,6 +14,7 @@ import xiangshan.backend.fu.NewCSR.CSREvents.TrapEntryHSEventSinkBundle import xiangshan.backend.fu.NewCSR.CSREnumTypeImplicitCast._ import xiangshan.backend.fu.NewCSR.CSRBundleImplicitCast._ import xiangshan.backend.fu.NewCSR.ChiselRecordForField._ +import xiangshan.backend.fu.util.CSRConst._ import scala.collection.immutable.SeqMap @@ -67,6 +68,10 @@ trait SupervisorLevel { self: NewCSR with MachineLevel => val scounteren = Module(new CSRModule("Scounteren", new Counteren)) .setAddr(CSRs.scounteren) + val ameScounteren = if (enableAme) Some( + Module(new CSRModule("AmeScounteren", new Counteren)).setAddr(AmeScounteren) + ) else None + val senvcfg = Module(new CSRModule("Senvcfg", new SEnvCfg)) .setAddr(CSRs.senvcfg) @@ -161,6 +166,19 @@ trait SupervisorLevel { self: NewCSR with MachineLevel => )) }).setAddr(CSRs.scountovf) + val ameScountovf = if (enableAme) Some( + Module(new CSRModule("AmeScountovf", new CSRBundle { + override val len: Int = 32 + val OFVEC = RO(31, 3).withReset(0.U) + }) with HasAmeMhpmeventOfBundle { + regOut.OFVEC := Mux1H(Seq( + privState.isModeM -> ameOfVec, + privState.isModeHS -> (ameMcounteren.HPM.asUInt & ameOfVec), + privState.isModeVS -> (ameMcounteren.HPM.asUInt & ameHcounteren.HPM.asUInt & ameOfVec), + )) + }).setAddr(AmeScountovf) + ) else None + val sstateen0 = Module(new CSRModule("Sstateen0", new Sstateen0Bundle) with HasStateenBundle { // For every bit in an mstateen CSR that is zero (whether read-only zero or set to zero), the same bit // appears as read-only zero in the matching hstateen and sstateen CSRs. For every bit in an hstateen @@ -178,7 +196,8 @@ trait SupervisorLevel { self: NewCSR with MachineLevel => val scontext = Module(new CSRModule("Scontext", new ScontextBundle)).setAddr(CSRs.scontext) - val supervisorLevelCSRMods: Seq[CSRModule[_]] = Seq( + val supervisorLevelCSRMods: Seq[CSRModule[_]] = ( + Seq( sie, stvec, scounteren, @@ -196,7 +215,7 @@ trait SupervisorLevel { self: NewCSR with MachineLevel => sstateen2, sstateen3, scontext, - ) + ) ++ ameScounteren.toSeq ++ ameScountovf.toSeq) val supervisorLevelCSRMap: SeqMap[Int, (CSRAddrWriteBundle[_], UInt)] = SeqMap( CSRs.sstatus -> (mstatus.wAliasSstatus, mstatus.sstatusRdata), @@ -280,3 +299,10 @@ trait HasMhpmeventOfBundle { self: CSRModule[_] => val mcounteren = IO(Input(new Counteren)) val hcounteren = IO(Input(new Counteren)) } + +trait HasAmeMhpmeventOfBundle { self: CSRModule[_] => + val ameOfVec = IO(Input(UInt(perfCntNum.W))) + val privState = IO(Input(new PrivState)) + val ameMcounteren = IO(Input(new Counteren)) + val ameHcounteren = IO(Input(new Counteren)) +} diff --git a/src/main/scala/xiangshan/backend/fu/NewCSR/Unprivileged.scala b/src/main/scala/xiangshan/backend/fu/NewCSR/Unprivileged.scala index d7d525e2ad7..8a4ec5888de 100644 --- a/src/main/scala/xiangshan/backend/fu/NewCSR/Unprivileged.scala +++ b/src/main/scala/xiangshan/backend/fu/NewCSR/Unprivileged.scala @@ -12,6 +12,7 @@ import xiangshan.backend.fu.NewCSR.CSRConfig._ import xiangshan.backend.fu.fpu.Bundles.{Fflags, Frm} import xiangshan.backend.fu.NewCSR.CSREnumTypeImplicitCast._ import xiangshan.XSCoreParameters +import xiangshan.backend.fu.util.CSRConst._ import scala.collection.immutable.SeqMap @@ -317,6 +318,45 @@ trait Unprivileged { self: NewCSR with MachineLevel with SupervisorLevel => }).setAddr(CSRs.cycle + num) ) + val ameCycle = if (enableAme) Some( + Module(new CSRModule("AmeCycle", new CSRBundle { + val cycle = RO(63, 0) + }) with HasAmeMHPMSink with HasDebugStopBundle { + when(unprivCountUpdate) { + reg := mHPM.cycle + }.otherwise { + reg := reg + } + regOut := Mux(debugModeStopCount, reg.asUInt, mHPM.cycle) + }).setAddr(AmeCycle) + ) else None + + val ameInstret = if (enableAme) Some( + Module(new CSRModule("AmeInstret", new CSRBundle { + val instret = RO(63, 0) + }) with HasAmeMHPMSink with HasDebugStopBundle { + when(unprivCountUpdate) { + reg := mHPM.instret + }.otherwise { + reg := reg + } + regOut := Mux(debugModeStopCount, reg.asUInt, mHPM.instret) + }).setAddr(AmeInstret) + ) else None + + val ameHpmcounters: Seq[CSRModule[_]] = if (enableAme) (0 until ameCounterNum).map(idx => + Module(new CSRModule(s"AmeHpmcounter${idx + 3}", new CSRBundle { + val hpmcounter = RO(63, 0).withReset(0.U) + }) with HasAmeMHPMSink with HasDebugStopBundle { + when(unprivCountUpdate) { + reg := mHPM.hpmcounters(idx) + }.otherwise { + reg := reg + } + regOut := Mux(debugModeStopCount, reg.asUInt, mHPM.hpmcounters(idx)) + }).setAddr(AmeHpmcounter3 + idx) + ) else Seq.empty + val unprivilegedCSRMap: SeqMap[Int, (CSRAddrWriteBundle[_], UInt)] = SeqMap( CSRs.fflags -> (fcsr.wAliasFflags -> fcsr.fflagsRdata), CSRs.frm -> (fcsr.wAliasFfm -> fcsr.frmRdata), @@ -345,7 +385,11 @@ trait Unprivileged { self: NewCSR with MachineLevel with SupervisorLevel => CSRs.cycle -> (cycle.w -> cycle.rdata), CSRs.time -> (time.w -> time.rdata), CSRs.instret -> (instret.w -> instret.rdata), - ) ++ hpmcounters.map(counter => (counter.addr -> (counter.w -> counter.rdata))) + ) ++ + hpmcounters.map(counter => counter.addr -> (counter.w -> counter.rdata)) ++ + ameCycle.toSeq.map(c => c.addr -> (c.w -> c.rdata)) ++ + ameInstret.toSeq.map(c => c.addr -> (c.w -> c.rdata)) ++ + ameHpmcounters.map(counter => counter.addr -> (counter.w -> counter.rdata)) val unprivilegedCSRMods: Seq[CSRModule[_]] = Seq( fcsr, @@ -366,7 +410,7 @@ trait Unprivileged { self: NewCSR with MachineLevel with SupervisorLevel => cycle, time, instret, - ) ++ hpmcounters + ) ++ hpmcounters ++ ameCycle.toSeq ++ ameInstret.toSeq ++ ameHpmcounters val unprivilegedCSROutMap: SeqMap[Int, UInt] = SeqMap( CSRs.fflags -> fcsr.fflags.asUInt, @@ -396,7 +440,11 @@ trait Unprivileged { self: NewCSR with MachineLevel with SupervisorLevel => CSRs.cycle -> cycle.rdata, CSRs.time -> time.rdata, CSRs.instret -> instret.rdata, - ) ++ hpmcounters.map(counter => (counter.addr -> counter.rdata)) + ) ++ + hpmcounters.map(counter => counter.addr -> counter.rdata) ++ + ameCycle.toSeq.map(c => c.addr -> c.rdata) ++ + ameInstret.toSeq.map(c => c.addr -> c.rdata) ++ + ameHpmcounters.map(counter => counter.addr -> counter.rdata) } class CSRVTypeBundle extends CSRBundle { @@ -438,8 +486,16 @@ trait HasMHPMSink { self: CSRModule[_] => val htimedelta = IO(Input(UInt(64.W))) } +trait HasAmeMHPMSink { self: CSRModule[_] => + val mHPM = IO(Input(new Bundle { + val cycle = UInt(64.W) + val instret = UInt(64.W) + val hpmcounters = Vec(perfCntNum, UInt(XLEN.W)) + })) +} + trait HasDebugStopBundle { self: CSRModule[_] => val debugModeStopCount = IO(Input(Bool())) val debugModeStopTime = IO(Input(Bool())) val unprivCountUpdate = IO(Input(Bool())) -} \ No newline at end of file +} diff --git a/src/main/scala/xiangshan/backend/fu/util/CSRConst.scala b/src/main/scala/xiangshan/backend/fu/util/CSRConst.scala index bb758858e4b..0e477a0f8de 100644 --- a/src/main/scala/xiangshan/backend/fu/util/CSRConst.scala +++ b/src/main/scala/xiangshan/backend/fu/util/CSRConst.scala @@ -37,6 +37,23 @@ trait HasCSRConst { // Machine level Bitmap Check(Custom Read/Write) val Mbmc = 0xBC2 + // AME (CUTE PMU) CSR windows + val AmeScounteren = 0x5E6 + val AmeHcounteren = 0x6C6 + val AmeMcounteren = 0x7E8 + val AmeMcountinhibit = 0x7E9 + val AmeMhpmevent3 = 0xBC3 + val AmeMhpmevent31 = 0xBDF + val AmeMcycle = 0xBE0 + val AmeMinstret = 0xBE2 + val AmeMhpmcounter3 = 0xBE3 + val AmeMhpmcounter31 = 0xBFF + val AmeCycle = 0xCE0 + val AmeInstret = 0xCE2 + val AmeHpmcounter3 = 0xCE3 + val AmeHpmcounter31 = 0xCFF + val AmeScountovf = 0xDE0 + def privEcall = 0x000.U def privEbreak = 0x001.U def privMNret = 0x702.U