From 7a62d60ac2eaf3b47a23ec60ae8278ea2ce1c7e8 Mon Sep 17 00:00:00 2001 From: Jacob Tilger Date: Tue, 30 Jan 2024 20:58:34 +0100 Subject: [PATCH 01/19] added counter csr-addresses to constants --- src/main/scala/vexriscv/Riscv.scala | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/scala/vexriscv/Riscv.scala b/src/main/scala/vexriscv/Riscv.scala index 52ccf36e..89e3b5ec 100644 --- a/src/main/scala/vexriscv/Riscv.scala +++ b/src/main/scala/vexriscv/Riscv.scala @@ -216,6 +216,9 @@ object Riscv{ def MCYCLEH = 0xB80 // MRW Upper 32 bits of mcycle, RV32I only. def MINSTRETH = 0xB82 // MRW Upper 32 bits of minstret, RV32I only. val MCOUNTEREN = 0x306 + val MCOUNTER = 0xB03 // MRW Base address for mhpmcounterX. + val MCOUNTERH = 0xB83 // MRW Base address for mhpmcounterXh, RV32I only. + val MEVENT = 0x323 // MRW Base address for mhpmeventX. val SSTATUS = 0x100 val SIE = 0x104 @@ -234,6 +237,8 @@ object Riscv{ def UTIMEH = 0xC81 def UINSTRET = 0xC02 // UR Machine instructions-retired counter. def UINSTRETH = 0xC82 // UR Upper 32 bits of minstret, RV32I only. + val UCOUNTER = 0xC03 // UR Base address for hpmcounter. + val UCOUNTERH = 0xC83 // UR Base address for hpmcounterXh, RV32I only. val FFLAGS = 0x1 val FRM = 0x2 From 248ad248f47df0cea6c4adce30052a3d633e00dd Mon Sep 17 00:00:00 2001 From: Jacob Tilger Date: Wed, 31 Jan 2024 11:56:07 +0100 Subject: [PATCH 02/19] extracted existing counters to new plugin --- .../scala/vexriscv/plugin/CounterPlugin.scala | 101 ++++++++++++++++++ .../scala/vexriscv/plugin/CsrPlugin.scala | 94 +--------------- 2 files changed, 104 insertions(+), 91 deletions(-) create mode 100644 src/main/scala/vexriscv/plugin/CounterPlugin.scala diff --git a/src/main/scala/vexriscv/plugin/CounterPlugin.scala b/src/main/scala/vexriscv/plugin/CounterPlugin.scala new file mode 100644 index 00000000..d2038e70 --- /dev/null +++ b/src/main/scala/vexriscv/plugin/CounterPlugin.scala @@ -0,0 +1,101 @@ +package vexriscv.plugin + +import spinal.core._ + +import vexriscv.VexRiscv +import vexriscv.Riscv.CSR._ + +import scala.collection.mutable._ + +trait CounterService{ + def getCondition(eventId : BigInt) : Bool +} + +case class CounterPluginConfig( + NumOfCounters : Byte = 29, + + mcycleAccess : CsrAccess = CsrAccess.READ_WRITE, + ucycleAccess : CsrAccess = CsrAccess.READ_ONLY, + + minstretAccess : CsrAccess = CsrAccess.READ_WRITE, + uinstretAccess : CsrAccess = CsrAccess.READ_ONLY, + + mcounterenAccess : CsrAccess = CsrAccess.READ_WRITE, + scounterenAccess : CsrAccess = CsrAccess.READ_WRITE, + + mcounterAccess : CsrAccess = CsrAccess.READ_WRITE, + ucounterAccess : CsrAccess = CsrAccess.READ_ONLY, + + // management + meventAccess : CsrAccess = CsrAccess.READ_WRITE, + mcounterinhibitAccess : CsrAccess = CsrAccess.READ_WRITE + ) { + assert(!ucycleAccess.canWrite) +} + +class CounterPlugin(config : CounterPluginConfig) extends Plugin[VexRiscv] with CounterService { + import config._ + + def xlen = 32 + + assert(NumOfCounters <= 29, "Cannot create more than 29 custom counters") + assert(NumOfCounters >= 0, "Cannot create less than 0 custom counters") + +// counters : Array[Reg] = null +// event : Array[Reg] = null + +// mcouen : Reg = null +// scouen : Reg = null + +// inhibit : Reg = null + + val eventType : Map[BigInt, Bool] = new HashMap() + + implicit class CsrAccessPimper(csrAccess : CsrAccess){ + import CsrAccess._ + def apply(csrService : CsrInterface, csrAddress : Int, thats : (Int, Data)*) : Unit = { + if(csrAccess == `WRITE_ONLY` || csrAccess == `READ_WRITE`) for(that <- thats) csrService.w(csrAddress,that._1, that._2) + if(csrAccess == `READ_ONLY` || csrAccess == `READ_WRITE`) for(that <- thats) csrService.r(csrAddress,that._1, that._2) + } + def apply(csrService : CsrInterface, csrAddress : Int, that : Data) : Unit = { + if(csrAccess == `WRITE_ONLY` || csrAccess == `READ_WRITE`) csrService.w(csrAddress, 0, that) + if(csrAccess == `READ_ONLY` || csrAccess == `READ_WRITE`) csrService.r(csrAddress, 0, that) + } + } + + override def getCondition(eventId : BigInt) : Bool = { + if (!eventType.contains(eventId)) { + eventType(eventId) = new Bool() + } + + eventType(eventId) + } + + override def build(pipeline : VexRiscv) : Unit = { + import pipeline._ + import pipeline.config._ + + pipeline plug new Area{ + val csrService = pipeline.service(classOf[CsrInterface]) + + // cycle + val cycle = Reg(UInt(64 bits)) init(0) + cycle := cycle + 1 + ucycleAccess(csrService, UCYCLE, cycle(31 downto 0)) + ucycleAccess(csrService, UCYCLEH, cycle(63 downto 32)) + mcycleAccess(csrService, MCYCLE, cycle(31 downto 0)) + mcycleAccess(csrService, MCYCLEH, cycle(63 downto 32)) + // instret + val instret = Reg(UInt(64 bits)) init(0) + when(pipeline.stages.last.arbitration.isFiring) { + instret := instret + 1 + } + uinstretAccess(csrService, UINSTRET, instret(31 downto 0)) + uinstretAccess(csrService, UINSTRETH, instret(63 downto 32)) + minstretAccess(csrService, MINSTRET, instret(31 downto 0)) + minstretAccess(csrService, MINSTRETH, instret(63 downto 32)) + + // TODO counters + } + } +} diff --git a/src/main/scala/vexriscv/plugin/CsrPlugin.scala b/src/main/scala/vexriscv/plugin/CsrPlugin.scala index db63107e..2cff78d4 100644 --- a/src/main/scala/vexriscv/plugin/CsrPlugin.scala +++ b/src/main/scala/vexriscv/plugin/CsrPlugin.scala @@ -51,10 +51,6 @@ case class CsrPluginConfig( mscratchGen : Boolean, mcauseAccess : CsrAccess, mbadaddrAccess : CsrAccess, - mcycleAccess : CsrAccess, - minstretAccess : CsrAccess, - ucycleAccess : CsrAccess, - uinstretAccess : CsrAccess = CsrAccess.NONE, wfiGenAsWait : Boolean, ecallGen : Boolean, xtvecModeGen : Boolean = false, @@ -68,8 +64,6 @@ case class CsrPluginConfig( sepcAccess : CsrAccess = CsrAccess.NONE, scauseAccess : CsrAccess = CsrAccess.NONE, sbadaddrAccess : CsrAccess = CsrAccess.NONE, - scycleAccess : CsrAccess = CsrAccess.NONE, - sinstretAccess : CsrAccess = CsrAccess.NONE, satpAccess : CsrAccess = CsrAccess.NONE, utimeAccess :CsrAccess = CsrAccess.NONE, medelegAccess : CsrAccess = CsrAccess.NONE, @@ -85,7 +79,6 @@ case class CsrPluginConfig( var withPrivilegedDebug : Boolean = false, //For the official RISC-V debug spec implementation var debugTriggers : Int = 2 ){ - assert(!ucycleAccess.canWrite) def privilegeGen = userGen || supervisorGen || withPrivilegedDebug def noException = this.copy(ecallGen = false, ebreakGen = false, catchIllegalAccess = false) def noExceptionButEcall = this.copy(ecallGen = true, ebreakGen = false, catchIllegalAccess = false) @@ -111,9 +104,6 @@ object CsrPluginConfig{ mscratchGen = true, mcauseAccess = CsrAccess.READ_ONLY, mbadaddrAccess = CsrAccess.READ_ONLY, - mcycleAccess = CsrAccess.NONE, - minstretAccess = CsrAccess.NONE, - ucycleAccess = CsrAccess.NONE, wfiGenAsWait = true, ecallGen = true, xtvecModeGen = false, @@ -127,8 +117,6 @@ object CsrPluginConfig{ sepcAccess = CsrAccess.READ_WRITE, scauseAccess = CsrAccess.READ_WRITE, sbadaddrAccess = CsrAccess.READ_WRITE, - scycleAccess = CsrAccess.NONE, - sinstretAccess = CsrAccess.NONE, satpAccess = CsrAccess.NONE, medelegAccess = CsrAccess.READ_WRITE, //Could have been WRITE_ONLY :( midelegAccess = CsrAccess.READ_WRITE, //Could have been WRITE_ONLY :( @@ -150,10 +138,6 @@ object CsrPluginConfig{ mscratchGen = true, mcauseAccess = CsrAccess.READ_ONLY, mbadaddrAccess = CsrAccess.READ_ONLY, - mcycleAccess = CsrAccess.NONE, - minstretAccess = CsrAccess.NONE, - ucycleAccess = CsrAccess.NONE, - uinstretAccess = CsrAccess.NONE, wfiGenAsWait = true, ecallGen = true, xtvecModeGen = false, @@ -167,8 +151,6 @@ object CsrPluginConfig{ sepcAccess = CsrAccess.READ_WRITE, scauseAccess = CsrAccess.READ_WRITE, sbadaddrAccess = CsrAccess.READ_WRITE, - scycleAccess = CsrAccess.NONE, - sinstretAccess = CsrAccess.NONE, satpAccess = CsrAccess.NONE, //Implemented into the MMU plugin medelegAccess = CsrAccess.WRITE_ONLY, midelegAccess = CsrAccess.WRITE_ONLY, @@ -191,10 +173,6 @@ object CsrPluginConfig{ mscratchGen = true, mcauseAccess = CsrAccess.READ_WRITE, mbadaddrAccess = CsrAccess.READ_WRITE, - mcycleAccess = CsrAccess.READ_WRITE, - minstretAccess = CsrAccess.READ_WRITE, - ucycleAccess = CsrAccess.READ_ONLY, - uinstretAccess = CsrAccess.READ_ONLY, wfiGenAsWait = true, ecallGen = true, xtvecModeGen = false, @@ -208,8 +186,6 @@ object CsrPluginConfig{ sepcAccess = CsrAccess.READ_WRITE, scauseAccess = CsrAccess.READ_WRITE, sbadaddrAccess = CsrAccess.READ_WRITE, - scycleAccess = CsrAccess.READ_WRITE, - sinstretAccess = CsrAccess.READ_WRITE, satpAccess = CsrAccess.NONE, //Implemented into the MMU plugin medelegAccess = CsrAccess.READ_WRITE, midelegAccess = CsrAccess.READ_WRITE, @@ -231,12 +207,8 @@ object CsrPluginConfig{ mscratchGen = true, mcauseAccess = CsrAccess.READ_WRITE, mbadaddrAccess = CsrAccess.READ_WRITE, - mcycleAccess = CsrAccess.READ_WRITE, - minstretAccess = CsrAccess.READ_WRITE, ecallGen = true, - wfiGenAsWait = true, - ucycleAccess = CsrAccess.READ_ONLY, - uinstretAccess = CsrAccess.READ_ONLY + wfiGenAsWait = true ) def all2(mtvecInit : BigInt) : CsrPluginConfig = CsrPluginConfig( @@ -253,20 +225,14 @@ object CsrPluginConfig{ mscratchGen = true, mcauseAccess = CsrAccess.READ_WRITE, mbadaddrAccess = CsrAccess.READ_WRITE, - mcycleAccess = CsrAccess.READ_WRITE, - minstretAccess = CsrAccess.READ_WRITE, ecallGen = true, wfiGenAsWait = true, - ucycleAccess = CsrAccess.READ_ONLY, - uinstretAccess = CsrAccess.READ_ONLY, supervisorGen = true, sscratchGen = true, stvecAccess = CsrAccess.READ_WRITE, sepcAccess = CsrAccess.READ_WRITE, scauseAccess = CsrAccess.READ_WRITE, sbadaddrAccess = CsrAccess.READ_WRITE, - scycleAccess = CsrAccess.READ_WRITE, - sinstretAccess = CsrAccess.READ_WRITE, satpAccess = CsrAccess.READ_WRITE, medelegAccess = CsrAccess.READ_WRITE, midelegAccess = CsrAccess.READ_WRITE @@ -286,12 +252,8 @@ object CsrPluginConfig{ mscratchGen = false, mcauseAccess = CsrAccess.READ_ONLY, mbadaddrAccess = CsrAccess.READ_ONLY, - mcycleAccess = CsrAccess.NONE, - minstretAccess = CsrAccess.NONE, ecallGen = false, - wfiGenAsWait = false, - ucycleAccess = CsrAccess.NONE, - uinstretAccess = CsrAccess.NONE + wfiGenAsWait = false ) def smallest(mtvecInit : BigInt) = CsrPluginConfig( @@ -308,12 +270,8 @@ object CsrPluginConfig{ mscratchGen = false, mcauseAccess = CsrAccess.READ_ONLY, mbadaddrAccess = CsrAccess.NONE, - mcycleAccess = CsrAccess.NONE, - minstretAccess = CsrAccess.NONE, ecallGen = false, - wfiGenAsWait = false, - ucycleAccess = CsrAccess.NONE, - uinstretAccess = CsrAccess.NONE + wfiGenAsWait = false ) def secure(mtvecInit : BigInt) = CsrPluginConfig( @@ -330,10 +288,6 @@ object CsrPluginConfig{ mscratchGen = true, mcauseAccess = CsrAccess.READ_WRITE, mbadaddrAccess = CsrAccess.READ_WRITE, - mcycleAccess = CsrAccess.READ_WRITE, - minstretAccess = CsrAccess.READ_WRITE, - ucycleAccess = CsrAccess.READ_ONLY, - uinstretAccess = CsrAccess.READ_ONLY, wfiGenAsWait = true, ecallGen = true, userGen = true, @@ -434,7 +388,6 @@ trait CsrInterface{ def inDebugMode() : Bool } - trait IContextSwitching{ def isContextSwitching : Bool } @@ -998,9 +951,6 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep val exceptionCode = Reg(UInt(trapCodeWidth bits)) } val mtval = Reg(UInt(xlen bits)) - val mcycle = Reg(UInt(64 bits)) init(0) - val minstret = Reg(UInt(64 bits)) init(0) - val medeleg = supervisorGen generate new Area { val IAM, IAF, II, BP, LAM, LAF, SAM, SAF, EU, ES, IPF, LPF, SPF = RegInit(False) @@ -1044,10 +994,6 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep if(mscratchGen) READ_WRITE(CSR.MSCRATCH, mscratch) mcauseAccess(CSR.MCAUSE, xlen-1 -> mcause.interrupt, 0 -> mcause.exceptionCode) mbadaddrAccess(CSR.MBADADDR, mtval) - mcycleAccess(CSR.MCYCLE, mcycle(31 downto 0)) - mcycleAccess(CSR.MCYCLEH, mcycle(63 downto 32)) - minstretAccess(CSR.MINSTRET, minstret(31 downto 0)) - minstretAccess(CSR.MINSTRETH, minstret(63 downto 32)) if(supervisorGen) { for((id, enable) <- medeleg.mapping) medelegAccess(CSR.MEDELEG, id -> enable) @@ -1055,38 +1001,11 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep } //User CSR - ucycleAccess(CSR.UCYCLE, mcycle(31 downto 0)) - ucycleAccess(CSR.UCYCLEH, mcycle(63 downto 32)) - uinstretAccess(CSR.UINSTRET, minstret(31 downto 0)) - uinstretAccess(CSR.UINSTRETH, minstret(63 downto 32)) - if(utimeAccess != CsrAccess.NONE) { utimeAccess(CSR.UTIME, utime(31 downto 0)) utimeAccess(CSR.UTIMEH, utime(63 downto 32)) } - class Xcounteren(csrId : Int) extends Area{ - val IR,TM,CY = RegInit(True) //For backward compatibility - if(ucycleAccess != CsrAccess.NONE) rw(csrId, 0 -> CY) - if(utimeAccess != CsrAccess.NONE) rw(csrId, 1 -> TM) - if(uinstretAccess != CsrAccess.NONE) rw(csrId, 2 -> IR) - } - def xcounterChecks(access : CsrAccess, csrId : Int, enable : Xcounteren => Bool) = { - if(access != CsrAccess.NONE) during(csrId){ - if(userGen) when(privilege < 3 && !enable(mcounteren)){ forceFailCsr() } - if(supervisorGen) when(privilege < 1 && !enable(scounteren)){ forceFailCsr() } - } - } - - val mcounteren = userGen generate new Xcounteren(CSR.MCOUNTEREN) - val scounteren = supervisorGen generate new Xcounteren(CSR.SCOUNTEREN) - xcounterChecks(ucycleAccess , CSR.UCYCLE , _.CY) - xcounterChecks(ucycleAccess , CSR.UCYCLEH , _.CY) - xcounterChecks(utimeAccess , CSR.UTIME , _.TM) - xcounterChecks(utimeAccess , CSR.UTIMEH , _.TM) - xcounterChecks(uinstretAccess, CSR.UINSTRET , _.IR) - xcounterChecks(uinstretAccess, CSR.UINSTRETH, _.IR) - pipeline(MPP) := mstatus.MPP } @@ -1172,13 +1091,6 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep val beforeLastStage = pipeline.stages(pipeline.stages.size-2) val stagesFromExecute = pipeline.stages.dropWhile(_ != execute) - //Manage counters - mcycle := mcycle + (if(withPrivilegedDebug) U(!debugMode || !debug.dcsr.stopcount) else U(1)) - when(lastStage.arbitration.isFiring) { - minstret := minstret + 1 - } - - if(supervisorGen) { addInterrupt(sip.STIP && sie.STIE, id = 5, privilege = 1, delegators = List(Delegator(mideleg.ST, 3))) addInterrupt(sip.SSIP && sie.SSIE, id = 1, privilege = 1, delegators = List(Delegator(mideleg.SS, 3))) From 20f638ea168769491c7a6699f2f36b211c1fd233 Mon Sep 17 00:00:00 2001 From: Jacob Tilger Date: Wed, 31 Jan 2024 12:03:25 +0100 Subject: [PATCH 03/19] removed counter config from demos --- src/main/scala/vexriscv/demo/Briey.scala | 6 +----- src/main/scala/vexriscv/demo/VexRiscvAhbLite3.scala | 6 +----- .../scala/vexriscv/demo/VexRiscvAvalonForSim.scala | 6 +----- .../demo/VexRiscvAvalonWithIntegratedJtag.scala | 6 +----- .../vexriscv/demo/VexRiscvAxi4WithIntegratedJtag.scala | 6 +----- .../scala/vexriscv/demo/smp/VexRiscvSmpCluster.scala | 9 +-------- src/test/scala/vexriscv/experimental/GenMicro.scala | 10 ++-------- 7 files changed, 8 insertions(+), 41 deletions(-) diff --git a/src/main/scala/vexriscv/demo/Briey.scala b/src/main/scala/vexriscv/demo/Briey.scala index 32e6d62e..9d83b7c1 100644 --- a/src/main/scala/vexriscv/demo/Briey.scala +++ b/src/main/scala/vexriscv/demo/Briey.scala @@ -146,12 +146,8 @@ object BrieyConfig{ mscratchGen = false, mcauseAccess = CsrAccess.READ_ONLY, mbadaddrAccess = CsrAccess.READ_ONLY, - mcycleAccess = CsrAccess.NONE, - minstretAccess = CsrAccess.NONE, ecallGen = false, - wfiGenAsWait = false, - ucycleAccess = CsrAccess.NONE, - uinstretAccess = CsrAccess.NONE + wfiGenAsWait = false ) ), new YamlPlugin("cpu0.yaml") diff --git a/src/main/scala/vexriscv/demo/VexRiscvAhbLite3.scala b/src/main/scala/vexriscv/demo/VexRiscvAhbLite3.scala index f817fb3b..1959beef 100644 --- a/src/main/scala/vexriscv/demo/VexRiscvAhbLite3.scala +++ b/src/main/scala/vexriscv/demo/VexRiscvAhbLite3.scala @@ -122,12 +122,8 @@ object VexRiscvAhbLite3{ mscratchGen = false, mcauseAccess = CsrAccess.READ_ONLY, mbadaddrAccess = CsrAccess.READ_ONLY, - mcycleAccess = CsrAccess.NONE, - minstretAccess = CsrAccess.NONE, ecallGen = false, - wfiGenAsWait = false, - ucycleAccess = CsrAccess.NONE, - uinstretAccess = CsrAccess.NONE + wfiGenAsWait = false ) ), new YamlPlugin("cpu0.yaml") diff --git a/src/main/scala/vexriscv/demo/VexRiscvAvalonForSim.scala b/src/main/scala/vexriscv/demo/VexRiscvAvalonForSim.scala index b2c3f69c..f4f3dfc0 100644 --- a/src/main/scala/vexriscv/demo/VexRiscvAvalonForSim.scala +++ b/src/main/scala/vexriscv/demo/VexRiscvAvalonForSim.scala @@ -120,12 +120,8 @@ object VexRiscvAvalonForSim{ mscratchGen = false, mcauseAccess = CsrAccess.READ_ONLY, mbadaddrAccess = CsrAccess.READ_ONLY, - mcycleAccess = CsrAccess.NONE, - minstretAccess = CsrAccess.NONE, ecallGen = false, - wfiGenAsWait = false, - ucycleAccess = CsrAccess.NONE, - uinstretAccess = CsrAccess.NONE + wfiGenAsWait = false ) ), new YamlPlugin("cpu0.yaml") diff --git a/src/main/scala/vexriscv/demo/VexRiscvAvalonWithIntegratedJtag.scala b/src/main/scala/vexriscv/demo/VexRiscvAvalonWithIntegratedJtag.scala index 063d945a..c3911434 100644 --- a/src/main/scala/vexriscv/demo/VexRiscvAvalonWithIntegratedJtag.scala +++ b/src/main/scala/vexriscv/demo/VexRiscvAvalonWithIntegratedJtag.scala @@ -117,12 +117,8 @@ object VexRiscvAvalonWithIntegratedJtag{ mscratchGen = false, mcauseAccess = CsrAccess.READ_ONLY, mbadaddrAccess = CsrAccess.READ_ONLY, - mcycleAccess = CsrAccess.NONE, - minstretAccess = CsrAccess.NONE, ecallGen = false, - wfiGenAsWait = false, - ucycleAccess = CsrAccess.NONE, - uinstretAccess = CsrAccess.NONE + wfiGenAsWait = false ) ), new YamlPlugin("cpu0.yaml") diff --git a/src/main/scala/vexriscv/demo/VexRiscvAxi4WithIntegratedJtag.scala b/src/main/scala/vexriscv/demo/VexRiscvAxi4WithIntegratedJtag.scala index 67556e94..2409424f 100644 --- a/src/main/scala/vexriscv/demo/VexRiscvAxi4WithIntegratedJtag.scala +++ b/src/main/scala/vexriscv/demo/VexRiscvAxi4WithIntegratedJtag.scala @@ -118,12 +118,8 @@ object VexRiscvAxi4WithIntegratedJtag{ mscratchGen = false, mcauseAccess = CsrAccess.READ_ONLY, mbadaddrAccess = CsrAccess.READ_ONLY, - mcycleAccess = CsrAccess.NONE, - minstretAccess = CsrAccess.NONE, ecallGen = false, - wfiGenAsWait = false, - ucycleAccess = CsrAccess.NONE, - uinstretAccess = CsrAccess.NONE + wfiGenAsWait = false ) ), new YamlPlugin("cpu0.yaml") diff --git a/src/main/scala/vexriscv/demo/smp/VexRiscvSmpCluster.scala b/src/main/scala/vexriscv/demo/smp/VexRiscvSmpCluster.scala index 6fffb6a5..e37ece7d 100644 --- a/src/main/scala/vexriscv/demo/smp/VexRiscvSmpCluster.scala +++ b/src/main/scala/vexriscv/demo/smp/VexRiscvSmpCluster.scala @@ -208,11 +208,7 @@ object VexRiscvSmpClusterGen { if(csrFull){ c = c.copy( mcauseAccess = CsrAccess.READ_WRITE, - mbadaddrAccess = CsrAccess.READ_WRITE, - ucycleAccess = CsrAccess.READ_ONLY, - uinstretAccess = CsrAccess.READ_ONLY, - mcycleAccess = CsrAccess.READ_WRITE, - minstretAccess = CsrAccess.READ_WRITE + mbadaddrAccess = CsrAccess.READ_WRITE ) } c @@ -232,13 +228,10 @@ object VexRiscvSmpClusterGen { mscratchGen = forceMscratch, mcauseAccess = CsrAccess.READ_ONLY, mbadaddrAccess = CsrAccess.READ_ONLY, - mcycleAccess = CsrAccess.NONE, - minstretAccess = CsrAccess.NONE, ecallGen = true, ebreakGen = true, wfiGenAsWait = false, wfiGenAsNop = true, - ucycleAccess = CsrAccess.NONE, withPrivilegedDebug = privilegedDebug ) } diff --git a/src/test/scala/vexriscv/experimental/GenMicro.scala b/src/test/scala/vexriscv/experimental/GenMicro.scala index 90666a7a..2b8968d2 100644 --- a/src/test/scala/vexriscv/experimental/GenMicro.scala +++ b/src/test/scala/vexriscv/experimental/GenMicro.scala @@ -93,13 +93,10 @@ object GenMicro extends App{ mscratchGen = false, mcauseAccess = CsrAccess.READ_ONLY, mbadaddrAccess = CsrAccess.NONE, - mcycleAccess = CsrAccess.NONE, - minstretAccess = CsrAccess.NONE, ecallGen = false, ebreakGen = false, wfiGenAsWait = false, wfiGenAsNop = false, - ucycleAccess = CsrAccess.NONE, noCsrAlu = true ) else CsrPluginConfig( catchIllegalAccess = false, @@ -115,13 +112,10 @@ object GenMicro extends App{ mscratchGen = true, mcauseAccess = CsrAccess.READ_ONLY, mbadaddrAccess = CsrAccess.READ_ONLY, - mcycleAccess = CsrAccess.NONE, - minstretAccess = CsrAccess.NONE, ecallGen = true, ebreakGen = true, wfiGenAsWait = false, - wfiGenAsNop = true, - ucycleAccess = CsrAccess.NONE + wfiGenAsNop = true ) ))) ) @@ -159,4 +153,4 @@ object GenMicroSynthesis { Bench(rtls, targets, "/eda/tmp/") } -} \ No newline at end of file +} From d9d841d748b32f58a567fa47ca970b43336ffd6b Mon Sep 17 00:00:00 2001 From: Jacob Tilger Date: Wed, 31 Jan 2024 13:02:39 +0100 Subject: [PATCH 04/19] exposed debug-state to other plugins --- .../scala/vexriscv/plugin/CsrPlugin.scala | 45 ++++++++++++++++++- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/src/main/scala/vexriscv/plugin/CsrPlugin.scala b/src/main/scala/vexriscv/plugin/CsrPlugin.scala index 2cff78d4..867a4c9a 100644 --- a/src/main/scala/vexriscv/plugin/CsrPlugin.scala +++ b/src/main/scala/vexriscv/plugin/CsrPlugin.scala @@ -334,7 +334,7 @@ case class CsrMapping() extends Area with CsrInterface { override def allowCsr() = allowCsrSignal := True override def isHazardFree() = hazardFree override def forceFailCsr() = doForceFailCsr := True - override def inDebugMode(): Bool = ??? + override def inDebugMode() : Bool = ??? } @@ -388,6 +388,29 @@ trait CsrInterface{ def inDebugMode() : Bool } +trait DebugService{ + case class DebugState(xlen : Int) extends Bundle{ + val dpc = UInt(xlen bits) + val dcsr = new Bundle{ + val prv = UInt(2 bits) + val step = Bool + val nmip = Bool + val mprven = Bool + val cause = UInt(3 bits) + val stoptime = Bool + val stopcount = Bool + val stepie = Bool + val ebreaku = Bool + val ebreaks = Bool + val ebreakm = Bool + val xdebugver = UInt(4 bits) + } + } + + def inDebugMode() : Bool + def debugState() : DebugState +} + trait IContextSwitching{ def isContextSwitching : Bool } @@ -395,7 +418,7 @@ trait IWake{ def askWake() : Unit } -class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with ExceptionService with PrivilegeService with InterruptionInhibitor with ExceptionInhibitor with IContextSwitching with CsrInterface with IWake with VexRiscvRegressionArg { +class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with ExceptionService with PrivilegeService with DebugService with InterruptionInhibitor with ExceptionInhibitor with IContextSwitching with CsrInterface with IWake with VexRiscvRegressionArg { import config._ import CsrAccess._ @@ -434,6 +457,7 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep var debugBus : DebugHartBus = null var debugMode : Bool = null + var debugStateB : DebugState = null var injectionPort : Stream[Bits] = null override def askWake(): Unit = thirdPartyWake := True @@ -441,6 +465,7 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep override def isContextSwitching = contextSwitching override def inDebugMode(): Bool = if(withPrivilegedDebug) debugMode else False + override def debugState(): DebugState = debugStateB object EnvCtrlEnum extends SpinalEnum(binarySequential){ val NONE, XRET = newElement() @@ -912,6 +937,22 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep } }) + // make debug state accessible + debugStateB = new DebugState(xlen) + debugStateB.dcsr.xdebugver := debug.dcsr.xdebugver + debugStateB.dcsr.ebreakm := debug.dcsr.ebreakm + debugStateB.dcsr.ebreaks := debug.dcsr.ebreaks + debugStateB.dcsr.ebreaku := debug.dcsr.ebreaku + debugStateB.dcsr.stepie := debug.dcsr.stepie + debugStateB.dcsr.stopcount := debug.dcsr.stopcount + debugStateB.dcsr.stoptime := debug.dcsr.stoptime + debugStateB.dcsr.cause := debug.dcsr.cause + debugStateB.dcsr.mprven := debug.dcsr.mprven + debugStateB.dcsr.nmip := debug.dcsr.nmip + debugStateB.dcsr.step := debug.dcsr.step + debugStateB.dcsr.prv := debug.dcsr.prv + debugStateB.dpc := debug.dpc + def guardedWrite(csrId : Int, bitRange: Range, allowed : Seq[Int], target : Bits) = { onWrite(csrId){ when(allowed.map(writeData()(bitRange) === _).orR){ From 5dd6ff2ea12ca0a23dd79c4a8d03c0a829226614 Mon Sep 17 00:00:00 2001 From: Jacob Tilger Date: Wed, 31 Jan 2024 15:30:50 +0100 Subject: [PATCH 05/19] exposes privilege information --- src/main/scala/vexriscv/Services.scala | 6 ++- .../scala/vexriscv/plugin/CsrPlugin.scala | 54 +++++++++++++------ 2 files changed, 44 insertions(+), 16 deletions(-) diff --git a/src/main/scala/vexriscv/Services.scala b/src/main/scala/vexriscv/Services.scala index f0ef7136..8b67eb7f 100644 --- a/src/main/scala/vexriscv/Services.scala +++ b/src/main/scala/vexriscv/Services.scala @@ -49,6 +49,8 @@ trait PrivilegeService{ def isUser() : Bool def isSupervisor() : Bool def isMachine() : Bool + def hasUser() : Boolean + def hasSupervisor() : Boolean def forceMachine() : Unit def encodeBits() : Bits = { @@ -70,6 +72,8 @@ case class PrivilegeServiceDefault() extends PrivilegeService{ override def isUser(): Bool = False override def isSupervisor(): Bool = False override def isMachine(): Bool = True + override def hasUser(): Boolean = false + override def hasSupervisor(): Boolean = false override def forceMachine(): Unit = {} } @@ -143,4 +147,4 @@ class CacheReport { class DebugReport { @BeanProperty var hardwareBreakpointCount = 0 -} \ No newline at end of file +} diff --git a/src/main/scala/vexriscv/plugin/CsrPlugin.scala b/src/main/scala/vexriscv/plugin/CsrPlugin.scala index 867a4c9a..b17078fe 100644 --- a/src/main/scala/vexriscv/plugin/CsrPlugin.scala +++ b/src/main/scala/vexriscv/plugin/CsrPlugin.scala @@ -407,6 +407,7 @@ trait DebugService{ } } + def hasDebugMode() : Boolean def inDebugMode() : Bool def debugState() : DebugState } @@ -464,8 +465,13 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep override def isContextSwitching = contextSwitching - override def inDebugMode(): Bool = if(withPrivilegedDebug) debugMode else False - override def debugState(): DebugState = debugStateB + override def hasDebugMode(): Boolean = withPrivilegedDebug + override def inDebugMode(): Bool = if(hasDebugMode) debugMode else False + override def debugState(): DebugState = { + val state = new DebugState(xlen) + state := debugStateB + state + } object EnvCtrlEnum extends SpinalEnum(binarySequential){ val NONE, XRET = newElement() @@ -640,6 +646,8 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep override def isUser() : Bool = privilege === 0 override def isSupervisor(): Bool = privilege === 1 override def isMachine(): Bool = privilege === 3 + override def hasUser() : Boolean = userGen + override def hasSupervisor() : Boolean = supervisorGen override def forceMachine(): Unit = forceMachineWire := True override def build(pipeline: VexRiscv): Unit = { @@ -939,19 +947,35 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep // make debug state accessible debugStateB = new DebugState(xlen) - debugStateB.dcsr.xdebugver := debug.dcsr.xdebugver - debugStateB.dcsr.ebreakm := debug.dcsr.ebreakm - debugStateB.dcsr.ebreaks := debug.dcsr.ebreaks - debugStateB.dcsr.ebreaku := debug.dcsr.ebreaku - debugStateB.dcsr.stepie := debug.dcsr.stepie - debugStateB.dcsr.stopcount := debug.dcsr.stopcount - debugStateB.dcsr.stoptime := debug.dcsr.stoptime - debugStateB.dcsr.cause := debug.dcsr.cause - debugStateB.dcsr.mprven := debug.dcsr.mprven - debugStateB.dcsr.nmip := debug.dcsr.nmip - debugStateB.dcsr.step := debug.dcsr.step - debugStateB.dcsr.prv := debug.dcsr.prv - debugStateB.dpc := debug.dpc + if (hasDebugMode()) { + debugStateB.dcsr.xdebugver := debug.dcsr.xdebugver + debugStateB.dcsr.ebreakm := debug.dcsr.ebreakm + debugStateB.dcsr.ebreaks := debug.dcsr.ebreaks + debugStateB.dcsr.ebreaku := debug.dcsr.ebreaku + debugStateB.dcsr.stepie := debug.dcsr.stepie + debugStateB.dcsr.stopcount := debug.dcsr.stopcount + debugStateB.dcsr.stoptime := debug.dcsr.stoptime + debugStateB.dcsr.cause := debug.dcsr.cause + debugStateB.dcsr.mprven := debug.dcsr.mprven + debugStateB.dcsr.nmip := debug.dcsr.nmip + debugStateB.dcsr.step := debug.dcsr.step + debugStateB.dcsr.prv := debug.dcsr.prv + debugStateB.dpc := debug.dpc + } else { + debugStateB.dcsr.xdebugver := 0 + debugStateB.dcsr.ebreakm := False + debugStateB.dcsr.ebreaks := False + debugStateB.dcsr.ebreaku := False + debugStateB.dcsr.stepie := False + debugStateB.dcsr.stopcount := False + debugStateB.dcsr.stoptime := False + debugStateB.dcsr.cause := 0 + debugStateB.dcsr.mprven := False + debugStateB.dcsr.nmip := False + debugStateB.dcsr.step := False + debugStateB.dcsr.prv := 0 + debugStateB.dpc := 0 + } def guardedWrite(csrId : Int, bitRange: Range, allowed : Seq[Int], target : Bits) = { onWrite(csrId){ From cff3bc39eafbf7405cff7cc28e0b16774ddf45d6 Mon Sep 17 00:00:00 2001 From: Jacob Tilger Date: Wed, 31 Jan 2024 15:35:56 +0100 Subject: [PATCH 06/19] moved timer to CounterPlugin --- .../demo/VexRiscvAxi4LinuxPlicClint.scala | 6 +- .../demo/smp/VexRiscvSmpCluster.scala | 4 +- .../scala/vexriscv/plugin/CounterPlugin.scala | 120 +++++++++++++++--- .../scala/vexriscv/plugin/CsrPlugin.scala | 9 -- 4 files changed, 107 insertions(+), 32 deletions(-) diff --git a/src/main/scala/vexriscv/demo/VexRiscvAxi4LinuxPlicClint.scala b/src/main/scala/vexriscv/demo/VexRiscvAxi4LinuxPlicClint.scala index a8ab02a4..4304e3fe 100644 --- a/src/main/scala/vexriscv/demo/VexRiscvAxi4LinuxPlicClint.scala +++ b/src/main/scala/vexriscv/demo/VexRiscvAxi4LinuxPlicClint.scala @@ -96,7 +96,7 @@ object VexRiscvAxi4LinuxPlicClint{ earlyBranch = false, catchAddressMisaligned = true ), - new CsrPlugin(CsrPluginConfig.openSbi(mhartid = 0, misa = Riscv.misaToInt(s"ima")).copy(utimeAccess = CsrAccess.READ_ONLY)), + new CsrPlugin(CsrPluginConfig.openSbi(mhartid = 0, misa = Riscv.misaToInt(s"ima"))), new YamlPlugin("cpu0.yaml") ) ) @@ -152,7 +152,9 @@ object VexRiscvAxi4LinuxPlicClint{ plugin.softwareInterrupt setAsDirectionLess() := cpu.clintCtrl.io.softwareInterrupt(0) plugin.externalInterrupt setAsDirectionLess() := cpu.plicCtrl.io.targets(0) plugin.externalInterruptS setAsDirectionLess() := cpu.plicCtrl.io.targets(1) - plugin.utime setAsDirectionLess() := cpu.clintCtrl.io.time + } + case plugin: CounterPlugin => { + plugin.time setAsDirectionLess() := cpu.clintCtrl.io.time } case _ => } diff --git a/src/main/scala/vexriscv/demo/smp/VexRiscvSmpCluster.scala b/src/main/scala/vexriscv/demo/smp/VexRiscvSmpCluster.scala index e37ece7d..179e6111 100644 --- a/src/main/scala/vexriscv/demo/smp/VexRiscvSmpCluster.scala +++ b/src/main/scala/vexriscv/demo/smp/VexRiscvSmpCluster.scala @@ -150,7 +150,7 @@ class VexRiscvSmpClusterWithPeripherals(p : VexRiscvSmpClusterParameter) extends plic.addTarget(core.cpu.externalSupervisorInterrupt) List(clint.logic, core.cpu.logic).produce { for (plugin <- core.cpu.config.plugins) plugin match { - case plugin: CsrPlugin if plugin.utime != null => plugin.utime := clint.logic.io.time + case plugin: CounterPlugin if plugin.time != null => plugin.time := clint.logic.io.time case _ => } } @@ -204,7 +204,7 @@ object VexRiscvSmpClusterGen { val misa = Riscv.misaToInt(s"ima${if(withFloat) "f" else ""}${if(withDouble) "d" else ""}${if(rvc) "c" else ""}${if(withSupervisor) "s" else ""}") val csrConfig = if(withSupervisor){ - var c = CsrPluginConfig.openSbi(mhartid = hartId, misa = misa).copy(utimeAccess = CsrAccess.READ_ONLY, withPrivilegedDebug = privilegedDebug) + var c = CsrPluginConfig.openSbi(mhartid = hartId, misa = misa).copy(withPrivilegedDebug = privilegedDebug) if(csrFull){ c = c.copy( mcauseAccess = CsrAccess.READ_WRITE, diff --git a/src/main/scala/vexriscv/plugin/CounterPlugin.scala b/src/main/scala/vexriscv/plugin/CounterPlugin.scala index d2038e70..54b7fe7b 100644 --- a/src/main/scala/vexriscv/plugin/CounterPlugin.scala +++ b/src/main/scala/vexriscv/plugin/CounterPlugin.scala @@ -2,7 +2,7 @@ package vexriscv.plugin import spinal.core._ -import vexriscv.VexRiscv +import vexriscv._ import vexriscv.Riscv.CSR._ import scala.collection.mutable._ @@ -20,6 +20,8 @@ case class CounterPluginConfig( minstretAccess : CsrAccess = CsrAccess.READ_WRITE, uinstretAccess : CsrAccess = CsrAccess.READ_ONLY, + utimeAccess : CsrAccess = CsrAccess.READ_ONLY, + mcounterenAccess : CsrAccess = CsrAccess.READ_WRITE, scounterenAccess : CsrAccess = CsrAccess.READ_WRITE, @@ -33,6 +35,12 @@ case class CounterPluginConfig( assert(!ucycleAccess.canWrite) } +object Priv{ + val M = 3 + val S = 1 + val U = 0 +} + class CounterPlugin(config : CounterPluginConfig) extends Plugin[VexRiscv] with CounterService { import config._ @@ -51,16 +59,39 @@ class CounterPlugin(config : CounterPluginConfig) extends Plugin[VexRiscv] with val eventType : Map[BigInt, Bool] = new HashMap() - implicit class CsrAccessPimper(csrAccess : CsrAccess){ + var time : UInt = null + + implicit class PrivilegeHelper(p : PrivilegeService){ + def canMachine() : Bool = p.isMachine() + def canSupervisor() : Bool = p.isMachine() || p.isSupervisor() + } + + implicit class CsrAccessHelper(csrAccess : CsrAccess){ import CsrAccess._ - def apply(csrService : CsrInterface, csrAddress : Int, thats : (Int, Data)*) : Unit = { - if(csrAccess == `WRITE_ONLY` || csrAccess == `READ_WRITE`) for(that <- thats) csrService.w(csrAddress,that._1, that._2) - if(csrAccess == `READ_ONLY` || csrAccess == `READ_WRITE`) for(that <- thats) csrService.r(csrAddress,that._1, that._2) - } + import Priv._ def apply(csrService : CsrInterface, csrAddress : Int, that : Data) : Unit = { if(csrAccess == `WRITE_ONLY` || csrAccess == `READ_WRITE`) csrService.w(csrAddress, 0, that) if(csrAccess == `READ_ONLY` || csrAccess == `READ_WRITE`) csrService.r(csrAddress, 0, that) } + def apply( + csrSrv : CsrInterface, + prvSrv : PrivilegeService, + csrAddress : Int, + that : Data, + privAllows : (Int, Bool)* + ) : Unit = { + apply(csrSrv, csrAddress, that) + if(csrAccess != CsrAccess.NONE) csrSrv.during(csrAddress){ + for (ii <- privAllows) { + if (ii._1 == M) + when (~prvSrv.canMachine() || ~ii._2) { csrSrv.forceFailCsr() } + if (ii._1 == S && prvSrv.hasSupervisor()) + when (~prvSrv.canSupervisor() || ~ii._2) { csrSrv.forceFailCsr() } + if (prvSrv.hasUser()) + when (~ii._2) { csrSrv.forceFailCsr() } + } + } + } } override def getCondition(eventId : BigInt) : Bool = { @@ -71,29 +102,80 @@ class CounterPlugin(config : CounterPluginConfig) extends Plugin[VexRiscv] with eventType(eventId) } + override def setup(pipeline : VexRiscv) : Unit = { + import pipeline._ + import pipeline.config._ + + if (utimeAccess != CsrAccess.NONE) time = in UInt(64 bits) setName("utime") + } + override def build(pipeline : VexRiscv) : Unit = { import pipeline._ import pipeline.config._ pipeline plug new Area{ - val csrService = pipeline.service(classOf[CsrInterface]) + val csrSrv = pipeline.service(classOf[CsrInterface]) + val dbgSrv = pipeline.service(classOf[DebugService]) + val prvSrv = pipeline.service(classOf[PrivilegeService]) + + val dbgCtrEn = ~(dbgSrv.inDebugMode() && dbgSrv.debugState().dcsr.stopcount) - // cycle val cycle = Reg(UInt(64 bits)) init(0) - cycle := cycle + 1 - ucycleAccess(csrService, UCYCLE, cycle(31 downto 0)) - ucycleAccess(csrService, UCYCLEH, cycle(63 downto 32)) - mcycleAccess(csrService, MCYCLE, cycle(31 downto 0)) - mcycleAccess(csrService, MCYCLEH, cycle(63 downto 32)) - // instret + cycle := cycle + U(dbgCtrEn) val instret = Reg(UInt(64 bits)) init(0) when(pipeline.stages.last.arbitration.isFiring) { - instret := instret + 1 + instret := instret + U(dbgCtrEn) + } + + val menable = RegInit(Bits(3 + NumOfCounters bits).getAllTrue) + val senable = RegInit(Bits(3 + NumOfCounters bits).getAllTrue) + + val expose = new Area { + import Priv._ + // enable + mcounterenAccess(csrSrv, prvSrv, MCOUNTEREN, menable.resize(32), S -> False, U -> False) + scounterenAccess(csrSrv, prvSrv, SCOUNTEREN, senable.resize(32), U -> False) + + // fixed counters + ucycleAccess(csrSrv, prvSrv, UCYCLE, cycle(31 downto 0), + S -> menable(0), + U -> (if (prvSrv.hasSupervisor()) senable(0) else True), + U -> menable(0) + ) + ucycleAccess(csrSrv, prvSrv, UCYCLEH, cycle(63 downto 32), + S -> menable(0), + U -> (if (prvSrv.hasSupervisor()) senable(0) else True), + U -> menable(0) + ) + + mcycleAccess(csrSrv, prvSrv, MCYCLE, cycle(31 downto 0), S -> False, U -> False) + mcycleAccess(csrSrv, prvSrv, MCYCLEH, cycle(63 downto 32), S -> False, U -> False) + + utimeAccess(csrSrv, prvSrv, UTIME, time(31 downto 0), + S -> menable(1), + U -> (if (prvSrv.hasSupervisor()) senable(1) else True), + U -> menable(1) + ) + utimeAccess(csrSrv, prvSrv, UTIMEH, time(63 downto 32), + S -> menable(1), + U -> (if (prvSrv.hasSupervisor()) senable(1) else True), + U -> menable(1) + ) + + uinstretAccess(csrSrv, prvSrv, UINSTRET, instret(31 downto 0), + S -> menable(2), + U -> (if (prvSrv.hasSupervisor()) senable(2) else True), + U -> menable(2) + ) + uinstretAccess(csrSrv, prvSrv, UINSTRETH, instret(63 downto 32), + S -> menable(2), + U -> (if (prvSrv.hasSupervisor()) senable(2) else True), + U -> menable(2) + ) + + minstretAccess(csrSrv, prvSrv, MINSTRET, instret(31 downto 0), S -> False, U -> False) + minstretAccess(csrSrv, prvSrv, MINSTRETH, instret(63 downto 32), S -> False, U -> False) } - uinstretAccess(csrService, UINSTRET, instret(31 downto 0)) - uinstretAccess(csrService, UINSTRETH, instret(63 downto 32)) - minstretAccess(csrService, MINSTRET, instret(31 downto 0)) - minstretAccess(csrService, MINSTRETH, instret(63 downto 32)) // TODO counters } diff --git a/src/main/scala/vexriscv/plugin/CsrPlugin.scala b/src/main/scala/vexriscv/plugin/CsrPlugin.scala index b17078fe..766806cd 100644 --- a/src/main/scala/vexriscv/plugin/CsrPlugin.scala +++ b/src/main/scala/vexriscv/plugin/CsrPlugin.scala @@ -65,7 +65,6 @@ case class CsrPluginConfig( scauseAccess : CsrAccess = CsrAccess.NONE, sbadaddrAccess : CsrAccess = CsrAccess.NONE, satpAccess : CsrAccess = CsrAccess.NONE, - utimeAccess :CsrAccess = CsrAccess.NONE, medelegAccess : CsrAccess = CsrAccess.NONE, midelegAccess : CsrAccess = CsrAccess.NONE, withExternalMhartid : Boolean = false, @@ -452,7 +451,6 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep var thirdPartyWake : Bool = null var inWfi : Bool = null var externalMhartId : UInt = null - var utime : UInt = null var stoptime : Bool = null var xretAwayFromMachine : Bool = null @@ -622,7 +620,6 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep pipeline.update(MPP, UInt(2 bits)) if(withExternalMhartid) externalMhartId = in UInt(mhartidWidth bits) - if(utimeAccess != CsrAccess.NONE) utime = in UInt(64 bits) setName("utime") if(supervisorGen) { decoderService.addDefault(RESCHEDULE_NEXT, False) @@ -1065,12 +1062,6 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep midelegAccess(CSR.MIDELEG, 9 -> mideleg.SE, 5 -> mideleg.ST, 1 -> mideleg.SS) } - //User CSR - if(utimeAccess != CsrAccess.NONE) { - utimeAccess(CSR.UTIME, utime(31 downto 0)) - utimeAccess(CSR.UTIMEH, utime(63 downto 32)) - } - pipeline(MPP) := mstatus.MPP } From 6f578430abc1d0e728036423b43ababb94d18342 Mon Sep 17 00:00:00 2001 From: Jacob Tilger Date: Wed, 31 Jan 2024 16:26:44 +0100 Subject: [PATCH 07/19] added custom counters --- src/main/scala/vexriscv/Riscv.scala | 1 + .../scala/vexriscv/plugin/CounterPlugin.scala | 80 ++++++++++++++----- 2 files changed, 62 insertions(+), 19 deletions(-) diff --git a/src/main/scala/vexriscv/Riscv.scala b/src/main/scala/vexriscv/Riscv.scala index 89e3b5ec..d4bbaa15 100644 --- a/src/main/scala/vexriscv/Riscv.scala +++ b/src/main/scala/vexriscv/Riscv.scala @@ -218,6 +218,7 @@ object Riscv{ val MCOUNTEREN = 0x306 val MCOUNTER = 0xB03 // MRW Base address for mhpmcounterX. val MCOUNTERH = 0xB83 // MRW Base address for mhpmcounterXh, RV32I only. + val MCOUNTINHIBIT = 0x320 val MEVENT = 0x323 // MRW Base address for mhpmeventX. val SSTATUS = 0x100 diff --git a/src/main/scala/vexriscv/plugin/CounterPlugin.scala b/src/main/scala/vexriscv/plugin/CounterPlugin.scala index 54b7fe7b..72dbf53d 100644 --- a/src/main/scala/vexriscv/plugin/CounterPlugin.scala +++ b/src/main/scala/vexriscv/plugin/CounterPlugin.scala @@ -12,25 +12,25 @@ trait CounterService{ } case class CounterPluginConfig( - NumOfCounters : Byte = 29, + NumOfCounters : Byte = 29, - mcycleAccess : CsrAccess = CsrAccess.READ_WRITE, - ucycleAccess : CsrAccess = CsrAccess.READ_ONLY, + mcycleAccess : CsrAccess = CsrAccess.READ_WRITE, + ucycleAccess : CsrAccess = CsrAccess.READ_ONLY, - minstretAccess : CsrAccess = CsrAccess.READ_WRITE, - uinstretAccess : CsrAccess = CsrAccess.READ_ONLY, + minstretAccess : CsrAccess = CsrAccess.READ_WRITE, + uinstretAccess : CsrAccess = CsrAccess.READ_ONLY, - utimeAccess : CsrAccess = CsrAccess.READ_ONLY, + utimeAccess : CsrAccess = CsrAccess.READ_ONLY, - mcounterenAccess : CsrAccess = CsrAccess.READ_WRITE, - scounterenAccess : CsrAccess = CsrAccess.READ_WRITE, + mcounterenAccess : CsrAccess = CsrAccess.READ_WRITE, + scounterenAccess : CsrAccess = CsrAccess.READ_WRITE, - mcounterAccess : CsrAccess = CsrAccess.READ_WRITE, - ucounterAccess : CsrAccess = CsrAccess.READ_ONLY, + mcounterAccess : CsrAccess = CsrAccess.READ_WRITE, + ucounterAccess : CsrAccess = CsrAccess.READ_ONLY, // management - meventAccess : CsrAccess = CsrAccess.READ_WRITE, - mcounterinhibitAccess : CsrAccess = CsrAccess.READ_WRITE + meventAccess : CsrAccess = CsrAccess.READ_WRITE, + mcountinhibitAccess : CsrAccess = CsrAccess.READ_WRITE ) { assert(!ucycleAccess.canWrite) } @@ -96,7 +96,7 @@ class CounterPlugin(config : CounterPluginConfig) extends Plugin[VexRiscv] with override def getCondition(eventId : BigInt) : Bool = { if (!eventType.contains(eventId)) { - eventType(eventId) = new Bool() + eventType(eventId) = Bool } eventType(eventId) @@ -120,22 +120,66 @@ class CounterPlugin(config : CounterPluginConfig) extends Plugin[VexRiscv] with val dbgCtrEn = ~(dbgSrv.inDebugMode() && dbgSrv.debugState().dcsr.stopcount) + val menable = RegInit(Bits(3 + NumOfCounters bits).getAllTrue) + val senable = RegInit(Bits(3 + NumOfCounters bits).getAllTrue) + val inhibit = Reg(Bits(NumOfCounters bits)) init(0) + val inhibitCY = RegInit(False) + val inhibitIR = RegInit(False) + val cycle = Reg(UInt(64 bits)) init(0) - cycle := cycle + U(dbgCtrEn) + cycle := cycle + U(dbgCtrEn && ~inhibitCY) val instret = Reg(UInt(64 bits)) init(0) when(pipeline.stages.last.arbitration.isFiring) { - instret := instret + U(dbgCtrEn) + instret := instret + U(dbgCtrEn && ~inhibitIR) } + + val counter = Array.fill(NumOfCounters){Reg(UInt(64 bits)) init(0)} + val events = Array.fill(NumOfCounters){Reg(UInt(xlen bits)) init(0)} - val menable = RegInit(Bits(3 + NumOfCounters bits).getAllTrue) - val senable = RegInit(Bits(3 + NumOfCounters bits).getAllTrue) + var customCounters = new Area { + val increment = Array.fill(NumOfCounters){Bool} + + for (ii <- 0 until NumOfCounters) { + counter(ii) := counter(ii) + U(dbgCtrEn && ~inhibit(ii) && increment(ii)) + + for (event <- eventType) { + when (event._1 =/= U(0, xlen bits) && event._1 === events(ii)) { + increment(ii) := event._2 + } otherwise { + increment(ii) := False + } + } + } + } val expose = new Area { import Priv._ + // inhibit + csrSrv.during(MCOUNTINHIBIT){ when (~prvSrv.isMachine()) {csrSrv.forceFailCsr()} } + csrSrv.rw(MCOUNTINHIBIT, 0 -> inhibitCY, 2 -> inhibitIR, 3 -> inhibit) + // enable mcounterenAccess(csrSrv, prvSrv, MCOUNTEREN, menable.resize(32), S -> False, U -> False) scounterenAccess(csrSrv, prvSrv, SCOUNTEREN, senable.resize(32), U -> False) + // custom counters + for (ii <- 0 until NumOfCounters) { + ucounterAccess(csrSrv, prvSrv, UCOUNTER + ii, counter(ii)(31 downto 0), + S -> menable(3 + ii), + U -> (if (prvSrv.hasSupervisor()) senable(3 + ii) else True), + U -> menable(3 + ii) + ) + ucounterAccess(csrSrv, prvSrv, UCOUNTERH + ii, counter(ii)(63 downto 32), + S -> menable(3 + ii), + U -> (if (prvSrv.hasSupervisor()) senable(3 + ii) else True), + U -> menable(3 + ii) + ) + + mcounterAccess(csrSrv, prvSrv, MCOUNTER + ii, counter(ii)(31 downto 0), S -> False, U -> False) + mcounterAccess(csrSrv, prvSrv, MCOUNTERH + ii, counter(ii)(63 downto 31), S -> False, U -> False) + meventAccess(csrSrv, prvSrv, MCOUNTER + ii, events(ii), S -> False, U -> False) + } + // fixed counters ucycleAccess(csrSrv, prvSrv, UCYCLE, cycle(31 downto 0), S -> menable(0), @@ -176,8 +220,6 @@ class CounterPlugin(config : CounterPluginConfig) extends Plugin[VexRiscv] with minstretAccess(csrSrv, prvSrv, MINSTRET, instret(31 downto 0), S -> False, U -> False) minstretAccess(csrSrv, prvSrv, MINSTRETH, instret(63 downto 32), S -> False, U -> False) } - - // TODO counters } } } From d50a1bc327e0c2ca5511457f2de6751683582b19 Mon Sep 17 00:00:00 2001 From: Jacob Tilger Date: Wed, 31 Jan 2024 16:53:05 +0100 Subject: [PATCH 08/19] final touches --- src/main/scala/vexriscv/plugin/CounterPlugin.scala | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/scala/vexriscv/plugin/CounterPlugin.scala b/src/main/scala/vexriscv/plugin/CounterPlugin.scala index 72dbf53d..a5804384 100644 --- a/src/main/scala/vexriscv/plugin/CounterPlugin.scala +++ b/src/main/scala/vexriscv/plugin/CounterPlugin.scala @@ -142,11 +142,11 @@ class CounterPlugin(config : CounterPluginConfig) extends Plugin[VexRiscv] with for (ii <- 0 until NumOfCounters) { counter(ii) := counter(ii) + U(dbgCtrEn && ~inhibit(ii) && increment(ii)) + increment(ii) := False + for (event <- eventType) { when (event._1 =/= U(0, xlen bits) && event._1 === events(ii)) { increment(ii) := event._2 - } otherwise { - increment(ii) := False } } } @@ -159,8 +159,8 @@ class CounterPlugin(config : CounterPluginConfig) extends Plugin[VexRiscv] with csrSrv.rw(MCOUNTINHIBIT, 0 -> inhibitCY, 2 -> inhibitIR, 3 -> inhibit) // enable - mcounterenAccess(csrSrv, prvSrv, MCOUNTEREN, menable.resize(32), S -> False, U -> False) - scounterenAccess(csrSrv, prvSrv, SCOUNTEREN, senable.resize(32), U -> False) + mcounterenAccess(csrSrv, prvSrv, MCOUNTEREN, menable, S -> False, U -> False) + scounterenAccess(csrSrv, prvSrv, SCOUNTEREN, senable, U -> False) // custom counters for (ii <- 0 until NumOfCounters) { @@ -176,8 +176,8 @@ class CounterPlugin(config : CounterPluginConfig) extends Plugin[VexRiscv] with ) mcounterAccess(csrSrv, prvSrv, MCOUNTER + ii, counter(ii)(31 downto 0), S -> False, U -> False) - mcounterAccess(csrSrv, prvSrv, MCOUNTERH + ii, counter(ii)(63 downto 31), S -> False, U -> False) - meventAccess(csrSrv, prvSrv, MCOUNTER + ii, events(ii), S -> False, U -> False) + mcounterAccess(csrSrv, prvSrv, MCOUNTERH + ii, counter(ii)(63 downto 32), S -> False, U -> False) + meventAccess(csrSrv, prvSrv, MEVENT + ii, events(ii), S -> False, U -> False) } // fixed counters From 6d3c518923ac38c9e1e2e1f56bc6f6de98b5df73 Mon Sep 17 00:00:00 2001 From: Jacob Tilger Date: Wed, 31 Jan 2024 16:53:25 +0100 Subject: [PATCH 09/19] added Counter to full config --- src/main/scala/vexriscv/demo/GenFull.scala | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/scala/vexriscv/demo/GenFull.scala b/src/main/scala/vexriscv/demo/GenFull.scala index eb1dba33..0a38d149 100644 --- a/src/main/scala/vexriscv/demo/GenFull.scala +++ b/src/main/scala/vexriscv/demo/GenFull.scala @@ -80,6 +80,7 @@ object GenFull extends App{ earlyBranch = false, catchAddressMisaligned = true ), + new CounterPlugin(CounterPluginConfig()), new YamlPlugin("cpu0.yaml") ) ) From c06d7f5cb4bfb5c4c54c039135f1a78d8c317308 Mon Sep 17 00:00:00 2001 From: Jacob Tilger Date: Wed, 31 Jan 2024 17:12:42 +0100 Subject: [PATCH 10/19] renamed utime to time & doc --- README.md | 12 ++++++++++++ src/main/scala/vexriscv/plugin/CounterPlugin.scala | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index c7578c6f..85437240 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,7 @@ - [YamlPlugin](#yamlplugin) - [FpuPlugin](#fpuplugin) - [AesPlugin](#aesplugin) + - [CounterPlugin](#counterplugin) @@ -1319,3 +1320,14 @@ It was also ported on libressl via the following patch : Speed up of 4 was observed in libressl running in linux. + +#### CounterPlugin + +Provides performance-counter and time CSRs. + +Here is how to provide a custom event condition (which can then be configured by code): +```scala +val ctrSrv = pipeline.service(classOf[CounterService]) +ctrSrv.getCondition(eventId) := boolCond +``` +eventId is BigInt, but only events between 0 and 2 ** XLEN (excluding boundaries) can be selected by cpu. diff --git a/src/main/scala/vexriscv/plugin/CounterPlugin.scala b/src/main/scala/vexriscv/plugin/CounterPlugin.scala index a5804384..c711e559 100644 --- a/src/main/scala/vexriscv/plugin/CounterPlugin.scala +++ b/src/main/scala/vexriscv/plugin/CounterPlugin.scala @@ -106,7 +106,7 @@ class CounterPlugin(config : CounterPluginConfig) extends Plugin[VexRiscv] with import pipeline._ import pipeline.config._ - if (utimeAccess != CsrAccess.NONE) time = in UInt(64 bits) setName("utime") + if (utimeAccess != CsrAccess.NONE) time = in UInt(64 bits) setName("time") } override def build(pipeline : VexRiscv) : Unit = { From 659a8b1dbc10c9e157d68e94ea3c66ea111db371 Mon Sep 17 00:00:00 2001 From: Jacob Tilger Date: Mon, 5 Feb 2024 13:48:09 +0100 Subject: [PATCH 11/19] readded legacy counters/timers --- .../scala/vexriscv/plugin/CounterPlugin.scala | 2 +- .../scala/vexriscv/plugin/CsrPlugin.scala | 90 +++++++++++++++++-- 2 files changed, 84 insertions(+), 8 deletions(-) diff --git a/src/main/scala/vexriscv/plugin/CounterPlugin.scala b/src/main/scala/vexriscv/plugin/CounterPlugin.scala index c711e559..a5804384 100644 --- a/src/main/scala/vexriscv/plugin/CounterPlugin.scala +++ b/src/main/scala/vexriscv/plugin/CounterPlugin.scala @@ -106,7 +106,7 @@ class CounterPlugin(config : CounterPluginConfig) extends Plugin[VexRiscv] with import pipeline._ import pipeline.config._ - if (utimeAccess != CsrAccess.NONE) time = in UInt(64 bits) setName("time") + if (utimeAccess != CsrAccess.NONE) time = in UInt(64 bits) setName("utime") } override def build(pipeline : VexRiscv) : Unit = { diff --git a/src/main/scala/vexriscv/plugin/CsrPlugin.scala b/src/main/scala/vexriscv/plugin/CsrPlugin.scala index 766806cd..e07ec9ed 100644 --- a/src/main/scala/vexriscv/plugin/CsrPlugin.scala +++ b/src/main/scala/vexriscv/plugin/CsrPlugin.scala @@ -76,7 +76,13 @@ case class CsrPluginConfig( wfiOutput : Boolean = false, exportPrivilege : Boolean = false, var withPrivilegedDebug : Boolean = false, //For the official RISC-V debug spec implementation - var debugTriggers : Int = 2 + var debugTriggers : Int = 2, + // these options only have effect, when no CounterService is present in Pipeline + utimeAccess : CsrAccess = CsrAccess.NONE, + mcycleAccess : CsrAccess = CsrAccess.NONE, + minstretAccess : CsrAccess = CsrAccess.NONE, + ucycleAccess : CsrAccess = CsrAccess.NONE, + uinstretAccess : CsrAccess = CsrAccess.NONE ){ def privilegeGen = userGen || supervisorGen || withPrivilegedDebug def noException = this.copy(ecallGen = false, ebreakGen = false, catchIllegalAccess = false) @@ -189,7 +195,11 @@ object CsrPluginConfig{ medelegAccess = CsrAccess.READ_WRITE, midelegAccess = CsrAccess.READ_WRITE, pipelineCsrRead = false, - deterministicInteruptionEntry = false + deterministicInteruptionEntry = false, + mcycleAccess = CsrAccess.READ_WRITE, + minstretAccess = CsrAccess.READ_WRITE, + ucycleAccess = CsrAccess.READ_ONLY, + uinstretAccess = CsrAccess.READ_ONLY ) def all(mtvecInit : BigInt) : CsrPluginConfig = CsrPluginConfig( @@ -207,7 +217,11 @@ object CsrPluginConfig{ mcauseAccess = CsrAccess.READ_WRITE, mbadaddrAccess = CsrAccess.READ_WRITE, ecallGen = true, - wfiGenAsWait = true + wfiGenAsWait = true, + mcycleAccess = CsrAccess.READ_WRITE, + minstretAccess = CsrAccess.READ_WRITE, + ucycleAccess = CsrAccess.READ_ONLY, + uinstretAccess = CsrAccess.READ_ONLY ) def all2(mtvecInit : BigInt) : CsrPluginConfig = CsrPluginConfig( @@ -234,7 +248,11 @@ object CsrPluginConfig{ sbadaddrAccess = CsrAccess.READ_WRITE, satpAccess = CsrAccess.READ_WRITE, medelegAccess = CsrAccess.READ_WRITE, - midelegAccess = CsrAccess.READ_WRITE + midelegAccess = CsrAccess.READ_WRITE, + mcycleAccess = CsrAccess.READ_WRITE, + minstretAccess = CsrAccess.READ_WRITE, + ucycleAccess = CsrAccess.READ_ONLY, + uinstretAccess = CsrAccess.READ_ONLY ) def small(mtvecInit : BigInt) = CsrPluginConfig( @@ -291,7 +309,11 @@ object CsrPluginConfig{ ecallGen = true, userGen = true, medelegAccess = CsrAccess.READ_WRITE, - midelegAccess = CsrAccess.READ_WRITE + midelegAccess = CsrAccess.READ_WRITE, + mcycleAccess = CsrAccess.READ_WRITE, + minstretAccess = CsrAccess.READ_WRITE, + ucycleAccess = CsrAccess.READ_ONLY, + uinstretAccess = CsrAccess.READ_ONLY ) } @@ -333,7 +355,7 @@ case class CsrMapping() extends Area with CsrInterface { override def allowCsr() = allowCsrSignal := True override def isHazardFree() = hazardFree override def forceFailCsr() = doForceFailCsr := True - override def inDebugMode() : Bool = ??? + override def inDebugMode(): Bool = ??? } @@ -451,6 +473,7 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep var thirdPartyWake : Bool = null var inWfi : Bool = null var externalMhartId : UInt = null + var utime : UInt = null var stoptime : Bool = null var xretAwayFromMachine : Bool = null @@ -464,7 +487,7 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep override def isContextSwitching = contextSwitching override def hasDebugMode(): Boolean = withPrivilegedDebug - override def inDebugMode(): Bool = if(hasDebugMode) debugMode else False + override def inDebugMode(): Bool = if(hasDebugMode()) debugMode else False override def debugState(): DebugState = { val state = new DebugState(xlen) state := debugStateB @@ -620,6 +643,7 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep pipeline.update(MPP, UInt(2 bits)) if(withExternalMhartid) externalMhartId = in UInt(mhartidWidth bits) + if(pipeline.serviceExist(classOf[CounterService]) && utimeAccess != CsrAccess.NONE) utime = in UInt(64 bits) setName("utime") if(supervisorGen) { decoderService.addDefault(RESCHEDULE_NEXT, False) @@ -1062,6 +1086,58 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep midelegAccess(CSR.MIDELEG, 9 -> mideleg.SE, 5 -> mideleg.ST, 1 -> mideleg.SS) } + // legacy counter/timer generation, when no counter-plugin exists + var counters : Area = (!pipeline.serviceExist(classOf[CounterService])) generate new Area { + SpinalInfo("No CounterService was found. Generating legacy counters and timer") + val mcycle = Reg(UInt(64 bits)) init(0) + val minstret = Reg(UInt(64 bits)) init(0) + + mcycleAccess(CSR.MCYCLE, mcycle(31 downto 0)) + mcycleAccess(CSR.MCYCLEH, mcycle(63 downto 32)) + minstretAccess(CSR.MINSTRET, minstret(31 downto 0)) + minstretAccess(CSR.MINSTRETH, minstret(63 downto 32)) + + ucycleAccess(CSR.UCYCLE, mcycle(31 downto 0)) + ucycleAccess(CSR.UCYCLEH, mcycle(63 downto 32)) + uinstretAccess(CSR.UINSTRET, minstret(31 downto 0)) + uinstretAccess(CSR.UINSTRETH, minstret(63 downto 32)) + + if(utimeAccess != CsrAccess.NONE) { + utimeAccess(CSR.UTIME, utime(31 downto 0)) + utimeAccess(CSR.UTIMEH, utime(63 downto 32)) + } + + class Xcounteren(csrId : Int) extends Area{ + val IR,TM,CY = RegInit(True) //For backward compatibility + if(ucycleAccess != CsrAccess.NONE) rw(csrId, 0 -> CY) + if(utimeAccess != CsrAccess.NONE) rw(csrId, 1 -> TM) + if(uinstretAccess != CsrAccess.NONE) rw(csrId, 2 -> IR) + } + + def xcounterChecks(access : CsrAccess, csrId : Int, enable : Xcounteren => Bool) = { + if(access != CsrAccess.NONE) during(csrId){ + if(userGen) when(privilege < 3 && !enable(mcounteren)){forceFailCsr()} + if(supervisorGen) when(privilege < 1 && !enable(scounteren)){forceFailCsr()} + } + } + + val mcounteren = userGen generate new Xcounteren(CSR.MCOUNTEREN) + val scounteren = supervisorGen generate new Xcounteren(CSR.SCOUNTEREN) + + xcounterChecks(ucycleAccess , CSR.UCYCLE , _.CY) + xcounterChecks(ucycleAccess , CSR.UCYCLEH , _.CY) + xcounterChecks(utimeAccess , CSR.UTIME , _.TM) + xcounterChecks(utimeAccess , CSR.UTIMEH , _.TM) + xcounterChecks(uinstretAccess, CSR.UINSTRET , _.IR) + xcounterChecks(uinstretAccess, CSR.UINSTRETH, _.IR) + + // update + mcycle := mcycle + (if(hasDebugMode()) U(!debugMode || !debug.dcsr.stopcount) else U(1)) + when(pipeline.stages.last.arbitration.isFiring) { + minstret := minstret + (if(hasDebugMode()) U(!debugMode || !debug.dcsr.stopcount) else U(1)) + } + } + pipeline(MPP) := mstatus.MPP } From ca82922d67951a579b1601f9156405872253945d Mon Sep 17 00:00:00 2001 From: Jacob Tilger Date: Mon, 5 Feb 2024 13:56:36 +0100 Subject: [PATCH 12/19] added tags to regs to avoid warning when no counters will be generated --- src/main/scala/vexriscv/plugin/CounterPlugin.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/scala/vexriscv/plugin/CounterPlugin.scala b/src/main/scala/vexriscv/plugin/CounterPlugin.scala index a5804384..aa351a36 100644 --- a/src/main/scala/vexriscv/plugin/CounterPlugin.scala +++ b/src/main/scala/vexriscv/plugin/CounterPlugin.scala @@ -120,8 +120,8 @@ class CounterPlugin(config : CounterPluginConfig) extends Plugin[VexRiscv] with val dbgCtrEn = ~(dbgSrv.inDebugMode() && dbgSrv.debugState().dcsr.stopcount) - val menable = RegInit(Bits(3 + NumOfCounters bits).getAllTrue) - val senable = RegInit(Bits(3 + NumOfCounters bits).getAllTrue) + val menable = RegInit(Bits(3 + NumOfCounters bits).getAllTrue) allowUnsetRegToAvoidLatch + val senable = RegInit(Bits(3 + NumOfCounters bits).getAllTrue) allowUnsetRegToAvoidLatch val inhibit = Reg(Bits(NumOfCounters bits)) init(0) val inhibitCY = RegInit(False) val inhibitIR = RegInit(False) From aef4b4ab7e2a6ba8226dfd582f3d7be47160e99e Mon Sep 17 00:00:00 2001 From: Jacob Tilger Date: Mon, 5 Feb 2024 14:04:20 +0100 Subject: [PATCH 13/19] fixed demo configs --- .../vexriscv/demo/VexRiscvAxi4LinuxPlicClint.scala | 13 +++++++++++++ .../vexriscv/demo/smp/VexRiscvSmpCluster.scala | 13 +++++++++++++ 2 files changed, 26 insertions(+) diff --git a/src/main/scala/vexriscv/demo/VexRiscvAxi4LinuxPlicClint.scala b/src/main/scala/vexriscv/demo/VexRiscvAxi4LinuxPlicClint.scala index 4304e3fe..a253f870 100644 --- a/src/main/scala/vexriscv/demo/VexRiscvAxi4LinuxPlicClint.scala +++ b/src/main/scala/vexriscv/demo/VexRiscvAxi4LinuxPlicClint.scala @@ -97,6 +97,19 @@ object VexRiscvAxi4LinuxPlicClint{ catchAddressMisaligned = true ), new CsrPlugin(CsrPluginConfig.openSbi(mhartid = 0, misa = Riscv.misaToInt(s"ima"))), + new CounterPlugin(CounterPluginConfig( + NumOfCounters = 0, + mcycleAccess = CsrAccess.NONE, + ucycleAccess = CsrAccess.NONE, + minstretAccess = CsrAccess.NONE, + uinstretAccess = CsrAccess.NONE, + mcounterenAccess = CsrAccess.NONE, + scounterenAccess = CsrAccess.NONE, + mcounterAccess = CsrAccess.NONE, + ucounterAccess = CsrAccess.NONE, + meventAccess = CsrAccess.NONE, + mcountinhibitAccess = CsrAccess.NONE + )), new YamlPlugin("cpu0.yaml") ) ) diff --git a/src/main/scala/vexriscv/demo/smp/VexRiscvSmpCluster.scala b/src/main/scala/vexriscv/demo/smp/VexRiscvSmpCluster.scala index 179e6111..dd3d794e 100644 --- a/src/main/scala/vexriscv/demo/smp/VexRiscvSmpCluster.scala +++ b/src/main/scala/vexriscv/demo/smp/VexRiscvSmpCluster.scala @@ -351,6 +351,19 @@ object VexRiscvSmpClusterGen { catchAddressMisaligned = true, fenceiGenAsAJump = false ), + new CounterPlugin(if(csrFull) CounterPluginConfig() else CounterPluginConfig( + NumOfCounters = 0, + mcycleAccess = CsrAccess.NONE, + ucycleAccess = CsrAccess.NONE, + minstretAccess = CsrAccess.NONE, + uinstretAccess = CsrAccess.NONE, + mcounterenAccess = CsrAccess.NONE, + scounterenAccess = CsrAccess.NONE, + mcounterAccess = CsrAccess.NONE, + ucounterAccess = CsrAccess.NONE, + meventAccess = CsrAccess.NONE, + mcountinhibitAccess = CsrAccess.NONE + )), new YamlPlugin(s"cpu$hartId.yaml") ) ) From 9a8cdde9aae1fb1911ad6a73058aa9451d32d970 Mon Sep 17 00:00:00 2001 From: Jacob Tilger Date: Tue, 6 Feb 2024 17:04:57 +0100 Subject: [PATCH 14/19] fixed NullPointerException on utimeAccess NONE --- .../scala/vexriscv/plugin/CounterPlugin.scala | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/main/scala/vexriscv/plugin/CounterPlugin.scala b/src/main/scala/vexriscv/plugin/CounterPlugin.scala index aa351a36..a840416a 100644 --- a/src/main/scala/vexriscv/plugin/CounterPlugin.scala +++ b/src/main/scala/vexriscv/plugin/CounterPlugin.scala @@ -195,16 +195,18 @@ class CounterPlugin(config : CounterPluginConfig) extends Plugin[VexRiscv] with mcycleAccess(csrSrv, prvSrv, MCYCLE, cycle(31 downto 0), S -> False, U -> False) mcycleAccess(csrSrv, prvSrv, MCYCLEH, cycle(63 downto 32), S -> False, U -> False) - utimeAccess(csrSrv, prvSrv, UTIME, time(31 downto 0), - S -> menable(1), - U -> (if (prvSrv.hasSupervisor()) senable(1) else True), - U -> menable(1) - ) - utimeAccess(csrSrv, prvSrv, UTIMEH, time(63 downto 32), - S -> menable(1), - U -> (if (prvSrv.hasSupervisor()) senable(1) else True), - U -> menable(1) - ) + if(utimeAccess != CsrAccess.NONE) { + utimeAccess(csrSrv, prvSrv, UTIME, time(31 downto 0), + S -> menable(1), + U -> (if (prvSrv.hasSupervisor()) senable(1) else True), + U -> menable(1) + ) + utimeAccess(csrSrv, prvSrv, UTIMEH, time(63 downto 32), + S -> menable(1), + U -> (if (prvSrv.hasSupervisor()) senable(1) else True), + U -> menable(1) + ) + } uinstretAccess(csrSrv, prvSrv, UINSTRET, instret(31 downto 0), S -> menable(2), From ff2f9ef0c6ac651e9b8c8d8d8407c080c3a99daa Mon Sep 17 00:00:00 2001 From: Jacob Tilger Date: Thu, 29 Feb 2024 14:36:55 +0100 Subject: [PATCH 15/19] fixed cross-phase issue --- README.md | 6 ++++++ src/main/scala/vexriscv/plugin/CounterPlugin.scala | 5 ++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 85437240..e7242652 100644 --- a/README.md +++ b/README.md @@ -1326,6 +1326,12 @@ Speed up of 4 was observed in libressl running in linux. Date: Thu, 29 Feb 2024 15:40:03 +0100 Subject: [PATCH 16/19] better documentation --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index e7242652..26e2c66c 100644 --- a/README.md +++ b/README.md @@ -1337,3 +1337,4 @@ val ctrSrv = pipeline.service(classOf[CounterService]) ctrSrv.getCondition(eventId) := boolCond ``` eventId is BigInt, but only events between 0 and 2 ** XLEN (excluding boundaries) can be selected by cpu. +The configured counter counts clockcycles with boolCond asserted. From 7882b0fd0120a0c81b67afa68a8bd3ed8ead75db Mon Sep 17 00:00:00 2001 From: Jacob Tilger Date: Thu, 21 Mar 2024 13:19:45 +0100 Subject: [PATCH 17/19] Revert "removed counter config from demos" This reverts commit 20f638ea168769491c7a6699f2f36b211c1fd233. --- src/main/scala/vexriscv/demo/Briey.scala | 6 +++++- src/main/scala/vexriscv/demo/VexRiscvAhbLite3.scala | 6 +++++- .../scala/vexriscv/demo/VexRiscvAvalonForSim.scala | 6 +++++- .../demo/VexRiscvAvalonWithIntegratedJtag.scala | 6 +++++- .../vexriscv/demo/VexRiscvAxi4WithIntegratedJtag.scala | 6 +++++- .../scala/vexriscv/demo/smp/VexRiscvSmpCluster.scala | 9 ++++++++- src/test/scala/vexriscv/experimental/GenMicro.scala | 10 ++++++++-- 7 files changed, 41 insertions(+), 8 deletions(-) diff --git a/src/main/scala/vexriscv/demo/Briey.scala b/src/main/scala/vexriscv/demo/Briey.scala index 9d83b7c1..32e6d62e 100644 --- a/src/main/scala/vexriscv/demo/Briey.scala +++ b/src/main/scala/vexriscv/demo/Briey.scala @@ -146,8 +146,12 @@ object BrieyConfig{ mscratchGen = false, mcauseAccess = CsrAccess.READ_ONLY, mbadaddrAccess = CsrAccess.READ_ONLY, + mcycleAccess = CsrAccess.NONE, + minstretAccess = CsrAccess.NONE, ecallGen = false, - wfiGenAsWait = false + wfiGenAsWait = false, + ucycleAccess = CsrAccess.NONE, + uinstretAccess = CsrAccess.NONE ) ), new YamlPlugin("cpu0.yaml") diff --git a/src/main/scala/vexriscv/demo/VexRiscvAhbLite3.scala b/src/main/scala/vexriscv/demo/VexRiscvAhbLite3.scala index 1959beef..f817fb3b 100644 --- a/src/main/scala/vexriscv/demo/VexRiscvAhbLite3.scala +++ b/src/main/scala/vexriscv/demo/VexRiscvAhbLite3.scala @@ -122,8 +122,12 @@ object VexRiscvAhbLite3{ mscratchGen = false, mcauseAccess = CsrAccess.READ_ONLY, mbadaddrAccess = CsrAccess.READ_ONLY, + mcycleAccess = CsrAccess.NONE, + minstretAccess = CsrAccess.NONE, ecallGen = false, - wfiGenAsWait = false + wfiGenAsWait = false, + ucycleAccess = CsrAccess.NONE, + uinstretAccess = CsrAccess.NONE ) ), new YamlPlugin("cpu0.yaml") diff --git a/src/main/scala/vexriscv/demo/VexRiscvAvalonForSim.scala b/src/main/scala/vexriscv/demo/VexRiscvAvalonForSim.scala index f4f3dfc0..b2c3f69c 100644 --- a/src/main/scala/vexriscv/demo/VexRiscvAvalonForSim.scala +++ b/src/main/scala/vexriscv/demo/VexRiscvAvalonForSim.scala @@ -120,8 +120,12 @@ object VexRiscvAvalonForSim{ mscratchGen = false, mcauseAccess = CsrAccess.READ_ONLY, mbadaddrAccess = CsrAccess.READ_ONLY, + mcycleAccess = CsrAccess.NONE, + minstretAccess = CsrAccess.NONE, ecallGen = false, - wfiGenAsWait = false + wfiGenAsWait = false, + ucycleAccess = CsrAccess.NONE, + uinstretAccess = CsrAccess.NONE ) ), new YamlPlugin("cpu0.yaml") diff --git a/src/main/scala/vexriscv/demo/VexRiscvAvalonWithIntegratedJtag.scala b/src/main/scala/vexriscv/demo/VexRiscvAvalonWithIntegratedJtag.scala index c3911434..063d945a 100644 --- a/src/main/scala/vexriscv/demo/VexRiscvAvalonWithIntegratedJtag.scala +++ b/src/main/scala/vexriscv/demo/VexRiscvAvalonWithIntegratedJtag.scala @@ -117,8 +117,12 @@ object VexRiscvAvalonWithIntegratedJtag{ mscratchGen = false, mcauseAccess = CsrAccess.READ_ONLY, mbadaddrAccess = CsrAccess.READ_ONLY, + mcycleAccess = CsrAccess.NONE, + minstretAccess = CsrAccess.NONE, ecallGen = false, - wfiGenAsWait = false + wfiGenAsWait = false, + ucycleAccess = CsrAccess.NONE, + uinstretAccess = CsrAccess.NONE ) ), new YamlPlugin("cpu0.yaml") diff --git a/src/main/scala/vexriscv/demo/VexRiscvAxi4WithIntegratedJtag.scala b/src/main/scala/vexriscv/demo/VexRiscvAxi4WithIntegratedJtag.scala index 2409424f..67556e94 100644 --- a/src/main/scala/vexriscv/demo/VexRiscvAxi4WithIntegratedJtag.scala +++ b/src/main/scala/vexriscv/demo/VexRiscvAxi4WithIntegratedJtag.scala @@ -118,8 +118,12 @@ object VexRiscvAxi4WithIntegratedJtag{ mscratchGen = false, mcauseAccess = CsrAccess.READ_ONLY, mbadaddrAccess = CsrAccess.READ_ONLY, + mcycleAccess = CsrAccess.NONE, + minstretAccess = CsrAccess.NONE, ecallGen = false, - wfiGenAsWait = false + wfiGenAsWait = false, + ucycleAccess = CsrAccess.NONE, + uinstretAccess = CsrAccess.NONE ) ), new YamlPlugin("cpu0.yaml") diff --git a/src/main/scala/vexriscv/demo/smp/VexRiscvSmpCluster.scala b/src/main/scala/vexriscv/demo/smp/VexRiscvSmpCluster.scala index dd3d794e..6180651e 100644 --- a/src/main/scala/vexriscv/demo/smp/VexRiscvSmpCluster.scala +++ b/src/main/scala/vexriscv/demo/smp/VexRiscvSmpCluster.scala @@ -208,7 +208,11 @@ object VexRiscvSmpClusterGen { if(csrFull){ c = c.copy( mcauseAccess = CsrAccess.READ_WRITE, - mbadaddrAccess = CsrAccess.READ_WRITE + mbadaddrAccess = CsrAccess.READ_WRITE, + ucycleAccess = CsrAccess.READ_ONLY, + uinstretAccess = CsrAccess.READ_ONLY, + mcycleAccess = CsrAccess.READ_WRITE, + minstretAccess = CsrAccess.READ_WRITE ) } c @@ -228,10 +232,13 @@ object VexRiscvSmpClusterGen { mscratchGen = forceMscratch, mcauseAccess = CsrAccess.READ_ONLY, mbadaddrAccess = CsrAccess.READ_ONLY, + mcycleAccess = CsrAccess.NONE, + minstretAccess = CsrAccess.NONE, ecallGen = true, ebreakGen = true, wfiGenAsWait = false, wfiGenAsNop = true, + ucycleAccess = CsrAccess.NONE, withPrivilegedDebug = privilegedDebug ) } diff --git a/src/test/scala/vexriscv/experimental/GenMicro.scala b/src/test/scala/vexriscv/experimental/GenMicro.scala index 2b8968d2..90666a7a 100644 --- a/src/test/scala/vexriscv/experimental/GenMicro.scala +++ b/src/test/scala/vexriscv/experimental/GenMicro.scala @@ -93,10 +93,13 @@ object GenMicro extends App{ mscratchGen = false, mcauseAccess = CsrAccess.READ_ONLY, mbadaddrAccess = CsrAccess.NONE, + mcycleAccess = CsrAccess.NONE, + minstretAccess = CsrAccess.NONE, ecallGen = false, ebreakGen = false, wfiGenAsWait = false, wfiGenAsNop = false, + ucycleAccess = CsrAccess.NONE, noCsrAlu = true ) else CsrPluginConfig( catchIllegalAccess = false, @@ -112,10 +115,13 @@ object GenMicro extends App{ mscratchGen = true, mcauseAccess = CsrAccess.READ_ONLY, mbadaddrAccess = CsrAccess.READ_ONLY, + mcycleAccess = CsrAccess.NONE, + minstretAccess = CsrAccess.NONE, ecallGen = true, ebreakGen = true, wfiGenAsWait = false, - wfiGenAsNop = true + wfiGenAsNop = true, + ucycleAccess = CsrAccess.NONE ) ))) ) @@ -153,4 +159,4 @@ object GenMicroSynthesis { Bench(rtls, targets, "/eda/tmp/") } -} +} \ No newline at end of file From 7b520aa685bb0c19833383822210c1933a668c56 Mon Sep 17 00:00:00 2001 From: Dolu1990 Date: Fri, 22 Mar 2024 09:13:58 +0100 Subject: [PATCH 18/19] fix my bad conflict resolution --- src/main/scala/vexriscv/plugin/CsrPlugin.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/vexriscv/plugin/CsrPlugin.scala b/src/main/scala/vexriscv/plugin/CsrPlugin.scala index a0be7037..22015ec8 100644 --- a/src/main/scala/vexriscv/plugin/CsrPlugin.scala +++ b/src/main/scala/vexriscv/plugin/CsrPlugin.scala @@ -87,7 +87,7 @@ case class CsrPluginConfig( exportPrivilege : Boolean = false, var withPrivilegedDebug : Boolean = false, //For the official RISC-V debug spec implementation var debugTriggers : Int = 2, - var debugTriggersLsu : Boolean = false + var debugTriggersLsu : Boolean = false, // these options only have effect, when no CounterService is present in Pipeline utimeAccess : CsrAccess = CsrAccess.NONE, mcycleAccess : CsrAccess = CsrAccess.NONE, From 5148bbac17d19b9a5a25f4a0e99f60b24b4c70b6 Mon Sep 17 00:00:00 2001 From: Jacob Tilger Date: Fri, 22 Mar 2024 09:37:54 +0100 Subject: [PATCH 19/19] fixed broken conditional generation --- src/main/scala/vexriscv/plugin/CsrPlugin.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/vexriscv/plugin/CsrPlugin.scala b/src/main/scala/vexriscv/plugin/CsrPlugin.scala index 22015ec8..4e61236c 100644 --- a/src/main/scala/vexriscv/plugin/CsrPlugin.scala +++ b/src/main/scala/vexriscv/plugin/CsrPlugin.scala @@ -654,7 +654,7 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep pipeline.update(MPP, UInt(2 bits)) if(withExternalMhartid) externalMhartId = in UInt(mhartidWidth bits) - if(pipeline.serviceExist(classOf[CounterService]) && utimeAccess != CsrAccess.NONE) utime = in UInt(64 bits) setName("utime") + if(!pipeline.serviceExist(classOf[CounterService]) && utimeAccess != CsrAccess.NONE) utime = in UInt(64 bits) setName("utime") if(supervisorGen) { decoderService.addDefault(RESCHEDULE_NEXT, False)