1
0
rocket-chip/src/main/scala/rocketchip/Periphery.scala

368 lines
11 KiB
Scala
Raw Normal View History

// See LICENSE.SiFive for license details.
package rocketchip
import Chisel._
import config._
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
2017-02-09 22:59:09 +01:00
import coreplex._
import diplomacy._
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
2017-02-09 22:59:09 +01:00
import tile.XLen
import uncore.tilelink2._
import uncore.axi4._
import uncore.converters._
import uncore.devices._
import uncore.util._
import util._
2016-09-16 07:06:39 +02:00
import scala.math.max
/** Specifies the size of external memory */
case class MasterConfig(base: Long, size: Long, beatBytes: Int, idBits: Int)
case object ExtMem extends Field[MasterConfig]
case object ExtBus extends Field[MasterConfig]
case class SlaveConfig(beatBytes: Int, idBits: Int, sourceBits: Int)
case object ExtIn extends Field[SlaveConfig]
/** Specifies the number of external interrupts */
case object NExtTopInterrupts extends Field[Int]
/** Source of RTC. First bundle is TopIO.extra, Second bundle is periphery.io.extra **/
case object RTCPeriod extends Field[Int]
/* Specifies the periphery bus configuration */
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 {
implicit val p: Parameters
def peripheryBusConfig = p(PeripheryBusConfig)
def peripheryBusBytes = peripheryBusConfig.beatBytes
def socBusConfig = p(SOCBusConfig)
def socBusBytes = socBusConfig.beatBytes
def cacheBlockBytes = p(CacheBlockBytes)
def peripheryBusArithmetic = p(PeripheryBusArithmetic)
def nMemoryChannels = p(coreplex.BankedL2Config).nMemoryChannels
}
/////
2016-10-29 07:30:13 +02:00
trait PeripheryExtInterrupts {
this: HasTopLevelNetworks =>
2017-03-01 09:03:01 +01:00
private val device = new Device with DeviceInterrupts {
def describe(resources: ResourceBindings): Description = {
Description("soc/offchip-interrupts", describeInterrupts(resources))
}
}
val nExtInterrupts = p(NExtTopInterrupts)
val extInterrupts = IntInternalInputNode(IntSourcePortSimple(num = nExtInterrupts, resources = device.int))
2016-10-29 06:20:49 +02:00
val extInterruptXing = LazyModule(new IntXing)
intBus.intnode := extInterruptXing.intnode
extInterruptXing.intnode := extInterrupts
}
trait PeripheryExtInterruptsBundle {
this: HasTopLevelNetworksBundle {
2016-10-29 07:30:13 +02:00
val outer: PeripheryExtInterrupts
} =>
val interrupts = UInt(INPUT, width = outer.nExtInterrupts)
}
trait PeripheryExtInterruptsModule {
this: HasTopLevelNetworksModule {
2016-10-29 07:30:13 +02:00
val outer: PeripheryExtInterrupts
val io: PeripheryExtInterruptsBundle
} =>
outer.extInterrupts.bundleIn(0).zipWithIndex.foreach { case(o, i) => o := io.interrupts(i) }
}
/////
trait PeripheryMasterAXI4Mem {
this: HasTopLevelNetworks =>
val module: PeripheryMasterAXI4MemModule
private val config = p(ExtMem)
private val channels = p(BankedL2Config).nMemoryChannels
private val lineBytes = p(CacheBlockBytes)
2017-03-01 09:03:01 +01:00
private val device = new MemoryDevice
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 = base.intersect(filter).toList,
2017-03-01 09:03:01 +01:00
resources = device.reg,
2016-11-15 00:19:39 +01:00
regionType = RegionType.UNCACHED, // cacheable
executable = true,
supportsWrite = TransferSizes(1, 256), // The slave supports 1-256 byte transfers
supportsRead = TransferSizes(1, 256),
interleavedId = Some(0))), // slave does not interleave read responses
beatBytes = config.beatBytes)
})
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
}
}
trait PeripheryMasterAXI4MemBundle {
this: HasTopLevelNetworksBundle {
val outer: PeripheryMasterAXI4Mem
2016-10-29 07:30:13 +02:00
} =>
val mem_axi4 = outer.mem_axi4.bundleOut
}
trait PeripheryMasterAXI4MemModule {
this: HasTopLevelNetworksModule {
val outer: PeripheryMasterAXI4Mem
val io: PeripheryMasterAXI4MemBundle
2016-10-29 07:30:13 +02:00
} =>
}
/////
trait PeripheryZero {
this: HasTopLevelNetworks =>
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: HasTopLevelNetworksBundle {
val outer: PeripheryZero
} =>
}
trait PeripheryZeroModule {
this: HasTopLevelNetworksModule {
val outer: PeripheryZero
val io: PeripheryZeroBundle
} =>
}
/////
// PeripheryMasterAXI4MMIO is an example, make your own cake pattern like this one.
2016-10-29 07:30:13 +02:00
trait PeripheryMasterAXI4MMIO {
this: HasTopLevelNetworks =>
private val config = p(ExtBus)
2017-03-01 09:03:01 +01:00
private val device = new SimpleDevice("mmio", Nil)
val mmio_axi4 = AXI4BlindOutputNode(Seq(AXI4SlavePortParameters(
slaves = Seq(AXI4SlaveParameters(
address = List(AddressSet(BigInt(config.base), config.size-1)),
2017-03-01 09:03:01 +01:00
resources = device.reg,
executable = true, // Can we run programs on this memory?
supportsWrite = TransferSizes(1, 256), // The slave supports 1-256 byte transfers
supportsRead = TransferSizes(1, 256),
interleavedId = Some(0))), // slave does not interleave read responses
beatBytes = config.beatBytes)))
mmio_axi4 :=
AXI4Buffer()(
// AXI4Fragmenter(lite=false, maxInFlight = 20)( // beef device up to support awlen = 0xff
TLToAXI4(idBits = config.idBits)( // use idBits = 0 for AXI4-Lite
TLWidthWidget(socBusConfig.beatBytes)( // convert width before attaching to socBus
socBus.node)))
}
2016-10-29 07:30:13 +02:00
trait PeripheryMasterAXI4MMIOBundle {
this: HasTopLevelNetworksBundle {
2016-10-29 07:30:13 +02:00
val outer: PeripheryMasterAXI4MMIO
} =>
2016-11-23 01:58:24 +01:00
val mmio_axi4 = outer.mmio_axi4.bundleOut
}
2016-10-29 07:30:13 +02:00
trait PeripheryMasterAXI4MMIOModule {
this: HasTopLevelNetworksModule {
2016-10-29 07:30:13 +02:00
val outer: PeripheryMasterAXI4MMIO
val io: PeripheryMasterAXI4MMIOBundle
} =>
// nothing to do
}
/////
2016-11-23 01:58:24 +01:00
// PeripherySlaveAXI4 is an example, make your own cake pattern like this one.
trait PeripherySlaveAXI4 extends HasTopLevelNetworks {
private val config = p(ExtIn)
val l2FrontendAXI4Node = AXI4BlindInputNode(Seq(AXI4MasterPortParameters(
2016-11-23 01:58:24 +01:00
masters = Seq(AXI4MasterParameters(
id = IdRange(0, 1 << config.idBits))))))
l2FrontendBus.node :=
TLSourceShrinker(1 << config.sourceBits)(
TLWidthWidget(config.beatBytes)(
AXI4ToTL()(
AXI4Fragmenter()(
l2FrontendAXI4Node))))
2016-11-23 01:58:24 +01:00
}
trait PeripherySlaveAXI4Bundle extends HasTopLevelNetworksBundle {
2016-11-23 01:58:24 +01:00
val outer: PeripherySlaveAXI4
val l2_frontend_bus_axi4 = outer.l2FrontendAXI4Node.bundleIn
2016-11-23 01:58:24 +01:00
}
trait PeripherySlaveAXI4Module extends HasTopLevelNetworksModule {
2016-11-23 01:58:24 +01:00
val outer: PeripherySlaveAXI4
val io: PeripherySlaveAXI4Bundle
// nothing to do
}
/////
// Add an external TL-UL slave
trait PeripheryMasterTLMMIO {
this: HasTopLevelNetworks =>
private val config = p(ExtBus)
2017-03-01 09:03:01 +01:00
private val device = new SimpleDevice("mmio", Nil)
val mmio_tl = TLBlindOutputNode(Seq(TLManagerPortParameters(
managers = Seq(TLManagerParameters(
address = List(AddressSet(BigInt(config.base), config.size-1)),
2017-03-01 09:03:01 +01:00
resources = device.reg,
executable = true,
supportsGet = TransferSizes(1, cacheBlockBytes),
supportsPutFull = TransferSizes(1, cacheBlockBytes),
supportsPutPartial = TransferSizes(1, cacheBlockBytes))),
beatBytes = config.beatBytes)))
mmio_tl :=
TLBuffer()(
TLSourceShrinker(config.idBits)(
TLWidthWidget(socBusConfig.beatBytes)(
socBus.node)))
}
trait PeripheryMasterTLMMIOBundle {
this: HasTopLevelNetworksBundle {
val outer: PeripheryMasterTLMMIO
} =>
val mmio_tl = outer.mmio_tl.bundleOut
}
trait PeripheryMasterTLMMIOModule {
this: HasTopLevelNetworksModule {
val outer: PeripheryMasterTLMMIO
val io: PeripheryMasterTLMMIOBundle
} =>
// nothing to do
}
/////
// NOTE: this port is NOT allowed to issue Acquires
trait PeripherySlaveTL extends HasTopLevelNetworks {
private val config = p(ExtIn)
val l2FrontendTLNode = TLBlindInputNode(Seq(TLClientPortParameters(
clients = Seq(TLClientParameters(
sourceId = IdRange(0, 1 << config.idBits))))))
l2FrontendBus.node :=
TLSourceShrinker(1 << config.sourceBits)(
TLWidthWidget(config.beatBytes)(
l2FrontendTLNode))
}
trait PeripherySlaveTLBundle extends HasTopLevelNetworksBundle {
val outer: PeripherySlaveTL
val l2_frontend_bus_tl = outer.l2FrontendTLNode.bundleIn
}
trait PeripherySlaveTLModule extends HasTopLevelNetworksModule {
val outer: PeripherySlaveTL
val io: PeripherySlaveTLBundle
// nothing to do
}
/////
2016-10-29 07:30:13 +02:00
trait PeripheryBootROM {
this: HasTopLevelNetworks =>
val coreplex: CoreplexRISCVPlatform
private val bootrom_address = 0x1000
private val bootrom_size = 0x1000
private lazy val bootrom_contents = GenerateBootROM(p, bootrom_address, coreplex.configString)
val bootrom = LazyModule(new TLROM(bootrom_address, bootrom_size, bootrom_contents, true, peripheryBusConfig.beatBytes))
bootrom.node := TLFragmenter(peripheryBusConfig.beatBytes, cacheBlockBytes)(peripheryBus.node)
}
trait PeripheryBootROMBundle {
this: HasTopLevelNetworksBundle {
2016-10-29 07:30:13 +02:00
val outer: PeripheryBootROM
} =>
}
2016-10-29 07:30:13 +02:00
trait PeripheryBootROMModule {
this: HasTopLevelNetworksModule {
2016-10-29 07:30:13 +02:00
val outer: PeripheryBootROM
val io: PeripheryBootROMBundle
} =>
}
/////
2016-10-29 07:30:13 +02:00
trait PeripheryTestRAM {
this: HasTopLevelNetworks =>
2016-10-29 07:30:13 +02:00
val testram = LazyModule(new TLRAM(AddressSet(0x52000000, 0xfff), true, peripheryBusConfig.beatBytes))
testram.node := TLFragmenter(peripheryBusConfig.beatBytes, cacheBlockBytes)(peripheryBus.node)
}
trait PeripheryTestRAMBundle {
this: HasTopLevelNetworksBundle {
2016-10-29 07:30:13 +02:00
val outer: PeripheryTestRAM
} =>
}
2016-10-29 07:30:13 +02:00
trait PeripheryTestRAMModule {
this: HasTopLevelNetworksModule {
2016-10-29 07:30:13 +02:00
val outer: PeripheryTestRAM
val io: PeripheryTestRAMBundle
} =>
}
/////
2016-10-29 07:30:13 +02:00
trait PeripheryTestBusMaster {
this: HasTopLevelNetworks =>
val fuzzer = LazyModule(new TLFuzzer(5000))
peripheryBus.node := fuzzer.node
}
trait PeripheryTestBusMasterBundle {
this: HasTopLevelNetworksBundle {
2016-10-29 07:30:13 +02:00
val outer: PeripheryTestBusMaster
} =>
}
trait PeripheryTestBusMasterModule {
this: HasTopLevelNetworksModule {
2016-10-29 07:30:13 +02:00
val outer: PeripheryTestBusMaster
val io: PeripheryTestBusMasterBundle
} =>
}