FpuPlugin.access port added

Privileged debug access added
This commit is contained in:
Charles Papon 2023-03-10 14:44:14 +08:00
parent 6be1531d36
commit 94f19032f0
4 changed files with 141 additions and 18 deletions

View File

@ -53,6 +53,8 @@ case class VexRiscvConfig(){
case None => false case None => false
} }
def FLEN = if(withRvd) 64 else if(withRvf) 32 else 0
//Default Stageables //Default Stageables
object IS_RVC extends Stageable(Bool) object IS_RVC extends Stageable(Bool)
object BYPASSABLE_EXECUTE_STAGE extends Stageable(Bool) object BYPASSABLE_EXECUTE_STAGE extends Stageable(Bool)

View File

@ -645,6 +645,8 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep
xretAwayFromMachine = False xretAwayFromMachine = False
if(pipeline.config.FLEN == 64) pipeline.service(classOf[FpuPlugin]).requireAccessPort()
injectionPort = withPrivilegedDebug generate pipeline.service(classOf[IBusFetcher]).getInjectionPort().setCompositeName(this, "injectionPort") injectionPort = withPrivilegedDebug generate pipeline.service(classOf[IBusFetcher]).getInjectionPort().setCompositeName(this, "injectionPort")
debugMode = withPrivilegedDebug generate Bool().setName("debugMode") debugMode = withPrivilegedDebug generate Bool().setName("debugMode")
debugBus = withPrivilegedDebug generate slave(DebugHartBus()).setName("debugBus") debugBus = withPrivilegedDebug generate slave(DebugHartBus()).setName("debugBus")
@ -727,35 +729,58 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep
timeout.clear() timeout.clear()
} }
val inject = new Area{
val cmd = bus.dmToHart.translateWith(bus.dmToHart.data).takeWhen(bus.dmToHart.op === DebugDmToHartOp.EXECUTE)
injectionPort << cmd.toStream.stage
val pending = RegInit(False) setWhen(cmd.valid) clearWhen(bus.exception || bus.commit || bus.ebreak || bus.redo)
when(cmd.valid){ timeout.clear() }
bus.redo := pending && timeout.state
}
val dataCsrr = new Area{ val dataCsrr = new Area{
bus.hartToDm.valid := isWriting(DebugModule.CSR_DATA) bus.hartToDm.valid := isWriting(DebugModule.CSR_DATA)
bus.hartToDm.address := 0 bus.hartToDm.address := 0
bus.hartToDm.data := execute.input(SRC1) bus.hartToDm.data := execute.input(SRC1)
} }
val withDebugFpuAccess = pipeline.config.FLEN == 64
val dataCsrw = new Area{ val dataCsrw = new Area{
val value = Reg(Bits(32 bits)) val value = Vec.fill(1+withDebugFpuAccess.toInt)(Reg(Bits(32 bits)))
val fromDm = new Area{ val fromDm = new Area{
when(bus.dmToHart.valid && bus.dmToHart.op === DebugDmToHartOp.DATA){ when(bus.dmToHart.valid && bus.dmToHart.op === DebugDmToHartOp.DATA){
value := bus.dmToHart.data value(bus.dmToHart.address.resized) := bus.dmToHart.data
} }
} }
val toHart = new Area{ val toHart = new Area{
r(DebugModule.CSR_DATA, value) r(DebugModule.CSR_DATA, value(0))
} }
} }
val inject = new Area{
val cmd = bus.dmToHart.takeWhen(bus.dmToHart.op === DebugDmToHartOp.EXECUTE || bus.dmToHart.op === DebugDmToHartOp.REG_READ || bus.dmToHart.op === DebugDmToHartOp.REG_WRITE)
val buffer = cmd.toStream.stage
injectionPort.valid := buffer.valid && buffer.op === DebugDmToHartOp.EXECUTE
injectionPort.payload := buffer.data
buffer.ready := injectionPort.fire
val fpu = withDebugFpuAccess generate new Area {
val access = service(classOf[FpuPlugin]).access
access.start := buffer.valid && buffer.op === DebugDmToHartOp.REG_READ || buffer.op === DebugDmToHartOp.REG_WRITE
access.regId := buffer.address
access.write := buffer.op === DebugDmToHartOp.REG_WRITE
access.writeData := dataCsrw.value.take(2).asBits
access.size := buffer.size
when(access.readDataValid) {
bus.hartToDm.valid := True
bus.hartToDm.address := access.readDataChunk.resized
bus.hartToDm.data := access.readData
}
bus.regSuccess := access.done
buffer.ready setWhen(access.done)
}
if(!withDebugFpuAccess) bus.regSuccess := False
val pending = RegInit(False) setWhen(cmd.valid && bus.dmToHart.op === DebugDmToHartOp.EXECUTE) clearWhen(bus.exception || bus.commit || bus.ebreak || bus.redo)
when(cmd.valid){ timeout.clear() }
bus.redo := pending && timeout.state
}
val dpc = Reg(UInt(32 bits)) val dpc = Reg(UInt(32 bits))
val dcsr = new Area{ val dcsr = new Area{
rw(CSR.DPC, dpc) rw(CSR.DPC, dpc)

View File

@ -42,8 +42,12 @@ class EmbeddedRiscvJtag(var p : DebugTransportModuleParameter,
version = p.version + 1, version = p.version + 1,
harts = 1, harts = 1,
progBufSize = 2, progBufSize = 2,
datacount = XLEN/32, datacount = (XLEN max pipeline.config.FLEN)/32,
xlens = List(XLEN) hartsConfig = List(DebugModuleCpuConfig(
xlen = XLEN,
flen = pipeline.config.FLEN,
withFpuRegAccess = pipeline.config.FLEN == 64
))
) )
) )

View File

@ -3,12 +3,25 @@ package vexriscv.plugin
import spinal.core._ import spinal.core._
import spinal.core.internals.{BoolLiteral, Literal} import spinal.core.internals.{BoolLiteral, Literal}
import spinal.lib._ import spinal.lib._
import spinal.lib.fsm._
import vexriscv._ import vexriscv._
import vexriscv.Riscv._ import vexriscv.Riscv._
import vexriscv.ip.fpu._ import vexriscv.ip.fpu._
import scala.collection.mutable.ArrayBuffer import scala.collection.mutable.ArrayBuffer
class FpuAcessPort(val p : FpuParameter) extends Bundle{
val start = Bool()
val regId = UInt(5 bits)
val size = UInt(3 bits)
val write = Bool()
val writeData = p.storeLoadType()
val readData = Bits(32 bits)
val readDataValid = Bool()
val readDataChunk = UInt(1 bits)
val done = Bool()
}
class FpuPlugin(externalFpu : Boolean = false, class FpuPlugin(externalFpu : Boolean = false,
simHalt : Boolean = false, simHalt : Boolean = false,
val p : FpuParameter) extends Plugin[VexRiscv] with VexRiscvRegressionArg { val p : FpuParameter) extends Plugin[VexRiscv] with VexRiscvRegressionArg {
@ -24,6 +37,11 @@ class FpuPlugin(externalFpu : Boolean = false,
object FPU_FORMAT extends Stageable(FpuFormat()) object FPU_FORMAT extends Stageable(FpuFormat())
var port : FpuPort = null //Commit port is already isolated var port : FpuPort = null //Commit port is already isolated
var access : FpuAcessPort = null //Meant to be used for debuging features only
def requireAccessPort(): Unit = {
access = new FpuAcessPort(p).setName("fpuAccess")
}
override def getVexRiscvRegressionArgs(): Seq[String] = { override def getVexRiscvRegressionArgs(): Seq[String] = {
var args = List[String]() var args = List[String]()
@ -161,8 +179,6 @@ class FpuPlugin(externalFpu : Boolean = false,
dBusEncoding.addLoadWordEncoding(FLD) dBusEncoding.addLoadWordEncoding(FLD)
dBusEncoding.addStoreWordEncoding(FSD) dBusEncoding.addStoreWordEncoding(FSD)
} }
// exposeEncoding()
} }
override def build(pipeline: VexRiscv): Unit = { override def build(pipeline: VexRiscv): Unit = {
@ -239,6 +255,7 @@ class FpuPlugin(externalFpu : Boolean = false,
} }
} }
val inAccess = False
decode plug new Area{ decode plug new Area{
import decode._ import decode._
@ -248,7 +265,7 @@ class FpuPlugin(externalFpu : Boolean = false,
} }
//Maybe it might be better to not fork before fire to avoid RF stall on commits //Maybe it might be better to not fork before fire to avoid RF stall on commits
val forked = Reg(Bool) setWhen(port.cmd.fire) clearWhen(!arbitration.isStuck) init(False) val forked = Reg(Bool) setWhen(port.cmd.fire && !inAccess) clearWhen(!arbitration.isStuck) init(False)
val hazard = csr.pendings.msb || csr.csrActive || csr.fs === 0 && !csrService.inDebugMode() val hazard = csr.pendings.msb || csr.csrActive || csr.fs === 0 && !csrService.inDebugMode()
@ -269,7 +286,7 @@ class FpuPlugin(externalFpu : Boolean = false,
port.cmd.format := (if(p.withDouble) input(FPU_FORMAT) else FpuFormat.FLOAT()) port.cmd.format := (if(p.withDouble) input(FPU_FORMAT) else FpuFormat.FLOAT())
port.cmd.roundMode := roundMode.as(FpuRoundMode()) port.cmd.roundMode := roundMode.as(FpuRoundMode())
insert(FPU_FORKED) := forked || port.cmd.fire insert(FPU_FORKED) := forked || port.cmd.fire && !inAccess
insert(FPU_COMMIT_SYNC) := List(FpuOpcode.LOAD, FpuOpcode.FMV_W_X, FpuOpcode.I2F).map(_ === input(FPU_OPCODE)).orR insert(FPU_COMMIT_SYNC) := List(FpuOpcode.LOAD, FpuOpcode.FMV_W_X, FpuOpcode.I2F).map(_ === input(FPU_OPCODE)).orR
insert(FPU_COMMIT_LOAD) := input(FPU_OPCODE) === FpuOpcode.LOAD insert(FPU_COMMIT_LOAD) := input(FPU_OPCODE) === FpuOpcode.LOAD
@ -326,6 +343,81 @@ class FpuPlugin(externalFpu : Boolean = false,
port.commit << commit.pipelined(s2m = true, m2s = false) port.commit << commit.pipelined(s2m = true, m2s = false)
} }
if(access != null) pipeline plug new StateMachine{
val IDLE, CMD, RSP, RSP_0, RSP_1, COMMIT, DONE = State()
setEntry(IDLE)
inAccess setWhen(!this.isActive(IDLE))
IDLE.whenIsActive{
when(access.start){
goto(CMD)
}
}
CMD.whenIsActive{
port.cmd.valid := True
port.cmd.rs2 := access.regId
port.cmd.rd := access.regId
port.cmd.format := access.size.muxListDc(List(
2 -> FpuFormat.FLOAT(),
3 -> FpuFormat.DOUBLE()
))
when(access.write) {
port.cmd.opcode := FpuOpcode.LOAD
when(port.cmd.ready){
goto(COMMIT)
}
} otherwise {
port.cmd.opcode := FpuOpcode.STORE
when(port.cmd.ready){
goto(RSP)
}
}
}
access.done := False
COMMIT.whenIsActive{
port.commit.valid := True
port.commit.opcode := FpuOpcode.LOAD
port.commit.rd := access.regId
port.commit.write := True
port.commit.value := access.writeData
when(port.commit.ready){
goto(DONE)
}
}
access.readDataValid := False
access.readDataChunk.assignDontCare()
access.readData.assignDontCare()
RSP.whenIsActive {
when(port.rsp.valid) {
goto(RSP_0)
}
}
RSP_0.whenIsActive {
access.readDataValid := True
access.readDataChunk := 0
access.readData := port.rsp.value(31 downto 0)
when(access.size > 2) {
goto(RSP_1)
} otherwise {
goto(DONE)
}
}
RSP_1.whenIsActive {
access.readDataValid := True
access.readDataChunk := 1
access.readData := port.rsp.value(63 downto 32)
goto(DONE)
}
DONE whenIsActive{
port.rsp.ready := True
access.done := True
goto(IDLE)
}
}
pipeline.stages.dropRight(1).foreach(s => s.output(FPU_FORKED) clearWhen(s.arbitration.isStuck)) pipeline.stages.dropRight(1).foreach(s => s.output(FPU_FORKED) clearWhen(s.arbitration.isStuck))
Component.current.afterElaboration{ Component.current.afterElaboration{