2016-11-28 01:16:37 +01:00
|
|
|
// See LICENSE.SiFive for license details.
|
|
|
|
// See LICENSE.Berkeley for license details.
|
2014-09-13 03:06:41 +02:00
|
|
|
|
2017-07-23 17:31:04 +02:00
|
|
|
package freechips.rocketchip.tile
|
2012-03-25 00:56:59 +01:00
|
|
|
|
|
|
|
import Chisel._
|
2017-07-07 19:48:16 +02:00
|
|
|
import freechips.rocketchip.config._
|
|
|
|
import freechips.rocketchip.coreplex._
|
|
|
|
import freechips.rocketchip.diplomacy._
|
2017-07-23 17:31:04 +02:00
|
|
|
import freechips.rocketchip.rocket._
|
2017-07-07 19:48:16 +02:00
|
|
|
import freechips.rocketchip.tilelink._
|
2017-10-20 05:44:54 +02:00
|
|
|
import freechips.rocketchip.interrupts._
|
2017-07-07 19:48:16 +02:00
|
|
|
import freechips.rocketchip.util._
|
2012-03-25 00:56:59 +01:00
|
|
|
|
2017-02-09 22:59:09 +01:00
|
|
|
case class RocketTileParams(
|
|
|
|
core: RocketCoreParams = RocketCoreParams(),
|
|
|
|
icache: Option[ICacheParams] = Some(ICacheParams()),
|
|
|
|
dcache: Option[DCacheParams] = Some(DCacheParams()),
|
|
|
|
rocc: Seq[RoCCParams] = Nil,
|
|
|
|
btb: Option[BTBParams] = Some(BTBParams()),
|
2017-08-01 00:40:54 +02:00
|
|
|
dataScratchpadBytes: Int = 0,
|
2017-09-20 07:59:28 +02:00
|
|
|
trace: Boolean = false,
|
2017-09-21 03:53:44 +02:00
|
|
|
hcfOnUncorrectable: Boolean = false,
|
2017-08-31 02:57:52 +02:00
|
|
|
name: Option[String] = Some("tile"),
|
2017-12-21 02:18:38 +01:00
|
|
|
hartId: Int = 0,
|
2017-11-18 02:26:48 +01:00
|
|
|
blockerCtrlAddr: Option[BigInt] = None,
|
2017-10-26 22:52:34 +02:00
|
|
|
boundaryBuffers: Boolean = false // if synthesized with hierarchical PnR, cut feed-throughs?
|
|
|
|
) extends TileParams {
|
2017-02-09 22:59:09 +01:00
|
|
|
require(icache.isDefined)
|
|
|
|
require(dcache.isDefined)
|
|
|
|
}
|
2017-10-10 06:03:18 +02:00
|
|
|
|
2017-12-21 02:18:38 +01:00
|
|
|
class RocketTile(val rocketParams: RocketTileParams)(implicit p: Parameters) extends BaseTile(rocketParams)(p)
|
2017-07-07 19:48:16 +02:00
|
|
|
with HasExternalInterrupts
|
2017-06-22 21:07:09 +02:00
|
|
|
with HasLazyRoCC // implies CanHaveSharedFPU with CanHavePTW with HasHellaCache
|
2017-01-17 03:24:08 +01:00
|
|
|
with CanHaveScratchpad { // implies CanHavePTW with HasHellaCache with HasICacheFrontend
|
2015-12-02 02:54:56 +01:00
|
|
|
|
2017-01-17 03:24:08 +01:00
|
|
|
nDCachePorts += 1 // core TODO dcachePorts += () => module.core.io.dmem ??
|
2014-08-08 21:23:02 +02:00
|
|
|
|
2017-12-21 02:18:38 +01:00
|
|
|
val dtimProperty = scratch.map(d => Map(
|
|
|
|
"sifive,dtim" -> d.device.asProperty)).getOrElse(Nil)
|
|
|
|
|
|
|
|
val itimProperty = tileParams.icache.flatMap(_.itimAddr.map(i => Map(
|
|
|
|
"sifive,itim" -> frontend.icache.device.asProperty))).getOrElse(Nil)
|
2017-03-30 08:51:59 +02:00
|
|
|
|
|
|
|
val cpuDevice = new Device {
|
2017-12-21 02:18:38 +01:00
|
|
|
def describe(resources: ResourceBindings): Description =
|
|
|
|
toDescription(resources)("sifive,rocket0", dtimProperty ++ itimProperty)
|
2017-03-30 08:51:59 +02:00
|
|
|
}
|
2017-03-02 01:47:10 +01:00
|
|
|
|
|
|
|
ResourceBinding {
|
2017-12-21 02:18:38 +01:00
|
|
|
Resource(cpuDevice, "reg").bind(ResourceInt(BigInt(hartId)))
|
2017-03-02 01:47:10 +01:00
|
|
|
}
|
|
|
|
|
2017-01-17 03:24:08 +01:00
|
|
|
override lazy val module = new RocketTileModule(this)
|
|
|
|
}
|
2016-11-11 22:07:45 +01:00
|
|
|
|
2017-01-17 03:24:08 +01:00
|
|
|
class RocketTileBundle(outer: RocketTile) extends BaseTileBundle(outer)
|
2017-09-21 23:58:15 +02:00
|
|
|
with CanHaltAndCatchFire {
|
|
|
|
val halt_and_catch_fire = outer.rocketParams.hcfOnUncorrectable.option(Bool(OUTPUT))
|
|
|
|
}
|
2017-01-17 03:24:08 +01:00
|
|
|
|
|
|
|
class RocketTileModule(outer: RocketTile) extends BaseTileModule(outer, () => new RocketTileBundle(outer))
|
2017-07-07 19:48:16 +02:00
|
|
|
with HasExternalInterruptsModule
|
2017-06-22 21:07:09 +02:00
|
|
|
with HasLazyRoCCModule
|
2017-01-17 03:24:08 +01:00
|
|
|
with CanHaveScratchpadModule {
|
|
|
|
|
2017-02-09 22:59:09 +01:00
|
|
|
val core = Module(p(BuildCore)(outer.p))
|
2017-09-21 03:53:44 +02:00
|
|
|
val uncorrectable = RegInit(Bool(false))
|
|
|
|
|
2017-03-30 04:14:04 +02:00
|
|
|
decodeCoreInterrupts(core.io.interrupts) // Decode the interrupt vector
|
2017-11-07 01:54:21 +01:00
|
|
|
outer.busErrorUnit.foreach { beu => core.io.interrupts.buserror.get := beu.module.io.interrupt }
|
2017-03-30 04:14:04 +02:00
|
|
|
core.io.hartid := io.hartid // Pass through the hartid
|
2017-09-20 07:59:28 +02:00
|
|
|
io.trace.foreach { _ := core.io.trace }
|
2017-09-21 23:58:15 +02:00
|
|
|
io.halt_and_catch_fire.foreach { _ := uncorrectable }
|
2017-01-17 03:24:08 +01:00
|
|
|
outer.frontend.module.io.cpu <> core.io.imem
|
2017-09-02 02:50:54 +02:00
|
|
|
outer.frontend.module.io.reset_vector := io.reset_vector
|
2017-04-25 02:14:23 +02:00
|
|
|
outer.frontend.module.io.hartid := io.hartid
|
2017-04-27 00:54:43 +02:00
|
|
|
outer.dcache.module.io.hartid := io.hartid
|
2017-01-17 03:24:08 +01:00
|
|
|
dcachePorts += core.io.dmem // TODO outer.dcachePorts += () => module.core.io.dmem ??
|
|
|
|
fpuOpt foreach { fpu => core.io.fpu <> fpu.io }
|
2017-03-24 21:00:47 +01:00
|
|
|
core.io.ptw <> ptw.io.dpath
|
2017-06-22 21:07:09 +02:00
|
|
|
roccCore.cmd <> core.io.rocc.cmd
|
|
|
|
roccCore.exception := core.io.rocc.exception
|
|
|
|
core.io.rocc.resp <> roccCore.resp
|
|
|
|
core.io.rocc.busy := roccCore.busy
|
|
|
|
core.io.rocc.interrupt := roccCore.interrupt
|
2016-11-21 21:19:33 +01:00
|
|
|
|
2017-09-21 03:53:44 +02:00
|
|
|
when(!uncorrectable) { uncorrectable :=
|
|
|
|
List(outer.frontend.module.io.errors, outer.dcache.module.io.errors)
|
|
|
|
.flatMap { e => e.uncorrectable.map(_.valid) }
|
|
|
|
.reduceOption(_||_)
|
|
|
|
.getOrElse(false.B)
|
|
|
|
}
|
2017-03-02 22:37:25 +01:00
|
|
|
|
2017-02-09 22:59:09 +01:00
|
|
|
// TODO eliminate this redundancy
|
|
|
|
val h = dcachePorts.size
|
|
|
|
val c = core.dcacheArbPorts
|
|
|
|
val o = outer.nDCachePorts
|
|
|
|
require(h == c, s"port list size was $h, core expected $c")
|
|
|
|
require(h == o, s"port list size was $h, outer counted $o")
|
2017-01-17 03:24:08 +01:00
|
|
|
// TODO figure out how to move the below into their respective mix-ins
|
|
|
|
dcacheArb.io.requestor <> dcachePorts
|
2017-03-24 21:00:47 +01:00
|
|
|
ptw.io.requestor <> ptwPorts
|
2017-01-17 03:24:08 +01:00
|
|
|
}
|
2016-11-11 00:56:42 +01:00
|
|
|
|
2017-10-06 07:46:16 +02:00
|
|
|
class RocketTileWrapperBundle[+L <: RocketTileWrapper](_outer: L) extends BaseTileBundle(_outer)
|
|
|
|
with CanHaltAndCatchFire {
|
|
|
|
val halt_and_catch_fire = _outer.rocket.module.io.halt_and_catch_fire.map(_.cloneType)
|
|
|
|
}
|
|
|
|
|
2017-10-23 18:39:01 +02:00
|
|
|
class RocketTileWrapper(
|
|
|
|
params: RocketTileParams,
|
2017-10-26 22:52:34 +02:00
|
|
|
val crossing: CoreplexClockCrossing)
|
2017-10-25 23:45:44 +02:00
|
|
|
(implicit p: Parameters) extends BaseTile(params) with HasCrossing {
|
2017-04-28 23:49:24 +02:00
|
|
|
|
2017-10-23 18:39:01 +02:00
|
|
|
val rocket = LazyModule(new RocketTile(params))
|
2017-03-27 11:45:37 +02:00
|
|
|
|
2017-10-26 22:52:34 +02:00
|
|
|
// The buffers needed to cut feed-through paths are microarchitecture specific, so belong here
|
2017-10-23 18:39:01 +02:00
|
|
|
val masterBuffer = LazyModule(new TLBuffer(BufferParams.none, BufferParams.flow, BufferParams.none, BufferParams.flow, BufferParams(1)))
|
2017-12-21 02:18:38 +01:00
|
|
|
val masterNode = crossing match {
|
2017-10-26 22:52:34 +02:00
|
|
|
case _: AsynchronousCrossing => rocket.masterNode
|
|
|
|
case SynchronousCrossing(b) =>
|
|
|
|
require (!params.boundaryBuffers || (b.depth >= 1 && !b.flow && !b.pipe), "Buffer misconfiguration creates feed-through paths")
|
|
|
|
rocket.masterNode
|
|
|
|
case RationalCrossing(dir) =>
|
|
|
|
require (dir != SlowToFast, "Misconfiguration? Core slower than fabric")
|
|
|
|
if (params.boundaryBuffers) {
|
|
|
|
masterBuffer.node :=* rocket.masterNode
|
|
|
|
} else {
|
|
|
|
rocket.masterNode
|
|
|
|
}
|
|
|
|
}
|
2017-08-01 00:40:54 +02:00
|
|
|
|
2017-10-23 18:39:01 +02:00
|
|
|
val slaveBuffer = LazyModule(new TLBuffer(BufferParams.flow, BufferParams.none, BufferParams.none, BufferParams.none, BufferParams.none))
|
2017-10-26 22:52:34 +02:00
|
|
|
val slaveNode: TLInwardNode = crossing match {
|
|
|
|
case _: SynchronousCrossing => rocket.slaveNode // requirement already checked
|
|
|
|
case _: AsynchronousCrossing => rocket.slaveNode
|
|
|
|
case _: RationalCrossing =>
|
|
|
|
if (params.boundaryBuffers) {
|
|
|
|
DisableMonitors { implicit p => rocket.slaveNode :*= slaveBuffer.node }
|
|
|
|
} else {
|
|
|
|
rocket.slaveNode
|
|
|
|
}
|
|
|
|
}
|
2017-08-01 00:40:54 +02:00
|
|
|
|
2017-12-21 02:18:38 +01:00
|
|
|
rocket.intInwardNode := intXbar.intnode
|
|
|
|
val intInwardNode = intXbar.intnode
|
|
|
|
val intOutwardNode = rocket.intOutwardNode
|
2017-09-16 03:49:40 +02:00
|
|
|
|
2017-10-06 07:46:16 +02:00
|
|
|
override lazy val module = new BaseTileModule(this, () => new RocketTileWrapperBundle(this)) {
|
2017-07-23 17:31:04 +02:00
|
|
|
// signals that do not change based on crossing type:
|
2017-03-27 11:45:37 +02:00
|
|
|
rocket.module.io.hartid := io.hartid
|
2017-09-02 02:50:54 +02:00
|
|
|
rocket.module.io.reset_vector := io.reset_vector
|
2017-09-20 07:59:28 +02:00
|
|
|
io.trace.foreach { _ := rocket.module.io.trace.get }
|
2017-09-21 23:58:15 +02:00
|
|
|
io.halt_and_catch_fire.foreach { _ := rocket.module.io.halt_and_catch_fire.get }
|
2017-03-27 11:45:37 +02:00
|
|
|
}
|
|
|
|
}
|