Refactor Tile to use cake pattern (#502)
* [rocket] Refactor Tile into cake pattern with traits * [rocket] cacheDataBits &etc in HasCoreParameters * [rocket] pass TLEdgeOut implicitly rather than relying on val edge in HasCoreParameters * [rocket] frontend and icache now diplomatic * [rocket] file name capitalization * [rocket] re-add hook for inserting externally-defined Cores * [rocket] add FPUCoreIO * [groundtest] move TL1 Config instances to where they are used * [unittest] remove legacy unit tests * [groundtest] remove legacy device tests
This commit is contained in:
parent
622e311962
commit
74b6a8d02b
@ -69,7 +69,7 @@ endif
|
|||||||
|
|
||||||
ifeq ($(SUITE),UnittestSuite)
|
ifeq ($(SUITE),UnittestSuite)
|
||||||
PROJECT=unittest
|
PROJECT=unittest
|
||||||
CONFIGS=JunctionsUnitTestConfig UncoreUnitTestConfig TLSimpleUnitTestConfig TLWidthUnitTestConfig TLXbarUnitTestConfig
|
CONFIGS=UncoreUnitTestConfig TLSimpleUnitTestConfig TLWidthUnitTestConfig TLXbarUnitTestConfig
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(SUITE), JtagDtmSuite)
|
ifeq ($(SUITE), JtagDtmSuite)
|
||||||
|
@ -4,16 +4,10 @@ package coreplex
|
|||||||
|
|
||||||
import Chisel._
|
import Chisel._
|
||||||
import config._
|
import config._
|
||||||
import junctions._
|
|
||||||
import diplomacy._
|
import diplomacy._
|
||||||
import uncore.tilelink._
|
import rocket.{TileInterrupts, XLen}
|
||||||
import uncore.tilelink2._
|
import uncore.tilelink2._
|
||||||
import uncore.coherence._
|
|
||||||
import uncore.agents._
|
|
||||||
import uncore.devices._
|
|
||||||
import uncore.util._
|
import uncore.util._
|
||||||
import uncore.converters._
|
|
||||||
import rocket._
|
|
||||||
import util._
|
import util._
|
||||||
|
|
||||||
/** Widths of various points in the SoC */
|
/** Widths of various points in the SoC */
|
||||||
@ -56,102 +50,17 @@ trait HasCoreplexParameters {
|
|||||||
case class CoreplexParameters(implicit val p: Parameters) extends HasCoreplexParameters
|
case class CoreplexParameters(implicit val p: Parameters) extends HasCoreplexParameters
|
||||||
|
|
||||||
abstract class BareCoreplex(implicit p: Parameters) extends LazyModule
|
abstract class BareCoreplex(implicit p: Parameters) extends LazyModule
|
||||||
|
|
||||||
abstract class BareCoreplexBundle[+L <: BareCoreplex](_outer: L) extends GenericParameterizedBundle(_outer) {
|
abstract class BareCoreplexBundle[+L <: BareCoreplex](_outer: L) extends GenericParameterizedBundle(_outer) {
|
||||||
val outer = _outer
|
val outer = _outer
|
||||||
implicit val p = outer.p
|
implicit val p = outer.p
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class BareCoreplexModule[+L <: BareCoreplex, +B <: BareCoreplexBundle[L]](_outer: L, _io: () => B) extends LazyModuleImp(_outer) {
|
abstract class BareCoreplexModule[+L <: BareCoreplex, +B <: BareCoreplexBundle[L]](_outer: L, _io: () => B) extends LazyModuleImp(_outer) {
|
||||||
val outer = _outer
|
val outer = _outer
|
||||||
val io = _io ()
|
val io = _io ()
|
||||||
}
|
}
|
||||||
|
|
||||||
trait CoreplexNetwork extends HasCoreplexParameters {
|
|
||||||
val module: CoreplexNetworkModule
|
|
||||||
|
|
||||||
val l1tol2 = LazyModule(new TLXbar)
|
|
||||||
val l1tol2_beatBytes = l1tol2Config.beatBytes
|
|
||||||
val l1tol2_lineBytes = p(CacheBlockBytes)
|
|
||||||
|
|
||||||
val cbus = LazyModule(new TLXbar)
|
|
||||||
val cbus_beatBytes = cbusConfig.beatBytes
|
|
||||||
val cbus_lineBytes = l1tol2_lineBytes
|
|
||||||
|
|
||||||
val intBar = LazyModule(new IntXbar)
|
|
||||||
|
|
||||||
val mmio = TLOutputNode()
|
|
||||||
val mmioInt = IntInputNode()
|
|
||||||
|
|
||||||
intBar.intnode := mmioInt
|
|
||||||
|
|
||||||
cbus.node :=
|
|
||||||
TLAtomicAutomata(arithmetic = true)( // disable once TLB uses TL2 metadata
|
|
||||||
TLWidthWidget(l1tol2_beatBytes)(
|
|
||||||
TLBuffer()(
|
|
||||||
l1tol2.node)))
|
|
||||||
|
|
||||||
mmio :=
|
|
||||||
TLBuffer()(
|
|
||||||
TLWidthWidget(l1tol2_beatBytes)(
|
|
||||||
l1tol2.node))
|
|
||||||
}
|
|
||||||
|
|
||||||
trait CoreplexNetworkBundle extends HasCoreplexParameters {
|
|
||||||
val outer: CoreplexNetwork
|
|
||||||
|
|
||||||
val mmio = outer.mmio.bundleOut
|
|
||||||
val interrupts = outer.mmioInt.bundleIn
|
|
||||||
}
|
|
||||||
|
|
||||||
trait CoreplexNetworkModule extends HasCoreplexParameters {
|
|
||||||
val outer: CoreplexNetwork
|
|
||||||
val io: CoreplexNetworkBundle
|
|
||||||
|
|
||||||
println("\nGenerated Address Map")
|
|
||||||
for (manager <- outer.l1tol2.node.edgesIn(0).manager.managers) {
|
|
||||||
val prot = (if (manager.supportsGet) "R" else "") +
|
|
||||||
(if (manager.supportsPutFull) "W" else "") +
|
|
||||||
(if (manager.executable) "X" else "") +
|
|
||||||
(if (manager.supportsAcquire) " [C]" else "")
|
|
||||||
manager.address.foreach { a =>
|
|
||||||
println(f"\t${manager.name}%s ${a.base}%x - ${a.base+a.mask+1}%x, $prot")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
trait BankedL2CoherenceManagers extends CoreplexNetwork {
|
|
||||||
val module: BankedL2CoherenceManagersModule
|
|
||||||
|
|
||||||
require (isPow2(l2Config.nBanksPerChannel))
|
|
||||||
require (isPow2(l1tol2_lineBytes))
|
|
||||||
|
|
||||||
val mem = Seq.fill(l2Config.nMemoryChannels) {
|
|
||||||
val bankBar = LazyModule(new TLXbar)
|
|
||||||
val output = TLOutputNode()
|
|
||||||
|
|
||||||
output := bankBar.node
|
|
||||||
val mask = ~BigInt((l2Config.nBanksPerChannel-1) * l1tol2_lineBytes)
|
|
||||||
for (i <- 0 until l2Config.nBanksPerChannel) {
|
|
||||||
val (in, out) = l2Config.coherenceManager(p)
|
|
||||||
in := TLFilter(AddressSet(i * l1tol2_lineBytes, mask))(l1tol2.node)
|
|
||||||
bankBar.node := out
|
|
||||||
}
|
|
||||||
|
|
||||||
output
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
trait BankedL2CoherenceManagersBundle extends CoreplexNetworkBundle {
|
|
||||||
val outer: BankedL2CoherenceManagers
|
|
||||||
|
|
||||||
require (l2Config.nMemoryChannels <= 1, "Seq in Chisel Bundle needed to support > 1") // !!!
|
|
||||||
val mem = outer.mem.map(_.bundleOut).toList.headOption // .headOption should be removed !!!
|
|
||||||
}
|
|
||||||
|
|
||||||
trait BankedL2CoherenceManagersModule extends CoreplexNetworkModule {
|
|
||||||
val outer: BankedL2CoherenceManagers
|
|
||||||
val io: BankedL2CoherenceManagersBundle
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class BaseCoreplex(implicit p: Parameters) extends BareCoreplex
|
abstract class BaseCoreplex(implicit p: Parameters) extends BareCoreplex
|
||||||
with CoreplexNetwork
|
with CoreplexNetwork
|
||||||
with BankedL2CoherenceManagers {
|
with BankedL2CoherenceManagers {
|
||||||
|
56
src/main/scala/coreplex/BaseTile.scala
Normal file
56
src/main/scala/coreplex/BaseTile.scala
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
// See LICENSE.SiFive for license details.
|
||||||
|
|
||||||
|
package coreplex
|
||||||
|
|
||||||
|
import Chisel._
|
||||||
|
import config._
|
||||||
|
import diplomacy._
|
||||||
|
import rocket.{TileInterrupts, XLen}
|
||||||
|
import uncore.tilelink2._
|
||||||
|
import util.GenericParameterizedBundle
|
||||||
|
|
||||||
|
abstract class BareTile(implicit p: Parameters) extends LazyModule
|
||||||
|
|
||||||
|
abstract class BareTileBundle[+L <: BareTile](_outer: L) extends GenericParameterizedBundle(_outer) {
|
||||||
|
val outer = _outer
|
||||||
|
implicit val p = outer.p
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class BareTileModule[+L <: BareTile, +B <: BareTileBundle[L]](_outer: L, _io: () => B) extends LazyModuleImp(_outer) {
|
||||||
|
val outer = _outer
|
||||||
|
val io = _io ()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Uses a tile-internal crossbar to provide a single TileLink master port
|
||||||
|
trait TileNetwork {
|
||||||
|
implicit val p: Parameters
|
||||||
|
val module: TileNetworkModule
|
||||||
|
val l1backend = LazyModule(new TLXbar)
|
||||||
|
val masterNodes = List(TLOutputNode())
|
||||||
|
masterNodes.head := l1backend.node
|
||||||
|
}
|
||||||
|
|
||||||
|
trait TileNetworkBundle {
|
||||||
|
val outer: TileNetwork
|
||||||
|
val master = outer.masterNodes.head.bundleOut
|
||||||
|
}
|
||||||
|
|
||||||
|
trait TileNetworkModule {
|
||||||
|
val outer: TileNetwork
|
||||||
|
val io: TileNetworkBundle
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class BaseTile(implicit p: Parameters) extends BareTile
|
||||||
|
with TileNetwork {
|
||||||
|
override lazy val module = new BaseTileModule(this, () => new BaseTileBundle(this))
|
||||||
|
}
|
||||||
|
|
||||||
|
class BaseTileBundle[+L <: BaseTile](_outer: L) extends BareTileBundle(_outer)
|
||||||
|
with TileNetworkBundle {
|
||||||
|
val hartid = UInt(INPUT, p(XLen))
|
||||||
|
val interrupts = new TileInterrupts()(p).asInput
|
||||||
|
val resetVector = UInt(INPUT, p(XLen))
|
||||||
|
}
|
||||||
|
|
||||||
|
class BaseTileModule[+L <: BaseTile, +B <: BaseTileBundle[L]](_outer: L, _io: () => B) extends BareTileModule(_outer, _io)
|
||||||
|
with TileNetworkModule
|
@ -6,14 +6,10 @@ package coreplex
|
|||||||
import Chisel._
|
import Chisel._
|
||||||
import config._
|
import config._
|
||||||
import diplomacy._
|
import diplomacy._
|
||||||
import junctions.PAddrBits
|
|
||||||
import rocket._
|
import rocket._
|
||||||
import uncore.tilelink._
|
|
||||||
import uncore.tilelink2._
|
|
||||||
import uncore.coherence._
|
|
||||||
import uncore.agents._
|
|
||||||
import uncore.devices._
|
|
||||||
import uncore.converters._
|
import uncore.converters._
|
||||||
|
import uncore.devices._
|
||||||
|
import uncore.tilelink2._
|
||||||
import uncore.util._
|
import uncore.util._
|
||||||
import util._
|
import util._
|
||||||
|
|
||||||
@ -44,15 +40,8 @@ class BaseCoreplexConfig extends Config ((site, here, up) => {
|
|||||||
//L1DataCache
|
//L1DataCache
|
||||||
case DCacheKey => DCacheConfig(nMSHRs = 2)
|
case DCacheKey => DCacheConfig(nMSHRs = 2)
|
||||||
case DataScratchpadSize => 0
|
case DataScratchpadSize => 0
|
||||||
//L2 Memory System Params
|
|
||||||
case AmoAluOperandBits => site(XLen)
|
|
||||||
case NAcquireTransactors => 7
|
|
||||||
case L2StoreDataQueueDepth => 1
|
|
||||||
case L2DirectoryRepresentation => new NullRepresentation(site(NTiles))
|
|
||||||
//Tile Constants
|
//Tile Constants
|
||||||
case BuildRoCC => Nil
|
case BuildRoCC => Nil
|
||||||
case RoccNMemChannels => site(BuildRoCC).map(_.nMemChannels).foldLeft(0)(_ + _)
|
|
||||||
case RoccNPTWPorts => site(BuildRoCC).map(_.nPTWPorts).foldLeft(0)(_ + _)
|
|
||||||
//Rocket Core Constants
|
//Rocket Core Constants
|
||||||
case CoreInstBits => if (site(UseCompressed)) 16 else 32
|
case CoreInstBits => if (site(UseCompressed)) 16 else 32
|
||||||
case FetchWidth => if (site(UseCompressed)) 2 else 1
|
case FetchWidth => if (site(UseCompressed)) 2 else 1
|
||||||
@ -76,37 +65,15 @@ class BaseCoreplexConfig extends Config ((site, here, up) => {
|
|||||||
case MtvecInit => Some(BigInt(0))
|
case MtvecInit => Some(BigInt(0))
|
||||||
case MtvecWritable => true
|
case MtvecWritable => true
|
||||||
//Uncore Paramters
|
//Uncore Paramters
|
||||||
case LNEndpoints => site(TLKey(site(TLId))).nManagers + site(TLKey(site(TLId))).nClients
|
|
||||||
case LNHeaderBits => log2Ceil(site(TLKey(site(TLId))).nManagers) +
|
|
||||||
log2Up(site(TLKey(site(TLId))).nClients)
|
|
||||||
case CBusConfig => TLBusConfig(beatBytes = site(XLen)/8)
|
case CBusConfig => TLBusConfig(beatBytes = site(XLen)/8)
|
||||||
case L1toL2Config => TLBusConfig(beatBytes = site(XLen)/8) // increase for more PCIe bandwidth
|
case L1toL2Config => TLBusConfig(beatBytes = site(XLen)/8) // increase for more PCIe bandwidth
|
||||||
case TLKey("L1toL2") => {
|
|
||||||
val useMEI = site(NTiles) <= 1
|
|
||||||
TileLinkParameters(
|
|
||||||
coherencePolicy = (
|
|
||||||
if (useMEI) new MEICoherence(site(L2DirectoryRepresentation))
|
|
||||||
else new MESICoherence(site(L2DirectoryRepresentation))),
|
|
||||||
nManagers = site(BankedL2Config).nBanks + 1 /* MMIO */,
|
|
||||||
nCachingClients = 1,
|
|
||||||
nCachelessClients = 1,
|
|
||||||
maxClientXacts = List(
|
|
||||||
// L1 cache
|
|
||||||
site(DCacheKey).nMSHRs + 1 /* IOMSHR */,
|
|
||||||
// RoCC
|
|
||||||
if (site(BuildRoCC).isEmpty) 1 else site(RoccMaxTaggedMemXacts)).max,
|
|
||||||
maxClientsPerPort = if (site(BuildRoCC).isEmpty) 1 else 2,
|
|
||||||
maxManagerXacts = site(NAcquireTransactors) + 2,
|
|
||||||
dataBeats = (8 * site(CacheBlockBytes)) / site(XLen),
|
|
||||||
dataBits = site(CacheBlockBytes)*8)
|
|
||||||
}
|
|
||||||
case BootROMFile => "./bootrom/bootrom.img"
|
case BootROMFile => "./bootrom/bootrom.img"
|
||||||
case NTiles => 1
|
case NTiles => site(RocketConfigs).size
|
||||||
|
case RocketConfigs => List(RocketConfig(site(XLen)))
|
||||||
|
case BuildCore => (c: RocketConfig, p: Parameters) => new Rocket(c)(p)
|
||||||
case BroadcastConfig => BroadcastConfig()
|
case BroadcastConfig => BroadcastConfig()
|
||||||
case BankedL2Config => BankedL2Config()
|
case BankedL2Config => BankedL2Config()
|
||||||
case CacheBlockBytes => 64
|
case CacheBlockBytes => 64
|
||||||
case CacheBlockOffsetBits => log2Up(site(CacheBlockBytes))
|
|
||||||
case EnableL2Logging => false
|
|
||||||
})
|
})
|
||||||
|
|
||||||
class WithNCores(n: Int) extends Config((site, here, up) => {
|
class WithNCores(n: Int) extends Config((site, here, up) => {
|
||||||
@ -185,7 +152,7 @@ class WithStatelessBridge extends Config((site, here, up) => {
|
|||||||
case DCacheKey => up(DCacheKey, site).copy(nMSHRs = 0)
|
case DCacheKey => up(DCacheKey, site).copy(nMSHRs = 0)
|
||||||
})
|
})
|
||||||
|
|
||||||
class WithL2Capacity(size_kb: Int) extends Config(Parameters.empty)
|
class WithL2Capacity(size_kb: Int) extends Config(Parameters.empty) // TODO
|
||||||
|
|
||||||
class WithNL2Ways(n: Int) extends Config((site, here, up) => {
|
class WithNL2Ways(n: Int) extends Config((site, here, up) => {
|
||||||
case CacheName("L2") => up(CacheName("L2"), site).copy(nWays = n)
|
case CacheName("L2") => up(CacheName("L2"), site).copy(nWays = n)
|
||||||
@ -205,7 +172,6 @@ class WithSmallCores extends Config((site, here, up) => {
|
|||||||
case FPUKey => None
|
case FPUKey => None
|
||||||
case UseVM => false
|
case UseVM => false
|
||||||
case BtbKey => BtbParameters(nEntries = 0)
|
case BtbKey => BtbParameters(nEntries = 0)
|
||||||
case NAcquireTransactors => 2
|
|
||||||
case CacheName("L1D") => up(CacheName("L1D"), site).copy(nSets = 64, nWays = 1, nTLBEntries = 4)
|
case CacheName("L1D") => up(CacheName("L1D"), site).copy(nSets = 64, nWays = 1, nTLBEntries = 4)
|
||||||
case CacheName("L1I") => up(CacheName("L1I"), site).copy(nSets = 64, nWays = 1, nTLBEntries = 4)
|
case CacheName("L1I") => up(CacheName("L1I"), site).copy(nSets = 64, nWays = 1, nTLBEntries = 4)
|
||||||
case DCacheKey => up(DCacheKey, site).copy(nMSHRs = 0)
|
case DCacheKey => up(DCacheKey, site).copy(nMSHRs = 0)
|
||||||
|
@ -4,69 +4,43 @@ package coreplex
|
|||||||
|
|
||||||
import Chisel._
|
import Chisel._
|
||||||
import config._
|
import config._
|
||||||
import junctions._
|
|
||||||
import diplomacy._
|
import diplomacy._
|
||||||
import uncore.tilelink._
|
|
||||||
import uncore.tilelink2._
|
|
||||||
import uncore.util._
|
|
||||||
import util._
|
import util._
|
||||||
import rocket._
|
|
||||||
|
|
||||||
/////
|
|
||||||
|
|
||||||
trait L2MasterPort extends CoreplexNetwork
|
|
||||||
{
|
|
||||||
val module: L2MasterPortModule
|
|
||||||
val l2in = TLInputNode()
|
|
||||||
l1tol2.node := l2in
|
|
||||||
}
|
|
||||||
|
|
||||||
trait L2MasterPortBundle extends CoreplexNetworkBundle
|
|
||||||
{
|
|
||||||
val outer: L2MasterPort
|
|
||||||
val l2in = outer.l2in.bundleIn
|
|
||||||
}
|
|
||||||
|
|
||||||
trait L2MasterPortModule extends CoreplexNetworkModule
|
|
||||||
{
|
|
||||||
val outer: L2MasterPort
|
|
||||||
val io: L2MasterPortBundle
|
|
||||||
}
|
|
||||||
|
|
||||||
/////
|
/////
|
||||||
|
|
||||||
class DefaultCoreplex(implicit p: Parameters) extends BaseCoreplex
|
class DefaultCoreplex(implicit p: Parameters) extends BaseCoreplex
|
||||||
with CoreplexRISCVPlatform
|
with CoreplexRISCVPlatform
|
||||||
with L2MasterPort
|
with HasL2MasterPort
|
||||||
with RocketTiles {
|
with HasSynchronousRocketTiles {
|
||||||
override lazy val module = new DefaultCoreplexModule(this, () => new DefaultCoreplexBundle(this))
|
override lazy val module = new DefaultCoreplexModule(this, () => new DefaultCoreplexBundle(this))
|
||||||
}
|
}
|
||||||
|
|
||||||
class DefaultCoreplexBundle[+L <: DefaultCoreplex](_outer: L) extends BaseCoreplexBundle(_outer)
|
class DefaultCoreplexBundle[+L <: DefaultCoreplex](_outer: L) extends BaseCoreplexBundle(_outer)
|
||||||
with CoreplexRISCVPlatformBundle
|
with CoreplexRISCVPlatformBundle
|
||||||
with L2MasterPortBundle
|
with HasL2MasterPortBundle
|
||||||
with RocketTilesBundle
|
with HasSynchronousRocketTilesBundle
|
||||||
|
|
||||||
class DefaultCoreplexModule[+L <: DefaultCoreplex, +B <: DefaultCoreplexBundle[L]](_outer: L, _io: () => B) extends BaseCoreplexModule(_outer, _io)
|
class DefaultCoreplexModule[+L <: DefaultCoreplex, +B <: DefaultCoreplexBundle[L]](_outer: L, _io: () => B) extends BaseCoreplexModule(_outer, _io)
|
||||||
with CoreplexRISCVPlatformModule
|
with CoreplexRISCVPlatformModule
|
||||||
with L2MasterPortModule
|
with HasL2MasterPortModule
|
||||||
with RocketTilesModule
|
with HasSynchronousRocketTilesModule
|
||||||
|
|
||||||
/////
|
/////
|
||||||
|
|
||||||
class MultiClockCoreplex(implicit p: Parameters) extends BaseCoreplex
|
class MultiClockCoreplex(implicit p: Parameters) extends BaseCoreplex
|
||||||
with CoreplexRISCVPlatform
|
with CoreplexRISCVPlatform
|
||||||
with L2MasterPort
|
with HasL2MasterPort
|
||||||
with AsyncRocketTiles {
|
with HasAsynchronousRocketTiles {
|
||||||
override lazy val module = new MultiClockCoreplexModule(this, () => new MultiClockCoreplexBundle(this))
|
override lazy val module = new MultiClockCoreplexModule(this, () => new MultiClockCoreplexBundle(this))
|
||||||
}
|
}
|
||||||
|
|
||||||
class MultiClockCoreplexBundle[+L <: MultiClockCoreplex](_outer: L) extends BaseCoreplexBundle(_outer)
|
class MultiClockCoreplexBundle[+L <: MultiClockCoreplex](_outer: L) extends BaseCoreplexBundle(_outer)
|
||||||
with CoreplexRISCVPlatformBundle
|
with CoreplexRISCVPlatformBundle
|
||||||
with L2MasterPortBundle
|
with HasL2MasterPortBundle
|
||||||
with AsyncRocketTilesBundle
|
with HasAsynchronousRocketTilesBundle
|
||||||
|
|
||||||
class MultiClockCoreplexModule[+L <: MultiClockCoreplex, +B <: MultiClockCoreplexBundle[L]](_outer: L, _io: () => B) extends BaseCoreplexModule(_outer, _io)
|
class MultiClockCoreplexModule[+L <: MultiClockCoreplex, +B <: MultiClockCoreplexBundle[L]](_outer: L, _io: () => B) extends BaseCoreplexModule(_outer, _io)
|
||||||
with CoreplexRISCVPlatformModule
|
with CoreplexRISCVPlatformModule
|
||||||
with L2MasterPortModule
|
with HasL2MasterPortModule
|
||||||
with AsyncRocketTilesModule
|
with HasAsynchronousRocketTilesModule
|
||||||
|
117
src/main/scala/coreplex/CoreplexNetwork.scala
Normal file
117
src/main/scala/coreplex/CoreplexNetwork.scala
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
// See LICENSE.SiFive for license details.
|
||||||
|
|
||||||
|
package coreplex
|
||||||
|
|
||||||
|
import Chisel._
|
||||||
|
import config._
|
||||||
|
import diplomacy._
|
||||||
|
import uncore.tilelink2._
|
||||||
|
import uncore.util._
|
||||||
|
import util._
|
||||||
|
|
||||||
|
trait CoreplexNetwork extends HasCoreplexParameters {
|
||||||
|
val module: CoreplexNetworkModule
|
||||||
|
|
||||||
|
val l1tol2 = LazyModule(new TLXbar)
|
||||||
|
val l1tol2_beatBytes = l1tol2Config.beatBytes
|
||||||
|
val l1tol2_lineBytes = p(CacheBlockBytes)
|
||||||
|
|
||||||
|
val cbus = LazyModule(new TLXbar)
|
||||||
|
val cbus_beatBytes = cbusConfig.beatBytes
|
||||||
|
val cbus_lineBytes = l1tol2_lineBytes
|
||||||
|
|
||||||
|
val intBar = LazyModule(new IntXbar)
|
||||||
|
|
||||||
|
val mmio = TLOutputNode()
|
||||||
|
val mmioInt = IntInputNode()
|
||||||
|
|
||||||
|
intBar.intnode := mmioInt
|
||||||
|
|
||||||
|
cbus.node :=
|
||||||
|
TLAtomicAutomata(arithmetic = true)( // disable once TLB uses TL2 metadata
|
||||||
|
TLWidthWidget(l1tol2_beatBytes)(
|
||||||
|
TLBuffer()(
|
||||||
|
l1tol2.node)))
|
||||||
|
|
||||||
|
mmio :=
|
||||||
|
TLBuffer()(
|
||||||
|
TLWidthWidget(l1tol2_beatBytes)(
|
||||||
|
l1tol2.node))
|
||||||
|
}
|
||||||
|
|
||||||
|
trait CoreplexNetworkBundle extends HasCoreplexParameters {
|
||||||
|
val outer: CoreplexNetwork
|
||||||
|
|
||||||
|
val mmio = outer.mmio.bundleOut
|
||||||
|
val interrupts = outer.mmioInt.bundleIn
|
||||||
|
}
|
||||||
|
|
||||||
|
trait CoreplexNetworkModule extends HasCoreplexParameters {
|
||||||
|
val outer: CoreplexNetwork
|
||||||
|
val io: CoreplexNetworkBundle
|
||||||
|
|
||||||
|
println("\nGenerated Address Map")
|
||||||
|
for (manager <- outer.l1tol2.node.edgesIn(0).manager.managers) {
|
||||||
|
val prot = (if (manager.supportsGet) "R" else "") +
|
||||||
|
(if (manager.supportsPutFull) "W" else "") +
|
||||||
|
(if (manager.executable) "X" else "") +
|
||||||
|
(if (manager.supportsAcquire) " [C]" else "")
|
||||||
|
manager.address.foreach { a =>
|
||||||
|
println(f"\t${manager.name}%s ${a.base}%x - ${a.base+a.mask+1}%x, $prot")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/////
|
||||||
|
|
||||||
|
trait BankedL2CoherenceManagers extends CoreplexNetwork {
|
||||||
|
val module: BankedL2CoherenceManagersModule
|
||||||
|
|
||||||
|
require (isPow2(l2Config.nBanksPerChannel))
|
||||||
|
require (isPow2(l1tol2_lineBytes))
|
||||||
|
|
||||||
|
val mem = Seq.fill(l2Config.nMemoryChannels) {
|
||||||
|
val bankBar = LazyModule(new TLXbar)
|
||||||
|
val output = TLOutputNode()
|
||||||
|
|
||||||
|
output := bankBar.node
|
||||||
|
val mask = ~BigInt((l2Config.nBanksPerChannel-1) * l1tol2_lineBytes)
|
||||||
|
for (i <- 0 until l2Config.nBanksPerChannel) {
|
||||||
|
val (in, out) = l2Config.coherenceManager(p)
|
||||||
|
in := TLFilter(AddressSet(i * l1tol2_lineBytes, mask))(l1tol2.node)
|
||||||
|
bankBar.node := out
|
||||||
|
}
|
||||||
|
|
||||||
|
output
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trait BankedL2CoherenceManagersBundle extends CoreplexNetworkBundle {
|
||||||
|
val outer: BankedL2CoherenceManagers
|
||||||
|
|
||||||
|
require (l2Config.nMemoryChannels <= 1, "Seq in Chisel Bundle needed to support > 1") // !!!
|
||||||
|
val mem = outer.mem.map(_.bundleOut).toList.headOption // .headOption should be removed !!!
|
||||||
|
}
|
||||||
|
|
||||||
|
trait BankedL2CoherenceManagersModule extends CoreplexNetworkModule {
|
||||||
|
val outer: BankedL2CoherenceManagers
|
||||||
|
val io: BankedL2CoherenceManagersBundle
|
||||||
|
}
|
||||||
|
|
||||||
|
/////
|
||||||
|
|
||||||
|
trait HasL2MasterPort extends CoreplexNetwork {
|
||||||
|
val module: HasL2MasterPortModule
|
||||||
|
val l2in = TLInputNode()
|
||||||
|
l1tol2.node := l2in
|
||||||
|
}
|
||||||
|
|
||||||
|
trait HasL2MasterPortBundle extends CoreplexNetworkBundle {
|
||||||
|
val outer: HasL2MasterPort
|
||||||
|
val l2in = outer.l2in.bundleIn
|
||||||
|
}
|
||||||
|
|
||||||
|
trait HasL2MasterPortModule extends CoreplexNetworkModule {
|
||||||
|
val outer: HasL2MasterPort
|
||||||
|
val io: HasL2MasterPortBundle
|
||||||
|
}
|
@ -5,86 +5,67 @@ package coreplex
|
|||||||
import Chisel._
|
import Chisel._
|
||||||
import config._
|
import config._
|
||||||
import diplomacy._
|
import diplomacy._
|
||||||
import uncore.tilelink2._
|
|
||||||
import uncore.coherence._
|
|
||||||
import rocket._
|
import rocket._
|
||||||
import uncore.devices.NTiles
|
import uncore.tilelink2._
|
||||||
|
|
||||||
trait RocketTiles extends CoreplexRISCVPlatform {
|
case object RocketConfigs extends Field[Seq[RocketConfig]]
|
||||||
val module: RocketTilesModule
|
|
||||||
|
|
||||||
val rocketTiles = List.tabulate(p(NTiles)) { i => LazyModule(new RocketTile(i)) }
|
trait HasSynchronousRocketTiles extends CoreplexRISCVPlatform {
|
||||||
val tileIntNodes = rocketTiles.map { _ => IntInternalOutputNode() }
|
val module: HasSynchronousRocketTilesModule
|
||||||
|
|
||||||
|
val rocketTiles: Seq[RocketTile] = p(RocketConfigs).map { c =>
|
||||||
|
LazyModule(new RocketTile(c)(p.alterPartial {
|
||||||
|
case SharedMemoryTLEdge => l1tol2.node.edgesIn(0)
|
||||||
|
case PAddrBits => l1tol2.node.edgesIn(0).bundle.addressBits
|
||||||
|
}))}
|
||||||
|
|
||||||
tileIntNodes.foreach { _ := plic.intnode }
|
|
||||||
rocketTiles.foreach { r =>
|
rocketTiles.foreach { r =>
|
||||||
|
r.masterNodes.foreach { l1tol2.node := _ }
|
||||||
r.slaveNode.foreach { _ := cbus.node }
|
r.slaveNode.foreach { _ := cbus.node }
|
||||||
l1tol2.node := r.cachedOut
|
|
||||||
l1tol2.node := r.uncachedOut
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val rocketTileIntNodes = rocketTiles.map { _ => IntInternalOutputNode() }
|
||||||
|
rocketTileIntNodes.foreach { _ := plic.intnode }
|
||||||
}
|
}
|
||||||
|
|
||||||
trait RocketTilesBundle extends CoreplexRISCVPlatformBundle {
|
trait HasSynchronousRocketTilesBundle extends CoreplexRISCVPlatformBundle {
|
||||||
val outer: RocketTiles
|
val outer: HasSynchronousRocketTiles
|
||||||
}
|
}
|
||||||
|
|
||||||
trait RocketTilesModule extends CoreplexRISCVPlatformModule {
|
trait HasSynchronousRocketTilesModule extends CoreplexRISCVPlatformModule {
|
||||||
val outer: RocketTiles
|
val outer: HasSynchronousRocketTiles
|
||||||
val io: RocketTilesBundle
|
val io: HasSynchronousRocketTilesBundle
|
||||||
|
|
||||||
outer.rocketTiles.map(_.module).zipWithIndex.foreach { case (tile, i) =>
|
outer.rocketTiles.map(_.module).zipWithIndex.foreach { case (tile, i) =>
|
||||||
tile.io.hartid := UInt(i)
|
tile.io.hartid := UInt(i)
|
||||||
tile.io.resetVector := io.resetVector
|
tile.io.resetVector := io.resetVector
|
||||||
tile.io.interrupts := outer.clint.module.io.tiles(i)
|
tile.io.interrupts := outer.clint.module.io.tiles(i)
|
||||||
tile.io.interrupts.debug := outer.debug.module.io.debugInterrupts(i)
|
tile.io.interrupts.debug := outer.debug.module.io.debugInterrupts(i)
|
||||||
tile.io.interrupts.meip := outer.tileIntNodes(i).bundleOut(0)(0)
|
tile.io.interrupts.meip := outer.rocketTileIntNodes(i).bundleOut(0)(0)
|
||||||
tile.io.interrupts.seip.foreach(_ := outer.tileIntNodes(i).bundleOut(0)(1))
|
tile.io.interrupts.seip.foreach(_ := outer.rocketTileIntNodes(i).bundleOut(0)(1))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AsyncRocketTile(tileId: Int)(implicit p: Parameters) extends LazyModule {
|
trait HasAsynchronousRocketTiles extends CoreplexRISCVPlatform {
|
||||||
val rocket = LazyModule(new RocketTile(tileId))
|
val module: HasAsynchronousRocketTilesModule
|
||||||
|
|
||||||
val cachedOut = TLAsyncOutputNode()
|
val rocketTiles: Seq[AsyncRocketTile] = p(RocketConfigs).map { c =>
|
||||||
val uncachedOut = TLAsyncOutputNode()
|
LazyModule(new AsyncRocketTile(c)(p.alterPartial {
|
||||||
val slaveNode = rocket.slaveNode.map(_ => TLAsyncInputNode())
|
case SharedMemoryTLEdge => l1tol2.node.edgesIn(0)
|
||||||
|
case PAddrBits => l1tol2.node.edgesIn(0).bundle.addressBits
|
||||||
|
}))}
|
||||||
|
|
||||||
cachedOut := TLAsyncCrossingSource()(rocket.cachedOut)
|
|
||||||
uncachedOut := TLAsyncCrossingSource()(rocket.uncachedOut)
|
|
||||||
(rocket.slaveNode zip slaveNode) foreach { case (r,n) => r := TLAsyncCrossingSink()(n) }
|
|
||||||
|
|
||||||
lazy val module = new LazyModuleImp(this) {
|
|
||||||
val io = new Bundle {
|
|
||||||
val cached = cachedOut.bundleOut
|
|
||||||
val uncached = uncachedOut.bundleOut
|
|
||||||
val slave = slaveNode.map(_.bundleIn)
|
|
||||||
val hartid = UInt(INPUT, p(XLen))
|
|
||||||
val interrupts = new TileInterrupts()(rocket.coreParams).asInput
|
|
||||||
val resetVector = UInt(INPUT, p(XLen))
|
|
||||||
}
|
|
||||||
rocket.module.io.interrupts := ShiftRegister(io.interrupts, 3)
|
|
||||||
// signals that do not change:
|
|
||||||
rocket.module.io.hartid := io.hartid
|
|
||||||
rocket.module.io.resetVector := io.resetVector
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
trait AsyncRocketTiles extends CoreplexRISCVPlatform {
|
|
||||||
val module: AsyncRocketTilesModule
|
|
||||||
|
|
||||||
val rocketTiles = List.tabulate(p(NTiles)) { i => LazyModule(new AsyncRocketTile(i)) }
|
|
||||||
val tileIntNodes = rocketTiles.map { _ => IntInternalOutputNode() }
|
|
||||||
|
|
||||||
tileIntNodes.foreach { _ := plic.intnode }
|
|
||||||
rocketTiles.foreach { r =>
|
rocketTiles.foreach { r =>
|
||||||
|
r.masterNodes.foreach { l1tol2.node := TLAsyncCrossingSink()(_) }
|
||||||
r.slaveNode.foreach { _ := TLAsyncCrossingSource()(cbus.node) }
|
r.slaveNode.foreach { _ := TLAsyncCrossingSource()(cbus.node) }
|
||||||
l1tol2.node := TLAsyncCrossingSink()(r.cachedOut)
|
|
||||||
l1tol2.node := TLAsyncCrossingSink()(r.uncachedOut)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val rocketTileIntNodes = rocketTiles.map { _ => IntInternalOutputNode() }
|
||||||
|
rocketTileIntNodes.foreach { _ := plic.intnode }
|
||||||
}
|
}
|
||||||
|
|
||||||
trait AsyncRocketTilesBundle extends CoreplexRISCVPlatformBundle {
|
trait HasAsynchronousRocketTilesBundle extends CoreplexRISCVPlatformBundle {
|
||||||
val outer: AsyncRocketTiles
|
val outer: HasAsynchronousRocketTiles
|
||||||
|
|
||||||
val tcrs = Vec(nTiles, new Bundle {
|
val tcrs = Vec(nTiles, new Bundle {
|
||||||
val clock = Clock(INPUT)
|
val clock = Clock(INPUT)
|
||||||
@ -92,9 +73,9 @@ trait AsyncRocketTilesBundle extends CoreplexRISCVPlatformBundle {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
trait AsyncRocketTilesModule extends CoreplexRISCVPlatformModule {
|
trait HasAsynchronousRocketTilesModule extends CoreplexRISCVPlatformModule {
|
||||||
val outer: AsyncRocketTiles
|
val outer: HasAsynchronousRocketTiles
|
||||||
val io: AsyncRocketTilesBundle
|
val io: HasAsynchronousRocketTilesBundle
|
||||||
|
|
||||||
outer.rocketTiles.map(_.module).zipWithIndex.foreach { case (tile, i) =>
|
outer.rocketTiles.map(_.module).zipWithIndex.foreach { case (tile, i) =>
|
||||||
tile.clock := io.tcrs(i).clock
|
tile.clock := io.tcrs(i).clock
|
||||||
@ -103,7 +84,7 @@ trait AsyncRocketTilesModule extends CoreplexRISCVPlatformModule {
|
|||||||
tile.io.resetVector := io.resetVector
|
tile.io.resetVector := io.resetVector
|
||||||
tile.io.interrupts := outer.clint.module.io.tiles(i)
|
tile.io.interrupts := outer.clint.module.io.tiles(i)
|
||||||
tile.io.interrupts.debug := outer.debug.module.io.debugInterrupts(i)
|
tile.io.interrupts.debug := outer.debug.module.io.debugInterrupts(i)
|
||||||
tile.io.interrupts.meip := outer.tileIntNodes(i).bundleOut(0)(0)
|
tile.io.interrupts.meip := outer.rocketTileIntNodes(i).bundleOut(0)(0)
|
||||||
tile.io.interrupts.seip.foreach(_ := outer.tileIntNodes(i).bundleOut(0)(1))
|
tile.io.interrupts.seip.foreach(_ := outer.rocketTileIntNodes(i).bundleOut(0)(1))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,6 @@ import uncore.util._
|
|||||||
import uncore.devices.NTiles
|
import uncore.devices.NTiles
|
||||||
import junctions._
|
import junctions._
|
||||||
import config._
|
import config._
|
||||||
import scala.math.max
|
|
||||||
import coreplex._
|
import coreplex._
|
||||||
import rocketchip._
|
import rocketchip._
|
||||||
|
|
||||||
@ -74,24 +73,6 @@ class Edge32BitMemtestConfig extends Config(
|
|||||||
|
|
||||||
/* Composable Configs to set individual parameters */
|
/* Composable Configs to set individual parameters */
|
||||||
class WithGroundTest extends Config((site, here, up) => {
|
class WithGroundTest extends Config((site, here, up) => {
|
||||||
case TLKey("L1toL2") => {
|
|
||||||
val useMEI = site(NTiles) <= 1
|
|
||||||
val dataBeats = (8 * site(CacheBlockBytes)) / site(XLen)
|
|
||||||
TileLinkParameters(
|
|
||||||
coherencePolicy = (
|
|
||||||
if (useMEI) new MEICoherence(site(L2DirectoryRepresentation))
|
|
||||||
else new MESICoherence(site(L2DirectoryRepresentation))),
|
|
||||||
nManagers = site(BankedL2Config).nBanks + 1,
|
|
||||||
nCachingClients = 1,
|
|
||||||
nCachelessClients = 1,
|
|
||||||
maxClientXacts = ((site(DCacheKey).nMSHRs + 1) +:
|
|
||||||
site(GroundTestKey).map(_.maxXacts))
|
|
||||||
.reduce(max(_, _)),
|
|
||||||
maxClientsPerPort = site(GroundTestKey).map(_.uncached).sum,
|
|
||||||
maxManagerXacts = site(NAcquireTransactors) + 2,
|
|
||||||
dataBeats = dataBeats,
|
|
||||||
dataBits = site(CacheBlockBytes)*8)
|
|
||||||
}
|
|
||||||
case FPUKey => None
|
case FPUKey => None
|
||||||
case UseAtomics => false
|
case UseAtomics => false
|
||||||
case UseCompressed => false
|
case UseCompressed => false
|
||||||
|
@ -6,19 +6,41 @@ import Chisel._
|
|||||||
import config._
|
import config._
|
||||||
import diplomacy._
|
import diplomacy._
|
||||||
import coreplex._
|
import coreplex._
|
||||||
import uncore.devices.NTiles
|
import rocket._
|
||||||
|
import uncore.agents._
|
||||||
|
import uncore.coherence._
|
||||||
|
import uncore.devices._
|
||||||
|
import uncore.tilelink._
|
||||||
import uncore.tilelink2._
|
import uncore.tilelink2._
|
||||||
import uncore.tilelink.TLId
|
import uncore.util._
|
||||||
|
import scala.math.max
|
||||||
|
|
||||||
case object TileId extends Field[Int]
|
case object TileId extends Field[Int]
|
||||||
|
|
||||||
class GroundTestCoreplex(implicit p: Parameters) extends BaseCoreplex {
|
class GroundTestCoreplex(implicit p: Parameters) extends BaseCoreplex {
|
||||||
val tiles = List.tabulate(p(NTiles)) { i =>
|
val tiles = List.tabulate(p(NTiles)) { i =>
|
||||||
LazyModule(new GroundTestTile()(p.alterPartial({
|
LazyModule(new GroundTestTile()(p.alter { (site, here, up) => {
|
||||||
case TLId => "L1toL2"
|
|
||||||
case TileId => i
|
case TileId => i
|
||||||
})))
|
case CacheBlockOffsetBits => log2Up(site(CacheBlockBytes))
|
||||||
|
case AmoAluOperandBits => site(XLen)
|
||||||
|
case SharedMemoryTLEdge => l1tol2.node.edgesIn(0)
|
||||||
|
case TLId => "L1toL2"
|
||||||
|
case TLKey("L1toL2") =>
|
||||||
|
TileLinkParameters(
|
||||||
|
coherencePolicy = new MESICoherence(new NullRepresentation(site(NTiles))),
|
||||||
|
nManagers = site(BankedL2Config).nBanks + 1,
|
||||||
|
nCachingClients = 1,
|
||||||
|
nCachelessClients = 1,
|
||||||
|
maxClientXacts = ((site(DCacheKey).nMSHRs + 1) +:
|
||||||
|
site(GroundTestKey).map(_.maxXacts))
|
||||||
|
.reduce(max(_, _)),
|
||||||
|
maxClientsPerPort = site(GroundTestKey).map(_.uncached).sum,
|
||||||
|
maxManagerXacts = 8,
|
||||||
|
dataBeats = (8 * site(CacheBlockBytes)) / site(XLen),
|
||||||
|
dataBits = site(CacheBlockBytes)*8)
|
||||||
|
}}))
|
||||||
}
|
}
|
||||||
|
|
||||||
tiles.foreach { lm =>
|
tiles.foreach { lm =>
|
||||||
l1tol2.node := lm.cachedOut
|
l1tol2.node := lm.cachedOut
|
||||||
l1tol2.node := lm.uncachedOut
|
l1tol2.node := lm.uncachedOut
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
package groundtest
|
package groundtest
|
||||||
|
|
||||||
import Chisel._
|
import Chisel._
|
||||||
|
import coreplex.BareTile
|
||||||
import rocket._
|
import rocket._
|
||||||
import uncore.tilelink._
|
import uncore.tilelink._
|
||||||
import uncore.util.CacheName
|
import uncore.util.CacheName
|
||||||
@ -105,11 +106,10 @@ abstract class GroundTest(implicit val p: Parameters) extends Module
|
|||||||
class GroundTestTile(implicit p: Parameters) extends LazyModule with HasGroundTestParameters {
|
class GroundTestTile(implicit p: Parameters) extends LazyModule with HasGroundTestParameters {
|
||||||
val dcacheParams = p.alterPartial {
|
val dcacheParams = p.alterPartial {
|
||||||
case CacheName => CacheName("L1D")
|
case CacheName => CacheName("L1D")
|
||||||
case rocket.TLCacheEdge => cachedOut.edgesOut(0)
|
|
||||||
}
|
}
|
||||||
val slave = None
|
val slave = None
|
||||||
val dcache = HellaCache(p(DCacheKey))(dcacheParams)
|
val dcache = HellaCache(p(DCacheKey))(dcacheParams)
|
||||||
val ucLegacy = LazyModule(new TLLegacy()(p))
|
val ucLegacy = LazyModule(new TLLegacy)
|
||||||
|
|
||||||
val cachedOut = TLOutputNode()
|
val cachedOut = TLOutputNode()
|
||||||
val uncachedOut = TLOutputNode()
|
val uncachedOut = TLOutputNode()
|
||||||
|
@ -23,7 +23,6 @@ import Chisel._
|
|||||||
import uncore.tilelink._
|
import uncore.tilelink._
|
||||||
import uncore.constants._
|
import uncore.constants._
|
||||||
import uncore.devices.NTiles
|
import uncore.devices.NTiles
|
||||||
import junctions._
|
|
||||||
import rocket._
|
import rocket._
|
||||||
import util.{Timer, DynamicTimer}
|
import util.{Timer, DynamicTimer}
|
||||||
import scala.util.Random
|
import scala.util.Random
|
||||||
|
@ -7,8 +7,6 @@ import Chisel._
|
|||||||
import config._
|
import config._
|
||||||
import scala.collection.mutable.HashMap
|
import scala.collection.mutable.HashMap
|
||||||
|
|
||||||
case object PAddrBits extends Field[Int]
|
|
||||||
|
|
||||||
case class MemAttr(prot: Int, cacheable: Boolean = false)
|
case class MemAttr(prot: Int, cacheable: Boolean = false)
|
||||||
|
|
||||||
sealed abstract class MemRegion {
|
sealed abstract class MemRegion {
|
||||||
|
93
src/main/scala/rocket/Core.scala
Normal file
93
src/main/scala/rocket/Core.scala
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
// See LICENSE.SiFive for license details.
|
||||||
|
|
||||||
|
package rocket
|
||||||
|
|
||||||
|
import Chisel._
|
||||||
|
import config._
|
||||||
|
import uncore.tilelink2.TLEdgeOut
|
||||||
|
import uncore.util.{CacheName, CacheBlockBytes}
|
||||||
|
import util._
|
||||||
|
|
||||||
|
case object BuildCore extends Field[(RocketConfig, Parameters) => CoreModule with HasCoreIO]
|
||||||
|
case object SharedMemoryTLEdge extends Field[TLEdgeOut]
|
||||||
|
|
||||||
|
trait HasCoreParameters {
|
||||||
|
implicit val p: Parameters
|
||||||
|
val xLen = p(XLen)
|
||||||
|
val fLen = xLen // TODO relax this
|
||||||
|
|
||||||
|
val usingVM = p(UseVM)
|
||||||
|
val usingUser = p(UseUser) || usingVM
|
||||||
|
val usingDebug = p(UseDebug)
|
||||||
|
val usingMulDiv = p(MulDivKey).nonEmpty
|
||||||
|
val usingFPU = p(FPUKey).nonEmpty
|
||||||
|
val usingAtomics = p(UseAtomics)
|
||||||
|
val usingCompressed = p(UseCompressed)
|
||||||
|
val usingRoCC = !p(BuildRoCC).isEmpty
|
||||||
|
val fastLoadWord = p(FastLoadWord)
|
||||||
|
val fastLoadByte = p(FastLoadByte)
|
||||||
|
val fastJAL = p(FastJAL)
|
||||||
|
val nBreakpoints = p(NBreakpoints)
|
||||||
|
val nPerfCounters = p(NPerfCounters)
|
||||||
|
val nPerfEvents = p(NPerfEvents)
|
||||||
|
val usingDataScratchpad = p(DataScratchpadSize) > 0
|
||||||
|
|
||||||
|
val retireWidth = p(RetireWidth)
|
||||||
|
val fetchWidth = p(FetchWidth)
|
||||||
|
val coreInstBits = p(CoreInstBits)
|
||||||
|
val coreInstBytes = coreInstBits/8
|
||||||
|
val coreDataBits = xLen
|
||||||
|
val coreDataBytes = coreDataBits/8
|
||||||
|
|
||||||
|
val dcacheArbPorts = 1 + usingVM.toInt + usingDataScratchpad.toInt + p(BuildRoCC).size
|
||||||
|
val coreDCacheReqTagBits = 6
|
||||||
|
val dcacheReqTagBits = coreDCacheReqTagBits + log2Ceil(dcacheArbPorts)
|
||||||
|
|
||||||
|
def pgIdxBits = 12
|
||||||
|
def pgLevelBits = 10 - log2Ceil(xLen / 32)
|
||||||
|
def vaddrBits = pgIdxBits + pgLevels * pgLevelBits
|
||||||
|
val paddrBits = p(PAddrBits)
|
||||||
|
def ppnBits = paddrBits - pgIdxBits
|
||||||
|
def vpnBits = vaddrBits - pgIdxBits
|
||||||
|
val pgLevels = p(PgLevels)
|
||||||
|
val asIdBits = p(ASIdBits)
|
||||||
|
val vpnBitsExtended = vpnBits + (vaddrBits < xLen).toInt
|
||||||
|
val vaddrBitsExtended = vpnBitsExtended + pgIdxBits
|
||||||
|
val coreMaxAddrBits = paddrBits max vaddrBitsExtended
|
||||||
|
val nCustomMrwCsrs = p(NCustomMRWCSRs)
|
||||||
|
|
||||||
|
// fetchWidth doubled, but coreInstBytes halved, for RVC
|
||||||
|
val decodeWidth = fetchWidth / (if (usingCompressed) 2 else 1)
|
||||||
|
|
||||||
|
// Print out log of committed instructions and their writeback values.
|
||||||
|
// Requires post-processing due to out-of-order writebacks.
|
||||||
|
val enableCommitLog = false
|
||||||
|
|
||||||
|
val maxPAddrBits = xLen match {
|
||||||
|
case 32 => 34
|
||||||
|
case 64 => 50
|
||||||
|
}
|
||||||
|
|
||||||
|
require(paddrBits <= maxPAddrBits)
|
||||||
|
require(!fastLoadByte || fastLoadWord)
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class CoreModule(implicit val p: Parameters) extends Module
|
||||||
|
with HasCoreParameters
|
||||||
|
|
||||||
|
abstract class CoreBundle(implicit val p: Parameters) extends ParameterizedBundle()(p)
|
||||||
|
with HasCoreParameters
|
||||||
|
|
||||||
|
trait HasCoreIO {
|
||||||
|
implicit val p: Parameters
|
||||||
|
val io = new Bundle {
|
||||||
|
val interrupts = new TileInterrupts().asInput
|
||||||
|
val hartid = UInt(INPUT, p(XLen))
|
||||||
|
val imem = new FrontendIO()(p.alterPartial({case CacheName => CacheName("L1I") }))
|
||||||
|
val dmem = new HellaCacheIO()(p.alterPartial({ case CacheName => CacheName("L1D") }))
|
||||||
|
val ptw = new DatapathPTWIO().flip
|
||||||
|
val fpu = new FPUCoreIO().flip
|
||||||
|
val rocc = new RoCCCoreIO().flip
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -38,7 +38,7 @@ class DCacheDataArray(implicit p: Parameters) extends L1HellaCacheModule()(p) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class DCache(cfg: DCacheConfig, val scratch: () => Option[AddressSet])(implicit p: Parameters) extends HellaCache(cfg)(p) {
|
class DCache(cfg: DCacheConfig, val scratch: () => Option[AddressSet] = () => None)(implicit p: Parameters) extends HellaCache(cfg)(p) {
|
||||||
override lazy val module = new DCacheModule(this)
|
override lazy val module = new DCacheModule(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,7 +149,7 @@ class FPUDecoder(implicit p: Parameters) extends FPUModule()(p) {
|
|||||||
sigs zip decoder map {case(s,d) => s := d}
|
sigs zip decoder map {case(s,d) => s := d}
|
||||||
}
|
}
|
||||||
|
|
||||||
class FPUIO(implicit p: Parameters) extends CoreBundle {
|
class FPUCoreIO(implicit p: Parameters) extends CoreBundle()(p) {
|
||||||
val inst = Bits(INPUT, 32)
|
val inst = Bits(INPUT, 32)
|
||||||
val fromint_data = Bits(INPUT, xLen)
|
val fromint_data = Bits(INPUT, xLen)
|
||||||
|
|
||||||
@ -174,7 +174,9 @@ class FPUIO(implicit p: Parameters) extends CoreBundle {
|
|||||||
val sboard_set = Bool(OUTPUT)
|
val sboard_set = Bool(OUTPUT)
|
||||||
val sboard_clr = Bool(OUTPUT)
|
val sboard_clr = Bool(OUTPUT)
|
||||||
val sboard_clra = UInt(OUTPUT, 5)
|
val sboard_clra = UInt(OUTPUT, 5)
|
||||||
|
}
|
||||||
|
|
||||||
|
class FPUIO(implicit p: Parameters) extends FPUCoreIO ()(p) {
|
||||||
val cp_req = Decoupled(new FPInput()).flip //cp doesn't pay attn to kill sigs
|
val cp_req = Decoupled(new FPInput()).flip //cp doesn't pay attn to kill sigs
|
||||||
val cp_resp = Decoupled(new FPResult())
|
val cp_resp = Decoupled(new FPResult())
|
||||||
}
|
}
|
||||||
@ -729,3 +731,14 @@ class FPU(cfg: FPUConfig)(implicit p: Parameters) extends FPUModule()(p) {
|
|||||||
when (ex_ctrl.div || ex_ctrl.sqrt) { io.illegal_rm := true }
|
when (ex_ctrl.div || ex_ctrl.sqrt) { io.illegal_rm := true }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Mix-ins for constructing tiles that may have an FPU external to the core pipeline */
|
||||||
|
trait CanHaveSharedFPU {
|
||||||
|
implicit val p: Parameters
|
||||||
|
}
|
||||||
|
|
||||||
|
trait CanHaveSharedFPUModule {
|
||||||
|
val outer: CanHaveSharedFPU
|
||||||
|
val fpuOpt = outer.p(FPUKey).map(cfg => Module(new FPU(cfg)(outer.p)))
|
||||||
|
// TODO fpArb could go here instead of inside LegacyRoccComplex
|
||||||
|
}
|
@ -5,8 +5,10 @@ package rocket
|
|||||||
|
|
||||||
import Chisel._
|
import Chisel._
|
||||||
import config._
|
import config._
|
||||||
|
import coreplex._
|
||||||
import diplomacy._
|
import diplomacy._
|
||||||
import uncore.tilelink2._
|
import uncore.tilelink2._
|
||||||
|
import uncore.util.CacheName
|
||||||
import util._
|
import util._
|
||||||
import Chisel.ImplicitConversions._
|
import Chisel.ImplicitConversions._
|
||||||
|
|
||||||
@ -149,3 +151,23 @@ class FrontendModule(outer: Frontend) extends LazyModuleImp(outer)
|
|||||||
io.cpu.resp.bits.btb.valid := s2_btb_resp_valid
|
io.cpu.resp.bits.btb.valid := s2_btb_resp_valid
|
||||||
io.cpu.resp.bits.btb.bits := s2_btb_resp_bits
|
io.cpu.resp.bits.btb.bits := s2_btb_resp_bits
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Mix-ins for constructing tiles that have an ICache-based pipeline frontend */
|
||||||
|
trait HasICacheFrontend extends CanHavePTW with TileNetwork {
|
||||||
|
val module: HasICacheFrontendModule
|
||||||
|
val frontend = LazyModule(new Frontend()(p.alterPartial({
|
||||||
|
case CacheName => CacheName("L1I")
|
||||||
|
})))
|
||||||
|
l1backend.node := frontend.node
|
||||||
|
nPTWPorts += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
trait HasICacheFrontendBundle extends TileNetworkBundle {
|
||||||
|
val outer: HasICacheFrontend
|
||||||
|
}
|
||||||
|
|
||||||
|
trait HasICacheFrontendModule extends CanHavePTWModule with TileNetworkModule {
|
||||||
|
val outer: HasICacheFrontend
|
||||||
|
//val io: HasICacheFrontendBundle
|
||||||
|
ptwPorts += outer.frontend.module.io.ptw
|
||||||
|
}
|
||||||
|
@ -5,12 +5,13 @@ package rocket
|
|||||||
|
|
||||||
import Chisel._
|
import Chisel._
|
||||||
import config.{Parameters, Field}
|
import config.{Parameters, Field}
|
||||||
|
import coreplex._
|
||||||
import diplomacy._
|
import diplomacy._
|
||||||
|
import uncore.constants._
|
||||||
import uncore.tilelink2._
|
import uncore.tilelink2._
|
||||||
import uncore.util._
|
import uncore.util._
|
||||||
import uncore.constants._
|
|
||||||
import uncore.tilelink.{TLKey, TLId}
|
|
||||||
import util.ParameterizedBundle
|
import util.ParameterizedBundle
|
||||||
|
import scala.collection.mutable.ListBuffer
|
||||||
|
|
||||||
case class DCacheConfig(
|
case class DCacheConfig(
|
||||||
nMSHRs: Int = 1,
|
nMSHRs: Int = 1,
|
||||||
@ -146,3 +147,26 @@ object HellaCache {
|
|||||||
else LazyModule(new NonBlockingDCache(cfg))
|
else LazyModule(new NonBlockingDCache(cfg))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Mix-ins for constructing tiles that have a HellaCache */
|
||||||
|
trait HasHellaCache extends TileNetwork {
|
||||||
|
val module: HasHellaCacheModule
|
||||||
|
implicit val p: Parameters
|
||||||
|
def findScratchpadFromICache: Option[AddressSet]
|
||||||
|
var nDCachePorts = 0
|
||||||
|
val dcacheParams = p.alterPartial({ case CacheName => CacheName("L1D") })
|
||||||
|
val dcache = HellaCache(p(DCacheKey), findScratchpadFromICache _)(dcacheParams)
|
||||||
|
l1backend.node := dcache.node
|
||||||
|
}
|
||||||
|
|
||||||
|
trait HasHellaCacheBundle extends TileNetworkBundle {
|
||||||
|
val outer: HasHellaCache
|
||||||
|
}
|
||||||
|
|
||||||
|
trait HasHellaCacheModule extends TileNetworkModule {
|
||||||
|
val outer: HasHellaCache
|
||||||
|
//val io: HasHellaCacheBundle
|
||||||
|
val dcachePorts = ListBuffer[HellaCacheIO]()
|
||||||
|
val dcacheArb = Module(new HellaCacheArbiter(outer.nDCachePorts)(outer.dcacheParams))
|
||||||
|
outer.dcache.module.io.cpu <> dcacheArb.io.mem
|
||||||
|
}
|
||||||
|
@ -15,7 +15,7 @@ import Chisel.ImplicitConversions._
|
|||||||
trait HasL1CacheParameters extends HasCacheParameters with HasCoreParameters {
|
trait HasL1CacheParameters extends HasCacheParameters with HasCoreParameters {
|
||||||
val cacheBlockBytes = p(CacheBlockBytes)
|
val cacheBlockBytes = p(CacheBlockBytes)
|
||||||
val lgCacheBlockBytes = log2Up(cacheBlockBytes)
|
val lgCacheBlockBytes = log2Up(cacheBlockBytes)
|
||||||
val cacheDataBits = p(TLCacheEdge).bundle.dataBits
|
val cacheDataBits = p(SharedMemoryTLEdge).bundle.dataBits
|
||||||
val cacheDataBeats = (cacheBlockBytes * 8) / cacheDataBits
|
val cacheDataBeats = (cacheBlockBytes * 8) / cacheDataBits
|
||||||
val refillCycles = cacheDataBeats
|
val refillCycles = cacheDataBeats
|
||||||
}
|
}
|
||||||
|
@ -4,11 +4,12 @@
|
|||||||
package rocket
|
package rocket
|
||||||
|
|
||||||
import Chisel._
|
import Chisel._
|
||||||
import uncore.util.PseudoLRU
|
import config._
|
||||||
import uncore.constants._
|
import uncore.constants._
|
||||||
|
import uncore.util.PseudoLRU
|
||||||
import util._
|
import util._
|
||||||
import Chisel.ImplicitConversions._
|
import Chisel.ImplicitConversions._
|
||||||
import config._
|
import scala.collection.mutable.ListBuffer
|
||||||
|
|
||||||
class PTWReq(implicit p: Parameters) extends CoreBundle()(p) {
|
class PTWReq(implicit p: Parameters) extends CoreBundle()(p) {
|
||||||
val prv = Bits(width = 2)
|
val prv = Bits(width = 2)
|
||||||
@ -217,3 +218,17 @@ class PTW(n: Int)(implicit p: Parameters) extends CoreModule()(p) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Mix-ins for constructing tiles that might have a PTW */
|
||||||
|
trait CanHavePTW extends HasHellaCache {
|
||||||
|
implicit val p: Parameters
|
||||||
|
val module: CanHavePTWModule
|
||||||
|
var nPTWPorts = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
trait CanHavePTWModule extends HasHellaCacheModule {
|
||||||
|
val outer: CanHavePTW
|
||||||
|
val ptwPorts = ListBuffer(outer.dcache.module.io.ptw)
|
||||||
|
val ptwOpt = if (outer.p(UseVM)) { Some(Module(new PTW(outer.nPTWPorts)(outer.p))) } else None
|
||||||
|
ptwOpt foreach { ptw => dcachePorts += ptw.io.mem }
|
||||||
|
}
|
@ -4,16 +4,159 @@
|
|||||||
package rocket
|
package rocket
|
||||||
|
|
||||||
import Chisel._
|
import Chisel._
|
||||||
import uncore.tilelink._
|
|
||||||
import uncore.constants._
|
|
||||||
import uncore.util.CacheName
|
|
||||||
import util._
|
|
||||||
import Chisel.ImplicitConversions._
|
import Chisel.ImplicitConversions._
|
||||||
import config._
|
import config._
|
||||||
|
import coreplex._
|
||||||
|
import diplomacy._
|
||||||
|
import uncore.constants._
|
||||||
|
import uncore.agents._
|
||||||
|
import uncore.coherence._
|
||||||
|
import uncore.devices._
|
||||||
|
import uncore.tilelink._
|
||||||
|
import uncore.tilelink2._
|
||||||
|
import uncore.util._
|
||||||
|
import util._
|
||||||
|
|
||||||
case object RoccMaxTaggedMemXacts extends Field[Int]
|
case object RoccMaxTaggedMemXacts extends Field[Int]
|
||||||
case object RoccNMemChannels extends Field[Int]
|
case object RoccNMemChannels extends Field[Int]
|
||||||
case object RoccNPTWPorts extends Field[Int]
|
case object RoccNPTWPorts extends Field[Int]
|
||||||
|
case object BuildRoCC extends Field[Seq[RoccParameters]]
|
||||||
|
|
||||||
|
trait CanHaveLegacyRoccs extends CanHaveSharedFPU with CanHavePTW with TileNetwork {
|
||||||
|
val module: CanHaveLegacyRoccsModule
|
||||||
|
val legacyRocc = if (p(BuildRoCC).isEmpty) None
|
||||||
|
else Some(LazyModule(new LegacyRoccComplex()(p.alter { (site, here, up) => {
|
||||||
|
case CacheBlockOffsetBits => log2Up(site(CacheBlockBytes))
|
||||||
|
case AmoAluOperandBits => site(XLen)
|
||||||
|
case RoccNMemChannels => site(BuildRoCC).map(_.nMemChannels).foldLeft(0)(_ + _)
|
||||||
|
case RoccNPTWPorts => site(BuildRoCC).map(_.nPTWPorts).foldLeft(0)(_ + _)
|
||||||
|
case TLId => "L1toL2"
|
||||||
|
case TLKey("L1toL2") =>
|
||||||
|
TileLinkParameters(
|
||||||
|
coherencePolicy = new MESICoherence(new NullRepresentation(site(NTiles))),
|
||||||
|
nManagers = site(BankedL2Config).nBanks + 1 /* MMIO */,
|
||||||
|
nCachingClients = 1,
|
||||||
|
nCachelessClients = 1,
|
||||||
|
maxClientXacts = List(
|
||||||
|
site(DCacheKey).nMSHRs + 1 /* IOMSHR */,
|
||||||
|
if (site(BuildRoCC).isEmpty) 1 else site(RoccMaxTaggedMemXacts)).max,
|
||||||
|
maxClientsPerPort = if (site(BuildRoCC).isEmpty) 1 else 2,
|
||||||
|
maxManagerXacts = 8,
|
||||||
|
dataBeats = (8 * site(CacheBlockBytes)) / site(XLen),
|
||||||
|
dataBits = site(CacheBlockBytes)*8)
|
||||||
|
}})))
|
||||||
|
|
||||||
|
// TODO for now, all legacy rocc mem ports mapped to one external node
|
||||||
|
legacyRocc foreach { lr =>
|
||||||
|
lr.masterNodes.foreach { l1backend.node := _ }
|
||||||
|
nPTWPorts += lr.nPTWPorts
|
||||||
|
nDCachePorts += lr.nRocc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trait CanHaveLegacyRoccsModule extends CanHaveSharedFPUModule with CanHavePTWModule with TileNetworkModule {
|
||||||
|
val outer: CanHaveLegacyRoccs
|
||||||
|
|
||||||
|
fpuOpt foreach { fpu =>
|
||||||
|
outer.legacyRocc.orElse {
|
||||||
|
fpu.io.cp_req.valid := Bool(false)
|
||||||
|
fpu.io.cp_resp.ready := Bool(false)
|
||||||
|
None
|
||||||
|
} foreach { lr =>
|
||||||
|
fpu.io.cp_req <> lr.module.io.fpu.cp_req
|
||||||
|
fpu.io.cp_resp <> lr.module.io.fpu.cp_resp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
outer.legacyRocc foreach { lr =>
|
||||||
|
ptwPorts ++= lr.module.io.ptw
|
||||||
|
dcachePorts ++= lr.module.io.dcache
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class LegacyRoccComplex(implicit p: Parameters) extends LazyModule with HasCoreParameters {
|
||||||
|
val buildRocc = p(BuildRoCC)
|
||||||
|
val usingRocc = !buildRocc.isEmpty
|
||||||
|
val nRocc = buildRocc.size
|
||||||
|
val nFPUPorts = buildRocc.filter(_.useFPU).size
|
||||||
|
val nMemChannels = buildRocc.map(_.nMemChannels).sum + nRocc
|
||||||
|
val nPTWPorts = buildRocc.map(_.nPTWPorts).sum
|
||||||
|
val roccOpcodes = buildRocc.map(_.opcodes)
|
||||||
|
|
||||||
|
val legacies = List.fill(nMemChannels) { LazyModule(new TLLegacy) }
|
||||||
|
val masterNodes = legacies.map(_ => TLOutputNode())
|
||||||
|
legacies.zip(masterNodes).foreach { case(l,m) => m := TLHintHandler()(l.node) }
|
||||||
|
|
||||||
|
lazy val module = new LazyModuleImp(this) {
|
||||||
|
val io = new Bundle {
|
||||||
|
val tl = masterNodes.map(_.bundleOut)
|
||||||
|
val dcache = Vec(nRocc, new HellaCacheIO)
|
||||||
|
val fpu = new Bundle {
|
||||||
|
val cp_req = Decoupled(new FPInput())
|
||||||
|
val cp_resp = Decoupled(new FPResult()).flip
|
||||||
|
}
|
||||||
|
val ptw = Vec(nPTWPorts, new TLBPTWIO)
|
||||||
|
val core = new Bundle {
|
||||||
|
val cmd = Decoupled(new RoCCCommand).flip
|
||||||
|
val resp = Decoupled(new RoCCResponse)
|
||||||
|
val busy = Bool(OUTPUT)
|
||||||
|
val interrupt = Bool(OUTPUT)
|
||||||
|
val exception = Bool(INPUT)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val respArb = Module(new RRArbiter(new RoCCResponse, nRocc))
|
||||||
|
io.core.resp <> respArb.io.out
|
||||||
|
|
||||||
|
val cmdRouter = Module(new RoccCommandRouter(roccOpcodes))
|
||||||
|
cmdRouter.io.in <> io.core.cmd
|
||||||
|
|
||||||
|
val roccs = buildRocc.zipWithIndex.map { case (accelParams, i) =>
|
||||||
|
val rocc = accelParams.generator(p.alterPartial({
|
||||||
|
case RoccNMemChannels => accelParams.nMemChannels
|
||||||
|
case RoccNPTWPorts => accelParams.nPTWPorts
|
||||||
|
}))
|
||||||
|
val dcIF = Module(new SimpleHellaCacheIF)
|
||||||
|
rocc.io.cmd <> cmdRouter.io.out(i)
|
||||||
|
rocc.io.exception := io.core.exception
|
||||||
|
dcIF.io.requestor <> rocc.io.mem
|
||||||
|
io.dcache(i) := dcIF.io.cache
|
||||||
|
legacies(i).module.io.legacy <> rocc.io.autl
|
||||||
|
respArb.io.in(i) <> Queue(rocc.io.resp)
|
||||||
|
rocc
|
||||||
|
}
|
||||||
|
|
||||||
|
(nRocc to legacies.size) zip roccs.map(_.io.utl) foreach { case(i, utl) =>
|
||||||
|
legacies(i).module.io.legacy <> utl
|
||||||
|
}
|
||||||
|
io.core.busy := cmdRouter.io.busy || roccs.map(_.io.busy).reduce(_ || _)
|
||||||
|
io.core.interrupt := roccs.map(_.io.interrupt).reduce(_ || _)
|
||||||
|
|
||||||
|
if (usingFPU && nFPUPorts > 0) {
|
||||||
|
val fpArb = Module(new InOrderArbiter(new FPInput, new FPResult, nFPUPorts))
|
||||||
|
val fp_rocc_ios = roccs.zip(buildRocc)
|
||||||
|
.filter { case (_, params) => params.useFPU }
|
||||||
|
.map { case (rocc, _) => rocc.io }
|
||||||
|
fpArb.io.in_req <> fp_rocc_ios.map(_.fpu_req)
|
||||||
|
fp_rocc_ios.zip(fpArb.io.in_resp).foreach {
|
||||||
|
case (rocc, arb) => rocc.fpu_resp <> arb
|
||||||
|
}
|
||||||
|
io.fpu.cp_req <> fpArb.io.out_req
|
||||||
|
fpArb.io.out_resp <> io.fpu.cp_resp
|
||||||
|
} else {
|
||||||
|
io.fpu.cp_req.valid := Bool(false)
|
||||||
|
io.fpu.cp_resp.ready := Bool(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case class RoccParameters(
|
||||||
|
opcodes: OpcodeSet,
|
||||||
|
generator: Parameters => RoCC,
|
||||||
|
nMemChannels: Int = 0,
|
||||||
|
nPTWPorts : Int = 0,
|
||||||
|
useFPU: Boolean = false)
|
||||||
|
|
||||||
class RoCCInstruction extends Bundle
|
class RoCCInstruction extends Bundle
|
||||||
{
|
{
|
||||||
@ -39,26 +182,30 @@ class RoCCResponse(implicit p: Parameters) extends CoreBundle()(p) {
|
|||||||
val data = Bits(width = xLen)
|
val data = Bits(width = xLen)
|
||||||
}
|
}
|
||||||
|
|
||||||
class RoCCInterface(implicit p: Parameters) extends CoreBundle()(p) {
|
class RoCCCoreIO(implicit p: Parameters) extends CoreBundle()(p) {
|
||||||
val cmd = Decoupled(new RoCCCommand).flip
|
val cmd = Decoupled(new RoCCCommand).flip
|
||||||
val resp = Decoupled(new RoCCResponse)
|
val resp = Decoupled(new RoCCResponse)
|
||||||
val mem = new HellaCacheIO
|
val mem = new HellaCacheIO
|
||||||
val busy = Bool(OUTPUT)
|
val busy = Bool(OUTPUT)
|
||||||
val interrupt = Bool(OUTPUT)
|
val interrupt = Bool(OUTPUT)
|
||||||
|
val exception = Bool(INPUT)
|
||||||
|
|
||||||
|
override def cloneType = new RoCCCoreIO()(p).asInstanceOf[this.type]
|
||||||
|
}
|
||||||
|
|
||||||
|
class RoCCIO(implicit p: Parameters) extends RoCCCoreIO()(p) {
|
||||||
// These should be handled differently, eventually
|
// These should be handled differently, eventually
|
||||||
val autl = new ClientUncachedTileLinkIO
|
val autl = new ClientUncachedTileLinkIO
|
||||||
val utl = Vec(p(RoccNMemChannels), new ClientUncachedTileLinkIO)
|
val utl = Vec(p(RoccNMemChannels), new ClientUncachedTileLinkIO)
|
||||||
val ptw = Vec(p(RoccNPTWPorts), new TLBPTWIO)
|
val ptw = Vec(p(RoccNPTWPorts), new TLBPTWIO)
|
||||||
val fpu_req = Decoupled(new FPInput)
|
val fpu_req = Decoupled(new FPInput)
|
||||||
val fpu_resp = Decoupled(new FPResult).flip
|
val fpu_resp = Decoupled(new FPResult).flip
|
||||||
val exception = Bool(INPUT)
|
|
||||||
|
|
||||||
override def cloneType = new RoCCInterface().asInstanceOf[this.type]
|
override def cloneType = new RoCCIO()(p).asInstanceOf[this.type]
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class RoCC(implicit p: Parameters) extends CoreModule()(p) {
|
abstract class RoCC(implicit p: Parameters) extends CoreModule()(p) {
|
||||||
val io = new RoCCInterface
|
val io = new RoCCIO
|
||||||
io.mem.req.bits.phys := Bool(true) // don't perform address translation
|
io.mem.req.bits.phys := Bool(true) // don't perform address translation
|
||||||
io.mem.invalidate_lr := Bool(false) // don't mess with LR/SC
|
io.mem.invalidate_lr := Bool(false) // don't mess with LR/SC
|
||||||
}
|
}
|
||||||
|
@ -4,14 +4,13 @@
|
|||||||
package rocket
|
package rocket
|
||||||
|
|
||||||
import Chisel._
|
import Chisel._
|
||||||
import uncore.devices._
|
import config._
|
||||||
import uncore.util.{CacheName, CacheBlockBytes}
|
|
||||||
import uncore.constants._
|
import uncore.constants._
|
||||||
import uncore.tilelink2._
|
|
||||||
import util._
|
import util._
|
||||||
import Chisel.ImplicitConversions._
|
import Chisel.ImplicitConversions._
|
||||||
import config._
|
|
||||||
|
|
||||||
|
case class RocketConfig(xLen: Int)
|
||||||
|
// TODO replace some of below fields with above Config
|
||||||
case object XLen extends Field[Int]
|
case object XLen extends Field[Int]
|
||||||
case object FetchWidth extends Field[Int]
|
case object FetchWidth extends Field[Int]
|
||||||
case object RetireWidth extends Field[Int]
|
case object RetireWidth extends Field[Int]
|
||||||
@ -33,72 +32,6 @@ case object NBreakpoints extends Field[Int]
|
|||||||
case object NPerfCounters extends Field[Int]
|
case object NPerfCounters extends Field[Int]
|
||||||
case object NPerfEvents extends Field[Int]
|
case object NPerfEvents extends Field[Int]
|
||||||
case object DataScratchpadSize extends Field[Int]
|
case object DataScratchpadSize extends Field[Int]
|
||||||
case object TLCacheEdge extends Field[TLEdgeOut]
|
|
||||||
|
|
||||||
trait HasCoreParameters {
|
|
||||||
implicit val p: Parameters
|
|
||||||
val xLen = p(XLen)
|
|
||||||
val fLen = xLen // TODO relax this
|
|
||||||
|
|
||||||
val usingVM = p(UseVM)
|
|
||||||
val usingUser = p(UseUser) || usingVM
|
|
||||||
val usingDebug = p(UseDebug)
|
|
||||||
val usingMulDiv = p(MulDivKey).nonEmpty
|
|
||||||
val usingFPU = p(FPUKey).nonEmpty
|
|
||||||
val usingAtomics = p(UseAtomics)
|
|
||||||
val usingCompressed = p(UseCompressed)
|
|
||||||
val usingRoCC = !p(BuildRoCC).isEmpty
|
|
||||||
val fastLoadWord = p(FastLoadWord)
|
|
||||||
val fastLoadByte = p(FastLoadByte)
|
|
||||||
val fastJAL = p(FastJAL)
|
|
||||||
val nBreakpoints = p(NBreakpoints)
|
|
||||||
val nPerfCounters = p(NPerfCounters)
|
|
||||||
val nPerfEvents = p(NPerfEvents)
|
|
||||||
val usingDataScratchpad = p(DataScratchpadSize) > 0
|
|
||||||
|
|
||||||
val retireWidth = p(RetireWidth)
|
|
||||||
val fetchWidth = p(FetchWidth)
|
|
||||||
val coreInstBits = p(CoreInstBits)
|
|
||||||
val coreInstBytes = coreInstBits/8
|
|
||||||
val coreDataBits = xLen
|
|
||||||
val coreDataBytes = coreDataBits/8
|
|
||||||
val dcacheArbPorts = 1 + usingVM.toInt + usingDataScratchpad.toInt + p(BuildRoCC).size
|
|
||||||
val coreDCacheReqTagBits = 6
|
|
||||||
val dcacheReqTagBits = coreDCacheReqTagBits + log2Ceil(dcacheArbPorts)
|
|
||||||
|
|
||||||
def pgIdxBits = 12
|
|
||||||
def pgLevelBits = 10 - log2Ceil(xLen / 32)
|
|
||||||
def vaddrBits = pgIdxBits + pgLevels * pgLevelBits
|
|
||||||
val paddrBits = p(TLCacheEdge).bundle.addressBits
|
|
||||||
def ppnBits = paddrBits - pgIdxBits
|
|
||||||
def vpnBits = vaddrBits - pgIdxBits
|
|
||||||
val pgLevels = p(PgLevels)
|
|
||||||
val asIdBits = p(ASIdBits)
|
|
||||||
val vpnBitsExtended = vpnBits + (vaddrBits < xLen).toInt
|
|
||||||
val vaddrBitsExtended = vpnBitsExtended + pgIdxBits
|
|
||||||
val coreMaxAddrBits = paddrBits max vaddrBitsExtended
|
|
||||||
val nCustomMrwCsrs = p(NCustomMRWCSRs)
|
|
||||||
|
|
||||||
// fetchWidth doubled, but coreInstBytes halved, for RVC
|
|
||||||
val decodeWidth = fetchWidth / (if (usingCompressed) 2 else 1)
|
|
||||||
|
|
||||||
// Print out log of committed instructions and their writeback values.
|
|
||||||
// Requires post-processing due to out-of-order writebacks.
|
|
||||||
val enableCommitLog = false
|
|
||||||
|
|
||||||
val maxPAddrBits = xLen match {
|
|
||||||
case 32 => 34
|
|
||||||
case 64 => 50
|
|
||||||
}
|
|
||||||
|
|
||||||
require(paddrBits <= maxPAddrBits)
|
|
||||||
require(!fastLoadByte || fastLoadWord)
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class CoreModule(implicit val p: Parameters) extends Module
|
|
||||||
with HasCoreParameters
|
|
||||||
abstract class CoreBundle(implicit val p: Parameters) extends ParameterizedBundle()(p)
|
|
||||||
with HasCoreParameters
|
|
||||||
|
|
||||||
class RegFile(n: Int, w: Int, zero: Boolean = false) {
|
class RegFile(n: Int, w: Int, zero: Boolean = false) {
|
||||||
private val rf = Mem(n, UInt(width = w))
|
private val rf = Mem(n, UInt(width = w))
|
||||||
@ -141,16 +74,7 @@ object ImmGen {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Rocket(implicit p: Parameters) extends CoreModule()(p) {
|
class Rocket(val c: RocketConfig)(implicit p: Parameters) extends CoreModule()(p) with HasCoreIO {
|
||||||
val io = new Bundle {
|
|
||||||
val interrupts = new TileInterrupts().asInput
|
|
||||||
val hartid = UInt(INPUT, xLen)
|
|
||||||
val imem = new FrontendIO()(p.alterPartial({case CacheName => CacheName("L1I") }))
|
|
||||||
val dmem = new HellaCacheIO()(p.alterPartial({ case CacheName => CacheName("L1D") }))
|
|
||||||
val ptw = new DatapathPTWIO().flip
|
|
||||||
val fpu = new FPUIO().flip
|
|
||||||
val rocc = new RoCCInterface().flip
|
|
||||||
}
|
|
||||||
|
|
||||||
val decode_table = {
|
val decode_table = {
|
||||||
(if (usingMulDiv) new MDecode +: (xLen > 32).option(new M64Decode).toSeq else Nil) ++:
|
(if (usingMulDiv) new MDecode +: (xLen > 32).option(new M64Decode).toSeq else Nil) ++:
|
||||||
@ -520,7 +444,7 @@ class Rocket(implicit p: Parameters) extends CoreModule()(p) {
|
|||||||
csr.io.hartid := io.hartid
|
csr.io.hartid := io.hartid
|
||||||
io.fpu.fcsr_rm := csr.io.fcsr_rm
|
io.fpu.fcsr_rm := csr.io.fcsr_rm
|
||||||
csr.io.fcsr_flags := io.fpu.fcsr_flags
|
csr.io.fcsr_flags := io.fpu.fcsr_flags
|
||||||
csr.io.rocc.interrupt <> io.rocc.interrupt
|
csr.io.rocc_interrupt := io.rocc.interrupt
|
||||||
csr.io.pc := wb_reg_pc
|
csr.io.pc := wb_reg_pc
|
||||||
csr.io.badaddr := encodeVirtualAddress(wb_reg_wdata, wb_reg_wdata)
|
csr.io.badaddr := encodeVirtualAddress(wb_reg_wdata, wb_reg_wdata)
|
||||||
io.ptw.ptbr := csr.io.ptbr
|
io.ptw.ptbr := csr.io.ptbr
|
@ -101,3 +101,34 @@ class ScratchpadSlavePort(implicit p: Parameters) extends LazyModule {
|
|||||||
tl_in.e.ready := Bool(true)
|
tl_in.e.ready := Bool(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Mix-ins for constructing tiles that have optional scratchpads */
|
||||||
|
trait CanHaveScratchpad extends HasHellaCache with HasICacheFrontend {
|
||||||
|
val module: CanHaveScratchpadModule
|
||||||
|
|
||||||
|
val slaveNode = if (p(DataScratchpadSize) == 0) None else Some(TLInputNode())
|
||||||
|
val scratch = if (p(DataScratchpadSize) == 0) None else Some(LazyModule(new ScratchpadSlavePort()(dcacheParams)))
|
||||||
|
|
||||||
|
(slaveNode zip scratch) foreach { case (node, lm) => lm.node := TLFragmenter(p(XLen)/8, p(CacheBlockBytes))(node) }
|
||||||
|
|
||||||
|
def findScratchpadFromICache: Option[AddressSet] = scratch.map { s =>
|
||||||
|
val finalNode = frontend.node.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)
|
||||||
|
}
|
||||||
|
|
||||||
|
nDCachePorts += 1 // core TODO dcachePorts += () => module.io.dmem ??
|
||||||
|
}
|
||||||
|
|
||||||
|
trait CanHaveScratchpadBundle extends HasHellaCacheBundle with HasICacheFrontendBundle {
|
||||||
|
val outer: CanHaveScratchpad
|
||||||
|
val slave = outer.slaveNode.map(_.bundleIn)
|
||||||
|
}
|
||||||
|
|
||||||
|
trait CanHaveScratchpadModule extends HasHellaCacheModule with HasICacheFrontendModule {
|
||||||
|
val outer: CanHaveScratchpad
|
||||||
|
val io: CanHaveScratchpadBundle
|
||||||
|
|
||||||
|
outer.scratch.foreach { lm => dcachePorts += lm.module.io.dmem }
|
||||||
|
}
|
||||||
|
@ -12,6 +12,7 @@ import diplomacy._
|
|||||||
import uncore.util._
|
import uncore.util._
|
||||||
import uncore.tilelink2._
|
import uncore.tilelink2._
|
||||||
|
|
||||||
|
case object PAddrBits extends Field[Int]
|
||||||
case object PgLevels extends Field[Int]
|
case object PgLevels extends Field[Int]
|
||||||
case object ASIdBits extends Field[Int]
|
case object ASIdBits extends Field[Int]
|
||||||
|
|
||||||
|
@ -4,161 +4,72 @@
|
|||||||
package rocket
|
package rocket
|
||||||
|
|
||||||
import Chisel._
|
import Chisel._
|
||||||
|
import config._
|
||||||
|
import coreplex._
|
||||||
import diplomacy._
|
import diplomacy._
|
||||||
import uncore.tilelink._
|
|
||||||
import uncore.tilelink2._
|
|
||||||
import uncore.util.{CacheName, CacheBlockBytes}
|
|
||||||
import uncore.converters._
|
import uncore.converters._
|
||||||
import uncore.devices._
|
import uncore.devices._
|
||||||
|
import uncore.tilelink2._
|
||||||
import util._
|
import util._
|
||||||
import config._
|
|
||||||
import scala.collection.mutable.ListBuffer
|
|
||||||
|
|
||||||
case object BuildRoCC extends Field[Seq[RoccParameters]]
|
class RocketTile(val c: RocketConfig)(implicit p: Parameters) extends BaseTile()(p)
|
||||||
|
with CanHaveLegacyRoccs // implies CanHaveSharedFPU with CanHavePTW with HasHellaCache
|
||||||
|
with CanHaveScratchpad { // implies CanHavePTW with HasHellaCache with HasICacheFrontend
|
||||||
|
|
||||||
case class RoccParameters(
|
nDCachePorts += 1 // core TODO dcachePorts += () => module.core.io.dmem ??
|
||||||
opcodes: OpcodeSet,
|
|
||||||
generator: Parameters => RoCC,
|
|
||||||
nMemChannels: Int = 0,
|
|
||||||
nPTWPorts : Int = 0,
|
|
||||||
useFPU: Boolean = false)
|
|
||||||
|
|
||||||
class RocketTile(tileId: Int)(implicit p: Parameters) extends LazyModule {
|
override lazy val module = new RocketTileModule(this)
|
||||||
val coreParams = p.alterPartial {
|
}
|
||||||
case TLCacheEdge => cachedOut.edgesOut(0)
|
|
||||||
}
|
|
||||||
val dcacheParams = coreParams.alterPartial({
|
|
||||||
case CacheName => CacheName("L1D")
|
|
||||||
case TLId => "L1toL2"
|
|
||||||
})
|
|
||||||
val icacheParams = coreParams.alterPartial({
|
|
||||||
case CacheName => CacheName("L1I")
|
|
||||||
case TLId => "L1toL2"
|
|
||||||
})
|
|
||||||
|
|
||||||
val slaveNode = if (p(DataScratchpadSize) == 0) None else Some(TLInputNode())
|
class RocketTileBundle(outer: RocketTile) extends BaseTileBundle(outer)
|
||||||
val scratch = if (p(DataScratchpadSize) == 0) None else Some(LazyModule(new ScratchpadSlavePort()(dcacheParams)))
|
with CanHaveScratchpadBundle
|
||||||
def findScratch() = scratch.map { s =>
|
|
||||||
val finalNode = uncachedOut.edgesOut(0).manager.managers.find(_.nodePath.last == s.node)
|
class RocketTileModule(outer: RocketTile) extends BaseTileModule(outer, () => new RocketTileBundle(outer))
|
||||||
require (finalNode.isDefined, "Could not find the scratch pad; not reachable via icache?")
|
with CanHaveLegacyRoccsModule
|
||||||
require (finalNode.get.address.size == 1, "Scratchpad address space was fragmented!")
|
with CanHaveScratchpadModule {
|
||||||
finalNode.get.address(0)
|
|
||||||
|
val core = Module(p(BuildCore)(outer.c, outer.p))
|
||||||
|
core.io.interrupts := io.interrupts
|
||||||
|
core.io.hartid := io.hartid
|
||||||
|
outer.frontend.module.io.cpu <> core.io.imem
|
||||||
|
outer.frontend.module.io.resetVector := io.resetVector
|
||||||
|
dcachePorts += core.io.dmem // TODO outer.dcachePorts += () => module.core.io.dmem ??
|
||||||
|
fpuOpt foreach { fpu => core.io.fpu <> fpu.io }
|
||||||
|
ptwOpt foreach { ptw => core.io.ptw <> ptw.io.dpath }
|
||||||
|
outer.legacyRocc foreach { lr =>
|
||||||
|
lr.module.io.core.cmd <> core.io.rocc.cmd
|
||||||
|
lr.module.io.core.exception := core.io.rocc.exception
|
||||||
|
core.io.rocc.resp <> lr.module.io.core.resp
|
||||||
|
core.io.rocc.busy := lr.module.io.core.busy
|
||||||
|
core.io.rocc.interrupt := lr.module.io.core.interrupt
|
||||||
}
|
}
|
||||||
|
|
||||||
val dcache = HellaCache(p(DCacheKey), findScratch)(dcacheParams)
|
// TODO figure out how to move the below into their respective mix-ins
|
||||||
val frontend = LazyModule(new Frontend()(icacheParams))
|
require(dcachePorts.size == core.dcacheArbPorts)
|
||||||
val ucLegacy = LazyModule(new TLLegacy()(icacheParams))
|
dcacheArb.io.requestor <> dcachePorts
|
||||||
val tileXbar = LazyModule(new TLXbar)
|
ptwOpt foreach { ptw => ptw.io.requestor <> ptwPorts }
|
||||||
tileXbar.node := TLHintHandler()(ucLegacy.node)
|
}
|
||||||
tileXbar.node := frontend.node
|
|
||||||
|
|
||||||
val cachedOut = TLOutputNode()
|
class AsyncRocketTile(c: RocketConfig)(implicit p: Parameters) extends LazyModule {
|
||||||
val uncachedOut = TLOutputNode()
|
val rocket = LazyModule(new RocketTile(c))
|
||||||
cachedOut := dcache.node
|
|
||||||
uncachedOut := tileXbar.node
|
|
||||||
val masterNodes = List(cachedOut, uncachedOut)
|
|
||||||
|
|
||||||
(slaveNode zip scratch) foreach { case (node, lm) => lm.node := TLFragmenter(p(XLen)/8, p(CacheBlockBytes))(node) }
|
val masterNodes = rocket.masterNodes.map(_ => TLAsyncOutputNode())
|
||||||
|
val slaveNode = rocket.slaveNode.map(_ => TLAsyncInputNode())
|
||||||
|
|
||||||
|
(rocket.masterNodes zip masterNodes) foreach { case (r,n) => n := TLAsyncCrossingSource()(r) }
|
||||||
|
(rocket.slaveNode zip slaveNode) foreach { case (r,n) => r := TLAsyncCrossingSink()(n) }
|
||||||
|
|
||||||
lazy val module = new LazyModuleImp(this) {
|
lazy val module = new LazyModuleImp(this) {
|
||||||
val io = new Bundle {
|
val io = new Bundle {
|
||||||
val cached = cachedOut.bundleOut
|
val master = masterNodes.map(_.bundleOut)
|
||||||
val uncached = uncachedOut.bundleOut
|
|
||||||
val slave = slaveNode.map(_.bundleIn)
|
val slave = slaveNode.map(_.bundleIn)
|
||||||
val hartid = UInt(INPUT, p(XLen))
|
val hartid = UInt(INPUT, p(XLen))
|
||||||
val interrupts = new TileInterrupts()(coreParams).asInput
|
val interrupts = new TileInterrupts()(p).asInput
|
||||||
val resetVector = UInt(INPUT, p(XLen))
|
val resetVector = UInt(INPUT, p(XLen))
|
||||||
}
|
}
|
||||||
|
rocket.module.io.interrupts := ShiftRegister(io.interrupts, 3)
|
||||||
val buildRocc = p(BuildRoCC)
|
// signals that do not change:
|
||||||
val usingRocc = !buildRocc.isEmpty
|
rocket.module.io.hartid := io.hartid
|
||||||
val nRocc = buildRocc.size
|
rocket.module.io.resetVector := io.resetVector
|
||||||
val nFPUPorts = buildRocc.filter(_.useFPU).size
|
|
||||||
|
|
||||||
val core = Module(new Rocket()(dcacheParams))
|
|
||||||
|
|
||||||
val ptwPorts = ListBuffer(frontend.module.io.ptw, dcache.module.io.ptw)
|
|
||||||
val dcPorts = ListBuffer(core.io.dmem)
|
|
||||||
val uncachedArbPorts = ListBuffer[ClientUncachedTileLinkIO]()
|
|
||||||
core.io.interrupts := io.interrupts
|
|
||||||
core.io.hartid := io.hartid
|
|
||||||
frontend.module.io.cpu <> core.io.imem
|
|
||||||
frontend.module.io.resetVector := io.resetVector
|
|
||||||
|
|
||||||
val fpuOpt = p(FPUKey).map(cfg => Module(new FPU(cfg)(coreParams)))
|
|
||||||
fpuOpt.foreach(fpu => core.io.fpu <> fpu.io)
|
|
||||||
|
|
||||||
if (usingRocc) {
|
|
||||||
val respArb = Module(new RRArbiter(new RoCCResponse()(coreParams), nRocc))
|
|
||||||
core.io.rocc.resp <> respArb.io.out
|
|
||||||
|
|
||||||
val roccOpcodes = buildRocc.map(_.opcodes)
|
|
||||||
val cmdRouter = Module(new RoccCommandRouter(roccOpcodes)(coreParams))
|
|
||||||
cmdRouter.io.in <> core.io.rocc.cmd
|
|
||||||
|
|
||||||
val roccs = buildRocc.zipWithIndex.map { case (accelParams, i) =>
|
|
||||||
val rocc = accelParams.generator(dcacheParams.alterPartial({
|
|
||||||
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))
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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))
|
|
||||||
|
|
||||||
ptwPorts ++= roccs.flatMap(_.io.ptw)
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
scratch.foreach { lm => lm.module.io.dmem +=: dcPorts }
|
|
||||||
|
|
||||||
require(dcPorts.size == core.dcacheArbPorts)
|
|
||||||
val dcArb = Module(new HellaCacheArbiter(dcPorts.size)(dcacheParams))
|
|
||||||
dcArb.io.requestor <> dcPorts
|
|
||||||
dcache.module.io.cpu <> dcArb.io.mem
|
|
||||||
|
|
||||||
if (nFPUPorts == 0) {
|
|
||||||
fpuOpt.foreach { fpu =>
|
|
||||||
fpu.io.cp_req.valid := Bool(false)
|
|
||||||
fpu.io.cp_resp.ready := Bool(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -155,7 +155,7 @@ class CSRFileIO(implicit p: Parameters) extends CoreBundle {
|
|||||||
val time = UInt(OUTPUT, xLen)
|
val time = UInt(OUTPUT, xLen)
|
||||||
val fcsr_rm = Bits(OUTPUT, FPConstants.RM_SZ)
|
val fcsr_rm = Bits(OUTPUT, FPConstants.RM_SZ)
|
||||||
val fcsr_flags = Valid(Bits(width = FPConstants.FLAGS_SZ)).flip
|
val fcsr_flags = Valid(Bits(width = FPConstants.FLAGS_SZ)).flip
|
||||||
val rocc = new RoCCInterface().flip
|
val rocc_interrupt = Bool(INPUT)
|
||||||
val interrupt = Bool(OUTPUT)
|
val interrupt = Bool(OUTPUT)
|
||||||
val interrupt_cause = UInt(OUTPUT, xLen)
|
val interrupt_cause = UInt(OUTPUT, xLen)
|
||||||
val bp = Vec(nBreakpoints, new BP).asOutput
|
val bp = Vec(nBreakpoints, new BP).asOutput
|
||||||
@ -252,7 +252,7 @@ class CSRFile(implicit p: Parameters) extends CoreModule()(p)
|
|||||||
val reg_hpmcounter = reg_hpmevent.map(e => WideCounter(64, ((UInt(0) +: io.events): Seq[UInt])(e)))
|
val reg_hpmcounter = reg_hpmevent.map(e => WideCounter(64, ((UInt(0) +: io.events): Seq[UInt])(e)))
|
||||||
|
|
||||||
val mip = Wire(init=reg_mip)
|
val mip = Wire(init=reg_mip)
|
||||||
mip.rocc := io.rocc.interrupt
|
mip.rocc := io.rocc_interrupt
|
||||||
val read_mip = mip.asUInt & supported_interrupts
|
val read_mip = mip.asUInt & supported_interrupts
|
||||||
|
|
||||||
val pending_interrupts = read_mip & reg_mie
|
val pending_interrupts = read_mip & reg_mie
|
||||||
|
@ -5,7 +5,7 @@ package uncore.agents
|
|||||||
|
|
||||||
import Chisel._
|
import Chisel._
|
||||||
import config._
|
import config._
|
||||||
import junctions.PAddrBits
|
import rocket.PAddrBits
|
||||||
import uncore.tilelink._
|
import uncore.tilelink._
|
||||||
import uncore.converters._
|
import uncore.converters._
|
||||||
import uncore.coherence._
|
import uncore.coherence._
|
||||||
|
@ -5,7 +5,7 @@ package uncore.agents
|
|||||||
|
|
||||||
import Chisel._
|
import Chisel._
|
||||||
import scala.reflect.ClassTag
|
import scala.reflect.ClassTag
|
||||||
import junctions.PAddrBits
|
import rocket.PAddrBits
|
||||||
import uncore.coherence._
|
import uncore.coherence._
|
||||||
import uncore.tilelink._
|
import uncore.tilelink._
|
||||||
import uncore.constants._
|
import uncore.constants._
|
||||||
|
@ -398,7 +398,7 @@ class AHBBridge(supportAtomics: Boolean = true)(implicit val p: Parameters) exte
|
|||||||
|
|
||||||
// Hasti and TileLink widths must agree at this point in the topology
|
// Hasti and TileLink widths must agree at this point in the topology
|
||||||
require (tlDataBits == hastiDataBits)
|
require (tlDataBits == hastiDataBits)
|
||||||
require (p(PAddrBits) == hastiAddrBits)
|
require (p(rocket.PAddrBits) == hastiAddrBits)
|
||||||
|
|
||||||
// AHB does not permit bursts to cross a 1KB boundary
|
// AHB does not permit bursts to cross a 1KB boundary
|
||||||
require (tlDataBits * tlDataBeats <= 1024*8)
|
require (tlDataBits * tlDataBeats <= 1024*8)
|
||||||
|
@ -5,7 +5,7 @@ package uncore.converters
|
|||||||
|
|
||||||
import Chisel._
|
import Chisel._
|
||||||
import util.{ReorderQueue, DecoupledHelper}
|
import util.{ReorderQueue, DecoupledHelper}
|
||||||
import junctions.PAddrBits
|
import rocket.PAddrBits
|
||||||
import uncore.tilelink._
|
import uncore.tilelink._
|
||||||
import uncore.util._
|
import uncore.util._
|
||||||
import uncore.constants._
|
import uncore.constants._
|
||||||
|
@ -65,7 +65,7 @@ trait HasTileLinkParameters {
|
|||||||
val tlMaxManagerXacts = tlExternal.maxManagerXacts
|
val tlMaxManagerXacts = tlExternal.maxManagerXacts
|
||||||
val tlClientXactIdBits = log2Up(tlMaxClientXacts*tlMaxClientsPerPort)
|
val tlClientXactIdBits = log2Up(tlMaxClientXacts*tlMaxClientsPerPort)
|
||||||
val tlManagerXactIdBits = log2Up(tlMaxManagerXacts)
|
val tlManagerXactIdBits = log2Up(tlMaxManagerXacts)
|
||||||
val tlBlockAddrBits = p(PAddrBits) - p(CacheBlockOffsetBits)
|
val tlBlockAddrBits = p(rocket.PAddrBits) - p(CacheBlockOffsetBits)
|
||||||
val tlDataBeats = tlExternal.dataBeats
|
val tlDataBeats = tlExternal.dataBeats
|
||||||
val tlDataBits = tlExternal.dataBitsPerBeat
|
val tlDataBits = tlExternal.dataBitsPerBeat
|
||||||
val tlDataBytes = tlDataBits/8
|
val tlDataBytes = tlDataBits/8
|
||||||
|
@ -5,7 +5,7 @@ package uncore.util
|
|||||||
|
|
||||||
import Chisel._
|
import Chisel._
|
||||||
import config.{Parameters, Field}
|
import config.{Parameters, Field}
|
||||||
import junctions.PAddrBits
|
import rocket.PAddrBits
|
||||||
import util.ParameterizedBundle
|
import util.ParameterizedBundle
|
||||||
import uncore.constants._
|
import uncore.constants._
|
||||||
|
|
||||||
|
@ -4,30 +4,13 @@ package unittest
|
|||||||
|
|
||||||
import Chisel._
|
import Chisel._
|
||||||
import config._
|
import config._
|
||||||
import junctions._
|
|
||||||
import rocketchip.{BaseConfig, BasePlatformConfig}
|
import rocketchip.{BaseConfig, BasePlatformConfig}
|
||||||
|
|
||||||
class WithJunctionsUnitTests extends Config((site, here, up) => {
|
|
||||||
case HastiId => "HastiTest"
|
|
||||||
case HastiKey("HastiTest") => HastiParameters(addrBits = 32, dataBits = 64)
|
|
||||||
case NastiKey => NastiParameters(addrBits = 32, dataBits = 64, idBits = 4)
|
|
||||||
case junctions.PAddrBits => 32
|
|
||||||
case rocket.XLen => 64
|
|
||||||
case UnitTests => (p: Parameters) => Seq(
|
|
||||||
Module(new junctions.MultiWidthFifoTest),
|
|
||||||
Module(new junctions.HastiTest()(p)))
|
|
||||||
})
|
|
||||||
|
|
||||||
class JunctionsUnitTestConfig extends Config(new WithJunctionsUnitTests ++ new BasePlatformConfig)
|
|
||||||
|
|
||||||
class WithUncoreUnitTests extends Config((site, here, up) => {
|
class WithUncoreUnitTests extends Config((site, here, up) => {
|
||||||
case uncore.tilelink.TLId => "L1toL2"
|
case uncore.tilelink.TLId => "L1toL2"
|
||||||
case UnitTests => (q: Parameters) => {
|
case UnitTests => (q: Parameters) => {
|
||||||
implicit val p = q
|
implicit val p = q
|
||||||
Seq(
|
Seq(
|
||||||
Module(new uncore.devices.ROMSlaveTest()),
|
|
||||||
Module(new uncore.devices.TileLinkRAMTest()),
|
|
||||||
Module(new uncore.converters.TileLinkWidthAdapterTest()),
|
|
||||||
Module(new uncore.tilelink2.TLFuzzRAMTest),
|
Module(new uncore.tilelink2.TLFuzzRAMTest),
|
||||||
Module(new uncore.ahb.AHBBridgeTest),
|
Module(new uncore.ahb.AHBBridgeTest),
|
||||||
Module(new uncore.apb.APBBridgeTest),
|
Module(new uncore.apb.APBBridgeTest),
|
||||||
@ -36,7 +19,7 @@ class WithUncoreUnitTests extends Config((site, here, up) => {
|
|||||||
Module(new uncore.axi4.AXI4BridgeTest)) }
|
Module(new uncore.axi4.AXI4BridgeTest)) }
|
||||||
})
|
})
|
||||||
|
|
||||||
class UncoreUnitTestConfig extends Config(new WithUncoreUnitTests ++ new BaseConfig)
|
class UncoreUnitTestConfig extends Config(new WithUncoreUnitTests ++ new BasePlatformConfig)
|
||||||
|
|
||||||
class WithTLSimpleUnitTests extends Config((site, here, up) => {
|
class WithTLSimpleUnitTests extends Config((site, here, up) => {
|
||||||
case UnitTests => (q: Parameters) => {
|
case UnitTests => (q: Parameters) => {
|
||||||
|
Loading…
Reference in New Issue
Block a user