CfuPlugin addition

This commit is contained in:
Dolu1990 2019-07-29 14:17:51 +02:00 committed by Charles Papon
parent 84602f89b0
commit 6951f5b8e6
1 changed files with 120 additions and 0 deletions

View File

@ -0,0 +1,120 @@
package vexriscv.plugin
import vexriscv.{DecoderService, Stageable, VexRiscv}
import spinal.core._
import spinal.lib._
case class CfuParameter(latency : Int,
dropWidth : Int,
CFU_VERSION : Int,
CFU_INTERFACE_ID_W : Int,
CFU_FUNCTION_ID_W : Int,
CFU_REORDER_ID_W : Int,
CFU_REQ_RESP_ID_W : Int,
CFU_INPUTS : Int,
CFU_INPUT_DATA_W : Int,
CFU_OUTPUTS : Int,
CFU_OUTPUT_DATA_W : Int,
CFU_FLOW_REQ_READY_ALWAYS : Int,
CFU_FLOW_RESP_READY_ALWAYS : Int)
case class CfuCmd(p : CfuParameter) extends Bundle{
val function_id = UInt(p.CFU_FUNCTION_ID_W bits)
val reorder_id = UInt(p.CFU_REORDER_ID_W bits)
val request_id = UInt(p.CFU_REQ_RESP_ID_W bits)
val inputs = Vec(Bits(p.CFU_INPUT_DATA_W bits), p.CFU_INPUTS)
}
case class CfuRsp(p : CfuParameter) extends Bundle{
val response_ok = Bool()
val response_id = UInt(p.CFU_REQ_RESP_ID_W bits)
val outputs = Vec(Bits(p.CFU_OUTPUT_DATA_W bits), p.CFU_OUTPUTS)
}
case class CfuBus(p : CfuParameter) extends Bundle with IMasterSlave{
val interface_id = UInt(p.CFU_INTERFACE_ID_W bits)
val cmd = Stream(CfuCmd(p))
val rsp = Stream(CfuRsp(p))
override def asMaster(): Unit = {
out(interface_id)
master(cmd)
slave(rsp)
}
}
class CfuPlugin(val p: CfuParameter) extends Plugin[VexRiscv]{
assert(p.CFU_INPUTS <= 2)
assert(p.CFU_OUTPUTS == 1)
assert(p.CFU_FLOW_REQ_READY_ALWAYS == false)
assert(p.CFU_FLOW_RESP_READY_ALWAYS == false)
var bus : CfuBus = null
object CFU_ENABLE extends Stageable(Bool())
object CFU_FUNCTION extends Stageable(UInt(p.CFU_FUNCTION_ID_W bits))
object CFU_IN_FLIGHT extends Stageable(Bool())
override def setup(pipeline: VexRiscv): Unit = {
import pipeline.config._
bus = CfuBus(p)
val decoderService = pipeline.service(classOf[DecoderService])
decoderService.add(List(
M"000000-----------000-----0010011" -> List(
CFU_ENABLE -> True,
CFU_FUNCTION -> U"00",
REGFILE_WRITE_VALID -> ???,
BYPASSABLE_EXECUTE_STAGE -> ???,
BYPASSABLE_MEMORY_STAGE -> ???,
RS1_USE -> ???,
RS2_USE -> ???
),
M"000000-----------001-----0010011" -> List(
CFU_ENABLE -> True,
CFU_FUNCTION -> U"01",
REGFILE_WRITE_VALID -> ???,
BYPASSABLE_EXECUTE_STAGE -> ???,
BYPASSABLE_MEMORY_STAGE -> ???,
RS1_USE -> ???,
RS2_USE -> ???
)
))
}
override def build(pipeline: VexRiscv): Unit = {
import pipeline._
import pipeline.config._
val forkStage = execute
val joinStageId = Math.min(stages.length - 1, pipeline.indexOf(execute) + p.latency - 1)
val joinStage = stages(joinStageId)
forkStage plug new Area{
import forkStage._
val schedule = arbitration.isValid && input(CFU_ENABLE)
val hold = RegInit(False) setWhen(schedule) clearWhen(bus.cmd.ready)
val fired = RegInit(False) setWhen(bus.cmd.fire) clearWhen(!arbitration.isStuckByOthers)
insert(CFU_IN_FLIGHT) := schedule || hold || fired
bus.cmd.valid := (schedule || hold) && !fired
arbitration.haltItself setWhen(bus.cmd.valid && !bus.cmd.ready)
bus.cmd.function_id := input(CFU_FUNCTION)
bus.cmd.reorder_id := 0
bus.cmd.request_id := 0
if(p.CFU_INPUTS >= 1) bus.cmd.inputs(0) := input(RS1)
if(p.CFU_INPUTS >= 2) bus.cmd.inputs(1) := input(RS2)
}
joinStage plug new Area{
import joinStage._
when(input(CFU_IN_FLIGHT)){
arbitration.haltItself setWhen(!bus.rsp.valid)
bus.rsp.ready := arbitration.isStuckByOthers
output(REGFILE_WRITE_DATA) := bus.rsp.outputs(0)
}
}
}
}