FpuPlugin.access port added
Privileged debug access added
This commit is contained in:
parent
6be1531d36
commit
94f19032f0
|
@ -53,6 +53,8 @@ case class VexRiscvConfig(){
|
|||
case None => false
|
||||
}
|
||||
|
||||
def FLEN = if(withRvd) 64 else if(withRvf) 32 else 0
|
||||
|
||||
//Default Stageables
|
||||
object IS_RVC extends Stageable(Bool)
|
||||
object BYPASSABLE_EXECUTE_STAGE extends Stageable(Bool)
|
||||
|
|
|
@ -645,6 +645,8 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep
|
|||
|
||||
xretAwayFromMachine = False
|
||||
|
||||
if(pipeline.config.FLEN == 64) pipeline.service(classOf[FpuPlugin]).requireAccessPort()
|
||||
|
||||
injectionPort = withPrivilegedDebug generate pipeline.service(classOf[IBusFetcher]).getInjectionPort().setCompositeName(this, "injectionPort")
|
||||
debugMode = withPrivilegedDebug generate Bool().setName("debugMode")
|
||||
debugBus = withPrivilegedDebug generate slave(DebugHartBus()).setName("debugBus")
|
||||
|
@ -727,35 +729,58 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep
|
|||
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{
|
||||
bus.hartToDm.valid := isWriting(DebugModule.CSR_DATA)
|
||||
bus.hartToDm.address := 0
|
||||
bus.hartToDm.data := execute.input(SRC1)
|
||||
}
|
||||
|
||||
val withDebugFpuAccess = pipeline.config.FLEN == 64
|
||||
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{
|
||||
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{
|
||||
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 dcsr = new Area{
|
||||
rw(CSR.DPC, dpc)
|
||||
|
|
|
@ -42,8 +42,12 @@ class EmbeddedRiscvJtag(var p : DebugTransportModuleParameter,
|
|||
version = p.version + 1,
|
||||
harts = 1,
|
||||
progBufSize = 2,
|
||||
datacount = XLEN/32,
|
||||
xlens = List(XLEN)
|
||||
datacount = (XLEN max pipeline.config.FLEN)/32,
|
||||
hartsConfig = List(DebugModuleCpuConfig(
|
||||
xlen = XLEN,
|
||||
flen = pipeline.config.FLEN,
|
||||
withFpuRegAccess = pipeline.config.FLEN == 64
|
||||
))
|
||||
)
|
||||
)
|
||||
|
||||
|
|
|
@ -3,12 +3,25 @@ package vexriscv.plugin
|
|||
import spinal.core._
|
||||
import spinal.core.internals.{BoolLiteral, Literal}
|
||||
import spinal.lib._
|
||||
import spinal.lib.fsm._
|
||||
import vexriscv._
|
||||
import vexriscv.Riscv._
|
||||
import vexriscv.ip.fpu._
|
||||
|
||||
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,
|
||||
simHalt : Boolean = false,
|
||||
val p : FpuParameter) extends Plugin[VexRiscv] with VexRiscvRegressionArg {
|
||||
|
@ -24,6 +37,11 @@ class FpuPlugin(externalFpu : Boolean = false,
|
|||
object FPU_FORMAT extends Stageable(FpuFormat())
|
||||
|
||||
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] = {
|
||||
var args = List[String]()
|
||||
|
@ -161,8 +179,6 @@ class FpuPlugin(externalFpu : Boolean = false,
|
|||
dBusEncoding.addLoadWordEncoding(FLD)
|
||||
dBusEncoding.addStoreWordEncoding(FSD)
|
||||
}
|
||||
|
||||
// exposeEncoding()
|
||||
}
|
||||
|
||||
override def build(pipeline: VexRiscv): Unit = {
|
||||
|
@ -239,6 +255,7 @@ class FpuPlugin(externalFpu : Boolean = false,
|
|||
}
|
||||
}
|
||||
|
||||
val inAccess = False
|
||||
decode plug new Area{
|
||||
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
|
||||
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()
|
||||
|
||||
|
@ -269,7 +286,7 @@ class FpuPlugin(externalFpu : Boolean = false,
|
|||
port.cmd.format := (if(p.withDouble) input(FPU_FORMAT) else FpuFormat.FLOAT())
|
||||
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_LOAD) := input(FPU_OPCODE) === FpuOpcode.LOAD
|
||||
|
@ -326,6 +343,81 @@ class FpuPlugin(externalFpu : Boolean = 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))
|
||||
|
||||
Component.current.afterElaboration{
|
||||
|
|
Loading…
Reference in New Issue