Rename SimpleBus into PipelinedMemoryBus

Move PipelinedMemoryBus into SpinalHDL lib
This commit is contained in:
Dolu1990 2018-11-30 17:37:17 +01:00
parent 2f6a2dfccc
commit b1b7da4f10
8 changed files with 71 additions and 393 deletions

View File

@ -29,16 +29,16 @@ lazy val root = (project in file(".")).
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.2.2",
"com.github.spinalhdl" % "spinalhdl-lib_2.11" % "1.2.2", // "com.github.spinalhdl" % "spinalhdl-lib_2.11" % "1.2.2",
"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") addCompilerPlugin("org.scala-lang.plugins" % "scala-continuations-plugin_2.11.6" % "1.0.2")

View File

@ -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 MuraxPipelinedMemoryBusToApbBridge(
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

View File

@ -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,42 @@ 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{ class MuraxPipelinedMemoryBusToApbBridge(apb3Config: Apb3Config, pipelineBridge : Boolean, pipelinedMemoryBusConfig : PipelinedMemoryBusConfig) extends Component{
assert(apb3Config.dataWidth == simpleBusConfig.dataWidth) assert(apb3Config.dataWidth == pipelinedMemoryBusConfig.dataWidth)
val io = new Bundle { val io = new Bundle {
val simpleBus = slave(SimpleBus(simpleBusConfig)) val pipelinedMemoryBus = slave(PipelinedMemoryBus(pipelinedMemoryBusConfig))
val apb = master(Apb3(apb3Config)) val apb = master(Apb3(apb3Config))
} }
val simpleBusStage = SimpleBus(simpleBusConfig) val pipelinedMemoryBusStage = PipelinedMemoryBus(pipelinedMemoryBusConfig)
simpleBusStage.cmd << (if(pipelineBridge) io.simpleBus.cmd.halfPipe() else io.simpleBus.cmd) pipelinedMemoryBusStage.cmd << (if(pipelineBridge) io.pipelinedMemoryBus.cmd.halfPipe() else io.pipelinedMemoryBus.cmd)
simpleBusStage.rsp >-> io.simpleBus.rsp pipelinedMemoryBusStage.rsp >-> io.pipelinedMemoryBus.rsp
val state = RegInit(False) val state = RegInit(False)
simpleBusStage.cmd.ready := False pipelinedMemoryBusStage.cmd.ready := False
io.apb.PSEL(0) := simpleBusStage.cmd.valid io.apb.PSEL(0) := pipelinedMemoryBusStage.cmd.valid
io.apb.PENABLE := state io.apb.PENABLE := state
io.apb.PWRITE := simpleBusStage.cmd.wr io.apb.PWRITE := pipelinedMemoryBusStage.cmd.write
io.apb.PADDR := simpleBusStage.cmd.address.resized io.apb.PADDR := pipelinedMemoryBusStage.cmd.address.resized
io.apb.PWDATA := simpleBusStage.cmd.data io.apb.PWDATA := pipelinedMemoryBusStage.cmd.data
simpleBusStage.rsp.valid := False pipelinedMemoryBusStage.rsp.valid := False
simpleBusStage.rsp.data := io.apb.PRDATA pipelinedMemoryBusStage.rsp.data := io.apb.PRDATA
when(!state) { when(!state) {
state := simpleBusStage.cmd.valid state := pipelinedMemoryBusStage.cmd.valid
} otherwise { } otherwise {
when(io.apb.PREADY){ when(io.apb.PREADY){
state := False state := False
simpleBusStage.rsp.valid := !simpleBusStage.cmd.wr pipelinedMemoryBusStage.rsp.valid := !pipelinedMemoryBusStage.cmd.write
simpleBusStage.cmd.ready := True pipelinedMemoryBusStage.cmd.ready := True
} }
} }
} }
class MuraxSimpleBusDecoder(master : SimpleBus, val specification : Seq[(SimpleBus,SizeMapping)], pipelineMaster : Boolean) extends Area{ class MuraxPipelinedMemoryBusDecoder(master : PipelinedMemoryBus, val specification : Seq[(PipelinedMemoryBus,SizeMapping)], pipelineMaster : Boolean) extends Area{
val masterPipelined = SimpleBus(master.config) val masterPipelined = PipelinedMemoryBus(master.config)
if(!pipelineMaster) { if(!pipelineMaster) {
masterPipelined.cmd << master.cmd masterPipelined.cmd << master.cmd
masterPipelined.rsp >> master.rsp masterPipelined.rsp >> master.rsp
@ -151,7 +152,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)

View File

@ -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)
}

View File

@ -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)

View File

@ -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

View File

@ -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
@ -176,11 +176,11 @@ case class DBusSimpleBus() extends Bundle with IMasterSlave{
rsp.error := False //TODO rsp.error := False //TODO
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(

View File

@ -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