Merge remote-tracking branch 'origin/master' into dev
This commit is contained in:
commit
312e8b99b8
|
@ -681,18 +681,17 @@ case class IBusSimpleCmd() extends Bundle{
|
||||||
}
|
}
|
||||||
|
|
||||||
case class IBusSimpleRsp() extends Bundle with IMasterSlave{
|
case class IBusSimpleRsp() extends Bundle with IMasterSlave{
|
||||||
val ready = Bool
|
|
||||||
val error = Bool
|
val error = Bool
|
||||||
val inst = Bits(32 bits)
|
val inst = Bits(32 bits)
|
||||||
|
|
||||||
override def asMaster(): Unit = {
|
override def asMaster(): Unit = {
|
||||||
out(ready,error,inst)
|
out(error,inst)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case class IBusSimpleBus(interfaceKeepData : Boolean) extends Bundle with IMasterSlave{
|
case class IBusSimpleBus(interfaceKeepData : Boolean) extends Bundle with IMasterSlave{
|
||||||
var cmd = Stream(IBusSimpleCmd())
|
var cmd = Stream(IBusSimpleCmd())
|
||||||
var rsp = IBusSimpleRsp()
|
var rsp = Flow(IBusSimpleRsp())
|
||||||
|
|
||||||
override def asMaster(): Unit = {
|
override def asMaster(): Unit = {
|
||||||
master(cmd)
|
master(cmd)
|
||||||
|
@ -701,7 +700,8 @@ case class IBusSimpleBus(interfaceKeepData : Boolean) extends Bundle with IMaste
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
There is at least one cycle latency between que cmd and the rsp. the rsp.ready flag should be false after a cmd until the rsp is present.
|
**Important** : There should be at least one cycle latency between que cmd and the rsp. The IBus.cmd can remove request when a CPU jump occure or when the CPU is halted by someting in the pipeline. As many arbitration aren't made for this behaviour, it is important to add a buffer to the iBus.cmd to avoid this. Ex : iBus.cmd.s2mPipe, which add a zero latency buffer and cut the iBus.cmd.ready path.
|
||||||
|
You can also do iBus.cmd.s2mPipe.m2sPipe, which will cut all combinatorial path of the bus but then as a latency of 1 cycle. which mean you should probably set the busLatencyMin to 2.
|
||||||
|
|
||||||
Note that bridges are implemented to convert this interface into AXI4 and Avalon
|
Note that bridges are implemented to convert this interface into AXI4 and Avalon
|
||||||
|
|
||||||
|
|
|
@ -2,15 +2,15 @@ name := "VexRiscv"
|
||||||
|
|
||||||
organization := "com.github.spinalhdl"
|
organization := "com.github.spinalhdl"
|
||||||
|
|
||||||
version := "1.0"
|
version := "1.0.0"
|
||||||
|
|
||||||
scalaVersion := "2.11.6"
|
scalaVersion := "2.11.6"
|
||||||
|
|
||||||
EclipseKeys.withSource := true
|
EclipseKeys.withSource := true
|
||||||
|
|
||||||
libraryDependencies ++= Seq(
|
libraryDependencies ++= Seq(
|
||||||
"com.github.spinalhdl" % "spinalhdl-core_2.11" % "1.1.6",
|
"com.github.spinalhdl" % "spinalhdl-core_2.11" % "1.2.0",
|
||||||
"com.github.spinalhdl" % "spinalhdl-lib_2.11" % "1.1.6",
|
"com.github.spinalhdl" % "spinalhdl-lib_2.11" % "1.2.0",
|
||||||
"org.scalatest" % "scalatest_2.11" % "2.2.1",
|
"org.scalatest" % "scalatest_2.11" % "2.2.1",
|
||||||
"org.yaml" % "snakeyaml" % "1.8"
|
"org.yaml" % "snakeyaml" % "1.8"
|
||||||
)
|
)
|
||||||
|
@ -19,4 +19,4 @@ libraryDependencies ++= Seq(
|
||||||
|
|
||||||
addCompilerPlugin("org.scala-lang.plugins" % "scala-continuations-plugin_2.11.6" % "1.0.2")
|
addCompilerPlugin("org.scala-lang.plugins" % "scala-continuations-plugin_2.11.6" % "1.0.2")
|
||||||
scalacOptions += "-P:continuations:enable"
|
scalacOptions += "-P:continuations:enable"
|
||||||
fork := true
|
fork := true
|
||||||
|
|
|
@ -6,7 +6,7 @@ import spinal.core._
|
||||||
import scala.collection.mutable.ArrayBuffer
|
import scala.collection.mutable.ArrayBuffer
|
||||||
|
|
||||||
object VexRiscvConfig{
|
object VexRiscvConfig{
|
||||||
def apply(plugins : Seq[Plugin[VexRiscv]]) : VexRiscvConfig = {
|
def apply(plugins : Seq[Plugin[VexRiscv]] = ArrayBuffer()) : VexRiscvConfig = {
|
||||||
val config = VexRiscvConfig()
|
val config = VexRiscvConfig()
|
||||||
config.plugins ++= plugins
|
config.plugins ++= plugins
|
||||||
config
|
config
|
||||||
|
|
|
@ -101,17 +101,17 @@ object VexRiscvSynthesisBench {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// val rtls = List(smallestNoCsr, smallest, smallAndProductive, smallAndProductiveWithICache, fullNoMmuNoCache, noCacheNoMmuMaxPerf, fullNoMmuMaxPerf, fullNoMmu, full)
|
val rtls = List(smallestNoCsr, smallest, smallAndProductive, smallAndProductiveWithICache, fullNoMmuNoCache, noCacheNoMmuMaxPerf, fullNoMmuMaxPerf, fullNoMmu, full)
|
||||||
val rtls = List(smallestNoCsr)
|
//val rtls = List(smallestNoCsr)
|
||||||
// val rtls = List(smallAndProductive, smallAndProductiveWithICache, fullNoMmuMaxPerf, fullNoMmu, full)
|
// val rtls = List(smallAndProductive, smallAndProductiveWithICache, fullNoMmuMaxPerf, fullNoMmu, full)
|
||||||
// val rtls = List(smallAndProductive, full)
|
// val rtls = List(smallAndProductive, full)
|
||||||
|
|
||||||
val targets = /*XilinxStdTargets(
|
val targets = XilinxStdTargets(
|
||||||
vivadoArtix7Path = "/eda/Xilinx/Vivado/2017.2/bin"
|
vivadoArtix7Path = "/eda/Xilinx/Vivado/2017.2/bin"
|
||||||
) ++ AlteraStdTargets(
|
) ++ AlteraStdTargets(
|
||||||
quartusCycloneIVPath = "/eda/intelFPGA_lite/17.0/quartus/bin",
|
quartusCycloneIVPath = "/eda/intelFPGA_lite/17.0/quartus/bin",
|
||||||
quartusCycloneVPath = "/eda/intelFPGA_lite/17.0/quartus/bin"
|
quartusCycloneVPath = "/eda/intelFPGA_lite/17.0/quartus/bin"
|
||||||
) ++ */IcestormStdTargets()
|
) ++ IcestormStdTargets()
|
||||||
|
|
||||||
// val targets = IcestormStdTargets()
|
// val targets = IcestormStdTargets()
|
||||||
Bench(rtls, targets, "/eda/tmp/")
|
Bench(rtls, targets, "/eda/tmp/")
|
||||||
|
|
|
@ -24,16 +24,16 @@ object VexRiscvCachedWishboneForSim{
|
||||||
//CPU configuration
|
//CPU configuration
|
||||||
val cpuConfig = VexRiscvConfig(
|
val cpuConfig = VexRiscvConfig(
|
||||||
plugins = List(
|
plugins = List(
|
||||||
new PcManagerSimplePlugin(0x00000000l, false),
|
|
||||||
// new IBusSimplePlugin(
|
// new IBusSimplePlugin(
|
||||||
// interfaceKeepData = false,
|
// resetVector = 0x80000000l,
|
||||||
// catchAccessFault = false
|
// prediction = STATIC
|
||||||
// ),
|
// ),
|
||||||
// new DBusSimplePlugin(
|
// new DBusSimplePlugin(
|
||||||
// catchAddressMisaligned = false,
|
// catchAddressMisaligned = false,
|
||||||
// catchAccessFault = false
|
// catchAccessFault = false
|
||||||
// ),
|
// ),
|
||||||
new IBusCachedPlugin(
|
new IBusCachedPlugin(
|
||||||
|
resetVector = 0x80000000l,
|
||||||
prediction = STATIC,
|
prediction = STATIC,
|
||||||
config = InstructionCacheConfig(
|
config = InstructionCacheConfig(
|
||||||
cacheSize = 4096,
|
cacheSize = 4096,
|
||||||
|
@ -79,7 +79,7 @@ object VexRiscvCachedWishboneForSim{
|
||||||
),
|
),
|
||||||
new RegFilePlugin(
|
new RegFilePlugin(
|
||||||
regFileReadyKind = plugin.SYNC,
|
regFileReadyKind = plugin.SYNC,
|
||||||
zeroBoot = false
|
zeroBoot = true
|
||||||
),
|
),
|
||||||
new IntAluPlugin,
|
new IntAluPlugin,
|
||||||
new SrcPlugin(
|
new SrcPlugin(
|
||||||
|
@ -117,36 +117,22 @@ object VexRiscvCachedWishboneForSim{
|
||||||
//cpu.setDefinitionName("VexRiscvAvalon")
|
//cpu.setDefinitionName("VexRiscvAvalon")
|
||||||
cpu.rework {
|
cpu.rework {
|
||||||
for (plugin <- cpuConfig.plugins) plugin match {
|
for (plugin <- cpuConfig.plugins) plugin match {
|
||||||
// case plugin: IBusSimplePlugin => {
|
case plugin: IBusSimplePlugin => {
|
||||||
// plugin.iBus.asDirectionLess() //Unset IO properties of iBus
|
|
||||||
// iBus = master(plugin.iBus.toAvalon())
|
|
||||||
// .setName("iBusAvalon")
|
|
||||||
// .addTag(ClockDomainTag(ClockDomain.current)) //Specify a clock domain to the iBus (used by QSysify)
|
|
||||||
// }
|
|
||||||
case plugin: IBusCachedPlugin => {
|
|
||||||
plugin.iBus.asDirectionLess() //Unset IO properties of iBus
|
plugin.iBus.asDirectionLess() //Unset IO properties of iBus
|
||||||
master(plugin.iBus.toWishbone()).setName("iBusWishbone")
|
master(plugin.iBus.toWishbone()).setName("iBusWishbone")
|
||||||
}
|
}
|
||||||
// case plugin: DBusSimplePlugin => {
|
case plugin: IBusCachedPlugin => {
|
||||||
// plugin.dBus.asDirectionLess()
|
plugin.iBus.asDirectionLess()
|
||||||
// master(plugin.dBus.toAvalon())
|
master(plugin.iBus.toWishbone()).setName("iBusWishbone")
|
||||||
// .setName("dBusAvalon")
|
}
|
||||||
// .addTag(ClockDomainTag(ClockDomain.current))
|
case plugin: DBusSimplePlugin => {
|
||||||
// }
|
plugin.dBus.asDirectionLess()
|
||||||
|
master(plugin.dBus.toWishbone()).setName("dBusWishbone")
|
||||||
|
}
|
||||||
case plugin: DBusCachedPlugin => {
|
case plugin: DBusCachedPlugin => {
|
||||||
plugin.dBus.asDirectionLess()
|
plugin.dBus.asDirectionLess()
|
||||||
master(plugin.dBus.toWishbone()).setName("dBusWishbone")
|
master(plugin.dBus.toWishbone()).setName("dBusWishbone")
|
||||||
}
|
}
|
||||||
// case plugin: DebugPlugin => {
|
|
||||||
// plugin.io.bus.asDirectionLess()
|
|
||||||
// slave(plugin.io.bus.fromAvalon())
|
|
||||||
// .setName("debugBusAvalon")
|
|
||||||
// .addTag(ClockDomainTag(plugin.debugClockDomain))
|
|
||||||
// .parent = null //Avoid the io bundle to be interpreted as a QSys conduit
|
|
||||||
// plugin.io.resetOut
|
|
||||||
// .addTag(ResetEmitterTag(plugin.debugClockDomain))
|
|
||||||
// .parent = null //Avoid the io bundle to be interpreted as a QSys conduit
|
|
||||||
// }
|
|
||||||
case _ =>
|
case _ =>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,7 @@ trait PredictionInterface{
|
||||||
}
|
}
|
||||||
|
|
||||||
class BranchPlugin(earlyBranch : Boolean,
|
class BranchPlugin(earlyBranch : Boolean,
|
||||||
catchAddressMisaligned : Boolean) extends Plugin[VexRiscv] with PredictionInterface{
|
catchAddressMisaligned : Boolean = false) extends Plugin[VexRiscv] with PredictionInterface{
|
||||||
|
|
||||||
|
|
||||||
lazy val branchStage = if(earlyBranch) pipeline.execute else pipeline.memory
|
lazy val branchStage = if(earlyBranch) pipeline.execute else pipeline.memory
|
||||||
|
@ -218,7 +218,7 @@ class BranchPlugin(earlyBranch : Boolean,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
insert(BRANCH_DO) := input(PREDICTION_HAD_BRANCHED) =/= insert(BRANCH_COND_RESULT)
|
insert(BRANCH_DO) := input(PREDICTION_HAD_BRANCHED) =/= input(BRANCH_COND_RESULT)
|
||||||
|
|
||||||
//Calculation of the branch target / correction
|
//Calculation of the branch target / correction
|
||||||
val imm = IMM(input(INSTRUCTION))
|
val imm = IMM(input(INSTRUCTION))
|
||||||
|
|
|
@ -4,7 +4,9 @@ import vexriscv._
|
||||||
import spinal.core._
|
import spinal.core._
|
||||||
import spinal.lib._
|
import spinal.lib._
|
||||||
import spinal.lib.bus.amba4.axi._
|
import spinal.lib.bus.amba4.axi._
|
||||||
import spinal.lib.bus.avalon.{AvalonMMConfig, AvalonMM}
|
import spinal.lib.bus.avalon.{AvalonMM, AvalonMMConfig}
|
||||||
|
import spinal.lib.bus.wishbone.{Wishbone, WishboneConfig}
|
||||||
|
import vexriscv.ip.DataCacheMemCmd
|
||||||
|
|
||||||
|
|
||||||
case class DBusSimpleCmd() extends Bundle{
|
case class DBusSimpleCmd() extends Bundle{
|
||||||
|
@ -45,6 +47,21 @@ object DBusSimpleBus{
|
||||||
useResponse = true,
|
useResponse = true,
|
||||||
maximumPendingReadTransactions = 1
|
maximumPendingReadTransactions = 1
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def getWishboneConfig() = WishboneConfig(
|
||||||
|
addressWidth = 30,
|
||||||
|
dataWidth = 32,
|
||||||
|
selWidth = 4,
|
||||||
|
useSTALL = false,
|
||||||
|
useLOCK = false,
|
||||||
|
useERR = true,
|
||||||
|
useRTY = false,
|
||||||
|
tgaWidth = 0,
|
||||||
|
tgcWidth = 0,
|
||||||
|
tgdWidth = 0,
|
||||||
|
useBTE = true,
|
||||||
|
useCTI = true
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
case class DBusSimpleBus() extends Bundle with IMasterSlave{
|
case class DBusSimpleBus() extends Bundle with IMasterSlave{
|
||||||
|
@ -133,10 +150,39 @@ case class DBusSimpleBus() extends Bundle with IMasterSlave{
|
||||||
|
|
||||||
mm
|
mm
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def toWishbone(): Wishbone = {
|
||||||
|
val wishboneConfig = DBusSimpleBus.getWishboneConfig()
|
||||||
|
val bus = Wishbone(wishboneConfig)
|
||||||
|
val cmdStage = cmd.halfPipe()
|
||||||
|
|
||||||
|
bus.ADR := cmdStage.address >> 2
|
||||||
|
bus.CTI :=B"000"
|
||||||
|
bus.BTE := "00"
|
||||||
|
bus.SEL := (cmdStage.size.mux (
|
||||||
|
U(0) -> B"0001",
|
||||||
|
U(1) -> B"0011",
|
||||||
|
default -> B"1111"
|
||||||
|
) << cmdStage.address(1 downto 0)).resized
|
||||||
|
when(!cmdStage.wr) {
|
||||||
|
bus.SEL := "1111"
|
||||||
|
}
|
||||||
|
bus.WE := cmdStage.wr
|
||||||
|
bus.DAT_MOSI := cmdStage.data
|
||||||
|
|
||||||
|
cmdStage.ready := cmdStage.valid && bus.ACK
|
||||||
|
bus.CYC := cmdStage.valid
|
||||||
|
bus.STB := cmdStage.valid
|
||||||
|
|
||||||
|
rsp.ready := cmdStage.valid && !bus.WE && bus.ACK
|
||||||
|
rsp.data := bus.DAT_MISO
|
||||||
|
rsp.error := False //TODO
|
||||||
|
bus
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class DBusSimplePlugin(catchAddressMisaligned : Boolean, catchAccessFault : Boolean, earlyInjection : Boolean = false) extends Plugin[VexRiscv]{
|
class DBusSimplePlugin(catchAddressMisaligned : Boolean = false, catchAccessFault : Boolean = false, earlyInjection : Boolean = false) extends Plugin[VexRiscv]{
|
||||||
|
|
||||||
var dBus : DBusSimpleBus = null
|
var dBus : DBusSimpleBus = null
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,7 @@ case class Masked(value : BigInt,care : BigInt){
|
||||||
def toString(bitCount : Int) = (0 until bitCount).map(i => if(care.testBit(i)) (if(value.testBit(i)) "1" else "0") else "-").reverseIterator.reduce(_+_)
|
def toString(bitCount : Int) = (0 until bitCount).map(i => if(care.testBit(i)) (if(value.testBit(i)) "1" else "0") else "-").reverseIterator.reduce(_+_)
|
||||||
}
|
}
|
||||||
|
|
||||||
class DecoderSimplePlugin(catchIllegalInstruction : Boolean, forceLegalInstructionComputation : Boolean = false) extends Plugin[VexRiscv] with DecoderService {
|
class DecoderSimplePlugin(catchIllegalInstruction : Boolean = false, forceLegalInstructionComputation : Boolean = false) extends Plugin[VexRiscv] with DecoderService {
|
||||||
override def add(encoding: Seq[(MaskedLiteral, Seq[(Stageable[_ <: BaseType], Any)])]): Unit = encoding.foreach(e => this.add(e._1,e._2))
|
override def add(encoding: Seq[(MaskedLiteral, Seq[(Stageable[_ <: BaseType], Any)])]): Unit = encoding.foreach(e => this.add(e._1,e._2))
|
||||||
override def add(key: MaskedLiteral, values: Seq[(Stageable[_ <: BaseType], Any)]): Unit = {
|
override def add(key: MaskedLiteral, values: Seq[(Stageable[_ <: BaseType], Any)]): Unit = {
|
||||||
val instructionModel = encodings.getOrElseUpdate(key,ArrayBuffer[(Stageable[_ <: BaseType], BaseType)]())
|
val instructionModel = encodings.getOrElseUpdate(key,ArrayBuffer[(Stageable[_ <: BaseType], BaseType)]())
|
||||||
|
|
|
@ -5,10 +5,10 @@ import spinal.core._
|
||||||
import spinal.lib._
|
import spinal.lib._
|
||||||
|
|
||||||
|
|
||||||
class HazardSimplePlugin(bypassExecute : Boolean,
|
class HazardSimplePlugin(bypassExecute : Boolean = false,
|
||||||
bypassMemory: Boolean,
|
bypassMemory: Boolean = false,
|
||||||
bypassWriteBack: Boolean,
|
bypassWriteBack: Boolean = false,
|
||||||
bypassWriteBackBuffer : Boolean,
|
bypassWriteBackBuffer : Boolean = false,
|
||||||
pessimisticUseSrc : Boolean = false,
|
pessimisticUseSrc : Boolean = false,
|
||||||
pessimisticWriteRegFile : Boolean = false,
|
pessimisticWriteRegFile : Boolean = false,
|
||||||
pessimisticAddressMatch : Boolean = false) extends Plugin[VexRiscv] {
|
pessimisticAddressMatch : Boolean = false) extends Plugin[VexRiscv] {
|
||||||
|
|
|
@ -5,6 +5,7 @@ import spinal.core._
|
||||||
import spinal.lib._
|
import spinal.lib._
|
||||||
import spinal.lib.bus.amba4.axi._
|
import spinal.lib.bus.amba4.axi._
|
||||||
import spinal.lib.bus.avalon.{AvalonMM, AvalonMMConfig}
|
import spinal.lib.bus.avalon.{AvalonMM, AvalonMMConfig}
|
||||||
|
import spinal.lib.bus.wishbone.{Wishbone, WishboneConfig}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -43,6 +44,21 @@ object IBusSimpleBus{
|
||||||
useResponse = true,
|
useResponse = true,
|
||||||
maximumPendingReadTransactions = 8
|
maximumPendingReadTransactions = 8
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def getWishboneConfig() = WishboneConfig(
|
||||||
|
addressWidth = 30,
|
||||||
|
dataWidth = 32,
|
||||||
|
selWidth = 4,
|
||||||
|
useSTALL = false,
|
||||||
|
useLOCK = false,
|
||||||
|
useERR = true,
|
||||||
|
useRTY = false,
|
||||||
|
tgaWidth = 0,
|
||||||
|
tgcWidth = 0,
|
||||||
|
tgdWidth = 0,
|
||||||
|
useBTE = true,
|
||||||
|
useCTI = true
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -96,6 +112,29 @@ case class IBusSimpleBus(interfaceKeepData : Boolean) extends Bundle with IMaste
|
||||||
|
|
||||||
mm
|
mm
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def toWishbone(): Wishbone = {
|
||||||
|
val wishboneConfig = IBusSimpleBus.getWishboneConfig()
|
||||||
|
val bus = Wishbone(wishboneConfig)
|
||||||
|
val cmdPipe = cmd.stage()
|
||||||
|
|
||||||
|
bus.ADR := (cmdPipe.pc >> 2)
|
||||||
|
bus.CTI := B"000"
|
||||||
|
bus.BTE := "00"
|
||||||
|
bus.SEL := "1111"
|
||||||
|
bus.WE := False
|
||||||
|
bus.DAT_MOSI.assignDontCare()
|
||||||
|
bus.CYC := cmdPipe.valid
|
||||||
|
bus.STB := cmdPipe.valid
|
||||||
|
|
||||||
|
|
||||||
|
cmdPipe.ready := cmdPipe.valid && bus.ACK
|
||||||
|
rsp.valid := bus.CYC && bus.ACK
|
||||||
|
rsp.inst := bus.DAT_MISO
|
||||||
|
rsp.error := False //TODO
|
||||||
|
bus
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -64,7 +64,7 @@ class MemoryTranslatorPlugin(tlbSize : Int,
|
||||||
val shared = new Area {
|
val shared = new Area {
|
||||||
val cache = Mem(CacheLine(), tlbSize)
|
val cache = Mem(CacheLine(), tlbSize)
|
||||||
var free = True
|
var free = True
|
||||||
val readAddr = cache.addressType.assignDontCare()
|
val readAddr = cache.addressType().assignDontCare()
|
||||||
val readData = RegNext(cache.readSync(readAddr))
|
val readData = RegNext(cache.readSync(readAddr))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -126,7 +126,7 @@ object StreamVexPimper{
|
||||||
val ret = cloneOf(pimped)
|
val ret = cloneOf(pimped)
|
||||||
|
|
||||||
val rValid = RegInit(False)
|
val rValid = RegInit(False)
|
||||||
val rData = Reg(pimped.dataType)
|
val rData = Reg(pimped.payloadType)
|
||||||
if(!discardInput) rValid.clearWhen(flush)
|
if(!discardInput) rValid.clearWhen(flush)
|
||||||
|
|
||||||
pimped.ready := (Bool(collapsBubble) && !ret.valid) || ret.ready
|
pimped.ready := (Bool(collapsBubble) && !ret.valid) || ret.ready
|
||||||
|
@ -148,7 +148,7 @@ object StreamVexPimper{
|
||||||
val ret = cloneOf(pimped)
|
val ret = cloneOf(pimped)
|
||||||
|
|
||||||
val rValid = RegInit(False)
|
val rValid = RegInit(False)
|
||||||
val rBits = Reg(pimped.dataType)
|
val rBits = Reg(pimped.payloadType)
|
||||||
|
|
||||||
ret.valid := pimped.valid || rValid
|
ret.valid := pimped.valid || rValid
|
||||||
pimped.ready := !rValid
|
pimped.ready := !rValid
|
||||||
|
|
|
@ -4,7 +4,7 @@ import spinal.core._
|
||||||
import spinal.lib._
|
import spinal.lib._
|
||||||
import vexriscv.{VexRiscv, _}
|
import vexriscv.{VexRiscv, _}
|
||||||
|
|
||||||
class MulDivIterativePlugin(genMul : Boolean, genDiv : Boolean, mulUnrollFactor : Int, divUnrollFactor : Int) extends Plugin[VexRiscv]{
|
class MulDivIterativePlugin(genMul : Boolean = true, genDiv : Boolean = true, mulUnrollFactor : Int = 1, divUnrollFactor : Int = 1) extends Plugin[VexRiscv]{
|
||||||
object IS_MUL extends Stageable(Bool)
|
object IS_MUL extends Stageable(Bool)
|
||||||
object IS_DIV extends Stageable(Bool)
|
object IS_DIV extends Stageable(Bool)
|
||||||
object IS_REM extends Stageable(Bool)
|
object IS_REM extends Stageable(Bool)
|
||||||
|
|
|
@ -4,7 +4,7 @@ import vexriscv.{RVC_GEN, Riscv, VexRiscv}
|
||||||
import spinal.core._
|
import spinal.core._
|
||||||
|
|
||||||
|
|
||||||
class SrcPlugin(separatedAddSub : Boolean, executeInsertion : Boolean = false) extends Plugin[VexRiscv]{
|
class SrcPlugin(separatedAddSub : Boolean = false, executeInsertion : Boolean = false) extends Plugin[VexRiscv]{
|
||||||
override def build(pipeline: VexRiscv): Unit = {
|
override def build(pipeline: VexRiscv): Unit = {
|
||||||
import pipeline._
|
import pipeline._
|
||||||
import pipeline.config._
|
import pipeline.config._
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package vexriscv
|
package vexriscv.test
|
||||||
|
|
||||||
import java.awt.{Color, Dimension, Graphics}
|
|
||||||
import java.awt.event.{MouseEvent, MouseListener}
|
import java.awt.event.{MouseEvent, MouseListener}
|
||||||
|
import java.awt.{Color, Dimension, Graphics}
|
||||||
import javax.swing.JPanel
|
import javax.swing.JPanel
|
||||||
|
|
||||||
abstract class JLedArray(ledCount : Int,ledDiameter : Int = 20, blackThickness : Int = 2) extends JPanel{
|
abstract class JLedArray(ledCount : Int,ledDiameter : Int = 20, blackThickness : Int = 2) extends JPanel{
|
|
@ -624,6 +624,8 @@ public:
|
||||||
bool error;
|
bool error;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
uint32_t periphWriteTimer = 0;
|
||||||
|
queue<MemWrite> periphWritesGolden;
|
||||||
queue<MemWrite> periphWrites;
|
queue<MemWrite> periphWrites;
|
||||||
queue<MemRead> periphRead;
|
queue<MemRead> periphRead;
|
||||||
Workspace *ws;
|
Workspace *ws;
|
||||||
|
@ -663,11 +665,11 @@ public:
|
||||||
}
|
}
|
||||||
virtual void dWrite(int32_t address, int32_t size, uint32_t data){
|
virtual void dWrite(int32_t address, int32_t size, uint32_t data){
|
||||||
if((address & 0xF0000000) == 0xF0000000){
|
if((address & 0xF0000000) == 0xF0000000){
|
||||||
MemWrite t = periphWrites.front();
|
MemWrite w;
|
||||||
if(t.address != address || t.size != size || t.data != data){
|
w.address = address;
|
||||||
fail();
|
w.size = size;
|
||||||
}
|
w.data = data;
|
||||||
periphWrites.pop();
|
periphWritesGolden.push(w);
|
||||||
}else {
|
}else {
|
||||||
mem.write(address, size, (uint8_t*)&data);
|
mem.write(address, size, (uint8_t*)&data);
|
||||||
}
|
}
|
||||||
|
@ -677,6 +679,23 @@ public:
|
||||||
void step() {
|
void step() {
|
||||||
rfWriteValid = false;
|
rfWriteValid = false;
|
||||||
RiscvGolden::step();
|
RiscvGolden::step();
|
||||||
|
|
||||||
|
switch(periphWrites.empty() + uint32_t(periphWritesGolden.empty())*2){
|
||||||
|
case 3: periphWriteTimer = 0; break;
|
||||||
|
case 1: case 2: if(periphWriteTimer++ == 20){ cout << "periphWrite timout" << endl; fail();} break;
|
||||||
|
case 0:
|
||||||
|
MemWrite t = periphWrites.front();
|
||||||
|
MemWrite t2 = periphWritesGolden.front();
|
||||||
|
if(t.address != t2.address || t.size != t2.size || t.data != t2.data){
|
||||||
|
cout << "periphWrite missmatch" << endl;
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
periphWrites.pop();
|
||||||
|
periphWritesGolden.pop();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -903,7 +922,7 @@ public:
|
||||||
if(bootPc != -1) top->VexRiscv->core->prefetch_pc = bootPc;
|
if(bootPc != -1) top->VexRiscv->core->prefetch_pc = bootPc;
|
||||||
#else
|
#else
|
||||||
if(bootPc != -1) {
|
if(bootPc != -1) {
|
||||||
#ifdef IBUS_SIMPLE
|
#if defined(IBUS_SIMPLE) || defined(IBUS_SIMPLE_WISHBONE)
|
||||||
top->VexRiscv->IBusSimplePlugin_fetchPc_pcReg = bootPc;
|
top->VexRiscv->IBusSimplePlugin_fetchPc_pcReg = bootPc;
|
||||||
#ifdef COMPRESSED
|
#ifdef COMPRESSED
|
||||||
top->VexRiscv->IBusSimplePlugin_decodePc_pcReg = bootPc;
|
top->VexRiscv->IBusSimplePlugin_decodePc_pcReg = bootPc;
|
||||||
|
@ -1261,10 +1280,9 @@ public:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef IBUS_CACHED_WISHBONE
|
#if defined(IBUS_CACHED_WISHBONE) || defined(IBUS_SIMPLE_WISHBONE)
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
||||||
|
|
||||||
class IBusCachedWishbone : public SimElement{
|
class IBusCachedWishbone : public SimElement{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -1282,21 +1300,24 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void preCycle(){
|
virtual void preCycle(){
|
||||||
top->iBusWishbone_DAT_MISO = VL_RANDOM_I(32);
|
|
||||||
if (top->iBusWishbone_CYC && top->iBusWishbone_STB && top->iBusWishbone_ACK) {
|
|
||||||
if(top->iBusWishbone_WE){
|
|
||||||
|
|
||||||
} else {
|
|
||||||
bool error;
|
|
||||||
ws->iBusAccess(top->iBusWishbone_ADR << 2,&top->iBusWishbone_DAT_MISO,&error);
|
|
||||||
top->iBusWishbone_ERR = error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void postCycle(){
|
virtual void postCycle(){
|
||||||
|
|
||||||
if(ws->iStall)
|
if(ws->iStall)
|
||||||
top->iBusWishbone_ACK = VL_RANDOM_I(7) < 100;
|
top->iBusWishbone_ACK = VL_RANDOM_I(7) < 100;
|
||||||
|
|
||||||
|
top->iBusWishbone_DAT_MISO = VL_RANDOM_I(32);
|
||||||
|
if (top->iBusWishbone_CYC && top->iBusWishbone_STB && top->iBusWishbone_ACK) {
|
||||||
|
if(top->iBusWishbone_WE){
|
||||||
|
|
||||||
|
} else {
|
||||||
|
bool error;
|
||||||
|
ws->iBusAccess(top->iBusWishbone_ADR << 2,&top->iBusWishbone_DAT_MISO,&error);
|
||||||
|
top->iBusWishbone_ERR = error;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
@ -1398,7 +1419,7 @@ public:
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef DBUS_CACHED_WISHBONE
|
#if defined(DBUS_CACHED_WISHBONE) || defined(DBUS_SIMPLE_WISHBONE)
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
||||||
|
|
||||||
|
@ -1419,22 +1440,23 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void preCycle(){
|
virtual void preCycle(){
|
||||||
top->dBusWishbone_DAT_MISO = VL_RANDOM_I(32);
|
|
||||||
if (top->dBusWishbone_CYC && top->dBusWishbone_STB && top->dBusWishbone_ACK) {
|
|
||||||
if(top->dBusWishbone_WE){
|
|
||||||
bool dummy;
|
|
||||||
ws->dBusAccess(top->dBusWishbone_ADR << 2 ,1,2,top->dBusWishbone_SEL,&top->dBusWishbone_DAT_MOSI,&dummy);
|
|
||||||
} else {
|
|
||||||
bool error;
|
|
||||||
ws->dBusAccess(top->dBusWishbone_ADR << 2,0,2,0xF,&top->dBusWishbone_DAT_MISO,&error);
|
|
||||||
top->dBusWishbone_ERR = error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void postCycle(){
|
virtual void postCycle(){
|
||||||
if(ws->iStall)
|
if(ws->iStall)
|
||||||
top->dBusWishbone_ACK = VL_RANDOM_I(7) < 100;
|
top->dBusWishbone_ACK = VL_RANDOM_I(7) < 100;
|
||||||
|
top->dBusWishbone_DAT_MISO = VL_RANDOM_I(32);
|
||||||
|
if (top->dBusWishbone_CYC && top->dBusWishbone_STB && top->dBusWishbone_ACK) {
|
||||||
|
if(top->dBusWishbone_WE){
|
||||||
|
bool dummy;
|
||||||
|
ws->dBusAccess(top->dBusWishbone_ADR << 2 ,1,2,top->dBusWishbone_SEL,&top->dBusWishbone_DAT_MOSI,&dummy);
|
||||||
|
} else {
|
||||||
|
bool error;
|
||||||
|
ws->dBusAccess(top->dBusWishbone_ADR << 2,0,2,0xF,&top->dBusWishbone_DAT_MISO,&error);
|
||||||
|
top->dBusWishbone_ERR = error;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
@ -1871,7 +1893,7 @@ void Workspace::fillSimELements(){
|
||||||
#ifdef IBUS_CACHED_AVALON
|
#ifdef IBUS_CACHED_AVALON
|
||||||
simElements.push_back(new IBusCachedAvalon(this));
|
simElements.push_back(new IBusCachedAvalon(this));
|
||||||
#endif
|
#endif
|
||||||
#ifdef IBUS_CACHED_WISHBONE
|
#if defined(IBUS_CACHED_WISHBONE) || defined(IBUS_SIMPLE_WISHBONE)
|
||||||
simElements.push_back(new IBusCachedWishbone(this));
|
simElements.push_back(new IBusCachedWishbone(this));
|
||||||
#endif
|
#endif
|
||||||
#ifdef DBUS_SIMPLE
|
#ifdef DBUS_SIMPLE
|
||||||
|
@ -1886,7 +1908,7 @@ void Workspace::fillSimELements(){
|
||||||
#ifdef DBUS_CACHED_AVALON
|
#ifdef DBUS_CACHED_AVALON
|
||||||
simElements.push_back(new DBusCachedAvalon(this));
|
simElements.push_back(new DBusCachedAvalon(this));
|
||||||
#endif
|
#endif
|
||||||
#ifdef DBUS_CACHED_WISHBONE
|
#if defined(DBUS_CACHED_WISHBONE) || defined(DBUS_SIMPLE_WISHBONE)
|
||||||
simElements.push_back(new DBusCachedWishbone(this));
|
simElements.push_back(new DBusCachedWishbone(this));
|
||||||
#endif
|
#endif
|
||||||
#ifdef DEBUG_PLUGIN_STD
|
#ifdef DEBUG_PLUGIN_STD
|
||||||
|
|
|
@ -11,6 +11,7 @@ import javax.swing._
|
||||||
|
|
||||||
import spinal.lib.com.jtag.sim.JtagTcp
|
import spinal.lib.com.jtag.sim.JtagTcp
|
||||||
import spinal.lib.com.uart.sim.{UartDecoder, UartEncoder}
|
import spinal.lib.com.uart.sim.{UartDecoder, UartEncoder}
|
||||||
|
import vexriscv.test.{JLedArray, JSwitchArray}
|
||||||
|
|
||||||
import scala.collection.mutable
|
import scala.collection.mutable
|
||||||
|
|
||||||
|
@ -21,7 +22,7 @@ object MuraxSim {
|
||||||
// def config = MuraxConfig.default.copy(onChipRamSize = 256 kB)
|
// def config = MuraxConfig.default.copy(onChipRamSize = 256 kB)
|
||||||
def config = MuraxConfig.default.copy(onChipRamSize = 4 kB, onChipRamHexFile = "src/main/ressource/hex/muraxDemo.hex")
|
def config = MuraxConfig.default.copy(onChipRamSize = 4 kB, onChipRamHexFile = "src/main/ressource/hex/muraxDemo.hex")
|
||||||
|
|
||||||
SimConfig.allOptimisation.compile(new Murax(config)).doSimUntilVoid{dut =>
|
SimConfig.allOptimisation.withWave.compile(new Murax(config)).doSimUntilVoid{dut =>
|
||||||
val mainClkPeriod = (1e12/dut.config.coreFrequency.toDouble).toLong
|
val mainClkPeriod = (1e12/dut.config.coreFrequency.toDouble).toLong
|
||||||
val jtagClkPeriod = mainClkPeriod*4
|
val jtagClkPeriod = mainClkPeriod*4
|
||||||
val uartBaudRate = 115200
|
val uartBaudRate = 115200
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
package vexriscv.experimental
|
||||||
|
|
||||||
|
import spinal.core.SpinalVerilog
|
||||||
|
import vexriscv.ip.InstructionCacheConfig
|
||||||
|
import vexriscv.{VexRiscv, VexRiscvConfig, plugin}
|
||||||
|
import vexriscv.plugin._
|
||||||
|
|
||||||
|
import scala.collection.mutable.ArrayBuffer
|
||||||
|
|
||||||
|
object Presentation extends App{
|
||||||
|
|
||||||
|
val config = VexRiscvConfig()
|
||||||
|
|
||||||
|
config.plugins ++= List(
|
||||||
|
new IBusSimplePlugin(resetVector = 0x80000000l),
|
||||||
|
new DBusSimplePlugin,
|
||||||
|
new CsrPlugin(CsrPluginConfig.smallest),
|
||||||
|
new DecoderSimplePlugin,
|
||||||
|
new RegFilePlugin(regFileReadyKind = plugin.SYNC),
|
||||||
|
new IntAluPlugin,
|
||||||
|
new SrcPlugin,
|
||||||
|
new MulDivIterativePlugin(
|
||||||
|
mulUnrollFactor = 4,
|
||||||
|
divUnrollFactor = 1
|
||||||
|
),
|
||||||
|
new FullBarrelShifterPlugin,
|
||||||
|
new HazardSimplePlugin,
|
||||||
|
new BranchPlugin(
|
||||||
|
earlyBranch = false
|
||||||
|
),
|
||||||
|
new YamlPlugin("cpu0.yaml")
|
||||||
|
)
|
||||||
|
|
||||||
|
new VexRiscv(config)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue