2016-08-11 02:20:00 +02:00
|
|
|
// See LICENSE for license details.
|
|
|
|
|
|
|
|
package coreplex
|
|
|
|
|
|
|
|
import Chisel._
|
|
|
|
import junctions._
|
|
|
|
import uncore.tilelink._
|
|
|
|
import uncore.coherence._
|
|
|
|
import uncore.agents._
|
|
|
|
import uncore.devices._
|
|
|
|
import uncore.converters._
|
|
|
|
import rocket._
|
|
|
|
import rocket.Util._
|
2016-09-15 22:04:01 +02:00
|
|
|
import util.ConfigUtils._
|
2016-09-11 08:39:29 +02:00
|
|
|
import rocketchip.{GlobalAddrMap, NCoreplexExtClients}
|
2016-08-11 02:20:00 +02:00
|
|
|
import cde.{Parameters, Config, Dump, Knob, CDEMatchError}
|
|
|
|
|
|
|
|
class BaseCoreplexConfig extends Config (
|
|
|
|
topDefinitions = { (pname,site,here) =>
|
|
|
|
type PF = PartialFunction[Any,Any]
|
|
|
|
def findBy(sname:Any):Any = here[PF](site[Any](sname))(pname)
|
2016-09-02 23:56:00 +02:00
|
|
|
lazy val innerDataBits = site(XLen)
|
2016-08-11 02:20:00 +02:00
|
|
|
lazy val innerDataBeats = (8 * site(CacheBlockBytes)) / innerDataBits
|
|
|
|
pname match {
|
|
|
|
//Memory Parameters
|
|
|
|
case PAddrBits => 32
|
|
|
|
case PgLevels => if (site(XLen) == 64) 3 /* Sv39 */ else 2 /* Sv32 */
|
|
|
|
case ASIdBits => 7
|
|
|
|
//Params used by all caches
|
|
|
|
case NSets => findBy(CacheName)
|
|
|
|
case NWays => findBy(CacheName)
|
|
|
|
case RowBits => findBy(CacheName)
|
|
|
|
case NTLBEntries => findBy(CacheName)
|
|
|
|
case CacheIdBits => findBy(CacheName)
|
|
|
|
case SplitMetadata => findBy(CacheName)
|
|
|
|
case "L1I" => {
|
|
|
|
case NSets => Knob("L1I_SETS") //64
|
|
|
|
case NWays => Knob("L1I_WAYS") //4
|
|
|
|
case RowBits => site(TLKey("L1toL2")).dataBitsPerBeat
|
|
|
|
case NTLBEntries => 8
|
|
|
|
case CacheIdBits => 0
|
|
|
|
case SplitMetadata => false
|
|
|
|
}:PF
|
|
|
|
case "L1D" => {
|
|
|
|
case NSets => Knob("L1D_SETS") //64
|
|
|
|
case NWays => Knob("L1D_WAYS") //4
|
|
|
|
case RowBits => site(TLKey("L1toL2")).dataBitsPerBeat
|
|
|
|
case NTLBEntries => 8
|
|
|
|
case CacheIdBits => 0
|
|
|
|
case SplitMetadata => false
|
|
|
|
}:PF
|
|
|
|
case ECCCode => None
|
|
|
|
case Replacer => () => new RandomReplacement(site(NWays))
|
|
|
|
//L1InstCache
|
|
|
|
case BtbKey => BtbParameters()
|
|
|
|
//L1DataCache
|
2016-08-18 01:53:39 +02:00
|
|
|
case DCacheKey => DCacheConfig(nMSHRs = site(Knob("L1D_MSHRS")))
|
2016-09-03 00:59:16 +02:00
|
|
|
case DataScratchpadSize => 0
|
2016-08-11 02:20:00 +02:00
|
|
|
//L2 Memory System Params
|
2016-08-17 05:04:02 +02:00
|
|
|
case AmoAluOperandBits => site(XLen)
|
2016-08-11 02:20:00 +02:00
|
|
|
case NAcquireTransactors => 7
|
|
|
|
case L2StoreDataQueueDepth => 1
|
|
|
|
case L2DirectoryRepresentation => new NullRepresentation(site(NTiles))
|
|
|
|
case BuildL2CoherenceManager => (id: Int, p: Parameters) =>
|
|
|
|
Module(new L2BroadcastHub()(p.alterPartial({
|
|
|
|
case InnerTLId => "L1toL2"
|
|
|
|
case OuterTLId => "L2toMC" })))
|
|
|
|
case NCachedTileLinkPorts => 1
|
|
|
|
case NUncachedTileLinkPorts => 1
|
|
|
|
//Tile Constants
|
|
|
|
case BuildTiles => {
|
2016-09-02 09:05:40 +02:00
|
|
|
List.tabulate(site(NTiles)){ i => (r: Bool, p: Parameters) =>
|
2016-08-11 02:20:00 +02:00
|
|
|
Module(new RocketTile(resetSignal = r)(p.alterPartial({
|
2016-09-02 09:05:40 +02:00
|
|
|
case TileId => i
|
2016-08-11 02:20:00 +02:00
|
|
|
case TLId => "L1toL2"
|
|
|
|
case NUncachedTileLinkPorts => 1 + site(RoccNMemChannels)
|
|
|
|
})))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case BuildRoCC => Nil
|
|
|
|
case RoccNMemChannels => site(BuildRoCC).map(_.nMemChannels).foldLeft(0)(_ + _)
|
|
|
|
case RoccNPTWPorts => site(BuildRoCC).map(_.nPTWPorts).foldLeft(0)(_ + _)
|
|
|
|
//Rocket Core Constants
|
2016-08-17 05:04:02 +02:00
|
|
|
case CoreInstBits => if (site(UseCompressed)) 16 else 32
|
2016-08-11 02:20:00 +02:00
|
|
|
case FetchWidth => if (site(UseCompressed)) 2 else 1
|
|
|
|
case RetireWidth => 1
|
|
|
|
case UseVM => true
|
|
|
|
case UseUser => true
|
|
|
|
case UseDebug => true
|
|
|
|
case NBreakpoints => 1
|
2016-08-27 05:27:27 +02:00
|
|
|
case NPerfCounters => 0
|
|
|
|
case NPerfEvents => 0
|
2016-08-11 02:20:00 +02:00
|
|
|
case FastLoadWord => true
|
|
|
|
case FastLoadByte => false
|
2016-09-13 11:32:00 +02:00
|
|
|
case FastJAL => false
|
2016-08-11 02:20:00 +02:00
|
|
|
case XLen => 64
|
2016-08-17 09:57:35 +02:00
|
|
|
case FPUKey => Some(FPUConfig())
|
2016-09-13 01:50:08 +02:00
|
|
|
case MulDivKey => Some(MulDivConfig(mulUnroll = 8, mulEarlyOut = (site(XLen) > 32), divEarlyOut = true))
|
2016-08-17 09:57:35 +02:00
|
|
|
case UseAtomics => true
|
|
|
|
case UseCompressed => true
|
2016-08-11 02:20:00 +02:00
|
|
|
case DMKey => new DefaultDebugModuleConfig(site(NTiles), site(XLen))
|
|
|
|
case NCustomMRWCSRs => 0
|
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
|
|
|
case MtvecInit => None
|
2016-08-11 02:20:00 +02:00
|
|
|
case MtvecWritable => true
|
|
|
|
//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 TLKey("L1toL2") => {
|
|
|
|
val useMEI = site(NTiles) <= 1 && site(NCachedTileLinkPorts) <= 1
|
|
|
|
TileLinkParameters(
|
|
|
|
coherencePolicy = (
|
|
|
|
if (useMEI) new MEICoherence(site(L2DirectoryRepresentation))
|
|
|
|
else new MESICoherence(site(L2DirectoryRepresentation))),
|
|
|
|
nManagers = site(NBanksPerMemoryChannel)*site(NMemoryChannels) + 1 /* MMIO */,
|
|
|
|
nCachingClients = site(NCachedTileLinkPorts),
|
2016-09-15 09:38:46 +02:00
|
|
|
nCachelessClients = site(NCoreplexExtClients) + site(NUncachedTileLinkPorts),
|
2016-08-11 02:20:00 +02:00
|
|
|
maxClientXacts = max_int(
|
|
|
|
// L1 cache
|
2016-08-18 01:53:39 +02:00
|
|
|
site(DCacheKey).nMSHRs + 1 /* IOMSHR */,
|
2016-08-11 02:20:00 +02:00
|
|
|
// RoCC
|
|
|
|
if (site(BuildRoCC).isEmpty) 1 else site(RoccMaxTaggedMemXacts)),
|
|
|
|
maxClientsPerPort = if (site(BuildRoCC).isEmpty) 1 else 2,
|
|
|
|
maxManagerXacts = site(NAcquireTransactors) + 2,
|
|
|
|
dataBeats = innerDataBeats,
|
|
|
|
dataBits = site(CacheBlockBytes)*8)
|
|
|
|
}
|
|
|
|
case TLKey("L2toMC") =>
|
|
|
|
TileLinkParameters(
|
|
|
|
coherencePolicy = new MEICoherence(
|
|
|
|
new NullRepresentation(site(NBanksPerMemoryChannel))),
|
|
|
|
nManagers = 1,
|
|
|
|
nCachingClients = site(NBanksPerMemoryChannel),
|
|
|
|
nCachelessClients = 0,
|
|
|
|
maxClientXacts = 1,
|
|
|
|
maxClientsPerPort = site(NAcquireTransactors) + 2,
|
|
|
|
maxManagerXacts = 1,
|
|
|
|
dataBeats = innerDataBeats,
|
|
|
|
dataBits = site(CacheBlockBytes)*8)
|
|
|
|
case TLKey("Outermost") => site(TLKey("L2toMC")).copy(
|
|
|
|
maxClientXacts = site(NAcquireTransactors) + 2,
|
|
|
|
maxClientsPerPort = site(NBanksPerMemoryChannel),
|
|
|
|
dataBeats = site(MIFDataBeats))
|
|
|
|
case TLKey("L2toMMIO") => {
|
|
|
|
TileLinkParameters(
|
|
|
|
coherencePolicy = new MICoherence(
|
|
|
|
new NullRepresentation(site(NBanksPerMemoryChannel))),
|
2016-09-15 03:09:27 +02:00
|
|
|
nManagers = 1,
|
2016-08-11 02:20:00 +02:00
|
|
|
nCachingClients = 0,
|
|
|
|
nCachelessClients = 1,
|
|
|
|
maxClientXacts = 4,
|
|
|
|
maxClientsPerPort = 1,
|
|
|
|
maxManagerXacts = 1,
|
|
|
|
dataBeats = innerDataBeats,
|
|
|
|
dataBits = site(CacheBlockBytes) * 8)
|
|
|
|
}
|
|
|
|
case TLKey("MMIO_Outermost") => site(TLKey("L2toMMIO")).copy(dataBeats = site(MIFDataBeats))
|
|
|
|
|
|
|
|
case BootROMFile => "./bootrom/bootrom.img"
|
2016-09-13 20:29:26 +02:00
|
|
|
case NTiles => 1
|
2016-08-11 02:20:00 +02:00
|
|
|
case NBanksPerMemoryChannel => Knob("NBANKS_PER_MEM_CHANNEL")
|
|
|
|
case BankIdLSB => 0
|
|
|
|
case CacheBlockBytes => Dump("CACHE_BLOCK_BYTES", 64)
|
|
|
|
case CacheBlockOffsetBits => log2Up(here(CacheBlockBytes))
|
|
|
|
case EnableL2Logging => false
|
|
|
|
case _ => throw new CDEMatchError
|
|
|
|
}},
|
|
|
|
knobValues = {
|
|
|
|
case "NBANKS_PER_MEM_CHANNEL" => 1
|
|
|
|
case "L1D_MSHRS" => 2
|
|
|
|
case "L1D_SETS" => 64
|
|
|
|
case "L1D_WAYS" => 4
|
|
|
|
case "L1I_SETS" => 64
|
|
|
|
case "L1I_WAYS" => 4
|
|
|
|
case _ => throw new CDEMatchError
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
class WithNCores(n: Int) extends Config(
|
2016-09-13 20:29:26 +02:00
|
|
|
(pname,site,here) => pname match {
|
|
|
|
case NTiles => n
|
|
|
|
})
|
2016-08-11 02:20:00 +02:00
|
|
|
|
|
|
|
class WithNBanksPerMemChannel(n: Int) extends Config(
|
|
|
|
knobValues = {
|
|
|
|
case "NBANKS_PER_MEM_CHANNEL" => n
|
|
|
|
case _ => throw new CDEMatchError
|
|
|
|
})
|
|
|
|
|
2016-09-03 00:59:16 +02:00
|
|
|
class WithDataScratchpad(n: Int) extends Config(
|
|
|
|
(pname,site,here) => pname match {
|
|
|
|
case DataScratchpadSize => n
|
|
|
|
case NSets if site(CacheName) == "L1D" => n / site(CacheBlockBytes)
|
|
|
|
case _ => throw new CDEMatchError
|
|
|
|
})
|
|
|
|
|
2016-08-11 02:20:00 +02:00
|
|
|
class WithL2Cache extends Config(
|
|
|
|
(pname,site,here) => pname match {
|
|
|
|
case "L2_CAPACITY_IN_KB" => Knob("L2_CAPACITY_IN_KB")
|
|
|
|
case "L2Bank" => {
|
|
|
|
case NSets => (((here[Int]("L2_CAPACITY_IN_KB")*1024) /
|
|
|
|
site(CacheBlockBytes)) /
|
|
|
|
(site(NBanksPerMemoryChannel)*site(NMemoryChannels))) /
|
|
|
|
site(NWays)
|
|
|
|
case NWays => Knob("L2_WAYS")
|
|
|
|
case RowBits => site(TLKey(site(TLId))).dataBitsPerBeat
|
|
|
|
case CacheIdBits => log2Ceil(site(NMemoryChannels) * site(NBanksPerMemoryChannel))
|
|
|
|
case SplitMetadata => Knob("L2_SPLIT_METADATA")
|
|
|
|
}: PartialFunction[Any,Any]
|
|
|
|
case NAcquireTransactors => 2
|
|
|
|
case NSecondaryMisses => 4
|
|
|
|
case L2DirectoryRepresentation => new FullRepresentation(site(NTiles))
|
|
|
|
case BuildL2CoherenceManager => (id: Int, p: Parameters) =>
|
|
|
|
Module(new L2HellaCacheBank()(p.alterPartial({
|
|
|
|
case CacheId => id
|
|
|
|
case CacheName => "L2Bank"
|
|
|
|
case InnerTLId => "L1toL2"
|
|
|
|
case OuterTLId => "L2toMC"})))
|
|
|
|
case L2Replacer => () => new SeqRandom(site(NWays))
|
|
|
|
case _ => throw new CDEMatchError
|
|
|
|
},
|
|
|
|
knobValues = { case "L2_WAYS" => 8; case "L2_CAPACITY_IN_KB" => 2048; case "L2_SPLIT_METADATA" => false; case _ => throw new CDEMatchError }
|
|
|
|
)
|
|
|
|
|
|
|
|
class WithBufferlessBroadcastHub extends Config(
|
|
|
|
(pname, site, here) => pname match {
|
|
|
|
case BuildL2CoherenceManager => (id: Int, p: Parameters) =>
|
|
|
|
Module(new BufferlessBroadcastHub()(p.alterPartial({
|
|
|
|
case InnerTLId => "L1toL2"
|
|
|
|
case OuterTLId => "L2toMC" })))
|
|
|
|
})
|
|
|
|
|
|
|
|
/**
|
|
|
|
* WARNING!!! IGNORE AT YOUR OWN PERIL!!!
|
|
|
|
*
|
|
|
|
* There is a very restrictive set of conditions under which the stateless
|
|
|
|
* bridge will function properly. There can only be a single tile. This tile
|
|
|
|
* MUST use the blocking data cache (L1D_MSHRS == 0) and MUST NOT have an
|
|
|
|
* uncached channel capable of writes (i.e. a RoCC accelerator).
|
|
|
|
*
|
|
|
|
* This is because the stateless bridge CANNOT generate probes, so if your
|
|
|
|
* system depends on coherence between channels in any way,
|
|
|
|
* DO NOT use this configuration.
|
|
|
|
*/
|
|
|
|
class WithStatelessBridge extends Config (
|
|
|
|
topDefinitions = (pname, site, here) => pname match {
|
|
|
|
case BuildL2CoherenceManager => (id: Int, p: Parameters) =>
|
|
|
|
Module(new ManagerToClientStatelessBridge()(p.alterPartial({
|
|
|
|
case InnerTLId => "L1toL2"
|
|
|
|
case OuterTLId => "L2toMC" })))
|
|
|
|
},
|
|
|
|
knobValues = {
|
|
|
|
case "L1D_MSHRS" => 0
|
|
|
|
case _ => throw new CDEMatchError
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
class WithPLRU extends Config(
|
|
|
|
(pname, site, here) => pname match {
|
|
|
|
case L2Replacer => () => new SeqPLRU(site(NSets), site(NWays))
|
|
|
|
case _ => throw new CDEMatchError
|
|
|
|
})
|
|
|
|
|
|
|
|
class WithL2Capacity(size_kb: Int) extends Config(
|
|
|
|
knobValues = {
|
|
|
|
case "L2_CAPACITY_IN_KB" => size_kb
|
|
|
|
case _ => throw new CDEMatchError
|
|
|
|
})
|
|
|
|
|
|
|
|
class WithNL2Ways(n: Int) extends Config(
|
|
|
|
knobValues = {
|
|
|
|
case "L2_WAYS" => n
|
|
|
|
case _ => throw new CDEMatchError
|
|
|
|
})
|
|
|
|
|
|
|
|
class WithRV32 extends Config(
|
|
|
|
(pname,site,here) => pname match {
|
|
|
|
case XLen => 32
|
2016-09-07 08:53:12 +02:00
|
|
|
case FPUKey => Some(FPUConfig(divSqrt = false))
|
2016-08-11 02:20:00 +02:00
|
|
|
case _ => throw new CDEMatchError
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
class WithBlockingL1 extends Config (
|
|
|
|
knobValues = {
|
|
|
|
case "L1D_MSHRS" => 0
|
|
|
|
case _ => throw new CDEMatchError
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
class WithSmallCores extends Config (
|
2016-09-07 10:58:25 +02:00
|
|
|
topDefinitions = { (pname,site,here) => pname match {
|
|
|
|
case MulDivKey => Some(MulDivConfig())
|
|
|
|
case FPUKey => None
|
|
|
|
case UseVM => false
|
|
|
|
case UseUser => false
|
|
|
|
case NTLBEntries => 4
|
|
|
|
case BtbKey => BtbParameters(nEntries = 0)
|
|
|
|
case NAcquireTransactors => 2
|
|
|
|
case _ => throw new CDEMatchError
|
|
|
|
}},
|
2016-08-11 02:20:00 +02:00
|
|
|
knobValues = {
|
|
|
|
case "L1D_SETS" => 64
|
|
|
|
case "L1D_WAYS" => 1
|
|
|
|
case "L1I_SETS" => 64
|
|
|
|
case "L1I_WAYS" => 1
|
|
|
|
case "L1D_MSHRS" => 0
|
|
|
|
case _ => throw new CDEMatchError
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
class WithRoccExample extends Config(
|
|
|
|
(pname, site, here) => pname match {
|
|
|
|
case BuildRoCC => Seq(
|
|
|
|
RoccParameters(
|
|
|
|
opcodes = OpcodeSet.custom0,
|
|
|
|
generator = (p: Parameters) => Module(new AccumulatorExample()(p))),
|
|
|
|
RoccParameters(
|
|
|
|
opcodes = OpcodeSet.custom1,
|
|
|
|
generator = (p: Parameters) => Module(new TranslatorExample()(p)),
|
|
|
|
nPTWPorts = 1),
|
|
|
|
RoccParameters(
|
|
|
|
opcodes = OpcodeSet.custom2,
|
|
|
|
generator = (p: Parameters) => Module(new CharacterCountExample()(p))))
|
|
|
|
|
|
|
|
case RoccMaxTaggedMemXacts => 1
|
|
|
|
case _ => throw new CDEMatchError
|
|
|
|
})
|
|
|
|
|
|
|
|
class WithSplitL2Metadata extends Config(
|
|
|
|
knobValues = { case "L2_SPLIT_METADATA" => true; case _ => throw new CDEMatchError })
|