From a7d148d0ff5e22a68b5931dbb949a82bd8803c11 Mon Sep 17 00:00:00 2001 From: Dolu1990 Date: Tue, 19 Jan 2021 15:53:11 +0100 Subject: [PATCH] fpu add vex csr --- src/main/scala/vexriscv/Riscv.scala | 6 ++-- src/main/scala/vexriscv/ip/fpu/FpuCore.scala | 8 ++--- .../scala/vexriscv/ip/fpu/Interface.scala | 2 +- .../scala/vexriscv/plugin/CsrPlugin.scala | 15 +++++++++ .../scala/vexriscv/plugin/FpuPlugin.scala | 33 +++++++++++++++++-- 5 files changed, 54 insertions(+), 10 deletions(-) diff --git a/src/main/scala/vexriscv/Riscv.scala b/src/main/scala/vexriscv/Riscv.scala index df49682..e22b324 100644 --- a/src/main/scala/vexriscv/Riscv.scala +++ b/src/main/scala/vexriscv/Riscv.scala @@ -221,12 +221,14 @@ object Riscv{ val SIP = 0x144 val SATP = 0x180 - - def UCYCLE = 0xC00 // UR Machine ucycle counter. def UCYCLEH = 0xC80 def UTIME = 0xC01 // rdtime def UTIMEH = 0xC81 + val FFLAGS = 0x1 + val FRM = 0x2 + val FCSR = 0x3 + } } diff --git a/src/main/scala/vexriscv/ip/fpu/FpuCore.scala b/src/main/scala/vexriscv/ip/fpu/FpuCore.scala index ca297f8..56c0fab 100644 --- a/src/main/scala/vexriscv/ip/fpu/FpuCore.scala +++ b/src/main/scala/vexriscv/ip/fpu/FpuCore.scala @@ -629,6 +629,10 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{ val isCommited = rf.lock.map(_.commited).read(arbitrated.lockId) val commited = arbitrated.haltWhen(!isCommited).toFlow + for(i <- 0 until portCount){ + completion(i).increments += (RegNext(commited.fire && commited.source === i) init(False)) + } + when(commited.valid){ for(i <- 0 until rfLockCount) when(commited.lockId === i){ rf.lock(i).valid := False @@ -639,10 +643,6 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{ port.valid := commited.valid && rf.lock.map(_.write).read(commited.lockId) port.address := commited.source @@ commited.rd port.data := commited.value - - for(i <- 0 until portCount){ - completion(i).increments += (RegNext(port.fire && commited.source === i) init(False)) - } } } diff --git a/src/main/scala/vexriscv/ip/fpu/Interface.scala b/src/main/scala/vexriscv/ip/fpu/Interface.scala index a83d5f6..255f9cb 100644 --- a/src/main/scala/vexriscv/ip/fpu/Interface.scala +++ b/src/main/scala/vexriscv/ip/fpu/Interface.scala @@ -53,7 +53,7 @@ case class FpuParameter( internalMantissaSize : Int, } case class FpuFlags() extends Bundle{ - val NV, DZ, OF, UF, NX = Bool() + val NX, UF, OF, DZ, NV = Bool() } case class FpuCompletion() extends Bundle{ diff --git a/src/main/scala/vexriscv/plugin/CsrPlugin.scala b/src/main/scala/vexriscv/plugin/CsrPlugin.scala index 7eee653..f11abbf 100644 --- a/src/main/scala/vexriscv/plugin/CsrPlugin.scala +++ b/src/main/scala/vexriscv/plugin/CsrPlugin.scala @@ -307,6 +307,8 @@ case class CsrRead(that : Data , bitOffset : Int) case class CsrReadToWriteOverride(that : Data, bitOffset : Int) //Used for special cases, as MIP where there shadow stuff case class CsrOnWrite(doThat :() => Unit) 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]]() @@ -316,7 +318,10 @@ case class CsrMapping() extends CsrInterface{ override def r2w(csrAddress : Int, bitOffset : Int, that : Data): Unit = addMappingAt(csrAddress, CsrReadToWriteOverride(that,bitOffset)) override def onWrite(csrAddress: Int)(body: => Unit): Unit = addMappingAt(csrAddress, CsrOnWrite(() => body)) override def duringWrite(csrAddress: Int)(body: => Unit): Unit = addMappingAt(csrAddress, CsrDuringWrite(() => body)) + override def duringRead(csrAddress: Int)(body: => Unit): Unit = addMappingAt(csrAddress, CsrDuringRead(() => 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 duringAny(): Bool = ??? } @@ -324,6 +329,9 @@ trait CsrInterface{ def onWrite(csrAddress : Int)(doThat : => Unit) : Unit def onRead(csrAddress : Int)(doThat : => Unit) : Unit def duringWrite(csrAddress: Int)(body: => Unit): Unit + def duringRead(csrAddress: Int)(body: => Unit): Unit + def during(csrAddress: Int)(body: => Unit): Unit + def duringAny(): Bool def r(csrAddress : Int, bitOffset : Int, that : Data): Unit def w(csrAddress : Int, bitOffset : Int, that : Data): Unit def rw(csrAddress : Int, bitOffset : Int,that : Data): Unit ={ @@ -380,6 +388,8 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep interface } + + var exceptionPendings : Vec[Bool] = null override def isExceptionPending(stage : Stage): Bool = exceptionPendings(pipeline.stages.indexOf(stage)) @@ -446,6 +456,9 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep override def onWrite(csrAddress: Int)(body: => Unit): Unit = csrMapping.onWrite(csrAddress)(body) override def duringWrite(csrAddress: Int)(body: => Unit): Unit = csrMapping.duringWrite(csrAddress)(body) override def onRead(csrAddress: Int)(body: => Unit): Unit = csrMapping.onRead(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 duringAny(): Bool = pipeline.execute.arbitration.isValid && pipeline.execute.input(IS_CSR) override def setup(pipeline: VexRiscv): Unit = { import pipeline.config._ @@ -1102,6 +1115,8 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep for (element <- jobs) element match { case element : CsrDuringWrite => when(writeInstruction){element.doThat()} + case element : CsrDuringRead => when(readInstruction){element.doThat()} + case element : CsrDuring => {element.doThat()} case _ => } when(writeEnable) { diff --git a/src/main/scala/vexriscv/plugin/FpuPlugin.scala b/src/main/scala/vexriscv/plugin/FpuPlugin.scala index 7b55ef3..adac48c 100644 --- a/src/main/scala/vexriscv/plugin/FpuPlugin.scala +++ b/src/main/scala/vexriscv/plugin/FpuPlugin.scala @@ -44,15 +44,42 @@ class FpuPlugin(externalFpu : Boolean = false, override def build(pipeline: VexRiscv): Unit = { import pipeline._ import pipeline.config._ + import Riscv._ val internal = !externalFpu generate pipeline plug new Area{ val fpu = FpuCore(1, p) fpu.io.port(0).cmd << port.cmd fpu.io.port(0).commit << port.commit fpu.io.port(0).rsp >> port.rsp + fpu.io.port(0).completion <> port.completion } + val csr = pipeline plug new Area{ + val pendings = Reg(UInt(5 bits)) init(0) + pendings := pendings + U(port.cmd.fire) - port.completion.count + + val hasPending = pendings =/= 0 + + val flags = Reg(FpuFlags()) + flags.NV init(False) setWhen(port.completion.flag.NV) + flags.DZ init(False) setWhen(port.completion.flag.DZ) + flags.OF init(False) setWhen(port.completion.flag.OF) + flags.UF init(False) setWhen(port.completion.flag.UF) + flags.NX init(False) setWhen(port.completion.flag.NX) + + val service = pipeline.service(classOf[CsrInterface]) + val rm = Reg(Bits(3 bits)) + + service.rw(CSR.FCSR, 5,rm) + service.rw(CSR.FCSR, 0, flags) + service.rw(CSR.FRM, 5,rm) + service.rw(CSR.FFLAGS, 0,flags) + + val csrActive = service.duringAny() + execute.arbitration.haltByOther setWhen(csrActive && hasPending) // pessimistic + } + decode plug new Area{ import decode._ @@ -60,12 +87,12 @@ class FpuPlugin(externalFpu : Boolean = false, val forked = Reg(Bool) setWhen(port.cmd.fire) clearWhen(!arbitration.isStuck) init(False) val i2fReady = Reg(Bool()) setWhen(!arbitration.isStuckByOthers) clearWhen(!arbitration.isStuck) - val i2fHazard = input(FPU_OPCODE) === FpuOpcode.I2F && !i2fReady + val hazard = input(FPU_OPCODE) === FpuOpcode.I2F && !i2fReady || csr.pendings.msb || csr.csrActive - arbitration.haltItself setWhen(arbitration.isValid && i2fHazard) + arbitration.haltItself setWhen(arbitration.isValid && hazard) arbitration.haltItself setWhen(port.cmd.isStall) - port.cmd.valid := arbitration.isValid && input(FPU_ENABLE) && !forked && !i2fHazard + port.cmd.valid := arbitration.isValid && input(FPU_ENABLE) && !forked && !hazard port.cmd.opcode := input(FPU_OPCODE) port.cmd.value := RegNext(output(RS1)) port.cmd.function := 0