2017-07-23 17:31:04 +02:00
|
|
|
// See LICENSE.SiFive for license details.
|
|
|
|
|
|
|
|
package freechips.rocketchip.coreplex
|
|
|
|
|
|
|
|
import Chisel._
|
|
|
|
import freechips.rocketchip.config.{Field, Parameters}
|
|
|
|
import freechips.rocketchip.devices.tilelink._
|
|
|
|
import freechips.rocketchip.devices.debug.{HasPeripheryDebug, HasPeripheryDebugModuleImp}
|
|
|
|
import freechips.rocketchip.diplomacy._
|
|
|
|
import freechips.rocketchip.tile._
|
|
|
|
import freechips.rocketchip.tilelink._
|
|
|
|
import freechips.rocketchip.util._
|
|
|
|
|
2017-10-11 00:02:50 +02:00
|
|
|
case class TLNodeChain(in: TLInwardNode, out: TLOutwardNode)
|
|
|
|
|
2017-10-10 08:43:18 +02:00
|
|
|
// TODO: how specific are these to RocketTiles?
|
2017-10-11 00:02:50 +02:00
|
|
|
case class TileMasterPortParams(
|
|
|
|
addBuffers: Int = 0,
|
|
|
|
blockerCtrlAddr: Option[BigInt] = None,
|
2017-10-11 01:24:32 +02:00
|
|
|
cork: Option[Boolean] = None) {
|
2017-10-11 00:02:50 +02:00
|
|
|
def adapterChain(coreplex: HasPeripheryBus)
|
|
|
|
(implicit p: Parameters): () => TLNodeChain = {
|
|
|
|
|
|
|
|
val blockerParams = blockerCtrlAddr.map(BusBlockerParams(_, coreplex.pbus.beatBytes, coreplex.sbus.beatBytes, 1))
|
|
|
|
|
2017-10-11 01:24:32 +02:00
|
|
|
val tile_master_cork = cork.map(u => (LazyModule(new TLCacheCork(unsafe = u))))
|
2017-10-11 00:02:50 +02:00
|
|
|
val tile_master_blocker = blockerParams.map(bp => LazyModule(new BusBlocker(bp)))
|
|
|
|
val tile_master_fixer = LazyModule(new TLFIFOFixer(TLFIFOFixer.allUncacheable))
|
|
|
|
val tile_master_buffer = LazyModule(new TLBufferChain(addBuffers))
|
|
|
|
|
2017-10-11 09:29:11 +02:00
|
|
|
tile_master_blocker.foreach { _.controlNode := coreplex.pbus.toVariableWidthSlaves }
|
|
|
|
|
2017-10-11 00:02:50 +02:00
|
|
|
val nodes = List(
|
|
|
|
Some(tile_master_buffer.node),
|
|
|
|
Some(tile_master_fixer.node),
|
|
|
|
tile_master_blocker.map(_.node),
|
2017-10-11 09:29:11 +02:00
|
|
|
tile_master_cork.map(_.node)
|
|
|
|
).flatMap(b=>b)
|
2017-10-11 00:02:50 +02:00
|
|
|
|
|
|
|
nodes.init zip nodes.tail foreach { case(front, back) => front :=* back }
|
|
|
|
|
2017-10-11 09:29:11 +02:00
|
|
|
() => TLNodeChain(in = nodes.last, out = nodes.head)
|
2017-10-11 00:02:50 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
case class TileSlavePortParams(
|
|
|
|
addBuffers: Int = 0,
|
|
|
|
blockerCtrlAddr: Option[BigInt] = None) {
|
|
|
|
def adapterChain(coreplex: HasPeripheryBus)
|
|
|
|
(implicit p: Parameters): () => TLNodeChain = {
|
|
|
|
|
|
|
|
val blockerParams = blockerCtrlAddr.map(BusBlockerParams(_, coreplex.pbus.beatBytes, coreplex.sbus.beatBytes, 1))
|
|
|
|
|
|
|
|
val tile_slave_blocker = blockerParams.map(bp => LazyModule(new BusBlocker(bp)))
|
|
|
|
val tile_slave_buffer = LazyModule(new TLBufferChain(addBuffers))
|
|
|
|
|
2017-10-11 09:29:11 +02:00
|
|
|
tile_slave_blocker.foreach { _.controlNode := coreplex.pbus.toVariableWidthSlaves }
|
|
|
|
|
2017-10-11 00:02:50 +02:00
|
|
|
val nodes = List(
|
|
|
|
Some(tile_slave_buffer.node),
|
2017-10-11 09:29:11 +02:00
|
|
|
tile_slave_blocker.map(_.node)
|
|
|
|
).flatMap(b=>b)
|
2017-10-11 00:02:50 +02:00
|
|
|
|
|
|
|
nodes.init zip nodes.tail foreach { case(front, back) => front :=* back }
|
|
|
|
|
2017-10-11 09:29:11 +02:00
|
|
|
() => TLNodeChain(in = nodes.last, out = nodes.head)
|
2017-10-11 00:02:50 +02:00
|
|
|
}
|
|
|
|
}
|
2017-10-10 08:43:18 +02:00
|
|
|
|
|
|
|
case class RocketCrossingParams(
|
|
|
|
crossingType: CoreplexClockCrossing = SynchronousCrossing(),
|
2017-10-11 00:02:50 +02:00
|
|
|
master: TileMasterPortParams = TileMasterPortParams(),
|
|
|
|
slave: TileSlavePortParams = TileSlavePortParams()) {
|
2017-10-10 08:43:18 +02:00
|
|
|
def knownRatio: Option[Int] = crossingType match {
|
|
|
|
case RationalCrossing(_) => Some(2)
|
|
|
|
case _ => None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-09 03:33:44 +02:00
|
|
|
case object RocketTilesKey extends Field[Seq[RocketTileParams]](Nil)
|
2017-10-10 08:43:18 +02:00
|
|
|
case object RocketCrossingKey extends Field[Seq[RocketCrossingParams]](List(RocketCrossingParams()))
|
2017-07-23 17:31:04 +02:00
|
|
|
|
2017-10-06 09:56:23 +02:00
|
|
|
trait HasRocketTiles extends HasTiles
|
2017-07-23 17:31:04 +02:00
|
|
|
with HasPeripheryBus
|
|
|
|
with HasPeripheryPLIC
|
|
|
|
with HasPeripheryClint
|
|
|
|
with HasPeripheryDebug {
|
|
|
|
val module: HasRocketTilesModuleImp
|
|
|
|
|
2017-10-06 09:56:23 +02:00
|
|
|
protected val tileParams = p(RocketTilesKey)
|
2017-10-10 08:43:18 +02:00
|
|
|
private val NumRocketTiles = tileParams.size
|
|
|
|
private val crossingParams = p(RocketCrossingKey)
|
|
|
|
private val crossings = crossingParams.size match {
|
|
|
|
case 1 => List.fill(NumRocketTiles) { crossingParams.head }
|
|
|
|
case NumRocketTiles => crossingParams
|
|
|
|
case _ => throw new Exception("RocketCrossingKey.size must == 1 or == RocketTilesKey.size")
|
|
|
|
}
|
2017-07-23 17:31:04 +02:00
|
|
|
|
|
|
|
// Make a wrapper for each tile that will wire it to coreplex devices and crossbars,
|
|
|
|
// according to the specified type of clock crossing.
|
2017-10-10 08:43:18 +02:00
|
|
|
private val crossingTuples = localIntNodes.zip(tileParams).zip(crossings)
|
|
|
|
val tiles: Seq[BaseTile] = crossingTuples.map { case ((lip, tp), crossing) =>
|
2017-07-23 17:31:04 +02:00
|
|
|
val pWithExtra = p.alterPartial {
|
2017-08-31 02:57:52 +02:00
|
|
|
case TileKey => tp
|
|
|
|
case BuildRoCC => tp.rocc
|
2017-07-23 17:31:04 +02:00
|
|
|
case SharedMemoryTLEdge => sharedMemoryTLEdge
|
2017-10-10 08:43:18 +02:00
|
|
|
case RocketCrossingKey => List(crossing)
|
2017-07-23 17:31:04 +02:00
|
|
|
}
|
|
|
|
|
2017-10-10 08:43:18 +02:00
|
|
|
val wrapper = crossing.crossingType match {
|
2017-07-23 17:31:04 +02:00
|
|
|
case SynchronousCrossing(params) => {
|
2017-10-05 09:31:53 +02:00
|
|
|
val wrapper = LazyModule(new SyncRocketTile(tp)(pWithExtra))
|
2017-10-11 00:02:50 +02:00
|
|
|
sbus.fromSyncTiles(params, crossing.master.adapterChain(this), tp.name) :=* wrapper.masterNode
|
2017-10-11 00:25:08 +02:00
|
|
|
FlipRendering { implicit p => wrapper.slaveNode :*= pbus.toSyncSlaves(crossing.slave.adapterChain(this), tp.name) }
|
2017-07-23 17:31:04 +02:00
|
|
|
wrapper
|
|
|
|
}
|
|
|
|
case AsynchronousCrossing(depth, sync) => {
|
2017-10-05 09:31:53 +02:00
|
|
|
val wrapper = LazyModule(new AsyncRocketTile(tp)(pWithExtra))
|
2017-10-11 00:02:50 +02:00
|
|
|
sbus.fromAsyncTiles(depth, sync, crossing.master.adapterChain(this), tp.name) :=* wrapper.masterNode
|
2017-10-11 00:25:08 +02:00
|
|
|
FlipRendering { implicit p => wrapper.slaveNode :*= pbus.toAsyncSlaves(sync, crossing.slave.adapterChain(this), tp.name) }
|
2017-07-23 17:31:04 +02:00
|
|
|
wrapper
|
|
|
|
}
|
|
|
|
case RationalCrossing(direction) => {
|
2017-10-05 09:31:53 +02:00
|
|
|
val wrapper = LazyModule(new RationalRocketTile(tp)(pWithExtra))
|
2017-10-11 00:02:50 +02:00
|
|
|
sbus.fromRationalTiles(direction, crossing.master.adapterChain(this), tp.name) :=* wrapper.masterNode
|
2017-10-11 00:25:08 +02:00
|
|
|
FlipRendering { implicit p => wrapper.slaveNode :*= pbus.toRationalSlaves(crossing.slave.adapterChain(this), tp.name) }
|
2017-07-23 17:31:04 +02:00
|
|
|
wrapper
|
|
|
|
}
|
|
|
|
}
|
2017-08-31 02:57:52 +02:00
|
|
|
tp.name.foreach(wrapper.suggestName) // Try to stabilize this name for downstream tools
|
2017-07-23 17:31:04 +02:00
|
|
|
|
|
|
|
// Local Interrupts must be synchronized to the core clock
|
|
|
|
// before being passed into this module.
|
|
|
|
// This allows faster latency for interrupts which are already synchronized.
|
|
|
|
// The CLINT and PLIC outputs interrupts that are synchronous to the periphery clock,
|
|
|
|
// so may or may not need to be synchronized depending on the Tile's crossing type.
|
|
|
|
// Debug interrupt is definitely asynchronous in all cases.
|
|
|
|
val asyncIntXbar = LazyModule(new IntXbar)
|
|
|
|
asyncIntXbar.intnode := debug.intnode // debug
|
|
|
|
wrapper.asyncIntNode := asyncIntXbar.intnode
|
|
|
|
|
|
|
|
val periphIntXbar = LazyModule(new IntXbar)
|
|
|
|
periphIntXbar.intnode := clint.intnode // msip+mtip
|
|
|
|
periphIntXbar.intnode := plic.intnode // meip
|
2017-08-31 02:57:52 +02:00
|
|
|
if (tp.core.useVM) periphIntXbar.intnode := plic.intnode // seip
|
2017-07-23 17:31:04 +02:00
|
|
|
wrapper.periphIntNode := periphIntXbar.intnode
|
|
|
|
|
|
|
|
val coreIntXbar = LazyModule(new IntXbar)
|
|
|
|
lip.foreach { coreIntXbar.intnode := _ } // lip
|
|
|
|
wrapper.coreIntNode := coreIntXbar.intnode
|
|
|
|
|
2017-09-27 21:02:04 +02:00
|
|
|
wrapper.intOutputNode.foreach { case int =>
|
|
|
|
val rocketIntXing = LazyModule(new IntXing(wrapper.outputInterruptXingLatency))
|
2017-09-27 21:46:29 +02:00
|
|
|
FlipRendering { implicit p => rocketIntXing.intnode := int }
|
2017-09-27 21:02:04 +02:00
|
|
|
plic.intnode := rocketIntXing.intnode
|
|
|
|
}
|
2017-09-16 03:49:40 +02:00
|
|
|
|
2017-07-23 17:31:04 +02:00
|
|
|
wrapper
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-08 02:29:50 +02:00
|
|
|
trait HasRocketTilesModuleImp extends HasTilesModuleImp
|
2017-07-23 17:31:04 +02:00
|
|
|
with HasPeripheryDebugModuleImp {
|
2017-10-08 02:29:50 +02:00
|
|
|
val outer: HasRocketTiles
|
2017-07-23 17:31:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
class RocketCoreplex(implicit p: Parameters) extends BaseCoreplex
|
|
|
|
with HasRocketTiles {
|
|
|
|
override lazy val module = new RocketCoreplexModule(this)
|
|
|
|
}
|
|
|
|
|
|
|
|
class RocketCoreplexModule[+L <: RocketCoreplex](_outer: L) extends BaseCoreplexModule(_outer)
|
|
|
|
with HasRocketTilesModuleImp
|