mirror of
https://github.com/SpinalHDL/VexRiscv.git
synced 2025-01-03 03:43:39 -05:00
Merge remote-tracking branch 'origin/dev'
This commit is contained in:
commit
414d2aba54
18 changed files with 138 additions and 512 deletions
|
@ -45,7 +45,7 @@ before_install:
|
||||||
- sudo make install
|
- sudo make install
|
||||||
- cd ..
|
- cd ..
|
||||||
|
|
||||||
- git clone https://github.com/SpinalHDL/SpinalHDL.git
|
- git clone https://github.com/SpinalHDL/SpinalHDL.git -b dev
|
||||||
|
|
||||||
- cd VexRiscv
|
- cd VexRiscv
|
||||||
#- curl -T README.md -udolu1990:$BINTRAY_KEY https://api.bintray.com/content/spinalhdl/VexRiscv/test/0.0.4/README.md
|
#- curl -T README.md -udolu1990:$BINTRAY_KEY https://api.bintray.com/content/spinalhdl/VexRiscv/test/0.0.4/README.md
|
||||||
|
|
16
build.sbt
16
build.sbt
|
@ -25,22 +25,20 @@ lazy val root = (project in file(".")).
|
||||||
settings(
|
settings(
|
||||||
inThisBuild(List(
|
inThisBuild(List(
|
||||||
organization := "com.github.spinalhdl",
|
organization := "com.github.spinalhdl",
|
||||||
scalaVersion := "2.11.6",
|
scalaVersion := "2.11.12",
|
||||||
version := "1.0.0"
|
version := "1.0.0"
|
||||||
)),
|
)),
|
||||||
libraryDependencies ++= Seq(
|
libraryDependencies ++= Seq(
|
||||||
"com.github.spinalhdl" % "spinalhdl-core_2.11" % "1.2.2",
|
"com.github.spinalhdl" % "spinalhdl-core_2.11" % "1.3.0",
|
||||||
"com.github.spinalhdl" % "spinalhdl-lib_2.11" % "1.2.2",
|
"com.github.spinalhdl" % "spinalhdl-lib_2.11" % "1.3.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"
|
||||||
),
|
),
|
||||||
name := "VexRiscv"
|
name := "VexRiscv"
|
||||||
)/*.dependsOn(spinalHdlSim,spinalHdlCore,spinalHdlLib)
|
)//.dependsOn(spinalHdlSim,spinalHdlCore,spinalHdlLib)
|
||||||
lazy val spinalHdlSim = ProjectRef(file("../SpinalHDL"), "SpinalHDL-sim")
|
//lazy val spinalHdlSim = ProjectRef(file("../SpinalHDL"), "SpinalHDL-sim")
|
||||||
lazy val spinalHdlCore = ProjectRef(file("../SpinalHDL"), "SpinalHDL-core")
|
//lazy val spinalHdlCore = ProjectRef(file("../SpinalHDL"), "SpinalHDL-core")
|
||||||
lazy val spinalHdlLib = ProjectRef(file("../SpinalHDL"), "SpinalHDL-lib")*/
|
//lazy val spinalHdlLib = ProjectRef(file("../SpinalHDL"), "SpinalHDL-lib")
|
||||||
|
|
||||||
|
|
||||||
addCompilerPlugin("org.scala-lang.plugins" % "scala-continuations-plugin_2.11.6" % "1.0.2")
|
|
||||||
scalacOptions += "-P:continuations:enable"
|
|
||||||
fork := true
|
fork := true
|
|
@ -1 +1 @@
|
||||||
sbt.version=0.13.16
|
sbt.version=1.2.7
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "5.2.1")
|
addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "5.2.4")
|
||||||
|
|
||||||
|
|
|
@ -1,58 +0,0 @@
|
||||||
package spinal.lib.misc
|
|
||||||
|
|
||||||
import spinal.core._
|
|
||||||
|
|
||||||
import scala.collection.mutable.ArrayBuffer
|
|
||||||
|
|
||||||
object HexTools{
|
|
||||||
def readHexFile(path : String, hexOffset : Int, callback : (Int, Int) => Unit) : Unit ={
|
|
||||||
import scala.io.Source
|
|
||||||
def hToI(that : String, start : Int, size : Int) = Integer.parseInt(that.substring(start,start + size), 16)
|
|
||||||
|
|
||||||
var offset = 0
|
|
||||||
for (line <- Source.fromFile(path).getLines) {
|
|
||||||
if (line.charAt(0) == ':'){
|
|
||||||
val byteCount = hToI(line, 1, 2)
|
|
||||||
val nextAddr = hToI(line, 3, 4) + offset
|
|
||||||
val key = hToI(line, 7, 2)
|
|
||||||
key match {
|
|
||||||
case 0 =>
|
|
||||||
for(i <- 0 until byteCount){
|
|
||||||
callback(nextAddr + i - hexOffset, hToI(line, 9 + i * 2, 2))
|
|
||||||
}
|
|
||||||
case 2 =>
|
|
||||||
offset = hToI(line, 9, 4) << 4
|
|
||||||
case 4 =>
|
|
||||||
offset = hToI(line, 9, 4) << 16
|
|
||||||
case 3 =>
|
|
||||||
case 5 =>
|
|
||||||
case 1 =>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def readHexFile(path : String, hexOffset : Int): Array[BigInt] ={
|
|
||||||
var onChipRomSize = 0
|
|
||||||
readHexFile(path, hexOffset ,(address, _) => {
|
|
||||||
onChipRomSize = Math.max((address).toInt, onChipRomSize) + 1
|
|
||||||
})
|
|
||||||
|
|
||||||
val initContent = Array.fill[BigInt]((onChipRomSize+3)/4)(0)
|
|
||||||
readHexFile(path, hexOffset,(address,data) => {
|
|
||||||
val addressWithoutOffset = (address).toInt
|
|
||||||
if(addressWithoutOffset < onChipRomSize)
|
|
||||||
initContent(addressWithoutOffset >> 2) |= BigInt(data) << ((addressWithoutOffset & 3)*8)
|
|
||||||
})
|
|
||||||
initContent
|
|
||||||
}
|
|
||||||
|
|
||||||
def initRam[T <: Data](ram : Mem[T], onChipRamHexFile : String, hexOffset : BigInt): Unit ={
|
|
||||||
val initContent = Array.fill[BigInt](ram.wordCount)(0)
|
|
||||||
HexTools.readHexFile(onChipRamHexFile, 0,(address,data) => {
|
|
||||||
val addressWithoutOffset = (address - hexOffset).toInt
|
|
||||||
initContent(addressWithoutOffset >> 2) |= BigInt(data) << ((addressWithoutOffset & 3)*8)
|
|
||||||
})
|
|
||||||
ram.initBigInt(initContent)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -22,6 +22,8 @@ case class VexRiscvConfig(){
|
||||||
var withWriteBackStage = true
|
var withWriteBackStage = true
|
||||||
val plugins = ArrayBuffer[Plugin[VexRiscv]]()
|
val plugins = ArrayBuffer[Plugin[VexRiscv]]()
|
||||||
|
|
||||||
|
def add(that : Plugin[VexRiscv]) : this.type = {plugins += that;this}
|
||||||
|
|
||||||
//Default Stageables
|
//Default Stageables
|
||||||
object IS_RVC extends Stageable(Bool)
|
object IS_RVC extends Stageable(Bool)
|
||||||
object BYPASSABLE_EXECUTE_STAGE extends Stageable(Bool)
|
object BYPASSABLE_EXECUTE_STAGE extends Stageable(Bool)
|
||||||
|
|
|
@ -4,8 +4,9 @@ import spinal.core._
|
||||||
import spinal.lib._
|
import spinal.lib._
|
||||||
import spinal.lib.bus.amba3.apb._
|
import spinal.lib.bus.amba3.apb._
|
||||||
import spinal.lib.bus.misc.SizeMapping
|
import spinal.lib.bus.misc.SizeMapping
|
||||||
|
import spinal.lib.bus.simple.PipelinedMemoryBus
|
||||||
import spinal.lib.com.jtag.Jtag
|
import spinal.lib.com.jtag.Jtag
|
||||||
import spinal.lib.com.spi.ddr.SpiDdrMaster
|
import spinal.lib.com.spi.ddr.SpiXdrMaster
|
||||||
import spinal.lib.com.uart._
|
import spinal.lib.com.uart._
|
||||||
import spinal.lib.io.{InOutWrapper, TriStateArray}
|
import spinal.lib.io.{InOutWrapper, TriStateArray}
|
||||||
import spinal.lib.misc.{InterruptCtrl, Prescaler, Timer}
|
import spinal.lib.misc.{InterruptCtrl, Prescaler, Timer}
|
||||||
|
@ -13,6 +14,7 @@ import spinal.lib.soc.pinsec.{PinsecTimerCtrl, PinsecTimerCtrlExternal}
|
||||||
import vexriscv.plugin._
|
import vexriscv.plugin._
|
||||||
import vexriscv.{VexRiscv, VexRiscvConfig, plugin}
|
import vexriscv.{VexRiscv, VexRiscvConfig, plugin}
|
||||||
import spinal.lib.com.spi.ddr._
|
import spinal.lib.com.spi.ddr._
|
||||||
|
import spinal.lib.bus.simple._
|
||||||
import scala.collection.mutable.ArrayBuffer
|
import scala.collection.mutable.ArrayBuffer
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -39,7 +41,7 @@ case class MuraxConfig(coreFrequency : HertzNumber,
|
||||||
pipelineApbBridge : Boolean,
|
pipelineApbBridge : Boolean,
|
||||||
gpioWidth : Int,
|
gpioWidth : Int,
|
||||||
uartCtrlConfig : UartCtrlMemoryMappedConfig,
|
uartCtrlConfig : UartCtrlMemoryMappedConfig,
|
||||||
xipConfig : SpiDdrMasterCtrl.MemoryMappingParameters,
|
xipConfig : SpiXdrMasterCtrl.MemoryMappingParameters,
|
||||||
hardwareBreakpointCount : Int,
|
hardwareBreakpointCount : Int,
|
||||||
cpuPlugins : ArrayBuffer[Plugin[VexRiscv]]){
|
cpuPlugins : ArrayBuffer[Plugin[VexRiscv]]){
|
||||||
require(pipelineApbBridge || pipelineMainBus, "At least pipelineMainBus or pipelineApbBridge should be enable to avoid wipe transactions")
|
require(pipelineApbBridge || pipelineMainBus, "At least pipelineMainBus or pipelineApbBridge should be enable to avoid wipe transactions")
|
||||||
|
@ -59,11 +61,11 @@ object MuraxConfig{
|
||||||
pipelineMainBus = false,
|
pipelineMainBus = false,
|
||||||
pipelineApbBridge = true,
|
pipelineApbBridge = true,
|
||||||
gpioWidth = 32,
|
gpioWidth = 32,
|
||||||
xipConfig = ifGen(withXip) (SpiDdrMasterCtrl.MemoryMappingParameters(
|
xipConfig = ifGen(withXip) (SpiXdrMasterCtrl.MemoryMappingParameters(
|
||||||
SpiDdrMasterCtrl.Parameters(8, 12, SpiDdrParameter(2, 2, 1)).addFullDuplex(0,1,false),
|
SpiXdrMasterCtrl.Parameters(8, 12, SpiXdrParameter(2, 2, 1)).addFullDuplex(0,1,false),
|
||||||
cmdFifoDepth = 32,
|
cmdFifoDepth = 32,
|
||||||
rspFifoDepth = 32,
|
rspFifoDepth = 32,
|
||||||
xip = SpiDdrMasterCtrl.XipBusParameters(addressWidth = 24, dataWidth = 32)
|
xip = SpiXdrMasterCtrl.XipBusParameters(addressWidth = 24, dataWidth = 32)
|
||||||
)),
|
)),
|
||||||
hardwareBreakpointCount = if(withXip) 3 else 0,
|
hardwareBreakpointCount = if(withXip) 3 else 0,
|
||||||
cpuPlugins = ArrayBuffer( //DebugPlugin added by the toplevel
|
cpuPlugins = ArrayBuffer( //DebugPlugin added by the toplevel
|
||||||
|
@ -163,7 +165,7 @@ case class Murax(config : MuraxConfig) extends Component{
|
||||||
val gpioA = master(TriStateArray(gpioWidth bits))
|
val gpioA = master(TriStateArray(gpioWidth bits))
|
||||||
val uart = master(Uart())
|
val uart = master(Uart())
|
||||||
|
|
||||||
val xip = ifGen(genXip)(master(SpiDdrMaster(xipConfig.ctrl.spi)))
|
val xip = ifGen(genXip)(master(SpiXdrMaster(xipConfig.ctrl.spi)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -207,14 +209,14 @@ case class Murax(config : MuraxConfig) extends Component{
|
||||||
)
|
)
|
||||||
|
|
||||||
val system = new ClockingArea(systemClockDomain) {
|
val system = new ClockingArea(systemClockDomain) {
|
||||||
val simpleBusConfig = SimpleBusConfig(
|
val pipelinedMemoryBusConfig = PipelinedMemoryBusConfig(
|
||||||
addressWidth = 32,
|
addressWidth = 32,
|
||||||
dataWidth = 32
|
dataWidth = 32
|
||||||
)
|
)
|
||||||
|
|
||||||
//Arbiter of the cpu dBus/iBus to drive the mainBus
|
//Arbiter of the cpu dBus/iBus to drive the mainBus
|
||||||
//Priority to dBus, !! cmd transactions can change on the fly !!
|
//Priority to dBus, !! cmd transactions can change on the fly !!
|
||||||
val mainBusArbiter = new MuraxMasterArbiter(simpleBusConfig)
|
val mainBusArbiter = new MuraxMasterArbiter(pipelinedMemoryBusConfig)
|
||||||
|
|
||||||
//Instanciate the CPU
|
//Instanciate the CPU
|
||||||
val cpu = new VexRiscv(
|
val cpu = new VexRiscv(
|
||||||
|
@ -252,23 +254,23 @@ case class Murax(config : MuraxConfig) extends Component{
|
||||||
|
|
||||||
|
|
||||||
//****** MainBus slaves ********
|
//****** MainBus slaves ********
|
||||||
val mainBusMapping = ArrayBuffer[(SimpleBus,SizeMapping)]()
|
val mainBusMapping = ArrayBuffer[(PipelinedMemoryBus,SizeMapping)]()
|
||||||
val ram = new MuraxSimpleBusRam(
|
val ram = new MuraxPipelinedMemoryBusRam(
|
||||||
onChipRamSize = onChipRamSize,
|
onChipRamSize = onChipRamSize,
|
||||||
onChipRamHexFile = onChipRamHexFile,
|
onChipRamHexFile = onChipRamHexFile,
|
||||||
simpleBusConfig = simpleBusConfig
|
pipelinedMemoryBusConfig = pipelinedMemoryBusConfig
|
||||||
)
|
)
|
||||||
mainBusMapping += ram.io.bus -> (0x80000000l, onChipRamSize)
|
mainBusMapping += ram.io.bus -> (0x80000000l, onChipRamSize)
|
||||||
|
|
||||||
val apbBridge = new MuraxSimpleBusToApbBridge(
|
val apbBridge = new PipelinedMemoryBusToApbBridge(
|
||||||
apb3Config = Apb3Config(
|
apb3Config = Apb3Config(
|
||||||
addressWidth = 20,
|
addressWidth = 20,
|
||||||
dataWidth = 32
|
dataWidth = 32
|
||||||
),
|
),
|
||||||
pipelineBridge = pipelineApbBridge,
|
pipelineBridge = pipelineApbBridge,
|
||||||
simpleBusConfig = simpleBusConfig
|
pipelinedMemoryBusConfig = pipelinedMemoryBusConfig
|
||||||
)
|
)
|
||||||
mainBusMapping += apbBridge.io.simpleBus -> (0xF0000000l, 1 MB)
|
mainBusMapping += apbBridge.io.pipelinedMemoryBus -> (0xF0000000l, 1 MB)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -288,15 +290,15 @@ case class Murax(config : MuraxConfig) extends Component{
|
||||||
apbMapping += timer.io.apb -> (0x20000, 4 kB)
|
apbMapping += timer.io.apb -> (0x20000, 4 kB)
|
||||||
|
|
||||||
val xip = ifGen(genXip)(new Area{
|
val xip = ifGen(genXip)(new Area{
|
||||||
val ctrl = Apb3SpiDdrMasterCtrl(xipConfig)
|
val ctrl = Apb3SpiXdrMasterCtrl(xipConfig)
|
||||||
ctrl.io.spi <> io.xip
|
ctrl.io.spi <> io.xip
|
||||||
externalInterrupt setWhen(ctrl.io.interrupt)
|
externalInterrupt setWhen(ctrl.io.interrupt)
|
||||||
apbMapping += ctrl.io.apb -> (0x1F000, 4 kB)
|
apbMapping += ctrl.io.apb -> (0x1F000, 4 kB)
|
||||||
|
|
||||||
val accessBus = new SimpleBus(SimpleBusConfig(24,32))
|
val accessBus = new PipelinedMemoryBus(PipelinedMemoryBusConfig(24,32))
|
||||||
mainBusMapping += accessBus -> (0xE0000000l, 16 MB)
|
mainBusMapping += accessBus -> (0xE0000000l, 16 MB)
|
||||||
|
|
||||||
ctrl.io.xip.cmd.valid <> (accessBus.cmd.valid && !accessBus.cmd.wr)
|
ctrl.io.xip.cmd.valid <> (accessBus.cmd.valid && !accessBus.cmd.write)
|
||||||
ctrl.io.xip.cmd.ready <> accessBus.cmd.ready
|
ctrl.io.xip.cmd.ready <> accessBus.cmd.ready
|
||||||
ctrl.io.xip.cmd.payload <> accessBus.cmd.address
|
ctrl.io.xip.cmd.payload <> accessBus.cmd.address
|
||||||
|
|
||||||
|
@ -316,7 +318,7 @@ case class Murax(config : MuraxConfig) extends Component{
|
||||||
)
|
)
|
||||||
|
|
||||||
val mainBusDecoder = new Area {
|
val mainBusDecoder = new Area {
|
||||||
val logic = new MuraxSimpleBusDecoder(
|
val logic = new MuraxPipelinedMemoryBusDecoder(
|
||||||
master = mainBusArbiter.io.masterBus,
|
master = mainBusArbiter.io.masterBus,
|
||||||
specification = mainBusMapping,
|
specification = mainBusMapping,
|
||||||
pipelineMaster = pipelineMainBus
|
pipelineMaster = pipelineMainBus
|
||||||
|
|
|
@ -7,17 +7,18 @@ import spinal.lib.bus.amba3.apb.{Apb3, Apb3Config, Apb3SlaveFactory}
|
||||||
import spinal.lib.bus.misc.SizeMapping
|
import spinal.lib.bus.misc.SizeMapping
|
||||||
import spinal.lib.misc.{HexTools, InterruptCtrl, Prescaler, Timer}
|
import spinal.lib.misc.{HexTools, InterruptCtrl, Prescaler, Timer}
|
||||||
import spinal.lib._
|
import spinal.lib._
|
||||||
|
import spinal.lib.bus.simple._
|
||||||
import vexriscv.plugin.{DBusSimpleBus, IBusSimpleBus}
|
import vexriscv.plugin.{DBusSimpleBus, IBusSimpleBus}
|
||||||
|
|
||||||
class MuraxMasterArbiter(simpleBusConfig : SimpleBusConfig) extends Component{
|
class MuraxMasterArbiter(pipelinedMemoryBusConfig : PipelinedMemoryBusConfig) extends Component{
|
||||||
val io = new Bundle{
|
val io = new Bundle{
|
||||||
val iBus = slave(IBusSimpleBus(false))
|
val iBus = slave(IBusSimpleBus(false))
|
||||||
val dBus = slave(DBusSimpleBus())
|
val dBus = slave(DBusSimpleBus())
|
||||||
val masterBus = master(SimpleBus(simpleBusConfig))
|
val masterBus = master(PipelinedMemoryBus(pipelinedMemoryBusConfig))
|
||||||
}
|
}
|
||||||
|
|
||||||
io.masterBus.cmd.valid := io.iBus.cmd.valid || io.dBus.cmd.valid
|
io.masterBus.cmd.valid := io.iBus.cmd.valid || io.dBus.cmd.valid
|
||||||
io.masterBus.cmd.wr := io.dBus.cmd.valid && io.dBus.cmd.wr
|
io.masterBus.cmd.write := io.dBus.cmd.valid && io.dBus.cmd.wr
|
||||||
io.masterBus.cmd.address := io.dBus.cmd.valid ? io.dBus.cmd.address | io.iBus.cmd.pc
|
io.masterBus.cmd.address := io.dBus.cmd.valid ? io.dBus.cmd.address | io.iBus.cmd.pc
|
||||||
io.masterBus.cmd.data := io.dBus.cmd.data
|
io.masterBus.cmd.data := io.dBus.cmd.data
|
||||||
io.masterBus.cmd.mask := io.dBus.cmd.size.mux(
|
io.masterBus.cmd.mask := io.dBus.cmd.size.mux(
|
||||||
|
@ -31,7 +32,7 @@ class MuraxMasterArbiter(simpleBusConfig : SimpleBusConfig) extends Component{
|
||||||
|
|
||||||
val rspPending = RegInit(False) clearWhen(io.masterBus.rsp.valid)
|
val rspPending = RegInit(False) clearWhen(io.masterBus.rsp.valid)
|
||||||
val rspTarget = RegInit(False)
|
val rspTarget = RegInit(False)
|
||||||
when(io.masterBus.cmd.fire && !io.masterBus.cmd.wr){
|
when(io.masterBus.cmd.fire && !io.masterBus.cmd.write){
|
||||||
rspTarget := io.dBus.cmd.valid
|
rspTarget := io.dBus.cmd.valid
|
||||||
rspPending := True
|
rspPending := True
|
||||||
}
|
}
|
||||||
|
@ -52,18 +53,18 @@ class MuraxMasterArbiter(simpleBusConfig : SimpleBusConfig) extends Component{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
case class MuraxSimpleBusRam(onChipRamSize : BigInt, onChipRamHexFile : String, simpleBusConfig : SimpleBusConfig) extends Component{
|
case class MuraxPipelinedMemoryBusRam(onChipRamSize : BigInt, onChipRamHexFile : String, pipelinedMemoryBusConfig : PipelinedMemoryBusConfig) extends Component{
|
||||||
val io = new Bundle{
|
val io = new Bundle{
|
||||||
val bus = slave(SimpleBus(simpleBusConfig))
|
val bus = slave(PipelinedMemoryBus(pipelinedMemoryBusConfig))
|
||||||
}
|
}
|
||||||
|
|
||||||
val ram = Mem(Bits(32 bits), onChipRamSize / 4)
|
val ram = Mem(Bits(32 bits), onChipRamSize / 4)
|
||||||
io.bus.rsp.valid := RegNext(io.bus.cmd.fire && !io.bus.cmd.wr) init(False)
|
io.bus.rsp.valid := RegNext(io.bus.cmd.fire && !io.bus.cmd.write) init(False)
|
||||||
io.bus.rsp.data := ram.readWriteSync(
|
io.bus.rsp.data := ram.readWriteSync(
|
||||||
address = (io.bus.cmd.address >> 2).resized,
|
address = (io.bus.cmd.address >> 2).resized,
|
||||||
data = io.bus.cmd.data,
|
data = io.bus.cmd.data,
|
||||||
enable = io.bus.cmd.valid,
|
enable = io.bus.cmd.valid,
|
||||||
write = io.bus.cmd.wr,
|
write = io.bus.cmd.write,
|
||||||
mask = io.bus.cmd.mask
|
mask = io.bus.cmd.mask
|
||||||
)
|
)
|
||||||
io.bus.cmd.ready := True
|
io.bus.cmd.ready := True
|
||||||
|
@ -95,42 +96,10 @@ case class Apb3Rom(onChipRamBinFile : String) extends Component{
|
||||||
io.apb.PREADY := True
|
io.apb.PREADY := True
|
||||||
}
|
}
|
||||||
|
|
||||||
class MuraxSimpleBusToApbBridge(apb3Config: Apb3Config, pipelineBridge : Boolean, simpleBusConfig : SimpleBusConfig) extends Component{
|
|
||||||
assert(apb3Config.dataWidth == simpleBusConfig.dataWidth)
|
|
||||||
|
|
||||||
val io = new Bundle {
|
|
||||||
val simpleBus = slave(SimpleBus(simpleBusConfig))
|
|
||||||
val apb = master(Apb3(apb3Config))
|
|
||||||
}
|
|
||||||
|
|
||||||
val simpleBusStage = SimpleBus(simpleBusConfig)
|
class MuraxPipelinedMemoryBusDecoder(master : PipelinedMemoryBus, val specification : Seq[(PipelinedMemoryBus,SizeMapping)], pipelineMaster : Boolean) extends Area{
|
||||||
simpleBusStage.cmd << (if(pipelineBridge) io.simpleBus.cmd.halfPipe() else io.simpleBus.cmd)
|
val masterPipelined = PipelinedMemoryBus(master.config)
|
||||||
simpleBusStage.rsp >-> io.simpleBus.rsp
|
|
||||||
|
|
||||||
val state = RegInit(False)
|
|
||||||
simpleBusStage.cmd.ready := False
|
|
||||||
|
|
||||||
io.apb.PSEL(0) := simpleBusStage.cmd.valid
|
|
||||||
io.apb.PENABLE := state
|
|
||||||
io.apb.PWRITE := simpleBusStage.cmd.wr
|
|
||||||
io.apb.PADDR := simpleBusStage.cmd.address.resized
|
|
||||||
io.apb.PWDATA := simpleBusStage.cmd.data
|
|
||||||
|
|
||||||
simpleBusStage.rsp.valid := False
|
|
||||||
simpleBusStage.rsp.data := io.apb.PRDATA
|
|
||||||
when(!state) {
|
|
||||||
state := simpleBusStage.cmd.valid
|
|
||||||
} otherwise {
|
|
||||||
when(io.apb.PREADY){
|
|
||||||
state := False
|
|
||||||
simpleBusStage.rsp.valid := !simpleBusStage.cmd.wr
|
|
||||||
simpleBusStage.cmd.ready := True
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class MuraxSimpleBusDecoder(master : SimpleBus, val specification : Seq[(SimpleBus,SizeMapping)], pipelineMaster : Boolean) extends Area{
|
|
||||||
val masterPipelined = SimpleBus(master.config)
|
|
||||||
if(!pipelineMaster) {
|
if(!pipelineMaster) {
|
||||||
masterPipelined.cmd << master.cmd
|
masterPipelined.cmd << master.cmd
|
||||||
masterPipelined.rsp >> master.rsp
|
masterPipelined.rsp >> master.rsp
|
||||||
|
@ -151,7 +120,7 @@ class MuraxSimpleBusDecoder(master : SimpleBus, val specification : Seq[(SimpleB
|
||||||
val noHit = !hits.orR
|
val noHit = !hits.orR
|
||||||
masterPipelined.cmd.ready := (hits,slaveBuses).zipped.map(_ && _.cmd.ready).orR || noHit
|
masterPipelined.cmd.ready := (hits,slaveBuses).zipped.map(_ && _.cmd.ready).orR || noHit
|
||||||
|
|
||||||
val rspPending = RegInit(False) clearWhen(masterPipelined.rsp.valid) setWhen(masterPipelined.cmd.fire && !masterPipelined.cmd.wr)
|
val rspPending = RegInit(False) clearWhen(masterPipelined.rsp.valid) setWhen(masterPipelined.cmd.fire && !masterPipelined.cmd.write)
|
||||||
val rspNoHit = RegNext(False) init(False) setWhen(noHit)
|
val rspNoHit = RegNext(False) init(False) setWhen(noHit)
|
||||||
val rspSourceId = RegNextWhen(OHToUInt(hits), masterPipelined.cmd.fire)
|
val rspSourceId = RegNextWhen(OHToUInt(hits), masterPipelined.cmd.fire)
|
||||||
masterPipelined.rsp.valid := slaveBuses.map(_.rsp.valid).orR || (rspPending && rspNoHit)
|
masterPipelined.rsp.valid := slaveBuses.map(_.rsp.valid).orR || (rspPending && rspNoHit)
|
||||||
|
|
|
@ -1,324 +0,0 @@
|
||||||
package vexriscv.demo
|
|
||||||
|
|
||||||
|
|
||||||
import spinal.core._
|
|
||||||
import spinal.lib.bus.misc._
|
|
||||||
import spinal.lib._
|
|
||||||
|
|
||||||
import scala.collection.mutable
|
|
||||||
import scala.collection.mutable.ArrayBuffer
|
|
||||||
|
|
||||||
case class SimpleBusConfig(addressWidth : Int, dataWidth : Int)
|
|
||||||
|
|
||||||
case class SimpleBusCmd(config : SimpleBusConfig) extends Bundle{
|
|
||||||
val wr = Bool
|
|
||||||
val address = UInt(config.addressWidth bits)
|
|
||||||
val data = Bits(config.dataWidth bits)
|
|
||||||
val mask = Bits(4 bit)
|
|
||||||
}
|
|
||||||
|
|
||||||
case class SimpleBusRsp(config : SimpleBusConfig) extends Bundle{
|
|
||||||
val data = Bits(config.dataWidth bits)
|
|
||||||
}
|
|
||||||
|
|
||||||
object SimpleBus{
|
|
||||||
def apply(addressWidth : Int, dataWidth : Int) = new SimpleBus(SimpleBusConfig(addressWidth, dataWidth))
|
|
||||||
}
|
|
||||||
case class SimpleBus(config : SimpleBusConfig) extends Bundle with IMasterSlave {
|
|
||||||
val cmd = Stream(SimpleBusCmd(config))
|
|
||||||
val rsp = Flow(SimpleBusRsp(config))
|
|
||||||
|
|
||||||
override def asMaster(): Unit = {
|
|
||||||
master(cmd)
|
|
||||||
slave(rsp)
|
|
||||||
}
|
|
||||||
|
|
||||||
def <<(m : SimpleBus) : Unit = {
|
|
||||||
val s = this
|
|
||||||
assert(m.config.addressWidth >= s.config.addressWidth)
|
|
||||||
assert(m.config.dataWidth == s.config.dataWidth)
|
|
||||||
s.cmd.valid := m.cmd.valid
|
|
||||||
s.cmd.wr := m.cmd.wr
|
|
||||||
s.cmd.address := m.cmd.address.resized
|
|
||||||
s.cmd.data := m.cmd.data
|
|
||||||
s.cmd.mask := m.cmd.mask
|
|
||||||
m.cmd.ready := s.cmd.ready
|
|
||||||
m.rsp.valid := s.rsp.valid
|
|
||||||
m.rsp.data := s.rsp.data
|
|
||||||
}
|
|
||||||
def >>(s : SimpleBus) : Unit = s << this
|
|
||||||
|
|
||||||
def cmdM2sPipe(): SimpleBus = {
|
|
||||||
val ret = cloneOf(this)
|
|
||||||
this.cmd.m2sPipe() >> ret.cmd
|
|
||||||
this.rsp << ret.rsp
|
|
||||||
ret
|
|
||||||
}
|
|
||||||
|
|
||||||
def cmdS2mPipe(): SimpleBus = {
|
|
||||||
val ret = cloneOf(this)
|
|
||||||
this.cmd.s2mPipe() >> ret.cmd
|
|
||||||
this.rsp << ret.rsp
|
|
||||||
ret
|
|
||||||
}
|
|
||||||
|
|
||||||
def rspPipe(): SimpleBus = {
|
|
||||||
val ret = cloneOf(this)
|
|
||||||
this.cmd >> ret.cmd
|
|
||||||
this.rsp << ret.rsp.stage()
|
|
||||||
ret
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
object SimpleBusArbiter{
|
|
||||||
def apply(inputs : Seq[SimpleBus], pendingRspMax : Int, rspRouteQueue : Boolean, transactionLock : Boolean): SimpleBus = {
|
|
||||||
val c = SimpleBusArbiter(inputs.head.config, inputs.size, pendingRspMax, rspRouteQueue, transactionLock)
|
|
||||||
(inputs, c.io.inputs).zipped.foreach(_ <> _)
|
|
||||||
c.io.output
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case class SimpleBusArbiter(simpleBusConfig : SimpleBusConfig, portCount : Int, pendingRspMax : Int, rspRouteQueue : Boolean, transactionLock : Boolean = true) extends Component{
|
|
||||||
val io = new Bundle{
|
|
||||||
val inputs = Vec(slave(SimpleBus(simpleBusConfig)), portCount)
|
|
||||||
val output = master(SimpleBus(simpleBusConfig))
|
|
||||||
}
|
|
||||||
val logic = if(portCount == 1) new Area{
|
|
||||||
io.output << io.inputs(0)
|
|
||||||
} else new Area {
|
|
||||||
val arbiterFactory = StreamArbiterFactory.lowerFirst
|
|
||||||
if(transactionLock) arbiterFactory.transactionLock else arbiterFactory.noLock
|
|
||||||
val arbiter = arbiterFactory.build(SimpleBusCmd(simpleBusConfig), portCount)
|
|
||||||
(arbiter.io.inputs, io.inputs).zipped.foreach(_ <> _.cmd)
|
|
||||||
|
|
||||||
val rspRouteOh = Bits(portCount bits)
|
|
||||||
|
|
||||||
val rsp = if(!rspRouteQueue) new Area{
|
|
||||||
assert(pendingRspMax == 1)
|
|
||||||
val pending = RegInit(False) clearWhen(io.output.rsp.valid)
|
|
||||||
val target = Reg(Bits(portCount bits))
|
|
||||||
rspRouteOh := target
|
|
||||||
when(io.output.cmd.fire && !io.output.cmd.wr){
|
|
||||||
target := arbiter.io.chosenOH
|
|
||||||
pending := True
|
|
||||||
}
|
|
||||||
io.output.cmd << arbiter.io.output.haltWhen(pending && !io.output.rsp.valid)
|
|
||||||
} else new Area{
|
|
||||||
val (outputCmdFork, routeCmdFork) = StreamFork2(arbiter.io.output)
|
|
||||||
io.output.cmd << outputCmdFork
|
|
||||||
|
|
||||||
val rspRoute = routeCmdFork.translateWith(arbiter.io.chosenOH).throwWhen(routeCmdFork.wr).queueLowLatency(size = pendingRspMax, latency = 1)
|
|
||||||
rspRoute.ready := io.output.rsp.valid
|
|
||||||
rspRouteOh := rspRoute.payload
|
|
||||||
}
|
|
||||||
|
|
||||||
for ((input, id) <- io.inputs.zipWithIndex) {
|
|
||||||
input.rsp.valid := io.output.rsp.valid && rspRouteOh(id)
|
|
||||||
input.rsp.payload := io.output.rsp.payload
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class SimpleBusSlaveFactory(bus: SimpleBus) extends BusSlaveFactoryDelayed{
|
|
||||||
bus.cmd.ready := True
|
|
||||||
|
|
||||||
val readAtCmd = Flow(Bits(bus.config.dataWidth bits))
|
|
||||||
val readAtRsp = readAtCmd.stage()
|
|
||||||
|
|
||||||
val askWrite = (bus.cmd.valid && bus.cmd.wr).allowPruning()
|
|
||||||
val askRead = (bus.cmd.valid && !bus.cmd.wr).allowPruning()
|
|
||||||
val doWrite = (askWrite && bus.cmd.ready).allowPruning()
|
|
||||||
val doRead = (askRead && bus.cmd.ready).allowPruning()
|
|
||||||
|
|
||||||
bus.rsp.valid := readAtRsp.valid
|
|
||||||
bus.rsp.data := readAtRsp.payload
|
|
||||||
|
|
||||||
readAtCmd.valid := doRead
|
|
||||||
readAtCmd.payload := 0
|
|
||||||
|
|
||||||
def readAddress() : UInt = bus.cmd.address
|
|
||||||
def writeAddress() : UInt = bus.cmd.address
|
|
||||||
|
|
||||||
override def readHalt(): Unit = bus.cmd.ready := False
|
|
||||||
override def writeHalt(): Unit = bus.cmd.ready := False
|
|
||||||
|
|
||||||
override def build(): Unit = {
|
|
||||||
super.doNonStopWrite(bus.cmd.data)
|
|
||||||
|
|
||||||
def doMappedElements(jobs : Seq[BusSlaveFactoryElement]) = super.doMappedElements(
|
|
||||||
jobs = jobs,
|
|
||||||
askWrite = askWrite,
|
|
||||||
askRead = askRead,
|
|
||||||
doWrite = doWrite,
|
|
||||||
doRead = doRead,
|
|
||||||
writeData = bus.cmd.data,
|
|
||||||
readData = readAtCmd.payload
|
|
||||||
)
|
|
||||||
|
|
||||||
switch(bus.cmd.address) {
|
|
||||||
for ((address, jobs) <- elementsPerAddress if address.isInstanceOf[SingleMapping]) {
|
|
||||||
is(address.asInstanceOf[SingleMapping].address) {
|
|
||||||
doMappedElements(jobs)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for ((address, jobs) <- elementsPerAddress if !address.isInstanceOf[SingleMapping]) {
|
|
||||||
when(address.hit(bus.cmd.address)){
|
|
||||||
doMappedElements(jobs)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override def busDataWidth: Int = bus.config.dataWidth
|
|
||||||
override def wordAddressInc: Int = busDataWidth / 8
|
|
||||||
}
|
|
||||||
|
|
||||||
case class SimpleBusDecoder(busConfig : SimpleBusConfig, mappings : Seq[AddressMapping], pendingMax : Int = 3) extends Component{
|
|
||||||
val io = new Bundle {
|
|
||||||
val input = slave(SimpleBus(busConfig))
|
|
||||||
val outputs = Vec(master(SimpleBus(busConfig)), 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 ((slaveBus, memorySpace, hit) <- (io.outputs, mappings, hits).zipped) yield {
|
|
||||||
hit := (memorySpace match {
|
|
||||||
case DefaultMapping => !hits.filterNot(_ == hit).orR
|
|
||||||
case _ => memorySpace.hit(io.input.cmd.address)
|
|
||||||
})
|
|
||||||
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 && !io.input.cmd.wr) - U(io.input.rsp.valid)
|
|
||||||
val rspHits = RegNextWhen(hits, io.input.cmd.fire)
|
|
||||||
val rspPending = rspPendingCounter =/= 0
|
|
||||||
val rspNoHit = if (!hasDefault) !rspHits.orR else False
|
|
||||||
io.input.rsp.valid := io.outputs.map(_.rsp.valid).orR || (rspPending && rspNoHit)
|
|
||||||
io.input.rsp.payload := io.outputs.map(_.rsp.payload).read(OHToUInt(rspHits))
|
|
||||||
|
|
||||||
val cmdWait = (io.input.cmd.valid && rspPending && hits =/= rspHits) || rspPendingCounter === pendingMax
|
|
||||||
when(cmdWait) {
|
|
||||||
io.input.cmd.ready := False
|
|
||||||
io.outputs.foreach(_.cmd.valid := False)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
object SimpleBusConnectors{
|
|
||||||
def direct(m : SimpleBus, s : SimpleBus) : Unit = m >> s
|
|
||||||
}
|
|
||||||
|
|
||||||
case class SimpleBusInterconnect(){
|
|
||||||
case class MasterModel(var connector : (SimpleBus,SimpleBus) => Unit = SimpleBusConnectors.direct)
|
|
||||||
case class SlaveModel(mapping : AddressMapping, var connector : (SimpleBus,SimpleBus) => Unit = SimpleBusConnectors.direct, var transactionLock : Boolean = true)
|
|
||||||
case class ConnectionModel(m : SimpleBus, s : SimpleBus, var connector : (SimpleBus,SimpleBus) => Unit = SimpleBusConnectors.direct)
|
|
||||||
|
|
||||||
val masters = mutable.LinkedHashMap[SimpleBus, MasterModel]()
|
|
||||||
val slaves = mutable.LinkedHashMap[SimpleBus, SlaveModel]()
|
|
||||||
val connections = ArrayBuffer[ConnectionModel]()
|
|
||||||
var arbitrationPendingRspMaxDefault = 1
|
|
||||||
var arbitrationRspRouteQueueDefault = false
|
|
||||||
|
|
||||||
def perfConfig(): Unit ={
|
|
||||||
arbitrationPendingRspMaxDefault = 7
|
|
||||||
arbitrationRspRouteQueueDefault = true
|
|
||||||
}
|
|
||||||
|
|
||||||
def areaConfig(): Unit ={
|
|
||||||
arbitrationPendingRspMaxDefault = 1
|
|
||||||
arbitrationRspRouteQueueDefault = false
|
|
||||||
}
|
|
||||||
|
|
||||||
def setConnector(bus : SimpleBus)( connector : (SimpleBus,SimpleBus) => Unit): Unit = (masters.get(bus), slaves.get(bus)) match {
|
|
||||||
case (Some(m), _) => m.connector = connector
|
|
||||||
case (None, Some(s)) => s.connector = connector
|
|
||||||
}
|
|
||||||
|
|
||||||
def setConnector(m : SimpleBus, s : SimpleBus)(connector : (SimpleBus,SimpleBus) => Unit): Unit = connections.find(e => e.m == m && e.s == s) match {
|
|
||||||
case Some(c) => c.connector = connector
|
|
||||||
}
|
|
||||||
|
|
||||||
def addSlave(bus: SimpleBus,mapping: AddressMapping) : this.type = {
|
|
||||||
slaves(bus) = SlaveModel(mapping)
|
|
||||||
this
|
|
||||||
}
|
|
||||||
|
|
||||||
def addSlaves(orders : (SimpleBus,AddressMapping)*) : this.type = {
|
|
||||||
orders.foreach(order => addSlave(order._1,order._2))
|
|
||||||
this
|
|
||||||
}
|
|
||||||
|
|
||||||
def noTransactionLockOn(slave : SimpleBus) : Unit = slaves(slave).transactionLock = false
|
|
||||||
def noTransactionLockOn(slaves : Seq[SimpleBus]) : Unit = slaves.foreach(noTransactionLockOn(_))
|
|
||||||
|
|
||||||
|
|
||||||
def addMaster(bus : SimpleBus, accesses : Seq[SimpleBus]) : this.type = {
|
|
||||||
masters(bus) = MasterModel()
|
|
||||||
for(s <- accesses) connections += ConnectionModel(bus, s)
|
|
||||||
this
|
|
||||||
}
|
|
||||||
|
|
||||||
def addMasters(specs : (SimpleBus,Seq[SimpleBus])*) : this.type = {
|
|
||||||
specs.foreach(spec => addMaster(spec._1,spec._2))
|
|
||||||
this
|
|
||||||
}
|
|
||||||
|
|
||||||
def build(): Unit ={
|
|
||||||
def applyName(bus : Bundle,name : String, onThat : Nameable) : Unit = {
|
|
||||||
if(bus.component == Component.current)
|
|
||||||
onThat.setCompositeName(bus,name)
|
|
||||||
else if(bus.isNamed)
|
|
||||||
onThat.setCompositeName(bus.component,bus.getName() + "_" + name)
|
|
||||||
}
|
|
||||||
|
|
||||||
val connectionsInput = mutable.HashMap[ConnectionModel,SimpleBus]()
|
|
||||||
val connectionsOutput = mutable.HashMap[ConnectionModel,SimpleBus]()
|
|
||||||
for((bus, model) <- masters){
|
|
||||||
val busConnections = connections.filter(_.m == bus)
|
|
||||||
val busSlaves = busConnections.map(c => slaves(c.s))
|
|
||||||
val decoder = new SimpleBusDecoder(bus.config, busSlaves.map(_.mapping))
|
|
||||||
applyName(bus,"decoder",decoder)
|
|
||||||
model.connector(bus, decoder.io.input)
|
|
||||||
for((connection, decoderOutput) <- (busConnections, decoder.io.outputs).zipped) {
|
|
||||||
connectionsInput(connection) = decoderOutput
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for((bus, model) <- slaves){
|
|
||||||
val busConnections = connections.filter(_.s == bus)
|
|
||||||
val busMasters = busConnections.map(c => masters(c.m))
|
|
||||||
val arbiter = new SimpleBusArbiter(bus.config, busMasters.size, arbitrationPendingRspMaxDefault, arbitrationRspRouteQueueDefault, model.transactionLock)
|
|
||||||
applyName(bus,"arbiter",arbiter)
|
|
||||||
model.connector(arbiter.io.output, bus)
|
|
||||||
for((connection, arbiterInput) <- (busConnections, arbiter.io.inputs).zipped) {
|
|
||||||
connectionsOutput(connection) = arbiterInput
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for(connection <- connections){
|
|
||||||
val m = connectionsInput(connection)
|
|
||||||
val s = connectionsOutput(connection)
|
|
||||||
if(m.config == s.config) {
|
|
||||||
connection.connector(m, s)
|
|
||||||
}else{
|
|
||||||
val tmp = cloneOf(s)
|
|
||||||
m >> tmp //Adapte the bus kind.
|
|
||||||
connection.connector(tmp,s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Will make SpinalHDL calling the build function at the end of the current component elaboration
|
|
||||||
Component.current.addPrePopTask(build)
|
|
||||||
}
|
|
|
@ -6,7 +6,7 @@ import spinal.lib._
|
||||||
import spinal.lib.bus.amba4.axi.{Axi4Config, Axi4Shared}
|
import spinal.lib.bus.amba4.axi.{Axi4Config, Axi4Shared}
|
||||||
import spinal.lib.bus.avalon.{AvalonMM, AvalonMMConfig}
|
import spinal.lib.bus.avalon.{AvalonMM, AvalonMMConfig}
|
||||||
import spinal.lib.bus.wishbone.{Wishbone, WishboneConfig}
|
import spinal.lib.bus.wishbone.{Wishbone, WishboneConfig}
|
||||||
import vexriscv.demo.SimpleBus
|
import spinal.lib.bus.simple._
|
||||||
|
|
||||||
case class DataCacheConfig( cacheSize : Int,
|
case class DataCacheConfig( cacheSize : Int,
|
||||||
bytePerLine : Int,
|
bytePerLine : Int,
|
||||||
|
@ -346,8 +346,8 @@ case class DataCacheMemBus(p : DataCacheConfig) extends Bundle with IMasterSlave
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def toSimpleBus(): SimpleBus = {
|
def toPipelinedMemoryBus(): PipelinedMemoryBus = {
|
||||||
val bus = SimpleBus(32,32)
|
val bus = PipelinedMemoryBus(32,32)
|
||||||
|
|
||||||
val counter = Reg(UInt(log2Up(p.burstSize) bits)) init(0)
|
val counter = Reg(UInt(log2Up(p.burstSize) bits)) init(0)
|
||||||
when(bus.cmd.fire){ counter := counter + 1 }
|
when(bus.cmd.fire){ counter := counter + 1 }
|
||||||
|
@ -355,7 +355,7 @@ case class DataCacheMemBus(p : DataCacheConfig) extends Bundle with IMasterSlave
|
||||||
|
|
||||||
bus.cmd.valid := cmd.valid
|
bus.cmd.valid := cmd.valid
|
||||||
bus.cmd.address := (cmd.address(31 downto 2) | counter.resized) @@ U"00"
|
bus.cmd.address := (cmd.address(31 downto 2) | counter.resized) @@ U"00"
|
||||||
bus.cmd.wr := cmd.wr
|
bus.cmd.write := cmd.wr
|
||||||
bus.cmd.mask := cmd.mask
|
bus.cmd.mask := cmd.mask
|
||||||
bus.cmd.data := cmd.data
|
bus.cmd.data := cmd.data
|
||||||
cmd.ready := bus.cmd.ready && (cmd.wr || counter === cmd.length)
|
cmd.ready := bus.cmd.ready && (cmd.wr || counter === cmd.length)
|
||||||
|
|
|
@ -6,7 +6,7 @@ import spinal.lib._
|
||||||
import spinal.lib.bus.amba4.axi.{Axi4Config, Axi4ReadOnly}
|
import spinal.lib.bus.amba4.axi.{Axi4Config, Axi4ReadOnly}
|
||||||
import spinal.lib.bus.avalon.{AvalonMM, AvalonMMConfig}
|
import spinal.lib.bus.avalon.{AvalonMM, AvalonMMConfig}
|
||||||
import spinal.lib.bus.wishbone.{Wishbone, WishboneConfig}
|
import spinal.lib.bus.wishbone.{Wishbone, WishboneConfig}
|
||||||
import vexriscv.demo.{SimpleBus, SimpleBusConfig}
|
import spinal.lib.bus.simple._
|
||||||
|
|
||||||
|
|
||||||
case class InstructionCacheConfig( cacheSize : Int,
|
case class InstructionCacheConfig( cacheSize : Int,
|
||||||
|
@ -46,7 +46,7 @@ case class InstructionCacheConfig( cacheSize : Int,
|
||||||
constantBurstBehavior = true
|
constantBurstBehavior = true
|
||||||
)
|
)
|
||||||
|
|
||||||
def getSimpleBusConfig() = SimpleBusConfig(
|
def getPipelinedMemoryBusConfig() = PipelinedMemoryBusConfig(
|
||||||
addressWidth = 32,
|
addressWidth = 32,
|
||||||
dataWidth = 32
|
dataWidth = 32
|
||||||
)
|
)
|
||||||
|
@ -185,13 +185,13 @@ case class InstructionCacheMemBus(p : InstructionCacheConfig) extends Bundle wit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def toSimpleBus(): SimpleBus = {
|
def toPipelinedMemoryBus(): PipelinedMemoryBus = {
|
||||||
val simpleBusConfig = p.getSimpleBusConfig()
|
val pipelinedMemoryBusConfig = p.getPipelinedMemoryBusConfig()
|
||||||
val bus = SimpleBus(simpleBusConfig)
|
val bus = PipelinedMemoryBus(pipelinedMemoryBusConfig)
|
||||||
val counter = Counter(p.burstSize, bus.cmd.fire)
|
val counter = Counter(p.burstSize, bus.cmd.fire)
|
||||||
bus.cmd.valid := cmd.valid
|
bus.cmd.valid := cmd.valid
|
||||||
bus.cmd.address := cmd.address(31 downto widthOf(counter.value) + 2) @@ counter @@ U"00"
|
bus.cmd.address := cmd.address(31 downto widthOf(counter.value) + 2) @@ counter @@ U"00"
|
||||||
bus.cmd.wr := False
|
bus.cmd.write := False
|
||||||
bus.cmd.mask.assignDontCare()
|
bus.cmd.mask.assignDontCare()
|
||||||
bus.cmd.data.assignDontCare()
|
bus.cmd.data.assignDontCare()
|
||||||
cmd.ready := counter.willOverflow
|
cmd.ready := counter.willOverflow
|
||||||
|
|
|
@ -501,34 +501,34 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
||||||
}
|
}
|
||||||
|
|
||||||
case class InterruptSource(cond : Bool, id : Int)
|
case class InterruptSource(cond : Bool, id : Int)
|
||||||
case class InterruptModel(privilege : Int, privilegeCond : Bool, sources : ArrayBuffer[InterruptSource])
|
case class InterruptPrivilege(privilege : Int, privilegeCond : Bool, sources : ArrayBuffer[InterruptSource])
|
||||||
val interruptModel = ArrayBuffer[InterruptModel]()
|
val interruptModel = ArrayBuffer[InterruptPrivilege]()
|
||||||
if(supervisorGen) interruptModel += InterruptModel(1, sstatus.SIE && privilege <= "01", ArrayBuffer(
|
if(supervisorGen) interruptModel += InterruptPrivilege(1, sstatus.SIE && privilege <= "01", ArrayBuffer(
|
||||||
InterruptSource(sip.STIP && sie.STIE, 5),
|
InterruptSource(sip.STIP && sie.STIE, 5),
|
||||||
InterruptSource(sip.SSIP && sie.SSIE, 1),
|
InterruptSource(sip.SSIP && sie.SSIE, 1),
|
||||||
InterruptSource(sip.SEIP && sie.SEIE, 9)
|
InterruptSource(sip.SEIP && sie.SEIE, 9)
|
||||||
))
|
))
|
||||||
|
|
||||||
interruptModel += InterruptModel(3, mstatus.MIE , ArrayBuffer(
|
interruptModel += InterruptPrivilege(3, mstatus.MIE , ArrayBuffer(
|
||||||
InterruptSource(mip.MTIP && mie.MTIE, 7),
|
InterruptSource(mip.MTIP && mie.MTIE, 7),
|
||||||
InterruptSource(mip.MSIP && mie.MSIE, 3),
|
InterruptSource(mip.MSIP && mie.MSIE, 3),
|
||||||
InterruptSource(mip.MEIP && mie.MEIE, 11)
|
InterruptSource(mip.MEIP && mie.MEIE, 11)
|
||||||
))
|
))
|
||||||
|
|
||||||
case class DelegatorModel(value : Bits, source : Int, target : Int)
|
case class DelegatorModel(value : Bits, source : Int, target : Int)
|
||||||
def solveDelegators(delegators : Seq[DelegatorModel], id : Int, lowerBound : Int): UInt = {
|
// def solveDelegators(delegators : Seq[DelegatorModel], id : Int, lowerBound : Int): UInt = {
|
||||||
val filtredDelegators = delegators.filter(_.target >= lowerBound)
|
// val filtredDelegators = delegators.filter(_.target >= lowerBound)
|
||||||
val ret = U(lowerBound, 2 bits)
|
// val ret = U(lowerBound, 2 bits)
|
||||||
for(d <- filtredDelegators){
|
// for(d <- filtredDelegators){
|
||||||
when(!d.value(id)){
|
// when(!d.value(id)){
|
||||||
ret := d.source
|
// ret := d.source
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
ret
|
// ret
|
||||||
}
|
// }
|
||||||
|
|
||||||
def solveDelegators(delegators : Seq[DelegatorModel], id : UInt, lowerBound : UInt): UInt = {
|
def solveDelegators(delegators : Seq[DelegatorModel], id : UInt, lowerBound : UInt): UInt = {
|
||||||
if(delegators.isEmpty) return CombInit(lowerBound)
|
if(delegators.isEmpty) return U"11"
|
||||||
val ret = U(delegators.last.target, 2 bits)
|
val ret = U(delegators.last.target, 2 bits)
|
||||||
for(d <- delegators){
|
for(d <- delegators){
|
||||||
when(!d.value(id) || d.target < lowerBound){
|
when(!d.value(id) || d.target < lowerBound){
|
||||||
|
@ -536,6 +536,15 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ret
|
ret
|
||||||
|
// val ret = U"11"
|
||||||
|
// var continue = True
|
||||||
|
// for(d <- delegators){
|
||||||
|
// continue = continue && d.value(id)
|
||||||
|
// when(continue){
|
||||||
|
// ret := d.source
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// ret.max(lowerBound)
|
||||||
}
|
}
|
||||||
|
|
||||||
val interruptDelegators = ArrayBuffer[DelegatorModel]()
|
val interruptDelegators = ArrayBuffer[DelegatorModel]()
|
||||||
|
@ -601,7 +610,6 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
||||||
|
|
||||||
when(exceptionValidsRegs.orR){
|
when(exceptionValidsRegs.orR){
|
||||||
fetcher.haltIt()
|
fetcher.haltIt()
|
||||||
// fetcher.flushIt()
|
|
||||||
}
|
}
|
||||||
} else null
|
} else null
|
||||||
|
|
||||||
|
@ -609,11 +617,10 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//Process interrupt request, code and privilege
|
||||||
val interrupt = False
|
val interrupt = False
|
||||||
val interruptCode = UInt(4 bits).assignDontCare().addTag(Verilator.public)
|
val interruptCode = UInt(4 bits).assignDontCare().addTag(Verilator.public)
|
||||||
val interruptTargetPrivilege = UInt(2 bits).assignDontCare()
|
val interruptDelegatorHit = interruptDelegators.map(d => (d -> False)).toMap
|
||||||
|
|
||||||
|
|
||||||
for(model <- interruptModel){
|
for(model <- interruptModel){
|
||||||
when(model.privilegeCond){
|
when(model.privilegeCond){
|
||||||
when(model.sources.map(_.cond).orR){
|
when(model.sources.map(_.cond).orR){
|
||||||
|
@ -622,11 +629,25 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
||||||
for(source <- model.sources){
|
for(source <- model.sources){
|
||||||
when(source.cond){
|
when(source.cond){
|
||||||
interruptCode := source.id
|
interruptCode := source.id
|
||||||
interruptTargetPrivilege := solveDelegators(interruptDelegators, source.id, model.privilege)
|
for(interruptDelegator <- interruptDelegators){
|
||||||
|
interruptDelegatorHit(interruptDelegator) := (if(interruptDelegator.target < model.privilege){
|
||||||
|
False
|
||||||
|
} else {
|
||||||
|
interruptDelegator.value(source.id)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val interruptTargetPrivilege = U(if(interruptDelegators.isEmpty) 3 else interruptDelegators.last.target, 2 bits)
|
||||||
|
for(interruptDelegator <- interruptDelegators){
|
||||||
|
when(!interruptDelegatorHit(interruptDelegator)){
|
||||||
|
interruptTargetPrivilege := interruptDelegator.source
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
interrupt.clearWhen(!allowInterrupts)
|
interrupt.clearWhen(!allowInterrupts)
|
||||||
|
|
||||||
val exception = if(exceptionPortCtrl != null) exceptionPortCtrl.exceptionValids.last && allowException else False
|
val exception = if(exceptionPortCtrl != null) exceptionPortCtrl.exceptionValids.last && allowException else False
|
||||||
|
@ -678,6 +699,7 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
||||||
jumpInterface.payload := (if(!mtvecModeGen) mtvec.base @@ "00" else (mtvec.mode === 0 || hadException) ? (mtvec.base @@ "00") | ((mtvec.base + trapCause) @@ "00") )
|
jumpInterface.payload := (if(!mtvecModeGen) mtvec.base @@ "00" else (mtvec.mode === 0 || hadException) ? (mtvec.base @@ "00") | ((mtvec.base + trapCause) @@ "00") )
|
||||||
beforeLastStage.arbitration.flushAll := True
|
beforeLastStage.arbitration.flushAll := True
|
||||||
|
|
||||||
|
privilege := targetPrivilege
|
||||||
switch(targetPrivilege){
|
switch(targetPrivilege){
|
||||||
if(supervisorGen) is(1) {
|
if(supervisorGen) is(1) {
|
||||||
sstatus.SIE := False
|
sstatus.SIE := False
|
||||||
|
|
|
@ -6,7 +6,7 @@ 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}
|
import spinal.lib.bus.wishbone.{Wishbone, WishboneConfig}
|
||||||
import vexriscv.demo.SimpleBus
|
import spinal.lib.bus.simple._
|
||||||
import vexriscv.ip.DataCacheMemCmd
|
import vexriscv.ip.DataCacheMemCmd
|
||||||
|
|
||||||
|
|
||||||
|
@ -177,10 +177,10 @@ case class DBusSimpleBus() extends Bundle with IMasterSlave{
|
||||||
bus
|
bus
|
||||||
}
|
}
|
||||||
|
|
||||||
def toSimpleBus() : SimpleBus = {
|
def toPipelinedMemoryBus() : PipelinedMemoryBus = {
|
||||||
val bus = SimpleBus(32,32)
|
val bus = PipelinedMemoryBus(32,32)
|
||||||
bus.cmd.valid := cmd.valid
|
bus.cmd.valid := cmd.valid
|
||||||
bus.cmd.wr := cmd.wr
|
bus.cmd.write := cmd.wr
|
||||||
bus.cmd.address := cmd.address.resized
|
bus.cmd.address := cmd.address.resized
|
||||||
bus.cmd.data := cmd.data
|
bus.cmd.data := cmd.data
|
||||||
bus.cmd.mask := cmd.size.mux(
|
bus.cmd.mask := cmd.size.mux(
|
||||||
|
|
|
@ -141,7 +141,7 @@ class DebugPlugin(val debugClockDomain : ClockDomain, hardwareBreakpointCount :
|
||||||
val haltIt = RegInit(False)
|
val haltIt = RegInit(False)
|
||||||
val stepIt = RegInit(False)
|
val stepIt = RegInit(False)
|
||||||
|
|
||||||
val isPipActive = RegNext(List(decode,execute, memory, writeBack).map(_.arbitration.isValid).orR)
|
val isPipActive = RegNext(stages.map(_.arbitration.isValid).orR)
|
||||||
val isPipBusy = isPipActive || RegNext(isPipActive)
|
val isPipBusy = isPipActive || RegNext(isPipActive)
|
||||||
val haltedByBreak = RegInit(False)
|
val haltedByBreak = RegInit(False)
|
||||||
|
|
||||||
|
@ -152,8 +152,8 @@ class DebugPlugin(val debugClockDomain : ClockDomain, hardwareBreakpointCount :
|
||||||
hardwareBreakpoints.foreach(_.valid init(False))
|
hardwareBreakpoints.foreach(_.valid init(False))
|
||||||
|
|
||||||
val busReadDataReg = Reg(Bits(32 bit))
|
val busReadDataReg = Reg(Bits(32 bit))
|
||||||
when(writeBack.arbitration.isValid) {
|
when(stages.last.arbitration.isValid) {
|
||||||
busReadDataReg := writeBack.output(REGFILE_WRITE_DATA)
|
busReadDataReg := stages.last.output(REGFILE_WRITE_DATA)
|
||||||
}
|
}
|
||||||
io.bus.cmd.ready := True
|
io.bus.cmd.ready := True
|
||||||
io.bus.rsp.data := busReadDataReg
|
io.bus.rsp.data := busReadDataReg
|
||||||
|
@ -195,11 +195,11 @@ class DebugPlugin(val debugClockDomain : ClockDomain, hardwareBreakpointCount :
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
decode.insert(DO_EBREAK) := !haltIt && (decode.input(IS_EBREAK) || hardwareBreakpoints.map(hb => hb.valid && hb.pc === (execute.input(PC) >> 1)).foldLeft(False)(_ || _))
|
decode.insert(DO_EBREAK) := !haltIt && (decode.input(IS_EBREAK) || hardwareBreakpoints.map(hb => hb.valid && hb.pc === (decode.input(PC) >> 1)).foldLeft(False)(_ || _))
|
||||||
when(execute.arbitration.isValid && execute.input(DO_EBREAK)){
|
when(execute.arbitration.isValid && execute.input(DO_EBREAK)){
|
||||||
execute.arbitration.haltByOther := True
|
execute.arbitration.haltByOther := True
|
||||||
busReadDataReg := execute.input(PC).asBits
|
busReadDataReg := execute.input(PC).asBits
|
||||||
when(List(memory, writeBack).map(_.arbitration.isValid).orR === False){
|
when(stagesFromExecute.tail.map(_.arbitration.isValid).orR === False){
|
||||||
iBusFetcher.flushIt()
|
iBusFetcher.flushIt()
|
||||||
iBusFetcher.haltIt()
|
iBusFetcher.haltIt()
|
||||||
execute.arbitration.flushAll := True
|
execute.arbitration.flushAll := True
|
||||||
|
|
|
@ -6,8 +6,7 @@ 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}
|
import spinal.lib.bus.wishbone.{Wishbone, WishboneConfig}
|
||||||
import vexriscv.demo.SimpleBus
|
import spinal.lib.bus.simple._
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
case class IBusSimpleCmd() extends Bundle{
|
case class IBusSimpleCmd() extends Bundle{
|
||||||
|
@ -136,11 +135,11 @@ case class IBusSimpleBus(interfaceKeepData : Boolean = false) extends Bundle wit
|
||||||
bus
|
bus
|
||||||
}
|
}
|
||||||
|
|
||||||
def toSimpleBus(): SimpleBus = {
|
def toPipelinedMemoryBus(): PipelinedMemoryBus = {
|
||||||
val bus = SimpleBus(32,32)
|
val bus = PipelinedMemoryBus(32,32)
|
||||||
bus.cmd.arbitrationFrom(cmd)
|
bus.cmd.arbitrationFrom(cmd)
|
||||||
bus.cmd.address := cmd.pc.resized
|
bus.cmd.address := cmd.pc.resized
|
||||||
bus.cmd.wr := False
|
bus.cmd.write := False
|
||||||
bus.cmd.mask.assignDontCare()
|
bus.cmd.mask.assignDontCare()
|
||||||
bus.cmd.data.assignDontCare()
|
bus.cmd.data.assignDontCare()
|
||||||
rsp.valid := bus.rsp.valid
|
rsp.valid := bus.rsp.valid
|
||||||
|
|
|
@ -35,7 +35,7 @@ public:
|
||||||
for(uint32_t i = 0;i < (1 << 12);i++) mem[i] = NULL;
|
for(uint32_t i = 0;i < (1 << 12);i++) mem[i] = NULL;
|
||||||
}
|
}
|
||||||
~Memory(){
|
~Memory(){
|
||||||
for(uint32_t i = 0;i < (1 << 12);i++) if(mem[i]) delete mem[i];
|
for(uint32_t i = 0;i < (1 << 12);i++) if(mem[i]) delete [] mem[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t* get(uint32_t address){
|
uint8_t* get(uint32_t address){
|
||||||
|
@ -106,6 +106,7 @@ void loadHexImpl(string path,Memory* mem) {
|
||||||
fseek(fp, 0, SEEK_SET);
|
fseek(fp, 0, SEEK_SET);
|
||||||
char* content = new char[size];
|
char* content = new char[size];
|
||||||
fread(content, 1, size, fp);
|
fread(content, 1, size, fp);
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
char* line = content;
|
char* line = content;
|
||||||
|
@ -146,7 +147,7 @@ void loadHexImpl(string path,Memory* mem) {
|
||||||
size--;
|
size--;
|
||||||
}
|
}
|
||||||
|
|
||||||
delete content;
|
delete [] content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -322,7 +323,7 @@ public:
|
||||||
case MCAUSE: return &mcause.raw; break;
|
case MCAUSE: return &mcause.raw; break;
|
||||||
case MBADADDR: return &mbadaddr; break;
|
case MBADADDR: return &mbadaddr; break;
|
||||||
case MEPC: return &mepc; break;
|
case MEPC: return &mepc; break;
|
||||||
default: fail(); break;
|
default: fail(); return NULL; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -683,8 +684,14 @@ public:
|
||||||
mem.read(address, 4, (uint8_t*)data);
|
mem.read(address, 4, (uint8_t*)data);
|
||||||
bool error;
|
bool error;
|
||||||
ws->iBusAccessPatch(address,data,&error);
|
ws->iBusAccessPatch(address,data,&error);
|
||||||
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool dRead(int32_t address, int32_t size, uint32_t *data){
|
virtual bool dRead(int32_t address, int32_t size, uint32_t *data){
|
||||||
|
if(size < 1 || size > 4){
|
||||||
|
cout << "dRead size=" << size << endl;
|
||||||
|
fail();
|
||||||
|
}
|
||||||
if(address & (size-1) != 0) cout << "Ref did a unaligned read" << endl;
|
if(address & (size-1) != 0) cout << "Ref did a unaligned read" << endl;
|
||||||
if((address & 0xF0000000) == 0xF0000000){
|
if((address & 0xF0000000) == 0xF0000000){
|
||||||
MemRead t = periphRead.front();
|
MemRead t = periphRead.front();
|
||||||
|
@ -696,6 +703,7 @@ public:
|
||||||
}else {
|
}else {
|
||||||
mem.read(address, size, (uint8_t*)data);
|
mem.read(address, size, (uint8_t*)data);
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
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 & (size-1) != 0) cout << "Ref did a unaligned write" << endl;
|
if(address & (size-1) != 0) cout << "Ref did a unaligned write" << endl;
|
||||||
|
@ -1059,13 +1067,13 @@ public:
|
||||||
#ifdef TRACE_WITH_TIME
|
#ifdef TRACE_WITH_TIME
|
||||||
currentTime <<
|
currentTime <<
|
||||||
#endif
|
#endif
|
||||||
" PC " << hex << setw(8) << top->VexRiscv->writeBack_PC << " : reg[" << dec << setw(2) << (uint32_t)top->VexRiscv->writeBack_RegFilePlugin_regFileWrite_payload_address << "] = " << hex << setw(8) << top->VexRiscv->writeBack_RegFilePlugin_regFileWrite_payload_data << endl;
|
" PC " << hex << setw(8) << top->VexRiscv->writeBack_PC << " : reg[" << dec << setw(2) << (uint32_t)top->VexRiscv->writeBack_RegFilePlugin_regFileWrite_payload_address << "] = " << hex << setw(8) << top->VexRiscv->writeBack_RegFilePlugin_regFileWrite_payload_data << dec << endl;
|
||||||
} else {
|
} else {
|
||||||
regTraces <<
|
regTraces <<
|
||||||
#ifdef TRACE_WITH_TIME
|
#ifdef TRACE_WITH_TIME
|
||||||
currentTime <<
|
currentTime <<
|
||||||
#endif
|
#endif
|
||||||
" PC " << hex << setw(8) << top->VexRiscv->writeBack_PC << endl;
|
" PC " << hex << setw(8) << top->VexRiscv->writeBack_PC << dec << endl;
|
||||||
}
|
}
|
||||||
if(riscvRefEnable) if(rfWriteValid != riscvRef.rfWriteValid ||
|
if(riscvRefEnable) if(rfWriteValid != riscvRef.rfWriteValid ||
|
||||||
(rfWriteValid && (rfWriteAddress!= riscvRef.rfWriteAddress || rfWriteData!= riscvRef.rfWriteData))){
|
(rfWriteValid && (rfWriteAddress!= riscvRef.rfWriteAddress || rfWriteData!= riscvRef.rfWriteData))){
|
||||||
|
@ -1113,7 +1121,7 @@ public:
|
||||||
staticMutex.unlock();
|
staticMutex.unlock();
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
staticMutex.lock();
|
staticMutex.lock();
|
||||||
cout << "FAIL " << name << " at PC=" << hex << setw(8) << top->VexRiscv->writeBack_PC << endl; //<< " seed : " << seed <<
|
cout << "FAIL " << name << " at PC=" << hex << setw(8) << top->VexRiscv->writeBack_PC << dec << endl; //<< " seed : " << seed <<
|
||||||
cycles += instanceCycles;
|
cycles += instanceCycles;
|
||||||
staticMutex.unlock();
|
staticMutex.unlock();
|
||||||
failed = true;
|
failed = true;
|
||||||
|
@ -2104,15 +2112,19 @@ public:
|
||||||
fseek(refFile, 0, SEEK_SET);
|
fseek(refFile, 0, SEEK_SET);
|
||||||
char* ref = new char[refSize];
|
char* ref = new char[refSize];
|
||||||
fread(ref, 1, refSize, refFile);
|
fread(ref, 1, refSize, refFile);
|
||||||
|
fclose(refFile);
|
||||||
|
|
||||||
|
|
||||||
logTraces.flush();
|
logTraces.flush();
|
||||||
|
logTraces.close();
|
||||||
|
|
||||||
FILE *logFile = fopen((name + ".logTrace").c_str(), "r");
|
FILE *logFile = fopen((name + ".logTrace").c_str(), "r");
|
||||||
fseek(logFile, 0, SEEK_END);
|
fseek(logFile, 0, SEEK_END);
|
||||||
uint32_t logSize = ftell(logFile);
|
uint32_t logSize = ftell(logFile);
|
||||||
fseek(logFile, 0, SEEK_SET);
|
fseek(logFile, 0, SEEK_SET);
|
||||||
char* log = new char[logSize];
|
char* log = new char[logSize];
|
||||||
fread(log, 1, logSize, logFile);
|
fread(log, 1, logSize, logFile);
|
||||||
|
fclose(logFile);
|
||||||
|
|
||||||
if(refSize > logSize || memcmp(log,ref,refSize))
|
if(refSize > logSize || memcmp(log,ref,refSize))
|
||||||
fail();
|
fail();
|
||||||
|
@ -2138,7 +2150,7 @@ public:
|
||||||
virtual void dBusAccess(uint32_t addr,bool wr, uint32_t size,uint32_t mask, uint32_t *data, bool *error) {
|
virtual void dBusAccess(uint32_t addr,bool wr, uint32_t size,uint32_t mask, uint32_t *data, bool *error) {
|
||||||
Workspace::dBusAccess(addr,wr,size,mask,data,error);
|
Workspace::dBusAccess(addr,wr,size,mask,data,error);
|
||||||
if(wr && addr == 0xF00FFF2C){
|
if(wr && addr == 0xF00FFF2C){
|
||||||
out32 << hex << setw(8) << std::setfill('0') << *data;
|
out32 << hex << setw(8) << std::setfill('0') << *data << dec;
|
||||||
if(++out32Counter % 4 == 0) out32 << "\n";
|
if(++out32Counter % 4 == 0) out32 << "\n";
|
||||||
*error = 0;
|
*error = 0;
|
||||||
}
|
}
|
||||||
|
@ -2157,15 +2169,19 @@ public:
|
||||||
fseek(refFile, 0, SEEK_SET);
|
fseek(refFile, 0, SEEK_SET);
|
||||||
char* ref = new char[refSize];
|
char* ref = new char[refSize];
|
||||||
fread(ref, 1, refSize, refFile);
|
fread(ref, 1, refSize, refFile);
|
||||||
|
fclose(refFile);
|
||||||
|
|
||||||
|
|
||||||
out32.flush();
|
out32.flush();
|
||||||
|
out32.close();
|
||||||
|
|
||||||
FILE *logFile = fopen((name + ".out32").c_str(), "r");
|
FILE *logFile = fopen((name + ".out32").c_str(), "r");
|
||||||
fseek(logFile, 0, SEEK_END);
|
fseek(logFile, 0, SEEK_END);
|
||||||
uint32_t logSize = ftell(logFile);
|
uint32_t logSize = ftell(logFile);
|
||||||
fseek(logFile, 0, SEEK_SET);
|
fseek(logFile, 0, SEEK_SET);
|
||||||
char* log = new char[logSize];
|
char* log = new char[logSize];
|
||||||
fread(log, 1, logSize, logFile);
|
fread(log, 1, logSize, logFile);
|
||||||
|
fclose(logFile);
|
||||||
|
|
||||||
if(refSize > logSize || memcmp(log,ref,refSize))
|
if(refSize > logSize || memcmp(log,ref,refSize))
|
||||||
fail();
|
fail();
|
||||||
|
|
|
@ -46,11 +46,11 @@ else
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
||||||
ifneq ($(shell dplus -VV | grep timerInterrupt ../../../../VexRiscv.v -w),)
|
ifneq ($(shell grep timerInterrupt ../../../../VexRiscv.v -w),)
|
||||||
ADDCFLAGS += -CFLAGS -DTIMER_INTERRUPT
|
ADDCFLAGS += -CFLAGS -DTIMER_INTERRUPT
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifneq ($(shell dplus -VV | grep externalInterrupt ../../../../VexRiscv.v -w),)
|
ifneq ($(shell grep externalInterrupt ../../../../VexRiscv.v -w),)
|
||||||
ADDCFLAGS += -CFLAGS -DEXTERNAL_INTERRUPT
|
ADDCFLAGS += -CFLAGS -DEXTERNAL_INTERRUPT
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
|
@ -20,9 +20,9 @@ import scala.collection.mutable
|
||||||
object MuraxSim {
|
object MuraxSim {
|
||||||
def main(args: Array[String]): Unit = {
|
def main(args: Array[String]): Unit = {
|
||||||
// def config = MuraxConfig.default.copy(onChipRamSize = 256 kB)
|
// def config = MuraxConfig.default.copy(onChipRamSize = 256 kB)
|
||||||
def config = MuraxConfig.default(withXip = true).copy(onChipRamSize = 4 kB, onChipRamHexFile = "src/main/ressource/hex/muraxDemo.hex")
|
def config = MuraxConfig.default(withXip = false).copy(onChipRamSize = 4 kB, onChipRamHexFile = "src/main/ressource/hex/muraxDemo.hex")
|
||||||
val simSlowDown = true
|
val simSlowDown = false
|
||||||
SimConfig.allOptimisation.withWave.compile(new Murax(config)).doSimUntilVoid{dut =>
|
SimConfig.allOptimisation.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
|
||||||
|
|
Loading…
Reference in a new issue