mirror of
https://github.com/SpinalHDL/VexRiscv.git
synced 2025-04-24 22:17:05 -04:00
Merge branch 'masterPrerelease'
This commit is contained in:
commit
ee36c36fdd
18 changed files with 584 additions and 58 deletions
|
@ -7,8 +7,8 @@ lazy val root = (project in file(".")).
|
|||
version := "2.0.0"
|
||||
)),
|
||||
libraryDependencies ++= Seq(
|
||||
"com.github.spinalhdl" % "spinalhdl-core_2.11" % "1.3.6",
|
||||
"com.github.spinalhdl" % "spinalhdl-lib_2.11" % "1.3.6",
|
||||
"com.github.spinalhdl" % "spinalhdl-core_2.11" % "1.3.8",
|
||||
"com.github.spinalhdl" % "spinalhdl-lib_2.11" % "1.3.8",
|
||||
"org.scalatest" % "scalatest_2.11" % "2.2.1",
|
||||
"org.yaml" % "snakeyaml" % "1.8"
|
||||
),
|
||||
|
|
|
@ -13,7 +13,9 @@ import spinal.lib.com.uart.{Apb3UartCtrl, Uart, UartCtrlGenerics, UartCtrlMemory
|
|||
import spinal.lib.graphic.RgbConfig
|
||||
import spinal.lib.graphic.vga.{Axi4VgaCtrl, Axi4VgaCtrlGenerics, Vga}
|
||||
import spinal.lib.io.TriStateArray
|
||||
import spinal.lib.memory.sdram.SdramGeneration.SDR
|
||||
import spinal.lib.memory.sdram._
|
||||
import spinal.lib.memory.sdram.sdr.{Axi4SharedSdramCtrl, IS42x320D, SdramInterface, SdramTimings}
|
||||
import spinal.lib.misc.HexTools
|
||||
import spinal.lib.soc.pinsec.{PinsecTimerCtrl, PinsecTimerCtrlExternal}
|
||||
import spinal.lib.system.debugger.{JtagAxi4SharedDebugger, JtagBridge, SystemDebugger, SystemDebuggerConfig}
|
||||
|
@ -412,6 +414,7 @@ object BrieyDe0Nano{
|
|||
def main(args: Array[String]) {
|
||||
object IS42x160G {
|
||||
def layout = SdramLayout(
|
||||
generation = SDR,
|
||||
bankWidth = 2,
|
||||
columnWidth = 9,
|
||||
rowWidth = 13,
|
||||
|
|
72
src/main/scala/vexriscv/demo/GenCustomInterrupt.scala
Normal file
72
src/main/scala/vexriscv/demo/GenCustomInterrupt.scala
Normal file
|
@ -0,0 +1,72 @@
|
|||
package vexriscv.demo
|
||||
|
||||
import spinal.core._
|
||||
import vexriscv.plugin._
|
||||
import vexriscv.{VexRiscv, VexRiscvConfig, plugin}
|
||||
|
||||
/**
|
||||
* Created by spinalvm on 15.06.17.
|
||||
*/
|
||||
object GenCustomInterrupt extends App{
|
||||
def cpu() = new VexRiscv(
|
||||
config = VexRiscvConfig(
|
||||
plugins = List(
|
||||
new UserInterruptPlugin(
|
||||
interruptName = "miaou",
|
||||
code = 20
|
||||
),
|
||||
new UserInterruptPlugin(
|
||||
interruptName = "rawrrr",
|
||||
code = 24
|
||||
),
|
||||
new CsrPlugin(
|
||||
CsrPluginConfig.smallest.copy(
|
||||
xtvecModeGen = true,
|
||||
mtvecAccess = CsrAccess.WRITE_ONLY
|
||||
)
|
||||
),
|
||||
new IBusSimplePlugin(
|
||||
resetVector = 0x80000000l,
|
||||
cmdForkOnSecondStage = false,
|
||||
cmdForkPersistence = false,
|
||||
prediction = NONE,
|
||||
catchAccessFault = false,
|
||||
compressedGen = false
|
||||
),
|
||||
new DBusSimplePlugin(
|
||||
catchAddressMisaligned = false,
|
||||
catchAccessFault = false
|
||||
),
|
||||
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 YamlPlugin("cpu0.yaml")
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
SpinalVerilog(cpu())
|
||||
}
|
77
src/main/scala/vexriscv/demo/GenSmallAndProductiveCfu.scala
Normal file
77
src/main/scala/vexriscv/demo/GenSmallAndProductiveCfu.scala
Normal file
|
@ -0,0 +1,77 @@
|
|||
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(
|
||||
stageCount = 1,
|
||||
allowZeroLatency = true,
|
||||
encoding = M"000000-------------------0001011",
|
||||
busParameter = CfuBusParameter(
|
||||
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())
|
||||
}
|
|
@ -119,7 +119,12 @@ make run IBUS=CACHED DBUS=CACHED DEBUG_PLUGIN=STD SUPERVISOR=yes CSR=yes COMPRE
|
|||
rm -rf cpio
|
||||
mkdir cpio
|
||||
cd cpio
|
||||
cpio -idv < ../rootfs.cpio
|
||||
sudo cpio -i < ../rootfs.cpio
|
||||
cd ..
|
||||
|
||||
rm rootfs.cpio
|
||||
cd cpio
|
||||
sudo find | sudo cpio -H newc -o > ../rootfs.cpio
|
||||
cd ..
|
||||
|
||||
make clean run IBUS=CACHED DBUS=CACHED DEBUG_PLUGIN=STD DHRYSTONE=yes SUPERVISOR=yes MMU=yes CSR=yes COMPRESSED=no MUL=yes DIV=yes LRSC=yes AMO=yes REDO=10 TRACE=no COREMARK=yes LINUX_REGRESSION=yes RUN_HEX=~/pro/riscv/zephyr/samples/synchronization/build/zephyr/zephyr.hex
|
||||
|
|
|
@ -65,7 +65,7 @@ object MuraxConfig{
|
|||
SpiXdrMasterCtrl.Parameters(8, 12, SpiXdrParameter(2, 2, 1)).addFullDuplex(0,1,false),
|
||||
cmdFifoDepth = 32,
|
||||
rspFifoDepth = 32,
|
||||
xip = SpiXdrMasterCtrl.XipBusParameters(addressWidth = 24, dataWidth = 32)
|
||||
xip = SpiXdrMasterCtrl.XipBusParameters(addressWidth = 24, lengthWidth = 2)
|
||||
)),
|
||||
hardwareBreakpointCount = if(withXip) 3 else 0,
|
||||
cpuPlugins = ArrayBuffer( //DebugPlugin added by the toplevel
|
||||
|
@ -298,13 +298,7 @@ case class Murax(config : MuraxConfig) extends Component{
|
|||
val accessBus = new PipelinedMemoryBus(PipelinedMemoryBusConfig(24,32))
|
||||
mainBusMapping += accessBus -> (0xE0000000l, 16 MB)
|
||||
|
||||
ctrl.io.xip.cmd.valid <> (accessBus.cmd.valid && !accessBus.cmd.write)
|
||||
ctrl.io.xip.cmd.ready <> accessBus.cmd.ready
|
||||
ctrl.io.xip.cmd.payload <> accessBus.cmd.address
|
||||
|
||||
ctrl.io.xip.rsp.valid <> accessBus.rsp.valid
|
||||
ctrl.io.xip.rsp.payload <> accessBus.rsp.data
|
||||
|
||||
ctrl.io.xip.fromPipelinedMemoryBus() << accessBus
|
||||
val bootloader = Apb3Rom("src/main/c/murax/xipBootloader/crt.bin")
|
||||
apbMapping += bootloader.io.apb -> (0x1E000, 4 kB)
|
||||
})
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
package vexriscv.demo
|
||||
|
||||
import spinal.core._
|
||||
import spinal.lib._
|
||||
import spinal.lib.eda.bench._
|
||||
import spinal.lib.eda.icestorm.IcestormStdTargets
|
||||
import vexriscv.VexRiscv
|
||||
import vexriscv.plugin.{DecoderSimplePlugin, KeepAttribute}
|
||||
import vexriscv.plugin.{DecoderSimplePlugin}
|
||||
|
||||
import scala.collection.mutable.ArrayBuffer
|
||||
import scala.util.Random
|
||||
|
|
|
@ -22,7 +22,8 @@ case class InstructionCacheConfig( cacheSize : Int,
|
|||
asyncTagMemory : Boolean,
|
||||
twoCycleCache : Boolean = true,
|
||||
twoCycleRam : Boolean = false,
|
||||
preResetFlush : Boolean = false){
|
||||
preResetFlush : Boolean = false,
|
||||
bypassGen : Boolean = false ){
|
||||
|
||||
assert(!(twoCycleRam && !twoCycleCache))
|
||||
|
||||
|
@ -108,8 +109,8 @@ case class InstructionCacheCpuFetch(p : InstructionCacheConfig) extends Bundle w
|
|||
val isRemoved = Bool()
|
||||
val pc = UInt(p.addressWidth bits)
|
||||
val data = Bits(p.cpuDataWidth bits)
|
||||
val dataBypassValid = Bool()
|
||||
val dataBypass = Bits(p.cpuDataWidth bits)
|
||||
val dataBypassValid = p.bypassGen generate Bool()
|
||||
val dataBypass = p.bypassGen generate Bits(p.cpuDataWidth bits)
|
||||
val mmuBus = MemoryTranslatorBus()
|
||||
val physicalAddress = UInt(p.addressWidth bits)
|
||||
val cacheMiss, error, mmuRefilling, mmuException, isUser = ifGen(!p.twoCycleCache)(Bool)
|
||||
|
@ -325,7 +326,7 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{
|
|||
val lineLoader = new Area{
|
||||
val fire = False
|
||||
val valid = RegInit(False) clearWhen(fire)
|
||||
val address = Reg(UInt(addressWidth bits))
|
||||
val address = KeepAttribute(Reg(UInt(addressWidth bits)))
|
||||
val hadError = RegInit(False) clearWhen(fire)
|
||||
val flushPending = RegInit(True)
|
||||
|
||||
|
@ -363,7 +364,7 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{
|
|||
io.mem.cmd.size := log2Up(p.bytePerLine)
|
||||
|
||||
val wayToAllocate = Counter(wayCount, !valid)
|
||||
val wordIndex = Reg(UInt(log2Up(memWordPerLine) bits)) init(0)
|
||||
val wordIndex = KeepAttribute(Reg(UInt(log2Up(memWordPerLine) bits)) init(0))
|
||||
|
||||
|
||||
val write = new Area{
|
||||
|
@ -415,15 +416,16 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{
|
|||
val id = OHToUInt(hits)
|
||||
val error = read.waysValues.map(_.tag.error).read(id)
|
||||
val data = read.waysValues.map(_.data).read(id)
|
||||
val word = data.subdivideIn(cpuDataWidth bits).read(io.cpu.fetch.pc(memWordToCpuWordRange))
|
||||
io.cpu.fetch.data := (io.cpu.fetch.dataBypassValid ? io.cpu.fetch.dataBypass | word)
|
||||
val word = if(cpuDataWidth == memDataWidth) CombInit(data) else data.subdivideIn(cpuDataWidth bits).read(io.cpu.fetch.pc(memWordToCpuWordRange))
|
||||
io.cpu.fetch.data := (if(p.bypassGen) (io.cpu.fetch.dataBypassValid ? io.cpu.fetch.dataBypass | word) else word)
|
||||
if(twoCycleCache){
|
||||
io.cpu.decode.data := RegNextWhen(io.cpu.fetch.data,!io.cpu.decode.isStuck)
|
||||
}
|
||||
}
|
||||
|
||||
if(twoCycleRam && wayCount == 1){
|
||||
io.cpu.fetch.data := (io.cpu.fetch.dataBypassValid ? io.cpu.fetch.dataBypass | read.waysValues.head.data.subdivideIn(cpuDataWidth bits).read(io.cpu.fetch.pc(memWordToCpuWordRange)))
|
||||
val cacheData = if(cpuDataWidth == memDataWidth) CombInit(read.waysValues.head.data) else read.waysValues.head.data.subdivideIn(cpuDataWidth bits).read(io.cpu.fetch.pc(memWordToCpuWordRange))
|
||||
io.cpu.fetch.data := (if(p.bypassGen) (io.cpu.fetch.dataBypassValid ? io.cpu.fetch.dataBypass | cacheData) else cacheData)
|
||||
}
|
||||
|
||||
io.cpu.fetch.mmuBus.cmd.isValid := io.cpu.fetch.isValid
|
||||
|
@ -458,8 +460,8 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{
|
|||
val id = OHToUInt(hits)
|
||||
val error = tags(id).error
|
||||
val data = fetchStage.read.waysValues.map(way => stage(way.data)).read(id)
|
||||
val word = data.subdivideIn(cpuDataWidth bits).read(io.cpu.decode.pc(memWordToCpuWordRange))
|
||||
when(stage(io.cpu.fetch.dataBypassValid)){
|
||||
val word = if(cpuDataWidth == memDataWidth) data else data.subdivideIn(cpuDataWidth bits).read(io.cpu.decode.pc(memWordToCpuWordRange))
|
||||
if(p.bypassGen) when(stage(io.cpu.fetch.dataBypassValid)){
|
||||
word := stage(io.cpu.fetch.dataBypass)
|
||||
}
|
||||
io.cpu.decode.data := word
|
||||
|
|
|
@ -53,7 +53,8 @@ trait PredictionInterface{
|
|||
class BranchPlugin(earlyBranch : Boolean,
|
||||
catchAddressMisaligned : Boolean = false,
|
||||
fenceiGenAsAJump : Boolean = false,
|
||||
fenceiGenAsANop : Boolean = false) extends Plugin[VexRiscv] with PredictionInterface{
|
||||
fenceiGenAsANop : Boolean = false,
|
||||
decodeBranchSrc2 : Boolean = false) extends Plugin[VexRiscv] with PredictionInterface{
|
||||
|
||||
|
||||
def catchAddressMisalignedForReal = catchAddressMisaligned && !pipeline(RVC_GEN)
|
||||
|
@ -310,6 +311,8 @@ class BranchPlugin(earlyBranch : Boolean,
|
|||
//Do branch calculations (conditions + target PC)
|
||||
object NEXT_PC extends Stageable(UInt(32 bits))
|
||||
object TARGET_MISSMATCH extends Stageable(Bool)
|
||||
object BRANCH_SRC2 extends Stageable(UInt(32 bits))
|
||||
val branchSrc2Stage = if(decodeBranchSrc2) decode else execute
|
||||
execute plug new Area {
|
||||
import execute._
|
||||
|
||||
|
@ -328,15 +331,16 @@ class BranchPlugin(earlyBranch : Boolean,
|
|||
)
|
||||
)
|
||||
|
||||
val imm = IMM(input(INSTRUCTION))
|
||||
val branch_src1 = (input(BRANCH_CTRL) === BranchCtrlEnum.JALR) ? input(RS1).asUInt | input(PC)
|
||||
val branch_src2 = input(BRANCH_CTRL).mux(
|
||||
|
||||
val imm = IMM(branchSrc2Stage.input(INSTRUCTION))
|
||||
branchSrc2Stage.insert(BRANCH_SRC2) := branchSrc2Stage.input(BRANCH_CTRL).mux(
|
||||
BranchCtrlEnum.JAL -> imm.j_sext,
|
||||
BranchCtrlEnum.JALR -> imm.i_sext,
|
||||
default -> imm.b_sext
|
||||
).asUInt
|
||||
|
||||
val branchAdder = branch_src1 + branch_src2
|
||||
val branchAdder = branch_src1 + input(BRANCH_SRC2)
|
||||
insert(BRANCH_CALC) := branchAdder(31 downto 1) @@ "0"
|
||||
insert(NEXT_PC) := input(PC) + (if(pipeline(RVC_GEN)) ((input(IS_RVC)) ? U(2) | U(4)) else 4)
|
||||
insert(TARGET_MISSMATCH) := decode.input(PC) =/= input(BRANCH_CALC)
|
||||
|
|
289
src/main/scala/vexriscv/plugin/CfuPlugin.scala
Normal file
289
src/main/scala/vexriscv/plugin/CfuPlugin.scala
Normal file
|
@ -0,0 +1,289 @@
|
|||
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}
|
||||
|
||||
case class CfuPluginParameter(
|
||||
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 : Boolean,
|
||||
CFU_FLOW_RESP_READY_ALWAYS : Boolean)
|
||||
|
||||
case class CfuBusParameter(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 : Boolean,
|
||||
CFU_FLOW_RESP_READY_ALWAYS : Boolean)
|
||||
|
||||
case class CfuCmd( p : CfuBusParameter ) 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)
|
||||
|
||||
def weakAssignFrom(m : CfuCmd): Unit ={
|
||||
def s = this
|
||||
WeakConnector(m, s, m.function_id, s.function_id, defaultValue = null, allowUpSize = false, allowDownSize = true , allowDrop = true)
|
||||
WeakConnector(m, s, m.reorder_id, s.reorder_id, defaultValue = null, allowUpSize = false , allowDownSize = false, allowDrop = false)
|
||||
WeakConnector(m, s, m.request_id, s.request_id, defaultValue = null, allowUpSize = false, allowDownSize = false, allowDrop = false)
|
||||
s.inputs := m.inputs
|
||||
}
|
||||
}
|
||||
|
||||
case class CfuRsp(p : CfuBusParameter) 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)
|
||||
|
||||
def weakAssignFrom(m : CfuRsp): Unit ={
|
||||
def s = this
|
||||
s.response_ok := m.response_ok
|
||||
s.response_id := m.response_id
|
||||
s.outputs := m.outputs
|
||||
}
|
||||
}
|
||||
|
||||
case class CfuBus(p : CfuBusParameter) extends Bundle with IMasterSlave{
|
||||
val cmd = Stream(CfuCmd(p))
|
||||
val rsp = Stream(CfuRsp(p))
|
||||
|
||||
def <<(m : CfuBus) : Unit = {
|
||||
val s = this
|
||||
s.cmd.arbitrationFrom(m.cmd)
|
||||
m.rsp.arbitrationFrom(s.rsp)
|
||||
|
||||
s.cmd.weakAssignFrom(m.cmd)
|
||||
m.rsp.weakAssignFrom(s.rsp)
|
||||
}
|
||||
|
||||
override def asMaster(): Unit = {
|
||||
master(cmd)
|
||||
slave(rsp)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
class CfuPlugin( val stageCount : Int,
|
||||
val allowZeroLatency : Boolean,
|
||||
val encoding : MaskedLiteral,
|
||||
val busParameter : CfuBusParameter) extends Plugin[VexRiscv]{
|
||||
def p = busParameter
|
||||
|
||||
assert(p.CFU_INPUTS <= 2)
|
||||
assert(p.CFU_OUTPUTS == 1)
|
||||
assert(p.CFU_FUNCTION_ID_W == 3)
|
||||
|
||||
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) + stageCount))
|
||||
|
||||
|
||||
val CFU_ENABLE = new Stageable(Bool()).setCompositeName(this, "CFU_ENABLE")
|
||||
val CFU_IN_FLIGHT = new Stageable(Bool()).setCompositeName(this, "CFU_IN_FLIGHT")
|
||||
|
||||
|
||||
override def setup(pipeline: VexRiscv): Unit = {
|
||||
import pipeline._
|
||||
import pipeline.config._
|
||||
|
||||
bus = master(CfuBus(p))
|
||||
joinException = pipeline.service(classOf[ExceptionService]).newExceptionPort(joinStage)
|
||||
|
||||
val decoderService = pipeline.service(classOf[DecoderService])
|
||||
decoderService.addDefault(CFU_ENABLE, False)
|
||||
|
||||
//custom-0
|
||||
decoderService.add(List(
|
||||
encoding -> List(
|
||||
CFU_ENABLE -> True,
|
||||
REGFILE_WRITE_VALID -> True,
|
||||
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._
|
||||
|
||||
|
||||
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 := U(input(INSTRUCTION)(14 downto 12)).resized
|
||||
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._
|
||||
|
||||
//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(p.CFU_FLOW_RESP_READY_ALWAYS){
|
||||
bus.rsp.toFlow.toStream.queueLowLatency(
|
||||
size = stageCount + 1,
|
||||
latency = 0
|
||||
)
|
||||
} else if(forkStage != joinStage && 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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
addPrePopTask(() => stages.dropWhile(_ != memory).reverse.dropWhile(_ != joinStage).foreach(s => s.input(CFU_IN_FLIGHT).init(False)))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
object CfuTest{
|
||||
|
||||
// stageCount = 0,
|
||||
// allowZeroLatency = true,
|
||||
def getCfuParameter() = CfuBusParameter(
|
||||
CFU_VERSION = 0,
|
||||
CFU_INTERFACE_ID_W = 0,
|
||||
CFU_FUNCTION_ID_W = 3,
|
||||
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
|
||||
)
|
||||
}
|
||||
case class CfuTest() extends Component{
|
||||
val io = new Bundle {
|
||||
val bus = slave(CfuBus(CfuTest.getCfuParameter()))
|
||||
}
|
||||
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.outputs(0) := ~(io.bus.cmd.inputs(0) & io.bus.cmd.inputs(1))
|
||||
}
|
||||
|
||||
|
||||
case class CfuBb(p : CfuBusParameter) extends BlackBox{
|
||||
val io = new Bundle {
|
||||
val clk, reset = in Bool()
|
||||
val bus = slave(CfuBus(p))
|
||||
}
|
||||
|
||||
mapCurrentClockDomain(io.clk, io.reset)
|
||||
}
|
||||
|
||||
//case class CfuGray(p : CfuBusParameter) extends BlackBox{
|
||||
// val req_function_id = in Bits(p.CFU_FUNCTION_ID_W)
|
||||
// val req_data = in Bits(p.CFU_REQ_INPUTS)
|
||||
// val resp_data = in Bits(p.CFU_FUNCTION_ID_W)
|
||||
// input `CFU_FUNCTION_ID req_function_id,
|
||||
// input [CFU_REQ_INPUTS-1:0]`CFU_REQ_DATA req_data,
|
||||
// output [CFU_RESP_OUTPUTS-1:0]`CFU_RESP_DATA resp_data
|
||||
// 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.outputs(0) := ~(io.bus.cmd.inputs(0) & io.bus.cmd.inputs(1))
|
||||
//}
|
||||
|
||||
|
||||
case class CfuDecoder(p : CfuBusParameter,
|
||||
mappings : Seq[AddressMapping],
|
||||
pendingMax : Int = 3) extends Component{
|
||||
val io = new Bundle {
|
||||
val input = slave(CfuBus(p))
|
||||
val outputs = Vec(master(CfuBus(p)), mappings.size)
|
||||
}
|
||||
val hasDefault = mappings.contains(DefaultMapping)
|
||||
val logic = if(hasDefault && mappings.size == 1){
|
||||
io.outputs(0) << io.input
|
||||
} else new Area {
|
||||
val hits = Vec(Bool, mappings.size)
|
||||
for (portId <- 0 until mappings.length) yield {
|
||||
val slaveBus = io.outputs(portId)
|
||||
val memorySpace = mappings(portId)
|
||||
val hit = hits(portId)
|
||||
hit := (memorySpace match {
|
||||
case DefaultMapping => !hits.filterNot(_ == hit).orR
|
||||
case _ => memorySpace.hit(io.input.cmd.function_id)
|
||||
})
|
||||
slaveBus.cmd.valid := io.input.cmd.valid && hit
|
||||
slaveBus.cmd.payload := io.input.cmd.payload.resized
|
||||
}
|
||||
val noHit = if (!hasDefault) !hits.orR else False
|
||||
io.input.cmd.ready := (hits, io.outputs).zipped.map(_ && _.cmd.ready).orR || noHit
|
||||
|
||||
val rspPendingCounter = Reg(UInt(log2Up(pendingMax + 1) bits)) init(0)
|
||||
rspPendingCounter := rspPendingCounter + U(io.input.cmd.fire) - U(io.input.rsp.fire)
|
||||
val rspHits = RegNextWhen(hits, io.input.cmd.fire)
|
||||
val rspPending = rspPendingCounter =/= 0
|
||||
val rspNoHitValid = if (!hasDefault) !rspHits.orR else False
|
||||
val rspNoHit = !hasDefault generate new Area{
|
||||
val doIt = RegInit(False) clearWhen(io.input.rsp.fire) setWhen(io.input.cmd.fire && noHit)
|
||||
val response_id = RegNextWhen(io.input.cmd.request_id, io.input.cmd.fire)
|
||||
}
|
||||
|
||||
io.input.rsp.valid := io.outputs.map(_.rsp.valid).orR || (rspPending && rspNoHitValid)
|
||||
io.input.rsp.payload := io.outputs.map(_.rsp.payload).read(OHToUInt(rspHits))
|
||||
if(!hasDefault) when(rspNoHit.doIt) {
|
||||
io.input.rsp.valid := True
|
||||
io.input.rsp.response_ok := False
|
||||
io.input.rsp.response_id := rspNoHit.response_id
|
||||
}
|
||||
for(output <- io.outputs) output.rsp.ready := io.input.rsp.ready
|
||||
|
||||
val cmdWait = (rspPending && (hits =/= rspHits || rspNoHitValid)) || rspPendingCounter === pendingMax
|
||||
when(cmdWait) {
|
||||
io.input.cmd.ready := False
|
||||
io.outputs.foreach(_.cmd.valid := False)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -69,7 +69,8 @@ case class CsrPluginConfig(
|
|||
midelegAccess : CsrAccess = CsrAccess.NONE,
|
||||
pipelineCsrRead : Boolean = false,
|
||||
pipelinedInterrupt : Boolean = true,
|
||||
deterministicInteruptionEntry : Boolean = false //Only used for simulatation purposes
|
||||
deterministicInteruptionEntry : Boolean = false, //Only used for simulatation purposes
|
||||
wfiOutput : Boolean = false
|
||||
){
|
||||
assert(!ucycleAccess.canWrite)
|
||||
def privilegeGen = userGen || supervisorGen
|
||||
|
@ -311,8 +312,11 @@ trait CsrInterface{
|
|||
trait IContextSwitching{
|
||||
def isContextSwitching : Bool
|
||||
}
|
||||
trait IWake{
|
||||
def askWake() : Unit
|
||||
}
|
||||
|
||||
class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with ExceptionService with PrivilegeService with InterruptionInhibitor with ExceptionInhibitor with IContextSwitching with CsrInterface{
|
||||
class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with ExceptionService with PrivilegeService with InterruptionInhibitor with ExceptionInhibitor with IContextSwitching with CsrInterface with IWake{
|
||||
import config._
|
||||
import CsrAccess._
|
||||
|
||||
|
@ -322,7 +326,6 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep
|
|||
|
||||
//Mannage ExceptionService calls
|
||||
val exceptionPortsInfos = ArrayBuffer[ExceptionPortInfo]()
|
||||
def exceptionCodeWidth = 4
|
||||
override def newExceptionPort(stage : Stage, priority : Int = 0) = {
|
||||
val interface = Flow(ExceptionCause())
|
||||
exceptionPortsInfos += ExceptionPortInfo(interface,stage,priority)
|
||||
|
@ -332,6 +335,7 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep
|
|||
var exceptionPendings : Vec[Bool] = null
|
||||
override def isExceptionPending(stage : Stage): Bool = exceptionPendings(pipeline.stages.indexOf(stage))
|
||||
|
||||
var redoInterface : Flow[UInt] = null
|
||||
var jumpInterface : Flow[UInt] = null
|
||||
var timerInterrupt, externalInterrupt, softwareInterrupt : Bool = null
|
||||
var externalInterruptS : Bool = null
|
||||
|
@ -339,6 +343,11 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep
|
|||
var privilege : UInt = null
|
||||
var selfException : Flow[ExceptionCause] = null
|
||||
var contextSwitching : Bool = null
|
||||
var thirdPartyWake : Bool = null
|
||||
var inWfi : Bool = null
|
||||
|
||||
override def askWake(): Unit = thirdPartyWake := True
|
||||
|
||||
override def isContextSwitching = contextSwitching
|
||||
|
||||
object EnvCtrlEnum extends SpinalEnum(binarySequential){
|
||||
|
@ -359,6 +368,16 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep
|
|||
|
||||
val csrMapping = new CsrMapping()
|
||||
|
||||
//Print CSR mapping
|
||||
def printCsr() {
|
||||
for ((address, things) <- csrMapping.mapping) {
|
||||
println("0x" + address.toHexString + " => ")
|
||||
for (thing <- things) {
|
||||
println(" - " + thing)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Interruption and exception data model
|
||||
case class Delegator(var enable : Bool, privilege : Int)
|
||||
case class InterruptSpec(var cond : Bool, id : Int, privilege : Int, delegators : List[Delegator])
|
||||
|
@ -379,6 +398,10 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep
|
|||
override def setup(pipeline: VexRiscv): Unit = {
|
||||
import pipeline.config._
|
||||
|
||||
inWfi = False.addTag(Verilator.public)
|
||||
|
||||
thirdPartyWake = False
|
||||
|
||||
val defaultEnv = List[(Stageable[_ <: BaseType],Any)](
|
||||
)
|
||||
|
||||
|
@ -422,6 +445,13 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep
|
|||
jumpInterface.valid := False
|
||||
jumpInterface.payload.assignDontCare()
|
||||
|
||||
|
||||
if(supervisorGen) {
|
||||
redoInterface = pcManagerService.createJumpInterface(pipeline.execute)
|
||||
redoInterface.valid := False
|
||||
redoInterface.payload.assignDontCare()
|
||||
}
|
||||
|
||||
exceptionPendings = Vec(Bool, pipeline.stages.length)
|
||||
timerInterrupt = in Bool() setName("timerInterrupt")
|
||||
externalInterrupt = in Bool() setName("externalInterrupt")
|
||||
|
@ -459,6 +489,7 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep
|
|||
import pipeline._
|
||||
import pipeline.config._
|
||||
val fetcher = service(classOf[IBusFetcher])
|
||||
val trapCodeWidth = log2Up((List(16) ++ interruptSpecs.map(_.id + 1) ++ exceptionPortsInfos.map(p => 1 << widthOf(p.port.code))).max)
|
||||
|
||||
//Define CSR mapping utilities
|
||||
implicit class CsrAccessPimper(csrAccess : CsrAccess){
|
||||
|
@ -511,7 +542,7 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep
|
|||
val mscratch = if(mscratchGen) Reg(Bits(xlen bits)) else null
|
||||
val mcause = new Area{
|
||||
val interrupt = Reg(Bool)
|
||||
val exceptionCode = Reg(UInt(exceptionCodeWidth bits))
|
||||
val exceptionCode = Reg(UInt(trapCodeWidth bits))
|
||||
}
|
||||
val mtval = Reg(UInt(xlen bits))
|
||||
val mcycle = Reg(UInt(64 bits)) randBoot()
|
||||
|
@ -582,7 +613,7 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep
|
|||
|
||||
val scause = new Area {
|
||||
val interrupt = Reg(Bool)
|
||||
val exceptionCode = Reg(UInt(exceptionCodeWidth bits))
|
||||
val exceptionCode = Reg(UInt(trapCodeWidth bits))
|
||||
}
|
||||
val stval = Reg(UInt(xlen bits))
|
||||
val sepc = Reg(UInt(xlen bits))
|
||||
|
@ -610,6 +641,13 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep
|
|||
scauseAccess(CSR.SCAUSE, xlen-1 -> scause.interrupt, 0 -> scause.exceptionCode)
|
||||
sbadaddrAccess(CSR.SBADADDR, stval)
|
||||
satpAccess(CSR.SATP, 31 -> satp.MODE, 22 -> satp.ASID, 0 -> satp.PPN)
|
||||
|
||||
|
||||
if(supervisorGen) onWrite(CSR.SATP){
|
||||
execute.arbitration.flushNext := True
|
||||
redoInterface.valid := True
|
||||
redoInterface.payload := execute.input(PC) + 4
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -733,7 +771,7 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep
|
|||
//Process interrupt request, code and privilege
|
||||
val interrupt = new Area {
|
||||
val valid = if(pipelinedInterrupt) RegNext(False) init(False) else False
|
||||
val code = if(pipelinedInterrupt) Reg(UInt(4 bits)) else UInt(4 bits).assignDontCare()
|
||||
val code = if(pipelinedInterrupt) Reg(UInt(trapCodeWidth bits)) else UInt(trapCodeWidth bits).assignDontCare()
|
||||
var privilegs = if (supervisorGen) List(1, 3) else List(3)
|
||||
val targetPrivilege = if(pipelinedInterrupt) Reg(UInt(2 bits)) else UInt(2 bits).assignDontCare()
|
||||
val privilegeAllowInterrupts = mutable.HashMap[Int, Bool]()
|
||||
|
@ -838,6 +876,10 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep
|
|||
}
|
||||
}
|
||||
|
||||
if(exceptionPortCtrl == null){
|
||||
if(mbadaddrAccess == CsrAccess.READ_ONLY) mtval := 0
|
||||
if(sbadaddrAccess == CsrAccess.READ_ONLY) stval := 0
|
||||
}
|
||||
|
||||
lastStage plug new Area{
|
||||
import lastStage._
|
||||
|
@ -885,8 +927,8 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep
|
|||
execute plug new Area{
|
||||
import execute._
|
||||
//Manage WFI instructions
|
||||
val inWfi = False.addTag(Verilator.public)
|
||||
val wfiWake = RegNext(interruptSpecs.map(_.cond).orR) init(False)
|
||||
if(wfiOutput) out(inWfi)
|
||||
val wfiWake = RegNext(interruptSpecs.map(_.cond).orR || thirdPartyWake) init(False)
|
||||
if(wfiGenAsWait) when(arbitration.isValid && input(ENV_CTRL) === EnvCtrlEnum.WFI){
|
||||
inWfi := True
|
||||
when(!wfiWake){
|
||||
|
@ -1044,3 +1086,18 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class UserInterruptPlugin(interruptName : String, code : Int, privilege : Int = 3) extends Plugin[VexRiscv]{
|
||||
var interrupt, interruptEnable : Bool = null
|
||||
override def setup(pipeline: VexRiscv): Unit = {
|
||||
val csr = pipeline.service(classOf[CsrPlugin])
|
||||
interrupt = in.Bool().setName(interruptName)
|
||||
val interruptPending = RegNext(interrupt) init(False)
|
||||
val interruptEnable = RegInit(False).setName(interruptName + "_enable")
|
||||
csr.addInterrupt(interruptPending , code, privilege, Nil)
|
||||
csr.r(csrAddress = CSR.MIP, bitOffset = code,interruptPending)
|
||||
csr.rw(csrAddress = CSR.MIE, bitOffset = code, interruptEnable)
|
||||
}
|
||||
override def build(pipeline: VexRiscv): Unit = {}
|
||||
}
|
|
@ -225,7 +225,13 @@ class DBusCachedPlugin(val config : DataCacheConfig,
|
|||
arbitration.haltItself := True
|
||||
}
|
||||
|
||||
if(relaxedMemoryTranslationRegister) insert(MEMORY_VIRTUAL_ADDRESS) := cache.io.cpu.execute.address
|
||||
if(relaxedMemoryTranslationRegister) {
|
||||
insert(MEMORY_VIRTUAL_ADDRESS) := cache.io.cpu.execute.address
|
||||
memory.input(MEMORY_VIRTUAL_ADDRESS)
|
||||
if(writeBack != null) addPrePopTask( () =>
|
||||
KeepAttribute(memory.input(MEMORY_VIRTUAL_ADDRESS).getDrivingReg)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val mmuAndBufferStage = if(writeBack != null) memory else execute
|
||||
|
|
|
@ -246,6 +246,11 @@ class DebugPlugin(val debugClockDomain : ClockDomain, hardwareBreakpointCount :
|
|||
}
|
||||
if(pipeline.things.contains(DEBUG_BYPASS_CACHE)) pipeline(DEBUG_BYPASS_CACHE) := True
|
||||
}
|
||||
|
||||
val wakeService = serviceElse(classOf[IWake], null)
|
||||
if(wakeService != null) when(haltIt){
|
||||
wakeService.askWake()
|
||||
}
|
||||
}}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,7 +61,7 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l,
|
|||
var redoBranch : Flow[UInt] = null
|
||||
var decodeExceptionPort : Flow[ExceptionCause] = null
|
||||
val tightlyCoupledPorts = ArrayBuffer[TightlyCoupledPort]()
|
||||
|
||||
def tightlyGen = tightlyCoupledPorts.nonEmpty
|
||||
|
||||
def newTightlyCoupledPort(p : TightlyCoupledPortParameter) = {
|
||||
val port = TightlyCoupledPort(p, null)
|
||||
|
@ -125,7 +125,7 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l,
|
|||
import pipeline.config._
|
||||
|
||||
pipeline plug new FetchArea(pipeline) {
|
||||
val cache = new InstructionCache(IBusCachedPlugin.this.config)
|
||||
val cache = new InstructionCache(IBusCachedPlugin.this.config.copy(bypassGen = tightlyGen))
|
||||
iBus = master(new InstructionCacheMemBus(IBusCachedPlugin.this.config)).setName("iBus")
|
||||
iBus <> cache.io.mem
|
||||
iBus.cmd.address.allowOverride := cache.io.mem.cmd.address
|
||||
|
@ -165,8 +165,8 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l,
|
|||
val tightlyCoupledHits = RegNextWhen(s0.tightlyCoupledHits, stages(1).input.ready)
|
||||
val tightlyCoupledHit = RegNextWhen(s0.tightlyCoupledHit, stages(1).input.ready)
|
||||
|
||||
cache.io.cpu.fetch.dataBypassValid := tightlyCoupledHit
|
||||
cache.io.cpu.fetch.dataBypass := (if(tightlyCoupledPorts.isEmpty) B(0) else MuxOH(tightlyCoupledHits, tightlyCoupledPorts.map(e => CombInit(e.bus.data))))
|
||||
if(tightlyGen) cache.io.cpu.fetch.dataBypassValid := tightlyCoupledHit
|
||||
if(tightlyGen) cache.io.cpu.fetch.dataBypass := MuxOH(tightlyCoupledHits, tightlyCoupledPorts.map(e => CombInit(e.bus.data)))
|
||||
|
||||
//Connect fetch cache side
|
||||
cache.io.cpu.fetch.isValid := stages(1).input.valid && !tightlyCoupledHit
|
||||
|
|
|
@ -3,7 +3,8 @@ import vexriscv._
|
|||
import vexriscv.VexRiscv
|
||||
import spinal.core._
|
||||
|
||||
class MulPlugin extends Plugin[VexRiscv]{
|
||||
//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]{
|
||||
object MUL_LL extends Stageable(UInt(32 bits))
|
||||
object MUL_LH extends Stageable(SInt(34 bits))
|
||||
object MUL_HL extends Stageable(SInt(34 bits))
|
||||
|
@ -19,8 +20,8 @@ class MulPlugin extends Plugin[VexRiscv]{
|
|||
|
||||
|
||||
val actions = List[(Stageable[_ <: BaseType],Any)](
|
||||
SRC1_CTRL -> Src1CtrlEnum.RS,
|
||||
SRC2_CTRL -> Src2CtrlEnum.RS,
|
||||
// SRC1_CTRL -> Src1CtrlEnum.RS,
|
||||
// SRC2_CTRL -> Src2CtrlEnum.RS,
|
||||
REGFILE_WRITE_VALID -> True,
|
||||
BYPASSABLE_EXECUTE_STAGE -> False,
|
||||
BYPASSABLE_MEMORY_STAGE -> False,
|
||||
|
@ -48,8 +49,26 @@ class MulPlugin extends Plugin[VexRiscv]{
|
|||
val aSigned,bSigned = Bool
|
||||
val a,b = Bits(32 bit)
|
||||
|
||||
a := input(SRC1)
|
||||
b := input(SRC2)
|
||||
// a := input(SRC1)
|
||||
// b := input(SRC2)
|
||||
|
||||
val withInputBuffer = inputBuffer generate new Area{
|
||||
val rs1 = RegNext(input(RS1))
|
||||
val rs2 = RegNext(input(RS2))
|
||||
a := rs1
|
||||
b := rs2
|
||||
|
||||
val delay = RegNext(arbitration.isStuck)
|
||||
when(arbitration.isValid && input(IS_MUL) && !delay){
|
||||
arbitration.haltItself := True
|
||||
}
|
||||
}
|
||||
|
||||
val noInputBuffer = (!inputBuffer) generate new Area{
|
||||
a := input(RS1)
|
||||
b := input(RS2)
|
||||
}
|
||||
|
||||
switch(input(INSTRUCTION)(13 downto 12)) {
|
||||
is(B"01") {
|
||||
aSigned := True
|
||||
|
|
|
@ -8,19 +8,6 @@ import scala.collection.mutable.ArrayBuffer
|
|||
|
||||
|
||||
|
||||
object KeepAttribute{
|
||||
object syn_keep_verilog extends AttributeFlag("synthesis syn_keep = 1", COMMENT_ATTRIBUTE){
|
||||
override def isLanguageReady(language: Language) : Boolean = language == Language.VERILOG || language == Language.SYSTEM_VERILOG
|
||||
}
|
||||
|
||||
object syn_keep_vhdl extends AttributeFlag("syn_keep"){
|
||||
override def isLanguageReady(language: Language) : Boolean = language == Language.VHDL
|
||||
}
|
||||
object keep extends AttributeFlag("keep")
|
||||
|
||||
def apply[T <: Data](that : T) = that.addAttribute(keep).addAttribute(syn_keep_verilog).addAttribute(syn_keep_vhdl)
|
||||
}
|
||||
|
||||
|
||||
class PcManagerSimplePlugin(resetVector : BigInt,
|
||||
relaxedPcCalculation : Boolean = false,
|
||||
|
|
|
@ -96,6 +96,11 @@ class RegFilePlugin(regFileReadyKind : RegFileReadKind,
|
|||
regFileWrite.address := U(shadowPrefix(output(INSTRUCTION)(rdRange)))
|
||||
regFileWrite.data := output(REGFILE_WRITE_DATA)
|
||||
|
||||
//Ensure no boot glitches modify X0
|
||||
if(!x0Init && zeroBoot) when(regFileWrite.address === 0){
|
||||
regFileWrite.valid := False
|
||||
}
|
||||
|
||||
//CPU will initialise constant register zero in the first cycle
|
||||
if(x0Init) {
|
||||
val boot = RegNext(False) init (True)
|
||||
|
|
|
@ -1548,7 +1548,7 @@ public:
|
|||
riscvRef.ipInput |= top->externalInterruptS << 9;
|
||||
#endif
|
||||
|
||||
riscvRef.liveness(top->VexRiscv->execute_CsrPlugin_inWfi);
|
||||
riscvRef.liveness(top->VexRiscv->CsrPlugin_inWfi);
|
||||
if(top->VexRiscv->CsrPlugin_interruptJump){
|
||||
if(riscvRefEnable) riscvRef.trap(true, top->VexRiscv->CsrPlugin_interrupt_code);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue