Merge pull request #1190 from freechipsproject/bus-api
BusWrapper API Update
This commit is contained in:
commit
20a8876856
@ -7,7 +7,7 @@ import freechips.rocketchip.config.Parameters
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.tilelink._
|
||||
import freechips.rocketchip.util._
|
||||
import freechips.rocketchip.coreplex.{CrossingWrapper, AsynchronousCrossing}
|
||||
import freechips.rocketchip.subsystem.{CrossingWrapper, AsynchronousCrossing}
|
||||
|
||||
class AXI4AsyncCrossingSource(sync: Int = 3)(implicit p: Parameters) extends LazyModule
|
||||
{
|
||||
|
@ -1,55 +0,0 @@
|
||||
// See LICENSE.SiFive for license details.
|
||||
|
||||
package freechips.rocketchip.coreplex
|
||||
|
||||
import Chisel._
|
||||
import freechips.rocketchip.config.{Field, Parameters}
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.tilelink._
|
||||
import freechips.rocketchip.util._
|
||||
|
||||
case class FrontBusParams(
|
||||
beatBytes: Int,
|
||||
blockBytes: Int,
|
||||
masterBuffering: BufferParams = BufferParams.default,
|
||||
slaveBuffering: BufferParams = BufferParams.default
|
||||
) extends TLBusParams
|
||||
|
||||
case object FrontBusKey extends Field[FrontBusParams]
|
||||
|
||||
class FrontBus(params: FrontBusParams)(implicit p: Parameters) extends TLBusWrapper(params, "FrontBus") {
|
||||
|
||||
private val master_buffer = LazyModule(new TLBuffer(params.masterBuffering))
|
||||
private val master_fixer = LazyModule(new TLFIFOFixer(TLFIFOFixer.all))
|
||||
|
||||
master_buffer.suggestName(s"${busName}_master_TLBuffer")
|
||||
master_fixer.suggestName(s"${busName}_master_TLFIFOFixer")
|
||||
|
||||
master_fixer.node :=* master_buffer.node
|
||||
inwardNode :=* master_fixer.node
|
||||
|
||||
def fromSyncPorts(addBuffers: Int = 0, name: Option[String] = None): TLInwardNode = {
|
||||
TLBuffer.chain(addBuffers).foldLeft(master_buffer.node:TLInwardNode)(_ :=* _)
|
||||
}
|
||||
|
||||
def fromSyncMasters(addBuffers: Int = 0, name: Option[String] = None): TLInwardNode = {
|
||||
TLBuffer.chain(addBuffers).foldLeft(master_buffer.node:TLInwardNode)(_ :=* _)
|
||||
}
|
||||
|
||||
def fromCoherentChip: TLInwardNode = inwardNode
|
||||
|
||||
def toSystemBus : TLOutwardNode = TLBuffer(params.slaveBuffering) :=* xbar.node
|
||||
|
||||
}
|
||||
|
||||
/** Provides buses that serve as attachment points,
|
||||
* for use in traits that connect individual devices or external ports.
|
||||
*/
|
||||
trait HasFrontBus extends HasSystemBus {
|
||||
private val frontbusParams = p(FrontBusKey)
|
||||
val frontbusBeatBytes = frontbusParams.beatBytes
|
||||
|
||||
val fbus = LazyModule(new FrontBus(frontbusParams))
|
||||
|
||||
FlipRendering { implicit p => sbus.fromFrontBus :=* fbus.toSystemBus }
|
||||
}
|
@ -1,79 +0,0 @@
|
||||
// See LICENSE.SiFive for license details.
|
||||
|
||||
package freechips.rocketchip.coreplex
|
||||
|
||||
import Chisel._
|
||||
import freechips.rocketchip.config._
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.tilelink._
|
||||
import freechips.rocketchip.util._
|
||||
|
||||
// TODO: applies to all caches, for now
|
||||
case object CacheBlockBytes extends Field[Int](64)
|
||||
|
||||
/** L2 Broadcast Hub configuration */
|
||||
case class BroadcastParams(
|
||||
nTrackers: Int = 4,
|
||||
bufferless: Boolean = false)
|
||||
|
||||
case object BroadcastKey extends Field(BroadcastParams())
|
||||
|
||||
/** L2 memory subsystem configuration */
|
||||
case class BankedL2Params(
|
||||
nMemoryChannels: Int = 1,
|
||||
nBanksPerChannel: Int = 1,
|
||||
coherenceManager: HasMemoryBus => (TLInwardNode, TLOutwardNode, () => Option[Bool]) = { coreplex =>
|
||||
implicit val p = coreplex.p
|
||||
val BroadcastParams(nTrackers, bufferless) = p(BroadcastKey)
|
||||
val bh = LazyModule(new TLBroadcast(coreplex.memBusBlockBytes, nTrackers, bufferless))
|
||||
val ww = LazyModule(new TLWidthWidget(coreplex.sbusBeatBytes))
|
||||
ww.node :*= bh.node
|
||||
(bh.node, ww.node, () => None)
|
||||
}) {
|
||||
val nBanks = nMemoryChannels*nBanksPerChannel
|
||||
}
|
||||
|
||||
case object BankedL2Key extends Field(BankedL2Params())
|
||||
|
||||
/** Parameterization of the memory-side bus created for each memory channel */
|
||||
case class MemoryBusParams(
|
||||
beatBytes: Int,
|
||||
blockBytes: Int,
|
||||
masterBuffering: BufferParams = BufferParams.none,
|
||||
slaveBuffering: BufferParams = BufferParams.none
|
||||
) extends TLBusParams
|
||||
|
||||
case object MemoryBusKey extends Field[MemoryBusParams]
|
||||
|
||||
/** Wrapper for creating TL nodes from a bus connected to the back of each mem channel */
|
||||
class MemoryBus(params: MemoryBusParams)(implicit p: Parameters) extends TLBusWrapper(params, "MemoryBus")(p) {
|
||||
def fromCoherenceManager: TLInwardNode = inwardBufNode
|
||||
def toDRAMController: TLOutwardNode = outwardBufNode
|
||||
def toVariableWidthSlave: TLOutwardNode = outwardFragNode
|
||||
}
|
||||
|
||||
trait HasMemoryBus extends HasSystemBus with HasPeripheryBus with HasInterruptBus {
|
||||
private val mbusParams = p(MemoryBusKey)
|
||||
private val l2Params = p(BankedL2Key)
|
||||
val MemoryBusParams(memBusBeatBytes, memBusBlockBytes, _, _) = mbusParams
|
||||
val BankedL2Params(nMemoryChannels, nBanksPerChannel, coherenceManager) = l2Params
|
||||
val nBanks = l2Params.nBanks
|
||||
val cacheBlockBytes = memBusBlockBytes
|
||||
private val (in, out, halt) = coherenceManager(this)
|
||||
def memBusCanCauseHalt: () => Option[Bool] = halt
|
||||
|
||||
require (isPow2(nMemoryChannels) || nMemoryChannels == 0)
|
||||
require (isPow2(nBanksPerChannel))
|
||||
require (isPow2(memBusBlockBytes))
|
||||
|
||||
private val mask = ~BigInt((nBanks-1) * memBusBlockBytes)
|
||||
val memBuses = Seq.tabulate(nMemoryChannels) { channel =>
|
||||
val mbus = LazyModule(new MemoryBus(mbusParams))
|
||||
for (bank <- 0 until nBanksPerChannel) {
|
||||
val offset = (bank * nMemoryChannels) + channel
|
||||
ForceFanout(a = true) { implicit p => in := sbus.toMemoryBus }
|
||||
mbus.fromCoherenceManager := TLFilter(TLFilter.Mmask(AddressSet(offset * memBusBlockBytes, mask))) := out
|
||||
}
|
||||
mbus
|
||||
}
|
||||
}
|
@ -1,61 +0,0 @@
|
||||
// See LICENSE.SiFive for license details.
|
||||
|
||||
package freechips.rocketchip.coreplex
|
||||
|
||||
import Chisel._
|
||||
import freechips.rocketchip.config.{Field, Parameters}
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.tilelink._
|
||||
|
||||
import freechips.rocketchip.config.Field
|
||||
|
||||
case class PeripheryBusParams(
|
||||
beatBytes: Int,
|
||||
blockBytes: Int,
|
||||
masterBuffering: BufferParams = BufferParams.default,
|
||||
slaveBuffering: BufferParams = BufferParams.none,
|
||||
arithmetic: Boolean = true,
|
||||
frequency: BigInt = BigInt(100000000) // 100 MHz as default bus frequency
|
||||
) extends TLBusParams {
|
||||
}
|
||||
|
||||
case object PeripheryBusKey extends Field[PeripheryBusParams]
|
||||
|
||||
class PeripheryBus(params: PeripheryBusParams)(implicit p: Parameters) extends TLBusWrapper(params, "PeripheryBus") {
|
||||
|
||||
def toFixedWidthSingleBeatSlave(widthBytes: Int) = {
|
||||
TLFragmenter(widthBytes, params.blockBytes) := outwardWWNode
|
||||
}
|
||||
|
||||
def toLargeBurstSlave(maxXferBytes: Int) = {
|
||||
TLFragmenter(params.beatBytes, maxXferBytes) := outwardBufNode
|
||||
}
|
||||
|
||||
val fromSystemBus: TLInwardNode = {
|
||||
val atomics = LazyModule(new TLAtomicAutomata(arithmetic = params.arithmetic))
|
||||
xbar.node :*= TLBuffer(params.masterBuffering) :*= atomics.node
|
||||
}
|
||||
|
||||
def toTile(name: Option[String] = None)(gen: Parameters => TLInwardNode) {
|
||||
this {
|
||||
LazyScope(s"${busName}ToTile${name.getOrElse("")}") {
|
||||
FlipRendering { implicit p =>
|
||||
gen(p) :*= outwardNode
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Provides buses that serve as attachment points,
|
||||
* for use in traits that connect individual devices or external ports.
|
||||
*/
|
||||
trait HasPeripheryBus extends HasSystemBus {
|
||||
private val pbusParams = p(PeripheryBusKey)
|
||||
val pbusBeatBytes = pbusParams.beatBytes
|
||||
|
||||
val pbus = LazyModule(new PeripheryBus(pbusParams))
|
||||
|
||||
// The peripheryBus hangs off of systemBus; here we convert TL-UH -> TL-UL
|
||||
pbus.fromSystemBus :*= sbus.toPeripheryBus()
|
||||
}
|
@ -1,83 +0,0 @@
|
||||
// See LICENSE.SiFive for license details.
|
||||
|
||||
package freechips.rocketchip.coreplex
|
||||
|
||||
import Chisel._
|
||||
import freechips.rocketchip.config.{Field, Parameters}
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.tilelink._
|
||||
import freechips.rocketchip.util._
|
||||
|
||||
case class SystemBusParams(
|
||||
beatBytes: Int,
|
||||
blockBytes: Int,
|
||||
masterBuffering: BufferParams = BufferParams.default,
|
||||
slaveBuffering: BufferParams = BufferParams.default
|
||||
) extends TLBusParams
|
||||
|
||||
case object SystemBusKey extends Field[SystemBusParams]
|
||||
|
||||
class SystemBus(params: SystemBusParams)(implicit p: Parameters) extends TLBusWrapper(params, "SystemBus") {
|
||||
|
||||
private val master_splitter = LazyModule(new TLSplitter) // Allows cycle-free connection to external networks
|
||||
master_splitter.suggestName(s"${busName}_master_TLSplitter")
|
||||
inwardNode :=* master_splitter.node
|
||||
def busView = master_splitter.node.edges.in.head
|
||||
|
||||
protected def inwardSplitNode: TLInwardNode = master_splitter.node
|
||||
protected def outwardSplitNode: TLOutwardNode = master_splitter.node
|
||||
|
||||
|
||||
private val port_fixer = LazyModule(new TLFIFOFixer(TLFIFOFixer.all))
|
||||
port_fixer.suggestName(s"${busName}_port_TLFIFOFixer")
|
||||
master_splitter.node :=* port_fixer.node
|
||||
|
||||
private val pbus_fixer = LazyModule(new TLFIFOFixer(TLFIFOFixer.all))
|
||||
pbus_fixer.suggestName(s"${busName}_pbus_TLFIFOFixer")
|
||||
pbus_fixer.node :*= outwardWWNode
|
||||
|
||||
def toSplitSlaves: TLOutwardNode = outwardSplitNode
|
||||
|
||||
def toPeripheryBus(addBuffers: Int = 0): TLOutwardNode = {
|
||||
TLBuffer.chain(addBuffers).foldRight(pbus_fixer.node:TLOutwardNode)(_ :*= _)
|
||||
}
|
||||
|
||||
val toMemoryBus: TLOutwardNode = outwardNode
|
||||
|
||||
val toSlave: TLOutwardNode = outwardBufNode
|
||||
|
||||
def fromCoherentChip: TLInwardNode = inwardNode
|
||||
|
||||
def fromFrontBus: TLInwardNode = master_splitter.node
|
||||
|
||||
def fromTile(name: Option[String])(gen: Parameters => TLOutwardNode) {
|
||||
this {
|
||||
LazyScope(s"${busName}FromTile${name.getOrElse("")}") {
|
||||
master_splitter.node :=* gen(p)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def fromSyncPorts(params: BufferParams = BufferParams.default, name: Option[String] = None): TLInwardNode = {
|
||||
val buffer = LazyModule(new TLBuffer(params))
|
||||
name.foreach { n => buffer.suggestName(s"${busName}_${n}_TLBuffer") }
|
||||
port_fixer.node :=* buffer.node
|
||||
buffer.node
|
||||
}
|
||||
|
||||
def fromSyncFIFOMaster(params: BufferParams = BufferParams.default, name: Option[String] = None): TLInwardNode = {
|
||||
fromSyncPorts(params, name)
|
||||
}
|
||||
}
|
||||
|
||||
/** Provides buses that serve as attachment points,
|
||||
* for use in traits that connect individual devices or external ports.
|
||||
*/
|
||||
trait HasSystemBus extends HasInterruptBus {
|
||||
private val sbusParams = p(SystemBusKey)
|
||||
val sbusBeatBytes = sbusParams.beatBytes
|
||||
|
||||
val sbus = LazyModule(new SystemBus(sbusParams))
|
||||
|
||||
def sharedMemoryTLEdge: TLEdge = sbus.busView
|
||||
}
|
@ -5,7 +5,7 @@ package freechips.rocketchip.devices.debug
|
||||
import Chisel._
|
||||
import chisel3.core.{IntParam, Input, Output}
|
||||
import freechips.rocketchip.config.{Field, Parameters}
|
||||
import freechips.rocketchip.coreplex.HasPeripheryBus
|
||||
import freechips.rocketchip.subsystem._
|
||||
import freechips.rocketchip.devices.tilelink._
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.jtag._
|
||||
@ -26,12 +26,9 @@ class DebugIO(implicit val p: Parameters) extends ParameterizedBundle()(p) with
|
||||
/** Either adds a JTAG DTM to system, and exports a JTAG interface,
|
||||
* or exports the Debug Module Interface (DMI), based on a global parameter.
|
||||
*/
|
||||
trait HasPeripheryDebug extends HasPeripheryBus {
|
||||
val module: HasPeripheryDebugModuleImp
|
||||
|
||||
trait HasPeripheryDebug { this: BaseSubsystem =>
|
||||
val debug = LazyModule(new TLDebugModule(pbus.beatBytes))
|
||||
|
||||
debug.node := pbus.toVariableWidthSlaves
|
||||
pbus.toVariableWidthSlave(Some("debug")){ debug.node }
|
||||
}
|
||||
|
||||
trait HasPeripheryDebugBundle {
|
||||
|
@ -4,7 +4,7 @@ package freechips.rocketchip.devices.tilelink
|
||||
|
||||
import Chisel._
|
||||
import freechips.rocketchip.config.{Field, Parameters}
|
||||
import freechips.rocketchip.coreplex._
|
||||
import freechips.rocketchip.subsystem.{BaseSubsystem, HasResetVectorWire}
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.tilelink._
|
||||
import freechips.rocketchip.util._
|
||||
@ -58,8 +58,8 @@ class TLROM(val base: BigInt, val size: Int, contentsDelayed: => Seq[Byte], exec
|
||||
}
|
||||
}
|
||||
|
||||
/** Adds a boot ROM that contains the DTB describing the system's coreplex. */
|
||||
trait HasPeripheryBootROM extends HasPeripheryBus {
|
||||
/** Adds a boot ROM that contains the DTB describing the system's subsystem. */
|
||||
trait HasPeripheryBootROM { this: BaseSubsystem =>
|
||||
val dtb: DTB
|
||||
private val params = p(BootROMParams)
|
||||
private lazy val contents = {
|
||||
@ -71,10 +71,10 @@ trait HasPeripheryBootROM extends HasPeripheryBus {
|
||||
|
||||
val bootrom = LazyModule(new TLROM(params.address, params.size, contents, true, pbus.beatBytes))
|
||||
|
||||
bootrom.node := pbus.toVariableWidthSlaves
|
||||
pbus.toVariableWidthSlave(Some("bootrom")){ bootrom.node }
|
||||
}
|
||||
|
||||
/** Coreplex will power-on running at 0x10040 (BootROM) */
|
||||
/** Subsystem will power-on running at 0x10040 (BootROM) */
|
||||
trait HasPeripheryBootROMModuleImp extends LazyModuleImp
|
||||
with HasResetVectorWire {
|
||||
val outer: HasPeripheryBootROM
|
||||
|
@ -4,7 +4,6 @@ package freechips.rocketchip.devices.tilelink
|
||||
|
||||
import Chisel._
|
||||
import freechips.rocketchip.config.{Field, Parameters}
|
||||
import freechips.rocketchip.coreplex.HasPeripheryBus
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.tilelink._
|
||||
import freechips.rocketchip.util._
|
||||
|
@ -4,7 +4,7 @@ package freechips.rocketchip.devices.tilelink
|
||||
|
||||
import Chisel._
|
||||
import freechips.rocketchip.config.{Field, Parameters}
|
||||
import freechips.rocketchip.coreplex.HasPeripheryBus
|
||||
import freechips.rocketchip.subsystem.BaseSubsystem
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.regmapper._
|
||||
import freechips.rocketchip.tilelink._
|
||||
@ -12,7 +12,7 @@ import freechips.rocketchip.interrupts._
|
||||
import freechips.rocketchip.util._
|
||||
import scala.math.{min,max}
|
||||
|
||||
object ClintConsts
|
||||
object CLINTConsts
|
||||
{
|
||||
def msipOffset(hart: Int) = hart * msipBytes
|
||||
def timecmpOffset(hart: Int) = 0x4000 + hart * timecmpBytes
|
||||
@ -25,16 +25,16 @@ object ClintConsts
|
||||
def ints = 2
|
||||
}
|
||||
|
||||
case class ClintParams(baseAddress: BigInt = 0x02000000, intStages: Int = 0)
|
||||
case class CLINTParams(baseAddress: BigInt = 0x02000000, intStages: Int = 0)
|
||||
{
|
||||
def address = AddressSet(baseAddress, ClintConsts.size-1)
|
||||
def address = AddressSet(baseAddress, CLINTConsts.size-1)
|
||||
}
|
||||
|
||||
case object ClintKey extends Field(ClintParams())
|
||||
case object CLINTKey extends Field(CLINTParams())
|
||||
|
||||
class CoreplexLocalInterrupter(params: ClintParams, beatBytes: Int)(implicit p: Parameters) extends LazyModule
|
||||
class CLINT(params: CLINTParams, beatBytes: Int)(implicit p: Parameters) extends LazyModule
|
||||
{
|
||||
import ClintConsts._
|
||||
import CLINTConsts._
|
||||
|
||||
// clint0 => at most 4095 devices
|
||||
val device = new SimpleDevice("clint", Seq("riscv,clint0")) {
|
||||
@ -90,8 +90,8 @@ class CoreplexLocalInterrupter(params: ClintParams, beatBytes: Int)(implicit p:
|
||||
}
|
||||
}
|
||||
|
||||
/** Trait that will connect a Clint to a coreplex */
|
||||
trait HasPeripheryClint extends HasPeripheryBus {
|
||||
val clint = LazyModule(new CoreplexLocalInterrupter(p(ClintKey), pbus.beatBytes))
|
||||
clint.node := pbus.toVariableWidthSlaves
|
||||
/** Trait that will connect a CLINT to a subsystem */
|
||||
trait HasPeripheryCLINT { this: BaseSubsystem =>
|
||||
val clint = LazyModule(new CLINT(p(CLINTKey), pbus.beatBytes))
|
||||
pbus.toVariableWidthSlave(Some("clint")) { clint.node }
|
||||
}
|
@ -4,7 +4,7 @@ package freechips.rocketchip.devices.tilelink
|
||||
|
||||
import Chisel._
|
||||
import freechips.rocketchip.config.{Field, Parameters}
|
||||
import freechips.rocketchip.coreplex.HasSystemBus
|
||||
import freechips.rocketchip.subsystem.BaseSubsystem
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.tilelink._
|
||||
import freechips.rocketchip.util._
|
||||
@ -118,9 +118,8 @@ class DeadlockDevice(params: ErrorParams, beatBytes: Int = 4)(implicit p: Parame
|
||||
}
|
||||
}
|
||||
|
||||
trait HasSystemErrorSlave extends HasSystemBus {
|
||||
trait HasSystemErrorSlave { this: BaseSubsystem =>
|
||||
private val params = p(ErrorParams)
|
||||
val error = LazyModule(new TLError(params, sbus.beatBytes))
|
||||
|
||||
error.node := sbus.toSlave
|
||||
sbus.toSlave(Some("Error")){ error.node }
|
||||
}
|
||||
|
@ -3,9 +3,9 @@
|
||||
package freechips.rocketchip.devices.tilelink
|
||||
|
||||
import Chisel._
|
||||
import freechips.rocketchip.coreplex.{HasPeripheryBus}
|
||||
import freechips.rocketchip.config.{Field, Parameters}
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.subsystem.BaseSubsystem
|
||||
import freechips.rocketchip.tilelink._
|
||||
import freechips.rocketchip.util._
|
||||
|
||||
@ -13,11 +13,11 @@ case class MaskROMParams(address: BigInt, name: String, depth: Int = 2048, width
|
||||
|
||||
case object PeripheryMaskROMKey extends Field[Seq[MaskROMParams]]
|
||||
|
||||
trait HasPeripheryMaskROMSlave extends HasPeripheryBus {
|
||||
trait HasPeripheryMaskROMSlave { this: BaseSubsystem =>
|
||||
val maskROMParams = p(PeripheryMaskROMKey)
|
||||
val maskROMs = maskROMParams map { params =>
|
||||
val maskROM = LazyModule(new TLMaskROM(params))
|
||||
maskROM.node := pbus.toFixedWidthSingleBeatSlave(maskROM.beatBytes)
|
||||
pbus.toFixedWidthSingleBeatSlave(maskROM.beatBytes, Some("MaskROM")) { maskROM.node }
|
||||
maskROM
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ package freechips.rocketchip.devices.tilelink
|
||||
import Chisel._
|
||||
import Chisel.ImplicitConversions._
|
||||
import freechips.rocketchip.config.{Field, Parameters}
|
||||
import freechips.rocketchip.coreplex.{HasInterruptBus, HasPeripheryBus}
|
||||
import freechips.rocketchip.subsystem.BaseSubsystem
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.regmapper._
|
||||
import freechips.rocketchip.tilelink._
|
||||
@ -268,9 +268,9 @@ class TLPLIC(params: PLICParams, beatBytes: Int)(implicit p: Parameters) extends
|
||||
}
|
||||
}
|
||||
|
||||
/** Trait that will connect a PLIC to a coreplex */
|
||||
trait HasPeripheryPLIC extends HasInterruptBus with HasPeripheryBus {
|
||||
/** Trait that will connect a PLIC to a subsystem */
|
||||
trait HasPeripheryPLIC { this: BaseSubsystem =>
|
||||
val plic = LazyModule(new TLPLIC(p(PLICKey), pbus.beatBytes))
|
||||
plic.node := pbus.toVariableWidthSlaves
|
||||
pbus.toVariableWidthSlave(Some("plic")) { plic.node }
|
||||
plic.intnode := ibus.toPLIC
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ package freechips.rocketchip.devices.tilelink
|
||||
|
||||
import Chisel._
|
||||
import freechips.rocketchip.config.{Field, Parameters}
|
||||
import freechips.rocketchip.coreplex.HasMemoryBus
|
||||
import freechips.rocketchip.subsystem.BaseSubsystem
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.tilelink._
|
||||
|
||||
@ -46,17 +46,17 @@ case class ZeroParams(base: Long, size: Long, beatBytes: Int)
|
||||
case object ZeroParams extends Field[ZeroParams]
|
||||
|
||||
/** Adds a /dev/null slave that generates zero-filled responses to reads */
|
||||
trait HasMemoryZeroSlave extends HasMemoryBus {
|
||||
trait HasMemoryZeroSlave { this: BaseSubsystem =>
|
||||
private val params = p(ZeroParams)
|
||||
private val device = new SimpleDevice("rom", Seq("ucbbar,cacheable-zero0"))
|
||||
|
||||
val zeros = memBuses.map(_.toVariableWidthSlave).zipWithIndex.map { case (node, channel) =>
|
||||
val zeros = memBuses.zipWithIndex.map { case (bus, channel) =>
|
||||
val channels = memBuses.size
|
||||
val base = AddressSet(params.base, params.size-1)
|
||||
val filter = AddressSet(channel * cacheBlockBytes, ~((channels-1) * cacheBlockBytes))
|
||||
val filter = AddressSet(channel * bus.blockBytes, ~((channels-1) * bus.blockBytes))
|
||||
val address = base.intersect(filter).get
|
||||
val zero = LazyModule(new TLZero(address, beatBytes = params.beatBytes, resources = device.reg("mem")))
|
||||
zero.node := node
|
||||
bus.toVariableWidthSlave(Some("Zero")) { zero.node }
|
||||
zero
|
||||
}
|
||||
}
|
||||
|
@ -25,50 +25,30 @@ abstract class LazyModule()(implicit val p: Parameters)
|
||||
parent.foreach(p => p.children = this :: p.children)
|
||||
|
||||
// suggestedName accumulates Some(names), taking the final one. Nones are ignored.
|
||||
private var suggestedName: Option[String] = None
|
||||
private var suggestedNameVar: Option[String] = None
|
||||
def suggestName(x: String): this.type = suggestName(Some(x))
|
||||
def suggestName(x: Option[String]): this.type = {
|
||||
x.foreach { n => suggestedName = Some(n) }
|
||||
x.foreach { n => suggestedNameVar = Some(n) }
|
||||
this
|
||||
}
|
||||
|
||||
private lazy val childNames =
|
||||
getClass.getMethods.filter { m =>
|
||||
m.getParameterTypes.isEmpty &&
|
||||
!java.lang.reflect.Modifier.isStatic(m.getModifiers) &&
|
||||
m.getName != "children" &&
|
||||
m.getName != "getChildren"
|
||||
}.flatMap { m =>
|
||||
if (classOf[LazyModule].isAssignableFrom(m.getReturnType)) {
|
||||
val obj = m.invoke(this)
|
||||
if (obj eq null) Seq() else Seq((m.getName, obj))
|
||||
} else if (classOf[Seq[LazyModule]].isAssignableFrom(m.getReturnType)) {
|
||||
val obj = m.invoke(this)
|
||||
if (obj eq null) Seq() else {
|
||||
val seq = try { obj.asInstanceOf[Seq[Object]] } catch { case _: Throwable => null }
|
||||
if (seq eq null) Seq() else {
|
||||
seq.zipWithIndex.map { case (l, i) => (m.getName + "_" + i, l) }
|
||||
}
|
||||
}
|
||||
} else Seq()
|
||||
}
|
||||
private def findValName =
|
||||
parent.flatMap(_.childNames.find(_._2 eq this)).map(_._1)
|
||||
|
||||
private def findClassName(c: Class[_]): String = {
|
||||
val n = c.getName.split('.').last
|
||||
if (n.contains('$')) findClassName(c.getSuperclass) else n
|
||||
}
|
||||
|
||||
lazy val className = findClassName(getClass)
|
||||
lazy val valName = suggestedName.orElse(findValName)
|
||||
lazy val outerName = if (nodes.size != 1) None else nodes(0).gco.flatMap(_.lazyModule.valName)
|
||||
lazy val suggestedName = suggestedNameVar.getOrElse(className)
|
||||
lazy val desiredName = className // + hashcode?
|
||||
|
||||
def moduleName = className + valName.orElse(outerName).map("_" + _).getOrElse("")
|
||||
def instanceName = valName.getOrElse(outerName.map(_ + "_").getOrElse("") + className)
|
||||
def name = valName.getOrElse(className)
|
||||
def name = suggestedName // className + suggestedName ++ hashcode ?
|
||||
def line = sourceLine(info)
|
||||
|
||||
// Accessing these names can only be done after circuit elaboration!
|
||||
lazy val moduleName = module.name // The final Verilog Module name
|
||||
lazy val pathName = module.pathName
|
||||
lazy val instanceName = pathName.split('.').last // The final Verilog instance name
|
||||
|
||||
def instantiate() { } // a hook for running things in module scope (after children exist, but before dangles+auto exists)
|
||||
def module: LazyModuleImpLike
|
||||
|
||||
@ -79,7 +59,7 @@ abstract class LazyModule()(implicit val p: Parameters)
|
||||
buf ++= "<graphml xmlns=\"http://graphml.graphdrawing.org/xmlns\" xmlns:y=\"http://www.yworks.com/xml/graphml\">\n"
|
||||
buf ++= " <key for=\"node\" id=\"n\" yfiles.type=\"nodegraphics\"/>\n"
|
||||
buf ++= " <key for=\"edge\" id=\"e\" yfiles.type=\"edgegraphics\"/>\n"
|
||||
buf ++= " <key for=\"node\" id=\"d\" attr.name=\"NodeDebugString\" attr.type=\"string\"/>\n"
|
||||
buf ++= " <key for=\"node\" id=\"d\" attr.name=\"Description\" attr.type=\"string\"/>\n"
|
||||
buf ++= " <graph id=\"G\" edgedefault=\"directed\">\n"
|
||||
nodesGraphML(buf, " ")
|
||||
edgesGraphML(buf, " ")
|
||||
@ -92,11 +72,13 @@ abstract class LazyModule()(implicit val p: Parameters)
|
||||
|
||||
private def nodesGraphML(buf: StringBuilder, pad: String) {
|
||||
buf ++= s"""${pad}<node id=\"${index}\">\n"""
|
||||
buf ++= s"""${pad} <data key=\"n\"><y:ShapeNode><y:NodeLabel modelName=\"sides\" modelPosition=\"w\" rotationAngle=\"270.0\">${module.instanceName}</y:NodeLabel></y:ShapeNode></data>\n"""
|
||||
buf ++= s"""${pad} <data key=\"n\"><y:ShapeNode><y:NodeLabel modelName=\"sides\" modelPosition=\"w\" rotationAngle=\"270.0\">${instanceName}</y:NodeLabel></y:ShapeNode></data>\n"""
|
||||
buf ++= s"""${pad} <data key=\"d\">${moduleName} (${pathName})</data>\n"""
|
||||
buf ++= s"""${pad} <graph id=\"${index}::\" edgedefault=\"directed\">\n"""
|
||||
nodes.filter(!_.omitGraphML).foreach { n =>
|
||||
buf ++= s"""${pad} <node id=\"${index}::${n.index}\">\n"""
|
||||
buf ++= s"""${pad} <data key=\"d\"><y:ShapeNode><y:Shape type="ellipse"/></y:ShapeNode>${n.nodedebugstring}</data>\n"""
|
||||
buf ++= s"""${pad} <data key=\"e\"><y:ShapeNode><y:Shape type="Ellipse"/></y:ShapeNode></data>\n"""
|
||||
buf ++= s"""${pad} <data key=\"d\">${n.nodedebugstring}</data>\n"""
|
||||
buf ++= s"""${pad} </node>\n"""
|
||||
}
|
||||
children.filter(!_.omitGraphML).foreach { _.nodesGraphML(buf, pad + " ") }
|
||||
@ -149,6 +131,7 @@ object LazyModule
|
||||
require (scope.get eq bc, s"LazyModule() applied to ${bc.name} before ${scope.get.name} ${sourceLine(sourceInfo)}")
|
||||
scope = bc.parent
|
||||
bc.info = sourceInfo
|
||||
if (!bc.suggestedNameVar.isDefined) bc.suggestName(valName.name)
|
||||
bc
|
||||
}
|
||||
}
|
||||
@ -162,8 +145,8 @@ sealed trait LazyModuleImpLike extends BaseModule
|
||||
// .module had better not be accessed while LazyModules are still being built!
|
||||
require (!LazyModule.scope.isDefined, s"${wrapper.name}.module was constructed before LazyModule() was run on ${LazyModule.scope.get.name}")
|
||||
|
||||
override def desiredName = wrapper.moduleName
|
||||
suggestName(wrapper.instanceName)
|
||||
override def desiredName = wrapper.desiredName
|
||||
suggestName(wrapper.suggestedName)
|
||||
|
||||
implicit val p = wrapper.p
|
||||
|
||||
@ -186,7 +169,7 @@ sealed trait LazyModuleImpLike extends BaseModule
|
||||
val auto = IO(new AutoBundle(forward.map { d => (d.name, d.data, d.flipped) }:_*))
|
||||
val dangles = (forward zip auto.elements) map { case (d, (_, io)) =>
|
||||
if (d.flipped) { d.data <> io } else { io <> d.data }
|
||||
d.copy(data = io, name = wrapper.valName.getOrElse("anon") + "_" + d.name)
|
||||
d.copy(data = io, name = wrapper.suggestedName + "_" + d.name)
|
||||
}
|
||||
wrapper.instantiate()
|
||||
(auto, dangles)
|
||||
|
@ -32,7 +32,6 @@ trait InwardNodeImp[DI, UI, EI, BI <: Data]
|
||||
|
||||
// optional methods to track node graph
|
||||
def mixI(pu: UI, node: InwardNode[DI, UI, BI]): UI = pu // insert node into parameters
|
||||
def getO(pu: UI): Option[BaseNode] = None // most-outward common node
|
||||
}
|
||||
|
||||
// DO = Downwards flowing Parameters generated by the outer side of the node
|
||||
@ -91,8 +90,6 @@ abstract class BaseNode(implicit val valName: ValName)
|
||||
if (name.isEmpty) "" else name + "_"
|
||||
}
|
||||
|
||||
protected[diplomacy] def gci: Option[BaseNode] // greatest common inner
|
||||
protected[diplomacy] def gco: Option[BaseNode] // greatest common outer
|
||||
def inputs: Seq[(BaseNode, RenderedEdge)]
|
||||
def outputs: Seq[(BaseNode, RenderedEdge)]
|
||||
|
||||
@ -322,9 +319,6 @@ sealed abstract class MixedNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data](
|
||||
}
|
||||
}
|
||||
|
||||
protected[diplomacy] def gco = if (uiParams.size != 1) None else inner.getO(uiParams(0))
|
||||
protected[diplomacy] def gci = if (doParams.size != 1) None else outer.getI(doParams(0))
|
||||
|
||||
protected[diplomacy] lazy val edgesOut = (oPorts zip doParams).map { case ((i, n, p, s), o) => outer.edgeO(o, n.uiParams(i), p, s) }
|
||||
protected[diplomacy] lazy val edgesIn = (iPorts zip uiParams).map { case ((o, n, p, s), i) => inner.edgeI(n.doParams(o), i, p, s) }
|
||||
|
||||
|
@ -211,7 +211,7 @@ case class Resource(owner: Device, key: String)
|
||||
}
|
||||
}
|
||||
|
||||
/** The resource binding scope for a LazyModule that generates a device tree (currently Coreplex only). */
|
||||
/** The resource binding scope for a LazyModule that generates a device tree (currently Subsystem only). */
|
||||
trait BindingScope
|
||||
{
|
||||
this: LazyModule =>
|
||||
|
@ -5,13 +5,13 @@ package freechips.rocketchip.groundtest
|
||||
|
||||
import Chisel._
|
||||
import freechips.rocketchip.config.Config
|
||||
import freechips.rocketchip.coreplex._
|
||||
import freechips.rocketchip.subsystem._
|
||||
import freechips.rocketchip.rocket.{DCacheParams}
|
||||
import freechips.rocketchip.tile.{MaxHartIdBits, XLen}
|
||||
|
||||
/** Actual testing target Configs */
|
||||
|
||||
class TraceGenConfig extends Config(new WithTraceGen(List.fill(2){ DCacheParams(nSets = 16, nWays = 1) }) ++ new BaseCoreplexConfig)
|
||||
class TraceGenConfig extends Config(new WithTraceGen(List.fill(2){ DCacheParams(nSets = 16, nWays = 1) }) ++ new BaseSubsystemConfig)
|
||||
|
||||
class TraceGenBufferlessConfig extends Config(new WithBufferlessBroadcastHub ++ new TraceGenConfig)
|
||||
|
||||
|
@ -7,7 +7,7 @@ import Chisel._
|
||||
import freechips.rocketchip.config.{Field, Parameters}
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.interrupts._
|
||||
import freechips.rocketchip.coreplex._
|
||||
import freechips.rocketchip.subsystem._
|
||||
import freechips.rocketchip.tilelink._
|
||||
import freechips.rocketchip.tile._
|
||||
|
||||
@ -15,10 +15,9 @@ import scala.math.max
|
||||
|
||||
case object TileId extends Field[Int]
|
||||
|
||||
class GroundTestCoreplex(implicit p: Parameters) extends BaseCoreplex
|
||||
class GroundTestSubsystem(implicit p: Parameters) extends BaseSubsystem
|
||||
with HasMasterAXI4MemPort
|
||||
with HasPeripheryTestRAMSlave
|
||||
with HasInterruptBus {
|
||||
with HasPeripheryTestRAMSlave {
|
||||
val tileParams = p(GroundTestTilesKey)
|
||||
val tiles = tileParams.zipWithIndex.map { case(c, i) => LazyModule(
|
||||
c.build(i, p.alterPartial {
|
||||
@ -28,19 +27,16 @@ class GroundTestCoreplex(implicit p: Parameters) extends BaseCoreplex
|
||||
)}
|
||||
|
||||
tiles.flatMap(_.dcacheOpt).foreach { dc =>
|
||||
sbus.fromTile(None) { implicit p => TileMasterPortParams(addBuffers = 1).adapt(this)(dc.node) }
|
||||
sbus.fromTile(None, buffers = 1){ dc.node }
|
||||
}
|
||||
|
||||
// No PLIC in ground test; so just sink the interrupts to nowhere
|
||||
IntSinkNode(IntSinkPortSimple()) := ibus.toPLIC
|
||||
|
||||
val pbusRAM = LazyModule(new TLRAM(AddressSet(testRamAddr, 0xffff), true, false, pbus.beatBytes))
|
||||
pbusRAM.node := pbus.toVariableWidthSlaves
|
||||
|
||||
override lazy val module = new GroundTestCoreplexModule(this)
|
||||
override lazy val module = new GroundTestSubsystemModuleImp(this)
|
||||
}
|
||||
|
||||
class GroundTestCoreplexModule[+L <: GroundTestCoreplex](_outer: L) extends BaseCoreplexModule(_outer)
|
||||
class GroundTestSubsystemModuleImp[+L <: GroundTestSubsystem](_outer: L) extends BaseSubsystemModuleImp(_outer)
|
||||
with HasMasterAXI4MemPortModuleImp {
|
||||
val success = IO(Bool(OUTPUT))
|
||||
|
||||
@ -51,13 +47,13 @@ class GroundTestCoreplexModule[+L <: GroundTestCoreplex](_outer: L) extends Base
|
||||
}
|
||||
|
||||
/** Adds a SRAM to the system for testing purposes. */
|
||||
trait HasPeripheryTestRAMSlave extends HasPeripheryBus {
|
||||
trait HasPeripheryTestRAMSlave { this: BaseSubsystem =>
|
||||
val testram = LazyModule(new TLRAM(AddressSet(0x52000000, 0xfff), true, true, pbus.beatBytes))
|
||||
testram.node := pbus.toVariableWidthSlaves
|
||||
pbus.toVariableWidthSlave(Some("TestRAM")) { testram.node }
|
||||
}
|
||||
|
||||
/** Adds a fuzzing master to the system for testing purposes. */
|
||||
trait HasPeripheryTestFuzzMaster extends HasPeripheryBus {
|
||||
trait HasPeripheryTestFuzzMaster { this: BaseSubsystem =>
|
||||
val fuzzer = LazyModule(new TLFuzzer(5000))
|
||||
pbus.bufferFromMasters := fuzzer.node
|
||||
pbus.fromOtherMaster(Some("Fuzzer")) { fuzzer.node }
|
||||
}
|
@ -9,7 +9,7 @@ import freechips.rocketchip.diplomacy.LazyModule
|
||||
|
||||
class TestHarness(implicit p: Parameters) extends Module {
|
||||
val io = new Bundle { val success = Bool(OUTPUT) }
|
||||
val dut = Module(LazyModule(new GroundTestCoreplex).module)
|
||||
val dut = Module(LazyModule(new GroundTestSubsystem).module)
|
||||
io.success := dut.success
|
||||
dut.connectSimAXIMem()
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ package freechips.rocketchip.groundtest
|
||||
import Chisel._
|
||||
import freechips.rocketchip.config._
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.coreplex._
|
||||
import freechips.rocketchip.subsystem._
|
||||
import freechips.rocketchip.interrupts._
|
||||
import freechips.rocketchip.rocket.{DCache, RocketCoreParams}
|
||||
import freechips.rocketchip.tile._
|
||||
|
@ -6,7 +6,7 @@ package freechips.rocketchip.rocket
|
||||
import Chisel._
|
||||
import Chisel.ImplicitConversions._
|
||||
import freechips.rocketchip.config.Parameters
|
||||
import freechips.rocketchip.coreplex.CacheBlockBytes
|
||||
import freechips.rocketchip.subsystem.CacheBlockBytes
|
||||
import freechips.rocketchip.tile.HasCoreParameters
|
||||
import freechips.rocketchip.util._
|
||||
|
||||
|
@ -5,7 +5,7 @@ package freechips.rocketchip.rocket
|
||||
import Chisel._
|
||||
import Chisel.ImplicitConversions._
|
||||
import freechips.rocketchip.config.Parameters
|
||||
import freechips.rocketchip.coreplex.{RocketTilesKey}
|
||||
import freechips.rocketchip.subsystem.{RocketTilesKey}
|
||||
import freechips.rocketchip.diplomacy.{AddressSet, RegionType}
|
||||
import freechips.rocketchip.tilelink._
|
||||
import freechips.rocketchip.util._
|
||||
|
@ -7,7 +7,7 @@ import Chisel._
|
||||
import Chisel.ImplicitConversions._
|
||||
import chisel3.core.withReset
|
||||
import freechips.rocketchip.config._
|
||||
import freechips.rocketchip.coreplex._
|
||||
import freechips.rocketchip.subsystem._
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.tilelink._
|
||||
import freechips.rocketchip.tile._
|
||||
|
@ -6,7 +6,7 @@ package freechips.rocketchip.rocket
|
||||
import Chisel._
|
||||
import chisel3.experimental.dontTouch
|
||||
import freechips.rocketchip.config.{Parameters, Field}
|
||||
import freechips.rocketchip.coreplex._
|
||||
import freechips.rocketchip.subsystem._
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.tile._
|
||||
import freechips.rocketchip.tilelink._
|
||||
|
@ -6,7 +6,7 @@ package freechips.rocketchip.rocket
|
||||
import Chisel._
|
||||
import Chisel.ImplicitConversions._
|
||||
import freechips.rocketchip.config.Parameters
|
||||
import freechips.rocketchip.coreplex.RocketTilesKey
|
||||
import freechips.rocketchip.subsystem.RocketTilesKey
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.tile._
|
||||
import freechips.rocketchip.tilelink._
|
||||
|
@ -6,7 +6,7 @@ package freechips.rocketchip.rocket
|
||||
import Chisel._
|
||||
import Chisel.ImplicitConversions._
|
||||
import freechips.rocketchip.config.Parameters
|
||||
import freechips.rocketchip.coreplex.CacheBlockBytes
|
||||
import freechips.rocketchip.subsystem.CacheBlockBytes
|
||||
import freechips.rocketchip.tile._
|
||||
import freechips.rocketchip.tilelink._
|
||||
import freechips.rocketchip.util._
|
||||
|
@ -7,7 +7,7 @@ import Chisel._
|
||||
import Chisel.ImplicitConversions._
|
||||
|
||||
import freechips.rocketchip.config.{Field, Parameters}
|
||||
import freechips.rocketchip.coreplex.CacheBlockBytes
|
||||
import freechips.rocketchip.subsystem.CacheBlockBytes
|
||||
import freechips.rocketchip.diplomacy.RegionType
|
||||
import freechips.rocketchip.tile.{XLen, CoreModule, CoreBundle}
|
||||
import freechips.rocketchip.tilelink._
|
||||
|
@ -1,6 +1,6 @@
|
||||
// See LICENSE.SiFive for license details.
|
||||
|
||||
package freechips.rocketchip.coreplex
|
||||
package freechips.rocketchip.subsystem
|
||||
|
||||
import Chisel._
|
||||
import freechips.rocketchip.config.Parameters
|
||||
@ -9,14 +9,14 @@ import freechips.rocketchip.tilelink._
|
||||
import freechips.rocketchip.devices.tilelink._
|
||||
import freechips.rocketchip.util._
|
||||
|
||||
/** BareCoreplex is the root class for creating a coreplex sub-system */
|
||||
abstract class BareCoreplex(implicit p: Parameters) extends LazyModule with BindingScope {
|
||||
/** BareSubsystem is the root class for creating a subsystem */
|
||||
abstract class BareSubsystem(implicit p: Parameters) extends LazyModule with BindingScope {
|
||||
lazy val dts = DTS(bindingTree)
|
||||
lazy val dtb = DTB(dts)
|
||||
lazy val json = JSON(bindingTree)
|
||||
}
|
||||
|
||||
abstract class BareCoreplexModule[+L <: BareCoreplex](_outer: L) extends LazyModuleImp(_outer) {
|
||||
abstract class BareSubsystemModuleImp[+L <: BareSubsystem](_outer: L) extends LazyModuleImp(_outer) {
|
||||
val outer = _outer
|
||||
ElaborationArtefacts.add("graphml", outer.graphML)
|
||||
ElaborationArtefacts.add("dts", outer.dts)
|
||||
@ -25,16 +25,54 @@ abstract class BareCoreplexModule[+L <: BareCoreplex](_outer: L) extends LazyMod
|
||||
println(outer.dts)
|
||||
}
|
||||
|
||||
/** Base Coreplex class with no peripheral devices or ports added */
|
||||
abstract class BaseCoreplex(implicit p: Parameters) extends BareCoreplex
|
||||
with HasInterruptBus
|
||||
with HasSystemBus
|
||||
with HasPeripheryBus
|
||||
with HasMemoryBus {
|
||||
override val module: BaseCoreplexModule[BaseCoreplex]
|
||||
/** Base Subsystem class with no peripheral devices or ports added */
|
||||
abstract class BaseSubsystem(implicit p: Parameters) extends BareSubsystem {
|
||||
override val module: BaseSubsystemModuleImp[BaseSubsystem]
|
||||
|
||||
// These are wrappers around the standard buses available in all subsytems, where
|
||||
// peripherals, tiles, ports, and other masters and slaves can attach themselves.
|
||||
val ibus = new InterruptBusWrapper()
|
||||
val sbus = LazyModule(new SystemBus(p(SystemBusKey)))
|
||||
val pbus = LazyModule(new PeripheryBus(p(PeripheryBusKey)))
|
||||
val fbus = LazyModule(new FrontBus(p(FrontBusKey)))
|
||||
|
||||
// The sbus masters the pbus; here we convert TL-UH -> TL-UL
|
||||
pbus.fromSystemBus { sbus.toPeripheryBus { pbus.crossTLIn } }
|
||||
|
||||
// The fbus masters the sbus; both are TL-UH or TL-C
|
||||
FlipRendering { implicit p =>
|
||||
fbus.toSystemBus { sbus.fromFrontBus { fbus.crossTLOut } }
|
||||
}
|
||||
|
||||
// The sbus masters the mbus; here we convert TL-C -> TL-UH
|
||||
private val mbusParams = p(MemoryBusKey)
|
||||
private val l2Params = p(BankedL2Key)
|
||||
val MemoryBusParams(memBusBeatBytes, memBusBlockBytes) = mbusParams
|
||||
val BankedL2Params(nMemoryChannels, nBanksPerChannel, coherenceManager) = l2Params
|
||||
val nBanks = l2Params.nBanks
|
||||
val cacheBlockBytes = memBusBlockBytes
|
||||
// TODO: the below call to coherenceManager should be wrapped in a LazyScope here,
|
||||
// but plumbing halt is too annoying for now.
|
||||
private val (in, out, halt) = coherenceManager(this)
|
||||
def memBusCanCauseHalt: () => Option[Bool] = halt
|
||||
|
||||
require (isPow2(nMemoryChannels) || nMemoryChannels == 0)
|
||||
require (isPow2(nBanksPerChannel))
|
||||
require (isPow2(memBusBlockBytes))
|
||||
|
||||
private val mask = ~BigInt((nBanks-1) * memBusBlockBytes)
|
||||
val memBuses = Seq.tabulate(nMemoryChannels) { channel =>
|
||||
val mbus = LazyModule(new MemoryBus(mbusParams)(p))
|
||||
for (bank <- 0 until nBanksPerChannel) {
|
||||
val offset = (bank * nMemoryChannels) + channel
|
||||
ForceFanout(a = true) { implicit p => sbus.toMemoryBus { in } }
|
||||
mbus.fromCoherenceManager(None) { TLFilter(TLFilter.Mmask(AddressSet(offset * memBusBlockBytes, mask))) } := out
|
||||
}
|
||||
mbus
|
||||
}
|
||||
|
||||
// Make topManagers an Option[] so as to avoid LM name reflection evaluating it...
|
||||
lazy val topManagers = Some(ManagerUnification(sharedMemoryTLEdge.manager.managers))
|
||||
lazy val topManagers = Some(ManagerUnification(sbus.busView.manager.managers))
|
||||
ResourceBinding {
|
||||
val managers = topManagers.get
|
||||
val max = managers.flatMap(_.address).map(_.max).max
|
||||
@ -59,9 +97,9 @@ abstract class BaseCoreplex(implicit p: Parameters) extends BareCoreplex
|
||||
}
|
||||
}
|
||||
|
||||
abstract class BaseCoreplexModule[+L <: BaseCoreplex](_outer: L) extends BareCoreplexModule(_outer) {
|
||||
abstract class BaseSubsystemModuleImp[+L <: BaseSubsystem](_outer: L) extends BareSubsystemModuleImp(_outer) {
|
||||
println("Generated Address Map")
|
||||
private val aw = (outer.sharedMemoryTLEdge.bundle.addressBits-1)/4 + 1
|
||||
private val aw = (outer.sbus.busView.bundle.addressBits-1)/4 + 1
|
||||
private val fmt = s"\t%${aw}x - %${aw}x %c%c%c%c%c %s"
|
||||
|
||||
private def collect(path: List[String], value: ResourceValue): List[(String, ResourceAddress)] = {
|
@ -1,7 +1,7 @@
|
||||
// See LICENSE.SiFive for license details.
|
||||
// See LICENSE.Berkeley for license details.
|
||||
|
||||
package freechips.rocketchip.coreplex
|
||||
package freechips.rocketchip.subsystem
|
||||
|
||||
import Chisel._
|
||||
import freechips.rocketchip.config._
|
||||
@ -13,7 +13,7 @@ import freechips.rocketchip.tile._
|
||||
import freechips.rocketchip.tilelink._
|
||||
import freechips.rocketchip.util._
|
||||
|
||||
class BaseCoreplexConfig extends Config ((site, here, up) => {
|
||||
class BaseSubsystemConfig extends Config ((site, here, up) => {
|
||||
// Tile parameters
|
||||
case PgLevels => if (site(XLen) == 64) 3 /* Sv39 */ else 2 /* Sv32 */
|
||||
case XLen => 64 // Applies to all cores
|
||||
@ -23,6 +23,7 @@ class BaseCoreplexConfig extends Config ((site, here, up) => {
|
||||
case SystemBusKey => SystemBusParams(beatBytes = site(XLen)/8, blockBytes = site(CacheBlockBytes))
|
||||
case PeripheryBusKey => PeripheryBusParams(beatBytes = site(XLen)/8, blockBytes = site(CacheBlockBytes))
|
||||
case MemoryBusKey => MemoryBusParams(beatBytes = site(XLen)/8, blockBytes = site(CacheBlockBytes))
|
||||
case FrontBusKey => FrontBusParams(beatBytes = site(XLen)/8, blockBytes = site(CacheBlockBytes))
|
||||
// Additional device Parameters
|
||||
case ErrorParams => ErrorParams(Seq(AddressSet(0x3000, 0xfff)), maxAtomic=site(XLen)/8, maxTransfer=4096)
|
||||
case BootROMParams => BootROMParams(contentFileName = "./bootrom/bootrom.img")
|
||||
@ -155,8 +156,8 @@ class WithIncoherentTiles extends Config((site, here, up) => {
|
||||
case RocketCrossingKey => up(RocketCrossingKey, site) map { r =>
|
||||
r.copy(master = r.master.copy(cork = Some(true)))
|
||||
}
|
||||
case BankedL2Key => up(BankedL2Key, site).copy(coherenceManager = { coreplex =>
|
||||
val ww = LazyModule(new TLWidthWidget(coreplex.sbusBeatBytes)(coreplex.p))
|
||||
case BankedL2Key => up(BankedL2Key, site).copy(coherenceManager = { subsystem =>
|
||||
val ww = LazyModule(new TLWidthWidget(subsystem.sbus.beatBytes)(subsystem.p))
|
||||
(ww.node, ww.node, () => None)
|
||||
})
|
||||
})
|
||||
@ -270,10 +271,6 @@ class WithJtagDTM extends Config ((site, here, up) => {
|
||||
case IncludeJtagDTM => true
|
||||
})
|
||||
|
||||
class WithNoPeripheryArithAMO extends Config ((site, here, up) => {
|
||||
case PeripheryBusKey => up(PeripheryBusKey, site).copy(arithmetic = false)
|
||||
})
|
||||
|
||||
class WithNBitPeripheryBus(nBits: Int) extends Config ((site, here, up) => {
|
||||
case PeripheryBusKey => up(PeripheryBusKey, site).copy(beatBytes = nBits/8)
|
||||
})
|
@ -1,6 +1,6 @@
|
||||
// See LICENSE.SiFive for license details.
|
||||
|
||||
package freechips.rocketchip.coreplex
|
||||
package freechips.rocketchip.subsystem
|
||||
|
||||
import Chisel._
|
||||
import freechips.rocketchip.config._
|
||||
@ -11,16 +11,16 @@ import freechips.rocketchip.interrupts._
|
||||
import freechips.rocketchip.util._
|
||||
|
||||
/** Enumerates the three types of clock crossing between tiles and system bus */
|
||||
sealed trait CoreplexClockCrossing
|
||||
sealed trait SubsystemClockCrossing
|
||||
{
|
||||
def sameClock = this match {
|
||||
case _: SynchronousCrossing => true
|
||||
case _ => false
|
||||
}
|
||||
}
|
||||
case class SynchronousCrossing(params: BufferParams = BufferParams.default) extends CoreplexClockCrossing
|
||||
case class RationalCrossing(direction: RationalDirection = FastToSlow) extends CoreplexClockCrossing
|
||||
case class AsynchronousCrossing(depth: Int, sync: Int = 3) extends CoreplexClockCrossing
|
||||
case class SynchronousCrossing(params: BufferParams = BufferParams.default) extends SubsystemClockCrossing
|
||||
case class RationalCrossing(direction: RationalDirection = FastToSlow) extends SubsystemClockCrossing
|
||||
case class AsynchronousCrossing(depth: Int, sync: Int = 3) extends SubsystemClockCrossing
|
||||
|
||||
private case class CrossingCheck(out: Boolean, source: BaseNode, sink: BaseNode)
|
||||
|
||||
@ -45,26 +45,26 @@ trait HasCrossingMethods extends LazyModule with LazyScope
|
||||
// TileLink
|
||||
|
||||
def crossTLSyncInOut(out: Boolean)(params: BufferParams = BufferParams.default)(implicit p: Parameters): TLNode = {
|
||||
val node = this { LazyModule(new TLBuffer(params)).node }
|
||||
checks = CrossingCheck(out, node, node) :: checks
|
||||
node
|
||||
val sync_xing = this { LazyModule(new TLBuffer(params)).node }
|
||||
checks = CrossingCheck(out, sync_xing, sync_xing) :: checks
|
||||
sync_xing
|
||||
}
|
||||
|
||||
def crossTLAsyncInOut(out: Boolean)(depth: Int = 8, sync: Int = 3)(implicit p: Parameters): TLNode = {
|
||||
lazy val asource = LazyModule(new TLAsyncCrossingSource(sync))
|
||||
lazy val asink = LazyModule(new TLAsyncCrossingSink(depth, sync))
|
||||
val source = if (out) this { asource } else asource
|
||||
val sink = if (out) asink else this { asink }
|
||||
lazy val async_xing_source = LazyModule(new TLAsyncCrossingSource(sync))
|
||||
lazy val async_xing_sink = LazyModule(new TLAsyncCrossingSink(depth, sync))
|
||||
val source = if (out) this { async_xing_source } else async_xing_source
|
||||
val sink = if (out) async_xing_sink else this { async_xing_sink }
|
||||
sink.node :*=* source.node
|
||||
checks = CrossingCheck(out, source.node, sink.node) :: checks
|
||||
NodeHandle(source.node, sink.node)
|
||||
}
|
||||
|
||||
def crossTLRationalInOut(out: Boolean)(direction: RationalDirection)(implicit p: Parameters): TLNode = {
|
||||
lazy val rsource = LazyModule(new TLRationalCrossingSource)
|
||||
lazy val rsink = LazyModule(new TLRationalCrossingSink(if (out) direction else direction.flip))
|
||||
val source = if (out) this { rsource } else rsource
|
||||
val sink = if (out) rsink else this { rsink }
|
||||
lazy val rational_xing_source = LazyModule(new TLRationalCrossingSource)
|
||||
lazy val rational_xing_sink = LazyModule(new TLRationalCrossingSink(if (out) direction else direction.flip))
|
||||
val source = if (out) this { rational_xing_source } else rational_xing_source
|
||||
val sink = if (out) rational_xing_sink else this { rational_xing_sink }
|
||||
sink.node :*=* source.node
|
||||
checks = CrossingCheck(out, source.node, sink.node) :: checks
|
||||
NodeHandle(source.node, sink.node)
|
||||
@ -77,13 +77,13 @@ trait HasCrossingMethods extends LazyModule with LazyScope
|
||||
def crossTLRationalIn (direction: RationalDirection)(implicit p: Parameters): TLNode = crossTLRationalInOut(false)(direction)
|
||||
def crossTLRationalOut(direction: RationalDirection)(implicit p: Parameters): TLNode = crossTLRationalInOut(true )(direction)
|
||||
|
||||
def crossTLIn(arg: CoreplexClockCrossing)(implicit p: Parameters): TLNode = arg match {
|
||||
def crossTLIn(arg: SubsystemClockCrossing)(implicit p: Parameters): TLNode = arg match {
|
||||
case x: SynchronousCrossing => crossTLSyncIn(x.params)
|
||||
case x: AsynchronousCrossing => crossTLAsyncIn(x.depth, x.sync)
|
||||
case x: RationalCrossing => crossTLRationalIn(x.direction)
|
||||
}
|
||||
|
||||
def crossTLOut(arg: CoreplexClockCrossing)(implicit p: Parameters): TLNode = arg match {
|
||||
def crossTLOut(arg: SubsystemClockCrossing)(implicit p: Parameters): TLNode = arg match {
|
||||
case x: SynchronousCrossing => crossTLSyncOut(x.params)
|
||||
case x: AsynchronousCrossing => crossTLAsyncOut(x.depth, x.sync)
|
||||
case x: RationalCrossing => crossTLRationalOut(x.direction)
|
||||
@ -92,16 +92,16 @@ trait HasCrossingMethods extends LazyModule with LazyScope
|
||||
// AXI4
|
||||
|
||||
def crossAXI4SyncInOut(out: Boolean)(params: BufferParams = BufferParams.default)(implicit p: Parameters): AXI4Node = {
|
||||
val node = this { LazyModule(new AXI4Buffer(params)).node }
|
||||
checks = CrossingCheck(out, node, node) :: checks
|
||||
node
|
||||
val axi4_sync_xing = this { LazyModule(new AXI4Buffer(params)).node }
|
||||
checks = CrossingCheck(out, axi4_sync_xing, axi4_sync_xing) :: checks
|
||||
axi4_sync_xing
|
||||
}
|
||||
|
||||
def crossAXI4AsyncInOut(out: Boolean)(depth: Int = 8, sync: Int = 3)(implicit p: Parameters): AXI4Node = {
|
||||
lazy val axi4asource = LazyModule(new AXI4AsyncCrossingSource(sync))
|
||||
lazy val axi4asink = LazyModule(new AXI4AsyncCrossingSink(depth, sync))
|
||||
val source = if (out) this { axi4asource } else axi4asource
|
||||
val sink = if (out) axi4asink else this { axi4asink }
|
||||
lazy val axi4_async_xing_source = LazyModule(new AXI4AsyncCrossingSource(sync))
|
||||
lazy val axi4_async_xing_sink = LazyModule(new AXI4AsyncCrossingSink(depth, sync))
|
||||
val source = if (out) this { axi4_async_xing_source } else axi4_async_xing_source
|
||||
val sink = if (out) axi4_async_xing_sink else this { axi4_async_xing_sink }
|
||||
sink.node :*=* source.node
|
||||
checks = CrossingCheck(out, source.node, sink.node) :: checks
|
||||
NodeHandle(source.node, sink.node)
|
||||
@ -112,13 +112,13 @@ trait HasCrossingMethods extends LazyModule with LazyScope
|
||||
def crossAXI4AsyncIn (depth: Int = 8, sync: Int = 3)(implicit p: Parameters): AXI4Node = crossAXI4AsyncInOut(false)(depth, sync)
|
||||
def crossAXI4AsyncOut(depth: Int = 8, sync: Int = 3)(implicit p: Parameters): AXI4Node = crossAXI4AsyncInOut(true )(depth, sync)
|
||||
|
||||
def crossAXI4In(arg: CoreplexClockCrossing)(implicit p: Parameters): AXI4Node = arg match {
|
||||
def crossAXI4In(arg: SubsystemClockCrossing)(implicit p: Parameters): AXI4Node = arg match {
|
||||
case x: SynchronousCrossing => crossAXI4SyncIn(x.params)
|
||||
case x: AsynchronousCrossing => crossAXI4AsyncIn(x.depth, x.sync)
|
||||
case x: RationalCrossing => throw new IllegalArgumentException("AXI4 Rational crossing unimplemented")
|
||||
}
|
||||
|
||||
def crossAXI4Out(arg: CoreplexClockCrossing)(implicit p: Parameters): AXI4Node = arg match {
|
||||
def crossAXI4Out(arg: SubsystemClockCrossing)(implicit p: Parameters): AXI4Node = arg match {
|
||||
case x: SynchronousCrossing => crossAXI4SyncOut(x.params)
|
||||
case x: AsynchronousCrossing => crossAXI4AsyncOut(x.depth, x.sync)
|
||||
case x: RationalCrossing => throw new IllegalArgumentException("AXI4 Rational crossing unimplemented")
|
||||
@ -127,30 +127,30 @@ trait HasCrossingMethods extends LazyModule with LazyScope
|
||||
// Interrupts
|
||||
|
||||
def crossIntSyncInOut(out: Boolean)(alreadyRegistered: Boolean = false)(implicit p: Parameters): IntNode = {
|
||||
lazy val intssource = LazyModule(new IntSyncCrossingSource(alreadyRegistered))
|
||||
lazy val intssink = LazyModule(new IntSyncCrossingSink(0))
|
||||
val source = if (out) this { intssource } else intssource
|
||||
val sink = if (out) intssink else this { intssink }
|
||||
lazy val int_sync_xing_source = LazyModule(new IntSyncCrossingSource(alreadyRegistered))
|
||||
lazy val int_sync_xing_sink = LazyModule(new IntSyncCrossingSink(0))
|
||||
val source = if (out) this { int_sync_xing_source } else int_sync_xing_source
|
||||
val sink = if (out) int_sync_xing_sink else this { int_sync_xing_sink }
|
||||
sink.node :*=* source.node
|
||||
checks = CrossingCheck(out, source.node, sink.node) :: checks
|
||||
NodeHandle(source.node, sink.node)
|
||||
}
|
||||
|
||||
def crossIntAsyncInOut(out: Boolean)(sync: Int = 3, alreadyRegistered: Boolean = false)(implicit p: Parameters): IntNode = {
|
||||
lazy val intasource = LazyModule(new IntSyncCrossingSource(alreadyRegistered))
|
||||
lazy val intasink = LazyModule(new IntSyncCrossingSink(sync))
|
||||
val source = if (out) this { intasource } else intasource
|
||||
val sink = if (out) intasink else this { intasink }
|
||||
lazy val int_async_xing_source = LazyModule(new IntSyncCrossingSource(alreadyRegistered))
|
||||
lazy val int_async_xing_sink = LazyModule(new IntSyncCrossingSink(sync))
|
||||
val source = if (out) this { int_async_xing_source } else int_async_xing_source
|
||||
val sink = if (out) int_async_xing_sink else this { int_async_xing_sink }
|
||||
sink.node :*=* source.node
|
||||
checks = CrossingCheck(out, source.node, sink.node) :: checks
|
||||
NodeHandle(source.node, sink.node)
|
||||
}
|
||||
|
||||
def crossIntRationalInOut(out: Boolean)(alreadyRegistered: Boolean = false)(implicit p: Parameters): IntNode = {
|
||||
lazy val intrsource = LazyModule(new IntSyncCrossingSource(alreadyRegistered))
|
||||
lazy val intrsink = LazyModule(new IntSyncCrossingSink(1))
|
||||
val source = if (out) this { intrsource } else intrsource
|
||||
val sink = if (out) intrsink else this { intrsink }
|
||||
lazy val int_rational_xing_source = LazyModule(new IntSyncCrossingSource(alreadyRegistered))
|
||||
lazy val int_rational_xing_sink = LazyModule(new IntSyncCrossingSink(1))
|
||||
val source = if (out) this { int_rational_xing_source } else int_rational_xing_source
|
||||
val sink = if (out) int_rational_xing_sink else this { int_rational_xing_sink }
|
||||
sink.node :*=* source.node
|
||||
checks = CrossingCheck(out, source.node, sink.node) :: checks
|
||||
NodeHandle(source.node, sink.node)
|
||||
@ -163,26 +163,26 @@ trait HasCrossingMethods extends LazyModule with LazyScope
|
||||
def crossIntRationalIn (alreadyRegistered: Boolean = false)(implicit p: Parameters): IntNode = crossIntRationalInOut(false)(alreadyRegistered)
|
||||
def crossIntRationalOut(alreadyRegistered: Boolean = false)(implicit p: Parameters): IntNode = crossIntRationalInOut(true )(alreadyRegistered)
|
||||
|
||||
def crossIntIn(arg: CoreplexClockCrossing, alreadyRegistered: Boolean)(implicit p: Parameters): IntNode = arg match {
|
||||
def crossIntIn(arg: SubsystemClockCrossing, alreadyRegistered: Boolean)(implicit p: Parameters): IntNode = arg match {
|
||||
case x: SynchronousCrossing => crossIntSyncIn(alreadyRegistered)
|
||||
case x: AsynchronousCrossing => crossIntAsyncIn(x.sync, alreadyRegistered)
|
||||
case x: RationalCrossing => crossIntRationalIn(alreadyRegistered)
|
||||
}
|
||||
|
||||
def crossIntOut(arg: CoreplexClockCrossing, alreadyRegistered: Boolean)(implicit p: Parameters): IntNode = arg match {
|
||||
def crossIntOut(arg: SubsystemClockCrossing, alreadyRegistered: Boolean)(implicit p: Parameters): IntNode = arg match {
|
||||
case x: SynchronousCrossing => crossIntSyncOut(alreadyRegistered)
|
||||
case x: AsynchronousCrossing => crossIntAsyncOut(x.sync, alreadyRegistered)
|
||||
case x: RationalCrossing => crossIntRationalOut(alreadyRegistered)
|
||||
}
|
||||
|
||||
def crossIntIn (arg: CoreplexClockCrossing)(implicit p: Parameters): IntNode = crossIntIn (arg, false)
|
||||
def crossIntOut(arg: CoreplexClockCrossing)(implicit p: Parameters): IntNode = crossIntOut(arg, false)
|
||||
def crossIntIn (arg: SubsystemClockCrossing)(implicit p: Parameters): IntNode = crossIntIn (arg, false)
|
||||
def crossIntOut(arg: SubsystemClockCrossing)(implicit p: Parameters): IntNode = crossIntOut(arg, false)
|
||||
}
|
||||
|
||||
trait HasCrossing extends HasCrossingMethods
|
||||
{
|
||||
this: LazyModule =>
|
||||
val crossing: CoreplexClockCrossing
|
||||
val crossing: SubsystemClockCrossing
|
||||
|
||||
def crossTLIn (implicit p: Parameters): TLNode = crossTLIn (crossing)
|
||||
def crossTLOut (implicit p: Parameters): TLNode = crossTLOut (crossing)
|
||||
@ -195,4 +195,4 @@ trait HasCrossing extends HasCrossingMethods
|
||||
def crossIntOut(alreadyRegistered: Boolean)(implicit p: Parameters): IntNode = crossIntOut(crossing, alreadyRegistered)
|
||||
}
|
||||
|
||||
class CrossingWrapper(val crossing: CoreplexClockCrossing)(implicit p: Parameters) extends SimpleLazyModule with HasCrossing
|
||||
class CrossingWrapper(val crossing: SubsystemClockCrossing)(implicit p: Parameters) extends SimpleLazyModule with HasCrossing
|
50
src/main/scala/subsystem/FrontBus.scala
Normal file
50
src/main/scala/subsystem/FrontBus.scala
Normal file
@ -0,0 +1,50 @@
|
||||
// See LICENSE.SiFive for license details.
|
||||
|
||||
package freechips.rocketchip.subsystem
|
||||
|
||||
import Chisel._
|
||||
import freechips.rocketchip.config.{Field, Parameters}
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.tilelink._
|
||||
import freechips.rocketchip.util._
|
||||
|
||||
case class FrontBusParams(
|
||||
beatBytes: Int,
|
||||
blockBytes: Int,
|
||||
sbusCrossing: SubsystemClockCrossing = SynchronousCrossing(),
|
||||
sbusBuffer: BufferParams = BufferParams.default) extends HasTLBusParams
|
||||
|
||||
case object FrontBusKey extends Field[FrontBusParams]
|
||||
|
||||
class FrontBus(params: FrontBusParams)
|
||||
(implicit p: Parameters) extends TLBusWrapper(params, "front_bus")
|
||||
with HasTLXbarPhy
|
||||
with HasCrossing {
|
||||
val crossing = params.sbusCrossing
|
||||
|
||||
def fromPort[D,U,E,B <: Data]
|
||||
(name: Option[String] = None, buffers: Int = 1)
|
||||
(gen: => NodeHandle[D,U,E,B,TLClientPortParameters,TLManagerPortParameters,TLEdgeOut,TLBundle] =
|
||||
TLIdentity.gen): InwardNodeHandle[D,U,E,B] = {
|
||||
from("port" named name) { fixFrom(TLFIFOFixer.all, buffers) :=* gen }
|
||||
}
|
||||
|
||||
def fromMasterNode(name: Option[String] = None, buffers: Int = 1)(gen: TLOutwardNode) {
|
||||
from("master" named name) { fixFrom(TLFIFOFixer.all, buffers) :=* gen }
|
||||
}
|
||||
|
||||
def fromMaster[D,U,E,B <: Data]
|
||||
(name: Option[String] = None, buffers: Int = 1)
|
||||
(gen: => NodeHandle[D,U,E,B,TLClientPortParameters,TLManagerPortParameters,TLEdgeOut,TLBundle] =
|
||||
TLIdentity.gen): InwardNodeHandle[D,U,E,B] = {
|
||||
from("master" named name) { fixFrom(TLFIFOFixer.all, buffers) :=* gen }
|
||||
}
|
||||
|
||||
def fromCoherentChip(gen: => TLNode): TLInwardNode = {
|
||||
from("coherent_subsystem") { inwardNode :=* gen }
|
||||
}
|
||||
|
||||
def toSystemBus(gen: => TLInwardNode) {
|
||||
to("sbus") { gen :=* TLBuffer(params.sbusBuffer) :=* outwardNode }
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
// See LICENSE.SiFive for license details.
|
||||
|
||||
package freechips.rocketchip.coreplex
|
||||
package freechips.rocketchip.subsystem
|
||||
|
||||
import Chisel._
|
||||
import chisel3.experimental.dontTouch
|
||||
@ -14,12 +14,14 @@ class ClockedTileInputs(implicit val p: Parameters) extends ParameterizedBundle
|
||||
with HasExternallyDrivenTileConstants
|
||||
with Clocked
|
||||
|
||||
trait HasTiles extends HasSystemBus {
|
||||
trait HasTiles { this: BaseSubsystem =>
|
||||
implicit val p: Parameters
|
||||
val tiles: Seq[BaseTile]
|
||||
protected def tileParams: Seq[TileParams] = tiles.map(_.tileParams)
|
||||
def nTiles: Int = tileParams.size
|
||||
def hartIdList: Seq[Int] = tileParams.map(_.hartId)
|
||||
def localIntCounts: Seq[Int] = tileParams.map(_.core.nLocalInterrupts)
|
||||
def sharedMemoryTLEdge = sbus.busView
|
||||
}
|
||||
|
||||
trait HasTilesBundle {
|
@ -1,6 +1,6 @@
|
||||
// See LICENSE.SiFive for license details.
|
||||
|
||||
package freechips.rocketchip.coreplex
|
||||
package freechips.rocketchip.subsystem
|
||||
|
||||
import Chisel._
|
||||
import freechips.rocketchip.config.{Field, Parameters}
|
||||
@ -24,11 +24,6 @@ class InterruptBusWrapper(implicit p: Parameters) {
|
||||
def toPLIC: IntOutwardNode = int_bus.intnode
|
||||
}
|
||||
|
||||
trait HasInterruptBus {
|
||||
implicit val p: Parameters
|
||||
val ibus = new InterruptBusWrapper
|
||||
}
|
||||
|
||||
/** Specifies the number of external interrupts */
|
||||
case object NExtTopInterrupts extends Field[Int](0)
|
||||
|
||||
@ -36,7 +31,7 @@ case object NExtTopInterrupts extends Field[Int](0)
|
||||
* However, it should not be used directly; instead one of the below
|
||||
* synchronization wiring child traits should be used.
|
||||
*/
|
||||
abstract trait HasExtInterrupts extends HasInterruptBus {
|
||||
abstract trait HasExtInterrupts { this: BaseSubsystem =>
|
||||
private val device = new Device with DeviceInterrupts {
|
||||
def describe(resources: ResourceBindings): Description = {
|
||||
Description("soc/external-interrupts", describeInterrupts(resources))
|
||||
@ -50,7 +45,7 @@ abstract trait HasExtInterrupts extends HasInterruptBus {
|
||||
/** This trait should be used if the External Interrupts have NOT
|
||||
* already been synchronized to the Periphery (PLIC) Clock.
|
||||
*/
|
||||
trait HasAsyncExtInterrupts extends HasExtInterrupts {
|
||||
trait HasAsyncExtInterrupts extends HasExtInterrupts { this: BaseSubsystem =>
|
||||
if (nExtInterrupts > 0) {
|
||||
ibus.fromAsync := extInterrupts
|
||||
}
|
||||
@ -59,7 +54,7 @@ trait HasAsyncExtInterrupts extends HasExtInterrupts {
|
||||
/** This trait can be used if the External Interrupts have already been synchronized
|
||||
* to the Periphery (PLIC) Clock.
|
||||
*/
|
||||
trait HasSyncExtInterrupts extends HasExtInterrupts {
|
||||
trait HasSyncExtInterrupts extends HasExtInterrupts { this: BaseSubsystem =>
|
||||
if (nExtInterrupts > 0) {
|
||||
ibus.fromSync := extInterrupts
|
||||
}
|
77
src/main/scala/subsystem/MemoryBus.scala
Normal file
77
src/main/scala/subsystem/MemoryBus.scala
Normal file
@ -0,0 +1,77 @@
|
||||
// See LICENSE.SiFive for license details.
|
||||
|
||||
package freechips.rocketchip.subsystem
|
||||
|
||||
import Chisel._
|
||||
import freechips.rocketchip.config._
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.tilelink._
|
||||
import freechips.rocketchip.util._
|
||||
|
||||
// TODO: applies to all caches, for now
|
||||
case object CacheBlockBytes extends Field[Int](64)
|
||||
|
||||
/** L2 Broadcast Hub configuration */
|
||||
case class BroadcastParams(
|
||||
nTrackers: Int = 4,
|
||||
bufferless: Boolean = false)
|
||||
|
||||
case object BroadcastKey extends Field(BroadcastParams())
|
||||
|
||||
/** L2 memory subsystem configuration */
|
||||
case class BankedL2Params(
|
||||
nMemoryChannels: Int = 1,
|
||||
nBanksPerChannel: Int = 1,
|
||||
coherenceManager: BaseSubsystem => (TLInwardNode, TLOutwardNode, () => Option[Bool]) = { subsystem =>
|
||||
implicit val p = subsystem.p
|
||||
val BroadcastParams(nTrackers, bufferless) = p(BroadcastKey)
|
||||
val bh = LazyModule(new TLBroadcast(subsystem.memBusBlockBytes, nTrackers, bufferless))
|
||||
val ww = LazyModule(new TLWidthWidget(subsystem.sbus.beatBytes))
|
||||
ww.node :*= bh.node
|
||||
(bh.node, ww.node, () => None)
|
||||
}) {
|
||||
val nBanks = nMemoryChannels*nBanksPerChannel
|
||||
}
|
||||
|
||||
case object BankedL2Key extends Field(BankedL2Params())
|
||||
|
||||
/** Parameterization of the memory-side bus created for each memory channel */
|
||||
case class MemoryBusParams(beatBytes: Int, blockBytes: Int) extends HasTLBusParams
|
||||
|
||||
case object MemoryBusKey extends Field[MemoryBusParams]
|
||||
|
||||
/** Wrapper for creating TL nodes from a bus connected to the back of each mem channel */
|
||||
class MemoryBus(params: MemoryBusParams)(implicit p: Parameters) extends TLBusWrapper(params, "memory_bus")(p)
|
||||
with HasTLXbarPhy {
|
||||
|
||||
def fromCoherenceManager(
|
||||
name: Option[String] = None,
|
||||
buffer: BufferParams = BufferParams.none)
|
||||
(gen: => TLNode): TLInwardNode = {
|
||||
from("coherence_manager" named name) {
|
||||
inwardNode := TLBuffer(buffer) := gen
|
||||
}
|
||||
}
|
||||
|
||||
def toDRAMController[D,U,E,B <: Data]
|
||||
(name: Option[String] = None, buffer: BufferParams = BufferParams.none)
|
||||
(gen: => NodeHandle[ TLClientPortParameters,TLManagerPortParameters,TLEdgeIn,TLBundle, D,U,E,B] =
|
||||
TLIdentity.gen): OutwardNodeHandle[D,U,E,B] = {
|
||||
to("memory_controller" named name) { gen := bufferTo(buffer) }
|
||||
}
|
||||
|
||||
def toVariableWidthSlave[D,U,E,B <: Data]
|
||||
(name: Option[String] = None, buffer: BufferParams = BufferParams.none)
|
||||
(gen: => NodeHandle[TLClientPortParameters,TLManagerPortParameters,TLEdgeIn,TLBundle,D,U,E,B] =
|
||||
TLIdentity.gen): OutwardNodeHandle[D,U,E,B] = {
|
||||
to("slave" named name) { gen :*= fragmentTo(buffer) }
|
||||
}
|
||||
|
||||
def toFixedWidthSlave[D,U,E,B <: Data]
|
||||
(name: Option[String] = None, buffer: BufferParams = BufferParams.none)
|
||||
(gen: => NodeHandle[TLClientPortParameters,TLManagerPortParameters,TLEdgeIn,TLBundle,D,U,E,B] =
|
||||
TLIdentity.gen): OutwardNodeHandle[D,U,E,B] = {
|
||||
to("slave" named name) { gen :*= fixedWidthTo(buffer) }
|
||||
}
|
||||
|
||||
}
|
117
src/main/scala/subsystem/PeripheryBus.scala
Normal file
117
src/main/scala/subsystem/PeripheryBus.scala
Normal file
@ -0,0 +1,117 @@
|
||||
// See LICENSE.SiFive for license details.
|
||||
|
||||
package freechips.rocketchip.subsystem
|
||||
|
||||
import Chisel._
|
||||
import freechips.rocketchip.config.{Field, Parameters}
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.tilelink._
|
||||
import freechips.rocketchip.util._
|
||||
|
||||
case class PeripheryBusParams(
|
||||
beatBytes: Int,
|
||||
blockBytes: Int,
|
||||
arithmeticAtomics: Boolean = true,
|
||||
bufferAtomics: BufferParams = BufferParams.default,
|
||||
sbusCrossingType: SubsystemClockCrossing = SynchronousCrossing(), // relative to sbus
|
||||
frequency: BigInt = BigInt(100000000) // 100 MHz as default bus frequency
|
||||
) extends HasTLBusParams
|
||||
|
||||
case object PeripheryBusKey extends Field[PeripheryBusParams]
|
||||
|
||||
class PeripheryBus(params: PeripheryBusParams)
|
||||
(implicit p: Parameters) extends TLBusWrapper(params, "periphery_bus")
|
||||
with HasTLXbarPhy
|
||||
with HasCrossing {
|
||||
val crossing = params.sbusCrossingType
|
||||
|
||||
def toSlave[D,U,E,B <: Data]
|
||||
(name: Option[String] = None, buffer: BufferParams = BufferParams.none)
|
||||
(gen: => NodeHandle[TLClientPortParameters,TLManagerPortParameters,TLEdgeIn,TLBundle,D,U,E,B] =
|
||||
TLIdentity.gen): OutwardNodeHandle[D,U,E,B] = {
|
||||
to("slave" named name) { gen :*= bufferTo(buffer) }
|
||||
}
|
||||
|
||||
def toVariableWidthSlaveNode(name: Option[String] = None, buffer: BufferParams = BufferParams.none)(node: TLInwardNode) { toVariableWidthSlaveNodeOption(name, buffer)(Some(node)) }
|
||||
|
||||
def toVariableWidthSlaveNodeOption(name: Option[String] = None, buffer: BufferParams = BufferParams.none)(node: Option[TLInwardNode]) {
|
||||
node foreach { n => to("slave" named name) { n :*= fragmentTo(buffer) } }
|
||||
}
|
||||
|
||||
def toVariableWidthSlave[D,U,E,B <: Data]
|
||||
(name: Option[String] = None, buffer: BufferParams = BufferParams.none)
|
||||
(gen: => NodeHandle[TLClientPortParameters,TLManagerPortParameters,TLEdgeIn,TLBundle,D,U,E,B] =
|
||||
TLIdentity.gen): OutwardNodeHandle[D,U,E,B] = {
|
||||
to("slave" named name) { gen :*= fragmentTo(buffer) }
|
||||
}
|
||||
|
||||
def toFixedWidthSlaveNode(name: Option[String] = None, buffer: BufferParams = BufferParams.none)(gen: TLInwardNode) {
|
||||
to("slave" named name) { gen :*= fixedWidthTo(buffer) }
|
||||
}
|
||||
|
||||
def toFixedWidthSlave[D,U,E,B <: Data]
|
||||
(name: Option[String] = None, buffer: BufferParams = BufferParams.none)
|
||||
(gen: => NodeHandle[TLClientPortParameters,TLManagerPortParameters,TLEdgeIn,TLBundle,D,U,E,B] =
|
||||
TLIdentity.gen): OutwardNodeHandle[D,U,E,B] = {
|
||||
to("slave" named name) { gen :*= fixedWidthTo(buffer) }
|
||||
}
|
||||
|
||||
def toFixedWidthSingleBeatSlaveNode
|
||||
(widthBytes: Int, name: Option[String] = None, buffer: BufferParams = BufferParams.none)
|
||||
(gen: TLInwardNode) {
|
||||
to("slave" named name) {
|
||||
gen :*= TLFragmenter(widthBytes, params.blockBytes) :*= fixedWidthTo(buffer)
|
||||
}
|
||||
}
|
||||
|
||||
def toFixedWidthSingleBeatSlave[D,U,E,B <: Data]
|
||||
(widthBytes: Int, name: Option[String] = None, buffer: BufferParams = BufferParams.none)
|
||||
(gen: => NodeHandle[TLClientPortParameters,TLManagerPortParameters,TLEdgeIn,TLBundle,D,U,E,B] =
|
||||
TLIdentity.gen): OutwardNodeHandle[D,U,E,B] = {
|
||||
to("slave" named name) {
|
||||
gen :*= TLFragmenter(widthBytes, params.blockBytes) :*= fixedWidthTo(buffer)
|
||||
}
|
||||
}
|
||||
|
||||
def toLargeBurstSlave[D,U,E,B <: Data]
|
||||
(maxXferBytes: Int, name: Option[String] = None, buffer: BufferParams = BufferParams.none)
|
||||
(gen: => NodeHandle[TLClientPortParameters,TLManagerPortParameters,TLEdgeIn,TLBundle,D,U,E,B] =
|
||||
TLIdentity.gen): OutwardNodeHandle[D,U,E,B] = {
|
||||
to("slave" named name) {
|
||||
gen :*= fragmentTo(params.beatBytes, maxXferBytes, buffer)
|
||||
}
|
||||
}
|
||||
|
||||
def toFixedWidthPort[D,U,E,B <: Data]
|
||||
(name: Option[String] = None, buffer: BufferParams = BufferParams.none)
|
||||
(gen: => NodeHandle[TLClientPortParameters,TLManagerPortParameters,TLEdgeIn,TLBundle,D,U,E,B] =
|
||||
TLIdentity.gen): OutwardNodeHandle[D,U,E,B] = {
|
||||
to("port" named name) { gen := fixedWidthTo(buffer) }
|
||||
}
|
||||
|
||||
|
||||
def fromSystemBus(gen: => TLOutwardNode) {
|
||||
from("sbus") {
|
||||
(inwardNode
|
||||
:*= TLBuffer(params.bufferAtomics)
|
||||
:*= TLAtomicAutomata(arithmetic = params.arithmeticAtomics)
|
||||
:*= gen)
|
||||
}
|
||||
}
|
||||
|
||||
def fromOtherMaster[D,U,E,B <: Data]
|
||||
(name: Option[String] = None, buffer: BufferParams = BufferParams.none)
|
||||
(gen: => NodeHandle[D,U,E,B,TLClientPortParameters,TLManagerPortParameters,TLEdgeOut,TLBundle] =
|
||||
TLIdentity.gen): InwardNodeHandle[D,U,E,B] = {
|
||||
from("master" named name) { bufferFrom(buffer) :=* gen }
|
||||
}
|
||||
|
||||
|
||||
def toTile
|
||||
(name: Option[String] = None, buffers: Int = 0)
|
||||
(gen: => TLNode): TLOutwardNode = {
|
||||
to("tile" named name) { FlipRendering { implicit p =>
|
||||
gen :*= bufferTo(buffers)
|
||||
}}
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
// See LICENSE.SiFive for license details.
|
||||
|
||||
package freechips.rocketchip.coreplex
|
||||
package freechips.rocketchip.subsystem
|
||||
|
||||
import Chisel._
|
||||
import freechips.rocketchip.config.{Field, Parameters}
|
||||
@ -27,11 +27,13 @@ case object ExtIn extends Field[SlavePortParams]
|
||||
///// The following traits add ports to the sytem, in some cases converting to different interconnect standards
|
||||
|
||||
/** Adds a port to the system intended to master an AXI4 DRAM controller. */
|
||||
trait HasMasterAXI4MemPort extends HasMemoryBus {
|
||||
trait HasMasterAXI4MemPort { this: BaseSubsystem =>
|
||||
val module: HasMasterAXI4MemPortModuleImp
|
||||
|
||||
private val params = p(ExtMem)
|
||||
private val portName = "axi4"
|
||||
private val device = new MemoryDevice
|
||||
val nMemoryChannels: Int
|
||||
|
||||
val mem_axi4 = AXI4SlaveNode(Seq.tabulate(nMemoryChannels) { channel =>
|
||||
val base = AddressSet(params.base, params.size-1)
|
||||
@ -49,13 +51,10 @@ trait HasMasterAXI4MemPort extends HasMemoryBus {
|
||||
beatBytes = params.beatBytes)
|
||||
})
|
||||
|
||||
val converter = LazyModule(new TLToAXI4())
|
||||
val trim = LazyModule(new AXI4IdIndexer(params.idBits))
|
||||
val yank = LazyModule(new AXI4UserYanker)
|
||||
val buffer = LazyModule(new AXI4Buffer)
|
||||
|
||||
memBuses.map(_.toDRAMController).foreach { case node =>
|
||||
mem_axi4 := buffer.node := yank.node := trim.node := converter.node := node
|
||||
memBuses.map { m =>
|
||||
mem_axi4 := m.toDRAMController(Some(portName)) {
|
||||
(AXI4UserYanker() := AXI4IdIndexer(params.idBits) := TLToAXI4())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -75,15 +74,17 @@ trait HasMasterAXI4MemPortBundle {
|
||||
/** Actually generates the corresponding IO in the concrete Module */
|
||||
trait HasMasterAXI4MemPortModuleImp extends LazyModuleImp with HasMasterAXI4MemPortBundle {
|
||||
val outer: HasMasterAXI4MemPort
|
||||
|
||||
val mem_axi4 = IO(HeterogeneousBag.fromNode(outer.mem_axi4.in))
|
||||
(mem_axi4 zip outer.mem_axi4.in) foreach { case (i, (o, _)) => i <> o }
|
||||
val nMemoryChannels = outer.nMemoryChannels
|
||||
}
|
||||
|
||||
/** Adds a AXI4 port to the system intended to master an MMIO device bus */
|
||||
trait HasMasterAXI4MMIOPort extends HasSystemBus {
|
||||
trait HasMasterAXI4MMIOPort { this: BaseSubsystem =>
|
||||
private val params = p(ExtBus)
|
||||
private val device = new SimpleBus("mmio", Nil)
|
||||
private val portName = "mmio_port_axi4"
|
||||
private val device = new SimpleBus(portName.kebab, Nil)
|
||||
val mmio_axi4 = AXI4SlaveNode(Seq(AXI4SlavePortParameters(
|
||||
slaves = Seq(AXI4SlaveParameters(
|
||||
address = AddressSet.misaligned(params.base, params.size),
|
||||
@ -93,13 +94,13 @@ trait HasMasterAXI4MMIOPort extends HasSystemBus {
|
||||
supportsRead = TransferSizes(1, params.maxXferBytes))),
|
||||
beatBytes = params.beatBytes)))
|
||||
|
||||
(mmio_axi4
|
||||
:= AXI4Buffer()
|
||||
:= AXI4UserYanker()
|
||||
:= AXI4Deinterleaver(sbus.blockBytes)
|
||||
:= AXI4IdIndexer(params.idBits)
|
||||
:= TLToAXI4()
|
||||
:= sbus.toFixedWidthPorts)
|
||||
mmio_axi4 := sbus.toFixedWidthPort(Some(portName)) {
|
||||
(AXI4Buffer()
|
||||
:= AXI4UserYanker()
|
||||
:= AXI4Deinterleaver(sbus.blockBytes)
|
||||
:= AXI4IdIndexer(params.idBits)
|
||||
:= TLToAXI4())
|
||||
}
|
||||
}
|
||||
|
||||
/** Common io name and methods for propagating or tying off the port bundle */
|
||||
@ -120,21 +121,22 @@ trait HasMasterAXI4MMIOPortModuleImp extends LazyModuleImp with HasMasterAXI4MMI
|
||||
}
|
||||
|
||||
/** Adds an AXI4 port to the system intended to be a slave on an MMIO device bus */
|
||||
trait HasSlaveAXI4Port extends HasSystemBus {
|
||||
trait HasSlaveAXI4Port { this: BaseSubsystem =>
|
||||
private val params = p(ExtIn)
|
||||
private val portName = "slave_port_axi4"
|
||||
val l2FrontendAXI4Node = AXI4MasterNode(Seq(AXI4MasterPortParameters(
|
||||
masters = Seq(AXI4MasterParameters(
|
||||
name = "AXI4 periphery",
|
||||
name = portName.kebab,
|
||||
id = IdRange(0, 1 << params.idBits))))))
|
||||
|
||||
private val fifoBits = 1
|
||||
(sbus.fromSyncPorts()
|
||||
:= TLWidthWidget(params.beatBytes)
|
||||
:= AXI4ToTL()
|
||||
:= AXI4UserYanker(Some(1 << (params.sourceBits - fifoBits - 1)))
|
||||
:= AXI4Fragmenter()
|
||||
:= AXI4IdIndexer(fifoBits)
|
||||
:= l2FrontendAXI4Node)
|
||||
sbus.fromPort(Some(portName)) {
|
||||
(TLWidthWidget(params.beatBytes)
|
||||
:= AXI4ToTL()
|
||||
:= AXI4UserYanker(Some(1 << (params.sourceBits - fifoBits - 1)))
|
||||
:= AXI4Fragmenter()
|
||||
:= AXI4IdIndexer(fifoBits))
|
||||
} := l2FrontendAXI4Node
|
||||
}
|
||||
|
||||
/** Common io name and methods for propagating or tying off the port bundle */
|
||||
@ -160,9 +162,10 @@ trait HasSlaveAXI4PortModuleImp extends LazyModuleImp with HasSlaveAXI4PortBundl
|
||||
}
|
||||
|
||||
/** Adds a TileLink port to the system intended to master an MMIO device bus */
|
||||
trait HasMasterTLMMIOPort extends HasSystemBus {
|
||||
trait HasMasterTLMMIOPort { this: BaseSubsystem =>
|
||||
private val params = p(ExtBus)
|
||||
private val device = new SimpleBus("mmio", Nil)
|
||||
private val portName = "mmio_port_tl"
|
||||
private val device = new SimpleBus(portName.kebab, Nil)
|
||||
val mmio_tl = TLManagerNode(Seq(TLManagerPortParameters(
|
||||
managers = Seq(TLManagerParameters(
|
||||
address = AddressSet.misaligned(params.base, params.size),
|
||||
@ -173,7 +176,9 @@ trait HasMasterTLMMIOPort extends HasSystemBus {
|
||||
supportsPutPartial = TransferSizes(1, sbus.blockBytes))),
|
||||
beatBytes = params.beatBytes)))
|
||||
|
||||
mmio_tl := TLBuffer() := TLSourceShrinker(1 << params.idBits) := sbus.toFixedWidthPorts
|
||||
mmio_tl := sbus.toFixedWidthPort(Some(portName)) {
|
||||
TLBuffer() := TLSourceShrinker(1 << params.idBits)
|
||||
}
|
||||
}
|
||||
|
||||
/** Common io name and methods for propagating or tying off the port bundle */
|
||||
@ -201,14 +206,17 @@ trait HasMasterTLMMIOPortModuleImp extends LazyModuleImp with HasMasterTLMMIOPor
|
||||
/** Adds an TL port to the system intended to be a slave on an MMIO device bus.
|
||||
* NOTE: this port is NOT allowed to issue Acquires.
|
||||
*/
|
||||
trait HasSlaveTLPort extends HasSystemBus {
|
||||
trait HasSlaveTLPort { this: BaseSubsystem =>
|
||||
private val params = p(ExtIn)
|
||||
private val portName = "slave_port_tl"
|
||||
val l2FrontendTLNode = TLClientNode(Seq(TLClientPortParameters(
|
||||
clients = Seq(TLClientParameters(
|
||||
name = "Front Port (TL)",
|
||||
name = portName.kebab,
|
||||
sourceId = IdRange(0, 1 << params.idBits))))))
|
||||
|
||||
sbus.fromSyncPorts() := TLSourceShrinker(1 << params.sourceBits) := TLWidthWidget(params.beatBytes) := l2FrontendTLNode
|
||||
sbus.fromPort(Some(portName)) {
|
||||
TLSourceShrinker(1 << params.sourceBits) := TLWidthWidget(params.beatBytes)
|
||||
} := l2FrontendTLNode
|
||||
}
|
||||
|
||||
/** Common io name and methods for propagating or tying off the port bundle */
|
@ -1,13 +1,13 @@
|
||||
// See LICENSE.SiFive for license details.
|
||||
|
||||
package freechips.rocketchip.coreplex
|
||||
package freechips.rocketchip.subsystem
|
||||
|
||||
import Chisel._
|
||||
import freechips.rocketchip.diplomacy.{LazyModuleImp, DTSTimebase}
|
||||
import freechips.rocketchip.devices.tilelink.HasPeripheryClint
|
||||
import freechips.rocketchip.devices.tilelink.HasPeripheryCLINT
|
||||
|
||||
trait HasRTCModuleImp extends LazyModuleImp {
|
||||
val outer: HasPeripheryClint
|
||||
val outer: BaseSubsystem with HasPeripheryCLINT
|
||||
private val pbusFreq = outer.p(PeripheryBusKey).frequency
|
||||
private val rtcFreq = outer.p(DTSTimebase)
|
||||
private val internalPeriod: BigInt = pbusFreq / rtcFreq
|
@ -1,6 +1,6 @@
|
||||
// See LICENSE.SiFive for license details.
|
||||
|
||||
package freechips.rocketchip.coreplex
|
||||
package freechips.rocketchip.subsystem
|
||||
|
||||
import Chisel._
|
||||
|
@ -1,6 +1,6 @@
|
||||
// See LICENSE.SiFive for license details.
|
||||
|
||||
package freechips.rocketchip.coreplex
|
||||
package freechips.rocketchip.subsystem
|
||||
|
||||
import Chisel._
|
||||
import chisel3.internal.sourceinfo.SourceInfo
|
||||
@ -14,41 +14,11 @@ import freechips.rocketchip.interrupts._
|
||||
import freechips.rocketchip.util._
|
||||
|
||||
// TODO: how specific are these to RocketTiles?
|
||||
case class TileMasterPortParams(
|
||||
addBuffers: Int = 0,
|
||||
cork: Option[Boolean] = None) {
|
||||
|
||||
def adapt(coreplex: HasPeripheryBus)
|
||||
(masterNode: TLOutwardNode)
|
||||
(implicit p: Parameters, sourceInfo: SourceInfo): TLOutwardNode = {
|
||||
val tile_master_cork = cork.map(u => (LazyModule(new TLCacheCork(unsafe = u))))
|
||||
val tile_master_fixer = LazyModule(new TLFIFOFixer(TLFIFOFixer.allUncacheable))
|
||||
|
||||
(Seq(tile_master_fixer.node) ++ TLBuffer.chain(addBuffers) ++ tile_master_cork.map(_.node))
|
||||
.foldRight(masterNode)(_ :=* _)
|
||||
}
|
||||
}
|
||||
|
||||
case class TileSlavePortParams(
|
||||
addBuffers: Int = 0,
|
||||
blockerCtrlAddr: Option[BigInt] = None) {
|
||||
|
||||
def adapt(coreplex: HasPeripheryBus)
|
||||
(slaveNode: TLInwardNode)
|
||||
(implicit p: Parameters, sourceInfo: SourceInfo): TLInwardNode = {
|
||||
val tile_slave_blocker =
|
||||
blockerCtrlAddr
|
||||
.map(BasicBusBlockerParams(_, coreplex.pbus.beatBytes, coreplex.sbus.beatBytes))
|
||||
.map(bp => LazyModule(new BasicBusBlocker(bp)))
|
||||
|
||||
tile_slave_blocker.foreach { _.controlNode := coreplex.pbus.toVariableWidthSlaves }
|
||||
(Seq() ++ tile_slave_blocker.map(_.node) ++ TLBuffer.chain(addBuffers))
|
||||
.foldLeft(slaveNode)(_ :*= _)
|
||||
}
|
||||
}
|
||||
case class TileMasterPortParams(buffers: Int = 0, cork: Option[Boolean] = None)
|
||||
case class TileSlavePortParams(buffers: Int = 0, blockerCtrlAddr: Option[BigInt] = None)
|
||||
|
||||
case class RocketCrossingParams(
|
||||
crossingType: CoreplexClockCrossing = SynchronousCrossing(),
|
||||
crossingType: SubsystemClockCrossing = SynchronousCrossing(),
|
||||
master: TileMasterPortParams = TileMasterPortParams(),
|
||||
slave: TileSlavePortParams = TileSlavePortParams()) {
|
||||
def knownRatio: Option[Int] = crossingType match {
|
||||
@ -61,10 +31,9 @@ case object RocketTilesKey extends Field[Seq[RocketTileParams]](Nil)
|
||||
case object RocketCrossingKey extends Field[Seq[RocketCrossingParams]](List(RocketCrossingParams()))
|
||||
|
||||
trait HasRocketTiles extends HasTiles
|
||||
with HasPeripheryBus
|
||||
with HasPeripheryPLIC
|
||||
with HasPeripheryClint
|
||||
with HasPeripheryDebug {
|
||||
with HasPeripheryCLINT
|
||||
with HasPeripheryDebug { this: BaseSubsystem =>
|
||||
val module: HasRocketTilesModuleImp
|
||||
|
||||
protected val rocketTileParams = p(RocketTilesKey)
|
||||
@ -95,7 +64,7 @@ trait HasRocketTiles extends HasTiles
|
||||
|
||||
def tileMasterBuffering: TLOutwardNode = rocket {
|
||||
// The buffers needed to cut feed-through paths are microarchitecture specific, so belong here
|
||||
val masterBuffer = LazyModule(new TLBuffer(BufferParams.none, BufferParams.flow, BufferParams.none, BufferParams.flow, BufferParams(1)))
|
||||
val masterBufferNode = TLBuffer(BufferParams.none, BufferParams.flow, BufferParams.none, BufferParams.flow, BufferParams(1))
|
||||
crossing.crossingType match {
|
||||
case _: AsynchronousCrossing => rocket.masterNode
|
||||
case SynchronousCrossing(b) =>
|
||||
@ -104,28 +73,41 @@ trait HasRocketTiles extends HasTiles
|
||||
case RationalCrossing(dir) =>
|
||||
require (dir != SlowToFast, "Misconfiguration? Core slower than fabric")
|
||||
if (tp.boundaryBuffers) {
|
||||
masterBuffer.node :=* rocket.masterNode
|
||||
masterBufferNode :=* rocket.masterNode
|
||||
} else {
|
||||
rocket.masterNode
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sbus.fromTile(tp.name) { implicit p => crossing.master.adapt(this)(rocket.crossTLOut :=* tileMasterBuffering) }
|
||||
sbus.fromTile(tp.name, crossing.master.buffers) {
|
||||
crossing.master.cork
|
||||
.map { u => TLCacheCork(unsafe = u) }
|
||||
.map { _ :=* rocket.crossTLOut }
|
||||
.getOrElse { rocket.crossTLOut }
|
||||
} :=* tileMasterBuffering
|
||||
|
||||
// Connect the slave ports of the tile to the periphery bus
|
||||
|
||||
def tileSlaveBuffering: TLInwardNode = rocket {
|
||||
val slaveBuffer = LazyModule(new TLBuffer(BufferParams.flow, BufferParams.none, BufferParams.none, BufferParams.none, BufferParams.none))
|
||||
val slaveBufferNode = TLBuffer(BufferParams.flow, BufferParams.none, BufferParams.none, BufferParams.none, BufferParams.none)
|
||||
crossing.crossingType match {
|
||||
case RationalCrossing(_) if (tp.boundaryBuffers) => rocket.slaveNode :*= slaveBuffer.node
|
||||
case RationalCrossing(_) if (tp.boundaryBuffers) => rocket.slaveNode :*= slaveBufferNode
|
||||
case _ => rocket.slaveNode
|
||||
}
|
||||
}
|
||||
|
||||
pbus.toTile(tp.name) { implicit p => crossing.slave.adapt(this)( DisableMonitors { implicit p =>
|
||||
tileSlaveBuffering :*= rocket.crossTLIn
|
||||
})}
|
||||
DisableMonitors { implicit p =>
|
||||
tileSlaveBuffering :*= pbus.toTile(tp.name) {
|
||||
crossing.slave.blockerCtrlAddr
|
||||
.map { BasicBusBlockerParams(_, pbus.beatBytes, sbus.beatBytes) }
|
||||
.map { bbbp => LazyModule(new BasicBusBlocker(bbbp)) }
|
||||
.map { bbb =>
|
||||
pbus.toVariableWidthSlave(Some("bus_blocker")) { bbb.controlNode }
|
||||
rocket.crossTLIn :*= bbb.node
|
||||
} .getOrElse { rocket.crossTLIn }
|
||||
}
|
||||
}
|
||||
|
||||
// Handle all the different types of interrupts crossing to or from the tile:
|
||||
// 1. Debug interrupt is definitely asynchronous in all cases.
|
||||
@ -163,13 +145,13 @@ trait HasRocketTilesModuleImp extends HasTilesModuleImp
|
||||
val outer: HasRocketTiles
|
||||
}
|
||||
|
||||
class RocketCoreplex(implicit p: Parameters) extends BaseCoreplex
|
||||
class RocketSubsystem(implicit p: Parameters) extends BaseSubsystem
|
||||
with HasRocketTiles {
|
||||
val tiles = rocketTiles
|
||||
override lazy val module = new RocketCoreplexModule(this)
|
||||
override lazy val module = new RocketSubsystemModuleImp(this)
|
||||
}
|
||||
|
||||
class RocketCoreplexModule[+L <: RocketCoreplex](_outer: L) extends BaseCoreplexModule(_outer)
|
||||
class RocketSubsystemModuleImp[+L <: RocketSubsystem](_outer: L) extends BaseSubsystemModuleImp(_outer)
|
||||
with HasRocketTilesModuleImp {
|
||||
tile_inputs.zip(outer.hartIdList).foreach { case(wire, i) =>
|
||||
wire.clock := clock
|
109
src/main/scala/subsystem/SystemBus.scala
Normal file
109
src/main/scala/subsystem/SystemBus.scala
Normal file
@ -0,0 +1,109 @@
|
||||
// See LICENSE.SiFive for license details.
|
||||
|
||||
package freechips.rocketchip.subsystem
|
||||
|
||||
import Chisel._
|
||||
import freechips.rocketchip.config.{Field, Parameters}
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.tilelink._
|
||||
import freechips.rocketchip.util._
|
||||
|
||||
case class SystemBusParams(
|
||||
beatBytes: Int,
|
||||
blockBytes: Int,
|
||||
pbusBuffer: BufferParams = BufferParams.none) extends HasTLBusParams
|
||||
|
||||
case object SystemBusKey extends Field[SystemBusParams]
|
||||
|
||||
class SystemBus(params: SystemBusParams)(implicit p: Parameters) extends TLBusWrapper(params, "system_bus")
|
||||
with HasTLXbarPhy {
|
||||
|
||||
private val master_splitter = LazyModule(new TLSplitter)
|
||||
inwardNode :=* master_splitter.node
|
||||
|
||||
protected def fixFromThenSplit(policy: TLFIFOFixer.Policy, buffers: Int): TLInwardNode =
|
||||
master_splitter.node :=* TLBuffer.chain(buffers).foldLeft(TLFIFOFixer(policy))(_ :=* _)
|
||||
|
||||
def busView = master_splitter.node.edges.in.head
|
||||
|
||||
def toPeripheryBus(gen: => TLNode): TLOutwardNode = {
|
||||
to("pbus") {
|
||||
(gen
|
||||
:= TLFIFOFixer(TLFIFOFixer.all)
|
||||
:= TLWidthWidget(params.beatBytes)
|
||||
:= bufferTo(params.pbusBuffer))
|
||||
}
|
||||
}
|
||||
|
||||
def toMemoryBus(gen: => TLInwardNode) {
|
||||
to("mbus") { gen := delayNode := outwardNode }
|
||||
}
|
||||
|
||||
def toSlave[D,U,E,B <: Data]
|
||||
(name: Option[String] = None, buffer: BufferParams = BufferParams.default)
|
||||
(gen: => NodeHandle[TLClientPortParameters,TLManagerPortParameters,TLEdgeIn,TLBundle,D,U,E,B] =
|
||||
TLIdentity.gen): OutwardNodeHandle[D,U,E,B] = {
|
||||
to("slave" named name) { gen :*= bufferTo(buffer) }
|
||||
}
|
||||
|
||||
def toSplitSlave[D,U,E,B <: Data]
|
||||
(name: Option[String] = None)
|
||||
(gen: => NodeHandle[TLClientPortParameters,TLManagerPortParameters,TLEdgeIn,TLBundle,D,U,E,B] =
|
||||
TLIdentity.gen): OutwardNodeHandle[D,U,E,B] = {
|
||||
to("slave" named name) { gen :=* master_splitter.node }
|
||||
}
|
||||
|
||||
def toFixedWidthSlave[D,U,E,B <: Data]
|
||||
(name: Option[String] = None, buffer: BufferParams = BufferParams.default)
|
||||
(gen: => NodeHandle[TLClientPortParameters,TLManagerPortParameters,TLEdgeIn,TLBundle,D,U,E,B] =
|
||||
TLIdentity.gen): OutwardNodeHandle[D,U,E,B] = {
|
||||
to("slave" named name) { gen :*= fixedWidthTo(buffer) }
|
||||
}
|
||||
|
||||
def toVariableWidthSlave[D,U,E,B <: Data]
|
||||
(name: Option[String] = None, buffer: BufferParams = BufferParams.default)
|
||||
(gen: => NodeHandle[TLClientPortParameters,TLManagerPortParameters,TLEdgeIn,TLBundle,D,U,E,B] =
|
||||
TLIdentity.gen): OutwardNodeHandle[D,U,E,B] = {
|
||||
to("slave" named name) { gen :*= fragmentTo(buffer) }
|
||||
}
|
||||
|
||||
def fromFrontBus(gen: => TLNode): TLInwardNode = {
|
||||
from("front_bus") { master_splitter.node :=* gen }
|
||||
}
|
||||
|
||||
def fromTile
|
||||
(name: Option[String], buffers: Int = 0, cork: Option[Boolean] = None)
|
||||
(gen: => TLNode): TLInwardNode = {
|
||||
from("tile" named name) {
|
||||
fixFromThenSplit(TLFIFOFixer.allUncacheable, buffers) :=* gen
|
||||
}
|
||||
}
|
||||
|
||||
def toFixedWidthPort[D,U,E,B <: Data]
|
||||
(name: Option[String] = None, buffer: BufferParams = BufferParams.default)
|
||||
(gen: => NodeHandle[TLClientPortParameters,TLManagerPortParameters,TLEdgeIn,TLBundle,D,U,E,B] =
|
||||
TLIdentity.gen): OutwardNodeHandle[D,U,E,B] = {
|
||||
to("port" named name) { gen := fixedWidthTo(buffer) }
|
||||
}
|
||||
|
||||
def fromPort[D,U,E,B <: Data]
|
||||
(name: Option[String] = None, buffers: Int = 0)
|
||||
(gen: => NodeHandle[D,U,E,B,TLClientPortParameters,TLManagerPortParameters,TLEdgeOut,TLBundle] =
|
||||
TLIdentity.gen): InwardNodeHandle[D,U,E,B] = {
|
||||
from("port" named name) { fixFromThenSplit(TLFIFOFixer.all, buffers) :=* gen }
|
||||
}
|
||||
|
||||
def fromCoherentMaster[D,U,E,B <: Data]
|
||||
(name: Option[String] = None, buffers: Int = 0)
|
||||
(gen: => NodeHandle[D,U,E,B,TLClientPortParameters,TLManagerPortParameters,TLEdgeOut,TLBundle] =
|
||||
TLIdentity.gen): InwardNodeHandle[D,U,E,B] = {
|
||||
from("coherent_master" named name) { fixFrom(TLFIFOFixer.all, buffers) :=* gen }
|
||||
}
|
||||
|
||||
def fromMaster[D,U,E,B <: Data]
|
||||
(name: Option[String] = None, buffers: Int = 0)
|
||||
(gen: => NodeHandle[D,U,E,B,TLClientPortParameters,TLManagerPortParameters,TLEdgeOut,TLBundle] =
|
||||
TLIdentity.gen): InwardNodeHandle[D,U,E,B] = {
|
||||
from("master" named name) { fixFromThenSplit(TLFIFOFixer.all, buffers) :=* gen }
|
||||
}
|
||||
}
|
@ -5,13 +5,13 @@ package freechips.rocketchip.system
|
||||
|
||||
import Chisel._
|
||||
import freechips.rocketchip.config.Config
|
||||
import freechips.rocketchip.coreplex._
|
||||
import freechips.rocketchip.subsystem._
|
||||
import freechips.rocketchip.devices.debug.{IncludeJtagDTM, JtagDTMKey}
|
||||
import freechips.rocketchip.diplomacy._
|
||||
|
||||
class WithJtagDTMSystem extends freechips.rocketchip.coreplex.WithJtagDTM
|
||||
class WithJtagDTMSystem extends freechips.rocketchip.subsystem.WithJtagDTM
|
||||
|
||||
class BaseConfig extends Config(new BaseCoreplexConfig().alter((site,here,up) => {
|
||||
class BaseConfig extends Config(new BaseSubsystemConfig().alter((site,here,up) => {
|
||||
// DTS descriptive parameters
|
||||
case DTSModel => "freechips,rocketchip-unknown"
|
||||
case DTSCompat => Nil
|
||||
|
@ -4,22 +4,22 @@ package freechips.rocketchip.system
|
||||
|
||||
import Chisel._
|
||||
import freechips.rocketchip.config.Parameters
|
||||
import freechips.rocketchip.coreplex._
|
||||
import freechips.rocketchip.subsystem._
|
||||
import freechips.rocketchip.devices.tilelink._
|
||||
import freechips.rocketchip.util.DontTouch
|
||||
|
||||
/** Example Top with periphery devices and ports, and a Rocket coreplex */
|
||||
class ExampleRocketSystem(implicit p: Parameters) extends RocketCoreplex
|
||||
/** Example Top with periphery devices and ports, and a Rocket subsystem */
|
||||
class ExampleRocketSystem(implicit p: Parameters) extends RocketSubsystem
|
||||
with HasAsyncExtInterrupts
|
||||
with HasMasterAXI4MemPort
|
||||
with HasMasterAXI4MMIOPort
|
||||
with HasSlaveAXI4Port
|
||||
with HasPeripheryBootROM
|
||||
with HasSystemErrorSlave {
|
||||
override lazy val module = new ExampleRocketSystemModule(this)
|
||||
override lazy val module = new ExampleRocketSystemModuleImp(this)
|
||||
}
|
||||
|
||||
class ExampleRocketSystemModule[+L <: ExampleRocketSystem](_outer: L) extends RocketCoreplexModule(_outer)
|
||||
class ExampleRocketSystemModuleImp[+L <: ExampleRocketSystem](_outer: L) extends RocketSubsystemModuleImp(_outer)
|
||||
with HasRTCModuleImp
|
||||
with HasExtInterruptsModuleImp
|
||||
with HasMasterAXI4MemPortModuleImp
|
||||
|
@ -2,13 +2,13 @@
|
||||
|
||||
package freechips.rocketchip.system
|
||||
|
||||
import freechips.rocketchip.coreplex.RocketTilesKey
|
||||
import freechips.rocketchip.subsystem.RocketTilesKey
|
||||
import freechips.rocketchip.tile.XLen
|
||||
import freechips.rocketchip.util.GeneratorApp
|
||||
|
||||
import scala.collection.mutable.LinkedHashSet
|
||||
|
||||
/** A Generator for platforms containing Rocket Coreplexes */
|
||||
/** A Generator for platforms containing Rocket Subsystemes */
|
||||
object Generator extends GeneratorApp {
|
||||
|
||||
val rv64RegrTestNames = LinkedHashSet(
|
||||
@ -50,7 +50,7 @@ object Generator extends GeneratorApp {
|
||||
override def addTestSuites {
|
||||
import DefaultTestSuites._
|
||||
val xlen = params(XLen)
|
||||
// TODO: for now only generate tests for the first core in the first coreplex
|
||||
// TODO: for now only generate tests for the first core in the first subsystem
|
||||
val tileParams = params(RocketTilesKey).head
|
||||
val coreParams = tileParams.core
|
||||
val vm = coreParams.useVM
|
||||
|
@ -5,7 +5,7 @@ package freechips.rocketchip.tile
|
||||
import Chisel._
|
||||
|
||||
import freechips.rocketchip.config._
|
||||
import freechips.rocketchip.coreplex._
|
||||
import freechips.rocketchip.subsystem._
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.interrupts._
|
||||
import freechips.rocketchip.rocket._
|
||||
@ -122,7 +122,7 @@ trait HasTileParameters {
|
||||
}
|
||||
|
||||
/** Base class for all Tiles that use TileLink */
|
||||
abstract class BaseTile(tileParams: TileParams, val crossing: CoreplexClockCrossing)
|
||||
abstract class BaseTile(tileParams: TileParams, val crossing: SubsystemClockCrossing)
|
||||
(implicit p: Parameters) extends LazyModule with HasTileParameters with HasCrossing
|
||||
{
|
||||
def module: BaseTileModuleImp[BaseTile]
|
||||
|
@ -18,7 +18,7 @@ class TileInterrupts(implicit p: Parameters) extends CoreBundle()(p) {
|
||||
val lip = Vec(coreParams.nLocalInterrupts, Bool())
|
||||
}
|
||||
|
||||
// Use diplomatic interrupts to external interrupts from the coreplex into the tile
|
||||
// Use diplomatic interrupts to external interrupts from the subsystem into the tile
|
||||
trait HasExternalInterrupts { this: BaseTile =>
|
||||
|
||||
val intInwardNode = intXbar.intnode
|
||||
@ -50,7 +50,7 @@ trait HasExternalInterrupts { this: BaseTile =>
|
||||
|
||||
// TODO: the order of the following two functions must match, and
|
||||
// also match the order which things are connected to the
|
||||
// per-tile crossbar in coreplex.HasRocketTiles
|
||||
// per-tile crossbar in subsystem.HasRocketTiles
|
||||
|
||||
// debug, msip, mtip, meip, seip, lip offsets in CSRs
|
||||
def csrIntMap: List[Int] = {
|
||||
|
@ -5,7 +5,7 @@ package freechips.rocketchip.tile
|
||||
import Chisel._
|
||||
|
||||
import freechips.rocketchip.config.{Parameters, Field}
|
||||
import freechips.rocketchip.coreplex.CacheBlockBytes
|
||||
import freechips.rocketchip.subsystem.CacheBlockBytes
|
||||
import freechips.rocketchip.tilelink.ClientMetadata
|
||||
import freechips.rocketchip.util._
|
||||
|
||||
|
@ -6,7 +6,7 @@ package freechips.rocketchip.tile
|
||||
import Chisel._
|
||||
|
||||
import freechips.rocketchip.config._
|
||||
import freechips.rocketchip.coreplex._
|
||||
import freechips.rocketchip.subsystem._
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.rocket._
|
||||
import freechips.rocketchip.tilelink._
|
||||
|
@ -5,7 +5,7 @@ package freechips.rocketchip.tile
|
||||
|
||||
import Chisel._
|
||||
import freechips.rocketchip.config._
|
||||
import freechips.rocketchip.coreplex.CoreplexClockCrossing
|
||||
import freechips.rocketchip.subsystem.SubsystemClockCrossing
|
||||
import freechips.rocketchip.devices.tilelink._
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.interrupts._
|
||||
@ -33,7 +33,7 @@ case class RocketTileParams(
|
||||
|
||||
class RocketTile(
|
||||
val rocketParams: RocketTileParams,
|
||||
crossing: CoreplexClockCrossing)
|
||||
crossing: SubsystemClockCrossing)
|
||||
(implicit p: Parameters) extends BaseTile(rocketParams, crossing)(p)
|
||||
with HasExternalInterrupts
|
||||
with HasLazyRoCC // implies CanHaveSharedFPU with CanHavePTW with HasHellaCache
|
||||
|
@ -7,7 +7,7 @@ import freechips.rocketchip.config.Parameters
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.util._
|
||||
import freechips.rocketchip.util.property._
|
||||
import freechips.rocketchip.coreplex.{CrossingWrapper, AsynchronousCrossing}
|
||||
import freechips.rocketchip.subsystem.{CrossingWrapper, AsynchronousCrossing}
|
||||
|
||||
class TLAsyncCrossingSource(sync: Int = 3)(implicit p: Parameters) extends LazyModule
|
||||
{
|
||||
|
@ -1,85 +0,0 @@
|
||||
// See LICENSE.SiFive for license details.
|
||||
|
||||
package freechips.rocketchip.tilelink
|
||||
|
||||
import Chisel._
|
||||
import freechips.rocketchip.config.{Field, Parameters}
|
||||
import freechips.rocketchip.diplomacy._
|
||||
|
||||
case object TLBusDelayProbability extends Field[Double](0.0)
|
||||
|
||||
/** Specifies widths of various attachement points in the SoC */
|
||||
trait TLBusParams {
|
||||
val beatBytes: Int
|
||||
val blockBytes: Int
|
||||
val masterBuffering: BufferParams
|
||||
val slaveBuffering: BufferParams
|
||||
|
||||
def beatBits: Int = beatBytes * 8
|
||||
def blockBits: Int = blockBytes * 8
|
||||
def blockBeats: Int = blockBytes / beatBytes
|
||||
def blockOffset: Int = log2Up(blockBytes)
|
||||
}
|
||||
|
||||
abstract class TLBusWrapper(params: TLBusParams, val busName: String)(implicit p: Parameters)
|
||||
extends SimpleLazyModule with LazyScope with TLBusParams {
|
||||
|
||||
val beatBytes = params.beatBytes
|
||||
val blockBytes = params.blockBytes
|
||||
val masterBuffering = params.masterBuffering
|
||||
val slaveBuffering = params.slaveBuffering
|
||||
require(blockBytes % beatBytes == 0)
|
||||
private val delayProb = p(TLBusDelayProbability)
|
||||
|
||||
protected val xbar = LazyModule(new TLXbar)
|
||||
xbar.suggestName(busName)
|
||||
|
||||
private val master_buffer = LazyModule(new TLBuffer(masterBuffering))
|
||||
master_buffer.suggestName(s"${busName}_master_TLBuffer")
|
||||
private val slave_buffer = LazyModule(new TLBuffer(slaveBuffering))
|
||||
slave_buffer.suggestName(s"${busName}_slave_TLBuffer")
|
||||
private val slave_frag = LazyModule(new TLFragmenter(beatBytes, blockBytes))
|
||||
slave_frag.suggestName(s"${busName}_slave_TLFragmenter")
|
||||
|
||||
private val slave_ww = LazyModule(new TLWidthWidget(beatBytes))
|
||||
slave_ww.suggestName(s"${busName}_slave_TLWidthWidget")
|
||||
|
||||
private val delayedNode = if (delayProb > 0.0) {
|
||||
val firstDelay = LazyModule(new TLDelayer(delayProb))
|
||||
val flowDelay = LazyModule(new TLBuffer(BufferParams.flow))
|
||||
val secondDelay = LazyModule(new TLDelayer(delayProb))
|
||||
firstDelay.node :*= xbar.node
|
||||
flowDelay.node :*= firstDelay.node
|
||||
secondDelay.node :*= flowDelay.node
|
||||
secondDelay.node
|
||||
} else {
|
||||
xbar.node
|
||||
}
|
||||
|
||||
xbar.node :=* master_buffer.node
|
||||
slave_buffer.node :*= delayedNode
|
||||
slave_frag.node :*= slave_buffer.node
|
||||
slave_ww.node :*= slave_buffer.node
|
||||
|
||||
protected def outwardNode: TLOutwardNode = delayedNode
|
||||
protected def outwardBufNode: TLOutwardNode = slave_buffer.node
|
||||
protected def outwardFragNode: TLOutwardNode = slave_frag.node
|
||||
protected def outwardWWNode: TLOutwardNode = slave_ww.node
|
||||
protected def inwardNode: TLInwardNode = xbar.node
|
||||
protected def inwardBufNode: TLInwardNode = master_buffer.node
|
||||
|
||||
def bufferFromMasters: TLInwardNode = inwardBufNode
|
||||
|
||||
def bufferToSlaves: TLOutwardNode = outwardBufNode
|
||||
|
||||
def toSyncSlaves(name: Option[String] = None, addBuffers: Int = 0): TLOutwardNode = {
|
||||
TLBuffer.chain(addBuffers).foldRight(outwardBufNode)(_ :*= _)
|
||||
}
|
||||
|
||||
def toVariableWidthSlaves: TLOutwardNode = outwardFragNode
|
||||
|
||||
def toFixedWidthSlaves: TLOutwardNode = outwardWWNode
|
||||
|
||||
def toFixedWidthPorts: TLOutwardNode = outwardWWNode // TODO, do/don't buffer here; knowing we will after the necessary port conversions
|
||||
|
||||
}
|
87
src/main/scala/tilelink/BusWrapper.scala
Normal file
87
src/main/scala/tilelink/BusWrapper.scala
Normal file
@ -0,0 +1,87 @@
|
||||
// See LICENSE.SiFive for license details.
|
||||
|
||||
package freechips.rocketchip.tilelink
|
||||
|
||||
import Chisel._
|
||||
import freechips.rocketchip.config.{Field, Parameters}
|
||||
import freechips.rocketchip.diplomacy._
|
||||
|
||||
case object TLBusDelayProbability extends Field[Double](0.0)
|
||||
|
||||
/** Specifies widths of various attachement points in the SoC */
|
||||
trait HasTLBusParams {
|
||||
val beatBytes: Int
|
||||
val blockBytes: Int
|
||||
|
||||
def beatBits: Int = beatBytes * 8
|
||||
def blockBits: Int = blockBytes * 8
|
||||
def blockBeats: Int = blockBytes / beatBytes
|
||||
def blockOffset: Int = log2Up(blockBytes)
|
||||
}
|
||||
|
||||
abstract class TLBusWrapper(params: HasTLBusParams, val busName: String)(implicit p: Parameters)
|
||||
extends SimpleLazyModule with LazyScope with HasTLBusParams {
|
||||
|
||||
val beatBytes = params.beatBytes
|
||||
val blockBytes = params.blockBytes
|
||||
require(blockBytes % beatBytes == 0)
|
||||
|
||||
protected def inwardNode: TLInwardNode
|
||||
protected def outwardNode: TLOutwardNode
|
||||
|
||||
protected def bufferFrom(buffer: BufferParams): TLInwardNode =
|
||||
inwardNode :=* TLBuffer(buffer)
|
||||
|
||||
protected def bufferFrom(buffers: Int): TLInwardNode =
|
||||
TLBuffer.chain(buffers).foldLeft(inwardNode)(_ :=* _)
|
||||
|
||||
protected def fixFrom(policy: TLFIFOFixer.Policy, buffers: Int): TLInwardNode =
|
||||
inwardNode :=* TLBuffer.chain(buffers).foldLeft(TLFIFOFixer(policy))(_ :=* _)
|
||||
|
||||
protected def bufferTo(buffer: BufferParams): TLOutwardNode =
|
||||
TLBuffer(buffer) :*= delayNode :*= outwardNode
|
||||
|
||||
protected def bufferTo(buffers: Int): TLOutwardNode =
|
||||
TLBuffer.chain(buffers).foldRight(delayNode)(_ :*= _) :*= outwardNode
|
||||
|
||||
protected def fixedWidthTo(buffer: BufferParams): TLOutwardNode =
|
||||
TLWidthWidget(beatBytes) :*= bufferTo(buffer)
|
||||
|
||||
protected def fragmentTo(buffer: BufferParams): TLOutwardNode =
|
||||
TLFragmenter(beatBytes, blockBytes) :*= bufferTo(buffer)
|
||||
|
||||
protected def fragmentTo(minSize: Int, maxSize: Int, buffer: BufferParams): TLOutwardNode =
|
||||
TLFragmenter(minSize, maxSize) :*= bufferTo(buffer)
|
||||
|
||||
protected def delayNode(implicit p: Parameters): TLNode = {
|
||||
val delayProb = p(TLBusDelayProbability)
|
||||
if (delayProb > 0.0) {
|
||||
TLDelayer(delayProb) :*=* TLBuffer(BufferParams.flow) :*=* TLDelayer(delayProb)
|
||||
} else {
|
||||
val nodelay = TLIdentityNode()
|
||||
nodelay
|
||||
}
|
||||
}
|
||||
|
||||
protected def to[T](name: String)(body: => T): T = {
|
||||
this { LazyScope(s"coupler_to_${name}") { body } }
|
||||
}
|
||||
|
||||
protected def from[T](name: String)(body: => T): T = {
|
||||
this { LazyScope(s"coupler_from_${name}") { body } }
|
||||
}
|
||||
}
|
||||
|
||||
trait HasTLXbarPhy { this: TLBusWrapper =>
|
||||
private val xbar = LazyModule(new TLXbar).suggestName(busName + "_xbar")
|
||||
|
||||
protected def inwardNode: TLInwardNode = xbar.node
|
||||
protected def outwardNode: TLOutwardNode = xbar.node
|
||||
}
|
||||
|
||||
object TLIdentity {
|
||||
def gen: TLNode = {
|
||||
val passthru = TLIdentityNode()
|
||||
passthru
|
||||
}
|
||||
}
|
@ -30,18 +30,6 @@ object TLImp extends NodeImp[TLClientPortParameters, TLManagerPortParameters, TL
|
||||
pd.copy(clients = pd.clients.map { c => c.copy (nodePath = node +: c.nodePath) })
|
||||
override def mixI(pu: TLManagerPortParameters, node: InwardNode[TLClientPortParameters, TLManagerPortParameters, TLBundle]): TLManagerPortParameters =
|
||||
pu.copy(managers = pu.managers.map { m => m.copy (nodePath = node +: m.nodePath) })
|
||||
override def getO(pu: TLManagerPortParameters): Option[BaseNode] = {
|
||||
val head = pu.managers.map(_.nodePath.headOption)
|
||||
if (head.exists(!_.isDefined) || head.map(_.get).distinct.size != 1) {
|
||||
None
|
||||
} else {
|
||||
val subproblem = pu.copy(managers = pu.managers.map(m => m.copy(nodePath = m.nodePath.tail)))
|
||||
getO(subproblem) match {
|
||||
case Some(x) => Some(x)
|
||||
case None => Some(head(0).get)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case class TLClientNode(portParams: Seq[TLClientPortParameters])(implicit valName: ValName) extends SourceNode(TLImp)(portParams)
|
||||
|
@ -7,7 +7,7 @@ import freechips.rocketchip.amba.ahb._
|
||||
import freechips.rocketchip.amba.apb._
|
||||
import freechips.rocketchip.amba.axi4._
|
||||
import freechips.rocketchip.config._
|
||||
import freechips.rocketchip.coreplex.{BaseCoreplexConfig}
|
||||
import freechips.rocketchip.subsystem.{BaseSubsystemConfig}
|
||||
import freechips.rocketchip.devices.tilelink._
|
||||
import freechips.rocketchip.tilelink._
|
||||
|
||||
@ -79,7 +79,7 @@ class WithTLXbarUnitTests extends Config((site, here, up) => {
|
||||
Module(new TLMulticlientXbarTest(4,4, txns=2*txns, timeout=timeout)) ) }
|
||||
})
|
||||
|
||||
class AMBAUnitTestConfig extends Config(new WithAMBAUnitTests ++ new WithTestDuration(10) ++ new BaseCoreplexConfig)
|
||||
class TLSimpleUnitTestConfig extends Config(new WithTLSimpleUnitTests ++ new WithTestDuration(10) ++ new BaseCoreplexConfig)
|
||||
class TLWidthUnitTestConfig extends Config(new WithTLWidthUnitTests ++ new WithTestDuration(10) ++ new BaseCoreplexConfig)
|
||||
class TLXbarUnitTestConfig extends Config(new WithTLXbarUnitTests ++ new WithTestDuration(10) ++ new BaseCoreplexConfig)
|
||||
class AMBAUnitTestConfig extends Config(new WithAMBAUnitTests ++ new WithTestDuration(10) ++ new BaseSubsystemConfig)
|
||||
class TLSimpleUnitTestConfig extends Config(new WithTLSimpleUnitTests ++ new WithTestDuration(10) ++ new BaseSubsystemConfig)
|
||||
class TLWidthUnitTestConfig extends Config(new WithTLWidthUnitTests ++ new WithTestDuration(10) ++ new BaseSubsystemConfig)
|
||||
class TLXbarUnitTestConfig extends Config(new WithTLXbarUnitTests ++ new WithTestDuration(10) ++ new BaseSubsystemConfig)
|
||||
|
@ -108,7 +108,7 @@ trait GeneratorApp extends App with HasGeneratorUtilities {
|
||||
/** Output software test Makefrags, which provide targets for integration testing. */
|
||||
def generateTestSuiteMakefrags {
|
||||
addTestSuites
|
||||
writeOutputFile(td, s"$longName.d", TestGeneration.generateMakefrag) // Coreplex-specific test suites
|
||||
writeOutputFile(td, s"$longName.d", TestGeneration.generateMakefrag) // Subsystem-specific test suites
|
||||
}
|
||||
|
||||
def addTestSuites {
|
||||
|
@ -43,6 +43,28 @@ package object util {
|
||||
def readAndHold(addr: UInt, enable: Bool): T = x.read(addr, enable) holdUnless RegNext(enable)
|
||||
}
|
||||
|
||||
implicit class StringToAugmentedString(val x: String) extends AnyVal {
|
||||
/** converts from camel case to to underscores, also removing all spaces */
|
||||
def underscore: String = x.tail.foldLeft(x.headOption.map(_.toLower + "") getOrElse "") {
|
||||
case (acc, c) if c.isUpper => acc + "_" + c.toLower
|
||||
case (acc, c) if c == ' ' => acc
|
||||
case (acc, c) => acc + c
|
||||
}
|
||||
|
||||
/** converts spaces or underscores to hyphens, also lowering case */
|
||||
def kebab: String = x.toLowerCase map {
|
||||
case ' ' => '-'
|
||||
case '_' => '-'
|
||||
case c => c
|
||||
}
|
||||
|
||||
def named(name: Option[String]): String = {
|
||||
x + name.map("_named_" + _ ).getOrElse("_with_no_name")
|
||||
}
|
||||
|
||||
def named(name: String): String = named(Some(name))
|
||||
}
|
||||
|
||||
implicit def uintToBitPat(x: UInt): BitPat = BitPat(x)
|
||||
implicit def wcToUInt(c: WideCounter): UInt = c.value
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user