1
0

Heterogeneous Tiles (#550)

Fundamental new features:

* Added tile package: This package is intended to hold components re-usable across different types of tile. Will be the future location of TL2-RoCC accelerators and new diplomatic versions of intra-tile interfaces.
* Adopted [ModuleName]Params convention: Code base was very inconsistent about what to name case classes that provide parameters to modules. Settled on calling them [ModuleName]Params to distinguish them from config.Parameters and config.Config. So far applied mostly only to case classes defined within rocket and tile.
* Defined RocketTileParams: A nested case class containing case classes for all the components of a tile (L1 caches and core). Allows all such parameters to vary per-tile.
* Defined RocketCoreParams: All the parameters that can be varied per-core.
* Defined L1CacheParams: A trait defining the parameters common to L1 caches, made concrete in different derived case classes.
* Defined RocketTilesKey: A sequence of RocketTileParams, one for every tile to be created.
* Provided HeterogeneousDualCoreConfig: An example of making a heterogeneous chip with two cores, one big and one little.
* Changes to legacy code: ReplacementPolicy moved to package util. L1Metadata moved to package tile. Legacy L2 cache agent removed because it can no longer share the metadata array implementation with the L1. Legacy GroundTests on life support.

Additional changes that got rolled in along the way:

* rocket: 	Fix critical path through BTB for I$ index bits > pgIdxBits
* coreplex: tiles connected via :=*
* groundtest: updated to use TileParams
* tilelink: cache cork requirements are relaxed to allow more cacheless masters
This commit is contained in:
Henry Cook 2017-02-09 13:59:09 -08:00 committed by GitHub
parent f9acd4988c
commit e8c8d2af71
57 changed files with 1084 additions and 1933 deletions

View File

@ -1,9 +1,35 @@
git: git:
submodules: false submodules: false
language: scala language: scala
sudo: required # run on new infrastructure
services: sudo: false
- docker cache:
apt: true
directories:
$HOME/.ivy2
regression/install
emulator/verilator
# packages needed to build riscv-tools
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- gcc-4.8
- g++-4.8
- gperf
- autoconf
- automake
- autotools-dev
- libmpc-dev
- libmpfr-dev
- libgmp-dev
- gawk
- build-essential
- bison
- flex
- texinfo
env: env:
matrix: matrix:
@ -21,8 +47,15 @@ branches:
- boom - boom
- /^hurricane.*$/ - /^hurricane.*$/
install:
- make tools verilator -C regression SUITE=none
before_install: before_install:
- docker pull hcook/docker-riscv:chisel - export CXX=g++-4.8 CC=gcc-4.8
script: script:
- docker run -v $(pwd):/opt/riscv/test hcook/docker-riscv:chisel /bin/sh -c "make emulator-ndebug -C regression SUITE=$SUITE; make emulator-regression-tests -C regression SUITE=$SUITE" - make emulator-ndebug -C regression SUITE=$SUITE
- travis_wait make emulator-regression-tests -C regression SUITE=$SUITE
before_cache:
- ls -t regression/install | tail -n+2 | sed s@^@regression/install/@ | xargs rm -rf

View File

@ -5,9 +5,9 @@ package coreplex
import Chisel._ import Chisel._
import config._ import config._
import diplomacy._ import diplomacy._
import rocket.{TileInterrupts, XLen} import tile.XLen
import tile.TileInterrupts
import uncore.tilelink2._ import uncore.tilelink2._
import uncore.util._
import util._ import util._
/** Widths of various points in the SoC */ /** Widths of various points in the SoC */
@ -15,6 +15,9 @@ case class TLBusConfig(beatBytes: Int)
case object CBusConfig extends Field[TLBusConfig] case object CBusConfig extends Field[TLBusConfig]
case object L1toL2Config extends Field[TLBusConfig] case object L1toL2Config extends Field[TLBusConfig]
// These parameters apply to all caches, for now
case object CacheBlockBytes extends Field[Int]
/** L2 Broadcast Hub configuration */ /** L2 Broadcast Hub configuration */
case class BroadcastConfig( case class BroadcastConfig(
nTrackers: Int = 4, nTrackers: Int = 4,
@ -42,10 +45,11 @@ case object BootROMFile extends Field[String]
trait HasCoreplexParameters { trait HasCoreplexParameters {
implicit val p: Parameters implicit val p: Parameters
lazy val tilesParams = p(RocketTilesKey)
lazy val cbusConfig = p(CBusConfig) lazy val cbusConfig = p(CBusConfig)
lazy val l1tol2Config = p(L1toL2Config) lazy val l1tol2Config = p(L1toL2Config)
lazy val nTiles = p(uncore.devices.NTiles) lazy val nTiles = tilesParams.size
lazy val hasSupervisor = p(rocket.UseVM) lazy val hasSupervisor = tilesParams.exists(_.core.useVM) // TODO ask andrew about this
lazy val l2Config = p(BankedL2Config) lazy val l2Config = p(BankedL2Config)
} }

View File

@ -1,56 +0,0 @@
// 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

View File

@ -7,6 +7,7 @@ import Chisel._
import config._ import config._
import diplomacy._ import diplomacy._
import rocket._ import rocket._
import tile._
import uncore.converters._ import uncore.converters._
import uncore.devices._ import uncore.devices._
import uncore.tilelink2._ import uncore.tilelink2._
@ -14,71 +15,42 @@ import uncore.util._
import util._ import util._
class BaseCoreplexConfig extends Config ((site, here, up) => { class BaseCoreplexConfig extends Config ((site, here, up) => {
//Memory Parameters
case PAddrBits => 32 case PAddrBits => 32
case PgLevels => if (site(XLen) == 64) 3 /* Sv39 */ else 2 /* Sv32 */ case PgLevels => if (site(XLen) == 64) 3 /* Sv39 */ else 2 /* Sv32 */
case ASIdBits => 7 case ASIdBits => 7
case XLen => 64 // Applies to all cores
case BuildCore => (p: Parameters) => new Rocket()(p)
case RocketCrossing => Synchronous case RocketCrossing => Synchronous
//Params used by all caches case RocketTilesKey => Nil
case CacheName("L1I") => CacheConfig(
nSets = 64,
nWays = 4,
rowBits = site(L1toL2Config).beatBytes*8,
nTLBEntries = 8,
cacheIdBits = 0,
splitMetadata = false)
case CacheName("L1D") => CacheConfig(
nSets = 64,
nWays = 4,
rowBits = site(L1toL2Config).beatBytes*8,
nTLBEntries = 8,
cacheIdBits = 0,
splitMetadata = false)
case ECCCode => None
case Replacer => () => new RandomReplacement(site(site(CacheName)).nWays)
//L1InstCache
case BtbKey => BtbParameters()
//L1DataCache
case DCacheKey => DCacheConfig(nMSHRs = 2)
case DataScratchpadSize => 0
//Tile Constants
case BuildRoCC => Nil
//Rocket Core Constants
case CoreInstBits => if (site(UseCompressed)) 16 else 32
case FetchWidth => if (site(UseCompressed)) 2 else 1
case RetireWidth => 1
case UseVM => true
case UseUser => false
case UseDebug => true
case NBreakpoints => 1
case NPerfCounters => 0
case NPerfEvents => 0
case FastLoadWord => true
case FastLoadByte => false
case FastJAL => false
case XLen => 64
case FPUKey => Some(FPUConfig())
case MulDivKey => Some(MulDivConfig(mulUnroll = 8, mulEarlyOut = (site(XLen) > 32), divEarlyOut = true))
case UseAtomics => true
case UseCompressed => true
case DMKey => new DefaultDebugModuleConfig(site(NTiles), site(XLen)) case DMKey => new DefaultDebugModuleConfig(site(NTiles), site(XLen))
case NCustomMRWCSRs => 0 case NTiles => site(RocketTilesKey).size
case MtvecInit => Some(BigInt(0))
case MtvecWritable => true
//Uncore Paramters
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 BootROMFile => "./bootrom/bootrom.img" case BootROMFile => "./bootrom/bootrom.img"
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
}) })
class WithNCores(n: Int) extends Config((site, here, up) => { class WithNBigCores(n: Int) extends Config((site, here, up) => {
case RocketConfigs => List.fill(n){ RocketConfig(site(XLen)) } case RocketTilesKey => {
val big = RocketTileParams(
core = RocketCoreParams(mulDiv = Some(MulDivParams(mulUnroll = 8, mulEarlyOut = true, divEarlyOut = true))),
dcache = Some(DCacheParams(rowBits = site(L1toL2Config).beatBytes*8, nMSHRs = 2)),
icache = Some(ICacheParams(rowBits = site(L1toL2Config).beatBytes*8)))
List.fill(n)(big) ++ up(RocketTilesKey, site)
}
})
class WithNSmallCores(n: Int) extends Config((site, here, up) => {
case RocketTilesKey => {
val small = RocketTileParams(
core = RocketCoreParams(useVM = false, fpu = None),
btb = None,
dcache = Some(DCacheParams(rowBits = site(L1toL2Config).beatBytes*8, nSets = 64, nWays = 1, nTLBEntries = 4, nMSHRs = 0)),
icache = Some(ICacheParams(rowBits = site(L1toL2Config).beatBytes*8, nSets = 64, nWays = 1, nTLBEntries = 4)))
List.fill(n)(small) ++ up(RocketTilesKey, site)
}
}) })
class WithNBanksPerMemChannel(n: Int) extends Config((site, here, up) => { class WithNBanksPerMemChannel(n: Int) extends Config((site, here, up) => {
@ -89,43 +61,50 @@ class WithNTrackersPerBank(n: Int) extends Config((site, here, up) => {
case BroadcastConfig => up(BroadcastConfig, site).copy(nTrackers = n) case BroadcastConfig => up(BroadcastConfig, site).copy(nTrackers = n)
}) })
// This is the number of sets **per way** // This is the number of icache sets for all Rocket tiles
class WithL1ICacheSets(sets: Int) extends Config((site, here, up) => { class WithL1ICacheSets(sets: Int) extends Config((site, here, up) => {
case CacheName("L1I") => up(CacheName("L1I"), site).copy(nSets = sets) case RocketTilesKey => up(RocketTilesKey, site) map { r =>
r.copy(icache = r.icache.map(_.copy(nSets = sets))) }
}) })
// This is the number of sets **per way** // This is the number of icache sets for all Rocket tiles
class WithL1DCacheSets(sets: Int) extends Config((site, here, up) => { class WithL1DCacheSets(sets: Int) extends Config((site, here, up) => {
case CacheName("L1D") => up(CacheName("L1D"), site).copy(nSets = sets) case RocketTilesKey => up(RocketTilesKey, site) map { r =>
r.copy(dcache = r.dcache.map(_.copy(nSets = sets))) }
}) })
class WithL1ICacheWays(ways: Int) extends Config((site, here, up) => { class WithL1ICacheWays(ways: Int) extends Config((site, here, up) => {
case CacheName("L1I") => up(CacheName("L1I"), site).copy(nWays = ways) case RocketTilesKey => up(RocketTilesKey, site) map { r =>
r.copy(icache = r.icache.map(_.copy(nWays = ways)))
}
}) })
class WithL1DCacheWays(ways: Int) extends Config((site, here, up) => { class WithL1DCacheWays(ways: Int) extends Config((site, here, up) => {
case CacheName("L1D") => up(CacheName("L1D"), site).copy(nWays = ways) case RocketTilesKey => up(RocketTilesKey, site) map { r =>
r.copy(dcache = r.dcache.map(_.copy(nWays = ways)))
}
}) })
class WithCacheBlockBytes(linesize: Int) extends Config((site, here, up) => { class WithCacheBlockBytes(linesize: Int) extends Config((site, here, up) => {
case CacheBlockBytes => linesize case CacheBlockBytes => linesize
}) })
class WithDataScratchpad(n: Int) extends Config((site, here, up) => { /** Warning: applies only to the most recently added tile.
case DataScratchpadSize => n * TODO: For now, there can only be a single scratchpad in the design
case CacheName("L1D") => up(CacheName("L1D"), site).copy(nSets = n / site(CacheBlockBytes)) * because its address is hardcoded.
*/
class WithDataScratchpad(size: Int) extends Config((site, here, up) => {
case RocketTilesKey => {
val prev = up(RocketTilesKey, site)
prev.head.copy(
dcache = prev.head.dcache.map(_.copy(nSets = size / site(CacheBlockBytes))),
dataScratchpadBytes = size) +: prev.tail
}
}) })
// TODO: re-add L2 class WithL2Cache extends Config(Parameters.empty) // TODO: re-add L2
class WithL2Cache extends Config((site, here, up) => { class WithL2Capacity(size_kb: Int) extends Config(Parameters.empty) // TODO: re-add L2
case CacheName("L2") => CacheConfig( class WithNL2Ways(n: Int) extends Config(Parameters.empty) // TODO: re-add L2
nSets = 1024,
nWays = 1,
rowBits = site(L1toL2Config).beatBytes*8,
nTLBEntries = 0,
cacheIdBits = 1,
splitMetadata = false)
})
class WithBufferlessBroadcastHub extends Config((site, here, up) => { class WithBufferlessBroadcastHub extends Config((site, here, up) => {
case BroadcastConfig => up(BroadcastConfig, site).copy(bufferless = true) case BroadcastConfig => up(BroadcastConfig, site).copy(bufferless = true)
@ -151,44 +130,39 @@ class WithStatelessBridge extends Config((site, here, up) => {
ww.node :*= cork.node ww.node :*= cork.node
(cork.node, ww.node) (cork.node, ww.node)
}) })
case DCacheKey => up(DCacheKey, site).copy(nMSHRs = 0)
})
class WithL2Capacity(size_kb: Int) extends Config(Parameters.empty) // TODO
class WithNL2Ways(n: Int) extends Config((site, here, up) => {
case CacheName("L2") => up(CacheName("L2"), site).copy(nWays = n)
}) })
class WithRV32 extends Config((site, here, up) => { class WithRV32 extends Config((site, here, up) => {
case XLen => 32 case XLen => 32
case FPUKey => Some(FPUConfig(divSqrt = false)) case RocketTilesKey => up(RocketTilesKey, site) map { r =>
r.copy(core = r.core.copy(
mulDiv = Some(MulDivParams(mulUnroll = 8)),
fpu = r.core.fpu.map(_.copy(divSqrt = false))))
}
}) })
class WithBlockingL1 extends Config((site, here, up) => { class WithBlockingL1 extends Config((site, here, up) => {
case DCacheKey => up(DCacheKey, site).copy(nMSHRs = 0) case RocketTilesKey => up(RocketTilesKey, site) map { r =>
r.copy(dcache = r.dcache.map(_.copy(nMSHRs = 0)))
}
}) })
class WithSmallCores extends Config((site, here, up) => { class WithNBreakpoints(hwbp: Int) extends Config ((site, here, up) => {
case MulDivKey => Some(MulDivConfig()) case RocketTilesKey => up(RocketTilesKey, site) map { r =>
case FPUKey => None r.copy(core = r.core.copy(nBreakpoints = hwbp))
case UseVM => false }
case BtbKey => BtbParameters(nEntries = 0)
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 DCacheKey => up(DCacheKey, site).copy(nMSHRs = 0)
}) })
class WithRoccExample extends Config((site, here, up) => { class WithRoccExample extends Config((site, here, up) => {
case BuildRoCC => Seq( case BuildRoCC => Seq(
RoccParameters( RoCCParams(
opcodes = OpcodeSet.custom0, opcodes = OpcodeSet.custom0,
generator = (p: Parameters) => Module(new AccumulatorExample()(p))), generator = (p: Parameters) => Module(new AccumulatorExample()(p))),
RoccParameters( RoCCParams(
opcodes = OpcodeSet.custom1, opcodes = OpcodeSet.custom1,
generator = (p: Parameters) => Module(new TranslatorExample()(p)), generator = (p: Parameters) => Module(new TranslatorExample()(p)),
nPTWPorts = 1), nPTWPorts = 1),
RoccParameters( RoCCParams(
opcodes = OpcodeSet.custom2, opcodes = OpcodeSet.custom2,
generator = (p: Parameters) => Module(new CharacterCountExample()(p)))) generator = (p: Parameters) => Module(new CharacterCountExample()(p))))
@ -196,23 +170,34 @@ class WithRoccExample extends Config((site, here, up) => {
}) })
class WithDefaultBtb extends Config((site, here, up) => { class WithDefaultBtb extends Config((site, here, up) => {
case BtbKey => BtbParameters() case RocketTilesKey => up(RocketTilesKey, site) map { r =>
r.copy(btb = Some(BTBParams()))
}
}) })
class WithFastMulDiv extends Config((site, here, up) => { class WithFastMulDiv extends Config((site, here, up) => {
case MulDivKey => Some(MulDivConfig(mulUnroll = 8, mulEarlyOut = (site(XLen) > 32), divEarlyOut = true)) case RocketTilesKey => up(RocketTilesKey, site) map { r =>
r.copy(core = r.core.copy(mulDiv = Some(
MulDivParams(mulUnroll = 8, mulEarlyOut = (site(XLen) > 32), divEarlyOut = true)
)))}
}) })
class WithoutMulDiv extends Config((site, here, up) => { class WithoutMulDiv extends Config((site, here, up) => {
case MulDivKey => None case RocketTilesKey => up(RocketTilesKey, site) map { r =>
r.copy(core = r.core.copy(mulDiv = None))
}
}) })
class WithoutFPU extends Config((site, here, up) => { class WithoutFPU extends Config((site, here, up) => {
case FPUKey => None case RocketTilesKey => up(RocketTilesKey, site) map { r =>
r.copy(core = r.core.copy(fpu = None))
}
}) })
class WithFPUWithoutDivSqrt extends Config((site, here, up) => { class WithFPUWithoutDivSqrt extends Config((site, here, up) => {
case FPUKey => Some(FPUConfig(divSqrt = false)) case RocketTilesKey => up(RocketTilesKey, site) map { r =>
r.copy(core = r.core.copy(fpu = r.core.fpu.map(_.copy(divSqrt = false))))
}
}) })
class WithBootROMFile(bootROMFile: String) extends Config((site, here, up) => { class WithBootROMFile(bootROMFile: String) extends Config((site, here, up) => {

View File

@ -6,14 +6,9 @@ import Chisel._
import config._ import config._
import junctions._ import junctions._
import diplomacy._ import diplomacy._
import uncore.tilelink._ import tile._
import uncore.tilelink2._ import uncore.tilelink2._
import uncore.coherence._
import uncore.agents._
import uncore.devices._ import uncore.devices._
import uncore.util._
import uncore.converters._
import rocket._
import util._ import util._
trait CoreplexRISCVPlatform extends CoreplexNetwork { trait CoreplexRISCVPlatform extends CoreplexNetwork {

View File

@ -6,6 +6,7 @@ import Chisel._
import config._ import config._
import diplomacy._ import diplomacy._
import rocket._ import rocket._
import tile._
import uncore.tilelink2._ import uncore.tilelink2._
sealed trait ClockCrossing sealed trait ClockCrossing
@ -13,18 +14,14 @@ case object Synchronous extends ClockCrossing
case object Rational extends ClockCrossing case object Rational extends ClockCrossing
case class Asynchronous(depth: Int, sync: Int = 2) extends ClockCrossing case class Asynchronous(depth: Int, sync: Int = 2) extends ClockCrossing
case object RocketConfigs extends Field[Seq[RocketConfig]] case object RocketTilesKey extends Field[Seq[RocketTileParams]]
case object RocketCrossing extends Field[ClockCrossing] case object RocketCrossing extends Field[ClockCrossing]
trait HasRocketTiles extends CoreplexRISCVPlatform { trait HasRocketTiles extends CoreplexRISCVPlatform {
val module: HasRocketTilesModule val module: HasRocketTilesModule
private val crossing = p(RocketCrossing) private val crossing = p(RocketCrossing)
private val configs = p(RocketConfigs) private val configs = p(RocketTilesKey)
private val pWithExtra = p.alterPartial {
case SharedMemoryTLEdge => l1tol2.node.edgesIn(0)
case PAddrBits => l1tol2.node.edgesIn(0).bundle.addressBits
}
private val rocketTileIntNodes = configs.map { _ => IntInternalOutputNode() } private val rocketTileIntNodes = configs.map { _ => IntInternalOutputNode() }
rocketTileIntNodes.foreach { _ := plic.intnode } rocketTileIntNodes.foreach { _ := plic.intnode }
@ -37,11 +34,20 @@ trait HasRocketTiles extends CoreplexRISCVPlatform {
} }
val rocketWires: Seq[HasRocketTilesBundle => Unit] = configs.zipWithIndex.map { case (c, i) => val rocketWires: Seq[HasRocketTilesBundle => Unit] = configs.zipWithIndex.map { case (c, i) =>
val pWithExtra = p.alterPartial {
case TileKey => c
case BuildRoCC => c.rocc
case SharedMemoryTLEdge => l1tol2.node.edgesIn(0)
case PAddrBits => l1tol2.node.edgesIn(0).bundle.addressBits
}
crossing match { crossing match {
case Synchronous => { case Synchronous => {
val tile = LazyModule(new RocketTile(c)(pWithExtra)) val tile = LazyModule(new RocketTile(c)(pWithExtra))
tile.masterNodes.foreach { l1tol2.node := TLBuffer()(_) } val buffer = LazyModule(new TLBuffer)
tile.slaveNode.foreach { _ := cbus.node } buffer.node :=* tile.masterNode
l1tol2.node :=* buffer.node
tile.slaveNode :*= cbus.node
(io: HasRocketTilesBundle) => { (io: HasRocketTilesBundle) => {
// leave clock as default (simpler for hierarchical PnR) // leave clock as default (simpler for hierarchical PnR)
tile.module.io.hartid := UInt(i) tile.module.io.hartid := UInt(i)
@ -51,8 +57,12 @@ trait HasRocketTiles extends CoreplexRISCVPlatform {
} }
case Asynchronous(depth, sync) => { case Asynchronous(depth, sync) => {
val wrapper = LazyModule(new AsyncRocketTile(c)(pWithExtra)) val wrapper = LazyModule(new AsyncRocketTile(c)(pWithExtra))
wrapper.masterNodes.foreach { l1tol2.node := TLAsyncCrossingSink(depth, sync)(_) } val sink = LazyModule(new TLAsyncCrossingSink(depth, sync))
wrapper.slaveNode.foreach { _ := TLAsyncCrossingSource(sync)(cbus.node) } val source = LazyModule(new TLAsyncCrossingSource(sync))
sink.node :=* wrapper.masterNode
l1tol2.node :=* sink.node
wrapper.slaveNode :*= source.node
source.node :*= cbus.node
(io: HasRocketTilesBundle) => { (io: HasRocketTilesBundle) => {
wrapper.module.clock := io.tcrs(i).clock wrapper.module.clock := io.tcrs(i).clock
wrapper.module.reset := io.tcrs(i).reset wrapper.module.reset := io.tcrs(i).reset
@ -63,8 +73,12 @@ trait HasRocketTiles extends CoreplexRISCVPlatform {
} }
case Rational => { case Rational => {
val wrapper = LazyModule(new RationalRocketTile(c)(pWithExtra)) val wrapper = LazyModule(new RationalRocketTile(c)(pWithExtra))
wrapper.masterNodes.foreach { l1tol2.node := TLRationalCrossingSink()(_) } val sink = LazyModule(new TLRationalCrossingSink)
wrapper.slaveNode.foreach { _ := TLRationalCrossingSource()(cbus.node) } val source = LazyModule(new TLRationalCrossingSource)
sink.node :=* wrapper.masterNode
l1tol2.node :=* sink.node
wrapper.slaveNode :*= source.node
source.node :*= cbus.node
(io: HasRocketTilesBundle) => { (io: HasRocketTilesBundle) => {
wrapper.module.clock := io.tcrs(i).clock wrapper.module.clock := io.tcrs(i).clock
wrapper.module.reset := io.tcrs(i).reset wrapper.module.reset := io.tcrs(i).reset
@ -79,7 +93,7 @@ trait HasRocketTiles extends CoreplexRISCVPlatform {
trait HasRocketTilesBundle extends CoreplexRISCVPlatformBundle { trait HasRocketTilesBundle extends CoreplexRISCVPlatformBundle {
val outer: HasRocketTiles val outer: HasRocketTiles
val tcrs = Vec(p(RocketConfigs).size, new Bundle { val tcrs = Vec(p(RocketTilesKey).size, new Bundle {
val clock = Clock(INPUT) val clock = Clock(INPUT)
val reset = Bool(INPUT) val reset = Bool(INPUT)
}) })

View File

@ -4,6 +4,7 @@
package groundtest package groundtest
import Chisel._ import Chisel._
import coreplex.CacheBlockBytes
import uncore.tilelink._ import uncore.tilelink._
import uncore.constants._ import uncore.constants._
import uncore.util._ import uncore.util._
@ -12,8 +13,9 @@ import config._
class CacheFillTest(implicit p: Parameters) extends GroundTest()(p) class CacheFillTest(implicit p: Parameters) extends GroundTest()(p)
with HasTileLinkParameters { with HasTileLinkParameters {
val l2Config = p(CacheName("L2")) //val l2Config = p(CacheName("L2"))
val capacityKb = l2Config.nSets * l2Config.nWays * l2Config.rowBits / (1024*8) //val capacityKb = l2Config.nSets * l2Config.nWays * l2Config.rowBits / (1024*8)
val capacityKb = 1024 // TODO
val nblocks = capacityKb * 1024 / p(CacheBlockBytes) val nblocks = capacityKb * 1024 / p(CacheBlockBytes)
val s_start :: s_prefetch :: s_retrieve :: s_finished :: Nil = Enum(Bits(), 4) val s_start :: s_prefetch :: s_retrieve :: s_finished :: Nil = Enum(Bits(), 4)
val state = Reg(init = s_start) val state = Reg(init = s_start)

View File

@ -11,6 +11,7 @@ import uncore.coherence._
import uncore.agents._ import uncore.agents._
import uncore.util._ import uncore.util._
import uncore.devices.NTiles import uncore.devices.NTiles
import tile.TileKey
import junctions._ import junctions._
import config._ import config._
import coreplex._ import coreplex._
@ -18,10 +19,10 @@ import rocketchip._
/** Actual testing target Configs */ /** Actual testing target Configs */
class GroundTestConfig extends Config(new WithGroundTest ++ new BaseConfig) class GroundTestConfig extends Config(new WithGroundTestTiles ++ new BaseConfig)
class ComparatorConfig extends Config( class ComparatorConfig extends Config(
new WithComparator ++ new GroundTestConfig) new WithComparator(1) ++ new GroundTestConfig)
class ComparatorL2Config extends Config( class ComparatorL2Config extends Config(
new WithAtomics ++ new WithPrefetches ++ new WithAtomics ++ new WithPrefetches ++
new WithL2Cache ++ new ComparatorConfig) new WithL2Cache ++ new ComparatorConfig)
@ -30,31 +31,32 @@ class ComparatorBufferlessConfig extends Config(
class ComparatorStatelessConfig extends Config( class ComparatorStatelessConfig extends Config(
new WithStatelessBridge ++ new ComparatorConfig) new WithStatelessBridge ++ new ComparatorConfig)
class MemtestConfig extends Config(new WithMemtest ++ new GroundTestConfig) class MemtestConfig extends Config(new WithMemtest(1) ++ new GroundTestConfig)
class MemtestL2Config extends Config( class MemtestL2Config extends Config(
new WithL2Cache ++ new MemtestConfig) new WithL2Cache ++ new MemtestConfig)
class MemtestBufferlessConfig extends Config( class MemtestBufferlessConfig extends Config(
new WithBufferlessBroadcastHub ++ new MemtestConfig) new WithBufferlessBroadcastHub ++ new MemtestConfig)
class MemtestStatelessConfig extends Config( class MemtestStatelessConfig extends Config(
new WithNGenerators(0, 1) ++ new WithStatelessBridge ++ new MemtestConfig) new WithStatelessBridge ++ new MemtestConfig)
// Test ALL the things // Test ALL the things
class FancyMemtestConfig extends Config( class FancyMemtestConfig extends Config(
new WithNGenerators(1, 2) ++ new WithNCores(2) ++ new WithMemtest ++ new WithMemtest(2) ++
new WithNMemoryChannels(2) ++ new WithNBanksPerMemChannel(4) ++ new WithNMemoryChannels(2) ++ new WithNBanksPerMemChannel(4) ++
new WithL2Cache ++ new GroundTestConfig) new WithL2Cache ++ new GroundTestConfig)
class CacheFillTestConfig extends Config( class CacheFillTestConfig extends Config(
new WithNL2Ways(4) ++ new WithL2Capacity(4) ++ new WithCacheFillTest ++ new WithL2Cache ++ new GroundTestConfig) new WithNL2Ways(4) ++ new WithL2Capacity(4) ++
new WithCacheFillTest(1) ++ new WithL2Cache ++ new GroundTestConfig)
class BroadcastRegressionTestConfig extends Config( class BroadcastRegressionTestConfig extends Config(
new WithBroadcastRegressionTest ++ new GroundTestConfig) new WithBroadcastRegressionTest(1) ++ new GroundTestConfig)
class BufferlessRegressionTestConfig extends Config( class BufferlessRegressionTestConfig extends Config(
new WithBufferlessBroadcastHub ++ new BroadcastRegressionTestConfig) new WithBufferlessBroadcastHub ++ new BroadcastRegressionTestConfig)
class CacheRegressionTestConfig extends Config( class CacheRegressionTestConfig extends Config(
new WithCacheRegressionTest ++ new WithL2Cache ++ new GroundTestConfig) new WithCacheRegressionTest(1) ++ new WithL2Cache ++ new GroundTestConfig)
class TraceGenConfig extends Config( class TraceGenConfig extends Config(
new WithNCores(2) ++ new WithTraceGen ++ new GroundTestConfig) new WithTraceGen(2) ++ new GroundTestConfig)
class TraceGenBufferlessConfig extends Config( class TraceGenBufferlessConfig extends Config(
new WithBufferlessBroadcastHub ++ new TraceGenConfig) new WithBufferlessBroadcastHub ++ new TraceGenConfig)
class TraceGenL2Config extends Config( class TraceGenL2Config extends Config(
@ -72,15 +74,15 @@ class Edge32BitMemtestConfig extends Config(
new WithEdgeDataBits(32) ++ new MemtestConfig) new WithEdgeDataBits(32) ++ new MemtestConfig)
/* Composable Configs to set individual parameters */ /* Composable Configs to set individual parameters */
class WithGroundTest extends Config((site, here, up) => {
case FPUKey => None class WithGroundTestTiles extends Config((site, here, up) => {
case UseAtomics => false case TileKey => site(GroundTestKey).head
case UseCompressed => false case NTiles => site(GroundTestKey).size
}) })
class WithComparator extends Config((site, here, up) => { class WithComparator(n: Int) extends Config((site, here, up) => {
case GroundTestKey => Seq.fill(site(NTiles)) { case GroundTestKey => Seq.fill(n) {
GroundTestTileSettings(uncached = 2) GroundTestTileParams(uncached = 2, dcache = None)
} }
case BuildGroundTest => case BuildGroundTest =>
(p: Parameters) => Module(new ComparatorCore()(p)) (p: Parameters) => Module(new ComparatorCore()(p))
@ -88,23 +90,21 @@ class WithComparator extends Config((site, here, up) => {
targets = Seq(site(ExtMem).base, testRamAddr), targets = Seq(site(ExtMem).base, testRamAddr),
width = 8, width = 8,
operations = 1000, operations = 1000,
atomics = site(UseAtomics), atomics = false,
prefetches = false) prefetches = false)
case FPUConfig => None
case UseAtomics => false
}) })
class WithAtomics extends Config((site, here, up) => { class WithAtomics extends Config((site, here, up) => {
case UseAtomics => true case ComparatorKey => up(ComparatorKey, site).copy(atomics = true)
}) })
class WithPrefetches extends Config((site, here, up) => { class WithPrefetches extends Config((site, here, up) => {
case ComparatorKey => up(ComparatorKey, site).copy(prefetches = true) case ComparatorKey => up(ComparatorKey, site).copy(prefetches = true)
}) })
class WithMemtest extends Config((site, here, up) => { class WithMemtest(n: Int) extends Config((site, here, up) => {
case GroundTestKey => Seq.fill(site(NTiles)) { case GroundTestKey => Seq.fill(n) {
GroundTestTileSettings(1, 1) GroundTestTileParams(uncached = 1)
} }
case GeneratorKey => TrafficGeneratorParameters( case GeneratorKey => TrafficGeneratorParameters(
maxRequests = 128, maxRequests = 128,
@ -113,23 +113,17 @@ class WithMemtest extends Config((site, here, up) => {
(p: Parameters) => Module(new GeneratorTest()(p)) (p: Parameters) => Module(new GeneratorTest()(p))
}) })
class WithNGenerators(nUncached: Int, nCached: Int) extends Config((site, here, up) => { class WithCacheFillTest(n: Int) extends Config((site, here, up) => {
case GroundTestKey => Seq.fill(site(NTiles)) { case GroundTestKey => Seq.fill(n) {
GroundTestTileSettings(nUncached, nCached) GroundTestTileParams(uncached = 1, dcache = None)
}
})
class WithCacheFillTest extends Config((site, here, up) => {
case GroundTestKey => Seq.fill(site(NTiles)) {
GroundTestTileSettings(uncached = 1)
} }
case BuildGroundTest => case BuildGroundTest =>
(p: Parameters) => Module(new CacheFillTest()(p)) (p: Parameters) => Module(new CacheFillTest()(p))
}) })
class WithBroadcastRegressionTest extends Config((site, here, up) => { class WithBroadcastRegressionTest(n: Int) extends Config((site, here, up) => {
case GroundTestKey => Seq.fill(site(NTiles)) { case GroundTestKey => Seq.fill(n) {
GroundTestTileSettings(1, 1, maxXacts = 3) GroundTestTileParams(uncached = 1, maxXacts = 3)
} }
case BuildGroundTest => case BuildGroundTest =>
(p: Parameters) => Module(new RegressionTest()(p)) (p: Parameters) => Module(new RegressionTest()(p))
@ -137,9 +131,9 @@ class WithBroadcastRegressionTest extends Config((site, here, up) => {
(p: Parameters) => RegressionTests.broadcastRegressions(p) (p: Parameters) => RegressionTests.broadcastRegressions(p)
}) })
class WithCacheRegressionTest extends Config((site, here, up) => { class WithCacheRegressionTest(n: Int) extends Config((site, here, up) => {
case GroundTestKey => Seq.fill(site(NTiles)) { case GroundTestKey => Seq.fill(n) {
GroundTestTileSettings(1, 1, maxXacts = 5) GroundTestTileParams(uncached = 1, maxXacts = 5)
} }
case BuildGroundTest => case BuildGroundTest =>
(p: Parameters) => Module(new RegressionTest()(p)) (p: Parameters) => Module(new RegressionTest()(p))
@ -147,9 +141,9 @@ class WithCacheRegressionTest extends Config((site, here, up) => {
(p: Parameters) => RegressionTests.cacheRegressions(p) (p: Parameters) => RegressionTests.cacheRegressions(p)
}) })
class WithTraceGen extends Config((site, here, up) => { class WithTraceGen(n: Int) extends Config((site, here, up) => {
case GroundTestKey => Seq.fill(site(NTiles)) { case GroundTestKey => Seq.fill(n) {
GroundTestTileSettings(uncached = 0, cached = 1) GroundTestTileParams(dcache = Some(DCacheParams(nSets = 16, nWays = 1)))
} }
case BuildGroundTest => case BuildGroundTest =>
(p: Parameters) => Module(new GroundTestTraceGenerator()(p)) (p: Parameters) => Module(new GroundTestTraceGenerator()(p))
@ -160,11 +154,9 @@ class WithTraceGen extends Config((site, here, up) => {
val nSets = 2 val nSets = 2
val nWays = 1 val nWays = 1
val blockOffset = site(CacheBlockOffsetBits) val blockOffset = site(CacheBlockOffsetBits)
val nBeats = site(TLKey("L1toL2")).dataBeats val nBeats = site(CacheBlockBytes)/site(L1toL2Config).beatBytes
List.tabulate(4 * nWays) { i => List.tabulate(4 * nWays) { i =>
Seq.tabulate(nBeats) { j => BigInt((j * 8) + ((i * nSets) << blockOffset)) } Seq.tabulate(nBeats) { j => BigInt((j * 8) + ((i * nSets) << blockOffset)) }
}.flatten }.flatten
} }
case UseAtomics => true
case CacheName("L1D") => up(CacheName("L1D"), site).copy(nSets = 16, nWays = 1)
}) })

View File

@ -7,6 +7,7 @@ import config._
import diplomacy._ import diplomacy._
import coreplex._ import coreplex._
import rocket._ import rocket._
import tile._
import uncore.agents._ import uncore.agents._
import uncore.coherence._ import uncore.coherence._
import uncore.devices._ import uncore.devices._
@ -31,9 +32,7 @@ class GroundTestCoreplex(implicit p: Parameters) extends BaseCoreplex {
nManagers = site(BankedL2Config).nBanks + 1, nManagers = site(BankedL2Config).nBanks + 1,
nCachingClients = 1, nCachingClients = 1,
nCachelessClients = 1, nCachelessClients = 1,
maxClientXacts = ((site(DCacheKey).nMSHRs + 1) +: maxClientXacts = site(GroundTestKey).map(_.maxXacts).reduce(max(_, _)),
site(GroundTestKey).map(_.maxXacts))
.reduce(max(_, _)),
maxClientsPerPort = site(GroundTestKey).map(_.uncached).sum, maxClientsPerPort = site(GroundTestKey).map(_.uncached).sum,
maxManagerXacts = 8, maxManagerXacts = 8,
dataBeats = (8 * site(CacheBlockBytes)) / site(XLen), dataBeats = (8 * site(CacheBlockBytes)) / site(XLen),
@ -41,10 +40,7 @@ class GroundTestCoreplex(implicit p: Parameters) extends BaseCoreplex {
}})) }}))
} }
tiles.foreach { lm => tiles.foreach { l1tol2.node :=* _.masterNode }
l1tol2.node := lm.cachedOut
l1tol2.node := lm.uncachedOut
}
val cbusRAM = LazyModule(new TLRAM(AddressSet(testRamAddr, 0xffff), false, cbus_beatBytes)) val cbusRAM = LazyModule(new TLRAM(AddressSet(testRamAddr, 0xffff), false, cbus_beatBytes))
cbusRAM.node := TLFragmenter(cbus_beatBytes, cbus_lineBytes)(cbus.node) cbusRAM.node := TLFragmenter(cbus_beatBytes, cbus_lineBytes)(cbus.node)
@ -52,8 +48,7 @@ class GroundTestCoreplex(implicit p: Parameters) extends BaseCoreplex {
override lazy val module = new GroundTestCoreplexModule(this, () => new GroundTestCoreplexBundle(this)) override lazy val module = new GroundTestCoreplexModule(this, () => new GroundTestCoreplexBundle(this))
} }
class GroundTestCoreplexBundle[+L <: GroundTestCoreplex](_outer: L) extends BaseCoreplexBundle(_outer) class GroundTestCoreplexBundle[+L <: GroundTestCoreplex](_outer: L) extends BaseCoreplexBundle(_outer) {
{
val success = Bool(OUTPUT) val success = Bool(OUTPUT)
} }

View File

@ -0,0 +1,57 @@
// See LICENSE.SiFive for license details.
// See LICENSE.Berkeley for license details.
package groundtest
import Chisel._
import config._
import rocket._
import tile._
import util.ParameterizedBundle
class DummyPTW(n: Int)(implicit p: Parameters) extends CoreModule()(p) {
val io = new Bundle {
val requestors = Vec(n, new TLBPTWIO).flip
}
val req_arb = Module(new RRArbiter(new PTWReq, n))
req_arb.io.in <> io.requestors.map(_.req)
req_arb.io.out.ready := Bool(true)
def vpn_to_ppn(vpn: UInt): UInt = vpn(ppnBits - 1, 0)
class QueueChannel extends ParameterizedBundle()(p) {
val ppn = UInt(width = ppnBits)
val chosen = UInt(width = log2Up(n))
}
val s1_ppn = vpn_to_ppn(req_arb.io.out.bits.addr)
val s2_ppn = RegEnable(s1_ppn, req_arb.io.out.valid)
val s2_chosen = RegEnable(req_arb.io.chosen, req_arb.io.out.valid)
val s2_valid = Reg(next = req_arb.io.out.valid)
val s2_resp = Wire(new PTWResp)
s2_resp.pte.ppn := s2_ppn
s2_resp.pte.reserved_for_software := UInt(0)
s2_resp.pte.d := Bool(true)
s2_resp.pte.a := Bool(false)
s2_resp.pte.g := Bool(false)
s2_resp.pte.u := Bool(true)
s2_resp.pte.r := Bool(true)
s2_resp.pte.w := Bool(true)
s2_resp.pte.x := Bool(false)
s2_resp.pte.v := Bool(true)
io.requestors.zipWithIndex.foreach { case (requestor, i) =>
requestor.resp.valid := s2_valid && s2_chosen === UInt(i)
requestor.resp.bits := s2_resp
requestor.status.vm := UInt("b01000")
requestor.status.prv := UInt(PRV.S)
requestor.status.debug := Bool(false)
requestor.status.mprv := Bool(true)
requestor.status.mpp := UInt(0)
requestor.ptbr.asid := UInt(0)
requestor.ptbr.ppn := UInt(0)
requestor.invalidate := Bool(false)
}
}

View File

@ -103,14 +103,13 @@ class IOGetAfterPutBlockRegression(implicit p: Parameters) extends Regression()(
* acknowledge both of them when the first one finished. * acknowledge both of them when the first one finished.
* This caused the state to go funky since the next time around it would * This caused the state to go funky since the next time around it would
* start the put in the middle */ * start the put in the middle */
class PutBlockMergeRegression(implicit p: Parameters) class PutBlockMergeRegression(nSets: Int)(implicit p: Parameters)
extends Regression()(p) with HasTileLinkParameters { extends Regression()(p) with HasTileLinkParameters {
val s_idle :: s_put :: s_wait :: s_done :: Nil = Enum(Bits(), 4) val s_idle :: s_put :: s_wait :: s_done :: Nil = Enum(Bits(), 4)
val state = Reg(init = s_idle) val state = Reg(init = s_idle)
disableCache() disableCache()
val nSets = p(CacheName("L2")).nSets
val addr_blocks = Vec(Seq(0, 0, nSets).map(num => UInt(num + memStartBlock))) val addr_blocks = Vec(Seq(0, 0, nSets).map(num => UInt(num + memStartBlock)))
val nSteps = addr_blocks.size val nSteps = addr_blocks.size
val (acq_beat, acq_done) = Counter(io.mem.acquire.fire(), tlDataBeats) val (acq_beat, acq_done) = Counter(io.mem.acquire.fire(), tlDataBeats)
@ -391,12 +390,9 @@ class PrefetchHitRegression(implicit p: Parameters) extends Regression()(p) {
* set. This assumes that there is only a single cache bank. If we want to * set. This assumes that there is only a single cache bank. If we want to
* test multibank configurations, we'll have to think of some other way to * test multibank configurations, we'll have to think of some other way to
* determine which banks are conflicting */ * determine which banks are conflicting */
class WritebackRegression(implicit p: Parameters) extends Regression()(p) { class WritebackRegression(nSets: Int, nWays: Int)(implicit p: Parameters) extends Regression()(p) {
disableCache() disableCache()
val nSets = p(CacheName("L2")).nSets
val nWays = p(CacheName("L2")).nWays
val addr_blocks = Vec.tabulate(nWays + 1) { i => UInt(memStartBlock + i * nSets) } val addr_blocks = Vec.tabulate(nWays + 1) { i => UInt(memStartBlock + i * nSets) }
val data = Vec.tabulate(nWays + 1) { i => UInt((i + 1) * 1423) } val data = Vec.tabulate(nWays + 1) { i => UInt((i + 1) * 1423) }
@ -443,11 +439,9 @@ class WritebackRegression(implicit p: Parameters) extends Regression()(p) {
io.errored := data_mismatch io.errored := data_mismatch
} }
class ReleaseRegression(implicit p: Parameters) extends Regression()(p) { class ReleaseRegression(nSets: Int, nWays: Int)(implicit p: Parameters) extends Regression()(p) {
disableMem() disableMem()
val nSets = p(CacheName("L1D")).nSets
val nWays = p(CacheName("L1D")).nWays
val blockOffset = p(CacheBlockOffsetBits) val blockOffset = p(CacheBlockOffsetBits)
val startBlock = memStartBlock + 10 val startBlock = memStartBlock + 10
@ -530,12 +524,9 @@ class PutBeforePutBlockRegression(implicit p: Parameters) extends Regression()(p
* Make sure that multiple gets to the same line and beat are merged * Make sure that multiple gets to the same line and beat are merged
* correctly, even if it is a cache miss. * correctly, even if it is a cache miss.
*/ */
class MergedGetRegression(implicit p: Parameters) extends Regression()(p) { class MergedGetRegression(nSets: Int, nWays: Int)(implicit p: Parameters) extends Regression()(p) {
disableCache() disableCache()
val nSets = p(CacheName("L2")).nSets
val nWays = p(CacheName("L2")).nWays
val (s_idle :: s_put :: s_get :: s_done :: Nil) = Enum(Bits(), 4) val (s_idle :: s_put :: s_get :: s_done :: Nil) = Enum(Bits(), 4)
val state = Reg(init = s_idle) val state = Reg(init = s_idle)
@ -697,23 +688,27 @@ class PutAfterReleaseRegression(implicit p: Parameters) extends Regression()(p)
} }
object RegressionTests { object RegressionTests {
val l1sets = 16 // TODO
val l1ways = 1 // TODO
val l2sets = 32 // TODO
val l2ways = 2 // TODO
def cacheRegressions(implicit p: Parameters) = Seq( def cacheRegressions(implicit p: Parameters) = Seq(
Module(new PutBlockMergeRegression), Module(new PutBlockMergeRegression(l2sets)),
Module(new NoAllocPutHitRegression), Module(new NoAllocPutHitRegression),
Module(new RepeatedNoAllocPutRegression), Module(new RepeatedNoAllocPutRegression),
Module(new WriteMaskedPutBlockRegression), Module(new WriteMaskedPutBlockRegression),
Module(new PrefetchHitRegression), Module(new PrefetchHitRegression),
Module(new WritebackRegression), Module(new WritebackRegression(l2sets, l2ways)),
Module(new PutBeforePutBlockRegression), Module(new PutBeforePutBlockRegression),
Module(new MixedAllocPutRegression), Module(new MixedAllocPutRegression),
Module(new ReleaseRegression), Module(new ReleaseRegression(l1sets, l1ways)),
Module(new MergedGetRegression), Module(new MergedGetRegression(l2sets, l2ways)),
Module(new MergedPutRegression)) Module(new MergedPutRegression))
def broadcastRegressions(implicit p: Parameters) = Seq( def broadcastRegressions(implicit p: Parameters) = Seq(
Module(new IOGetAfterPutBlockRegression), Module(new IOGetAfterPutBlockRegression),
Module(new WriteMaskedPutBlockRegression), Module(new WriteMaskedPutBlockRegression),
Module(new PutBeforePutBlockRegression), Module(new PutBeforePutBlockRegression),
Module(new ReleaseRegression), Module(new ReleaseRegression(l1sets, l1ways)),
Module(new PutAfterReleaseRegression)) Module(new PutAfterReleaseRegression))
} }

View File

@ -4,23 +4,33 @@
package groundtest package groundtest
import Chisel._ import Chisel._
import coreplex.BareTile import config._
import coreplex._
import rocket._ import rocket._
import tile._
import uncore.tilelink._ import uncore.tilelink._
import uncore.util.CacheName
import uncore.tilelink2._ import uncore.tilelink2._
import rocketchip.ExtMem import rocketchip.ExtMem
import diplomacy._ import diplomacy._
import scala.util.Random
import scala.collection.mutable.ListBuffer
import util.ParameterizedBundle import util.ParameterizedBundle
import config._
import scala.collection.mutable.ListBuffer
case object BuildGroundTest extends Field[Parameters => GroundTest] case object BuildGroundTest extends Field[Parameters => GroundTest]
case class GroundTestTileSettings( case class GroundTestTileParams(
uncached: Int = 0, cached: Int = 0, ptw: Int = 0, maxXacts: Int = 1) uncached: Int = 0,
case object GroundTestKey extends Field[Seq[GroundTestTileSettings]] ptw: Int = 0,
maxXacts: Int = 1,
dcache: Option[DCacheParams] = Some(DCacheParams())) extends TileParams {
val icache = None
val btb = None
val rocc = Nil
val core = rocket.RocketCoreParams() //TODO remove this
val cached = if(dcache.isDefined) 1 else 0
val dataScratchpadBytes = 0
}
case object GroundTestKey extends Field[Seq[GroundTestTileParams]]
trait HasGroundTestConstants { trait HasGroundTestConstants {
val timeoutCodeBits = 4 val timeoutCodeBits = 4
@ -29,61 +39,14 @@ trait HasGroundTestConstants {
trait HasGroundTestParameters { trait HasGroundTestParameters {
implicit val p: Parameters implicit val p: Parameters
val tileSettings = p(GroundTestKey)(p(TileId)) val tileParams = p(GroundTestKey)(p(TileId))
val nUncached = tileSettings.uncached val nUncached = tileParams.uncached
val nCached = tileSettings.cached val nCached = tileParams.cached
val nPTW = tileSettings.ptw val nPTW = tileParams.ptw
val memStart = p(ExtMem).base val memStart = p(ExtMem).base
val memStartBlock = memStart >> p(CacheBlockOffsetBits) val memStartBlock = memStart >> p(CacheBlockOffsetBits)
} }
class DummyPTW(n: Int)(implicit p: Parameters) extends CoreModule()(p) {
val io = new Bundle {
val requestors = Vec(n, new TLBPTWIO).flip
}
val req_arb = Module(new RRArbiter(new PTWReq, n))
req_arb.io.in <> io.requestors.map(_.req)
req_arb.io.out.ready := Bool(true)
def vpn_to_ppn(vpn: UInt): UInt = vpn(ppnBits - 1, 0)
class QueueChannel extends ParameterizedBundle()(p) {
val ppn = UInt(width = ppnBits)
val chosen = UInt(width = log2Up(n))
}
val s1_ppn = vpn_to_ppn(req_arb.io.out.bits.addr)
val s2_ppn = RegEnable(s1_ppn, req_arb.io.out.valid)
val s2_chosen = RegEnable(req_arb.io.chosen, req_arb.io.out.valid)
val s2_valid = Reg(next = req_arb.io.out.valid)
val s2_resp = Wire(new PTWResp)
s2_resp.pte.ppn := s2_ppn
s2_resp.pte.reserved_for_software := UInt(0)
s2_resp.pte.d := Bool(true)
s2_resp.pte.a := Bool(false)
s2_resp.pte.g := Bool(false)
s2_resp.pte.u := Bool(true)
s2_resp.pte.r := Bool(true)
s2_resp.pte.w := Bool(true)
s2_resp.pte.x := Bool(false)
s2_resp.pte.v := Bool(true)
io.requestors.zipWithIndex.foreach { case (requestor, i) =>
requestor.resp.valid := s2_valid && s2_chosen === UInt(i)
requestor.resp.bits := s2_resp
requestor.status.vm := UInt("b01000")
requestor.status.prv := UInt(PRV.S)
requestor.status.debug := Bool(false)
requestor.status.mprv := Bool(true)
requestor.status.mpp := UInt(0)
requestor.ptbr.asid := UInt(0)
requestor.ptbr.ppn := UInt(0)
requestor.invalidate := Bool(false)
}
}
class GroundTestStatus extends Bundle with HasGroundTestConstants { class GroundTestStatus extends Bundle with HasGroundTestConstants {
val finished = Bool(OUTPUT) val finished = Bool(OUTPUT)
val timeout = Valid(UInt(width = timeoutCodeBits)) val timeout = Valid(UInt(width = timeoutCodeBits))
@ -103,38 +66,33 @@ abstract class GroundTest(implicit val p: Parameters) extends Module
val io = new GroundTestIO val io = new GroundTestIO
} }
class GroundTestTile(implicit p: Parameters) extends LazyModule with HasGroundTestParameters { class GroundTestTile(implicit p: Parameters) extends LazyModule
val dcacheParams = p.alterPartial { with HasGroundTestParameters {
case CacheName => CacheName("L1D")
}
val slave = None val slave = None
val dcache = HellaCache(p(DCacheKey))(dcacheParams) val dcacheOpt = tileParams.dcache.map { dc => HellaCache(dc.nMSHRs == 0) }
val ucLegacy = LazyModule(new TLLegacy) val ucLegacy = LazyModule(new TLLegacy)
val cachedOut = TLOutputNode() val masterNode = TLOutputNode()
val uncachedOut = TLOutputNode() dcacheOpt.foreach { masterNode := _.node }
cachedOut := dcache.node masterNode := TLHintHandler()(ucLegacy.node)
uncachedOut := TLHintHandler()(ucLegacy.node)
val masterNodes = List(cachedOut, uncachedOut)
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 out = masterNode.bundleOut
val uncached = uncachedOut.bundleOut
val success = Bool(OUTPUT) val success = Bool(OUTPUT)
} }
val test = p(BuildGroundTest)(dcacheParams) val test = p(BuildGroundTest)(p)
val ptwPorts = ListBuffer.empty ++= test.io.ptw val ptwPorts = ListBuffer.empty ++= test.io.ptw
val uncachedArbPorts = ListBuffer.empty ++= test.io.mem val uncachedArbPorts = ListBuffer.empty ++= test.io.mem
if (nCached > 0) { dcacheOpt foreach { dcache =>
val dcacheArb = Module(new HellaCacheArbiter(nCached)(dcacheParams)) val dcacheArb = Module(new HellaCacheArbiter(nCached))
dcacheArb.io.requestor.zip(test.io.cache).foreach { dcacheArb.io.requestor.zip(test.io.cache).foreach {
case (requestor, cache) => case (requestor, cache) =>
val dcacheIF = Module(new SimpleHellaCacheIF()(dcacheParams)) val dcacheIF = Module(new SimpleHellaCacheIF())
dcacheIF.io.requestor <> cache dcacheIF.io.requestor <> cache
requestor <> dcacheIF.io.cache requestor <> dcacheIF.io.cache
} }
@ -147,7 +105,7 @@ class GroundTestTile(implicit p: Parameters) extends LazyModule with HasGroundTe
} }
if (ptwPorts.size > 0) { if (ptwPorts.size > 0) {
val ptw = Module(new DummyPTW(ptwPorts.size)(dcacheParams)) val ptw = Module(new DummyPTW(ptwPorts.size))
ptw.io.requestors <> ptwPorts ptw.io.requestors <> ptwPorts
} }

View File

@ -24,6 +24,7 @@ import uncore.tilelink._
import uncore.constants._ import uncore.constants._
import uncore.devices.NTiles import uncore.devices.NTiles
import rocket._ import rocket._
import tile._
import util.{Timer, DynamicTimer} import util.{Timer, DynamicTimer}
import scala.util.Random import scala.util.Random
import config._ import config._
@ -179,7 +180,7 @@ class TagMan(val logNumTags : Int) extends Module {
// =============== // ===============
class TraceGenerator(id: Int) class TraceGenerator(id: Int)
(implicit p: Parameters) extends L1HellaCacheModule()(p) (implicit val p: Parameters) extends Module
with HasTraceGenParams with HasTraceGenParams
with HasGroundTestParameters { with HasGroundTestParameters {
val io = new Bundle { val io = new Bundle {

View File

@ -129,7 +129,7 @@ class UncachedTileLinkGenerator(id: Int)
} }
class HellaCacheGenerator(id: Int) class HellaCacheGenerator(id: Int)
(implicit p: Parameters) extends L1HellaCacheModule()(p) with HasTrafficGeneratorParameters { (implicit val p: Parameters) extends Module with HasTrafficGeneratorParameters {
val io = new Bundle { val io = new Bundle {
val mem = new HellaCacheIO val mem = new HellaCacheIO
val status = new GroundTestStatus val status = new GroundTestStatus

View File

@ -5,6 +5,7 @@ package rocket
import Chisel._ import Chisel._
import config._ import config._
import tile._
import Instructions._ import Instructions._
object ALU object ALU

View File

@ -4,23 +4,22 @@
package rocket package rocket
import Chisel._ import Chisel._
import config._
import util._
import Chisel.ImplicitConversions._ import Chisel.ImplicitConversions._
import uncore.util.PseudoLRU import config._
import tile.HasCoreParameters
import util._
case object BtbKey extends Field[BtbParameters] case class BTBParams(
case class BtbParameters(
nEntries: Int = 40, nEntries: Int = 40,
nRAS: Int = 2, nRAS: Int = 2,
updatesOutOfOrder: Boolean = false) updatesOutOfOrder: Boolean = false)
abstract trait HasBtbParameters extends HasCoreParameters { trait HasBtbParameters extends HasCoreParameters {
val matchBits = pgIdxBits val btbParams = tileParams.btb.getOrElse(BTBParams(nEntries = 0))
val entries = p(BtbKey).nEntries val matchBits = pgIdxBits max log2Ceil(p(coreplex.CacheBlockBytes) * tileParams.icache.get.nSets)
val nRAS = p(BtbKey).nRAS val entries = btbParams.nEntries
val updatesOutOfOrder = p(BtbKey).updatesOutOfOrder val nRAS = btbParams.nRAS
val updatesOutOfOrder = btbParams.updatesOutOfOrder
val nPages = ((1 max(log2Up(entries)))+1)/2*2 // control logic assumes 2 divides pages val nPages = ((1 max(log2Up(entries)))+1)/2*2 // control logic assumes 2 divides pages
val opaqueBits = log2Up(entries) val opaqueBits = log2Up(entries)
val nBHT = 1 << log2Up(entries*2) val nBHT = 1 << log2Up(entries*2)

View File

@ -3,9 +3,10 @@
package rocket package rocket
import Chisel._ import Chisel._
import util._
import Chisel.ImplicitConversions._ import Chisel.ImplicitConversions._
import config._ import config._
import tile._
import util._
class BPControl(implicit p: Parameters) extends CoreBundle()(p) { class BPControl(implicit p: Parameters) extends CoreBundle()(p) {
val ttype = UInt(width = 4) val ttype = UInt(width = 4)

View File

@ -6,6 +6,7 @@ package rocket
import Chisel._ import Chisel._
import Instructions._ import Instructions._
import config._ import config._
import tile._
import uncore.devices._ import uncore.devices._
import util._ import util._
import Chisel.ImplicitConversions._ import Chisel.ImplicitConversions._
@ -60,14 +61,6 @@ class DCSR extends Bundle {
val prv = UInt(width = PRV.SZ) val prv = UInt(width = PRV.SZ)
} }
class TileInterrupts(implicit p: Parameters) extends CoreBundle()(p) {
val debug = Bool()
val mtip = Bool()
val msip = Bool()
val meip = Bool()
val seip = usingVM.option(Bool())
}
class MIP extends Bundle { class MIP extends Bundle {
val rocc = Bool() val rocc = Bool()
val meip = Bool() val meip = Bool()
@ -127,7 +120,8 @@ object CSR
val nCtr = firstHPM + nHPM val nCtr = firstHPM + nHPM
} }
class CSRFileIO(implicit p: Parameters) extends CoreBundle { class CSRFileIO(implicit p: Parameters) extends CoreBundle
with HasRocketCoreParameters {
val interrupts = new TileInterrupts().asInput val interrupts = new TileInterrupts().asInput
val hartid = UInt(INPUT, xLen) val hartid = UInt(INPUT, xLen)
val rw = new Bundle { val rw = new Bundle {
@ -163,7 +157,7 @@ class CSRFileIO(implicit p: Parameters) extends CoreBundle {
} }
class CSRFile(implicit p: Parameters) extends CoreModule()(p) class CSRFile(implicit p: Parameters) extends CoreModule()(p)
{ with HasRocketCoreParameters {
val io = new CSRFileIO val io = new CSRFileIO
val reset_mstatus = Wire(init=new MStatus().fromBits(0)) val reset_mstatus = Wire(init=new MStatus().fromBits(0))
@ -227,7 +221,7 @@ class CSRFile(implicit p: Parameters) extends CoreModule()(p)
val reg_mbadaddr = Reg(UInt(width = vaddrBitsExtended)) val reg_mbadaddr = Reg(UInt(width = vaddrBitsExtended))
val reg_mscratch = Reg(Bits(width = xLen)) val reg_mscratch = Reg(Bits(width = xLen))
val mtvecWidth = paddrBits min xLen val mtvecWidth = paddrBits min xLen
val reg_mtvec = p(MtvecInit) match { val reg_mtvec = mtvecInit match {
case Some(addr) => Reg(init=UInt(addr, mtvecWidth)) case Some(addr) => Reg(init=UInt(addr, mtvecWidth))
case None => Reg(UInt(width = mtvecWidth)) case None => Reg(UInt(width = mtvecWidth))
} }
@ -547,7 +541,7 @@ class CSRFile(implicit p: Parameters) extends CoreModule()(p)
when (decoded_addr(CSRs.mie)) { reg_mie := wdata & supported_interrupts } when (decoded_addr(CSRs.mie)) { reg_mie := wdata & supported_interrupts }
when (decoded_addr(CSRs.mepc)) { reg_mepc := formEPC(wdata) } when (decoded_addr(CSRs.mepc)) { reg_mepc := formEPC(wdata) }
when (decoded_addr(CSRs.mscratch)) { reg_mscratch := wdata } when (decoded_addr(CSRs.mscratch)) { reg_mscratch := wdata }
if (p(MtvecWritable)) if (mtvecWritable)
when (decoded_addr(CSRs.mtvec)) { reg_mtvec := wdata >> 2 << 2 } when (decoded_addr(CSRs.mtvec)) { reg_mtvec := wdata >> 2 << 2 }
when (decoded_addr(CSRs.mcause)) { reg_mcause := wdata & UInt((BigInt(1) << (xLen-1)) + 31) /* only implement 5 LSBs and MSB */ } when (decoded_addr(CSRs.mcause)) { reg_mcause := wdata & UInt((BigInt(1) << (xLen-1)) + 31) /* only implement 5 LSBs and MSB */ }
when (decoded_addr(CSRs.mbadaddr)) { reg_mbadaddr := wdata(vaddrBitsExtended-1,0) } when (decoded_addr(CSRs.mbadaddr)) { reg_mbadaddr := wdata(vaddrBitsExtended-1,0) }

View File

@ -1,93 +0,0 @@
// 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
}
}

View File

@ -4,13 +4,13 @@ package rocket
import Chisel._ import Chisel._
import Chisel.ImplicitConversions._ import Chisel.ImplicitConversions._
import config._
import diplomacy._ import diplomacy._
import uncore.constants._ import uncore.constants._
import uncore.tilelink2._ import uncore.tilelink2._
import uncore.util._ import uncore.util._
import util._ import util._
import TLMessages._ import TLMessages._
import config._
class DCacheDataReq(implicit p: Parameters) extends L1HellaCacheBundle()(p) { class DCacheDataReq(implicit p: Parameters) extends L1HellaCacheBundle()(p) {
val addr = Bits(width = untagBits) val addr = Bits(width = untagBits)
@ -38,22 +38,19 @@ class DCacheDataArray(implicit p: Parameters) extends L1HellaCacheModule()(p) {
} }
} }
class DCache(cfg: DCacheConfig, val scratch: () => Option[AddressSet] = () => None)(implicit p: Parameters) extends HellaCache(cfg)(p) { class DCache(val scratch: () => Option[AddressSet] = () => None)(implicit p: Parameters) extends HellaCache()(p) {
override lazy val module = new DCacheModule(this) override lazy val module = new DCacheModule(this)
} }
class DCacheModule(outer: DCache) extends HellaCacheModule(outer) { class DCacheModule(outer: DCache) extends HellaCacheModule(outer) {
val maxUncachedInFlight = cfg.nMMIOs
require(rowBits == encRowBits) // no ECC require(rowBits == encRowBits) // no ECC
val grantackq = Module(new Queue(tl_out.e.bits,1)) // TODO don't need this in scratchpad mode val grantackq = Module(new Queue(tl_out.e.bits,1)) // TODO don't need this in scratchpad mode
// tags // tags
val replacer = p(Replacer)() val replacer = cacheParams.replacement
def onReset = L1Metadata(UInt(0), ClientMetadata.onReset) def onReset = L1Metadata(UInt(0), ClientMetadata.onReset)
val metaReadArb = Module(new Arbiter(new MetaReadReq, 3)) val metaReadArb = Module(new Arbiter(new L1MetaReadReq, 3))
val metaWriteArb = Module(new Arbiter(new L1MetaWriteReq, 3)) val metaWriteArb = Module(new Arbiter(new L1MetaWriteReq, 3))
// data // data
@ -104,7 +101,7 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) {
when (!metaReadArb.io.in(2).ready) { io.cpu.req.ready := false } when (!metaReadArb.io.in(2).ready) { io.cpu.req.ready := false }
// address translation // address translation
val tlb = Module(new TLB) val tlb = Module(new TLB(nTLBEntries))
io.ptw <> tlb.io.ptw io.ptw <> tlb.io.ptw
tlb.io.req.valid := s1_valid_masked && s1_readwrite tlb.io.req.valid := s1_valid_masked && s1_readwrite
tlb.io.req.bits.passthrough := s1_req.phys tlb.io.req.bits.passthrough := s1_req.phys
@ -126,7 +123,7 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) {
val hitState = Mux(inScratchpad, ClientMetadata.maximum, ClientMetadata.onReset) val hitState = Mux(inScratchpad, ClientMetadata.maximum, ClientMetadata.onReset)
(inScratchpad, hitState, L1Metadata(UInt(0), ClientMetadata.onReset)) (inScratchpad, hitState, L1Metadata(UInt(0), ClientMetadata.onReset))
} else { } else {
val meta = Module(new MetadataArray(onReset _)) val meta = Module(new L1MetadataArray(onReset _))
meta.io.read <> metaReadArb.io.out meta.io.read <> metaReadArb.io.out
meta.io.write <> metaWriteArb.io.out meta.io.write <> metaWriteArb.io.out
val s1_meta = meta.io.resp val s1_meta = meta.io.resp

View File

@ -4,13 +4,13 @@
package rocket package rocket
import Chisel._ import Chisel._
import Chisel.ImplicitConversions._
import config._ import config._
import coreplex._ import coreplex._
import diplomacy._ import diplomacy._
import uncore.tilelink2._ import uncore.tilelink2._
import uncore.util.CacheName import tile._
import util._ import util._
import Chisel.ImplicitConversions._
class FrontendReq(implicit p: Parameters) extends CoreBundle()(p) { class FrontendReq(implicit p: Parameters) extends CoreBundle()(p) {
val pc = UInt(width = vaddrBitsExtended) val pc = UInt(width = vaddrBitsExtended)
@ -54,12 +54,12 @@ class FrontendBundle(outer: Frontend) extends CoreBundle()(outer.p) {
class FrontendModule(outer: Frontend) extends LazyModuleImp(outer) class FrontendModule(outer: Frontend) extends LazyModuleImp(outer)
with HasCoreParameters with HasCoreParameters
with HasL1CacheParameters { with HasL1ICacheParameters {
val io = new FrontendBundle(outer) val io = new FrontendBundle(outer)
implicit val edge = outer.node.edgesOut(0) implicit val edge = outer.node.edgesOut(0)
val icache = outer.icache.module val icache = outer.icache.module
val tlb = Module(new TLB) val tlb = Module(new TLB(nTLBEntries))
val s1_pc_ = Reg(UInt(width=vaddrBitsExtended)) val s1_pc_ = Reg(UInt(width=vaddrBitsExtended))
val s1_pc = ~(~s1_pc_ | (coreInstBytes-1)) // discard PC LSBS (this propagates down the pipeline) val s1_pc = ~(~s1_pc_ | (coreInstBytes-1)) // discard PC LSBS (this propagates down the pipeline)
@ -106,7 +106,7 @@ class FrontendModule(outer: Frontend) extends LazyModuleImp(outer)
s2_valid := Bool(false) s2_valid := Bool(false)
} }
if (p(BtbKey).nEntries > 0) { if (usingBTB) {
val btb = Module(new BTB) val btb = Module(new BTB)
btb.io.req.valid := false btb.io.req.valid := false
btb.io.req.bits.addr := s1_pc_ btb.io.req.bits.addr := s1_pc_
@ -153,21 +153,18 @@ class FrontendModule(outer: Frontend) extends LazyModuleImp(outer)
} }
/** Mix-ins for constructing tiles that have an ICache-based pipeline frontend */ /** Mix-ins for constructing tiles that have an ICache-based pipeline frontend */
trait HasICacheFrontend extends CanHavePTW with TileNetwork { trait HasICacheFrontend extends CanHavePTW with HasTileLinkMasterPort {
val module: HasICacheFrontendModule val module: HasICacheFrontendModule
val frontend = LazyModule(new Frontend()(p.alterPartial({ val frontend = LazyModule(new Frontend)
case CacheName => CacheName("L1I") masterNode := frontend.node
})))
l1backend.node := frontend.node
nPTWPorts += 1 nPTWPorts += 1
} }
trait HasICacheFrontendBundle extends TileNetworkBundle { trait HasICacheFrontendBundle extends HasTileLinkMasterPortBundle {
val outer: HasICacheFrontend val outer: HasICacheFrontend
} }
trait HasICacheFrontendModule extends CanHavePTWModule with TileNetworkModule { trait HasICacheFrontendModule extends CanHavePTWModule with HasTileLinkMasterPortModule {
val outer: HasICacheFrontend val outer: HasICacheFrontend
//val io: HasICacheFrontendBundle
ptwPorts += outer.frontend.module.io.ptw ptwPorts += outer.frontend.module.io.ptw
} }

View File

@ -7,43 +7,58 @@ import Chisel._
import config.{Parameters, Field} import config.{Parameters, Field}
import coreplex._ import coreplex._
import diplomacy._ import diplomacy._
import tile._
import uncore.constants._ import uncore.constants._
import uncore.tilelink2._ import uncore.tilelink2._
import uncore.util._ import uncore.util.Code
import util.ParameterizedBundle import util.{ParameterizedBundle, RandomReplacement}
import scala.collection.mutable.ListBuffer import scala.collection.mutable.ListBuffer
case class DCacheConfig( case class DCacheParams(
nMSHRs: Int = 1, nSets: Int = 64,
nSDQ: Int = 17, nWays: Int = 4,
nRPQ: Int = 16, rowBits: Int = 64,
nMMIOs: Int = 1) nTLBEntries: Int = 8,
splitMetadata: Boolean = false,
ecc: Option[Code] = None,
nMSHRs: Int = 1,
nSDQ: Int = 17,
nRPQ: Int = 16,
nMMIOs: Int = 1) extends L1CacheParams {
def replacement = new RandomReplacement(nWays)
}
case object DCacheKey extends Field[DCacheConfig] trait HasL1HellaCacheParameters extends HasL1CacheParameters
with HasCoreParameters {
val cacheParams = tileParams.dcache.get
val cfg = cacheParams
trait HasL1HellaCacheParameters extends HasL1CacheParameters { def wordBits = xLen // really, xLen max
val wordBits = xLen // really, xLen max def wordBytes = wordBits/8
val wordBytes = wordBits/8 def wordOffBits = log2Up(wordBytes)
val wordOffBits = log2Up(wordBytes) def beatBytes = cacheBlockBytes / cacheDataBeats
val beatBytes = cacheBlockBytes / cacheDataBeats def beatWords = beatBytes / wordBytes
val beatWords = beatBytes / wordBytes def beatOffBits = log2Up(beatBytes)
val beatOffBits = log2Up(beatBytes) def idxMSB = untagBits-1
val idxMSB = untagBits-1 def idxLSB = blockOffBits
val idxLSB = blockOffBits def offsetmsb = idxLSB-1
val offsetmsb = idxLSB-1 def offsetlsb = wordOffBits
val offsetlsb = wordOffBits def rowWords = rowBits/wordBits
val rowWords = rowBits/wordBits def doNarrowRead = coreDataBits * nWays % rowBits == 0
val doNarrowRead = coreDataBits * nWays % rowBits == 0 def encDataBits = code.width(coreDataBits)
val encDataBits = code.width(coreDataBits) def encRowBits = encDataBits*rowWords
val encRowBits = encDataBits*rowWords def lrscCycles = 32 // ISA requires 16-insn LRSC sequences to succeed
val nIOMSHRs = 1 def nIOMSHRs = cacheParams.nMMIOs
val lrscCycles = 32 // ISA requires 16-insn LRSC sequences to succeed def maxUncachedInFlight = cacheParams.nMMIOs
def dataScratchpadSize = tileParams.dataScratchpadBytes
require(isPow2(nSets)) require(isPow2(nSets), s"nSets($nSets) must be pow2")
require(rowBits >= coreDataBits) require(rowBits >= coreDataBits, s"rowBits($rowBits) < coreDataBits($coreDataBits)")
require(rowBits == cacheDataBits) // TODO should rowBits even be seperably specifiable? // TODO should rowBits even be seperably specifiable?
require(xLen <= cacheDataBits) // would need offset addr for puts if data width < xlen require(rowBits == cacheDataBits, s"rowBits($rowBits) != cacheDataBits($cacheDataBits)")
require(!usingVM || untagBits <= pgIdxBits) // would need offset addr for puts if data width < xlen
require(xLen <= cacheDataBits, s"xLen($xLen) > cacheDataBits($cacheDataBits)")
require(!usingVM || untagBits <= pgIdxBits, s"untagBits($untagBits) > pgIdxBits($pgIdxBits)")
} }
abstract class L1HellaCacheModule(implicit val p: Parameters) extends Module abstract class L1HellaCacheModule(implicit val p: Parameters) extends Module
@ -52,25 +67,7 @@ abstract class L1HellaCacheModule(implicit val p: Parameters) extends Module
abstract class L1HellaCacheBundle(implicit val p: Parameters) extends ParameterizedBundle()(p) abstract class L1HellaCacheBundle(implicit val p: Parameters) extends ParameterizedBundle()(p)
with HasL1HellaCacheParameters with HasL1HellaCacheParameters
class L1Metadata(implicit p: Parameters) extends Metadata()(p) with HasL1HellaCacheParameters { /** Bundle definitions for HellaCache interfaces */
val coh = new ClientMetadata
}
object L1Metadata {
def apply(tag: Bits, coh: ClientMetadata)(implicit p: Parameters) = {
val meta = Wire(new L1Metadata)
meta.tag := tag
meta.coh := coh
meta
}
}
class L1MetaReadReq(implicit p: Parameters) extends MetaReadReq {
val tag = Bits(width = tagBits)
override def cloneType = new L1MetaReadReq()(p).asInstanceOf[this.type] //TODO remove
}
class L1MetaWriteReq(implicit p: Parameters) extends
MetaWriteReq[L1Metadata](new L1Metadata)
trait HasCoreMemOp extends HasCoreParameters { trait HasCoreMemOp extends HasCoreParameters {
val addr = UInt(width = coreMaxAddrBits) val addr = UInt(width = coreMaxAddrBits)
@ -83,6 +80,10 @@ trait HasCoreData extends HasCoreParameters {
val data = Bits(width = coreDataBits) val data = Bits(width = coreDataBits)
} }
class HellaCacheReqInternal(implicit p: Parameters) extends CoreBundle()(p) with HasCoreMemOp {
val phys = Bool()
}
class HellaCacheReq(implicit p: Parameters) extends HellaCacheReqInternal()(p) with HasCoreData class HellaCacheReq(implicit p: Parameters) extends HellaCacheReqInternal()(p) with HasCoreData
class HellaCacheResp(implicit p: Parameters) extends CoreBundle()(p) class HellaCacheResp(implicit p: Parameters) extends CoreBundle()(p)
@ -104,7 +105,6 @@ class HellaCacheExceptions extends Bundle {
val pf = new AlignmentExceptions val pf = new AlignmentExceptions
} }
// interface between D$ and processor/DTLB // interface between D$ and processor/DTLB
class HellaCacheIO(implicit p: Parameters) extends CoreBundle()(p) { class HellaCacheIO(implicit p: Parameters) extends CoreBundle()(p) {
val req = Decoupled(new HellaCacheReq) val req = Decoupled(new HellaCacheReq)
@ -119,10 +119,13 @@ class HellaCacheIO(implicit p: Parameters) extends CoreBundle()(p) {
val ordered = Bool(INPUT) val ordered = Bool(INPUT)
} }
abstract class HellaCache(val cfg: DCacheConfig)(implicit p: Parameters) extends LazyModule { /** Base classes for Diplomatic TL2 HellaCaches */
abstract class HellaCache(implicit p: Parameters) extends LazyModule {
private val cfg = p(TileKey).dcache.get
val node = TLClientNode(TLClientParameters( val node = TLClientNode(TLClientParameters(
sourceId = IdRange(0, cfg.nMSHRs + cfg.nMMIOs), sourceId = IdRange(0, cfg.nMSHRs + cfg.nMMIOs),
supportsProbe = TransferSizes(p(CacheBlockBytes)))) supportsProbe = TransferSizes(1, p(CacheBlockBytes))))
val module: HellaCacheModule val module: HellaCacheModule
} }
@ -135,38 +138,101 @@ class HellaCacheBundle(outer: HellaCache) extends Bundle {
class HellaCacheModule(outer: HellaCache) extends LazyModuleImp(outer) class HellaCacheModule(outer: HellaCache) extends LazyModuleImp(outer)
with HasL1HellaCacheParameters { with HasL1HellaCacheParameters {
implicit val cfg = outer.cfg
implicit val edge = outer.node.edgesOut(0) implicit val edge = outer.node.edgesOut(0)
val io = new HellaCacheBundle(outer) val io = new HellaCacheBundle(outer)
val tl_out = io.mem(0) val tl_out = io.mem(0)
} }
object HellaCache { object HellaCache {
def apply(cfg: DCacheConfig, scratch: () => Option[AddressSet] = () => None)(implicit p: Parameters) = { def apply(blocking: Boolean, scratch: () => Option[AddressSet] = () => None)(implicit p: Parameters) = {
if (cfg.nMSHRs == 0) LazyModule(new DCache(cfg, scratch)) if (blocking) LazyModule(new DCache(scratch))
else LazyModule(new NonBlockingDCache(cfg)) else LazyModule(new NonBlockingDCache)
} }
} }
/** Mix-ins for constructing tiles that have a HellaCache */ /** Mix-ins for constructing tiles that have a HellaCache */
trait HasHellaCache extends TileNetwork {
trait HasHellaCache extends HasTileLinkMasterPort {
val module: HasHellaCacheModule val module: HasHellaCacheModule
implicit val p: Parameters implicit val p: Parameters
def findScratchpadFromICache: Option[AddressSet] def findScratchpadFromICache: Option[AddressSet]
var nDCachePorts = 0 var nDCachePorts = 0
val dcacheParams = p.alterPartial({ case CacheName => CacheName("L1D") }) val dcache = HellaCache(tileParams.dcache.get.nMSHRs == 0, findScratchpadFromICache _)
val dcache = HellaCache(p(DCacheKey), findScratchpadFromICache _)(dcacheParams) masterNode := dcache.node
l1backend.node := dcache.node
} }
trait HasHellaCacheBundle extends TileNetworkBundle { trait HasHellaCacheBundle extends HasTileLinkMasterPortBundle {
val outer: HasHellaCache val outer: HasHellaCache
} }
trait HasHellaCacheModule extends TileNetworkModule { trait HasHellaCacheModule extends HasTileLinkMasterPortModule {
val outer: HasHellaCache val outer: HasHellaCache
//val io: HasHellaCacheBundle //val io: HasHellaCacheBundle
val dcachePorts = ListBuffer[HellaCacheIO]() val dcachePorts = ListBuffer[HellaCacheIO]()
val dcacheArb = Module(new HellaCacheArbiter(outer.nDCachePorts)(outer.dcacheParams)) val dcacheArb = Module(new HellaCacheArbiter(outer.nDCachePorts)(outer.p))
outer.dcache.module.io.cpu <> dcacheArb.io.mem outer.dcache.module.io.cpu <> dcacheArb.io.mem
} }
/** Metadata array used for all HellaCaches */
class L1Metadata(implicit p: Parameters) extends L1HellaCacheBundle()(p) {
val coh = new ClientMetadata
val tag = UInt(width = tagBits)
}
object L1Metadata {
def apply(tag: Bits, coh: ClientMetadata)(implicit p: Parameters) = {
val meta = Wire(new L1Metadata)
meta.tag := tag
meta.coh := coh
meta
}
}
class L1MetaReadReq(implicit p: Parameters) extends L1HellaCacheBundle()(p) {
val idx = UInt(width = idxBits)
val way_en = UInt(width = nWays)
val tag = UInt(width = tagBits)
}
class L1MetaWriteReq(implicit p: Parameters) extends L1MetaReadReq()(p) {
val data = new L1Metadata
}
class L1MetadataArray[T <: L1Metadata](onReset: () => T)(implicit p: Parameters) extends L1HellaCacheModule()(p) {
val rstVal = onReset()
val io = new Bundle {
val read = Decoupled(new L1MetaReadReq).flip
val write = Decoupled(new L1MetaWriteReq).flip
val resp = Vec(nWays, rstVal.cloneType).asOutput
}
val rst_cnt = Reg(init=UInt(0, log2Up(nSets+1)))
val rst = rst_cnt < UInt(nSets)
val waddr = Mux(rst, rst_cnt, io.write.bits.idx)
val wdata = Mux(rst, rstVal, io.write.bits.data).asUInt
val wmask = Mux(rst || Bool(nWays == 1), SInt(-1), io.write.bits.way_en.asSInt).toBools
val rmask = Mux(rst || Bool(nWays == 1), SInt(-1), io.read.bits.way_en.asSInt).toBools
when (rst) { rst_cnt := rst_cnt+UInt(1) }
val metabits = rstVal.getWidth
if (hasSplitMetadata) {
val tag_arrs = List.fill(nWays){ SeqMem(nSets, UInt(width = metabits)) }
val tag_readout = Wire(Vec(nWays,rstVal.cloneType))
(0 until nWays).foreach { (i) =>
when (rst || (io.write.valid && wmask(i))) {
tag_arrs(i).write(waddr, wdata)
}
io.resp(i) := rstVal.fromBits(tag_arrs(i).read(io.read.bits.idx, io.read.valid && rmask(i)))
}
} else {
val tag_arr = SeqMem(nSets, Vec(nWays, UInt(width = metabits)))
when (rst || io.write.valid) {
tag_arr.write(waddr, Vec.fill(nWays)(wdata), wmask)
}
io.resp := tag_arr.read(io.read.bits.idx, io.read.valid).map(rstVal.fromBits(_))
}
io.read.ready := !rst && !io.write.valid // so really this could be a 6T RAM
io.write.ready := !rst
}

View File

@ -3,9 +3,10 @@
package rocket package rocket
import Chisel._ import Chisel._
import util._
import Chisel.ImplicitConversions._ import Chisel.ImplicitConversions._
import config._ import config._
import tile._
import util._
class Instruction(implicit val p: Parameters) extends ParameterizedBundle with HasCoreParameters { class Instruction(implicit val p: Parameters) extends ParameterizedBundle with HasCoreParameters {
val pf0 = Bool() // page fault on first half of instruction val pf0 = Bool() // page fault on first half of instruction

View File

@ -6,25 +6,32 @@ package rocket
import Chisel._ import Chisel._
import config._ import config._
import diplomacy._ import diplomacy._
import uncore.agents._ import tile._
import uncore.tilelink2._ import uncore.tilelink2._
import uncore.util._ import uncore.util.Code
import util._ import util._
import Chisel.ImplicitConversions._ import Chisel.ImplicitConversions._
trait HasL1CacheParameters extends HasCacheParameters with HasCoreParameters { case class ICacheParams(
val cacheBlockBytes = p(CacheBlockBytes) nSets: Int = 64,
val lgCacheBlockBytes = log2Up(cacheBlockBytes) nWays: Int = 4,
val cacheDataBits = p(SharedMemoryTLEdge).bundle.dataBits rowBits: Int = 128,
val cacheDataBeats = (cacheBlockBytes * 8) / cacheDataBits nTLBEntries: Int = 8,
val refillCycles = cacheDataBeats cacheIdBits: Int = 0,
splitMetadata: Boolean = false,
ecc: Option[Code] = None) extends L1CacheParams {
def replacement = new RandomReplacement(nWays)
} }
class ICacheReq(implicit p: Parameters) extends CoreBundle()(p) with HasL1CacheParameters { trait HasL1ICacheParameters extends HasL1CacheParameters with HasCoreParameters {
val cacheParams = tileParams.icache.get
}
class ICacheReq(implicit p: Parameters) extends CoreBundle()(p) with HasL1ICacheParameters {
val addr = UInt(width = vaddrBits) val addr = UInt(width = vaddrBits)
} }
class ICacheResp(implicit p: Parameters) extends CoreBundle()(p) with HasL1CacheParameters { class ICacheResp(implicit p: Parameters) extends CoreBundle()(p) with HasL1ICacheParameters {
val data = Bits(width = coreInstBits) val data = Bits(width = coreInstBits)
val datablock = Bits(width = rowBits) val datablock = Bits(width = rowBits)
} }
@ -46,8 +53,7 @@ class ICacheBundle(outer: ICache) extends CoreBundle()(outer.p) {
} }
class ICacheModule(outer: ICache) extends LazyModuleImp(outer) class ICacheModule(outer: ICache) extends LazyModuleImp(outer)
with HasCoreParameters with HasL1ICacheParameters {
with HasL1CacheParameters {
val io = new ICacheBundle(outer) val io = new ICacheBundle(outer)
val edge = outer.node.edgesOut(0) val edge = outer.node.edgesOut(0)
val tl_out = io.mem(0) val tl_out = io.mem(0)

View File

@ -4,12 +4,13 @@
package rocket package rocket
import Chisel._ import Chisel._
import Chisel.ImplicitConversions._
import Instructions._ import Instructions._
import uncore.constants.MemoryOpConstants._ import uncore.constants.MemoryOpConstants._
import ALU._ import ALU._
import config._ import config._
import tile.HasCoreParameters
import util._ import util._
import Chisel.ImplicitConversions._
abstract trait DecodeConstants extends HasCoreParameters abstract trait DecodeConstants extends HasCoreParameters
{ {

View File

@ -29,13 +29,13 @@ class MultiplierIO(dataBits: Int, tagBits: Int) extends Bundle {
val resp = Decoupled(new MultiplierResp(dataBits, tagBits)) val resp = Decoupled(new MultiplierResp(dataBits, tagBits))
} }
case class MulDivConfig( case class MulDivParams(
mulUnroll: Int = 1, mulUnroll: Int = 1,
mulEarlyOut: Boolean = false, mulEarlyOut: Boolean = false,
divEarlyOut: Boolean = false divEarlyOut: Boolean = false
) )
class MulDiv(cfg: MulDivConfig, width: Int, nXpr: Int = 32) extends Module { class MulDiv(cfg: MulDivParams, width: Int, nXpr: Int = 32) extends Module {
val io = new MultiplierIO(width, log2Up(nXpr)) val io = new MultiplierIO(width, log2Up(nXpr))
val w = io.req.bits.in1.getWidth val w = io.req.bits.in1.getWidth
val mulw = (w + cfg.mulUnroll - 1) / cfg.mulUnroll * cfg.mulUnroll val mulw = (w + cfg.mulUnroll - 1) / cfg.mulUnroll * cfg.mulUnroll

View File

@ -5,13 +5,12 @@ package rocket
import Chisel._ import Chisel._
import Chisel.ImplicitConversions._ import Chisel.ImplicitConversions._
import config._
import diplomacy._ import diplomacy._
import uncore.constants._ import uncore.constants._
import uncore.tilelink._
import uncore.tilelink2._ import uncore.tilelink2._
import uncore.util._ import uncore.util._
import util._ import util._
import config._
trait HasMissInfo extends HasL1HellaCacheParameters { trait HasMissInfo extends HasL1HellaCacheParameters {
val tag_match = Bool() val tag_match = Bool()
@ -19,11 +18,6 @@ trait HasMissInfo extends HasL1HellaCacheParameters {
val way_en = Bits(width = nWays) val way_en = Bits(width = nWays)
} }
class HellaCacheReqInternal(implicit p: Parameters) extends CoreBundle()(p)
with HasCoreMemOp {
val phys = Bool()
}
class L1DataReadReq(implicit p: Parameters) extends L1HellaCacheBundle()(p) { class L1DataReadReq(implicit p: Parameters) extends L1HellaCacheBundle()(p) {
val way_en = Bits(width = nWays) val way_en = Bits(width = nWays)
val addr = Bits(width = untagBits) val addr = Bits(width = untagBits)
@ -38,18 +32,14 @@ class L1RefillReq(implicit p: Parameters) extends L1DataReadReq()(p)
class Replay(implicit p: Parameters) extends HellaCacheReqInternal()(p) with HasCoreData class Replay(implicit p: Parameters) extends HellaCacheReqInternal()(p) with HasCoreData
class ReplayInternal(cfg: DCacheConfig)(implicit p: Parameters) extends HellaCacheReqInternal()(p) { class ReplayInternal(implicit p: Parameters) extends HellaCacheReqInternal()(p)
with HasL1HellaCacheParameters {
val sdq_id = UInt(width = log2Up(cfg.nSDQ)) val sdq_id = UInt(width = log2Up(cfg.nSDQ))
override def cloneType = new ReplayInternal(cfg)(p).asInstanceOf[this.type]
} }
class MSHRReq(implicit p: Parameters) extends Replay()(p) with HasMissInfo class MSHRReq(implicit p: Parameters) extends Replay()(p) with HasMissInfo
class MSHRReqInternal(cfg: DCacheConfig)(implicit p: Parameters) class MSHRReqInternal(implicit p: Parameters) extends ReplayInternal()(p) with HasMissInfo
extends ReplayInternal(cfg)(p) with HasMissInfo {
override def cloneType = new MSHRReqInternal(cfg)(p).asInstanceOf[this.type]
}
class WritebackReq(params: TLBundleParameters)(implicit p: Parameters) extends L1HellaCacheBundle()(p) { class WritebackReq(params: TLBundleParameters)(implicit p: Parameters) extends L1HellaCacheBundle()(p) {
val tag = Bits(width = tagBits) val tag = Bits(width = tagBits)
@ -145,13 +135,13 @@ class IOMSHR(id: Int)(implicit edge: TLEdgeOut, p: Parameters) extends L1HellaCa
} }
} }
class MSHR(id: Int)(implicit edge: TLEdgeOut, cfg: DCacheConfig, p: Parameters) extends L1HellaCacheModule()(p) { class MSHR(id: Int)(implicit edge: TLEdgeOut, p: Parameters) extends L1HellaCacheModule()(p) {
val io = new Bundle { val io = new Bundle {
val req_pri_val = Bool(INPUT) val req_pri_val = Bool(INPUT)
val req_pri_rdy = Bool(OUTPUT) val req_pri_rdy = Bool(OUTPUT)
val req_sec_val = Bool(INPUT) val req_sec_val = Bool(INPUT)
val req_sec_rdy = Bool(OUTPUT) val req_sec_rdy = Bool(OUTPUT)
val req_bits = new MSHRReqInternal(cfg).asInput val req_bits = new MSHRReqInternal().asInput
val idx_match = Bool(OUTPUT) val idx_match = Bool(OUTPUT)
val tag = Bits(OUTPUT, tagBits) val tag = Bits(OUTPUT, tagBits)
@ -163,7 +153,7 @@ class MSHR(id: Int)(implicit edge: TLEdgeOut, cfg: DCacheConfig, p: Parameters)
val refill = new L1RefillReq().asOutput // Data is bypassed val refill = new L1RefillReq().asOutput // Data is bypassed
val meta_read = Decoupled(new L1MetaReadReq) val meta_read = Decoupled(new L1MetaReadReq)
val meta_write = Decoupled(new L1MetaWriteReq) val meta_write = Decoupled(new L1MetaWriteReq)
val replay = Decoupled(new ReplayInternal(cfg)) val replay = Decoupled(new ReplayInternal)
val wb_req = Decoupled(new WritebackReq(edge.bundle)) val wb_req = Decoupled(new WritebackReq(edge.bundle))
val probe_rdy = Bool(OUTPUT) val probe_rdy = Bool(OUTPUT)
} }
@ -171,7 +161,7 @@ class MSHR(id: Int)(implicit edge: TLEdgeOut, cfg: DCacheConfig, p: Parameters)
val s_invalid :: s_wb_req :: s_wb_resp :: s_meta_clear :: s_refill_req :: s_refill_resp :: s_meta_write_req :: s_meta_write_resp :: s_drain_rpq :: Nil = Enum(UInt(), 9) val s_invalid :: s_wb_req :: s_wb_resp :: s_meta_clear :: s_refill_req :: s_refill_resp :: s_meta_write_req :: s_meta_write_resp :: s_drain_rpq :: Nil = Enum(UInt(), 9)
val state = Reg(init=s_invalid) val state = Reg(init=s_invalid)
val req = Reg(new MSHRReqInternal(cfg)) val req = Reg(new MSHRReqInternal)
val req_idx = req.addr(untagBits-1,blockOffBits) val req_idx = req.addr(untagBits-1,blockOffBits)
val req_tag = req.addr >> untagBits val req_tag = req.addr >> untagBits
val req_block_addr = (req.addr >> blockOffBits) << blockOffBits val req_block_addr = (req.addr >> blockOffBits) << blockOffBits
@ -195,7 +185,7 @@ class MSHR(id: Int)(implicit edge: TLEdgeOut, cfg: DCacheConfig, p: Parameters)
(state.isOneOf(s_refill_req, s_refill_resp) && (state.isOneOf(s_refill_req, s_refill_resp) &&
!cmd_requires_second_acquire && !refill_done)) !cmd_requires_second_acquire && !refill_done))
val rpq = Module(new Queue(new ReplayInternal(cfg), cfg.nRPQ)) val rpq = Module(new Queue(new ReplayInternal, cfg.nRPQ))
rpq.io.enq.valid := (io.req_pri_val && io.req_pri_rdy || io.req_sec_val && sec_rdy) && !isPrefetch(io.req_bits.cmd) rpq.io.enq.valid := (io.req_pri_val && io.req_pri_rdy || io.req_sec_val && sec_rdy) && !isPrefetch(io.req_bits.cmd)
rpq.io.enq.bits := io.req_bits rpq.io.enq.bits := io.req_bits
rpq.io.deq.ready := (io.replay.ready && state === s_drain_rpq) || state === s_invalid rpq.io.deq.ready := (io.replay.ready && state === s_drain_rpq) || state === s_invalid
@ -310,7 +300,7 @@ class MSHR(id: Int)(implicit edge: TLEdgeOut, cfg: DCacheConfig, p: Parameters)
} }
} }
class MSHRFile(implicit edge: TLEdgeOut, cfg: DCacheConfig, p: Parameters) extends L1HellaCacheModule()(p) { class MSHRFile(implicit edge: TLEdgeOut, p: Parameters) extends L1HellaCacheModule()(p) {
val io = new Bundle { val io = new Bundle {
val req = Decoupled(new MSHRReq).flip val req = Decoupled(new MSHRReq).flip
val resp = Decoupled(new HellaCacheResp) val resp = Decoupled(new HellaCacheResp)
@ -350,7 +340,7 @@ class MSHRFile(implicit edge: TLEdgeOut, cfg: DCacheConfig, p: Parameters) exten
val meta_read_arb = Module(new Arbiter(new L1MetaReadReq, cfg.nMSHRs)) val meta_read_arb = Module(new Arbiter(new L1MetaReadReq, cfg.nMSHRs))
val meta_write_arb = Module(new Arbiter(new L1MetaWriteReq, cfg.nMSHRs)) val meta_write_arb = Module(new Arbiter(new L1MetaWriteReq, cfg.nMSHRs))
val wb_req_arb = Module(new Arbiter(new WritebackReq(edge.bundle), cfg.nMSHRs)) val wb_req_arb = Module(new Arbiter(new WritebackReq(edge.bundle), cfg.nMSHRs))
val replay_arb = Module(new Arbiter(new ReplayInternal(cfg), cfg.nMSHRs)) val replay_arb = Module(new Arbiter(new ReplayInternal, cfg.nMSHRs))
val alloc_arb = Module(new Arbiter(Bool(), cfg.nMSHRs)) val alloc_arb = Module(new Arbiter(Bool(), cfg.nMSHRs))
var idx_match = Bool(false) var idx_match = Bool(false)
@ -671,14 +661,14 @@ class DataArray(implicit p: Parameters) extends L1HellaCacheModule()(p) {
io.write.ready := Bool(true) io.write.ready := Bool(true)
} }
class NonBlockingDCache(cfg: DCacheConfig)(implicit p: Parameters) extends HellaCache(cfg)(p) { class NonBlockingDCache(implicit p: Parameters) extends HellaCache()(p) {
override lazy val module = new NonBlockingDCacheModule(this) override lazy val module = new NonBlockingDCacheModule(this)
} }
class NonBlockingDCacheModule(outer: NonBlockingDCache) extends HellaCacheModule(outer) { class NonBlockingDCacheModule(outer: NonBlockingDCache) extends HellaCacheModule(outer) {
require(isPow2(nWays)) // TODO: relax this require(isPow2(nWays)) // TODO: relax this
require(p(DataScratchpadSize) == 0) require(dataScratchpadSize == 0)
val wb = Module(new WritebackUnit) val wb = Module(new WritebackUnit)
val prober = Module(new ProbeUnit) val prober = Module(new ProbeUnit)
@ -706,7 +696,7 @@ class NonBlockingDCacheModule(outer: NonBlockingDCache) extends HellaCacheModule
val s1_write = isWrite(s1_req.cmd) val s1_write = isWrite(s1_req.cmd)
val s1_readwrite = s1_read || s1_write || isPrefetch(s1_req.cmd) val s1_readwrite = s1_read || s1_write || isPrefetch(s1_req.cmd)
val dtlb = Module(new TLB) val dtlb = Module(new TLB(nTLBEntries))
io.ptw <> dtlb.io.ptw io.ptw <> dtlb.io.ptw
dtlb.io.req.valid := s1_valid_masked && s1_readwrite dtlb.io.req.valid := s1_valid_masked && s1_readwrite
dtlb.io.req.bits.passthrough := s1_req.phys dtlb.io.req.bits.passthrough := s1_req.phys
@ -754,8 +744,8 @@ class NonBlockingDCacheModule(outer: NonBlockingDCache) extends HellaCacheModule
// tags // tags
def onReset = L1Metadata(UInt(0), ClientMetadata.onReset) def onReset = L1Metadata(UInt(0), ClientMetadata.onReset)
val meta = Module(new MetadataArray(onReset _)) val meta = Module(new L1MetadataArray(onReset _))
val metaReadArb = Module(new Arbiter(new MetaReadReq, 5)) val metaReadArb = Module(new Arbiter(new L1MetaReadReq, 5))
val metaWriteArb = Module(new Arbiter(new L1MetaWriteReq, 2)) val metaWriteArb = Module(new Arbiter(new L1MetaWriteReq, 2))
meta.io.read <> metaReadArb.io.out meta.io.read <> metaReadArb.io.out
meta.io.write <> metaWriteArb.io.out meta.io.write <> metaWriteArb.io.out
@ -852,7 +842,7 @@ class NonBlockingDCacheModule(outer: NonBlockingDCache) extends HellaCacheModule
writeArb.io.in(0).bits.way_en := s3_way writeArb.io.in(0).bits.way_en := s3_way
// replacement policy // replacement policy
val replacer = p(Replacer)() val replacer = cacheParams.replacement
val s1_replaced_way_en = UIntToOH(replacer.way) val s1_replaced_way_en = UIntToOH(replacer.way)
val s2_replaced_way_en = UIntToOH(RegEnable(replacer.way, s1_clk_en)) val s2_replaced_way_en = UIntToOH(RegEnable(replacer.way, s1_clk_en))
val s2_repl_meta = Mux1H(s2_replaced_way_en, wayMap((w: Int) => RegEnable(meta.io.resp(w), s1_clk_en && s1_replaced_way_en(w))).toSeq) val s2_repl_meta = Mux1H(s2_replaced_way_en, wayMap((w: Int) => RegEnable(meta.io.resp(w), s1_clk_en && s1_replaced_way_en(w))).toSeq)

View File

@ -4,11 +4,12 @@
package rocket package rocket
import Chisel._ import Chisel._
import config._
import uncore.constants._
import uncore.util.PseudoLRU
import util._
import Chisel.ImplicitConversions._ import Chisel.ImplicitConversions._
import config._
import tile._
import uncore.constants._
import util._
import scala.collection.mutable.ListBuffer import scala.collection.mutable.ListBuffer
class PTWReq(implicit p: Parameters) extends CoreBundle()(p) { class PTWReq(implicit p: Parameters) extends CoreBundle()(p) {
@ -224,11 +225,12 @@ trait CanHavePTW extends HasHellaCache {
implicit val p: Parameters implicit val p: Parameters
val module: CanHavePTWModule val module: CanHavePTWModule
var nPTWPorts = 1 var nPTWPorts = 1
nDCachePorts += usingPTW.toInt
} }
trait CanHavePTWModule extends HasHellaCacheModule { trait CanHavePTWModule extends HasHellaCacheModule {
val outer: CanHavePTW val outer: CanHavePTW
val ptwPorts = ListBuffer(outer.dcache.module.io.ptw) val ptwPorts = ListBuffer(outer.dcache.module.io.ptw)
val ptwOpt = if (outer.p(UseVM)) { Some(Module(new PTW(outer.nPTWPorts)(outer.p))) } else None val ptwOpt = if (outer.usingPTW) { Some(Module(new PTW(outer.nPTWPorts)(outer.p))) } else None
ptwOpt foreach { ptw => dcachePorts += ptw.io.mem } ptwOpt foreach { ptw => dcachePorts += ptw.io.mem }
} }

View File

@ -4,8 +4,9 @@ package rocket
import Chisel._ import Chisel._
import Chisel.ImplicitConversions._ import Chisel.ImplicitConversions._
import util._
import config._ import config._
import tile._
import util._
class ExpandedInstruction extends Bundle { class ExpandedInstruction extends Bundle {
val bits = UInt(width = 32) val bits = UInt(width = 32)
@ -150,14 +151,14 @@ class RVCDecoder(x: UInt)(implicit p: Parameters) {
} }
} }
class RVCExpander(implicit p: Parameters) extends Module { class RVCExpander(implicit val p: Parameters) extends Module with HasCoreParameters {
val io = new Bundle { val io = new Bundle {
val in = UInt(INPUT, 32) val in = UInt(INPUT, 32)
val out = new ExpandedInstruction val out = new ExpandedInstruction
val rvc = Bool(OUTPUT) val rvc = Bool(OUTPUT)
} }
if (p(UseCompressed)) { if (usingCompressed) {
io.rvc := io.in(1,0) =/= UInt(3) io.rvc := io.in(1,0) =/= UInt(3)
io.out := new RVCDecoder(io.in).decode io.out := new RVCDecoder(io.in).decode
} else { } else {

View File

@ -5,76 +5,57 @@ package rocket
import Chisel._ import Chisel._
import config._ import config._
import tile._
import uncore.constants._ import uncore.constants._
import util._ import util._
import Chisel.ImplicitConversions._ import Chisel.ImplicitConversions._
case class RocketConfig(xLen: Int) case class RocketCoreParams(
// TODO replace some of below fields with above Config useVM: Boolean = true,
case object XLen extends Field[Int] useUser: Boolean = false,
case object FetchWidth extends Field[Int] useDebug: Boolean = true,
case object RetireWidth extends Field[Int] useAtomics: Boolean = true,
case object FPUKey extends Field[Option[FPUConfig]] useCompressed: Boolean = true,
case object MulDivKey extends Field[Option[MulDivConfig]] nBreakpoints: Int = 1,
case object UseVM extends Field[Boolean] nPerfCounters: Int = 0,
case object UseUser extends Field[Boolean] nPerfEvents: Int = 0,
case object UseDebug extends Field[Boolean] nCustomMRWCSRs: Int = 0,
case object UseAtomics extends Field[Boolean] mtvecInit: Option[BigInt] = Some(BigInt(0)),
case object UseCompressed extends Field[Boolean] mtvecWritable: Boolean = true,
case object FastLoadWord extends Field[Boolean] fastLoadWord: Boolean = true,
case object FastLoadByte extends Field[Boolean] fastLoadByte: Boolean = false,
case object FastJAL extends Field[Boolean] fastJAL: Boolean = false,
case object CoreInstBits extends Field[Int] mulDiv: Option[MulDivParams] = Some(MulDivParams()),
case object NCustomMRWCSRs extends Field[Int] fpu: Option[FPUParams] = Some(FPUParams())
case object MtvecWritable extends Field[Boolean] ) extends CoreParams {
case object MtvecInit extends Field[Option[BigInt]] val fetchWidth: Int = if (useCompressed) 2 else 1
case object NBreakpoints extends Field[Int] // fetchWidth doubled, but coreInstBytes halved, for RVC:
case object NPerfCounters extends Field[Int] val decodeWidth: Int = fetchWidth / (if (useCompressed) 2 else 1)
case object NPerfEvents extends Field[Int] val retireWidth: Int = 1
case object DataScratchpadSize extends Field[Int] val instBits: Int = if (useCompressed) 16 else 32
class RegFile(n: Int, w: Int, zero: Boolean = false) {
private val rf = Mem(n, UInt(width = w))
private def access(addr: UInt) = rf(~addr(log2Up(n)-1,0))
private val reads = collection.mutable.ArrayBuffer[(UInt,UInt)]()
private var canRead = true
def read(addr: UInt) = {
require(canRead)
reads += addr -> Wire(UInt())
reads.last._2 := Mux(Bool(zero) && addr === UInt(0), UInt(0), access(addr))
reads.last._2
}
def write(addr: UInt, data: UInt) = {
canRead = false
when (addr =/= UInt(0)) {
access(addr) := data
for ((raddr, rdata) <- reads)
when (addr === raddr) { rdata := data }
}
}
} }
object ImmGen { trait HasRocketCoreParameters extends HasCoreParameters {
def apply(sel: UInt, inst: UInt) = { val rocketParams: RocketCoreParams = tileParams.core.asInstanceOf[RocketCoreParams]
val sign = Mux(sel === IMM_Z, SInt(0), inst(31).asSInt)
val b30_20 = Mux(sel === IMM_U, inst(30,20).asSInt, sign)
val b19_12 = Mux(sel =/= IMM_U && sel =/= IMM_UJ, sign, inst(19,12).asSInt)
val b11 = Mux(sel === IMM_U || sel === IMM_Z, SInt(0),
Mux(sel === IMM_UJ, inst(20).asSInt,
Mux(sel === IMM_SB, inst(7).asSInt, sign)))
val b10_5 = Mux(sel === IMM_U || sel === IMM_Z, Bits(0), inst(30,25))
val b4_1 = Mux(sel === IMM_U, Bits(0),
Mux(sel === IMM_S || sel === IMM_SB, inst(11,8),
Mux(sel === IMM_Z, inst(19,16), inst(24,21))))
val b0 = Mux(sel === IMM_S, inst(7),
Mux(sel === IMM_I, inst(20),
Mux(sel === IMM_Z, inst(15), Bits(0))))
Cat(sign, b30_20, b19_12, b11, b10_5, b4_1, b0).asSInt val fastLoadWord = rocketParams.fastLoadWord
} val fastLoadByte = rocketParams.fastLoadByte
val fastJAL = rocketParams.fastJAL
val nBreakpoints = rocketParams.nBreakpoints
val nPerfCounters = rocketParams.nPerfCounters
val nPerfEvents = rocketParams.nPerfEvents
val nCustomMrwCsrs = rocketParams.nCustomMRWCSRs
val mtvecInit = rocketParams.mtvecInit
val mtvecWritable = rocketParams.mtvecWritable
val mulDivParams = rocketParams.mulDiv.getOrElse(MulDivParams()) // TODO ask andrew about this
require(!fastLoadByte || fastLoadWord)
} }
class Rocket(val c: RocketConfig)(implicit p: Parameters) extends CoreModule()(p) with HasCoreIO { class Rocket(implicit p: Parameters) extends CoreModule()(p)
with HasRocketCoreParameters
with HasCoreIO {
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) ++:
@ -243,7 +224,7 @@ class Rocket(val c: RocketConfig)(implicit p: Parameters) extends CoreModule()(p
alu.io.in1 := ex_op1.asUInt alu.io.in1 := ex_op1.asUInt
// multiplier and divider // multiplier and divider
val div = Module(new MulDiv(p(MulDivKey).getOrElse(MulDivConfig()), width = xLen)) val div = Module(new MulDiv(mulDivParams, width = xLen))
div.io.req.valid := ex_reg_valid && ex_ctrl.div div.io.req.valid := ex_reg_valid && ex_ctrl.div
div.io.req.bits.dw := ex_ctrl.alu_dw div.io.req.bits.dw := ex_ctrl.alu_dw
div.io.req.bits.fn := ex_ctrl.alu_fn div.io.req.bits.fn := ex_ctrl.alu_fn
@ -324,9 +305,7 @@ class Rocket(val c: RocketConfig)(implicit p: Parameters) extends CoreModule()(p
val mem_int_wdata = Mux(!mem_reg_xcpt && (mem_ctrl.jalr ^ mem_npc_misaligned), mem_br_target, mem_reg_wdata.asSInt).asUInt val mem_int_wdata = Mux(!mem_reg_xcpt && (mem_ctrl.jalr ^ mem_npc_misaligned), mem_br_target, mem_reg_wdata.asSInt).asUInt
val mem_cfi = mem_ctrl.branch || mem_ctrl.jalr || mem_ctrl.jal val mem_cfi = mem_ctrl.branch || mem_ctrl.jalr || mem_ctrl.jal
val mem_cfi_taken = (mem_ctrl.branch && mem_br_taken) || mem_ctrl.jalr || (Bool(!fastJAL) && mem_ctrl.jal) val mem_cfi_taken = (mem_ctrl.branch && mem_br_taken) || mem_ctrl.jalr || (Bool(!fastJAL) && mem_ctrl.jal)
val mem_misprediction = val mem_misprediction = if (usingBTB) mem_wrong_npc else mem_cfi_taken
if (p(BtbKey).nEntries == 0) mem_cfi_taken
else mem_wrong_npc
take_pc_mem := mem_reg_valid && (mem_misprediction || mem_reg_flush_pipe) take_pc_mem := mem_reg_valid && (mem_misprediction || mem_reg_flush_pipe)
mem_reg_valid := !ctrl_killx mem_reg_valid := !ctrl_killx
@ -652,3 +631,44 @@ class Rocket(val c: RocketConfig)(implicit p: Parameters) extends CoreModule()(p
} }
} }
} }
class RegFile(n: Int, w: Int, zero: Boolean = false) {
private val rf = Mem(n, UInt(width = w))
private def access(addr: UInt) = rf(~addr(log2Up(n)-1,0))
private val reads = collection.mutable.ArrayBuffer[(UInt,UInt)]()
private var canRead = true
def read(addr: UInt) = {
require(canRead)
reads += addr -> Wire(UInt())
reads.last._2 := Mux(Bool(zero) && addr === UInt(0), UInt(0), access(addr))
reads.last._2
}
def write(addr: UInt, data: UInt) = {
canRead = false
when (addr =/= UInt(0)) {
access(addr) := data
for ((raddr, rdata) <- reads)
when (addr === raddr) { rdata := data }
}
}
}
object ImmGen {
def apply(sel: UInt, inst: UInt) = {
val sign = Mux(sel === IMM_Z, SInt(0), inst(31).asSInt)
val b30_20 = Mux(sel === IMM_U, inst(30,20).asSInt, sign)
val b19_12 = Mux(sel =/= IMM_U && sel =/= IMM_UJ, sign, inst(19,12).asSInt)
val b11 = Mux(sel === IMM_U || sel === IMM_Z, SInt(0),
Mux(sel === IMM_UJ, inst(20).asSInt,
Mux(sel === IMM_SB, inst(7).asSInt, sign)))
val b10_5 = Mux(sel === IMM_U || sel === IMM_Z, Bits(0), inst(30,25))
val b4_1 = Mux(sel === IMM_U, Bits(0),
Mux(sel === IMM_S || sel === IMM_SB, inst(11,8),
Mux(sel === IMM_Z, inst(19,16), inst(24,21))))
val b0 = Mux(sel === IMM_S, inst(7),
Mux(sel === IMM_I, inst(20),
Mux(sel === IMM_Z, inst(15), Bits(0))))
Cat(sign, b30_20, b19_12, b11, b10_5, b4_1, b0).asSInt
}
}

View File

@ -4,22 +4,24 @@ package rocket
import Chisel._ import Chisel._
import Chisel.ImplicitConversions._ import Chisel.ImplicitConversions._
import junctions._
import diplomacy._
import config._ import config._
import coreplex.CacheBlockBytes
import diplomacy._
import tile._
import uncore.constants._ import uncore.constants._
import uncore.tilelink2._ import uncore.tilelink2._
import uncore.util._ import uncore.util._
import util._
class ScratchpadSlavePort(implicit p: Parameters) extends LazyModule { class ScratchpadSlavePort(sizeBytes: Int)(implicit p: Parameters) extends LazyModule
val coreDataBytes = p(XLen)/8 with HasCoreParameters {
val node = TLManagerNode(Seq(TLManagerPortParameters( val node = TLManagerNode(Seq(TLManagerPortParameters(
Seq(TLManagerParameters( Seq(TLManagerParameters(
address = List(AddressSet(0x80000000L, BigInt(p(DataScratchpadSize)-1))), address = List(AddressSet(0x80000000L, BigInt(sizeBytes-1))),
regionType = RegionType.UNCACHED, regionType = RegionType.UNCACHED,
executable = true, executable = true,
supportsArithmetic = if (p(UseAtomics)) TransferSizes(1, coreDataBytes) else TransferSizes.none, supportsArithmetic = if (usingAtomics) TransferSizes(1, coreDataBytes) else TransferSizes.none,
supportsLogical = if (p(UseAtomics)) TransferSizes(1, coreDataBytes) else TransferSizes.none, supportsLogical = if (usingAtomics) TransferSizes(1, coreDataBytes) else TransferSizes.none,
supportsPutPartial = TransferSizes(1, coreDataBytes), supportsPutPartial = TransferSizes(1, coreDataBytes),
supportsPutFull = TransferSizes(1, coreDataBytes), supportsPutFull = TransferSizes(1, coreDataBytes),
supportsGet = TransferSizes(1, coreDataBytes), supportsGet = TransferSizes(1, coreDataBytes),
@ -106,10 +108,11 @@ class ScratchpadSlavePort(implicit p: Parameters) extends LazyModule {
trait CanHaveScratchpad extends HasHellaCache with HasICacheFrontend { trait CanHaveScratchpad extends HasHellaCache with HasICacheFrontend {
val module: CanHaveScratchpadModule val module: CanHaveScratchpadModule
val slaveNode = if (p(DataScratchpadSize) == 0) None else Some(TLInputNode()) val sizeBytes = tileParams.dataScratchpadBytes
val scratch = if (p(DataScratchpadSize) == 0) None else Some(LazyModule(new ScratchpadSlavePort()(dcacheParams))) val slaveNode = TLInputNode()
val scratch = if (sizeBytes > 0) Some(LazyModule(new ScratchpadSlavePort(sizeBytes))) else None
(slaveNode zip scratch) foreach { case (node, lm) => lm.node := TLFragmenter(p(XLen)/8, p(CacheBlockBytes))(node) } scratch foreach { lm => lm.node := TLFragmenter(p(XLen)/8, p(CacheBlockBytes))(slaveNode) }
def findScratchpadFromICache: Option[AddressSet] = scratch.map { s => def findScratchpadFromICache: Option[AddressSet] = scratch.map { s =>
val finalNode = frontend.node.edgesOut(0).manager.managers.find(_.nodePath.last == s.node) val finalNode = frontend.node.edgesOut(0).manager.managers.find(_.nodePath.last == s.node)
@ -118,12 +121,12 @@ trait CanHaveScratchpad extends HasHellaCache with HasICacheFrontend {
finalNode.get.address(0) finalNode.get.address(0)
} }
nDCachePorts += 1 // core TODO dcachePorts += () => module.io.dmem ?? nDCachePorts += (sizeBytes > 0).toInt
} }
trait CanHaveScratchpadBundle extends HasHellaCacheBundle with HasICacheFrontendBundle { trait CanHaveScratchpadBundle extends HasHellaCacheBundle with HasICacheFrontendBundle {
val outer: CanHaveScratchpad val outer: CanHaveScratchpad
val slave = outer.slaveNode.map(_.bundleIn) val slave = outer.slaveNode.bundleIn
} }
trait CanHaveScratchpadModule extends HasHellaCacheModule with HasICacheFrontendModule { trait CanHaveScratchpadModule extends HasHellaCacheModule with HasICacheFrontendModule {

View File

@ -4,24 +4,18 @@
package rocket package rocket
import Chisel._ import Chisel._
import util._
import Chisel.ImplicitConversions._ import Chisel.ImplicitConversions._
import scala.math._
import config._ import config._
import diplomacy._ import diplomacy._
import uncore.util._ import coreplex.CacheBlockBytes
import tile.{XLen, CoreModule, CoreBundle}
import uncore.tilelink2._ import uncore.tilelink2._
import util._
case object PAddrBits extends Field[Int] 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]
trait HasTLBParameters extends HasL1CacheParameters {
val entries = p(p(CacheName)).nTLBEntries
val camAddrBits = log2Ceil(entries)
val camTagBits = asIdBits + vpnBits
}
class TLBReq(implicit p: Parameters) extends CoreBundle()(p) { class TLBReq(implicit p: Parameters) extends CoreBundle()(p) {
val vpn = UInt(width = vpnBitsExtended) val vpn = UInt(width = vpnBitsExtended)
val passthrough = Bool() val passthrough = Bool()
@ -39,12 +33,15 @@ class TLBResp(implicit p: Parameters) extends CoreBundle()(p) {
val cacheable = Bool(OUTPUT) val cacheable = Bool(OUTPUT)
} }
class TLB(implicit edge: TLEdgeOut, val p: Parameters) extends Module with HasTLBParameters { class TLB(entries: Int)(implicit edge: TLEdgeOut, p: Parameters) extends CoreModule()(p) {
val io = new Bundle { val io = new Bundle {
val req = Decoupled(new TLBReq).flip val req = Decoupled(new TLBReq).flip
val resp = new TLBResp val resp = new TLBResp
val ptw = new TLBPTWIO val ptw = new TLBPTWIO
} }
val cacheBlockBytes = p(CacheBlockBytes)
val camAddrBits = log2Ceil(entries)
val camTagBits = asIdBits + vpnBits
val valid = Reg(init = UInt(0, entries)) val valid = Reg(init = UInt(0, entries))
val ppns = Reg(Vec(entries, UInt(width = ppnBits))) val ppns = Reg(Vec(entries, UInt(width = ppnBits)))
@ -182,7 +179,7 @@ class TLB(implicit edge: TLEdgeOut, val p: Parameters) extends Module with HasTL
} }
} }
class DecoupledTLB(implicit edge: TLEdgeOut, p: Parameters) extends Module { class DecoupledTLB(entries: Int)(implicit edge: TLEdgeOut, p: Parameters) extends Module {
val io = new Bundle { val io = new Bundle {
val req = Decoupled(new TLBReq).flip val req = Decoupled(new TLBReq).flip
val resp = Decoupled(new TLBResp) val resp = Decoupled(new TLBResp)
@ -191,7 +188,7 @@ class DecoupledTLB(implicit edge: TLEdgeOut, p: Parameters) extends Module {
val req = Reg(new TLBReq) val req = Reg(new TLBReq)
val resp = Reg(new TLBResp) val resp = Reg(new TLBResp)
val tlb = Module(new TLB) val tlb = Module(new TLB(entries))
val s_idle :: s_tlb_req :: s_tlb_resp :: s_done :: Nil = Enum(Bits(), 4) val s_idle :: s_tlb_req :: s_tlb_resp :: s_done :: Nil = Enum(Bits(), 4)
val state = Reg(init = s_idle) val state = Reg(init = s_idle)

View File

@ -7,12 +7,23 @@ import Chisel._
import config._ import config._
import coreplex._ import coreplex._
import diplomacy._ import diplomacy._
import uncore.converters._ import tile._
import uncore.devices._ import uncore.devices._
import uncore.tilelink2._ import uncore.tilelink2._
import util._ import util._
class RocketTile(val c: RocketConfig)(implicit p: Parameters) extends BaseTile()(p) case class RocketTileParams(
core: RocketCoreParams = RocketCoreParams(),
icache: Option[ICacheParams] = Some(ICacheParams()),
dcache: Option[DCacheParams] = Some(DCacheParams()),
rocc: Seq[RoCCParams] = Nil,
btb: Option[BTBParams] = Some(BTBParams()),
dataScratchpadBytes: Int = 0) extends TileParams {
require(icache.isDefined)
require(dcache.isDefined)
}
class RocketTile(val rocketParams: RocketTileParams)(implicit p: Parameters) extends BaseTile(rocketParams)(p)
with CanHaveLegacyRoccs // implies CanHaveSharedFPU with CanHavePTW with HasHellaCache with CanHaveLegacyRoccs // implies CanHaveSharedFPU with CanHavePTW with HasHellaCache
with CanHaveScratchpad { // implies CanHavePTW with HasHellaCache with HasICacheFrontend with CanHaveScratchpad { // implies CanHavePTW with HasHellaCache with HasICacheFrontend
@ -28,7 +39,7 @@ class RocketTileModule(outer: RocketTile) extends BaseTileModule(outer, () => ne
with CanHaveLegacyRoccsModule with CanHaveLegacyRoccsModule
with CanHaveScratchpadModule { with CanHaveScratchpadModule {
val core = Module(p(BuildCore)(outer.c, outer.p)) val core = Module(p(BuildCore)(outer.p))
core.io.interrupts := io.interrupts core.io.interrupts := io.interrupts
core.io.hartid := io.hartid core.io.hartid := io.hartid
outer.frontend.module.io.cpu <> core.io.imem outer.frontend.module.io.cpu <> core.io.imem
@ -44,25 +55,34 @@ class RocketTileModule(outer: RocketTile) extends BaseTileModule(outer, () => ne
core.io.rocc.interrupt := lr.module.io.core.interrupt core.io.rocc.interrupt := lr.module.io.core.interrupt
} }
// TODO eliminate this redundancy
val h = dcachePorts.size
val c = core.dcacheArbPorts
val o = outer.nDCachePorts
require(h == c, s"port list size was $h, core expected $c")
require(h == o, s"port list size was $h, outer counted $o")
// TODO figure out how to move the below into their respective mix-ins // TODO figure out how to move the below into their respective mix-ins
require(dcachePorts.size == core.dcacheArbPorts)
dcacheArb.io.requestor <> dcachePorts dcacheArb.io.requestor <> dcachePorts
ptwOpt foreach { ptw => ptw.io.requestor <> ptwPorts } ptwOpt foreach { ptw => ptw.io.requestor <> ptwPorts }
} }
class AsyncRocketTile(c: RocketConfig)(implicit p: Parameters) extends LazyModule { class AsyncRocketTile(rtp: RocketTileParams)(implicit p: Parameters) extends LazyModule {
val rocket = LazyModule(new RocketTile(c)) val rocket = LazyModule(new RocketTile(rtp))
val masterNodes = rocket.masterNodes.map(_ => TLAsyncOutputNode()) val masterNode = TLAsyncOutputNode()
val slaveNode = rocket.slaveNode.map(_ => TLAsyncInputNode()) val source = LazyModule(new TLAsyncCrossingSource)
source.node :=* rocket.masterNode
masterNode :=* source.node
(rocket.masterNodes zip masterNodes) foreach { case (r,n) => n := TLAsyncCrossingSource()(r) } val slaveNode = TLAsyncInputNode()
(rocket.slaveNode zip slaveNode) foreach { case (r,n) => r := TLAsyncCrossingSink()(n) } val sink = LazyModule(new TLAsyncCrossingSink)
rocket.slaveNode :*= sink.node
sink.node :*= slaveNode
lazy val module = new LazyModuleImp(this) { lazy val module = new LazyModuleImp(this) {
val io = new Bundle { val io = new Bundle {
val master = masterNodes.head.bundleOut // TODO fix after Chisel #366 val master = masterNode.bundleOut
val slave = slaveNode.map(_.bundleIn) val slave = slaveNode.bundleIn
val hartid = UInt(INPUT, p(XLen)) val hartid = UInt(INPUT, p(XLen))
val interrupts = new TileInterrupts()(p).asInput val interrupts = new TileInterrupts()(p).asInput
val resetVector = UInt(INPUT, p(XLen)) val resetVector = UInt(INPUT, p(XLen))
@ -74,19 +94,23 @@ class AsyncRocketTile(c: RocketConfig)(implicit p: Parameters) extends LazyModul
} }
} }
class RationalRocketTile(c: RocketConfig)(implicit p: Parameters) extends LazyModule { class RationalRocketTile(rtp: RocketTileParams)(implicit p: Parameters) extends LazyModule {
val rocket = LazyModule(new RocketTile(c)) val rocket = LazyModule(new RocketTile(rtp))
val masterNodes = rocket.masterNodes.map(_ => TLRationalOutputNode()) val masterNode = TLRationalOutputNode()
val slaveNode = rocket.slaveNode.map(_ => TLRationalInputNode()) val source = LazyModule(new TLRationalCrossingSource)
source.node :=* rocket.masterNode
masterNode :=* source.node
(rocket.masterNodes zip masterNodes) foreach { case (r,n) => n := TLRationalCrossingSource()(r) } val slaveNode = TLRationalInputNode()
(rocket.slaveNode zip slaveNode) foreach { case (r,n) => r := TLRationalCrossingSink()(n) } val sink = LazyModule(new TLRationalCrossingSink)
rocket.slaveNode :*= sink.node
sink.node :*= slaveNode
lazy val module = new LazyModuleImp(this) { lazy val module = new LazyModuleImp(this) {
val io = new Bundle { val io = new Bundle {
val master = masterNodes.head.bundleOut // TODO fix after Chisel #366 val master = masterNode.bundleOut
val slave = slaveNode.map(_.bundleIn) val slave = slaveNode.bundleIn
val hartid = UInt(INPUT, p(XLen)) val hartid = UInt(INPUT, p(XLen))
val interrupts = new TileInterrupts()(p).asInput val interrupts = new TileInterrupts()(p).asInput
val resetVector = UInt(INPUT, p(XLen)) val resetVector = UInt(INPUT, p(XLen))

View File

@ -38,33 +38,21 @@ class BasePlatformConfig extends Config((site, here, up) => {
case RTCPeriod => 100 // gives 10 MHz RTC assuming 1 GHz uncore clock case RTCPeriod => 100 // gives 10 MHz RTC assuming 1 GHz uncore clock
}) })
/** Actual elaboratable target Configs */
class BaseConfig extends Config(new BaseCoreplexConfig ++ new BasePlatformConfig) class BaseConfig extends Config(new BaseCoreplexConfig ++ new BasePlatformConfig)
class DefaultConfig extends Config(new WithBlockingL1 ++ new BaseConfig) class DefaultConfig extends Config(new WithBlockingL1 ++ new WithNBigCores(1) ++ new BaseConfig)
class DefaultL2Config extends Config(new WithL2Cache ++ new BaseConfig) class DefaultL2Config extends Config(new WithL2Cache ++ new WithNBigCores(1) ++ new BaseConfig)
class DefaultBufferlessConfig extends Config( class DefaultBufferlessConfig extends Config(
new WithBufferlessBroadcastHub ++ new BaseConfig) new WithBufferlessBroadcastHub ++ new WithNBigCores(1) ++ new BaseConfig)
class FPGAConfig extends Config ((site, here, up) => {
case NAcquireTransactors => 4
})
class FPGAConfig extends Config(Parameters.empty)
class DefaultFPGAConfig extends Config(new FPGAConfig ++ new BaseConfig) class DefaultFPGAConfig extends Config(new FPGAConfig ++ new BaseConfig)
class DefaultL2FPGAConfig extends Config( class DefaultL2FPGAConfig extends Config(
new WithL2Capacity(64) ++ new WithL2Cache ++ new DefaultFPGAConfig) new WithL2Capacity(64) ++ new WithL2Cache ++ new DefaultFPGAConfig)
class WithNMemoryChannels(n: Int) extends Config((site, here, up) => { class DefaultSmallConfig extends Config(new WithNSmallCores(1) ++ new BaseConfig)
case BankedL2Config => up(BankedL2Config, site).copy(nMemoryChannels = n)
})
class WithExtMemSize(n: Long) extends Config((site, here, up) => {
case ExtMem => up(ExtMem, site).copy(size = n)
})
class WithScratchpads extends Config(new WithNMemoryChannels(0) ++ new WithDataScratchpad(16384))
class DefaultFPGASmallConfig extends Config(new WithSmallCores ++ new DefaultFPGAConfig)
class DefaultSmallConfig extends Config(new WithSmallCores ++ new BaseConfig)
class DefaultRV32Config extends Config(new WithRV32 ++ new DefaultConfig) class DefaultRV32Config extends Config(new WithRV32 ++ new DefaultConfig)
class DualBankConfig extends Config( class DualBankConfig extends Config(
@ -83,12 +71,7 @@ class DualChannelDualBankL2Config extends Config(
new WithNMemoryChannels(2) ++ new WithNBanksPerMemChannel(2) ++ new WithNMemoryChannels(2) ++ new WithNBanksPerMemChannel(2) ++
new WithL2Cache ++ new BaseConfig) new WithL2Cache ++ new BaseConfig)
class RoccExampleConfig extends Config(new WithRoccExample ++ new BaseConfig) class RoccExampleConfig extends Config(new WithRoccExample ++ new DefaultConfig)
class WithEdgeDataBits(dataBits: Int) extends Config((site, here, up) => {
case ExtMem => up(ExtMem, site).copy(beatBytes = dataBits/8)
case ZeroConfig => up(ZeroConfig, site).copy(beatBytes = dataBits/8)
})
class Edge128BitConfig extends Config( class Edge128BitConfig extends Config(
new WithEdgeDataBits(128) ++ new BaseConfig) new WithEdgeDataBits(128) ++ new BaseConfig)
@ -107,12 +90,22 @@ class OctoChannelBenchmarkConfig extends Config(new WithNMemoryChannels(8) ++ ne
class EightChannelConfig extends Config(new WithNMemoryChannels(8) ++ new BaseConfig) class EightChannelConfig extends Config(new WithNMemoryChannels(8) ++ new BaseConfig)
class DualCoreConfig extends Config( class DualCoreConfig extends Config(
new WithNCores(2) ++ new WithL2Cache ++ new BaseConfig) new WithNBigCores(2) ++ new WithL2Cache ++ new BaseConfig)
class HeterogeneousDualCoreConfig extends Config(
new WithNSmallCores(1) ++ new WithNBigCores(1) ++ new WithL2Cache ++ new BaseConfig)
class TinyConfig extends Config( class TinyConfig extends Config(
new WithScratchpads ++ new WithScratchpad ++
new WithSmallCores ++ new WithRV32 ++ new WithRV32 ++
new WithStatelessBridge ++ new BaseConfig) new WithStatelessBridge ++
new WithNSmallCores(1) ++ new BaseConfig)
/* Composable partial function Configs to set individual parameters */
class WithEdgeDataBits(dataBits: Int) extends Config((site, here, up) => {
case ExtMem => up(ExtMem, site).copy(beatBytes = dataBits/8)
case ZeroConfig => up(ZeroConfig, site).copy(beatBytes = dataBits/8)
})
class WithJtagDTM extends Config ((site, here, up) => { class WithJtagDTM extends Config ((site, here, up) => {
case IncludeJtagDTM => true case IncludeJtagDTM => true
@ -134,10 +127,18 @@ class WithNExtTopInterrupts(nExtInts: Int) extends Config((site, here, up) => {
case NExtTopInterrupts => nExtInts case NExtTopInterrupts => nExtInts
}) })
class WithNBreakpoints(hwbp: Int) extends Config ((site, here, up) => {
case NBreakpoints => hwbp
})
class WithRTCPeriod(nCycles: Int) extends Config((site, here, up) => { class WithRTCPeriod(nCycles: Int) extends Config((site, here, up) => {
case RTCPeriod => nCycles case RTCPeriod => nCycles
}) })
class WithNMemoryChannels(n: Int) extends Config((site, here, up) => {
case BankedL2Config => up(BankedL2Config, site).copy(nMemoryChannels = n)
})
class WithExtMemSize(n: Long) extends Config((site, here, up) => {
case ExtMem => up(ExtMem, site).copy(size = n)
})
class WithScratchpad extends Config(new WithNMemoryChannels(0) ++ new WithDataScratchpad(16384))
class DefaultFPGASmallConfig extends Config(new WithNSmallCores(1) ++ new DefaultFPGAConfig)

View File

@ -2,7 +2,9 @@
package rocketchip package rocketchip
import rocket.{XLen, UseVM, UseAtomics, UseCompressed, FPUKey} import tile.XLen
import coreplex.RocketTilesKey
import scala.collection.mutable.LinkedHashSet import scala.collection.mutable.LinkedHashSet
/** A Generator for platforms containing Rocket Coreplexes */ /** A Generator for platforms containing Rocket Coreplexes */
@ -47,9 +49,11 @@ object Generator extends util.GeneratorApp {
override def addTestSuites { override def addTestSuites {
import DefaultTestSuites._ import DefaultTestSuites._
val xlen = params(XLen) val xlen = params(XLen)
val vm = params(UseVM) // TODO: for now only generate tests for the first core in the first coreplex
val coreParams = params(RocketTilesKey).head.core
val vm = coreParams.useVM
val env = if (vm) List("p","v") else List("p") val env = if (vm) List("p","v") else List("p")
params(FPUKey) foreach { case cfg => coreParams.fpu foreach { case cfg =>
if (xlen == 32) { if (xlen == 32) {
TestGeneration.addSuites(env.map(rv32ufNoDiv)) TestGeneration.addSuites(env.map(rv32ufNoDiv))
} else { } else {
@ -62,8 +66,8 @@ object Generator extends util.GeneratorApp {
} }
} }
} }
if (params(UseAtomics)) TestGeneration.addSuites(env.map(if (xlen == 64) rv64ua else rv32ua)) if (coreParams.useAtomics) TestGeneration.addSuites(env.map(if (xlen == 64) rv64ua else rv32ua))
if (params(UseCompressed)) TestGeneration.addSuites(env.map(if (xlen == 64) rv64uc else rv32uc)) if (coreParams.useCompressed) TestGeneration.addSuites(env.map(if (xlen == 64) rv64uc else rv32uc))
val (rvi, rvu) = val (rvi, rvu) =
if (xlen == 64) ((if (vm) rv64i else rv64pi), rv64u) if (xlen == 64) ((if (vm) rv64i else rv64pi), rv64u)
else ((if (vm) rv32i else rv32pi), rv32u) else ((if (vm) rv32i else rv32pi), rv32u)

View File

@ -4,20 +4,16 @@ package rocketchip
import Chisel._ import Chisel._
import config._ import config._
import junctions._ import coreplex._
import junctions.NastiConstants._
import diplomacy._ import diplomacy._
import uncore.tilelink._ import tile.XLen
import uncore.tilelink2._ import uncore.tilelink2._
import uncore.axi4._ import uncore.axi4._
import uncore.converters._ import uncore.converters._
import uncore.devices._ import uncore.devices._
import uncore.agents._
import uncore.util._ import uncore.util._
import util._ import util._
import rocket.XLen
import scala.math.max import scala.math.max
import coreplex._
/** Specifies the size of external memory */ /** Specifies the size of external memory */
case class MasterConfig(base: Long, size: Long, beatBytes: Int, idBits: Int) case class MasterConfig(base: Long, size: Long, beatBytes: Int, idBits: Int)

View File

@ -6,7 +6,7 @@ import config._
import junctions._ import junctions._
import diplomacy._ import diplomacy._
import uncore.devices._ import uncore.devices._
import rocket._ import tile.XLen
import coreplex._ import coreplex._
import uncore.tilelink2._ import uncore.tilelink2._
import util._ import util._
@ -59,14 +59,15 @@ object GenerateConfigString {
res append plic.globalConfigString res append plic.globalConfigString
res append clint.globalConfigString res append clint.globalConfigString
res append "core {\n" res append "core {\n"
for (i <- 0 until c.nTiles) { // TODO heterogeneous tiles c.tilesParams.zipWithIndex.map { case(t, i) =>
val isa = { val isa = {
val m = if (p(MulDivKey).nonEmpty) "m" else "" val m = if (t.core.mulDiv.nonEmpty) "m" else ""
val a = if (p(UseAtomics)) "a" else "" val a = if (t.core.useAtomics) "a" else ""
val f = if (p(FPUKey).nonEmpty) "f" else "" val f = if (t.core.fpu.nonEmpty) "f" else ""
val d = if (p(FPUKey).nonEmpty && p(XLen) > 32) "d" else "" val d = if (t.core.fpu.nonEmpty && p(XLen) > 32) "d" else ""
val s = if (c.hasSupervisor) "s" else "" val c = if (t.core.useCompressed) "c" else ""
s"rv${p(XLen)}i$m$a$f$d$s" val s = if (t.core.useVM) "s" else ""
s"rv${p(XLen)}i$m$a$f$d$c$s"
} }
res append s" $i {\n" res append s" $i {\n"
res append " 0 {\n" res append " 0 {\n"

View File

@ -0,0 +1,81 @@
// See LICENSE.SiFive for license details.
package tile
import Chisel._
import config._
import diplomacy._
import rocket._
import uncore.tilelink2._
import util._
case object SharedMemoryTLEdge extends Field[TLEdgeOut]
case object TileKey extends Field[TileParams]
trait TileParams {
val core: CoreParams
val icache: Option[ICacheParams]
val dcache: Option[DCacheParams]
val rocc: Seq[RoCCParams]
val btb: Option[BTBParams]
val dataScratchpadBytes: Int
}
trait HasTileParameters {
implicit val p: Parameters
val tileParams: TileParams = p(TileKey)
val usingVM = tileParams.core.useVM
val usingUser = tileParams.core.useUser || usingVM
val usingDebug = tileParams.core.useDebug
val usingRoCC = !tileParams.rocc.isEmpty
val usingBTB = tileParams.btb.isDefined && tileParams.btb.get.nEntries > 0
val usingPTW = usingVM
val usingDataScratchpad = tileParams.dcache.isDefined && tileParams.dataScratchpadBytes > 0
def dcacheArbPorts = 1 + usingVM.toInt + usingDataScratchpad.toInt + tileParams.rocc.size
}
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 TileLink master port to connect caches and accelerators to the coreplex
trait HasTileLinkMasterPort extends HasTileParameters {
implicit val p: Parameters
val module: HasTileLinkMasterPortModule
val masterNode = TLOutputNode()
}
trait HasTileLinkMasterPortBundle {
val outer: HasTileLinkMasterPort
val master = outer.masterNode.bundleOut
}
trait HasTileLinkMasterPortModule {
val outer: HasTileLinkMasterPort
val io: HasTileLinkMasterPortBundle
}
abstract class BaseTile(tileParams: TileParams)(implicit p: Parameters) extends BareTile
with HasTileLinkMasterPort {
override lazy val module = new BaseTileModule(this, () => new BaseTileBundle(this))
}
class BaseTileBundle[+L <: BaseTile](_outer: L) extends BareTileBundle(_outer)
with HasTileLinkMasterPortBundle {
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 HasTileLinkMasterPortModule

View File

@ -0,0 +1,88 @@
// See LICENSE.SiFive for license details.
package tile
import Chisel._
import config._
import rocket._
import util._
case object BuildCore extends Field[Parameters => CoreModule with HasCoreIO]
case object XLen extends Field[Int]
// These parameters can be varied per-core
trait CoreParams {
val useVM: Boolean
val useUser: Boolean
val useDebug: Boolean
val useAtomics: Boolean
val useCompressed: Boolean
val mulDiv: Option[MulDivParams]
val fpu: Option[FPUParams]
val fetchWidth: Int
val decodeWidth: Int
val retireWidth: Int
val instBits: Int
}
trait HasCoreParameters extends HasTileParameters {
val coreParams: CoreParams = tileParams.core
val xLen = p(XLen)
val fLen = xLen // TODO relax this
require(xLen == 32 || xLen == 64)
val usingMulDiv = coreParams.mulDiv.nonEmpty
val usingFPU = coreParams.fpu.nonEmpty
val usingAtomics = coreParams.useAtomics
val usingCompressed = coreParams.useCompressed
val retireWidth = coreParams.retireWidth
val fetchWidth = coreParams.fetchWidth
val decodeWidth = coreParams.decodeWidth
val coreInstBits = coreParams.instBits
val coreInstBytes = coreInstBits/8
val coreDataBits = xLen
val coreDataBytes = coreDataBits/8
val coreDCacheReqTagBits = 6
val dcacheReqTagBits = coreDCacheReqTagBits + log2Ceil(dcacheArbPorts)
def pgIdxBits = 12
def pgLevelBits = 10 - log2Ceil(xLen / 32)
def vaddrBits = pgIdxBits + pgLevels * pgLevelBits
val paddrBits = 32//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 maxPAddrBits = xLen match { case 32 => 34; case 64 => 50 }
require(paddrBits <= maxPAddrBits)
// Print out log of committed instructions and their writeback values.
// Requires post-processing due to out-of-order writebacks.
val enableCommitLog = false
}
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)
val dmem = new HellaCacheIO()(p)
val ptw = new DatapathPTWIO().flip
val fpu = new FPUCoreIO().flip
val rocc = new RoCCCoreIO().flip
}
}

View File

@ -1,17 +1,18 @@
// See LICENSE.Berkeley for license details. // See LICENSE.Berkeley for license details.
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package rocket package tile
import Chisel._ import Chisel._
import Instructions._
import util._
import Chisel.ImplicitConversions._ import Chisel.ImplicitConversions._
import FPConstants._ import FPConstants._
import rocket.DecodeLogic
import rocket.Instructions._
import uncore.constants.MemoryOpConstants._ import uncore.constants.MemoryOpConstants._
import config._ import config._
import util._
case class FPUConfig( case class FPUParams(
divSqrt: Boolean = true, divSqrt: Boolean = true,
sfmaLatency: Int = 3, sfmaLatency: Int = 3,
dfmaLatency: Int = 4 dfmaLatency: Int = 4
@ -496,7 +497,7 @@ class FPUFMAPipe(val latency: Int, expWidth: Int, sigWidth: Int)(implicit p: Par
io.out := Pipe(valid, res, latency-1) io.out := Pipe(valid, res, latency-1)
} }
class FPU(cfg: FPUConfig)(implicit p: Parameters) extends FPUModule()(p) { class FPU(cfg: FPUParams)(implicit p: Parameters) extends FPUModule()(p) {
val io = new FPUIO val io = new FPUIO
val ex_reg_valid = Reg(next=io.valid, init=Bool(false)) val ex_reg_valid = Reg(next=io.valid, init=Bool(false))
@ -742,12 +743,10 @@ class FPU(cfg: FPUConfig)(implicit p: Parameters) extends FPUModule()(p) {
} }
/** Mix-ins for constructing tiles that may have an FPU external to the core pipeline */ /** Mix-ins for constructing tiles that may have an FPU external to the core pipeline */
trait CanHaveSharedFPU { trait CanHaveSharedFPU extends HasTileParameters
implicit val p: Parameters
}
trait CanHaveSharedFPUModule { trait CanHaveSharedFPUModule {
val outer: CanHaveSharedFPU val outer: CanHaveSharedFPU
val fpuOpt = outer.p(FPUKey).map(cfg => Module(new FPU(cfg)(outer.p))) val fpuOpt = outer.tileParams.core.fpu.map(params => Module(new FPU(params)(outer.p)))
// TODO fpArb could go here instead of inside LegacyRoccComplex // TODO fpArb could go here instead of inside LegacyRoccComplex
} }

View File

@ -0,0 +1,15 @@
// See LICENSE.SiFive for license details.
package tile
import Chisel._
import config.Parameters
import util._
class TileInterrupts(implicit p: Parameters) extends CoreBundle()(p) {
val debug = Bool()
val mtip = Bool()
val msip = Bool()
val meip = Bool()
val seip = usingVM.option(Bool())
}

View File

@ -0,0 +1,52 @@
// See LICENSE.SiFive for license details.
package tile
import Chisel._
import config.{Parameters, Field}
import coreplex.CacheBlockBytes
import rocket.PAddrBits
import uncore.tilelink2.ClientMetadata
import uncore.util.{Code, IdentityCode}
import util.ParameterizedBundle
trait L1CacheParams {
def nSets: Int
def nWays: Int
def rowBits: Int
def nTLBEntries: Int
def splitMetadata: Boolean
def ecc: Option[Code]
}
trait HasL1CacheParameters {
implicit val p: Parameters
val cacheParams: L1CacheParams
def cacheBlockBytes = p(CacheBlockBytes)
def lgCacheBlockBytes = log2Up(cacheBlockBytes)
def nSets = cacheParams.nSets
def blockOffBits = lgCacheBlockBytes
def idxBits = log2Up(cacheParams.nSets)
def untagBits = blockOffBits + idxBits
def tagBits = p(PAddrBits) - untagBits
def nWays = cacheParams.nWays
def wayBits = log2Up(nWays)
def isDM = nWays == 1
def rowBits = cacheParams.rowBits
def rowBytes = rowBits/8
def rowOffBits = log2Up(rowBytes)
def code = cacheParams.ecc.getOrElse(new IdentityCode)
def nTLBEntries = cacheParams.nTLBEntries
def hasSplitMetadata = cacheParams.splitMetadata
def cacheDataBits = p(SharedMemoryTLEdge).bundle.dataBits
def cacheDataBeats = (cacheBlockBytes * 8) / cacheDataBits
def refillCycles = cacheDataBeats
}
abstract class L1CacheModule(implicit val p: Parameters) extends Module
with HasL1CacheParameters
abstract class L1CacheBundle(implicit val p: Parameters) extends ParameterizedBundle()(p)
with HasL1CacheParameters

View File

@ -1,13 +1,14 @@
// See LICENSE.Berkeley for license details. // See LICENSE.Berkeley for license details.
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
package rocket package tile
import Chisel._ import Chisel._
import Chisel.ImplicitConversions._ import Chisel.ImplicitConversions._
import config._ import config._
import coreplex._ import coreplex._
import diplomacy._ import diplomacy._
import rocket._
import uncore.constants._ import uncore.constants._
import uncore.agents._ import uncore.agents._
import uncore.coherence._ import uncore.coherence._
@ -20,9 +21,9 @@ 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]] case object BuildRoCC extends Field[Seq[RoCCParams]]
trait CanHaveLegacyRoccs extends CanHaveSharedFPU with CanHavePTW with TileNetwork { trait CanHaveLegacyRoccs extends CanHaveSharedFPU with CanHavePTW with HasTileLinkMasterPort {
val module: CanHaveLegacyRoccsModule val module: CanHaveLegacyRoccsModule
val legacyRocc = if (p(BuildRoCC).isEmpty) None val legacyRocc = if (p(BuildRoCC).isEmpty) None
else Some(LazyModule(new LegacyRoccComplex()(p.alter { (site, here, up) => { else Some(LazyModule(new LegacyRoccComplex()(p.alter { (site, here, up) => {
@ -38,7 +39,7 @@ trait CanHaveLegacyRoccs extends CanHaveSharedFPU with CanHavePTW with TileNetwo
nCachingClients = 1, nCachingClients = 1,
nCachelessClients = 1, nCachelessClients = 1,
maxClientXacts = List( maxClientXacts = List(
site(DCacheKey).nMSHRs + 1 /* IOMSHR */, tileParams.dcache.get.nMSHRs + 1 /* IOMSHR */,
if (site(BuildRoCC).isEmpty) 1 else site(RoccMaxTaggedMemXacts)).max, if (site(BuildRoCC).isEmpty) 1 else site(RoccMaxTaggedMemXacts)).max,
maxClientsPerPort = if (site(BuildRoCC).isEmpty) 1 else 2, maxClientsPerPort = if (site(BuildRoCC).isEmpty) 1 else 2,
maxManagerXacts = 8, maxManagerXacts = 8,
@ -46,15 +47,16 @@ trait CanHaveLegacyRoccs extends CanHaveSharedFPU with CanHavePTW with TileNetwo
dataBits = site(CacheBlockBytes)*8) dataBits = site(CacheBlockBytes)*8)
}}))) }})))
// TODO for now, all legacy rocc mem ports mapped to one external node
legacyRocc foreach { lr => legacyRocc foreach { lr =>
lr.masterNodes.foreach { l1backend.node := _ } masterNode := lr.masterNode
nPTWPorts += lr.nPTWPorts nPTWPorts += lr.nPTWPorts
nDCachePorts += lr.nRocc nDCachePorts += lr.nRocc
} }
} }
trait CanHaveLegacyRoccsModule extends CanHaveSharedFPUModule with CanHavePTWModule with TileNetworkModule { trait CanHaveLegacyRoccsModule extends CanHaveSharedFPUModule
with CanHavePTWModule
with HasTileLinkMasterPortModule {
val outer: CanHaveLegacyRoccs val outer: CanHaveLegacyRoccs
fpuOpt foreach { fpu => fpuOpt foreach { fpu =>
@ -84,13 +86,13 @@ class LegacyRoccComplex(implicit p: Parameters) extends LazyModule {
val nPTWPorts = buildRocc.map(_.nPTWPorts).sum val nPTWPorts = buildRocc.map(_.nPTWPorts).sum
val roccOpcodes = buildRocc.map(_.opcodes) val roccOpcodes = buildRocc.map(_.opcodes)
val masterNode = TLOutputNode()
val legacies = List.fill(nMemChannels) { LazyModule(new TLLegacy()(p.alterPartial({ case PAddrBits => 32 }))) } val legacies = List.fill(nMemChannels) { LazyModule(new TLLegacy()(p.alterPartial({ case PAddrBits => 32 }))) }
val masterNodes = legacies.map(_ => TLOutputNode()) legacies.foreach { leg => masterNode := TLHintHandler()(leg.node) }
legacies.zip(masterNodes).foreach { case(l,m) => m := TLHintHandler()(l.node) }
lazy val module = new LazyModuleImp(this) with HasCoreParameters { lazy val module = new LazyModuleImp(this) with HasCoreParameters {
val io = new Bundle { val io = new Bundle {
val tl = masterNodes.map(_.bundleOut) val tl = masterNode.bundleOut
val dcache = Vec(nRocc, new HellaCacheIO) val dcache = Vec(nRocc, new HellaCacheIO)
val fpu = new Bundle { val fpu = new Bundle {
val cp_req = Decoupled(new FPInput()) val cp_req = Decoupled(new FPInput())
@ -117,7 +119,7 @@ class LegacyRoccComplex(implicit p: Parameters) extends LazyModule {
case RoccNMemChannels => accelParams.nMemChannels case RoccNMemChannels => accelParams.nMemChannels
case RoccNPTWPorts => accelParams.nPTWPorts case RoccNPTWPorts => accelParams.nPTWPorts
})) }))
val dcIF = Module(new SimpleHellaCacheIF()(p.alterPartial({ case CacheName => CacheName("L1D") }))) val dcIF = Module(new SimpleHellaCacheIF)
rocc.io.cmd <> cmdRouter.io.out(i) rocc.io.cmd <> cmdRouter.io.out(i)
rocc.io.exception := io.core.exception rocc.io.exception := io.core.exception
dcIF.io.requestor <> rocc.io.mem dcIF.io.requestor <> rocc.io.mem
@ -151,7 +153,7 @@ class LegacyRoccComplex(implicit p: Parameters) extends LazyModule {
} }
} }
case class RoccParameters( case class RoCCParams(
opcodes: OpcodeSet, opcodes: OpcodeSet,
generator: Parameters => RoCC, generator: Parameters => RoCC,
nMemChannels: Int = 0, nMemChannels: Int = 0,

View File

@ -0,0 +1,3 @@
// See LICENSE.SiFive for license details.
package object tile extends rocket.constants.ScalarOpConstants

View File

@ -1,980 +0,0 @@
// See LICENSE.Berkeley for license details.
// See LICENSE.SiFive for license details.
package uncore.agents
import Chisel._
import scala.reflect.ClassTag
import rocket.PAddrBits
import uncore.coherence._
import uncore.tilelink._
import uncore.constants._
import uncore.util._
import util._
import config.{Parameters, Field}
case object CacheId extends Field[Int]
case object L2DirectoryRepresentation extends Field[DirectoryRepresentation]
trait HasOuterCacheParameters extends HasCacheParameters with HasCoherenceAgentParameters {
val cacheId = p(CacheId)
val idxLSB = cacheIdBits
val idxMSB = idxLSB + idxBits - 1
val tagLSB = idxLSB + idxBits
val tagMSB = tagLSB + tagBits - 1
def inSameSet(block_a: HasCacheBlockAddress, block_b: HasCacheBlockAddress): Bool =
inSameSet(block_a, block_b.addr_block)
def inSameSet(block: HasCacheBlockAddress, addr: UInt): Bool =
inSet(block, addr(idxMSB, idxLSB))
def inSet(block: HasCacheBlockAddress, idx: UInt): Bool =
block.addr_block(idxMSB,idxLSB) === idx
def haveSameTag(block: HasCacheBlockAddress, addr: UInt): Bool =
hasTag(block, addr(tagMSB, tagLSB))
def hasTag(block: HasCacheBlockAddress, tag: UInt): Bool =
block.addr_block(tagMSB, tagLSB) === tag
def isSameBlock(block: HasCacheBlockAddress, tag: UInt, idx: UInt) =
hasTag(block, tag) && inSet(block, idx)
//val blockAddrBits = p(TLBlockAddrBits)
val refillCyclesPerBeat = outerDataBits/rowBits
val refillCycles = refillCyclesPerBeat*outerDataBeats
val internalDataBeats = p(CacheBlockBytes)*8/rowBits
require(refillCyclesPerBeat == 1)
val amoAluOperandBits = p(AmoAluOperandBits)
require(amoAluOperandBits <= innerDataBits)
require(rowBits == innerDataBits) // TODO: relax this by improving s_data_* states
val nSecondaryMisses = p(NSecondaryMisses)
val isLastLevelCache = true
val alwaysWriteFullBeat = !p(ECCCode).isEmpty
}
abstract class L2HellaCacheModule(implicit val p: Parameters) extends Module
with HasOuterCacheParameters {
def doInternalOutputArbitration[T <: Data : ClassTag](
out: DecoupledIO[T],
ins: Seq[DecoupledIO[T]],
block_transfer: T => Bool = (t: T) => Bool(false)) {
val arb = Module(new RRArbiter(out.bits, ins.size))
out.valid := arb.io.out.valid && !block_transfer(arb.io.out.bits)
out.bits := arb.io.out.bits
arb.io.out.ready := out.ready && !block_transfer(arb.io.out.bits)
arb.io.in <> ins
}
def doInternalInputRouting[T <: Bundle with HasL2Id](in: ValidIO[T], outs: Seq[ValidIO[T]]) {
outs.map(_.bits := in.bits)
outs.zipWithIndex.map { case (o,i) => o.valid := in.valid && in.bits.id === UInt(i) }
}
}
abstract class L2HellaCacheBundle(implicit val p: Parameters) extends ParameterizedBundle()(p)
with HasOuterCacheParameters
trait HasL2Id extends HasCoherenceAgentParameters {
val id = UInt(width = log2Up(nTransactors + 1))
}
trait HasL2InternalRequestState extends HasOuterCacheParameters {
val tag_match = Bool()
val meta = new L2Metadata
val way_en = Bits(width = nWays)
}
trait HasL2BeatAddr extends HasOuterCacheParameters {
val addr_beat = UInt(width = log2Up(refillCycles))
}
trait HasL2Data extends HasOuterCacheParameters
with HasL2BeatAddr {
val data = UInt(width = rowBits)
def hasData(dummy: Int = 0) = Bool(true)
def hasMultibeatData(dummy: Int = 0) = Bool(refillCycles > 1)
}
class L2Metadata(implicit p: Parameters) extends Metadata()(p) with HasOuterCacheParameters {
val coh = new HierarchicalMetadata
}
object L2Metadata {
def apply(tag: Bits, coh: HierarchicalMetadata)
(implicit p: Parameters): L2Metadata = {
val meta = Wire(new L2Metadata)
meta.tag := tag
meta.coh := coh
meta
}
def apply(
tag: Bits,
inner: ManagerMetadata,
outer: ClientMetadata)(implicit p: Parameters): L2Metadata = {
val coh = Wire(new HierarchicalMetadata)
coh.inner := inner
coh.outer := outer
apply(tag, coh)
}
}
class L2MetaReadReq(implicit p: Parameters) extends MetaReadReq()(p) with HasL2Id {
val tag = Bits(width = tagBits)
}
class L2MetaWriteReq(implicit p: Parameters) extends MetaWriteReq[L2Metadata](new L2Metadata)(p)
with HasL2Id {
override def cloneType = new L2MetaWriteReq().asInstanceOf[this.type]
}
class L2MetaResp(implicit p: Parameters) extends L2HellaCacheBundle()(p)
with HasL2Id
with HasL2InternalRequestState
trait HasL2MetaReadIO extends HasOuterCacheParameters {
val read = Decoupled(new L2MetaReadReq)
val resp = Valid(new L2MetaResp).flip
}
trait HasL2MetaWriteIO extends HasOuterCacheParameters {
val write = Decoupled(new L2MetaWriteReq)
}
class L2MetaRWIO(implicit p: Parameters) extends L2HellaCacheBundle()(p)
with HasL2MetaReadIO
with HasL2MetaWriteIO
class L2MetaReadOnlyIO(implicit p: Parameters) extends L2HellaCacheBundle()(p)
with HasL2MetaReadIO
trait HasL2MetaRWIO extends HasOuterCacheParameters {
val meta = new L2MetaRWIO
}
class L2MetadataArray(implicit p: Parameters) extends L2HellaCacheModule()(p) {
val io = new L2MetaRWIO().flip
def onReset = L2Metadata(UInt(0), HierarchicalMetadata.onReset)
val meta = Module(new MetadataArray(onReset _))
meta.io.read <> io.read
meta.io.write <> io.write
val way_en_1h = UInt((BigInt(1) << nWays) - 1)
val s1_way_en_1h = RegEnable(way_en_1h, io.read.valid)
meta.io.read.bits.way_en := way_en_1h
val s1_tag = RegEnable(io.read.bits.tag, io.read.valid)
val s1_id = RegEnable(io.read.bits.id, io.read.valid)
def wayMap[T <: Data](f: Int => T) = Vec((0 until nWays).map(f))
val s1_clk_en = Reg(next = io.read.fire())
val s1_tag_eq_way = wayMap((w: Int) => meta.io.resp(w).tag === s1_tag)
val s1_tag_match_way = wayMap((w: Int) => s1_tag_eq_way(w) && meta.io.resp(w).coh.outer.isValid() && s1_way_en_1h(w).toBool).asUInt
val s1_idx = RegEnable(io.read.bits.idx, io.read.valid) // deal with stalls?
val s2_tag_match_way = RegEnable(s1_tag_match_way, s1_clk_en)
val s2_tag_match = s2_tag_match_way.orR
val s2_hit_coh = Mux1H(s2_tag_match_way, wayMap((w: Int) => RegEnable(meta.io.resp(w).coh, s1_clk_en)))
val replacer = p(L2Replacer)()
val s1_hit_way = Wire(Bits())
s1_hit_way := Bits(0)
(0 until nWays).foreach(i => when (s1_tag_match_way(i)) { s1_hit_way := Bits(i) })
replacer.access(io.read.bits.idx)
replacer.update(s1_clk_en, s1_tag_match_way.orR, s1_idx, s1_hit_way)
val s1_replaced_way_en = UIntToOH(replacer.way)
val s2_replaced_way_en = UIntToOH(RegEnable(replacer.way, s1_clk_en))
val s2_repl_meta = Mux1H(s2_replaced_way_en, wayMap((w: Int) =>
RegEnable(meta.io.resp(w), s1_clk_en && s1_replaced_way_en(w))).toSeq)
io.resp.valid := Reg(next = s1_clk_en)
io.resp.bits.id := RegEnable(s1_id, s1_clk_en)
io.resp.bits.tag_match := s2_tag_match
io.resp.bits.meta := Mux(s2_tag_match,
L2Metadata(s2_repl_meta.tag, s2_hit_coh),
s2_repl_meta)
io.resp.bits.way_en := Mux(s2_tag_match, s2_tag_match_way, s2_replaced_way_en)
}
class L2DataReadReq(implicit p: Parameters) extends L2HellaCacheBundle()(p)
with HasL2BeatAddr
with HasL2Id {
val addr_idx = UInt(width = idxBits)
val way_en = Bits(width = nWays)
}
object L2DataReadReq {
def apply(
id: UInt,
way_en: UInt,
addr_idx: UInt,
addr_beat: UInt)(implicit p: Parameters) = {
val req = Wire(new L2DataReadReq)
req.id := id
req.way_en := way_en
req.addr_idx := addr_idx
req.addr_beat := addr_beat
req
}
}
class L2DataWriteReq(implicit p: Parameters) extends L2DataReadReq()(p)
with HasL2Data {
val wmask = Bits(width = rowBits/8)
}
object L2DataWriteReq {
def apply(
id: UInt,
way_en: UInt,
addr_idx: UInt,
addr_beat: UInt,
wmask: UInt,
data: UInt)(implicit p: Parameters) = {
val req = Wire(new L2DataWriteReq)
req.id := id
req.way_en := way_en
req.addr_idx := addr_idx
req.addr_beat := addr_beat
req.wmask := wmask
req.data := data
req
}
}
class L2DataResp(implicit p: Parameters) extends L2HellaCacheBundle()(p)
with HasL2Id
with HasL2Data
trait HasL2DataReadIO extends HasOuterCacheParameters {
val read = Decoupled(new L2DataReadReq)
val resp = Valid(new L2DataResp).flip
}
trait HasL2DataWriteIO extends HasOuterCacheParameters {
val write = Decoupled(new L2DataWriteReq)
}
class L2DataRWIO(implicit p: Parameters) extends L2HellaCacheBundle()(p)
with HasL2DataReadIO
with HasL2DataWriteIO
trait HasL2DataRWIO extends HasOuterCacheParameters {
val data = new L2DataRWIO
}
class L2DataArray(delay: Int)(implicit p: Parameters) extends L2HellaCacheModule()(p) {
val io = new L2DataRWIO().flip
val array = SeqMem(nWays*nSets*refillCycles, Vec(rowBits/8, Bits(width=8)))
val ren = !io.write.valid && io.read.valid
val raddr = Cat(OHToUInt(io.read.bits.way_en), io.read.bits.addr_idx, io.read.bits.addr_beat)
val waddr = Cat(OHToUInt(io.write.bits.way_en), io.write.bits.addr_idx, io.write.bits.addr_beat)
val wdata = Vec.tabulate(rowBits/8)(i => io.write.bits.data(8*(i+1)-1,8*i))
val wmask = io.write.bits.wmask.toBools
when (io.write.valid) { array.write(waddr, wdata, wmask) }
val r_req = Pipe(io.read.fire(), io.read.bits)
io.resp := Pipe(r_req.valid, r_req.bits, delay)
io.resp.bits.data := Pipe(r_req.valid, array.read(raddr, ren).asUInt, delay).bits
io.read.ready := !io.write.valid
io.write.ready := Bool(true)
}
class L2HellaCacheBank(implicit p: Parameters) extends HierarchicalCoherenceAgent()(p)
with HasOuterCacheParameters {
require(isPow2(nSets))
require(isPow2(nWays))
val meta = Module(new L2MetadataArray) // TODO: add delay knob
val data = Module(new L2DataArray(1))
val tshrfile = Module(new TSHRFile)
io.inner <> tshrfile.io.inner
io.outer <> tshrfile.io.outer
tshrfile.io.incoherent <> io.incoherent
meta.io <> tshrfile.io.meta
data.io <> tshrfile.io.data
disconnectOuterProbeAndFinish()
}
class TSHRFileIO(implicit p: Parameters) extends HierarchicalTLIO()(p)
with HasL2MetaRWIO
with HasL2DataRWIO
class TSHRFile(implicit p: Parameters) extends L2HellaCacheModule()(p)
with HasCoherenceAgentWiringHelpers {
val io = new TSHRFileIO
// Create TSHRs for outstanding transactions
val irelTrackerList =
(0 until nReleaseTransactors).map(id =>
Module(new CacheVoluntaryReleaseTracker(id)))
val iacqTrackerList =
(nReleaseTransactors until nTransactors).map(id =>
Module(new CacheAcquireTracker(id)))
val trackerList = irelTrackerList ++ iacqTrackerList
// Don't allow a writeback request to go through if we are taking
// a voluntary release for the same block.
// The writeback can go forward once the voluntary release is handled
def writebackConflictsWithVolRelease(wb: L2WritebackReq): Bool =
irelTrackerList
.map(tracker =>
!tracker.io.alloc.idle &&
isSameBlock(tracker.io.alloc, wb.tag, wb.idx))
.reduce(_ || _) ||
(io.inner.release.valid &&
isSameBlock(io.inner.release.bits, wb.tag, wb.idx))
// WritebackUnit evicts data from L2, including invalidating L1s
val wb = Module(new L2WritebackUnit(nTransactors))
val trackerAndWbIOs = trackerList.map(_.io) :+ wb.io
doInternalOutputArbitration(wb.io.wb.req, trackerList.map(_.io.wb.req),
block_transfer = writebackConflictsWithVolRelease _)
doInternalInputRouting(wb.io.wb.resp, trackerList.map(_.io.wb.resp))
// Propagate incoherence flags
(trackerList.map(_.io.incoherent) :+ wb.io.incoherent) foreach { _ := io.incoherent }
// Handle acquire transaction initiation
val irel_vs_iacq_conflict =
io.inner.acquire.valid &&
io.inner.release.valid &&
inSameSet(io.inner.acquire.bits, io.inner.release.bits)
doInputRoutingWithAllocation(
in = io.inner.acquire,
outs = trackerList.map(_.io.inner.acquire),
allocs = trackerList.map(_.io.alloc.iacq),
allocOverride = Some(!irel_vs_iacq_conflict))
assert(PopCount(trackerList.map(_.io.alloc.iacq.should)) <= UInt(1),
"At most a single tracker should now be allocated for any given Acquire")
// Wire releases from clients
doInputRoutingWithAllocation(
in = io.inner.release,
outs = trackerAndWbIOs.map(_.inner.release),
allocs = trackerAndWbIOs.map(_.alloc.irel))
assert(PopCount(trackerAndWbIOs.map(_.alloc.irel.should)) <= UInt(1),
"At most a single tracker should now be allocated for any given Release")
// Wire probe requests and grant reply to clients, finish acks from clients
doOutputArbitration(io.inner.probe, trackerList.map(_.io.inner.probe) :+ wb.io.inner.probe)
doOutputArbitration(io.inner.grant, trackerList.map(_.io.inner.grant) :+ wb.io.inner.grant)
doInputRouting(io.inner.finish, trackerList.map(_.io.inner.finish))
// Create an arbiter for the one memory port
val outerList = trackerList.map(_.io.outer) :+ wb.io.outer
val outer_arb = Module(new ClientTileLinkIOArbiter(outerList.size)
(p.alterPartial({ case TLId => p(OuterTLId)})))
outer_arb.io.in <> outerList
io.outer <> outer_arb.io.out
// Wire local memory arrays
doInternalOutputArbitration(io.meta.read, trackerList.map(_.io.meta.read) :+ wb.io.meta.read)
doInternalOutputArbitration(io.meta.write, trackerList.map(_.io.meta.write))
doInternalOutputArbitration(io.data.read, trackerList.map(_.io.data.read) :+ wb.io.data.read)
doInternalOutputArbitration(io.data.write, trackerList.map(_.io.data.write))
doInternalInputRouting(io.meta.resp, trackerList.map(_.io.meta.resp) :+ wb.io.meta.resp)
doInternalInputRouting(io.data.resp, trackerList.map(_.io.data.resp) :+ wb.io.data.resp)
}
class L2XactTrackerIO(implicit p: Parameters) extends HierarchicalXactTrackerIO()(p)
with HasL2DataRWIO
with HasL2MetaRWIO
with HasL2WritebackIO
trait HasRowBeatCounters extends HasOuterCacheParameters with HasPendingBitHelpers {
def mergeData(dataBits: Int)(beat: UInt, incoming: UInt): Unit
def connectDataBeatCounter[S <: L2HellaCacheBundle](inc: Bool, data: S, beat: UInt, full_block: Bool) = {
if(data.refillCycles > 1) {
val (multi_cnt, multi_done) = Counter(full_block && inc, data.refillCycles)
(Mux(!full_block, beat, multi_cnt), Mux(!full_block, inc, multi_done))
} else { (UInt(0), inc) }
}
def connectInternalDataBeatCounter[T <: L2HellaCacheBundle with HasL2BeatAddr](
in: DecoupledIO[T],
beat: UInt = UInt(0),
full_block: Bool = Bool(true)): (UInt, Bool) = {
connectDataBeatCounter(in.fire(), in.bits, beat, full_block)
}
def connectInternalDataBeatCounter[T <: L2HellaCacheBundle with HasL2Data](
in: ValidIO[T],
full_block: Bool): Bool = {
connectDataBeatCounter(in.valid, in.bits, UInt(0), full_block)._2
}
def addPendingBitInternal[T <: L2HellaCacheBundle with HasL2BeatAddr](in: DecoupledIO[T]) =
Fill(in.bits.refillCycles, in.fire()) & UIntToOH(in.bits.addr_beat)
def addPendingBitInternal[T <: L2HellaCacheBundle with HasL2BeatAddr](in: ValidIO[T]) =
Fill(in.bits.refillCycles, in.valid) & UIntToOH(in.bits.addr_beat)
def dropPendingBit[T <: L2HellaCacheBundle with HasL2BeatAddr] (in: DecoupledIO[T]) =
~Fill(in.bits.refillCycles, in.fire()) | ~UIntToOH(in.bits.addr_beat)
def dropPendingBitInternal[T <: L2HellaCacheBundle with HasL2BeatAddr] (in: ValidIO[T]) =
~Fill(in.bits.refillCycles, in.valid) | ~UIntToOH(in.bits.addr_beat)
// TODO: Deal with the possibility that rowBits != tlDataBits
def mergeDataInternal[T <: L2HellaCacheBundle with HasL2Data with HasL2BeatAddr](in: ValidIO[T]) {
when(in.valid) { mergeData(rowBits)(in.bits.addr_beat, in.bits.data) }
}
}
trait ReadsFromOuterCacheDataArray extends HasCoherenceMetadataBuffer
with HasRowBeatCounters
with HasDataBuffer {
def io: HasL2DataRWIO
val pending_reads = Reg(init=Bits(0, width = innerDataBeats))
val pending_resps = Reg(init=Bits(0, width = innerDataBeats))
val curr_read_beat = PriorityEncoder(pending_reads)
def readDataArray(drop_pending_bit: UInt,
add_pending_bit: UInt = UInt(0),
block_pending_read: Bool = Bool(false),
can_update_pending: Bool = Bool(true)) {
val port = io.data
when (can_update_pending) {
pending_reads := (pending_reads | add_pending_bit) &
dropPendingBit(port.read) & drop_pending_bit
}
port.read.valid := state === s_busy && pending_reads.orR && !block_pending_read
port.read.bits := L2DataReadReq(
id = UInt(trackerId),
way_en = xact_way_en,
addr_idx = xact_addr_idx,
addr_beat = curr_read_beat)
pending_resps := (pending_resps & dropPendingBitInternal(port.resp)) |
addPendingBitInternal(port.read)
scoreboard += (pending_reads.orR, pending_resps.orR)
mergeDataInternal(port.resp)
}
}
trait WritesToOuterCacheDataArray extends HasCoherenceMetadataBuffer
with HasRowBeatCounters
with HasDataBuffer {
def io: HasL2DataRWIO
val pending_writes = Reg(init=Bits(0, width = innerDataBeats))
val curr_write_beat = PriorityEncoder(pending_writes)
def writeDataArray(add_pending_bit: UInt = UInt(0),
block_pending_write: Bool = Bool(false),
can_update_pending: Bool = Bool(true)) {
val port = io.data
when (can_update_pending) {
pending_writes := (pending_writes & dropPendingBit(port.write)) |
add_pending_bit
}
port.write.valid := state === s_busy && pending_writes.orR && !block_pending_write
port.write.bits := L2DataWriteReq(
id = UInt(trackerId),
way_en = xact_way_en,
addr_idx = xact_addr_idx,
addr_beat = curr_write_beat,
wmask = ~UInt(0, port.write.bits.wmask.getWidth),
data = data_buffer(curr_write_beat))
scoreboard += pending_writes.orR
}
}
trait HasAMOALU extends HasAcquireMetadataBuffer
with HasByteWriteMaskBuffer
with HasRowBeatCounters {
val io: L2XactTrackerIO
// Provide a single ALU per tracker to merge Puts and AMOs with data being
// refilled, written back, or extant in the cache
val amoalu = Module(new AMOALU(amoAluOperandBits, rhsIsAligned = true))
val amo_result = Reg(init = UInt(0, innerDataBits))
def initializeAMOALUIOs() {
amoalu.io.addr := Cat(xact_addr_block, xact_addr_beat, xact_addr_byte)
amoalu.io.cmd := xact_op_code
amoalu.io.typ := xact_op_size
amoalu.io.lhs := io.data.resp.bits.data // default, overwritten by calls to mergeData
amoalu.io.rhs := data_buffer.head // default, overwritten by calls to mergeData
}
// Utility function for applying any buffered stored data to the cache line
// before storing it back into the data array
override def mergeData(dataBits: Int)(beat: UInt, incoming: UInt) {
val old_data = incoming // Refilled, written back, or de-cached data
val new_data = data_buffer(beat) // Newly Put data is already in the buffer
val amo_shift_bits = xact_amo_shift_bytes << 3
amoalu.io.lhs := old_data >> amo_shift_bits
amoalu.io.rhs := new_data >> amo_shift_bits
val wmask = FillInterleaved(8, wmask_buffer(beat))
data_buffer(beat) := ~wmask & old_data |
wmask & Mux(xact_iacq.isAtomic(), amoalu.io.out << amo_shift_bits, new_data)
wmask_buffer(beat) := ~UInt(0, innerWriteMaskBits)
when(xact_iacq.isAtomic() && xact_addr_beat === beat) { amo_result := old_data }
}
}
trait HasCoherenceMetadataBuffer extends HasOuterCacheParameters
with HasBlockAddressBuffer
with HasXactTrackerStates {
def trackerId: Int
val xact_way_en = Reg{ Bits(width = nWays) }
val xact_old_meta = Reg{ new L2Metadata }
val pending_coh = Reg{ xact_old_meta.coh }
val pending_meta_write = Reg{ Bool() } // pending_meta_write has own state (s_meta_write)
val inner_coh = pending_coh.inner
val outer_coh = pending_coh.outer
val xact_addr_idx = xact_addr_block(idxMSB,idxLSB)
val xact_addr_tag = xact_addr_block >> UInt(tagLSB)
// Utility function for updating the metadata that will be kept in this cache
def updatePendingCohWhen(flag: Bool, next: HierarchicalMetadata) {
when(flag && pending_coh =/= next) {
pending_meta_write := Bool(true)
pending_coh := next
}
}
def metaRead(port: HasL2MetaReadIO, next_state: UInt, way_en_known: Bool = Bool(false)) {
port.read.valid := state === s_meta_read
port.read.bits.id := UInt(trackerId)
port.read.bits.idx := xact_addr_idx
port.read.bits.tag := xact_addr_tag
port.read.bits.way_en := Mux(way_en_known, xact_way_en, ~UInt(0, nWays))
when(state === s_meta_read && port.read.ready) { state := s_meta_resp }
when(state === s_meta_resp && port.resp.valid) {
xact_old_meta := port.resp.bits.meta
when (!way_en_known) { xact_way_en := port.resp.bits.way_en }
state := next_state
}
}
def metaWrite(port: HasL2MetaWriteIO, to_write: L2Metadata, next_state: UInt) {
port.write.valid := state === s_meta_write
port.write.bits.id := UInt(trackerId)
port.write.bits.idx := xact_addr_idx
port.write.bits.way_en := xact_way_en
port.write.bits.data := to_write
when(state === s_meta_write && port.write.ready) { state := next_state }
}
}
trait TriggersWritebacks extends HasCoherenceMetadataBuffer {
def triggerWriteback(wb: L2WritebackIO, next_state: UInt) {
wb.req.valid := state === s_wb_req
wb.req.bits.id := UInt(trackerId)
wb.req.bits.idx := xact_addr_idx
wb.req.bits.tag := xact_old_meta.tag
wb.req.bits.way_en := xact_way_en
when(state === s_wb_req && wb.req.ready) { state := s_wb_resp }
when(state === s_wb_resp && wb.resp.valid) { state := s_outer_acquire }
}
}
class CacheVoluntaryReleaseTracker(trackerId: Int)(implicit p: Parameters)
extends VoluntaryReleaseTracker(trackerId)(p)
with HasDataBuffer
with WritesToOuterCacheDataArray {
val io = new L2XactTrackerIO
pinAllReadyValidLow(io)
// Avoid metatdata races with writebacks
routeInParent(
iacqMatches = inSameSet(_, xact_addr_block),
irelCanAlloc = Bool(true))
// Initialize and accept pending Release beats
innerRelease(
block_vol_ignt = pending_writes.orR,
next = s_meta_read)
io.inner.release.ready := state === s_idle || irel_can_merge || irel_same_xact
// Begin a transaction by getting the current block metadata
metaRead(io.meta, s_busy)
// Write the voluntarily written back data to this cache
writeDataArray(add_pending_bit = addPendingBitWhenBeatHasData(io.inner.release),
can_update_pending = state =/= s_idle || io.alloc.irel.should)
// End a transaction by updating the block metadata
metaWrite(
io.meta,
L2Metadata(
tag = xact_addr_tag,
inner = xact_old_meta.coh.inner.onRelease(xact_vol_irel),
outer = Mux(xact_vol_irel.hasData(),
xact_old_meta.coh.outer.onHit(M_XWR),
xact_old_meta.coh.outer)),
s_idle)
mergeDataInner(io.inner.release)
when(irel_is_allocating) {
pending_writes := addPendingBitWhenBeatHasData(io.inner.release)
}
quiesce(s_meta_write) {}
// Checks for illegal behavior
assert(!(state === s_meta_resp && io.meta.resp.valid && !io.meta.resp.bits.tag_match),
"VoluntaryReleaseTracker accepted Release for a block not resident in this cache!")
}
class CacheAcquireTracker(trackerId: Int)(implicit p: Parameters)
extends AcquireTracker(trackerId)(p)
with HasByteWriteMaskBuffer
with HasAMOALU
with TriggersWritebacks
with ReadsFromOuterCacheDataArray
with WritesToOuterCacheDataArray {
val io = new L2XactTrackerIO
pinAllReadyValidLow(io)
initializeAMOALUIOs()
val pending_coh_on_ognt = HierarchicalMetadata(
ManagerMetadata.onReset,
pending_coh.outer.onGrant(io.outer.grant.bits, xact_op_code))
val pending_coh_on_ignt = HierarchicalMetadata(
pending_coh.inner.onGrant(io.ignt()),
Mux(ognt_counter.down.done,
pending_coh_on_ognt.outer,
pending_coh.outer))
val pending_coh_on_irel = HierarchicalMetadata(
pending_coh.inner.onRelease(io.irel()), // Drop sharer
Mux(io.irel().hasData(), // Dirty writeback
pending_coh.outer.onHit(M_XWR),
pending_coh.outer))
val pending_coh_on_hit = HierarchicalMetadata(
io.meta.resp.bits.meta.coh.inner,
io.meta.resp.bits.meta.coh.outer.onHit(xact_op_code))
val pending_coh_on_miss = HierarchicalMetadata.onReset
val before_wb_req = state.isOneOf(s_meta_read, s_meta_resp)
routeInParent(
iacqMatches = inSameSet(_, xact_addr_block),
irelMatches = (irel: HasCacheBlockAddress) =>
Mux(before_wb_req, inSameSet(irel, xact_addr_block), exactAddrMatch(irel)),
iacqCanAlloc = Bool(true))
// TileLink allows for Gets-under-Get
// and Puts-under-Put, and either may also merge with a preceding prefetch
// that requested the correct permissions (via op_code)
def acquiresAreMergeable(sec: AcquireMetadata): Bool = {
val allowedTypes = List((Acquire.getType, Acquire.getType),
(Acquire.putType, Acquire.putType),
(Acquire.putBlockType, Acquire.putBlockType),
(Acquire.getPrefetchType, Acquire.getPrefetchType),
(Acquire.putPrefetchType, Acquire.putPrefetchType),
(Acquire.getPrefetchType, Acquire.getType),
(Acquire.putPrefetchType, Acquire.putType),
(Acquire.putPrefetchType, Acquire.putBlockType))
allowedTypes.map { case(a, b) => xact_iacq.isBuiltInType(a) && sec.isBuiltInType(b) }.reduce(_||_) &&
xact_op_code === sec.op_code() &&
sec.conflicts(xact_addr_block) &&
xact_allocate
}
// First, take care of accpeting new acquires or secondary misses
// Handling of primary and secondary misses' data and write mask merging
def iacq_can_merge = acquiresAreMergeable(io.iacq()) &&
state =/= s_idle &&
state =/= s_meta_resp &&
state =/= s_meta_write &&
!all_pending_done &&
!io.inner.release.fire() &&
!io.outer.grant.fire() &&
!io.data.resp.valid &&
ignt_q.io.enq.ready && ignt_q.io.deq.valid
innerAcquire(
can_alloc = Bool(true),
next = s_meta_read)
io.inner.acquire.ready := state === s_idle || iacq_can_merge ||
iacq_same_xact_multibeat
// Begin a transaction by getting the current block metadata
// Defined here because of Chisel default wire demands, used in s_meta_resp
val coh = io.meta.resp.bits.meta.coh
val tag_match = io.meta.resp.bits.tag_match
val is_hit = (if(!isLastLevelCache) tag_match && coh.outer.isHit(xact_op_code)
else tag_match && coh.outer.isValid())
val needs_writeback = !tag_match &&
xact_allocate &&
(coh.outer.requiresVoluntaryWriteback() ||
coh.inner.requiresProbesOnVoluntaryWriteback())
val needs_inner_probes = tag_match && coh.inner.requiresProbes(xact_iacq)
val should_update_meta = !tag_match && xact_allocate ||
is_hit && pending_coh_on_hit =/= coh
def full_representation = coh.inner.full()
metaRead(
io.meta,
Mux(needs_writeback, s_wb_req,
Mux(needs_inner_probes, s_inner_probe,
Mux(!is_hit, s_outer_acquire, s_busy))))
updatePendingCohWhen(
io.meta.resp.valid,
Mux(is_hit, pending_coh_on_hit,
Mux(tag_match, coh, pending_coh_on_miss)))
// Issue a request to the writeback unit
triggerWriteback(io.wb, s_outer_acquire)
// Track which clients yet need to be probed and make Probe message
// If we're probing, we know the tag matches, so if this is the
// last level cache, we can use the data without upgrading permissions
val skip_outer_acquire =
(if(!isLastLevelCache) xact_old_meta.coh.outer.isHit(xact_op_code)
else xact_old_meta.coh.outer.isValid())
innerProbe(
inner_coh.makeProbe(curr_probe_dst, xact_iacq, xact_addr_block),
Mux(!skip_outer_acquire, s_outer_acquire, s_busy))
// Handle incoming releases from clients, which may reduce sharer counts
// and/or write back dirty data, and may be unexpected voluntary releases
innerRelease() // Don't block on pending_writes because they won't happen until s_busy
def irel_can_merge = io.irel().conflicts(xact_addr_block) &&
io.irel().isVoluntary() &&
!state.isOneOf(s_idle, s_meta_read, s_meta_resp, s_meta_write) &&
!all_pending_done &&
!io.outer.grant.fire() &&
!io.inner.grant.fire() &&
!vol_ignt_counter.pending
io.inner.release.ready := irel_can_merge || irel_same_xact
updatePendingCohWhen(io.inner.release.fire(), pending_coh_on_irel)
mergeDataInner(io.inner.release)
// Send outer request
outerAcquire(
caching = xact_allocate,
coh = xact_old_meta.coh.outer, // TODO outer_coh?
data = data_buffer(ognt_counter.up.idx),
wmask = wmask_buffer(ognt_counter.up.idx),
next = s_busy)
// Handle the response from outer memory
updatePendingCohWhen(ognt_counter.down.done, pending_coh_on_ognt)
mergeDataOuter(io.outer.grant)
// Send read request and get resp
// Going back to the original inner transaction:
// We read from the the cache at this level if data wasn't written back or refilled.
// We may still merge further Gets, requiring further beats to be read.
// If ECC requires a full writemask, we'll read out data on partial writes as well.
readDataArray(
drop_pending_bit = (dropPendingBitWhenBeatHasData(io.inner.release) &
dropPendingBitWhenBeatHasData(io.outer.grant)),
add_pending_bit = addPendingBitWhenBeatNeedsRead(
io.inner.acquire,
always = Bool(alwaysWriteFullBeat),
unless = data_valid(io.iacq().addr_beat)),
block_pending_read = ognt_counter.pending,
can_update_pending = state =/= s_idle || io.alloc.irel.should)
// No override for first accepted acquire
val alloc_override = xact_allocate && (state =/= s_idle)
// Do write
// We write data to the cache at this level if it was Put here with allocate flag,
// written back dirty, or refilled from outer memory.
writeDataArray(
add_pending_bit = (addPendingBitWhenBeatHasDataAndAllocs(io.inner.acquire, alloc_override) |
addPendingBitWhenBeatHasData(io.inner.release) |
addPendingBitWhenBeatHasData(io.outer.grant, xact_allocate)),
block_pending_write = (ognt_counter.pending ||
pending_put_data.orR ||
pending_reads(curr_write_beat) ||
pending_resps(curr_write_beat)),
can_update_pending = state =/= s_idle || io.alloc.iacq.should || io.alloc.irel.should)
// Acknowledge or respond with data
innerGrant(
data = Mux(xact_iacq.isAtomic(), amo_result, data_buffer(ignt_data_idx)),
external_pending = pending_writes.orR || ognt_counter.pending,
add_pending_bits = addPendingBitInternal(io.data.resp))
updatePendingCohWhen(io.inner.grant.fire() && io.ignt().last(), pending_coh_on_ignt)
// End a transaction by updating the block metadata
metaWrite(io.meta, L2Metadata(xact_addr_tag, pending_coh), s_idle)
// Initialization of some scoreboard logic based on the original
// Acquire message on on the results of the metadata read:
when(state === s_meta_resp && io.meta.resp.valid) {
// If some kind of Put is marked no-allocate but is already in the cache,
// we need to write its data to the data array
when(is_hit && !xact_allocate && xact_iacq.hasData()) {
pending_writes := addPendingBitsFromAcquire(xact_iacq)
xact_allocate := Bool(true)
}
when (needs_inner_probes) { initializeProbes() }
pending_meta_write := should_update_meta //TODO what edge case was this covering?
}
// Initialize more transaction metadata. Pla
when(iacq_is_allocating) {
amo_result := UInt(0)
pending_meta_write := Bool(false)
pending_reads := Mux( // Pick out the specific beats of data that need to be read
io.iacq().isBuiltInType(Acquire.getBlockType) || !io.iacq().isBuiltInType(),
~UInt(0, width = innerDataBeats),
addPendingBitWhenBeatNeedsRead(io.inner.acquire, Bool(alwaysWriteFullBeat)))
pending_writes := addPendingBitWhenBeatHasDataAndAllocs(io.inner.acquire)
pending_resps := UInt(0)
}
initDataInner(io.inner.acquire, iacq_is_allocating || iacq_is_merging)
// Wait for everything to quiesce
quiesce(Mux(pending_meta_write, s_meta_write, s_idle)) { clearWmaskBuffer() }
}
class L2WritebackReq(implicit p: Parameters)
extends L2HellaCacheBundle()(p) with HasL2Id {
val tag = Bits(width = tagBits)
val idx = Bits(width = idxBits)
val way_en = Bits(width = nWays)
}
class L2WritebackResp(implicit p: Parameters) extends L2HellaCacheBundle()(p) with HasL2Id
class L2WritebackIO(implicit p: Parameters) extends L2HellaCacheBundle()(p) {
val req = Decoupled(new L2WritebackReq)
val resp = Valid(new L2WritebackResp).flip
}
trait HasL2WritebackIO extends HasOuterCacheParameters {
val wb = new L2WritebackIO()
}
class L2WritebackUnitIO(implicit p: Parameters)
extends HierarchicalXactTrackerIO()(p) with HasL2DataRWIO {
val wb = new L2WritebackIO().flip()
val meta = new L2MetaReadOnlyIO
}
class L2WritebackUnit(val trackerId: Int)(implicit p: Parameters) extends XactTracker()(p)
with AcceptsVoluntaryReleases
with EmitsVoluntaryReleases
with EmitsInnerProbes
with ReadsFromOuterCacheDataArray
with RoutesInParent {
val io = new L2WritebackUnitIO
pinAllReadyValidLow(io)
val xact_id = Reg{ io.wb.req.bits.id }
val pending_coh_on_irel = HierarchicalMetadata(
inner_coh.onRelease(io.irel()), // Drop sharer
Mux(io.irel().hasData(), // Dirty writeback
outer_coh.onHit(M_XWR),
outer_coh))
routeInParent()
// Start the writeback sub-transaction
io.wb.req.ready := state === s_idle
val coh = io.meta.resp.bits.meta.coh
val needs_inner_probes = coh.inner.requiresProbesOnVoluntaryWriteback()
val needs_outer_release = coh.outer.requiresVoluntaryWriteback()
def full_representation = coh.inner.full()
// Even though we already read the metadata in the acquire tracker that
// sent the writeback request, we have to read it again in the writeback
// unit, since it may have been updated in the meantime.
metaRead(io.meta,
next_state = Mux(needs_inner_probes, s_inner_probe, s_busy),
way_en_known = Bool(true))
// Track which clients yet need to be probed and make Probe message
innerProbe(
inner_coh.makeProbeForVoluntaryWriteback(curr_probe_dst, xact_addr_block),
s_busy)
// Handle incoming releases from clients, which may reduce sharer counts
// and/or write back dirty data
innerRelease()
def irel_can_merge = io.irel().conflicts(xact_addr_block) &&
io.irel().isVoluntary() &&
!state.isOneOf(s_idle, s_meta_read, s_meta_resp) &&
!(state === s_busy && all_pending_done) &&
!vol_ignt_counter.pending &&
!blockInnerRelease()
io.inner.release.ready := irel_can_merge || irel_same_xact
updatePendingCohWhen(io.inner.release.fire(), pending_coh_on_irel)
mergeDataInner(io.inner.release)
// If a release didn't write back data, have to read it from data array
readDataArray(
drop_pending_bit = dropPendingBitWhenBeatHasData(io.inner.release))
// Once the data is buffered we can write it back to outer memory
outerRelease(
coh = outer_coh,
data = data_buffer(vol_ognt_counter.up.idx),
add_pending_data_bits = addPendingBitInternal(io.data.resp),
add_pending_send_bit = io.meta.resp.valid && needs_outer_release)
// Respond to the initiating transaction handler signalling completion of the writeback
io.wb.resp.valid := state === s_busy && all_pending_done
io.wb.resp.bits.id := xact_id
quiesce() {}
// State machine updates and transaction handler metadata intialization
when(state === s_idle && io.wb.req.valid) {
xact_id := io.wb.req.bits.id
xact_way_en := io.wb.req.bits.way_en
xact_addr_block := (if (cacheIdBits == 0) Cat(io.wb.req.bits.tag, io.wb.req.bits.idx)
else Cat(io.wb.req.bits.tag, io.wb.req.bits.idx, UInt(cacheId, cacheIdBits)))
state := s_meta_read
}
when (state === s_meta_resp && io.meta.resp.valid) {
pending_reads := Fill(innerDataBeats, needs_outer_release)
pending_coh := coh
when(needs_inner_probes) { initializeProbes() }
}
assert(!io.meta.resp.valid || io.meta.resp.bits.tag_match,
"L2 requested Writeback for block not present in cache")
}

View File

@ -6,6 +6,7 @@ import Chisel._
import junctions._ import junctions._
import util._ import util._
import regmapper._ import regmapper._
import tile.XLen
import uncore.tilelink2._ import uncore.tilelink2._
import config._ import config._
@ -848,7 +849,7 @@ trait DebugModule extends Module with HasDebugModuleParameters with HasRegMap {
*/ */
class TLDebugModule(address: BigInt = 0)(implicit p: Parameters) class TLDebugModule(address: BigInt = 0)(implicit p: Parameters)
extends TLRegisterRouter(address, beatBytes=p(rocket.XLen)/8, executable=true)( extends TLRegisterRouter(address, beatBytes=p(XLen)/8, executable=true)(
new TLRegBundle((), _ ) with DebugModuleBundle)( new TLRegBundle((), _ ) with DebugModuleBundle)(
new TLRegModule((), _, _) with DebugModule) new TLRegModule((), _, _) with DebugModule)

View File

@ -11,6 +11,7 @@ import regmapper._
import uncore.tilelink2._ import uncore.tilelink2._
import config._ import config._
import scala.math.min import scala.math.min
import tile.XLen
class GatewayPLICIO extends Bundle { class GatewayPLICIO extends Bundle {
val valid = Bool(OUTPUT) val valid = Bool(OUTPUT)
@ -59,7 +60,7 @@ class TLPLIC(supervisor: Boolean, maxPriorities: Int, address: BigInt = 0xC00000
val node = TLRegisterNode( val node = TLRegisterNode(
address = AddressSet(address, PLICConsts.size-1), address = AddressSet(address, PLICConsts.size-1),
beatBytes = p(rocket.XLen)/8, beatBytes = p(XLen)/8,
undefZero = false) undefZero = false)
val intnode = IntNexusNode( val intnode = IntNexusNode(

View File

@ -12,6 +12,7 @@ import uncore.util._
import util._ import util._
import scala.math.{min,max} import scala.math.{min,max}
import config._ import config._
import tile.XLen
/** Number of tiles */ /** Number of tiles */
case object NTiles extends Field[Int] case object NTiles extends Field[Int]
@ -83,7 +84,7 @@ trait CoreplexLocalInterrupterModule extends Module with HasRegMap with MixCorep
/** Power, Reset, Clock, Interrupt */ /** Power, Reset, Clock, Interrupt */
// Magic TL2 Incantation to create a TL2 Slave // Magic TL2 Incantation to create a TL2 Slave
class CoreplexLocalInterrupter(address: BigInt = 0x02000000)(implicit p: Parameters) class CoreplexLocalInterrupter(address: BigInt = 0x02000000)(implicit p: Parameters)
extends TLRegisterRouter(address, size = ClintConsts.size, beatBytes = p(rocket.XLen)/8, undefZero = true)( extends TLRegisterRouter(address, size = ClintConsts.size, beatBytes = p(XLen)/8, undefZero = true)(
new TLRegBundle((), _) with CoreplexLocalInterrupterBundle)( new TLRegBundle((), _) with CoreplexLocalInterrupterBundle)(
new TLRegModule((), _, _) with CoreplexLocalInterrupterModule) new TLRegModule((), _, _) with CoreplexLocalInterrupterModule)
{ {

View File

@ -28,8 +28,10 @@ class TLCacheCork(unsafe: Boolean = false)(implicit p: Parameters) extends LazyM
} }
((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) => ((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) =>
require (edgeIn.client.clients.size == 1 || unsafe, "Only one client can safely use a TLCacheCork") val clients = edgeIn.client.clients
require (edgeIn.client.clients.filter(_.supportsProbe).size == 1, "Only one caching client allowed") val caches = clients.filter(_.supportsProbe)
require (clients.size == 1 || caches.size == 0 || unsafe, "Only one client can safely use a TLCacheCork")
require (caches.size <= 1, "Only one caching client allowed")
edgeOut.manager.managers.foreach { case m => edgeOut.manager.managers.foreach { case m =>
require (!m.supportsAcquireB, "Cannot support caches beyond the Cork") require (!m.supportsAcquireB, "Cannot support caches beyond the Cork")
} }

View File

@ -27,7 +27,7 @@ case class TLManagerParameters(
require (!address.isEmpty) require (!address.isEmpty)
address.foreach { a => require (a.finite) } address.foreach { a => require (a.finite) }
address.combinations(2).foreach { case Seq(x,y) => require (!x.overlaps(y)) } address.combinations(2).foreach { case Seq(x,y) => require (!x.overlaps(y), s"$x and $y overlap.") }
require (supportsPutFull.contains(supportsPutPartial)) require (supportsPutFull.contains(supportsPutPartial))
require (supportsPutFull.contains(supportsArithmetic)) require (supportsPutFull.contains(supportsArithmetic))
require (supportsPutFull.contains(supportsLogical)) require (supportsPutFull.contains(supportsLogical))

View File

@ -1,181 +0,0 @@
// See LICENSE.Berkeley for license details.
// See LICENSE.SiFive for license details.
package uncore.util
import Chisel._
import config.{Parameters, Field}
import rocket.PAddrBits
import util.ParameterizedBundle
import uncore.constants._
case class CacheConfig(
nSets: Int,
nWays: Int,
rowBits: Int,
nTLBEntries: Int,
cacheIdBits: Int,
splitMetadata: Boolean)
case class CacheName(id: String) extends Field[CacheConfig]
case object CacheName extends Field[CacheName]
case object Replacer extends Field[() => ReplacementPolicy]
case object L2Replacer extends Field[() => SeqReplacementPolicy]
case object NPrimaryMisses extends Field[Int]
case object NSecondaryMisses extends Field[Int]
case object CacheBlockBytes extends Field[Int]
case object ECCCode extends Field[Option[Code]]
trait HasCacheParameters {
implicit val p: Parameters
val cacheConfig = p(p(CacheName))
val nSets = cacheConfig.nSets
val blockOffBits = log2Up(p(CacheBlockBytes))
val cacheIdBits = cacheConfig.cacheIdBits
val idxBits = log2Up(cacheConfig.nSets)
val untagBits = blockOffBits + cacheIdBits + idxBits
val tagBits = p(PAddrBits) - untagBits
val nWays = cacheConfig.nWays
val wayBits = log2Up(nWays)
val isDM = nWays == 1
val rowBits = cacheConfig.rowBits
val rowBytes = rowBits/8
val rowOffBits = log2Up(rowBytes)
val code = p(ECCCode).getOrElse(new IdentityCode)
val hasSplitMetadata = cacheConfig.splitMetadata
}
abstract class CacheModule(implicit val p: Parameters) extends Module
with HasCacheParameters
abstract class CacheBundle(implicit val p: Parameters) extends ParameterizedBundle()(p)
with HasCacheParameters
abstract class ReplacementPolicy {
def way: UInt
def miss: Unit
def hit: Unit
}
class RandomReplacement(ways: Int) extends ReplacementPolicy {
private val replace = Wire(Bool())
replace := Bool(false)
val lfsr = LFSR16(replace)
def way = if(ways == 1) UInt(0) else lfsr(log2Up(ways)-1,0)
def miss = replace := Bool(true)
def hit = {}
}
abstract class SeqReplacementPolicy {
def access(set: UInt): Unit
def update(valid: Bool, hit: Bool, set: UInt, way: UInt): Unit
def way: UInt
}
class SeqRandom(n_ways: Int) extends SeqReplacementPolicy {
val logic = new RandomReplacement(n_ways)
def access(set: UInt) = { }
def update(valid: Bool, hit: Bool, set: UInt, way: UInt) = {
when (valid && !hit) { logic.miss }
}
def way = logic.way
}
class PseudoLRU(n: Int)
{
require(isPow2(n))
val state_reg = Reg(Bits(width = n))
def access(way: UInt) {
state_reg := get_next_state(state_reg,way)
}
def get_next_state(state: UInt, way: UInt) = {
var next_state = state
var idx = UInt(1,1)
for (i <- log2Up(n)-1 to 0 by -1) {
val bit = way(i)
next_state = next_state.bitSet(idx, !bit)
idx = Cat(idx, bit)
}
next_state
}
def replace = get_replace_way(state_reg)
def get_replace_way(state: Bits) = {
var idx = UInt(1,1)
for (i <- 0 until log2Up(n))
idx = Cat(idx, state(idx))
idx(log2Up(n)-1,0)
}
}
class SeqPLRU(n_sets: Int, n_ways: Int) extends SeqReplacementPolicy {
val state = SeqMem(n_sets, Bits(width = n_ways-1))
val logic = new PseudoLRU(n_ways)
val current_state = Wire(Bits())
val plru_way = logic.get_replace_way(current_state)
val next_state = Wire(Bits())
def access(set: UInt) = {
current_state := Cat(state.read(set), Bits(0, width = 1))
}
def update(valid: Bool, hit: Bool, set: UInt, way: UInt) = {
val update_way = Mux(hit, way, plru_way)
next_state := logic.get_next_state(current_state, update_way)
when (valid) { state.write(set, next_state(n_ways-1,1)) }
}
def way = plru_way
}
abstract class Metadata(implicit p: Parameters) extends CacheBundle()(p) {
val tag = Bits(width = tagBits)
}
class MetaReadReq(implicit p: Parameters) extends CacheBundle()(p) {
val idx = Bits(width = idxBits)
val way_en = Bits(width = nWays)
}
class MetaWriteReq[T <: Metadata](gen: T)(implicit p: Parameters) extends MetaReadReq()(p) {
val data = gen.cloneType
override def cloneType = new MetaWriteReq(gen)(p).asInstanceOf[this.type]
}
class MetadataArray[T <: Metadata](onReset: () => T)(implicit p: Parameters) extends CacheModule()(p) {
val rstVal = onReset()
val io = new Bundle {
val read = Decoupled(new MetaReadReq).flip
val write = Decoupled(new MetaWriteReq(rstVal)).flip
val resp = Vec(nWays, rstVal.cloneType).asOutput
}
val rst_cnt = Reg(init=UInt(0, log2Up(nSets+1)))
val rst = rst_cnt < UInt(nSets)
val waddr = Mux(rst, rst_cnt, io.write.bits.idx)
val wdata = Mux(rst, rstVal, io.write.bits.data).asUInt
val wmask = Mux(rst || Bool(nWays == 1), SInt(-1), io.write.bits.way_en.asSInt).toBools
val rmask = Mux(rst || Bool(nWays == 1), SInt(-1), io.read.bits.way_en.asSInt).toBools
when (rst) { rst_cnt := rst_cnt+UInt(1) }
val metabits = rstVal.getWidth
if (hasSplitMetadata) {
val tag_arrs = List.fill(nWays){ SeqMem(nSets, UInt(width = metabits)) }
val tag_readout = Wire(Vec(nWays,rstVal.cloneType))
(0 until nWays).foreach { (i) =>
when (rst || (io.write.valid && wmask(i))) {
tag_arrs(i).write(waddr, wdata)
}
io.resp(i) := rstVal.fromBits(tag_arrs(i).read(io.read.bits.idx, io.read.valid && rmask(i)))
}
} else {
val tag_arr = SeqMem(nSets, Vec(nWays, UInt(width = metabits)))
when (rst || io.write.valid) {
tag_arr.write(waddr, Vec.fill(nWays)(wdata), wmask)
}
io.resp := tag_arr.read(io.read.bits.idx, io.read.valid).map(rstVal.fromBits(_))
}
io.read.ready := !rst && !io.write.valid // so really this could be a 6T RAM
io.write.ready := !rst
}

View File

@ -0,0 +1,83 @@
// See LICENSE.Berkeley for license details.
// See LICENSE.SiFive for license details.
package util
import Chisel._
abstract class ReplacementPolicy {
def way: UInt
def miss: Unit
def hit: Unit
}
class RandomReplacement(ways: Int) extends ReplacementPolicy {
private val replace = Wire(Bool())
replace := Bool(false)
val lfsr = LFSR16(replace)
def way = if(ways == 1) UInt(0) else lfsr(log2Up(ways)-1,0)
def miss = replace := Bool(true)
def hit = {}
}
abstract class SeqReplacementPolicy {
def access(set: UInt): Unit
def update(valid: Bool, hit: Bool, set: UInt, way: UInt): Unit
def way: UInt
}
class SeqRandom(n_ways: Int) extends SeqReplacementPolicy {
val logic = new RandomReplacement(n_ways)
def access(set: UInt) = { }
def update(valid: Bool, hit: Bool, set: UInt, way: UInt) = {
when (valid && !hit) { logic.miss }
}
def way = logic.way
}
class PseudoLRU(n: Int)
{
require(isPow2(n))
val state_reg = Reg(Bits(width = n))
def access(way: UInt) {
state_reg := get_next_state(state_reg,way)
}
def get_next_state(state: UInt, way: UInt) = {
var next_state = state
var idx = UInt(1,1)
for (i <- log2Up(n)-1 to 0 by -1) {
val bit = way(i)
next_state = next_state.bitSet(idx, !bit)
idx = Cat(idx, bit)
}
next_state
}
def replace = get_replace_way(state_reg)
def get_replace_way(state: Bits) = {
var idx = UInt(1,1)
for (i <- 0 until log2Up(n))
idx = Cat(idx, state(idx))
idx(log2Up(n)-1,0)
}
}
class SeqPLRU(n_sets: Int, n_ways: Int) extends SeqReplacementPolicy {
val state = SeqMem(n_sets, Bits(width = n_ways-1))
val logic = new PseudoLRU(n_ways)
val current_state = Wire(Bits())
val plru_way = logic.get_replace_way(current_state)
val next_state = Wire(Bits())
def access(set: UInt) = {
current_state := Cat(state.read(set), Bits(0, width = 1))
}
def update(valid: Bool, hit: Bool, set: UInt, way: UInt) = {
val update_way = Mux(hit, way, plru_way)
next_state := logic.get_next_state(current_state, update_way)
when (valid) { state.write(set, next_state(n_ways-1,1)) }
}
def way = plru_way
}