allow re-positionable PLIC and Clint, and change coreplex internal network names
This commit is contained in:
parent
5552f23294
commit
1c97a2a94c
@ -46,10 +46,14 @@ 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 tilesParams = p(RocketTilesKey)
|
||||||
lazy val cbusConfig = p(CBusConfig)
|
lazy val sbusConfig = p(L1toL2Config)
|
||||||
lazy val l1tol2Config = p(L1toL2Config)
|
lazy val pbusConfig = p(CBusConfig)
|
||||||
lazy val nTiles = tilesParams.size
|
lazy val nTiles = tilesParams.size
|
||||||
lazy val l2Config = p(BankedL2Config)
|
lazy val l2Config = p(BankedL2Config)
|
||||||
|
def sbusBeatBytes = sbusConfig.beatBytes
|
||||||
|
def sbusBlockBytes = p(CacheBlockBytes)
|
||||||
|
def pbusBeatBytes = pbusConfig.beatBytes
|
||||||
|
def pbusBlockBytes = sbusBlockBytes
|
||||||
}
|
}
|
||||||
|
|
||||||
case class CoreplexParameters(implicit val p: Parameters) extends HasCoreplexParameters
|
case class CoreplexParameters(implicit val p: Parameters) extends HasCoreplexParameters
|
||||||
|
@ -21,11 +21,12 @@ class BaseCoreplexConfig extends Config ((site, here, up) => {
|
|||||||
case XLen => 64 // Applies to all cores
|
case XLen => 64 // Applies to all cores
|
||||||
case ResetVectorBits => site(PAddrBits)
|
case ResetVectorBits => site(PAddrBits)
|
||||||
case MaxHartIdBits => log2Up(site(NTiles))
|
case MaxHartIdBits => log2Up(site(NTiles))
|
||||||
case MaxPriorityLevels => 7
|
|
||||||
case BuildCore => (p: Parameters) => new Rocket()(p)
|
case BuildCore => (p: Parameters) => new Rocket()(p)
|
||||||
case RocketCrossing => SynchronousCrossing()
|
case RocketCrossing => SynchronousCrossing()
|
||||||
case RocketTilesKey => Nil
|
case RocketTilesKey => Nil
|
||||||
case DMKey => DefaultDebugModuleConfig(site(XLen))
|
case DMKey => DefaultDebugModuleConfig(site(XLen))
|
||||||
|
case PLICKey => PLICParams()
|
||||||
|
case ClintKey => ClintParams()
|
||||||
case NTiles => site(RocketTilesKey).size
|
case NTiles => site(RocketTilesKey).size
|
||||||
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
|
||||||
|
@ -13,46 +13,40 @@ trait CoreplexNetwork extends HasCoreplexParameters {
|
|||||||
val module: CoreplexNetworkModule
|
val module: CoreplexNetworkModule
|
||||||
def bindingTree: ResourceMap
|
def bindingTree: ResourceMap
|
||||||
|
|
||||||
val tile_splitter = LazyModule(new TLSplitter)
|
// TODO: do we need one of these? val cbus = LazyModule(new TLXbar) // Locally-visible peripheral devices
|
||||||
|
val sbus = LazyModule(new TLXbar) // Globally-visible high-bandwidth devices
|
||||||
|
val pbus = LazyModule(new TLXbar) // Globally-visible low-bandwidth devices
|
||||||
|
val tile_splitter = LazyModule(new TLSplitter) // Allows cycle-free connection to external networks
|
||||||
|
val int_xbar = LazyModule(new IntXbar) // Interrupt crossbar
|
||||||
|
|
||||||
val l1tol2 = LazyModule(new TLXbar)
|
val mmio = TLOutputNode() // Exernal memory-mapped IO slaves
|
||||||
val l1tol2_beatBytes = l1tol2Config.beatBytes
|
val mmioInt = IntInputNode() // Exernal devices' interrupts
|
||||||
val l1tol2_lineBytes = p(CacheBlockBytes)
|
val l2in = TLInputNode() // External masters talking to the frontside of the shared cache
|
||||||
|
val l2out = TLOutputNode() // External slaves hanging off the backside of the shared cache
|
||||||
|
|
||||||
val cbus = LazyModule(new TLXbar)
|
int_xbar.intnode := mmioInt
|
||||||
val cbus_beatBytes = cbusConfig.beatBytes
|
|
||||||
val cbus_lineBytes = l1tol2_lineBytes
|
|
||||||
|
|
||||||
val intBar = LazyModule(new IntXbar)
|
|
||||||
|
|
||||||
val mmio = TLOutputNode()
|
|
||||||
val mmioInt = IntInputNode()
|
|
||||||
val l2in = TLInputNode()
|
|
||||||
val l2out = TLOutputNode()
|
|
||||||
|
|
||||||
intBar.intnode := mmioInt
|
|
||||||
|
|
||||||
// Allows a variable number of inputs from outside to the Xbar
|
// Allows a variable number of inputs from outside to the Xbar
|
||||||
private val l2in_buffer = LazyModule(new TLBuffer)
|
private val l2in_buffer = LazyModule(new TLBuffer)
|
||||||
private val l2in_fifo = LazyModule(new TLFIFOFixer)
|
private val l2in_fifo = LazyModule(new TLFIFOFixer)
|
||||||
l1tol2.node :=* l2in_fifo.node
|
sbus.node :=* l2in_fifo.node
|
||||||
l1tol2.node :=* tile_splitter.node
|
sbus.node :=* tile_splitter.node
|
||||||
l2in_fifo.node :=* l2in_buffer.node
|
l2in_fifo.node :=* l2in_buffer.node
|
||||||
l2in_buffer.node :=* l2in
|
l2in_buffer.node :=* l2in
|
||||||
|
|
||||||
private val l2out_buffer = LazyModule(new TLBuffer(BufferParams.flow, BufferParams.none))
|
private val l2out_buffer = LazyModule(new TLBuffer(BufferParams.flow, BufferParams.none))
|
||||||
l2out :*= l2out_buffer.node
|
l2out :*= l2out_buffer.node
|
||||||
l2out_buffer.node :*= l1tol2.node
|
l2out_buffer.node :*= sbus.node
|
||||||
|
|
||||||
cbus.node :=
|
pbus.node :=
|
||||||
TLBuffer()(
|
TLBuffer()(
|
||||||
TLAtomicAutomata(arithmetic = true)( // disable once TLB uses TL2 metadata
|
TLAtomicAutomata(arithmetic = true)( // disable once TLB uses TL2 metadata
|
||||||
TLWidthWidget(l1tol2_beatBytes)(
|
TLWidthWidget(sbusBeatBytes)(
|
||||||
l1tol2.node)))
|
sbus.node)))
|
||||||
|
|
||||||
mmio :=
|
mmio :=
|
||||||
TLWidthWidget(l1tol2_beatBytes)(
|
TLWidthWidget(sbusBeatBytes)(
|
||||||
l1tol2.node)
|
sbus.node)
|
||||||
|
|
||||||
val root = new Device {
|
val root = new Device {
|
||||||
def describe(resources: ResourceBindings): Description = {
|
def describe(resources: ResourceBindings): Description = {
|
||||||
@ -168,16 +162,16 @@ trait BankedL2CoherenceManagers extends CoreplexNetwork {
|
|||||||
|
|
||||||
require (isPow2(l2Config.nMemoryChannels) || l2Config.nMemoryChannels == 0)
|
require (isPow2(l2Config.nMemoryChannels) || l2Config.nMemoryChannels == 0)
|
||||||
require (isPow2(l2Config.nBanksPerChannel))
|
require (isPow2(l2Config.nBanksPerChannel))
|
||||||
require (isPow2(l1tol2_lineBytes))
|
require (isPow2(sbusBlockBytes))
|
||||||
|
|
||||||
private val (in, out) = l2Config.coherenceManager(p, this)
|
private val (in, out) = l2Config.coherenceManager(p, this)
|
||||||
private val mask = ~BigInt((l2Config.nBanks-1) * l1tol2_lineBytes)
|
private val mask = ~BigInt((l2Config.nBanks-1) * sbusBlockBytes)
|
||||||
val mem = Seq.tabulate(l2Config.nMemoryChannels) { channel =>
|
val mem = Seq.tabulate(l2Config.nMemoryChannels) { channel =>
|
||||||
val node = TLOutputNode()
|
val node = TLOutputNode()
|
||||||
for (bank <- 0 until l2Config.nBanksPerChannel) {
|
for (bank <- 0 until l2Config.nBanksPerChannel) {
|
||||||
val offset = (bank * l2Config.nMemoryChannels) + channel
|
val offset = (bank * l2Config.nMemoryChannels) + channel
|
||||||
in := l1tol2.node
|
in := sbus.node
|
||||||
node := TLFilter(AddressSet(offset * l1tol2_lineBytes, mask))(out)
|
node := TLFilter(AddressSet(offset * sbusBlockBytes, mask))(out)
|
||||||
}
|
}
|
||||||
node
|
node
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ trait HasISPPort extends CoreplexNetwork {
|
|||||||
|
|
||||||
private val in_async = LazyModule(new TLAsyncCrossingSink)
|
private val in_async = LazyModule(new TLAsyncCrossingSink)
|
||||||
in_async.node :=* isp_in
|
in_async.node :=* isp_in
|
||||||
l1tol2.node :=* in_async.node
|
sbus.node :=* in_async.node
|
||||||
}
|
}
|
||||||
|
|
||||||
trait HasISPPortBundle extends CoreplexNetworkBundle {
|
trait HasISPPortBundle extends CoreplexNetworkBundle {
|
||||||
|
@ -10,20 +10,23 @@ import uncore.tilelink2._
|
|||||||
import uncore.devices._
|
import uncore.devices._
|
||||||
import util._
|
import util._
|
||||||
|
|
||||||
case object MaxPriorityLevels extends Field[Int]
|
/** Number of tiles */
|
||||||
|
case object NTiles extends Field[Int]
|
||||||
|
case object PLICKey extends Field[PLICParams]
|
||||||
|
case object ClintKey extends Field[ClintParams]
|
||||||
|
|
||||||
trait CoreplexRISCVPlatform extends CoreplexNetwork {
|
trait CoreplexRISCVPlatform extends CoreplexNetwork {
|
||||||
val module: CoreplexRISCVPlatformModule
|
val module: CoreplexRISCVPlatformModule
|
||||||
|
|
||||||
val debug = LazyModule(new TLDebugModule())
|
val debug = LazyModule(new TLDebugModule())
|
||||||
val plic = LazyModule(new TLPLIC(maxPriorities = p(MaxPriorityLevels)))
|
debug.node := TLFragmenter(pbusBeatBytes, pbusBlockBytes)(pbus.node)
|
||||||
val clint = LazyModule(new CoreplexLocalInterrupter)
|
|
||||||
|
|
||||||
debug.node := TLFragmenter(cbus_beatBytes, cbus_lineBytes)(cbus.node)
|
val plic = LazyModule(new TLPLIC(p(PLICKey)))
|
||||||
plic.node := TLFragmenter(cbus_beatBytes, cbus_lineBytes)(cbus.node)
|
plic.node := TLFragmenter(pbusBeatBytes, pbusBlockBytes)(pbus.node)
|
||||||
clint.node := TLFragmenter(cbus_beatBytes, cbus_lineBytes)(cbus.node)
|
plic.intnode := int_xbar.intnode
|
||||||
|
|
||||||
plic.intnode := intBar.intnode
|
val clint = LazyModule(new CoreplexLocalInterrupter(nTiles, p(ClintKey)))
|
||||||
|
clint.node := TLFragmenter(pbusBeatBytes, pbusBlockBytes)(pbus.node)
|
||||||
|
|
||||||
lazy val dts = DTS(bindingTree)
|
lazy val dts = DTS(bindingTree)
|
||||||
lazy val dtb = DTB(dts)
|
lazy val dtb = DTB(dts)
|
||||||
|
@ -65,7 +65,7 @@ trait HasRocketTiles extends CoreplexRISCVPlatform {
|
|||||||
buffer.node :=* wrapper.masterNode
|
buffer.node :=* wrapper.masterNode
|
||||||
fixer.node :=* buffer.node
|
fixer.node :=* buffer.node
|
||||||
tile_splitter.node :=* fixer.node
|
tile_splitter.node :=* fixer.node
|
||||||
wrapper.slaveNode :*= cbus.node
|
wrapper.slaveNode :*= pbus.node
|
||||||
wrapper.asyncIntNode := asyncIntXbar.intnode
|
wrapper.asyncIntNode := asyncIntXbar.intnode
|
||||||
wrapper.periphIntNode := periphIntXbar.intnode
|
wrapper.periphIntNode := periphIntXbar.intnode
|
||||||
wrapper.coreIntNode := coreIntXbar.intnode
|
wrapper.coreIntNode := coreIntXbar.intnode
|
||||||
@ -87,7 +87,7 @@ trait HasRocketTiles extends CoreplexRISCVPlatform {
|
|||||||
wrapper.asyncIntNode := asyncIntXbar.intnode
|
wrapper.asyncIntNode := asyncIntXbar.intnode
|
||||||
wrapper.periphIntNode := periphIntXbar.intnode
|
wrapper.periphIntNode := periphIntXbar.intnode
|
||||||
wrapper.coreIntNode := coreIntXbar.intnode
|
wrapper.coreIntNode := coreIntXbar.intnode
|
||||||
source.node :*= cbus.node
|
source.node :*= pbus.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
|
||||||
@ -107,7 +107,7 @@ trait HasRocketTiles extends CoreplexRISCVPlatform {
|
|||||||
wrapper.asyncIntNode := asyncIntXbar.intnode
|
wrapper.asyncIntNode := asyncIntXbar.intnode
|
||||||
wrapper.periphIntNode := periphIntXbar.intnode
|
wrapper.periphIntNode := periphIntXbar.intnode
|
||||||
wrapper.coreIntNode := coreIntXbar.intnode
|
wrapper.coreIntNode := coreIntXbar.intnode
|
||||||
source.node :*= cbus.node
|
source.node :*= pbus.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
|
||||||
|
@ -10,7 +10,6 @@ import uncore.tilelink._
|
|||||||
import uncore.coherence._
|
import uncore.coherence._
|
||||||
import uncore.agents._
|
import uncore.agents._
|
||||||
import uncore.util._
|
import uncore.util._
|
||||||
import uncore.devices.NTiles
|
|
||||||
import tile.TileKey
|
import tile.TileKey
|
||||||
import junctions._
|
import junctions._
|
||||||
import config._
|
import config._
|
||||||
|
@ -44,8 +44,8 @@ class GroundTestCoreplex(implicit p: Parameters) extends BaseCoreplex {
|
|||||||
tile_splitter.node :=* fixer.node
|
tile_splitter.node :=* fixer.node
|
||||||
tiles.foreach { fixer.node :=* _.masterNode }
|
tiles.foreach { fixer.node :=* _.masterNode }
|
||||||
|
|
||||||
val cbusRAM = LazyModule(new TLRAM(AddressSet(testRamAddr, 0xffff), false, cbus_beatBytes))
|
val pbusRAM = LazyModule(new TLRAM(AddressSet(testRamAddr, 0xffff), false, pbusBlockBytes))
|
||||||
cbusRAM.node := TLFragmenter(cbus_beatBytes, cbus_lineBytes)(cbus.node)
|
pbusRAM.node := TLFragmenter(pbusBeatBytes, pbusBlockBytes)(pbus.node)
|
||||||
|
|
||||||
override lazy val module = new GroundTestCoreplexModule(this, () => new GroundTestCoreplexBundle(this))
|
override lazy val module = new GroundTestCoreplexModule(this, () => new GroundTestCoreplexBundle(this))
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ package groundtest
|
|||||||
import Chisel._
|
import Chisel._
|
||||||
import uncore.tilelink._
|
import uncore.tilelink._
|
||||||
import uncore.constants._
|
import uncore.constants._
|
||||||
import uncore.devices.NTiles
|
import coreplex.NTiles
|
||||||
import rocket._
|
import rocket._
|
||||||
import tile._
|
import tile._
|
||||||
import util.{Timer, DynamicTimer}
|
import util.{Timer, DynamicTimer}
|
||||||
|
@ -5,7 +5,7 @@ package groundtest
|
|||||||
|
|
||||||
import Chisel._
|
import Chisel._
|
||||||
import uncore.tilelink._
|
import uncore.tilelink._
|
||||||
import uncore.devices.NTiles
|
import coreplex.NTiles
|
||||||
import uncore.constants._
|
import uncore.constants._
|
||||||
import junctions._
|
import junctions._
|
||||||
import rocket._
|
import rocket._
|
||||||
|
@ -14,9 +14,6 @@ import scala.math.{min,max}
|
|||||||
import config._
|
import config._
|
||||||
import tile.XLen
|
import tile.XLen
|
||||||
|
|
||||||
/** Number of tiles */
|
|
||||||
case object NTiles extends Field[Int]
|
|
||||||
|
|
||||||
object ClintConsts
|
object ClintConsts
|
||||||
{
|
{
|
||||||
def msipOffset(hart: Int) = hart * msipBytes
|
def msipOffset(hart: Int) = hart * msipBytes
|
||||||
@ -30,7 +27,12 @@ object ClintConsts
|
|||||||
def ints = 2
|
def ints = 2
|
||||||
}
|
}
|
||||||
|
|
||||||
class CoreplexLocalInterrupter(address: BigInt = 0x02000000)(implicit p: Parameters) extends LazyModule
|
case class ClintParams(baseAddress: BigInt = 0x02000000)
|
||||||
|
{
|
||||||
|
def address = AddressSet(baseAddress, ClintConsts.size-1)
|
||||||
|
}
|
||||||
|
|
||||||
|
class CoreplexLocalInterrupter(nTiles: Int, params: ClintParams)(implicit p: Parameters) extends LazyModule
|
||||||
{
|
{
|
||||||
import ClintConsts._
|
import ClintConsts._
|
||||||
|
|
||||||
@ -40,7 +42,7 @@ class CoreplexLocalInterrupter(address: BigInt = 0x02000000)(implicit p: Paramet
|
|||||||
}
|
}
|
||||||
|
|
||||||
val node = TLRegisterNode(
|
val node = TLRegisterNode(
|
||||||
address = Seq(AddressSet(address, size-1)),
|
address = Seq(params.address),
|
||||||
device = device,
|
device = device,
|
||||||
beatBytes = p(XLen)/8)
|
beatBytes = p(XLen)/8)
|
||||||
|
|
||||||
@ -64,8 +66,8 @@ class CoreplexLocalInterrupter(address: BigInt = 0x02000000)(implicit p: Paramet
|
|||||||
reg := newTime >> i
|
reg := newTime >> i
|
||||||
}
|
}
|
||||||
|
|
||||||
val timecmp = Seq.fill(p(NTiles)) { Seq.fill(timeWidth/regWidth)(Reg(UInt(width = regWidth))) }
|
val timecmp = Seq.fill(nTiles) { Seq.fill(timeWidth/regWidth)(Reg(UInt(width = regWidth))) }
|
||||||
val ipi = Seq.fill(p(NTiles)) { RegInit(UInt(0, width = 1)) }
|
val ipi = Seq.fill(nTiles) { RegInit(UInt(0, width = 1)) }
|
||||||
|
|
||||||
io.int.zipWithIndex.foreach { case (int, i) =>
|
io.int.zipWithIndex.foreach { case (int, i) =>
|
||||||
int(0) := ipi(i)(0) // msip
|
int(0) := ipi(i)(0) // msip
|
||||||
|
@ -53,11 +53,15 @@ object PLICConsts
|
|||||||
require(hartBase >= enableBase(maxHarts))
|
require(hartBase >= enableBase(maxHarts))
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Platform-Level Interrupt Controller */
|
case class PLICParams(baseAddress: BigInt = 0xC000000, maxPriorities: Int = 7)
|
||||||
class TLPLIC(maxPriorities: Int, address: BigInt = 0xC000000)(implicit p: Parameters) extends LazyModule
|
|
||||||
{
|
{
|
||||||
require (maxPriorities >= 0)
|
require (maxPriorities >= 0)
|
||||||
|
def address = AddressSet(baseAddress, PLICConsts.size-1)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Platform-Level Interrupt Controller */
|
||||||
|
class TLPLIC(params: PLICParams)(implicit p: Parameters) extends LazyModule
|
||||||
|
{
|
||||||
// plic0 => max devices 1023
|
// plic0 => max devices 1023
|
||||||
val device = new SimpleDevice("interrupt-controller", Seq("riscv,plic0")) {
|
val device = new SimpleDevice("interrupt-controller", Seq("riscv,plic0")) {
|
||||||
override val alwaysExtended = true
|
override val alwaysExtended = true
|
||||||
@ -73,7 +77,7 @@ class TLPLIC(maxPriorities: Int, address: BigInt = 0xC000000)(implicit p: Parame
|
|||||||
}
|
}
|
||||||
|
|
||||||
val node = TLRegisterNode(
|
val node = TLRegisterNode(
|
||||||
address = Seq(AddressSet(address, PLICConsts.size-1)),
|
address = Seq(params.address),
|
||||||
device = device,
|
device = device,
|
||||||
beatBytes = p(XLen)/8,
|
beatBytes = p(XLen)/8,
|
||||||
undefZero = false,
|
undefZero = false,
|
||||||
@ -87,7 +91,7 @@ class TLPLIC(maxPriorities: Int, address: BigInt = 0xC000000)(implicit p: Parame
|
|||||||
|
|
||||||
/* Negotiated sizes */
|
/* Negotiated sizes */
|
||||||
def nDevices: Int = intnode.edgesIn.map(_.source.num).sum
|
def nDevices: Int = intnode.edgesIn.map(_.source.num).sum
|
||||||
def nPriorities = min(maxPriorities, nDevices)
|
def nPriorities = min(params.maxPriorities, nDevices)
|
||||||
def nHarts = intnode.edgesOut.map(_.source.num).sum
|
def nHarts = intnode.edgesOut.map(_.source.num).sum
|
||||||
|
|
||||||
// Assign all the devices unique ranges
|
// Assign all the devices unique ranges
|
||||||
|
Loading…
Reference in New Issue
Block a user