mirror of
https://github.com/SpinalHDL/VexRiscv.git
synced 2025-01-03 03:43:39 -05:00
VfuPlugin wip
This commit is contained in:
parent
c242744d02
commit
b717f228d6
2 changed files with 199 additions and 0 deletions
64
src/main/scala/vexriscv/demo/GenSmallAndProductiveVfu.scala
Normal file
64
src/main/scala/vexriscv/demo/GenSmallAndProductiveVfu.scala
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
package vexriscv.demo
|
||||||
|
|
||||||
|
import spinal.core._
|
||||||
|
import vexriscv.plugin._
|
||||||
|
import vexriscv.{VexRiscv, VexRiscvConfig, plugin}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by spinalvm on 15.06.17.
|
||||||
|
*/
|
||||||
|
object GenSmallAndProductiveVfu 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 VfuPlugin(
|
||||||
|
stageCount = 2,
|
||||||
|
allowZeroLatency = false,
|
||||||
|
parameter = VfuParameter()
|
||||||
|
),
|
||||||
|
new YamlPlugin("cpu0.yaml")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
SpinalVerilog(cpu())
|
||||||
|
}
|
135
src/main/scala/vexriscv/plugin/VfuPlugin.scala
Normal file
135
src/main/scala/vexriscv/plugin/VfuPlugin.scala
Normal file
|
@ -0,0 +1,135 @@
|
||||||
|
package vexriscv.plugin
|
||||||
|
|
||||||
|
import vexriscv.{DecoderService, ExceptionCause, ExceptionService, Stage, Stageable, VexRiscv}
|
||||||
|
import spinal.core._
|
||||||
|
import spinal.lib._
|
||||||
|
import spinal.lib.bus.bmb.WeakConnector
|
||||||
|
import spinal.lib.bus.misc.{AddressMapping, DefaultMapping}
|
||||||
|
import vexriscv.Riscv.IMM
|
||||||
|
|
||||||
|
|
||||||
|
object VfuPlugin{
|
||||||
|
val ROUND_MODE_WIDTH = 3
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
case class VfuParameter() //Empty for now
|
||||||
|
|
||||||
|
case class VfuCmd( p : VfuParameter ) extends Bundle{
|
||||||
|
val instruction = Bits(32 bits)
|
||||||
|
val inputs = Vec(Bits(32 bits), 2)
|
||||||
|
val rounding = Bits(VfuPlugin.ROUND_MODE_WIDTH bits)
|
||||||
|
}
|
||||||
|
|
||||||
|
case class VfuRsp(p : VfuParameter) extends Bundle{
|
||||||
|
val output = Bits(32 bits)
|
||||||
|
}
|
||||||
|
|
||||||
|
case class VfuBus(p : VfuParameter) extends Bundle with IMasterSlave{
|
||||||
|
val cmd = Stream(VfuCmd(p))
|
||||||
|
val rsp = Stream(VfuRsp(p))
|
||||||
|
|
||||||
|
def <<(m : VfuBus) : Unit = {
|
||||||
|
val s = this
|
||||||
|
s.cmd << m.cmd
|
||||||
|
m.rsp << s.rsp
|
||||||
|
}
|
||||||
|
|
||||||
|
override def asMaster(): Unit = {
|
||||||
|
master(cmd)
|
||||||
|
slave(rsp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class VfuPlugin(val stageCount : Int,
|
||||||
|
val allowZeroLatency : Boolean,
|
||||||
|
val parameter : VfuParameter) extends Plugin[VexRiscv]{
|
||||||
|
def p = parameter
|
||||||
|
|
||||||
|
var bus : VfuBus = null
|
||||||
|
|
||||||
|
lazy val forkStage = pipeline.execute
|
||||||
|
lazy val joinStage = pipeline.stages(Math.min(pipeline.stages.length - 1, pipeline.indexOf(forkStage) + stageCount))
|
||||||
|
|
||||||
|
|
||||||
|
object VFU_ENABLE extends Stageable(Bool())
|
||||||
|
object VFU_IN_FLIGHT extends Stageable(Bool())
|
||||||
|
|
||||||
|
override def setup(pipeline: VexRiscv): Unit = {
|
||||||
|
import pipeline._
|
||||||
|
import pipeline.config._
|
||||||
|
|
||||||
|
bus = master(VfuBus(p))
|
||||||
|
|
||||||
|
val decoderService = pipeline.service(classOf[DecoderService])
|
||||||
|
decoderService.addDefault(VFU_ENABLE, False)
|
||||||
|
|
||||||
|
decoderService.add(
|
||||||
|
key = M"-------------------------0001011",
|
||||||
|
values = List(
|
||||||
|
REGFILE_WRITE_VALID -> True, //If you want to write something back into the integer register file
|
||||||
|
BYPASSABLE_EXECUTE_STAGE -> Bool(stageCount == 0),
|
||||||
|
BYPASSABLE_MEMORY_STAGE -> Bool(stageCount <= 1),
|
||||||
|
RS1_USE -> True,
|
||||||
|
RS2_USE -> True
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override def build(pipeline: VexRiscv): Unit = {
|
||||||
|
import pipeline._
|
||||||
|
import pipeline.config._
|
||||||
|
|
||||||
|
val csr = pipeline plug new Area{
|
||||||
|
val factory = pipeline.service(classOf[CsrInterface])
|
||||||
|
val rounding = Reg(Bits(VfuPlugin.ROUND_MODE_WIDTH bits))
|
||||||
|
|
||||||
|
factory.rw(csrAddress = 0xBC0, bitOffset = 0, that = rounding)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
forkStage plug new Area{
|
||||||
|
import forkStage._
|
||||||
|
val hazard = stages.dropWhile(_ != forkStage).tail.map(s => s.arbitration.isValid && s.input(HAS_SIDE_EFFECT)).orR
|
||||||
|
val scheduleWish = arbitration.isValid && input(VFU_ENABLE)
|
||||||
|
val schedule = scheduleWish && !hazard
|
||||||
|
arbitration.haltItself setWhen(scheduleWish && hazard)
|
||||||
|
|
||||||
|
val hold = RegInit(False) setWhen(schedule) clearWhen(bus.cmd.ready)
|
||||||
|
val fired = RegInit(False) setWhen(bus.cmd.fire) clearWhen(!arbitration.isStuckByOthers)
|
||||||
|
insert(VFU_IN_FLIGHT) := schedule || hold || fired
|
||||||
|
|
||||||
|
bus.cmd.valid := (schedule || hold) && !fired
|
||||||
|
arbitration.haltItself setWhen(bus.cmd.valid && !bus.cmd.ready)
|
||||||
|
|
||||||
|
bus.cmd.instruction := input(INSTRUCTION)
|
||||||
|
bus.cmd.inputs(0) := input(RS1)
|
||||||
|
bus.cmd.inputs(1) := input(RS2)
|
||||||
|
bus.cmd.rounding := csr.rounding
|
||||||
|
}
|
||||||
|
|
||||||
|
joinStage plug new Area{
|
||||||
|
import joinStage._
|
||||||
|
|
||||||
|
val rsp = if(forkStage != joinStage && allowZeroLatency) {
|
||||||
|
bus.rsp.s2mPipe()
|
||||||
|
} else {
|
||||||
|
bus.rsp.combStage()
|
||||||
|
}
|
||||||
|
|
||||||
|
rsp.ready := False
|
||||||
|
when(input(VFU_IN_FLIGHT) && input(REGFILE_WRITE_VALID)){
|
||||||
|
arbitration.haltItself setWhen(!bus.rsp.valid)
|
||||||
|
rsp.ready := !arbitration.isStuckByOthers
|
||||||
|
output(REGFILE_WRITE_DATA) := bus.rsp.output
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pipeline.stages.drop(1).foreach(s => s.output(VFU_IN_FLIGHT) clearWhen(s.arbitration.isStuck))
|
||||||
|
addPrePopTask(() => stages.dropWhile(_ != memory).reverse.dropWhile(_ != joinStage).foreach(s => s.input(VFU_IN_FLIGHT).init(False)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue