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
|
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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -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{
|
||||||
|
|
Loading…
Reference in New Issue