Thanks, Howard! I appreciate it.
A few more follow-up questions on the BusToplogy in LoopbackNICRocketConfig:
1. The loopback config has coherentBusTopology, which builds on top of the HierarchicalBusTopology in BaseSubSystemConfig — and adds a peripheral, control, and front bus for MMIO but then the config also removes any MMIO ports by adding WithNoMMIOPort and slave ports using WithNoSlavePorts. What’s the rationale behind this?
Note: Similarly, it also removes any external interrupts - WithNExtTopInterrupts(0). While we know that the NIC can trigger two interrupts, how does this work?
2. From what I’ve understood so far, the arbitration in TLXBar is effectively done by tracking the ReadyValidCancel interface of all the masters (sources), and the arbiter keeps track of earlyValids and validQuals.
Again, what’s the rationale behind picking earlyWinner and winnerQual separately, instead of just having a simple ReadyValid interface? Is it a performance optimization or critical to the core logic of the round-robin policy?
3. In terms of figuring out the inter-bus connects — in BusTopology.scala the three optional buses are connected in the following way:
(SBUS, CBUS, TLBusWrapperConnection.crossTo(xTypes.sbusToCbusXType)),
(CBUS, PBUS, TLBusWrapperConnection.crossTo(xTypes.cbusToPbusXType)),
(FBUS, SBUS, TLBusWrapperConnection.crossFrom(xTypes.fbusToSbusXType)))
3.1 What exactly is the role of the control bus in terms of acting as an intermediary between the system bus and peripheral bus? Also, what is the role of the fbus in MMIO and in the above config is it the master in the fbus to sbus connection?
3.2 I don’t precisely understand the role of xType. The code suggests that a TL clock crossing adapter between the buses, but if we look at the definitions, it seems like only a buffer depth varies between NoCrossing and SynchronousCrossing. And, what’s the role of the buffer here?
sbusToCbusXType: ClockCrossingType = NoCrossing, // buffer depth = 0
cbusToPbusXType: ClockCrossingType = SynchronousCrossing(), // buffer depth = 2
fbusToSbusXType: ClockCrossingType = SynchronousCrossing() // buffer depth = 2
dipolomacy/parameters.scala
case object NoCrossing // converts to SynchronousCrossing(BufferParams.none) via implicit def in package
case class SynchronousCrossing(params: BufferParams = BufferParams.default) extends ClockCrossingType
val default = BufferParams(2)
val none = BufferParams(0)
4. Where exactly does the NIC connect to the peripheral bus and interrupt bus? In NIC.scala we can see:
control.node := TLAtomicAutomata() := mmionode
But how does this control.node further connect to the PBUS?
Best,
Varun