Merge branch 'dev' into fiber

# Conflicts:
#	src/main/scala/vexriscv/demo/smp/VexRiscvSmpCluster.scala
#	src/main/scala/vexriscv/plugin/MulPlugin.scala
This commit is contained in:
Dolu1990 2021-03-15 10:35:02 +01:00
commit 3a34b8dae2
7 changed files with 126 additions and 98 deletions

View File

@ -31,6 +31,11 @@ case class VexRiscvConfig(){
case None => None case None => None
} }
} }
def get[T](clazz: Class[T]): T = {
plugins.find(_.getClass == clazz) match {
case Some(x) => x.asInstanceOf[T]
}
}
//Default Stageables //Default Stageables
object IS_RVC extends Stageable(Bool) object IS_RVC extends Stageable(Bool)

View File

@ -17,7 +17,7 @@ import spinal.idslplugin.PostInitCallback
import spinal.lib.misc.plic.PlicMapping import spinal.lib.misc.plic.PlicMapping
import spinal.lib.system.debugger.SystemDebuggerConfig import spinal.lib.system.debugger.SystemDebuggerConfig
import vexriscv.ip.{DataCacheAck, DataCacheConfig, DataCacheMemBus, InstructionCache, InstructionCacheConfig} import vexriscv.ip.{DataCacheAck, DataCacheConfig, DataCacheMemBus, InstructionCache, InstructionCacheConfig}
import vexriscv.plugin.{BranchPlugin, CsrAccess, CsrPlugin, CsrPluginConfig, DBusCachedPlugin, DBusSimplePlugin, DYNAMIC_TARGET, DebugPlugin, DecoderSimplePlugin, FpuPlugin, FullBarrelShifterPlugin, HazardSimplePlugin, IBusCachedPlugin, IBusSimplePlugin, IntAluPlugin, MmuPlugin, MmuPortConfig, MulDivIterativePlugin, MulPlugin, RegFilePlugin, STATIC, SrcPlugin, StaticMemoryTranslatorPlugin, YamlPlugin} import vexriscv.plugin._
import vexriscv.{Riscv, VexRiscv, VexRiscvBmbGenerator, VexRiscvConfig, plugin} import vexriscv.{Riscv, VexRiscv, VexRiscvBmbGenerator, VexRiscvConfig, plugin}
import scala.collection.mutable import scala.collection.mutable
@ -168,6 +168,7 @@ object VexRiscvSmpClusterGen {
iCacheWays : Int = 2, iCacheWays : Int = 2,
dCacheWays : Int = 2, dCacheWays : Int = 2,
iBusRelax : Boolean = false, iBusRelax : Boolean = false,
injectorStage : Boolean = false,
earlyBranch : Boolean = false, earlyBranch : Boolean = false,
dBusCmdMasterPipe : Boolean = false, dBusCmdMasterPipe : Boolean = false,
withMmu : Boolean = true, withMmu : Boolean = true,
@ -175,7 +176,8 @@ object VexRiscvSmpClusterGen {
withFloat : Boolean = false, withFloat : Boolean = false,
withDouble : Boolean = false, withDouble : Boolean = false,
externalFpu : Boolean = true, externalFpu : Boolean = true,
simHalt : Boolean = false simHalt : Boolean = false,
regfileRead : RegFileReadKind = plugin.ASYNC
) = { ) = {
assert(iCacheSize/iCacheWays <= 4096, "Instruction cache ways can't be bigger than 4096 bytes") assert(iCacheSize/iCacheWays <= 4096, "Instruction cache ways can't be bigger than 4096 bytes")
assert(dCacheSize/dCacheWays <= 4096, "Data cache ways can't be bigger than 4096 bytes") assert(dCacheSize/dCacheWays <= 4096, "Data cache ways can't be bigger than 4096 bytes")
@ -195,7 +197,7 @@ object VexRiscvSmpClusterGen {
prediction = vexriscv.plugin.NONE, prediction = vexriscv.plugin.NONE,
historyRamSizeLog2 = 9, historyRamSizeLog2 = 9,
relaxPredictorAddress = true, relaxPredictorAddress = true,
injectorStage = false, injectorStage = injectorStage,
relaxedPcCalculation = iBusRelax, relaxedPcCalculation = iBusRelax,
config = InstructionCacheConfig( config = InstructionCacheConfig(
cacheSize = iCacheSize, cacheSize = iCacheSize,
@ -250,7 +252,7 @@ object VexRiscvSmpClusterGen {
catchIllegalInstruction = true catchIllegalInstruction = true
), ),
new RegFilePlugin( new RegFilePlugin(
regFileReadyKind = plugin.ASYNC, regFileReadyKind = regfileRead,
zeroBoot = false, zeroBoot = false,
x0Init = true x0Init = true
), ),

View File

@ -511,7 +511,7 @@ case class DataCacheMemBus(p : DataCacheConfig) extends Bundle with IMasterSlave
cmdCtx.payload := aggregationCounter cmdCtx.payload := aggregationCounter
halt setWhen(!cmdCtx.ready) halt setWhen(!cmdCtx.ready)
val syncCtx = cmdCtx.queue(syncPendingMax) val syncCtx = cmdCtx.queue(syncPendingMax).s2mPipe().m2sPipe() //Assume latency of sync is at least 3 cycles
syncCtx.ready := bus.sync.fire syncCtx.ready := bus.sync.fire
sync.arbitrationFrom(bus.sync) sync.arbitrationFrom(bus.sync)

View File

@ -49,13 +49,11 @@ case class CfuCmd( p : CfuBusParameter ) extends Bundle{
} }
case class CfuRsp(p : CfuBusParameter) extends Bundle{ case class CfuRsp(p : CfuBusParameter) extends Bundle{
val response_ok = Bool()
val response_id = UInt(p.CFU_REQ_RESP_ID_W bits) val response_id = UInt(p.CFU_REQ_RESP_ID_W bits)
val outputs = Vec(Bits(p.CFU_OUTPUT_DATA_W bits), p.CFU_OUTPUTS) val outputs = Vec(Bits(p.CFU_OUTPUT_DATA_W bits), p.CFU_OUTPUTS)
def weakAssignFrom(m : CfuRsp): Unit ={ def weakAssignFrom(m : CfuRsp): Unit ={
def s = this def s = this
s.response_ok := m.response_ok
s.response_id := m.response_id s.response_id := m.response_id
s.outputs := m.outputs s.outputs := m.outputs
} }
@ -105,7 +103,6 @@ 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 joinException : Flow[ExceptionCause] = 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))
@ -121,7 +118,6 @@ class CfuPlugin(val stageCount : Int,
import pipeline.config._ import pipeline.config._
bus = master(CfuBus(p)) bus = master(CfuBus(p))
joinException = pipeline.service(classOf[ExceptionService]).newExceptionPort(joinStage)
val decoderService = pipeline.service(classOf[DecoderService]) val decoderService = pipeline.service(classOf[DecoderService])
decoderService.addDefault(CFU_ENABLE, False) decoderService.addDefault(CFU_ENABLE, False)
@ -207,22 +203,15 @@ class CfuPlugin(val stageCount : Int,
bus.rsp.combStage() bus.rsp.combStage()
} }
joinException.valid := False
joinException.code := 15
joinException.badAddr := 0
rsp.ready := False rsp.ready := False
when(input(CFU_IN_FLIGHT)){ when(input(CFU_IN_FLIGHT)){
arbitration.haltItself setWhen(!rsp.valid) arbitration.haltItself setWhen(!rsp.valid)
rsp.ready := !arbitration.isStuckByOthers rsp.ready := !arbitration.isStuckByOthers
output(REGFILE_WRITE_DATA) := rsp.outputs(0) output(REGFILE_WRITE_DATA) := rsp.outputs(0)
when(arbitration.isValid){
joinException.valid := !rsp.response_ok
}
} }
} }
pipeline.stages.drop(1).foreach(s => s.output(CFU_IN_FLIGHT) clearWhen(s.arbitration.isStuck))
addPrePopTask(() => stages.dropWhile(_ != memory).reverse.dropWhile(_ != joinStage).foreach(s => s.input(CFU_IN_FLIGHT).init(False))) addPrePopTask(() => stages.dropWhile(_ != memory).reverse.dropWhile(_ != joinStage).foreach(s => s.input(CFU_IN_FLIGHT).init(False)))
} }
} }
@ -251,7 +240,6 @@ case class CfuTest() extends Component{
val bus = slave(CfuBus(CfuTest.getCfuParameter())) val bus = slave(CfuBus(CfuTest.getCfuParameter()))
} }
io.bus.rsp.arbitrationFrom(io.bus.cmd) io.bus.rsp.arbitrationFrom(io.bus.cmd)
io.bus.rsp.response_ok := True
io.bus.rsp.response_id := io.bus.cmd.request_id io.bus.rsp.response_id := io.bus.cmd.request_id
io.bus.rsp.outputs(0) := ~(io.bus.cmd.inputs(0) & io.bus.cmd.inputs(1)) io.bus.rsp.outputs(0) := ~(io.bus.cmd.inputs(0) & io.bus.cmd.inputs(1))
} }
@ -320,7 +308,6 @@ case class CfuDecoder(p : CfuBusParameter,
io.input.rsp.payload := io.outputs.map(_.rsp.payload).read(OHToUInt(rspHits)) io.input.rsp.payload := io.outputs.map(_.rsp.payload).read(OHToUInt(rspHits))
if(!hasDefault) when(rspNoHit.doIt) { if(!hasDefault) when(rspNoHit.doIt) {
io.input.rsp.valid := True io.input.rsp.valid := True
io.input.rsp.response_ok := False
io.input.rsp.response_id := rspNoHit.response_id io.input.rsp.response_id := rspNoHit.response_id
} }
for(output <- io.outputs) output.rsp.ready := io.input.rsp.ready for(output <- io.outputs) output.rsp.ready := io.input.rsp.ready

View File

@ -31,6 +31,8 @@ class HazardSimplePlugin(bypassExecute : Boolean = false,
override def build(pipeline: VexRiscv): Unit = { override def build(pipeline: VexRiscv): Unit = {
import pipeline._ import pipeline._
import pipeline.config._ import pipeline.config._
pipeline plug new Area {
val src0Hazard = False val src0Hazard = False
val src1Hazard = False val src1Hazard = False
@ -113,6 +115,7 @@ class HazardSimplePlugin(bypassExecute : Boolean = false,
} }
} }
} }
}
class NoHazardPlugin extends Plugin[VexRiscv] with HazardService { class NoHazardPlugin extends Plugin[VexRiscv] with HazardService {

View File

@ -5,7 +5,8 @@ import spinal.core._
import spinal.lib.KeepAttribute import spinal.lib.KeepAttribute
//Input buffer generaly avoid the FPGA synthesis to duplicate reg inside the DSP cell, which could stress timings quite much. //Input buffer generaly avoid the FPGA synthesis to duplicate reg inside the DSP cell, which could stress timings quite much.
class MulPlugin(inputBuffer : Boolean = false) extends Plugin[VexRiscv] with VexRiscvRegressionArg { class MulPlugin(var inputBuffer : Boolean = false,
var outputBuffer : Boolean = false) extends Plugin[VexRiscv] with VexRiscvRegressionArg {
object MUL_LL extends Stageable(UInt(32 bits)) object MUL_LL extends Stageable(UInt(32 bits))
object MUL_LH extends Stageable(SInt(34 bits)) object MUL_LH extends Stageable(SInt(34 bits))
object MUL_HL extends Stageable(SInt(34 bits)) object MUL_HL extends Stageable(SInt(34 bits))
@ -19,7 +20,6 @@ class MulPlugin(inputBuffer : Boolean = false) extends Plugin[VexRiscv] with Vex
List("MUL=yes") List("MUL=yes")
} }
override def setup(pipeline: VexRiscv): Unit = { override def setup(pipeline: VexRiscv): Unit = {
import Riscv._ import Riscv._
import pipeline.config._ import pipeline.config._
@ -58,16 +58,25 @@ class MulPlugin(inputBuffer : Boolean = false) extends Plugin[VexRiscv] with Vex
// a := input(SRC1) // a := input(SRC1)
// b := input(SRC2) // b := input(SRC2)
val delay = (if(inputBuffer) 1 else 0) + (if(outputBuffer) 1 else 0)
val delayLogic = (delay != 0) generate new Area{
val counter = Reg(UInt(log2Up(delay+1) bits))
when(arbitration.isValid && input(IS_MUL) && counter =/= delay){
arbitration.haltItself := True
}
counter := counter + 1
when(!arbitration.isStuck || arbitration.isStuckByOthers){
counter := 0
}
}
val withInputBuffer = inputBuffer generate new Area{ val withInputBuffer = inputBuffer generate new Area{
val rs1 = RegNext(input(RS1)) val rs1 = RegNext(input(RS1))
val rs2 = RegNext(input(RS2)) val rs2 = RegNext(input(RS2))
a := rs1 a := rs1
b := rs2 b := rs2
val delay = RegNext(arbitration.isStuck)
when(arbitration.isValid && input(IS_MUL) && !delay){
arbitration.haltItself := True
}
} }
val noInputBuffer = (!inputBuffer) generate new Area{ val noInputBuffer = (!inputBuffer) generate new Area{
@ -96,10 +105,25 @@ class MulPlugin(inputBuffer : Boolean = false) extends Plugin[VexRiscv] with Vex
val bSLow = (False ## b(15 downto 0)).asSInt val bSLow = (False ## b(15 downto 0)).asSInt
val aHigh = (((aSigned && a.msb) ## a(31 downto 16))).asSInt val aHigh = (((aSigned && a.msb) ## a(31 downto 16))).asSInt
val bHigh = (((bSigned && b.msb) ## b(31 downto 16))).asSInt val bHigh = (((bSigned && b.msb) ## b(31 downto 16))).asSInt
val withOuputBuffer = outputBuffer generate new Area{
val mul_ll = RegNext(aULow * bULow)
val mul_lh = RegNext(aSLow * bHigh)
val mul_hl = RegNext(aHigh * bSLow)
val mul_hh = RegNext(aHigh * bHigh)
insert(MUL_LL) := mul_ll
insert(MUL_LH) := mul_lh
insert(MUL_HL) := mul_hl
insert(MUL_HH) := mul_hh
}
val noOutputBuffer = (!outputBuffer) generate new Area{
insert(MUL_LL) := aULow * bULow insert(MUL_LL) := aULow * bULow
insert(MUL_LH) := aSLow * bHigh insert(MUL_LH) := aSLow * bHigh
insert(MUL_HL) := aHigh * bSLow insert(MUL_HL) := aHigh * bSLow
insert(MUL_HH) := aHigh * bHigh insert(MUL_HH) := aHigh * bHigh
}
Component.current.afterElaboration{ Component.current.afterElaboration{
//Avoid synthesis tools to retime RS1 RS2 from execute stage to decode stage leading to bad timings (ex : Vivado, even if retiming is disabled) //Avoid synthesis tools to retime RS1 RS2 from execute stage to decode stage leading to bad timings (ex : Vivado, even if retiming is disabled)

View File

@ -173,11 +173,17 @@ class MulDivDimension extends VexRiscvDimension("MulDiv") {
} :: l } :: l
if(!noMemory && !noWriteBack) l = if(!noMemory && !noWriteBack) {
new VexRiscvPosition("MulDivFpga") { val inputBuffer = r.nextBoolean()
val outputBuffer = r.nextBoolean()
l = new VexRiscvPosition(s"MulDivFpga$inputBuffer$outputBuffer") {
override def testParam = "MUL=yes DIV=yes" override def testParam = "MUL=yes DIV=yes"
override def applyOn(config: VexRiscvConfig): Unit = { override def applyOn(config: VexRiscvConfig): Unit = {
config.plugins += new MulPlugin config.plugins += new MulPlugin(
inputBuffer = inputBuffer,
outputBuffer = outputBuffer
)
config.plugins += new MulDivIterativePlugin( config.plugins += new MulDivIterativePlugin(
genMul = false, genMul = false,
genDiv = true, genDiv = true,
@ -186,6 +192,7 @@ class MulDivDimension extends VexRiscvDimension("MulDiv") {
) )
} }
} :: l } :: l
}
random(r, l) random(r, l)
} }