CfuPlugin encoding can now specify cmd/rsp less instruction

This commit is contained in:
Charles Papon 2023-03-07 16:49:07 +08:00
parent 3cf8508db1
commit f11c642cd6
1 changed files with 35 additions and 17 deletions

View File

@ -1,6 +1,6 @@
package vexriscv.plugin package vexriscv.plugin
import vexriscv.{DecoderService, ExceptionCause, ExceptionService, Stage, Stageable, VexRiscv} import vexriscv.{DecoderService, ExceptionCause, ExceptionService, JumpService, Stage, Stageable, VexRiscv}
import spinal.core._ import spinal.core._
import spinal.lib._ import spinal.lib._
import spinal.lib.bus.bmb.WeakConnector import spinal.lib.bus.bmb.WeakConnector
@ -92,7 +92,9 @@ object CfuPlugin{
case class CfuPluginEncoding(instruction : MaskedLiteral, case class CfuPluginEncoding(instruction : MaskedLiteral,
functionId : List[Range], functionId : List[Range],
input2Kind : CfuPlugin.Input2Kind.E){ input2Kind : CfuPlugin.Input2Kind.E,
withCmd : Boolean = true,
withRsp : Boolean = true){
val functionIdWidth = functionId.map(_.size).sum val functionIdWidth = functionId.map(_.size).sum
} }
@ -110,6 +112,7 @@ class CfuPlugin(val stageCount : Int,
// assert(p.CFU_FUNCTION_ID_W == 3) // assert(p.CFU_FUNCTION_ID_W == 3)
var bus : CfuBus = null var bus : CfuBus = null
// var redoInterface : Flow[UInt] = null
lazy val forkStage = pipeline.execute lazy val forkStage = pipeline.execute
lazy val joinStage = pipeline.stages(Math.min(pipeline.stages.length - 1, pipeline.indexOf(forkStage) + stageCount)) lazy val joinStage = pipeline.stages(Math.min(pipeline.stages.length - 1, pipeline.indexOf(forkStage) + stageCount))
@ -119,32 +122,46 @@ class CfuPlugin(val stageCount : Int,
val CFU_IN_FLIGHT = new Stageable(Bool()).setCompositeName(this, "CFU_IN_FLIGHT") val CFU_IN_FLIGHT = new Stageable(Bool()).setCompositeName(this, "CFU_IN_FLIGHT")
val CFU_ENCODING = new Stageable(UInt(log2Up(encodings.size) bits)).setCompositeName(this, "CFU_ENCODING") val CFU_ENCODING = new Stageable(UInt(log2Up(encodings.size) bits)).setCompositeName(this, "CFU_ENCODING")
val CFU_INPUT_2_KIND = new Stageable(CfuPlugin.Input2Kind()).setCompositeName(this, "CFU_INPUT_2_KIND") val CFU_INPUT_2_KIND = new Stageable(CfuPlugin.Input2Kind()).setCompositeName(this, "CFU_INPUT_2_KIND")
val CFU_WITH_CMD = new Stageable(Bool()).setCompositeName(this, "CFU_WITH_CMD")
val CFU_WITH_RSP = new Stageable(Bool()).setCompositeName(this, "CFU_WITH_RSP")
override def setup(pipeline: VexRiscv): Unit = { override def setup(pipeline: VexRiscv): Unit = {
import pipeline._ import pipeline._
import pipeline.config._ import pipeline.config._
// val pcManagerService = pipeline.service(classOf[JumpService])
// if(encodings.contains(_.cmd)redoInterface = pcManagerService.createJumpInterface(pipeline.writeBack)
bus = master(CfuBus(p)) bus = master(CfuBus(p))
val decoderService = pipeline.service(classOf[DecoderService]) val decoderService = pipeline.service(classOf[DecoderService])
decoderService.addDefault(CFU_ENABLE, False) decoderService.addDefault(CFU_ENABLE, False)
decoderService.addDefault(CFU_WITH_CMD, False)
decoderService.addDefault(CFU_WITH_RSP, False)
for((encoding, id) <- encodings.zipWithIndex){ for((encoding, id) <- encodings.zipWithIndex){
var actions = List( var actions : List[(Stageable[_ <: BaseType], Any)] = List(
CFU_ENABLE -> True, CFU_ENABLE -> True,
REGFILE_WRITE_VALID -> True,
BYPASSABLE_EXECUTE_STAGE -> Bool(stageCount == 0),
BYPASSABLE_MEMORY_STAGE -> Bool(stageCount <= 1),
RS1_USE -> True,
CFU_ENCODING -> U(id), CFU_ENCODING -> U(id),
CFU_INPUT_2_KIND -> encoding.input2Kind() CFU_WITH_CMD -> Bool(encoding.withCmd),
CFU_WITH_RSP -> Bool(encoding.withRsp)
) )
if(encoding.withCmd){
actions :+= RS1_USE -> True
actions :+= CFU_INPUT_2_KIND -> encoding.input2Kind()
encoding.input2Kind match { encoding.input2Kind match {
case CfuPlugin.Input2Kind.RS => case CfuPlugin.Input2Kind.RS =>
actions :+= RS2_USE -> True actions :+= RS2_USE -> True
case CfuPlugin.Input2Kind.IMM_I => case CfuPlugin.Input2Kind.IMM_I =>
} }
}
if(encoding.withRsp){
actions :+= REGFILE_WRITE_VALID -> True
actions :+= BYPASSABLE_EXECUTE_STAGE -> Bool(stageCount == 0)
actions :+= BYPASSABLE_MEMORY_STAGE -> Bool(stageCount <= 1)
}
decoderService.add( decoderService.add(
key = encoding.instruction, key = encoding.instruction,
@ -190,7 +207,7 @@ class CfuPlugin(val stageCount : Int,
import forkStage._ import forkStage._
input(CFU_ENABLE).clearWhen(!input(LEGAL_INSTRUCTION)) input(CFU_ENABLE).clearWhen(!input(LEGAL_INSTRUCTION))
val hazard = stages.dropWhile(_ != forkStage).tail.map(s => s.arbitration.isValid && s.input(HAS_SIDE_EFFECT)).orR val hazard = stages.dropWhile(_ != forkStage).tail.map(s => s.arbitration.isValid && s.input(HAS_SIDE_EFFECT)).orR
val scheduleWish = arbitration.isValid && input(CFU_ENABLE) val scheduleWish = arbitration.isValid && input(CFU_ENABLE) && input(CFU_WITH_CMD)
val schedule = scheduleWish && !hazard val schedule = scheduleWish && !hazard
arbitration.haltItself setWhen(scheduleWish && hazard) arbitration.haltItself setWhen(scheduleWish && hazard)
@ -233,12 +250,13 @@ class CfuPlugin(val stageCount : Int,
bus.rsp.combStage() bus.rsp.combStage()
} }
val hazard = stages.dropWhile(_ != joinStage).tail.map(s => s.arbitration.isValid && s.input(HAS_SIDE_EFFECT)).orR
rsp.ready := False rsp.ready := False
when(input(CFU_IN_FLIGHT)){ when((arbitration.isValid || input(CFU_IN_FLIGHT)) && input(CFU_WITH_RSP)){
arbitration.haltItself setWhen(!rsp.valid) arbitration.haltItself setWhen(!rsp.valid || hazard)
rsp.ready := !arbitration.isStuckByOthers rsp.ready := !arbitration.isStuckByOthers && !hazard
output(REGFILE_WRITE_DATA) := rsp.outputs(0) output(REGFILE_WRITE_DATA) := rsp.outputs(0)
if(p.CFU_WITH_STATUS) when(arbitration.isFiring){ if(p.CFU_WITH_STATUS) when(rsp.fire){
switch(rsp.status) { switch(rsp.status) {
for (i <- 1 to 6) is(i) { for (i <- 1 to 6) is(i) {
csr.status.flags(i-1) := True csr.status.flags(i-1) := True