From 6066d8bc26a8dff72dd94a698575150fff4c850b Mon Sep 17 00:00:00 2001 From: Dolu1990 Date: Wed, 26 May 2021 11:44:46 +0200 Subject: [PATCH] CsrPlugin add API to implement CSR in a decoupled way. (very low level api) #174 --- .../scala/vexriscv/plugin/CsrPlugin.scala | 52 ++++++++++++++++--- 1 file changed, 45 insertions(+), 7 deletions(-) diff --git a/src/main/scala/vexriscv/plugin/CsrPlugin.scala b/src/main/scala/vexriscv/plugin/CsrPlugin.scala index c2d795c..a961938 100644 --- a/src/main/scala/vexriscv/plugin/CsrPlugin.scala +++ b/src/main/scala/vexriscv/plugin/CsrPlugin.scala @@ -344,8 +344,16 @@ case class CsrDuringWrite(doThat :() => Unit) case class CsrDuringRead(doThat :() => Unit) case class CsrDuring(doThat :() => Unit) case class CsrOnRead(doThat : () => Unit) + + case class CsrMapping() extends CsrInterface{ val mapping = mutable.LinkedHashMap[Int,ArrayBuffer[Any]]() + val always = ArrayBuffer[Any]() + val readDataSignal, readDataInit, writeDataSignal = Bits(32 bits) + val allowCsrSignal = False + val hazardFree = Bool() + + readDataSignal := readDataInit def addMappingAt(address : Int,that : Any) = mapping.getOrElseUpdate(address,new ArrayBuffer[Any]) += that override def r(csrAddress : Int, bitOffset : Int, that : Data): Unit = addMappingAt(csrAddress, CsrRead(that,bitOffset)) override def w(csrAddress : Int, bitOffset : Int, that : Data): Unit = addMappingAt(csrAddress, CsrWrite(that,bitOffset)) @@ -356,6 +364,12 @@ case class CsrMapping() extends CsrInterface{ override def during(csrAddress: Int)(body: => Unit): Unit = addMappingAt(csrAddress, CsrDuring(() => body)) override def onRead(csrAddress: Int)(body: => Unit): Unit = addMappingAt(csrAddress, CsrOnRead(() => {body})) override def duringAny(): Bool = ??? + override def durringWrite(body: => Unit) : Unit = always += CsrDuringRead(() => body) + override def durringRead(body: => Unit) : Unit = always += CsrDuringWrite(() => body) + override def readData() = readDataSignal + override def writeData() = writeDataSignal + override def allowCsr() = allowCsrSignal := True + override def isHazardFree() = hazardFree } @@ -372,6 +386,10 @@ trait CsrInterface{ r(csrAddress,bitOffset,that) w(csrAddress,bitOffset,that) } + def durringWrite(body: => Unit) : Unit //Called all the durration of a Csr write instruction in the execute stage + def durringRead(body: => Unit) : Unit //same than above for read + def allowCsr() : Unit //In case your csr do not use the regular API with csrAddress but is implemented using "side channels", you can call that if the current csr is implemented + def isHazardFree() : Bool // You should not have any side effect nor use readData() until this return True def r2w(csrAddress : Int, bitOffset : Int,that : Data): Unit @@ -396,6 +414,9 @@ trait CsrInterface{ } ret } + + def readData() : Bits //Return the 32 bits internal signal of the CsrPlugin for you to override (if you want) + def writeData() : Bits //Return the 32 bits value that the CsrPlugin want to write in the CSR (depend on readData combinatorialy) } @@ -461,7 +482,7 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep var allowException : Bool = null var allowEbreakException : Bool = null - val csrMapping = new CsrMapping() + var csrMapping : CsrMapping = null //Print CSR mapping def printCsr() { @@ -494,10 +515,18 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep override def duringRead(csrAddress: Int)(body: => Unit): Unit = csrMapping.duringRead(csrAddress)(body) override def during(csrAddress: Int)(body: => Unit): Unit = csrMapping.during(csrAddress)(body) override def duringAny(): Bool = pipeline.execute.arbitration.isValid && pipeline.execute.input(IS_CSR) + override def durringWrite(body: => Unit) = csrMapping.durringWrite(body) + override def durringRead(body: => Unit) = csrMapping.durringRead(body) + override def allowCsr() = csrMapping.allowCsr() + override def readData() = csrMapping.readData() + override def writeData() = csrMapping.writeData() + override def isHazardFree() = csrMapping.isHazardFree() override def setup(pipeline: VexRiscv): Unit = { import pipeline.config._ + csrMapping = new CsrMapping() + inWfi = False.addTag(Verilator.public) thirdPartyWake = False @@ -1110,17 +1139,19 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep val imm = IMM(input(INSTRUCTION)) def writeSrc = input(SRC1) - val readData = Bits(32 bits) + def readData = csrMapping.readDataSignal + def writeData = csrMapping.writeDataSignal val writeInstruction = arbitration.isValid && input(IS_CSR) && input(CSR_WRITE_OPCODE) val readInstruction = arbitration.isValid && input(IS_CSR) && input(CSR_READ_OPCODE) val writeEnable = writeInstruction && !arbitration.isStuck val readEnable = readInstruction && !arbitration.isStuck + csrMapping.hazardFree := !blockedBySideEffects val readToWriteData = CombInit(readData) - val writeData = if(noCsrAlu) writeSrc else input(INSTRUCTION)(13).mux( + writeData := (if(noCsrAlu) writeSrc else input(INSTRUCTION)(13).mux( False -> writeSrc, True -> Mux(input(INSTRUCTION)(12), readToWriteData & ~writeSrc, readToWriteData | writeSrc) - ) + )) when(arbitration.isValid && input(IS_CSR)) { if(!pipelineCsrRead) output(REGFILE_WRITE_DATA) := readData @@ -1185,13 +1216,13 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep csrOhDecoder match { case false => { - readData := 0 + csrMapping.readDataInit := 0 switch(csrAddress) { for ((address, jobs) <- csrMapping.mapping) { is(address) { doJobs(jobs) for (element <- jobs) element match { - case element: CsrRead if element.that.getBitsWidth != 0 => readData(element.bitOffset, element.that.getBitsWidth bits) := element.that.asBits + case element: CsrRead if element.that.getBitsWidth != 0 => csrMapping.readDataInit (element.bitOffset, element.that.getBitsWidth bits) := element.that.asBits case _ => } } @@ -1221,7 +1252,7 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep readDatas += masked } } - readData := readDatas.reduceBalancedTree(_ | _) + csrMapping.readDataInit := readDatas.reduceBalancedTree(_ | _) for ((address, jobs) <- csrMapping.mapping) { when(oh(address)){ doJobsOverride(jobs) @@ -1230,6 +1261,13 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep } } + csrMapping.always.foreach { + case element : CsrDuringWrite => when(writeInstruction){element.doThat()} + case element : CsrDuringRead => when(readInstruction){element.doThat()} + } + + illegalAccess clearWhen(csrMapping.allowCsrSignal) + when(privilege < csrAddress(9 downto 8).asUInt){ illegalAccess := True readInstruction := False