diff --git a/src/main/scala/vexriscv/demo/GenSmallAndProductiveCfu.scala b/src/main/scala/vexriscv/demo/GenSmallAndProductiveCfu.scala new file mode 100644 index 0000000..9983814 --- /dev/null +++ b/src/main/scala/vexriscv/demo/GenSmallAndProductiveCfu.scala @@ -0,0 +1,76 @@ +package vexriscv.demo + +import spinal.core._ +import vexriscv.plugin._ +import vexriscv.{VexRiscv, VexRiscvConfig, plugin} + +/** + * Created by spinalvm on 15.06.17. + */ +object GenSmallAndProductiveCfu extends App{ + def cpu() = new VexRiscv( + config = VexRiscvConfig( + plugins = List( + new IBusSimplePlugin( + resetVector = 0x80000000l, + cmdForkOnSecondStage = false, + cmdForkPersistence = false, + prediction = NONE, + catchAccessFault = false, + compressedGen = false + ), + new DBusSimplePlugin( + catchAddressMisaligned = false, + catchAccessFault = false + ), + new CsrPlugin(CsrPluginConfig.smallest), + new DecoderSimplePlugin( + catchIllegalInstruction = false + ), + new RegFilePlugin( + regFileReadyKind = plugin.SYNC, + zeroBoot = false + ), + new IntAluPlugin, + new SrcPlugin( + separatedAddSub = false, + executeInsertion = true + ), + new LightShifterPlugin, + new HazardSimplePlugin( + bypassExecute = true, + bypassMemory = true, + bypassWriteBack = true, + bypassWriteBackBuffer = true, + pessimisticUseSrc = false, + pessimisticWriteRegFile = false, + pessimisticAddressMatch = false + ), + new BranchPlugin( + earlyBranch = false, + catchAddressMisaligned = false + ), + new CfuPlugin( + p = CfuParameter( + stageCount = 1, + allowZeroLatency = true, + CFU_VERSION = 0, + CFU_INTERFACE_ID_W = 0, + CFU_FUNCTION_ID_W = 2, + CFU_REORDER_ID_W = 0, + CFU_REQ_RESP_ID_W = 0, + CFU_INPUTS = 2, + CFU_INPUT_DATA_W = 32, + CFU_OUTPUTS = 1, + CFU_OUTPUT_DATA_W = 32, + CFU_FLOW_REQ_READY_ALWAYS = false, + CFU_FLOW_RESP_READY_ALWAYS = false + ) + ), + new YamlPlugin("cpu0.yaml") + ) + ) + ) + + SpinalVerilog(cpu()) +} diff --git a/src/main/scala/vexriscv/plugin/CfuPlugin.scala b/src/main/scala/vexriscv/plugin/CfuPlugin.scala index e34b2e7..334fc25 100644 --- a/src/main/scala/vexriscv/plugin/CfuPlugin.scala +++ b/src/main/scala/vexriscv/plugin/CfuPlugin.scala @@ -1,12 +1,11 @@ package vexriscv.plugin -import vexriscv.{DecoderService, Stageable, VexRiscv} +import vexriscv.{DecoderService, ExceptionCause, ExceptionService, Stage, Stageable, VexRiscv} import spinal.core._ import spinal.lib._ case class CfuParameter(stageCount : Int, allowZeroLatency : Boolean, - dropWidth : Int, CFU_VERSION : Int, CFU_INTERFACE_ID_W : Int, CFU_FUNCTION_ID_W : Int, @@ -16,8 +15,8 @@ case class CfuParameter(stageCount : 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) + CFU_FLOW_REQ_READY_ALWAYS : Boolean, + CFU_FLOW_RESP_READY_ALWAYS : Boolean) case class CfuCmd(p : CfuParameter) extends Bundle{ val function_id = UInt(p.CFU_FUNCTION_ID_W bits) @@ -33,12 +32,10 @@ case class CfuRsp(p : CfuParameter) extends Bundle{ } 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) } @@ -47,39 +44,46 @@ case class CfuBus(p : CfuParameter) extends Bundle with IMasterSlave{ 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 + var joinException : Flow[ExceptionCause] = null + + lazy val forkStage = pipeline.execute + lazy val joinStage = pipeline.stages(Math.min(pipeline.stages.length - 1, pipeline.indexOf(forkStage) + p.stageCount - 1)) + 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._ import pipeline.config._ - bus = CfuBus(p) + bus = master(CfuBus(p)) + joinException = pipeline.service(classOf[ExceptionService]).newExceptionPort(joinStage) val decoderService = pipeline.service(classOf[DecoderService]) + + //custom-0 decoderService.add(List( - M"000000-----------000-----0010011" -> List( + M"000000-----------000-----0001011" -> List( CFU_ENABLE -> True, CFU_FUNCTION -> U"00", - REGFILE_WRITE_VALID -> ???, - BYPASSABLE_EXECUTE_STAGE -> ???, - BYPASSABLE_MEMORY_STAGE -> ???, - RS1_USE -> ???, - RS2_USE -> ??? + REGFILE_WRITE_VALID -> True, + BYPASSABLE_EXECUTE_STAGE -> Bool(p.stageCount == 0), + BYPASSABLE_MEMORY_STAGE -> Bool(p.stageCount <= 1), + RS1_USE -> True, + RS2_USE -> True ), - M"000000-----------001-----0010011" -> List( + M"000000-----------001-----0001011" -> List( CFU_ENABLE -> True, CFU_FUNCTION -> U"01", - REGFILE_WRITE_VALID -> ???, - BYPASSABLE_EXECUTE_STAGE -> ???, - BYPASSABLE_MEMORY_STAGE -> ???, - RS1_USE -> ???, - RS2_USE -> ??? + REGFILE_WRITE_VALID -> True, + BYPASSABLE_EXECUTE_STAGE -> Bool(p.stageCount == 0), + BYPASSABLE_MEMORY_STAGE -> Bool(p.stageCount <= 1), + RS1_USE -> True, + RS2_USE -> True ) )) } @@ -88,10 +92,6 @@ class CfuPlugin(val p: CfuParameter) extends Plugin[VexRiscv]{ import pipeline._ import pipeline.config._ - val forkStage = execute - val joinStageId = Math.min(stages.length - 1, pipeline.indexOf(execute) + p.stageCount - 1) - val joinStage = stages(joinStageId) - forkStage plug new Area{ import forkStage._ val schedule = arbitration.isValid && input(CFU_ENABLE) @@ -114,13 +114,30 @@ class CfuPlugin(val p: CfuParameter) extends Plugin[VexRiscv]{ //If the CFU interface can produce a result combinatorialy and the fork stage isn't the same than the join stage //Then it is required to add a buffer on rsp to not propagate the fork stage ready := False in the CPU pipeline. - val rsp = if(forkStage != joinStage && p.allowZeroLatency) bus.rsp.m2sPipe() else bus.rsp + val rsp = if(p.CFU_FLOW_RESP_READY_ALWAYS){ + bus.rsp.toFlow.toStream.queueLowLatency( + size = p.stageCount + 1, + latency = 0 + ) + } else if(forkStage != joinStage && p.allowZeroLatency) { + bus.rsp.m2sPipe() + } else { + bus.rsp.combStage() + } + joinException.valid := False + joinException.code := 15 + joinException.badAddr := 0 + rsp.ready := False when(input(CFU_IN_FLIGHT)){ arbitration.haltItself setWhen(!rsp.valid) rsp.ready := arbitration.isStuckByOthers output(REGFILE_WRITE_DATA) := rsp.outputs(0) + + when(arbitration.isValid){ + joinException.valid := !rsp.response_ok + } } } }