CsrPlugin add API to implement CSR in a decoupled way. (very low level api) #174
This commit is contained in:
parent
72328e7bc4
commit
6066d8bc26
|
@ -344,8 +344,16 @@ case class CsrDuringWrite(doThat :() => Unit)
|
||||||
case class CsrDuringRead(doThat :() => Unit)
|
case class CsrDuringRead(doThat :() => Unit)
|
||||||
case class CsrDuring(doThat :() => Unit)
|
case class CsrDuring(doThat :() => Unit)
|
||||||
case class CsrOnRead(doThat : () => Unit)
|
case class CsrOnRead(doThat : () => Unit)
|
||||||
|
|
||||||
|
|
||||||
case class CsrMapping() extends CsrInterface{
|
case class CsrMapping() extends CsrInterface{
|
||||||
val mapping = mutable.LinkedHashMap[Int,ArrayBuffer[Any]]()
|
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
|
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 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))
|
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 during(csrAddress: Int)(body: => Unit): Unit = addMappingAt(csrAddress, CsrDuring(() => body))
|
||||||
override def onRead(csrAddress: Int)(body: => Unit): Unit = addMappingAt(csrAddress, CsrOnRead(() => {body}))
|
override def onRead(csrAddress: Int)(body: => Unit): Unit = addMappingAt(csrAddress, CsrOnRead(() => {body}))
|
||||||
override def duringAny(): Bool = ???
|
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)
|
r(csrAddress,bitOffset,that)
|
||||||
w(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
|
def r2w(csrAddress : Int, bitOffset : Int,that : Data): Unit
|
||||||
|
|
||||||
|
@ -396,6 +414,9 @@ trait CsrInterface{
|
||||||
}
|
}
|
||||||
ret
|
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 allowException : Bool = null
|
||||||
var allowEbreakException : Bool = null
|
var allowEbreakException : Bool = null
|
||||||
|
|
||||||
val csrMapping = new CsrMapping()
|
var csrMapping : CsrMapping = null
|
||||||
|
|
||||||
//Print CSR mapping
|
//Print CSR mapping
|
||||||
def printCsr() {
|
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 duringRead(csrAddress: Int)(body: => Unit): Unit = csrMapping.duringRead(csrAddress)(body)
|
||||||
override def during(csrAddress: Int)(body: => Unit): Unit = csrMapping.during(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 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 = {
|
override def setup(pipeline: VexRiscv): Unit = {
|
||||||
import pipeline.config._
|
import pipeline.config._
|
||||||
|
|
||||||
|
csrMapping = new CsrMapping()
|
||||||
|
|
||||||
inWfi = False.addTag(Verilator.public)
|
inWfi = False.addTag(Verilator.public)
|
||||||
|
|
||||||
thirdPartyWake = False
|
thirdPartyWake = False
|
||||||
|
@ -1110,17 +1139,19 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep
|
||||||
|
|
||||||
val imm = IMM(input(INSTRUCTION))
|
val imm = IMM(input(INSTRUCTION))
|
||||||
def writeSrc = input(SRC1)
|
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 writeInstruction = arbitration.isValid && input(IS_CSR) && input(CSR_WRITE_OPCODE)
|
||||||
val readInstruction = arbitration.isValid && input(IS_CSR) && input(CSR_READ_OPCODE)
|
val readInstruction = arbitration.isValid && input(IS_CSR) && input(CSR_READ_OPCODE)
|
||||||
val writeEnable = writeInstruction && !arbitration.isStuck
|
val writeEnable = writeInstruction && !arbitration.isStuck
|
||||||
val readEnable = readInstruction && !arbitration.isStuck
|
val readEnable = readInstruction && !arbitration.isStuck
|
||||||
|
csrMapping.hazardFree := !blockedBySideEffects
|
||||||
|
|
||||||
val readToWriteData = CombInit(readData)
|
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,
|
False -> writeSrc,
|
||||||
True -> Mux(input(INSTRUCTION)(12), readToWriteData & ~writeSrc, readToWriteData | writeSrc)
|
True -> Mux(input(INSTRUCTION)(12), readToWriteData & ~writeSrc, readToWriteData | writeSrc)
|
||||||
)
|
))
|
||||||
|
|
||||||
when(arbitration.isValid && input(IS_CSR)) {
|
when(arbitration.isValid && input(IS_CSR)) {
|
||||||
if(!pipelineCsrRead) output(REGFILE_WRITE_DATA) := readData
|
if(!pipelineCsrRead) output(REGFILE_WRITE_DATA) := readData
|
||||||
|
@ -1185,13 +1216,13 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep
|
||||||
|
|
||||||
csrOhDecoder match {
|
csrOhDecoder match {
|
||||||
case false => {
|
case false => {
|
||||||
readData := 0
|
csrMapping.readDataInit := 0
|
||||||
switch(csrAddress) {
|
switch(csrAddress) {
|
||||||
for ((address, jobs) <- csrMapping.mapping) {
|
for ((address, jobs) <- csrMapping.mapping) {
|
||||||
is(address) {
|
is(address) {
|
||||||
doJobs(jobs)
|
doJobs(jobs)
|
||||||
for (element <- jobs) element match {
|
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 _ =>
|
case _ =>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1221,7 +1252,7 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep
|
||||||
readDatas += masked
|
readDatas += masked
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
readData := readDatas.reduceBalancedTree(_ | _)
|
csrMapping.readDataInit := readDatas.reduceBalancedTree(_ | _)
|
||||||
for ((address, jobs) <- csrMapping.mapping) {
|
for ((address, jobs) <- csrMapping.mapping) {
|
||||||
when(oh(address)){
|
when(oh(address)){
|
||||||
doJobsOverride(jobs)
|
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){
|
when(privilege < csrAddress(9 downto 8).asUInt){
|
||||||
illegalAccess := True
|
illegalAccess := True
|
||||||
readInstruction := False
|
readInstruction := False
|
||||||
|
|
Loading…
Reference in New Issue