2014-09-13 03:06:41 +02:00
|
|
|
// See LICENSE for license details.
|
|
|
|
|
2012-03-25 00:56:59 +01:00
|
|
|
package rocket
|
|
|
|
|
|
|
|
import Chisel._
|
2016-06-28 22:15:39 +02:00
|
|
|
import uncore.tilelink._
|
|
|
|
import uncore.agents._
|
2016-09-03 00:59:16 +02:00
|
|
|
import uncore.converters._
|
2016-06-28 22:15:39 +02:00
|
|
|
import uncore.devices._
|
2012-11-18 02:24:08 +01:00
|
|
|
import Util._
|
2015-10-22 03:18:32 +02:00
|
|
|
import cde.{Parameters, Field}
|
2012-03-25 00:56:59 +01:00
|
|
|
|
2015-12-02 02:54:56 +01:00
|
|
|
case object BuildRoCC extends Field[Seq[RoccParameters]]
|
2016-06-14 01:18:38 +02:00
|
|
|
case object NCachedTileLinkPorts extends Field[Int]
|
|
|
|
case object NUncachedTileLinkPorts extends Field[Int]
|
2016-09-02 09:05:40 +02:00
|
|
|
case object TileId extends Field[Int]
|
2015-12-02 02:54:56 +01:00
|
|
|
|
|
|
|
case class RoccParameters(
|
|
|
|
opcodes: OpcodeSet,
|
|
|
|
generator: Parameters => RoCC,
|
2015-12-03 01:28:23 +01:00
|
|
|
nMemChannels: Int = 0,
|
2016-02-25 07:39:00 +01:00
|
|
|
nPTWPorts : Int = 0,
|
2016-01-14 20:37:58 +01:00
|
|
|
useFPU: Boolean = false)
|
2014-08-08 21:23:02 +02:00
|
|
|
|
2016-09-22 01:54:35 +02:00
|
|
|
case class TileBundleConfig(
|
|
|
|
nCachedTileLinkPorts: Int,
|
|
|
|
nUncachedTileLinkPorts: Int,
|
|
|
|
xLen: Int,
|
|
|
|
hasSlavePort: Boolean)
|
|
|
|
|
|
|
|
class TileIO(c: TileBundleConfig)(implicit p: Parameters) extends Bundle {
|
|
|
|
val cached = Vec(c.nCachedTileLinkPorts, new ClientTileLinkIO)
|
|
|
|
val uncached = Vec(c.nUncachedTileLinkPorts, new ClientUncachedTileLinkIO)
|
|
|
|
val hartid = UInt(INPUT, c.xLen)
|
|
|
|
val interrupts = new TileInterrupts().asInput
|
|
|
|
val slave = c.hasSlavePort.option(new ClientUncachedTileLinkIO().flip)
|
|
|
|
val resetVector = UInt(INPUT, c.xLen)
|
|
|
|
|
|
|
|
override def cloneType = new TileIO(c).asInstanceOf[this.type]
|
|
|
|
}
|
|
|
|
|
2016-07-22 02:56:52 +02:00
|
|
|
abstract class Tile(clockSignal: Clock = null, resetSignal: Bool = null)
|
|
|
|
(implicit p: Parameters) extends Module(Option(clockSignal), Option(resetSignal)) {
|
2016-06-14 01:18:38 +02:00
|
|
|
val nCachedTileLinkPorts = p(NCachedTileLinkPorts)
|
|
|
|
val nUncachedTileLinkPorts = p(NUncachedTileLinkPorts)
|
2015-10-21 00:02:24 +02:00
|
|
|
val dcacheParams = p.alterPartial({ case CacheName => "L1D" })
|
2016-09-22 01:54:35 +02:00
|
|
|
val bc = TileBundleConfig(
|
|
|
|
nCachedTileLinkPorts = nCachedTileLinkPorts,
|
|
|
|
nUncachedTileLinkPorts = nUncachedTileLinkPorts,
|
|
|
|
xLen = p(XLen),
|
|
|
|
hasSlavePort = p(DataScratchpadSize) > 0)
|
2016-06-14 01:18:38 +02:00
|
|
|
|
2016-09-22 01:54:35 +02:00
|
|
|
val io = new TileIO(bc)
|
2014-09-24 22:04:20 +02:00
|
|
|
}
|
|
|
|
|
2016-07-22 02:56:52 +02:00
|
|
|
class RocketTile(clockSignal: Clock = null, resetSignal: Bool = null)
|
|
|
|
(implicit p: Parameters) extends Tile(clockSignal, resetSignal)(p) {
|
2016-06-14 01:18:38 +02:00
|
|
|
val buildRocc = p(BuildRoCC)
|
|
|
|
val usingRocc = !buildRocc.isEmpty
|
|
|
|
val nRocc = buildRocc.size
|
|
|
|
val nFPUPorts = buildRocc.filter(_.useFPU).size
|
|
|
|
|
2016-08-10 00:24:59 +02:00
|
|
|
val core = Module(new Rocket)
|
|
|
|
val icache = Module(new Frontend()(p.alterPartial({ case CacheName => "L1I" })))
|
2016-08-18 01:53:39 +02:00
|
|
|
val dcache = HellaCache(p(DCacheKey))(dcacheParams)
|
2014-08-08 21:23:02 +02:00
|
|
|
|
2016-05-22 01:56:17 +02:00
|
|
|
val ptwPorts = collection.mutable.ArrayBuffer(icache.io.ptw, dcache.ptw)
|
2016-03-25 22:16:56 +01:00
|
|
|
val dcPorts = collection.mutable.ArrayBuffer(core.io.dmem)
|
|
|
|
val uncachedArbPorts = collection.mutable.ArrayBuffer(icache.io.mem)
|
|
|
|
val uncachedPorts = collection.mutable.ArrayBuffer[ClientUncachedTileLinkIO]()
|
2016-05-22 01:56:17 +02:00
|
|
|
val cachedPorts = collection.mutable.ArrayBuffer(dcache.mem)
|
2016-09-14 01:25:31 +02:00
|
|
|
core.io.interrupts := io.interrupts
|
|
|
|
core.io.hartid := io.hartid
|
2015-08-02 06:11:25 +02:00
|
|
|
icache.io.cpu <> core.io.imem
|
Allow reset vector to be set dynamically
A chip's power-up sequence, or awake-from-sleep sequence, may wish to
set the reset PC based upon dynamic properties, e.g., the settings of
external pins. Support this by passing the reset vector to the Coreplex.
ExampleTop simply hard-wires the reset vector, as was the case before.
Additionally, allow MTVEC to *not* be reset. In most cases, including
riscv-tests, pk, and bbl, overriding MTVEC is one of the first things
that the boot sequence does. So the reset value is superfluous.
2016-09-20 01:45:57 +02:00
|
|
|
icache.io.resetVector := io.resetVector
|
2013-09-15 07:34:53 +02:00
|
|
|
|
2016-08-17 09:57:35 +02:00
|
|
|
val fpuOpt = p(FPUKey).map(cfg => Module(new FPU(cfg)))
|
2015-12-01 19:22:31 +01:00
|
|
|
fpuOpt.foreach(fpu => core.io.fpu <> fpu.io)
|
2015-07-22 02:10:56 +02:00
|
|
|
|
2016-03-25 22:16:56 +01:00
|
|
|
if (usingRocc) {
|
2015-11-26 01:02:27 +01:00
|
|
|
val respArb = Module(new RRArbiter(new RoCCResponse, nRocc))
|
|
|
|
core.io.rocc.resp <> respArb.io.out
|
|
|
|
|
2015-12-02 02:54:56 +01:00
|
|
|
val roccOpcodes = buildRocc.map(_.opcodes)
|
2015-11-26 01:02:27 +01:00
|
|
|
val cmdRouter = Module(new RoccCommandRouter(roccOpcodes))
|
|
|
|
cmdRouter.io.in <> core.io.rocc.cmd
|
|
|
|
|
2015-12-02 03:14:58 +01:00
|
|
|
val roccs = buildRocc.zipWithIndex.map { case (accelParams, i) =>
|
2016-01-14 20:37:58 +01:00
|
|
|
val rocc = accelParams.generator(p.alterPartial({
|
|
|
|
case RoccNMemChannels => accelParams.nMemChannels
|
2016-02-25 07:39:00 +01:00
|
|
|
case RoccNPTWPorts => accelParams.nPTWPorts
|
2016-01-14 20:37:58 +01:00
|
|
|
}))
|
2015-12-02 03:14:58 +01:00
|
|
|
val dcIF = Module(new SimpleHellaCacheIF()(dcacheParams))
|
|
|
|
rocc.io.cmd <> cmdRouter.io.out(i)
|
|
|
|
rocc.io.exception := core.io.rocc.exception
|
|
|
|
dcIF.io.requestor <> rocc.io.mem
|
2016-03-25 22:16:56 +01:00
|
|
|
dcPorts += dcIF.io.cache
|
|
|
|
uncachedArbPorts += rocc.io.autl
|
2015-12-02 03:14:58 +01:00
|
|
|
rocc
|
2015-11-26 01:02:27 +01:00
|
|
|
}
|
|
|
|
|
2015-12-02 01:48:05 +01:00
|
|
|
if (nFPUPorts > 0) {
|
|
|
|
fpuOpt.foreach { fpu =>
|
|
|
|
val fpArb = Module(new InOrderArbiter(new FPInput, new FPResult, nFPUPorts))
|
2015-12-02 03:14:58 +01:00
|
|
|
val fp_roccs = roccs.zip(buildRocc)
|
|
|
|
.filter { case (_, params) => params.useFPU }
|
|
|
|
.map { case (rocc, _) => rocc.io }
|
|
|
|
fpArb.io.in_req <> fp_roccs.map(_.fpu_req)
|
2015-12-02 01:48:05 +01:00
|
|
|
fp_roccs.zip(fpArb.io.in_resp).foreach {
|
2015-12-02 03:14:58 +01:00
|
|
|
case (rocc, fpu_resp) => rocc.fpu_resp <> fpu_resp
|
2015-12-02 01:48:05 +01:00
|
|
|
}
|
|
|
|
fpu.io.cp_req <> fpArb.io.out_req
|
|
|
|
fpArb.io.out_resp <> fpu.io.cp_resp
|
2015-12-01 19:22:31 +01:00
|
|
|
}
|
2015-12-02 01:48:05 +01:00
|
|
|
}
|
2015-12-01 19:22:31 +01:00
|
|
|
|
2015-11-26 01:02:27 +01:00
|
|
|
core.io.rocc.busy := cmdRouter.io.busy || roccs.map(_.io.busy).reduce(_ || _)
|
|
|
|
core.io.rocc.interrupt := roccs.map(_.io.interrupt).reduce(_ || _)
|
|
|
|
respArb.io.in <> roccs.map(rocc => Queue(rocc.io.resp))
|
|
|
|
|
2016-03-25 22:16:56 +01:00
|
|
|
ptwPorts ++= roccs.flatMap(_.io.ptw)
|
|
|
|
uncachedPorts ++= roccs.flatMap(_.io.utl)
|
|
|
|
}
|
|
|
|
|
2016-03-29 07:53:47 +02:00
|
|
|
val uncachedArb = Module(new ClientUncachedTileLinkIOArbiter(uncachedArbPorts.size))
|
2016-03-25 22:16:56 +01:00
|
|
|
uncachedArb.io.in <> uncachedArbPorts
|
|
|
|
uncachedArb.io.out +=: uncachedPorts
|
|
|
|
|
|
|
|
// Connect the caches and RoCC to the outer memory system
|
|
|
|
io.uncached <> uncachedPorts
|
|
|
|
io.cached <> cachedPorts
|
|
|
|
// TODO remove nCached/nUncachedTileLinkPorts parameters and these assertions
|
|
|
|
require(uncachedPorts.size == nUncachedTileLinkPorts)
|
|
|
|
require(cachedPorts.size == nCachedTileLinkPorts)
|
|
|
|
|
2016-03-25 22:17:25 +01:00
|
|
|
if (p(UseVM)) {
|
|
|
|
val ptw = Module(new PTW(ptwPorts.size)(dcacheParams))
|
|
|
|
ptw.io.requestor <> ptwPorts
|
|
|
|
ptw.io.mem +=: dcPorts
|
|
|
|
core.io.ptw <> ptw.io.dpath
|
|
|
|
}
|
2016-03-25 22:16:56 +01:00
|
|
|
|
2016-09-03 00:59:16 +02:00
|
|
|
io.slave foreach { case slavePort =>
|
|
|
|
val adapter = Module(new ScratchpadSlavePort()(dcacheParams))
|
|
|
|
adapter.io.tl <> TileLinkFragmenter(slavePort)
|
|
|
|
adapter.io.dmem +=: dcPorts
|
|
|
|
}
|
|
|
|
|
2016-08-09 22:08:00 +02:00
|
|
|
require(dcPorts.size == core.dcacheArbPorts)
|
2016-03-25 22:16:56 +01:00
|
|
|
val dcArb = Module(new HellaCacheArbiter(dcPorts.size)(dcacheParams))
|
|
|
|
dcArb.io.requestor <> dcPorts
|
2016-05-22 01:56:17 +02:00
|
|
|
dcache.cpu <> dcArb.io.mem
|
2015-12-02 05:41:58 +01:00
|
|
|
|
2016-08-17 09:57:35 +02:00
|
|
|
if (nFPUPorts == 0) {
|
2015-12-02 05:41:58 +01:00
|
|
|
fpuOpt.foreach { fpu =>
|
|
|
|
fpu.io.cp_req.valid := Bool(false)
|
|
|
|
fpu.io.cp_resp.ready := Bool(false)
|
|
|
|
}
|
|
|
|
}
|
2012-03-25 00:56:59 +01:00
|
|
|
}
|