compartmentalize Top into periphery traits
This commit is contained in:
parent
8536a2a47d
commit
2c000a99da
@ -165,7 +165,6 @@ class BasePlatformConfig extends Config (
|
|||||||
case ConfigString => makeConfigString()
|
case ConfigString => makeConfigString()
|
||||||
case GlobalAddrMap => globalAddrMap
|
case GlobalAddrMap => globalAddrMap
|
||||||
case RTCPeriod => 100 // gives 10 MHz RTC assuming 1 GHz uncore clock
|
case RTCPeriod => 100 // gives 10 MHz RTC assuming 1 GHz uncore clock
|
||||||
case RTCTick => (p: Parameters, t_io: Bundle, p_io:Bundle) => Counter(p(RTCPeriod)).inc()
|
|
||||||
case _ => throw new CDEMatchError
|
case _ => throw new CDEMatchError
|
||||||
}})
|
}})
|
||||||
|
|
||||||
|
276
src/main/scala/rocketchip/Periphery.scala
Normal file
276
src/main/scala/rocketchip/Periphery.scala
Normal file
@ -0,0 +1,276 @@
|
|||||||
|
// See LICENSE for license details.
|
||||||
|
|
||||||
|
package rocketchip
|
||||||
|
|
||||||
|
import Chisel._
|
||||||
|
import cde.{Parameters, Field}
|
||||||
|
import junctions._
|
||||||
|
import uncore.tilelink._
|
||||||
|
import uncore.tilelink2.{LazyModule, LazyModuleImp}
|
||||||
|
import uncore.converters._
|
||||||
|
import uncore.devices._
|
||||||
|
import uncore.util._
|
||||||
|
import rocket.Util._
|
||||||
|
import coreplex._
|
||||||
|
|
||||||
|
/** Options for memory bus interface */
|
||||||
|
object BusType {
|
||||||
|
sealed trait EnumVal
|
||||||
|
case object AXI extends EnumVal
|
||||||
|
case object AHB extends EnumVal
|
||||||
|
case object TL extends EnumVal
|
||||||
|
val busTypes = Seq(AXI, AHB, TL)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Memory channel controls */
|
||||||
|
case object TMemoryChannels extends Field[BusType.EnumVal]
|
||||||
|
/** External MMIO controls */
|
||||||
|
case object NExtMMIOAXIChannels extends Field[Int]
|
||||||
|
case object NExtMMIOAHBChannels extends Field[Int]
|
||||||
|
case object NExtMMIOTLChannels extends Field[Int]
|
||||||
|
/** External Bus controls */
|
||||||
|
case object NExtBusAXIChannels extends Field[Int]
|
||||||
|
/** Async configurations */
|
||||||
|
case object AsyncBusChannels extends Field[Boolean]
|
||||||
|
case object AsyncDebugBus extends Field[Boolean]
|
||||||
|
case object AsyncMemChannels extends Field[Boolean]
|
||||||
|
case object AsyncMMIOChannels extends Field[Boolean]
|
||||||
|
/** External address map settings */
|
||||||
|
case object ExtMMIOPorts extends Field[Seq[AddrMapEntry]]
|
||||||
|
/** Function for building Coreplex */
|
||||||
|
case object BuildCoreplex extends Field[Parameters => Coreplex]
|
||||||
|
/** Function for connecting coreplex extra ports to top-level extra ports */
|
||||||
|
case object ConnectExtraPorts extends Field[(Bundle, Bundle, Parameters) => Unit]
|
||||||
|
/** Specifies the size of external memory */
|
||||||
|
case object ExtMemSize extends Field[Long]
|
||||||
|
/** Specifies the actual sorce of External Interrupts as Top and Periphery.
|
||||||
|
* NExtInterrupts = NExtTopInterrupts + NExtPeripheryInterrupts
|
||||||
|
**/
|
||||||
|
case object NExtTopInterrupts extends Field[Int]
|
||||||
|
case object NExtPeripheryInterrupts extends Field[Int]
|
||||||
|
/** Source of RTC. First bundle is TopIO.extra, Second bundle is periphery.io.extra **/
|
||||||
|
case object RTCPeriod extends Field[Int]
|
||||||
|
|
||||||
|
object PeripheryUtils {
|
||||||
|
def addQueueAXI(source: NastiIO)(implicit p: Parameters) = {
|
||||||
|
val sink = Wire(new NastiIO)
|
||||||
|
sink.ar <> Queue(source.ar, 1)
|
||||||
|
sink.aw <> Queue(source.aw, 1)
|
||||||
|
sink.w <> Queue(source.w)
|
||||||
|
source.r <> Queue(sink.r)
|
||||||
|
source.b <> Queue(sink.b, 1)
|
||||||
|
sink
|
||||||
|
}
|
||||||
|
def convertTLtoAXI(tl: ClientUncachedTileLinkIO)(implicit p: Parameters) = {
|
||||||
|
val bridge = Module(new NastiIOTileLinkIOConverter())
|
||||||
|
bridge.io.tl <> tl
|
||||||
|
addQueueAXI(bridge.io.nasti)
|
||||||
|
}
|
||||||
|
def convertTLtoAHB(tl: ClientUncachedTileLinkIO, atomics: Boolean)(implicit p: Parameters) = {
|
||||||
|
val bridge = Module(new AHBBridge(atomics))
|
||||||
|
bridge.io.tl <> tl
|
||||||
|
bridge.io.ahb
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Utility trait for quick access to some relevant parameters */
|
||||||
|
trait HasPeripheryParameters {
|
||||||
|
implicit val p: Parameters
|
||||||
|
lazy val tMemChannels = p(TMemoryChannels)
|
||||||
|
lazy val nMemChannels = p(NMemoryChannels)
|
||||||
|
lazy val nMemAXIChannels = if (tMemChannels == BusType.AXI) nMemChannels else 0
|
||||||
|
lazy val nMemAHBChannels = if (tMemChannels == BusType.AHB) nMemChannels else 0
|
||||||
|
lazy val nMemTLChannels = if (tMemChannels == BusType.TL) nMemChannels else 0
|
||||||
|
lazy val innerParams = p.alterPartial({ case TLId => "L1toL2" })
|
||||||
|
lazy val innerMMIOParams = p.alterPartial({ case TLId => "L2toMMIO" })
|
||||||
|
lazy val outermostParams = p.alterPartial({ case TLId => "Outermost" })
|
||||||
|
lazy val outermostMMIOParams = p.alterPartial({ case TLId => "MMIO_Outermost" })
|
||||||
|
}
|
||||||
|
|
||||||
|
/////
|
||||||
|
|
||||||
|
trait PeripheryDebug extends LazyModule {
|
||||||
|
implicit val p: Parameters
|
||||||
|
}
|
||||||
|
|
||||||
|
trait PeripheryDebugBundle {
|
||||||
|
implicit val p: Parameters
|
||||||
|
val debug_clk = (p(AsyncDebugBus) && !p(IncludeJtagDTM)).option(Clock(INPUT))
|
||||||
|
val debug_rst = (p(AsyncDebugBus) && !p(IncludeJtagDTM)).option(Bool(INPUT))
|
||||||
|
val debug = (!p(IncludeJtagDTM)).option(new DebugBusIO()(p).flip)
|
||||||
|
val jtag = p(IncludeJtagDTM).option(new JTAGIO(true).flip)
|
||||||
|
}
|
||||||
|
|
||||||
|
trait PeripheryDebugModule {
|
||||||
|
implicit val p: Parameters
|
||||||
|
val outer: PeripheryDebug
|
||||||
|
val io: PeripheryDebugBundle
|
||||||
|
val coreplex: Coreplex
|
||||||
|
|
||||||
|
if (p(IncludeJtagDTM)) {
|
||||||
|
// JtagDTMWithSync is a wrapper which
|
||||||
|
// handles the synchronization as well.
|
||||||
|
val dtm = Module (new JtagDTMWithSync()(p))
|
||||||
|
dtm.io.jtag <> io.jtag.get
|
||||||
|
coreplex.io.debug <> dtm.io.debug
|
||||||
|
} else {
|
||||||
|
coreplex.io.debug <>
|
||||||
|
(if (p(AsyncDebugBus)) AsyncDebugBusFrom(io.debug_clk.get, io.debug_rst.get, io.debug.get)
|
||||||
|
else io.debug.get)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/////
|
||||||
|
|
||||||
|
trait PeripheryInterrupt extends LazyModule {
|
||||||
|
implicit val p: Parameters
|
||||||
|
}
|
||||||
|
|
||||||
|
trait PeripheryInterruptBundle {
|
||||||
|
implicit val p: Parameters
|
||||||
|
val interrupts = Vec(p(NExtTopInterrupts), Bool()).asInput
|
||||||
|
}
|
||||||
|
|
||||||
|
trait PeripheryInterruptModule {
|
||||||
|
implicit val p: Parameters
|
||||||
|
val outer: PeripheryInterrupt
|
||||||
|
val io: PeripheryInterruptBundle
|
||||||
|
val coreplex: Coreplex
|
||||||
|
|
||||||
|
val interrupts_periphery = Vec(p(NExtPeripheryInterrupts), Bool())
|
||||||
|
var interrupts_cnt = 0
|
||||||
|
|
||||||
|
// This places the Periphery Interrupts at Bits [0...]
|
||||||
|
// External interrupts are at the higher Bits.
|
||||||
|
// This may have some implications for prioritization of the interrupts,
|
||||||
|
// but PLIC could do some internal swizzling in the future.
|
||||||
|
coreplex.io.interrupts <> (interrupts_periphery ++ io.interrupts)
|
||||||
|
}
|
||||||
|
|
||||||
|
/////
|
||||||
|
|
||||||
|
trait PeripheryMasterMem extends LazyModule {
|
||||||
|
implicit val p: Parameters
|
||||||
|
}
|
||||||
|
|
||||||
|
trait PeripheryMasterMemBundle extends HasPeripheryParameters {
|
||||||
|
implicit val p: Parameters
|
||||||
|
val mem_clk = p(AsyncMemChannels).option(Vec(nMemChannels, Clock(INPUT)))
|
||||||
|
val mem_rst = p(AsyncMemChannels).option(Vec(nMemChannels, Bool (INPUT)))
|
||||||
|
val mem_axi = Vec(nMemAXIChannels, new NastiIO)
|
||||||
|
val mem_ahb = Vec(nMemAHBChannels, new HastiMasterIO)
|
||||||
|
val mem_tl = Vec(nMemTLChannels, new ClientUncachedTileLinkIO()(outermostParams))
|
||||||
|
}
|
||||||
|
|
||||||
|
trait PeripheryMasterMemModule extends HasPeripheryParameters {
|
||||||
|
implicit val p: Parameters
|
||||||
|
val outer: PeripheryMasterMem
|
||||||
|
val io: PeripheryMasterMemBundle
|
||||||
|
val coreplex: Coreplex
|
||||||
|
|
||||||
|
// Abuse the fact that zip takes the shorter of the two lists
|
||||||
|
((io.mem_axi zip coreplex.io.mem) zipWithIndex) foreach { case ((axi, mem), idx) =>
|
||||||
|
val axi_sync = PeripheryUtils.convertTLtoAXI(mem)(outermostParams)
|
||||||
|
axi_sync.ar.bits.cache := UInt("b0011")
|
||||||
|
axi_sync.aw.bits.cache := UInt("b0011")
|
||||||
|
axi <> (
|
||||||
|
if (!p(AsyncMemChannels)) axi_sync
|
||||||
|
else AsyncNastiTo(io.mem_clk.get(idx), io.mem_rst.get(idx), axi_sync)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
(io.mem_ahb zip coreplex.io.mem) foreach { case (ahb, mem) =>
|
||||||
|
ahb <> PeripheryUtils.convertTLtoAHB(mem, atomics = false)(outermostParams)
|
||||||
|
}
|
||||||
|
|
||||||
|
(io.mem_tl zip coreplex.io.mem) foreach { case (tl, mem) =>
|
||||||
|
tl <> ClientUncachedTileLinkEnqueuer(mem, 2)(outermostParams)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/////
|
||||||
|
|
||||||
|
trait PeripheryMasterMMIO extends LazyModule {
|
||||||
|
implicit val p: Parameters
|
||||||
|
}
|
||||||
|
|
||||||
|
trait PeripheryMasterMMIOBundle extends HasPeripheryParameters {
|
||||||
|
implicit val p: Parameters
|
||||||
|
val mmio_clk = p(AsyncMMIOChannels).option(Vec(p(NExtMMIOAXIChannels), Clock(INPUT)))
|
||||||
|
val mmio_rst = p(AsyncMMIOChannels).option(Vec(p(NExtMMIOAXIChannels), Bool (INPUT)))
|
||||||
|
val mmio_axi = Vec(p(NExtMMIOAXIChannels), new NastiIO)
|
||||||
|
val mmio_ahb = Vec(p(NExtMMIOAHBChannels), new HastiMasterIO)
|
||||||
|
val mmio_tl = Vec(p(NExtMMIOTLChannels), new ClientUncachedTileLinkIO()(outermostMMIOParams))
|
||||||
|
}
|
||||||
|
|
||||||
|
trait PeripheryMasterMMIOModule extends HasPeripheryParameters {
|
||||||
|
implicit val p: Parameters
|
||||||
|
val outer: PeripheryMasterMMIO
|
||||||
|
val io: PeripheryMasterMMIOBundle
|
||||||
|
val mmioNetwork: Option[TileLinkRecursiveInterconnect]
|
||||||
|
|
||||||
|
val mmio_ports = p(ExtMMIOPorts) map { port =>
|
||||||
|
TileLinkWidthAdapter(mmioNetwork.get.port(port.name), "MMIO_Outermost")
|
||||||
|
}
|
||||||
|
|
||||||
|
val mmio_axi_start = 0
|
||||||
|
val mmio_axi_end = mmio_axi_start + p(NExtMMIOAXIChannels)
|
||||||
|
val mmio_ahb_start = mmio_axi_end
|
||||||
|
val mmio_ahb_end = mmio_ahb_start + p(NExtMMIOAHBChannels)
|
||||||
|
val mmio_tl_start = mmio_ahb_end
|
||||||
|
val mmio_tl_end = mmio_tl_start + p(NExtMMIOTLChannels)
|
||||||
|
require (mmio_tl_end == mmio_ports.size)
|
||||||
|
|
||||||
|
for (i <- 0 until mmio_ports.size) {
|
||||||
|
if (mmio_axi_start <= i && i < mmio_axi_end) {
|
||||||
|
val idx = i-mmio_axi_start
|
||||||
|
val axi_sync = PeripheryUtils.convertTLtoAXI(mmio_ports(i))(outermostMMIOParams)
|
||||||
|
io.mmio_axi(idx) <> (
|
||||||
|
if (!p(AsyncMMIOChannels)) axi_sync
|
||||||
|
else AsyncNastiTo(io.mmio_clk.get(idx), io.mmio_rst.get(idx), axi_sync)
|
||||||
|
)
|
||||||
|
} else if (mmio_ahb_start <= i && i < mmio_ahb_end) {
|
||||||
|
val idx = i-mmio_ahb_start
|
||||||
|
io.mmio_ahb(idx) <> PeripheryUtils.convertTLtoAHB(mmio_ports(i), atomics = true)(outermostMMIOParams)
|
||||||
|
} else if (mmio_tl_start <= i && i < mmio_tl_end) {
|
||||||
|
val idx = i-mmio_tl_start
|
||||||
|
io.mmio_tl(idx) <> ClientUncachedTileLinkEnqueuer(mmio_ports(i), 2)(outermostMMIOParams)
|
||||||
|
} else {
|
||||||
|
require(false, "Unconnected external MMIO port")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/////
|
||||||
|
|
||||||
|
trait PeripherySlave extends LazyModule {
|
||||||
|
implicit val p: Parameters
|
||||||
|
}
|
||||||
|
|
||||||
|
trait PeripherySlaveBundle extends HasPeripheryParameters {
|
||||||
|
implicit val p: Parameters
|
||||||
|
val bus_clk = p(AsyncBusChannels).option(Vec(p(NExtBusAXIChannels), Clock(INPUT)))
|
||||||
|
val bus_rst = p(AsyncBusChannels).option(Vec(p(NExtBusAXIChannels), Bool (INPUT)))
|
||||||
|
val bus_axi = Vec(p(NExtBusAXIChannels), new NastiIO).flip
|
||||||
|
}
|
||||||
|
|
||||||
|
trait PeripherySlaveModule extends HasPeripheryParameters {
|
||||||
|
implicit val p: Parameters
|
||||||
|
val outer: PeripherySlave
|
||||||
|
val io: PeripherySlaveBundle
|
||||||
|
val coreplex: Coreplex
|
||||||
|
|
||||||
|
if (p(NExtBusAXIChannels) > 0) {
|
||||||
|
val arb = Module(new NastiArbiter(p(NExtBusAXIChannels)))
|
||||||
|
((io.bus_axi zip arb.io.master) zipWithIndex) foreach { case ((bus, port), idx) =>
|
||||||
|
port <> (
|
||||||
|
if (!p(AsyncBusChannels)) bus
|
||||||
|
else AsyncNastiFrom(io.bus_clk.get(idx), io.bus_rst.get(idx), bus)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
val conv = Module(new TileLinkIONastiIOConverter()(innerParams))
|
||||||
|
conv.io.nasti <> arb.io.slave
|
||||||
|
coreplex.io.ext_clients.head <> conv.io.tl
|
||||||
|
require(p(NExternalClients) == 1, "external devices can't slave ports. wait for tilelink2!")
|
||||||
|
}
|
||||||
|
}
|
@ -1,307 +0,0 @@
|
|||||||
// See LICENSE for license details.
|
|
||||||
|
|
||||||
package rocketchip
|
|
||||||
|
|
||||||
import Chisel._
|
|
||||||
import cde.{Parameters, Field}
|
|
||||||
import junctions._
|
|
||||||
import uncore.tilelink._
|
|
||||||
import uncore.devices._
|
|
||||||
import uncore.util._
|
|
||||||
import rocket.Util._
|
|
||||||
import uncore.converters._
|
|
||||||
import uncore.coherence.{InnerTLId, OuterTLId}
|
|
||||||
import rocket._
|
|
||||||
import coreplex._
|
|
||||||
import scala.collection.immutable.HashMap
|
|
||||||
|
|
||||||
/** Top-level parameters of RocketChip, values set in e.g. PublicConfigs.scala */
|
|
||||||
|
|
||||||
/** Options for memory bus interface */
|
|
||||||
object BusType {
|
|
||||||
sealed trait EnumVal
|
|
||||||
case object AXI extends EnumVal
|
|
||||||
case object AHB extends EnumVal
|
|
||||||
case object TL extends EnumVal
|
|
||||||
val busTypes = Seq(AXI, AHB, TL)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Memory channel controls */
|
|
||||||
case object TMemoryChannels extends Field[BusType.EnumVal]
|
|
||||||
/** External MMIO controls */
|
|
||||||
case object NExtMMIOAXIChannels extends Field[Int]
|
|
||||||
case object NExtMMIOAHBChannels extends Field[Int]
|
|
||||||
case object NExtMMIOTLChannels extends Field[Int]
|
|
||||||
/** External Bus controls */
|
|
||||||
case object NExtBusAXIChannels extends Field[Int]
|
|
||||||
/** Async configurations */
|
|
||||||
case object AsyncBusChannels extends Field[Boolean]
|
|
||||||
case object AsyncDebugBus extends Field[Boolean]
|
|
||||||
case object AsyncMemChannels extends Field[Boolean]
|
|
||||||
case object AsyncMMIOChannels extends Field[Boolean]
|
|
||||||
/** External address map settings */
|
|
||||||
case object ExtMMIOPorts extends Field[Seq[AddrMapEntry]]
|
|
||||||
/** Function for building Coreplex */
|
|
||||||
case object BuildCoreplex extends Field[Parameters => Coreplex]
|
|
||||||
/** Function for connecting coreplex extra ports to top-level extra ports */
|
|
||||||
case object ConnectExtraPorts extends Field[(Bundle, Bundle, Parameters) => Unit]
|
|
||||||
/** Specifies the size of external memory */
|
|
||||||
case object ExtMemSize extends Field[Long]
|
|
||||||
/** Specifies the actual sorce of External Interrupts as Top and Periphery.
|
|
||||||
* NExtInterrupts = NExtTopInterrupts + NExtPeripheryInterrupts
|
|
||||||
**/
|
|
||||||
case object NExtTopInterrupts extends Field[Int]
|
|
||||||
case object NExtPeripheryInterrupts extends Field[Int]
|
|
||||||
/** Source of RTC. First bundle is TopIO.extra, Second bundle is periphery.io.extra **/
|
|
||||||
case object RTCTick extends Field[(Parameters, Bundle, Bundle) => Bool]
|
|
||||||
case object RTCPeriod extends Field[Int]
|
|
||||||
|
|
||||||
|
|
||||||
/** Utility trait for quick access to some relevant parameters */
|
|
||||||
trait HasTopLevelParameters {
|
|
||||||
implicit val p: Parameters
|
|
||||||
lazy val tMemChannels = p(TMemoryChannels)
|
|
||||||
lazy val nMemChannels = p(NMemoryChannels)
|
|
||||||
lazy val nMemAXIChannels = if (tMemChannels == BusType.AXI) nMemChannels else 0
|
|
||||||
lazy val nMemAHBChannels = if (tMemChannels == BusType.AHB) nMemChannels else 0
|
|
||||||
lazy val nMemTLChannels = if (tMemChannels == BusType.TL) nMemChannels else 0
|
|
||||||
lazy val innerParams = p.alterPartial({ case TLId => "L1toL2" })
|
|
||||||
lazy val outermostParams = p.alterPartial({ case TLId => "Outermost" })
|
|
||||||
lazy val outermostMMIOParams = p.alterPartial({ case TLId => "MMIO_Outermost" })
|
|
||||||
lazy val exportMMIO = p(ExportMMIOPort)
|
|
||||||
}
|
|
||||||
|
|
||||||
class MemBackupCtrlIO extends Bundle {
|
|
||||||
val en = Bool(INPUT)
|
|
||||||
val in_valid = Bool(INPUT)
|
|
||||||
val out_ready = Bool(INPUT)
|
|
||||||
val out_valid = Bool(OUTPUT)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Top-level io for the chip */
|
|
||||||
class BasicTopIO(implicit val p: Parameters) extends ParameterizedBundle()(p)
|
|
||||||
with HasTopLevelParameters
|
|
||||||
|
|
||||||
class TopIO(implicit p: Parameters) extends BasicTopIO()(p) {
|
|
||||||
val mem_clk = p(AsyncMemChannels).option(Vec(nMemChannels, Clock(INPUT)))
|
|
||||||
val mem_rst = p(AsyncMemChannels).option(Vec(nMemChannels, Bool (INPUT)))
|
|
||||||
val mem_axi = Vec(nMemAXIChannels, new NastiIO)
|
|
||||||
val mem_ahb = Vec(nMemAHBChannels, new HastiMasterIO)
|
|
||||||
val mem_tl = Vec(nMemTLChannels, new ClientUncachedTileLinkIO()(outermostParams))
|
|
||||||
val interrupts = Vec(p(NExtTopInterrupts), Bool()).asInput
|
|
||||||
val bus_clk = p(AsyncBusChannels).option(Vec(p(NExtBusAXIChannels), Clock(INPUT)))
|
|
||||||
val bus_rst = p(AsyncBusChannels).option(Vec(p(NExtBusAXIChannels), Bool (INPUT)))
|
|
||||||
val bus_axi = Vec(p(NExtBusAXIChannels), new NastiIO).flip
|
|
||||||
val mmio_clk = p(AsyncMMIOChannels).option(Vec(p(NExtMMIOAXIChannels), Clock(INPUT)))
|
|
||||||
val mmio_rst = p(AsyncMMIOChannels).option(Vec(p(NExtMMIOAXIChannels), Bool (INPUT)))
|
|
||||||
val mmio_axi = Vec(p(NExtMMIOAXIChannels), new NastiIO)
|
|
||||||
val mmio_ahb = Vec(p(NExtMMIOAHBChannels), new HastiMasterIO)
|
|
||||||
val mmio_tl = Vec(p(NExtMMIOTLChannels), new ClientUncachedTileLinkIO()(outermostMMIOParams))
|
|
||||||
val debug_clk = (p(AsyncDebugBus) && !p(IncludeJtagDTM)).option(Clock(INPUT))
|
|
||||||
val debug_rst = (p(AsyncDebugBus) && !p(IncludeJtagDTM)).option(Bool(INPUT))
|
|
||||||
val debug = (!p(IncludeJtagDTM)).option(new DebugBusIO()(p).flip)
|
|
||||||
val jtag = p(IncludeJtagDTM).option(new JTAGIO(true).flip)
|
|
||||||
val extra = p(ExtraTopPorts)(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
object TopUtils {
|
|
||||||
// Connect two Nasti interfaces with queues in-between
|
|
||||||
def connectNasti(outer: NastiIO, inner: NastiIO)(implicit p: Parameters) {
|
|
||||||
val mifDataBeats = p(MIFDataBeats)
|
|
||||||
outer.ar <> Queue(inner.ar, 1)
|
|
||||||
outer.aw <> Queue(inner.aw, 1)
|
|
||||||
outer.w <> Queue(inner.w)
|
|
||||||
inner.r <> Queue(outer.r)
|
|
||||||
inner.b <> Queue(outer.b, 1)
|
|
||||||
}
|
|
||||||
def connectTilelinkNasti(nasti: NastiIO, tl: ClientUncachedTileLinkIO)(implicit p: Parameters) = {
|
|
||||||
val conv = Module(new NastiIOTileLinkIOConverter())
|
|
||||||
conv.io.tl <> tl
|
|
||||||
TopUtils.connectNasti(nasti, conv.io.nasti)
|
|
||||||
}
|
|
||||||
def connectTilelinkAhb(ahb: HastiMasterIO, tl: ClientUncachedTileLinkIO)(implicit p: Parameters) = {
|
|
||||||
val bridge = Module(new AHBBridge(true))
|
|
||||||
bridge.io.tl <> tl
|
|
||||||
bridge.io.ahb
|
|
||||||
}
|
|
||||||
def connectTilelink(
|
|
||||||
outer: ClientUncachedTileLinkIO, inner: ClientUncachedTileLinkIO)(implicit p: Parameters) = {
|
|
||||||
outer.acquire <> Queue(inner.acquire)
|
|
||||||
inner.grant <> Queue(outer.grant)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Top-level module for the chip */
|
|
||||||
//TODO: Remove this wrapper once multichannel DRAM controller is provided
|
|
||||||
class Top(topParams: Parameters) extends Module with HasTopLevelParameters {
|
|
||||||
implicit val p = topParams
|
|
||||||
|
|
||||||
val coreplex = p(BuildCoreplex)(p)
|
|
||||||
val periphery = Module(new Periphery()(innerParams))
|
|
||||||
|
|
||||||
val io = new TopIO {
|
|
||||||
val success = coreplex.hasSuccessFlag.option(Bool(OUTPUT))
|
|
||||||
}
|
|
||||||
io.success zip coreplex.io.success map { case (x, y) => x := y }
|
|
||||||
|
|
||||||
if (exportMMIO) { periphery.io.mmio_in.get <> coreplex.io.mmio.get }
|
|
||||||
periphery.io.mem_in <> coreplex.io.mem
|
|
||||||
coreplex.io.ext_clients <> periphery.io.clients_out
|
|
||||||
|
|
||||||
if (p(IncludeJtagDTM)) {
|
|
||||||
// JtagDTMWithSync is a wrapper which
|
|
||||||
// handles the synchronization as well.
|
|
||||||
val jtag_dtm = Module (new JtagDTMWithSync()(p))
|
|
||||||
jtag_dtm.io.jtag <> io.jtag.get
|
|
||||||
coreplex.io.debug <> jtag_dtm.io.debug
|
|
||||||
} else {
|
|
||||||
coreplex.io.debug <>
|
|
||||||
(if (p(AsyncDebugBus))
|
|
||||||
AsyncDebugBusFrom(io.debug_clk.get, io.debug_rst.get, io.debug.get)
|
|
||||||
else io.debug.get)
|
|
||||||
}
|
|
||||||
|
|
||||||
def asyncAxiTo(clocks: Seq[Clock], resets: Seq[Bool], inner_axis: Seq[NastiIO]): Seq[NastiIO] =
|
|
||||||
(clocks, resets, inner_axis).zipped.map {
|
|
||||||
case (clk, rst, in_axi) => AsyncNastiTo(clk, rst, in_axi)
|
|
||||||
}
|
|
||||||
|
|
||||||
def asyncAxiFrom(clocks: Seq[Clock], resets: Seq[Bool], outer_axis: Seq[NastiIO]): Seq[NastiIO] =
|
|
||||||
(clocks, resets, outer_axis).zipped.map {
|
|
||||||
case (clk, rst, out_axi) => AsyncNastiFrom(clk, rst, out_axi)
|
|
||||||
}
|
|
||||||
|
|
||||||
io.mmio_axi <>
|
|
||||||
(if (p(AsyncMMIOChannels))
|
|
||||||
asyncAxiTo(io.mmio_clk.get, io.mmio_rst.get, periphery.io.mmio_axi)
|
|
||||||
else periphery.io.mmio_axi)
|
|
||||||
io.mmio_ahb <> periphery.io.mmio_ahb
|
|
||||||
io.mmio_tl <> periphery.io.mmio_tl
|
|
||||||
|
|
||||||
io.mem_axi <>
|
|
||||||
(if (p(AsyncMemChannels))
|
|
||||||
asyncAxiTo(io.mem_clk.get, io.mem_rst.get, periphery.io.mem_axi)
|
|
||||||
else periphery.io.mem_axi)
|
|
||||||
io.mem_ahb <> periphery.io.mem_ahb
|
|
||||||
io.mem_tl <> periphery.io.mem_tl
|
|
||||||
|
|
||||||
periphery.io.bus_axi <>
|
|
||||||
(if (p(AsyncBusChannels))
|
|
||||||
asyncAxiFrom(io.bus_clk.get, io.bus_rst.get, io.bus_axi)
|
|
||||||
else io.bus_axi)
|
|
||||||
|
|
||||||
// This places the Periphery Interrupts at Bits [0...]
|
|
||||||
// Top-level interrupts are at the higher Bits.
|
|
||||||
// This may have some implications for prioritization of the interrupts,
|
|
||||||
// but PLIC could do some internal swizzling in the future.
|
|
||||||
coreplex.io.interrupts <> (periphery.io.interrupts ++ io.interrupts)
|
|
||||||
|
|
||||||
io.extra <> periphery.io.extra
|
|
||||||
|
|
||||||
coreplex.io.rtcTick := p(RTCTick)(p, io.extra, periphery.io.extra)
|
|
||||||
|
|
||||||
p(ConnectExtraPorts)(io.extra, coreplex.io.extra, p)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class Periphery(implicit val p: Parameters) extends Module
|
|
||||||
with HasTopLevelParameters {
|
|
||||||
val io = new Bundle {
|
|
||||||
val mem_in = Vec(nMemChannels, new ClientUncachedTileLinkIO()(outermostParams)).flip
|
|
||||||
val clients_out = Vec(p(NExternalClients), new ClientUncachedTileLinkIO()(innerParams))
|
|
||||||
val mmio_in = exportMMIO.option(new ClientUncachedTileLinkIO()(outermostMMIOParams).flip)
|
|
||||||
val mem_axi = Vec(nMemAXIChannels, new NastiIO)
|
|
||||||
val mem_ahb = Vec(nMemAHBChannels, new HastiMasterIO)
|
|
||||||
val mem_tl = Vec(nMemTLChannels, new ClientUncachedTileLinkIO()(outermostParams))
|
|
||||||
val bus_axi = Vec(p(NExtBusAXIChannels), new NastiIO).flip
|
|
||||||
val mmio_axi = Vec(p(NExtMMIOAXIChannels), new NastiIO)
|
|
||||||
val mmio_ahb = Vec(p(NExtMMIOAHBChannels), new HastiMasterIO)
|
|
||||||
val mmio_tl = Vec(p(NExtMMIOTLChannels), new ClientUncachedTileLinkIO()(outermostMMIOParams))
|
|
||||||
val interrupts = Vec(p(NExtPeripheryInterrupts), Bool()).asOutput
|
|
||||||
val extra = p(ExtraTopPorts)(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (io.bus_axi.size > 0) {
|
|
||||||
val conv = Module(new TileLinkIONastiIOConverter)
|
|
||||||
val arb = Module(new NastiArbiter(io.bus_axi.size))
|
|
||||||
arb.io.master <> io.bus_axi
|
|
||||||
conv.io.nasti <> arb.io.slave
|
|
||||||
io.clients_out.head <> conv.io.tl
|
|
||||||
}
|
|
||||||
|
|
||||||
def connectExternalMMIO(ports: Seq[ClientUncachedTileLinkIO])(implicit p: Parameters) {
|
|
||||||
val mmio_axi_start = 0
|
|
||||||
val mmio_axi_end = mmio_axi_start + p(NExtMMIOAXIChannels)
|
|
||||||
val mmio_ahb_start = mmio_axi_end
|
|
||||||
val mmio_ahb_end = mmio_ahb_start + p(NExtMMIOAHBChannels)
|
|
||||||
val mmio_tl_start = mmio_ahb_end
|
|
||||||
val mmio_tl_end = mmio_tl_start + p(NExtMMIOTLChannels)
|
|
||||||
require (mmio_tl_end == ports.size)
|
|
||||||
|
|
||||||
for (i <- 0 until ports.size) {
|
|
||||||
if (mmio_axi_start <= i && i < mmio_axi_end) {
|
|
||||||
TopUtils.connectTilelinkNasti(io.mmio_axi(i-mmio_axi_start), ports(i))
|
|
||||||
} else if (mmio_ahb_start <= i && i < mmio_ahb_end) {
|
|
||||||
val ahbBridge = Module(new AHBBridge(true))
|
|
||||||
io.mmio_ahb(i-mmio_ahb_start) <> ahbBridge.io.ahb
|
|
||||||
ahbBridge.io.tl <> ports(i)
|
|
||||||
} else if (mmio_tl_start <= i && i < mmio_tl_end) {
|
|
||||||
TopUtils.connectTilelink(io.mmio_tl(i-mmio_tl_start), ports(i))
|
|
||||||
} else {
|
|
||||||
require(false, "Unconnected external MMIO port")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def buildMMIONetwork(implicit p: Parameters) = {
|
|
||||||
val extAddrMap = p(GlobalAddrMap).subMap("io:ext")
|
|
||||||
|
|
||||||
val mmioNetwork = Module(new TileLinkRecursiveInterconnect(1, extAddrMap))
|
|
||||||
mmioNetwork.io.in.head <> io.mmio_in.get
|
|
||||||
|
|
||||||
val extraDevices = p(ExtraDevices)
|
|
||||||
|
|
||||||
val deviceMMIO = HashMap.newBuilder[String, ClientUncachedTileLinkIO]
|
|
||||||
for ((entry, i) <- extraDevices.addrMapEntries.zipWithIndex)
|
|
||||||
deviceMMIO += (entry.name -> mmioNetwork.port(entry.name))
|
|
||||||
|
|
||||||
val deviceClients = if (io.bus_axi.size > 0) io.clients_out.tail else io.clients_out
|
|
||||||
require(deviceClients.size == extraDevices.nClientPorts)
|
|
||||||
|
|
||||||
val buildParams = p.alterPartial({
|
|
||||||
case InnerTLId => "L2toMMIO" // Device MMIO port
|
|
||||||
case OuterTLId => "L1toL2" // Device client port
|
|
||||||
})
|
|
||||||
|
|
||||||
extraDevices.builder(deviceMMIO.result(), deviceClients,
|
|
||||||
io.interrupts, io.extra, buildParams)
|
|
||||||
|
|
||||||
val ext = p(ExtMMIOPorts).map(
|
|
||||||
port => TileLinkWidthAdapter(mmioNetwork.port(port.name), "MMIO_Outermost"))
|
|
||||||
connectExternalMMIO(ext)(outermostMMIOParams)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (exportMMIO) {
|
|
||||||
buildMMIONetwork(p.alterPartial({case TLId => "L2toMMIO"}))
|
|
||||||
}
|
|
||||||
|
|
||||||
for ((nasti, tl) <- io.mem_axi zip io.mem_in) {
|
|
||||||
TopUtils.connectTilelinkNasti(nasti, tl)(outermostParams)
|
|
||||||
// Memory cache type should be normal non-cacheable bufferable
|
|
||||||
// TODO why is this happening here? Would 0000 (device) be OK instead?
|
|
||||||
nasti.ar.bits.cache := UInt("b0011")
|
|
||||||
nasti.aw.bits.cache := UInt("b0011")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Abuse the fact that zip takes the shorter of the two lists
|
|
||||||
for ((ahb, tl) <- io.mem_ahb zip io.mem_in) {
|
|
||||||
val bridge = Module(new AHBBridge(false)) // no atomics
|
|
||||||
ahb <> bridge.io.ahb
|
|
||||||
bridge.io.tl <> tl
|
|
||||||
}
|
|
||||||
|
|
||||||
for ((mem_tl, tl) <- io.mem_tl zip io.mem_in) {
|
|
||||||
TopUtils.connectTilelink(mem_tl, tl)
|
|
||||||
}
|
|
||||||
}
|
|
@ -11,7 +11,7 @@ class TestHarness(implicit p: Parameters) extends Module {
|
|||||||
val io = new Bundle {
|
val io = new Bundle {
|
||||||
val success = Bool(OUTPUT)
|
val success = Bool(OUTPUT)
|
||||||
}
|
}
|
||||||
val dut = Module(new Top(p))
|
val dut = uncore.tilelink2.LazyModule(new ExampleTop(p)).module
|
||||||
|
|
||||||
// This test harness isn't especially flexible yet
|
// This test harness isn't especially flexible yet
|
||||||
require(dut.io.mem_clk.isEmpty)
|
require(dut.io.mem_clk.isEmpty)
|
||||||
@ -24,7 +24,6 @@ class TestHarness(implicit p: Parameters) extends Module {
|
|||||||
require(dut.io.mmio_rst.isEmpty)
|
require(dut.io.mmio_rst.isEmpty)
|
||||||
require(dut.io.mmio_ahb.isEmpty)
|
require(dut.io.mmio_ahb.isEmpty)
|
||||||
require(dut.io.mmio_tl.isEmpty)
|
require(dut.io.mmio_tl.isEmpty)
|
||||||
require(dut.io.extra.elements.isEmpty)
|
|
||||||
|
|
||||||
for (int <- dut.io.interrupts)
|
for (int <- dut.io.interrupts)
|
||||||
int := false
|
int := false
|
||||||
|
51
src/main/scala/rocketchip/Top.scala
Normal file
51
src/main/scala/rocketchip/Top.scala
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
// See LICENSE for license details.
|
||||||
|
|
||||||
|
package rocketchip
|
||||||
|
|
||||||
|
import Chisel._
|
||||||
|
import cde.{Parameters}
|
||||||
|
import junctions._
|
||||||
|
import uncore.tilelink._
|
||||||
|
import uncore.tilelink2.{LazyModule, LazyModuleImp}
|
||||||
|
import rocket.Util._
|
||||||
|
import coreplex._
|
||||||
|
|
||||||
|
|
||||||
|
/** Base Top with no Periphery */
|
||||||
|
|
||||||
|
abstract class BaseTop(val p: Parameters) extends LazyModule
|
||||||
|
|
||||||
|
class BaseTopBundle(val p: Parameters, val c: Coreplex) extends ParameterizedBundle()(p) {
|
||||||
|
val success = c.hasSuccessFlag.option(Bool(OUTPUT))
|
||||||
|
}
|
||||||
|
|
||||||
|
class BaseTopModule[L <: BaseTop, B <: BaseTopBundle](val p: Parameters, l: L, b: Coreplex => B) extends LazyModuleImp(l) {
|
||||||
|
val coreplex = p(BuildCoreplex)(p)
|
||||||
|
val outer: L = l
|
||||||
|
val io: B = b(coreplex)
|
||||||
|
|
||||||
|
io.success zip coreplex.io.success map { case (x, y) => x := y }
|
||||||
|
coreplex.io.rtcTick := Counter(p(RTCPeriod)).inc()
|
||||||
|
|
||||||
|
val mmioNetwork = p(ExportMMIOPort).option(
|
||||||
|
Module(new TileLinkRecursiveInterconnect(1, p(GlobalAddrMap).subMap("io:ext"))(
|
||||||
|
p.alterPartial({ case TLId => "L2toMMIO" }))))
|
||||||
|
mmioNetwork.foreach { _.io.in.head <> coreplex.io.mmio.get }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Example Top with Periphery */
|
||||||
|
|
||||||
|
class ExampleTop(p: Parameters) extends BaseTop(p)
|
||||||
|
with PeripheryDebug with PeripheryInterrupt
|
||||||
|
with PeripheryMasterMem with PeripheryMasterMMIO with PeripherySlave {
|
||||||
|
lazy val module = Module(new ExampleTopModule(p, this, new ExampleTopBundle(p, _)))
|
||||||
|
}
|
||||||
|
|
||||||
|
class ExampleTopBundle(p: Parameters, c: Coreplex) extends BaseTopBundle(p, c)
|
||||||
|
with PeripheryDebugBundle with PeripheryInterruptBundle
|
||||||
|
with PeripheryMasterMemBundle with PeripheryMasterMMIOBundle with PeripherySlaveBundle
|
||||||
|
|
||||||
|
class ExampleTopModule[L <: ExampleTop, B <: ExampleTopBundle](p: Parameters, l: L, b: Coreplex => B) extends BaseTopModule(p, l, b)
|
||||||
|
with PeripheryDebugModule with PeripheryInterruptModule
|
||||||
|
with PeripheryMasterMemModule with PeripheryMasterMMIOModule with PeripherySlaveModule
|
Loading…
Reference in New Issue
Block a user