diff --git a/src/main/scala/coreplex/CoreplexNetwork.scala b/src/main/scala/coreplex/CoreplexNetwork.scala index 9402548b..d4b700aa 100644 --- a/src/main/scala/coreplex/CoreplexNetwork.scala +++ b/src/main/scala/coreplex/CoreplexNetwork.scala @@ -71,27 +71,26 @@ trait CoreplexNetworkModule extends HasCoreplexParameters { trait BankedL2CoherenceManagers extends CoreplexNetwork { val module: BankedL2CoherenceManagersModule + require (isPow2(l2Config.nMemoryChannels) || l2Config.nMemoryChannels == 0) require (isPow2(l2Config.nBanksPerChannel)) require (isPow2(l1tol2_lineBytes)) - val mem = TLOutputNode() - for (channel <- 0 until l2Config.nMemoryChannels) { - val bankBar = LazyModule(new TLXbar) - val (in, out) = l2Config.coherenceManager(p, this) - - in :*= l1tol2.node - mem := bankBar.node - - val mask = ~BigInt((l2Config.nBanksPerChannel-1) * l1tol2_lineBytes) + private val (in, out) = l2Config.coherenceManager(p, this) + private val mask = ~BigInt((l2Config.nBanks-1) * l1tol2_lineBytes) + val mem = Seq.tabulate(l2Config.nMemoryChannels) { channel => + val node = TLOutputNode() for (bank <- 0 until l2Config.nBanksPerChannel) { - bankBar.node := TLFilter(AddressSet(bank * l1tol2_lineBytes, mask))(out) + val offset = (bank * l2Config.nMemoryChannels) + channel + in := l1tol2.node + node := TLFilter(AddressSet(offset * l1tol2_lineBytes, mask))(out) } + node } } trait BankedL2CoherenceManagersBundle extends CoreplexNetworkBundle { val outer: BankedL2CoherenceManagers - val mem = outer.mem.bundleOut + val mem = HeterogeneousBag(outer.mem.map(_.bundleOut)) } trait BankedL2CoherenceManagersModule extends CoreplexNetworkModule { diff --git a/src/main/scala/groundtest/Top.scala b/src/main/scala/groundtest/Top.scala index 5e328089..9fb40686 100644 --- a/src/main/scala/groundtest/Top.scala +++ b/src/main/scala/groundtest/Top.scala @@ -17,7 +17,7 @@ class GroundTestTop(implicit p: Parameters) extends BaseTop socBus.node := coreplex.mmio coreplex.mmioInt := intBus.intnode - mem.foreach { _ := coreplex.mem } + (mem zip coreplex.mem) foreach { case (xbar, channel) => xbar.node :=* channel } } class GroundTestTopBundle[+L <: GroundTestTop](_outer: L) extends BaseTopBundle(_outer) diff --git a/src/main/scala/rocketchip/BaseTop.scala b/src/main/scala/rocketchip/BaseTop.scala index 0a9bdec7..b5a8c582 100644 --- a/src/main/scala/rocketchip/BaseTop.scala +++ b/src/main/scala/rocketchip/BaseTop.scala @@ -35,6 +35,7 @@ trait TopNetwork extends HasPeripheryParameters { val peripheryBus = LazyModule(new TLXbar) val intBus = LazyModule(new IntXbar) val l2 = LazyModule(new TLBuffer) + val mem = Seq.fill(p(coreplex.BankedL2Config).nMemoryChannels) { LazyModule(new TLXbar) } peripheryBus.node := TLBuffer()( diff --git a/src/main/scala/rocketchip/Configs.scala b/src/main/scala/rocketchip/Configs.scala index a2d9c24b..7ee8ba1e 100644 --- a/src/main/scala/rocketchip/Configs.scala +++ b/src/main/scala/rocketchip/Configs.scala @@ -31,6 +31,7 @@ class BasePlatformConfig extends Config((site, here, up) => { case PeripheryBusArithmetic => true // Note that PLIC asserts that this is > 0. case IncludeJtagDTM => false + case ZeroConfig => ZeroConfig(base=0xa000000L, size=0x2000000L, beatBytes=8) case ExtMem => MasterConfig(base=0x80000000L, size=0x10000000L, beatBytes=8, idBits=4) case ExtBus => MasterConfig(base=0x60000000L, size=0x20000000L, beatBytes=8, idBits=4) case ExtIn => SlaveConfig(beatBytes=8, idBits=8, sourceBits=2) @@ -86,6 +87,7 @@ class RoccExampleConfig extends Config(new WithRoccExample ++ new BaseConfig) 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( diff --git a/src/main/scala/rocketchip/ExampleTop.scala b/src/main/scala/rocketchip/ExampleTop.scala index 1c466ca7..66fd1112 100644 --- a/src/main/scala/rocketchip/ExampleTop.scala +++ b/src/main/scala/rocketchip/ExampleTop.scala @@ -30,6 +30,7 @@ class ExampleTopModule[+L <: ExampleTop, +B <: ExampleTopBundle[L]](_outer: L, _ class ExampleRocketTop(implicit p: Parameters) extends ExampleTop with PeripheryBootROM + with PeripheryZero with PeripheryDebug with PeripheryCounter with HardwiredResetVector @@ -39,6 +40,7 @@ class ExampleRocketTop(implicit p: Parameters) extends ExampleTop class ExampleRocketTopBundle[+L <: ExampleRocketTop](_outer: L) extends ExampleTopBundle(_outer) with PeripheryBootROMBundle + with PeripheryZeroBundle with PeripheryDebugBundle with PeripheryCounterBundle with HardwiredResetVectorBundle @@ -46,6 +48,7 @@ class ExampleRocketTopBundle[+L <: ExampleRocketTop](_outer: L) extends ExampleT class ExampleRocketTopModule[+L <: ExampleRocketTop, +B <: ExampleRocketTopBundle[L]](_outer: L, _io: () => B) extends ExampleTopModule(_outer, _io) with PeripheryBootROMModule + with PeripheryZeroModule with PeripheryDebugModule with PeripheryCounterModule with HardwiredResetVectorModule diff --git a/src/main/scala/rocketchip/Periphery.scala b/src/main/scala/rocketchip/Periphery.scala index 5e544754..53b201e4 100644 --- a/src/main/scala/rocketchip/Periphery.scala +++ b/src/main/scala/rocketchip/Periphery.scala @@ -34,6 +34,9 @@ case object PeripheryBusConfig extends Field[TLBusConfig] case object PeripheryBusArithmetic extends Field[Boolean] /* Specifies the SOC-bus configuration */ case object SOCBusConfig extends Field[TLBusConfig] +/* Specifies the location of the Zero device */ +case class ZeroConfig(base: Long, size: Long, beatBytes: Int) +case object ZeroConfig extends Field[ZeroConfig] /** Utility trait for quick access to some relevant parameters */ trait HasPeripheryParameters { @@ -72,28 +75,21 @@ trait PeripheryExtInterruptsModule { ///// -trait PeripheryNoMem extends TopNetwork { - private val channels = p(BankedL2Config).nMemoryChannels - require (channels == 0) - val mem = Seq() -} - -///// - trait PeripheryMasterAXI4Mem { this: TopNetwork => val module: PeripheryMasterAXI4MemModule private val config = p(ExtMem) private val channels = p(BankedL2Config).nMemoryChannels + private val lineBytes = p(CacheBlockBytes) - val mem_axi4 = AXI4BlindOutputNode(Seq.tabulate(channels) { i => - val c_size = config.size/channels - val c_base = config.base + c_size*i + val mem_axi4 = AXI4BlindOutputNode(Seq.tabulate(channels) { channel => + val base = AddressSet(config.base, config.size-1) + val filter = AddressSet(channel * lineBytes, ~((channels-1) * lineBytes)) AXI4SlavePortParameters( slaves = Seq(AXI4SlaveParameters( - address = List(AddressSet(c_base, c_size-1)), + address = base.intersect(filter).toList, regionType = RegionType.UNCACHED, // cacheable executable = true, supportsWrite = TransferSizes(1, 256), // The slave supports 1-256 byte transfers @@ -102,10 +98,13 @@ trait PeripheryMasterAXI4Mem { beatBytes = config.beatBytes) }) - val mem = Seq.fill(channels) { - val converter = LazyModule(new TLToAXI4(config.idBits)) - mem_axi4 := AXI4Buffer()(converter.node) - converter.node + private val converter = LazyModule(new TLToAXI4(config.idBits)) + private val buffer = LazyModule(new AXI4Buffer) + + mem foreach { case xbar => + converter.node := xbar.node + buffer.node := converter.node + mem_axi4 := buffer.node } } @@ -125,6 +124,36 @@ trait PeripheryMasterAXI4MemModule { ///// +trait PeripheryZero { + this: TopNetwork => + val module: PeripheryZeroModule + + private val config = p(ZeroConfig) + private val address = AddressSet(config.base, config.size-1) + private val lineBytes = p(CacheBlockBytes) + + val zeros = mem map { case xbar => + val zero = LazyModule(new TLZero(address, beatBytes = config.beatBytes)) + zero.node := TLFragmenter(config.beatBytes, lineBytes)(xbar.node) + zero + } +} + +trait PeripheryZeroBundle { + this: TopNetworkBundle { + val outer: PeripheryZero + } => +} + +trait PeripheryZeroModule { + this: TopNetworkModule { + val outer: PeripheryZero + val io: PeripheryZeroBundle + } => +} + +///// + // PeripheryMasterAXI4MMIO is an example, make your own cake pattern like this one. trait PeripheryMasterAXI4MMIO { this: TopNetwork => diff --git a/src/main/scala/rocketchip/RocketPlexMaster.scala b/src/main/scala/rocketchip/RocketPlexMaster.scala index 0f7d1c05..06591dbb 100644 --- a/src/main/scala/rocketchip/RocketPlexMaster.scala +++ b/src/main/scala/rocketchip/RocketPlexMaster.scala @@ -12,14 +12,15 @@ import coreplex._ trait RocketPlexMaster extends TopNetwork { val module: RocketPlexMasterModule - val mem: Seq[TLInwardNode] val coreplex = LazyModule(new DefaultCoreplex) coreplex.l2in :=* l2.node socBus.node := coreplex.mmio coreplex.mmioInt := intBus.intnode - mem.foreach { _ := coreplex.mem } + + require (mem.size == coreplex.mem.size) + (mem zip coreplex.mem) foreach { case (xbar, channel) => xbar.node :=* channel } } trait RocketPlexMasterBundle extends TopNetworkBundle { diff --git a/src/main/scala/uncore/tilelink2/Zero.scala b/src/main/scala/uncore/tilelink2/Zero.scala new file mode 100644 index 00000000..2da7f940 --- /dev/null +++ b/src/main/scala/uncore/tilelink2/Zero.scala @@ -0,0 +1,44 @@ +// See LICENSE.SiFive for license details. + +package uncore.tilelink2 + +import Chisel._ +import config._ +import diplomacy._ + +class TLZero(address: AddressSet, executable: Boolean = true, beatBytes: Int = 4)(implicit p: Parameters) extends LazyModule +{ + val node = TLManagerNode(Seq(TLManagerPortParameters( + Seq(TLManagerParameters( + address = List(address), + regionType = RegionType.UNCACHED, + executable = executable, + supportsGet = TransferSizes(1, beatBytes), + supportsPutPartial = TransferSizes(1, beatBytes), + supportsPutFull = TransferSizes(1, beatBytes), + fifoId = Some(0))), // requests are handled in order + beatBytes = beatBytes, + minLatency = 1))) // no bypass needed for this device + + lazy val module = new LazyModuleImp(this) { + val io = new Bundle { + val in = node.bundleIn + } + + val in = io.in(0) + val edge = node.edgesIn(0) + + val a = Queue(in.a, 2) + val hasData = edge.hasData(a.bits) + + a.ready := in.d.ready + in.d.valid := a.valid + in.d.bits := edge.AccessAck(a.bits, UInt(0)) + in.d.bits.opcode := Mux(hasData, TLMessages.AccessAck, TLMessages.AccessAckData) + + // Tie off unused channels + in.b.valid := Bool(false) + in.c.ready := Bool(true) + in.e.ready := Bool(true) + } +} diff --git a/src/main/scala/uncore/util/Ecc.scala b/src/main/scala/uncore/util/Ecc.scala index b478e3c2..bfaaed12 100644 --- a/src/main/scala/uncore/util/Ecc.scala +++ b/src/main/scala/uncore/util/Ecc.scala @@ -10,7 +10,7 @@ abstract class Decoding def uncorrected: UInt def corrected: UInt def correctable: Bool - def uncorrectable: Bool + def uncorrectable: Bool // If true, correctable should be ignored def error = correctable || uncorrectable } @@ -81,7 +81,7 @@ class SECCode extends Code def uncorrected = swizzle(y) def corrected = swizzle(((y << 1) ^ UIntToOH(syndrome)) >> 1) def correctable = syndrome.orR - def uncorrectable = Bool(false) + def uncorrectable = syndrome > UInt(n) } private def mapping(i: Int) = i-1-log2Up(i) } diff --git a/src/main/scala/util/HeterogeneousBag.scala b/src/main/scala/util/HeterogeneousBag.scala new file mode 100644 index 00000000..1aaff08d --- /dev/null +++ b/src/main/scala/util/HeterogeneousBag.scala @@ -0,0 +1,13 @@ +package util + +import Chisel._ +import chisel3.core.Record +import scala.collection.immutable.ListMap + +final case class HeterogeneousBag[T <: Data](elts: Seq[T]) extends Record with collection.IndexedSeq[T] { + def apply(x: Int) = elts(x) + def length = elts.length + + val elements = ListMap(elts.zipWithIndex.map { case (n,i) => (i.toString, n) }:_*) + override def cloneType: this.type = (new HeterogeneousBag(elts.map(_.cloneType))).asInstanceOf[this.type] +}