1
0
rocket-chip/src/main/scala/rocket/Tile.scala

165 lines
5.8 KiB
Scala
Raw Normal View History

// See LICENSE.SiFive for license details.
// See LICENSE.Berkeley for license details.
2014-09-13 03:06:41 +02:00
package rocket
import Chisel._
2016-10-27 04:02:04 +02:00
import diplomacy._
import uncore.tilelink._
2016-10-27 04:02:04 +02:00
import uncore.tilelink2._
import uncore.util.{CacheName, CacheBlockBytes}
import uncore.converters._
import uncore.devices._
import util._
import config._
2016-11-11 00:56:42 +01:00
import scala.collection.mutable.ListBuffer
2015-12-02 02:54:56 +01:00
case object BuildRoCC extends Field[Seq[RoccParameters]]
case class RoccParameters(
opcodes: OpcodeSet,
generator: Parameters => RoCC,
nMemChannels: Int = 0,
2016-02-25 07:39:00 +01:00
nPTWPorts : Int = 0,
useFPU: Boolean = false)
class RocketTile(tileId: Int)(implicit p: Parameters) extends LazyModule {
val coreParams = p.alterPartial {
case TLCacheEdge => cachedOut.edgesOut(0)
}
val dcacheParams = coreParams.alterPartial({
2016-11-18 21:02:33 +01:00
case CacheName => CacheName("L1D")
case TLId => "L1toL2"
})
val icacheParams = coreParams.alterPartial({
2016-11-18 21:02:33 +01:00
case CacheName => CacheName("L1I")
case TLId => "L1toL2"
})
2016-11-11 00:56:42 +01:00
val slaveNode = if (p(DataScratchpadSize) == 0) None else Some(TLInputNode())
2016-10-27 04:54:47 +02:00
val scratch = if (p(DataScratchpadSize) == 0) None else Some(LazyModule(new ScratchpadSlavePort()(dcacheParams)))
def findScratch() = scratch.map { s =>
val finalNode = uncachedOut.edgesOut(0).manager.managers.find(_.nodePath.last == s.node)
require (finalNode.isDefined, "Could not find the scratch pad; not reachable via icache?")
require (finalNode.get.address.size == 1, "Scratchpad address space was fragmented!")
finalNode.get.address(0)
}
val dcache = HellaCache(p(DCacheKey), findScratch)(dcacheParams)
val frontend = LazyModule(new Frontend()(icacheParams))
val ucLegacy = LazyModule(new TLLegacy()(icacheParams))
val tileXbar = LazyModule(new TLXbar)
tileXbar.node := TLHintHandler()(ucLegacy.node)
tileXbar.node := frontend.node
2016-11-11 00:56:42 +01:00
val cachedOut = TLOutputNode()
val uncachedOut = TLOutputNode()
cachedOut := dcache.node
uncachedOut := tileXbar.node
val masterNodes = List(cachedOut, uncachedOut)
2016-11-11 00:56:42 +01:00
(slaveNode zip scratch) foreach { case (node, lm) => lm.node := TLFragmenter(p(XLen)/8, p(CacheBlockBytes))(node) }
2016-11-11 00:56:42 +01:00
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val cached = cachedOut.bundleOut
val uncached = uncachedOut.bundleOut
2016-11-11 00:56:42 +01:00
val slave = slaveNode.map(_.bundleIn)
val hartid = UInt(INPUT, p(XLen))
val interrupts = new TileInterrupts()(coreParams).asInput
2016-11-11 00:56:42 +01:00
val resetVector = UInt(INPUT, p(XLen))
}
2016-10-27 04:54:47 +02:00
2016-10-27 04:02:04 +02:00
val buildRocc = p(BuildRoCC)
val usingRocc = !buildRocc.isEmpty
val nRocc = buildRocc.size
val nFPUPorts = buildRocc.filter(_.useFPU).size
val core = Module(new Rocket()(dcacheParams))
2016-11-11 00:56:42 +01:00
val ptwPorts = ListBuffer(frontend.module.io.ptw, dcache.module.io.ptw)
2016-11-11 00:56:42 +01:00
val dcPorts = ListBuffer(core.io.dmem)
val uncachedArbPorts = ListBuffer[ClientUncachedTileLinkIO]()
2016-10-27 04:02:04 +02:00
core.io.interrupts := io.interrupts
core.io.hartid := io.hartid
frontend.module.io.cpu <> core.io.imem
frontend.module.io.resetVector := io.resetVector
2016-10-27 04:02:04 +02:00
val fpuOpt = p(FPUKey).map(cfg => Module(new FPU(cfg)(coreParams)))
2016-10-27 04:02:04 +02:00
fpuOpt.foreach(fpu => core.io.fpu <> fpu.io)
if (usingRocc) {
val respArb = Module(new RRArbiter(new RoCCResponse()(coreParams), nRocc))
2016-10-27 04:02:04 +02:00
core.io.rocc.resp <> respArb.io.out
val roccOpcodes = buildRocc.map(_.opcodes)
val cmdRouter = Module(new RoccCommandRouter(roccOpcodes)(coreParams))
2016-10-27 04:02:04 +02:00
cmdRouter.io.in <> core.io.rocc.cmd
val roccs = buildRocc.zipWithIndex.map { case (accelParams, i) =>
val rocc = accelParams.generator(dcacheParams.alterPartial({
2016-10-27 04:02:04 +02:00
case RoccNMemChannels => accelParams.nMemChannels
case RoccNPTWPorts => accelParams.nPTWPorts
}))
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
dcPorts += dcIF.io.cache
uncachedArbPorts += rocc.io.autl
rocc
}
if (nFPUPorts > 0) {
fpuOpt.foreach { fpu =>
val fpArb = Module(new InOrderArbiter(new FPInput()(coreParams), new FPResult()(coreParams), nFPUPorts))
2016-10-27 04:02:04 +02: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)
fp_roccs.zip(fpArb.io.in_resp).foreach {
case (rocc, fpu_resp) => rocc.fpu_resp <> fpu_resp
}
fpu.io.cp_req <> fpArb.io.out_req
fpArb.io.out_resp <> fpu.io.cp_resp
}
2015-12-01 19:22:31 +01:00
}
2016-10-27 04:02:04 +02: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-10-27 04:02:04 +02:00
ptwPorts ++= roccs.flatMap(_.io.ptw)
2016-11-11 00:56:42 +01:00
uncachedArbPorts ++= roccs.flatMap(_.io.utl) // TODO no difference between io.autl and io.utl for now
val uncachedArb = Module(new ClientUncachedTileLinkIOArbiter(uncachedArbPorts.size)(icacheParams))
uncachedArb.io.in <> uncachedArbPorts
ucLegacy.module.io.legacy <> uncachedArb.io.out
} else {
ucLegacy.module.io.legacy.acquire.valid := Bool(false)
ucLegacy.module.io.legacy.grant.ready := Bool(false)
}
2016-10-27 04:02:04 +02: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-10-27 04:54:47 +02:00
scratch.foreach { lm => lm.module.io.dmem +=: dcPorts }
2016-10-27 04:02:04 +02:00
require(dcPorts.size == core.dcacheArbPorts)
val dcArb = Module(new HellaCacheArbiter(dcPorts.size)(dcacheParams))
dcArb.io.requestor <> dcPorts
2016-11-11 00:56:42 +01:00
dcache.module.io.cpu <> dcArb.io.mem
2016-10-27 04:02:04 +02:00
if (nFPUPorts == 0) {
fpuOpt.foreach { fpu =>
fpu.io.cp_req.valid := Bool(false)
fpu.io.cp_resp.ready := Bool(false)
}
}
}
}