分析 Rocket Chip 中 Diplomacy 系统¶
概念¶
Diplomacy 主要实现了两个功能:
- 把整个总线结构在代码中表现出来
- 自动配置总线中各个端口的参数
具体来说,第一点实现了类似 Vivado Board Design 中连线的功能,第二点则是保证总线两端的参数一致,可以连接起来。
Diplomacy 为了表示总线的结构,每个模块可以对应一个 Node,Node 和 Node 之间连接形成一个图。Node 的类型主要有以下几个:
- Client:对应 AXI 里面的 Master,发起请求
- Manager:对应 AXI 里面的 Slave,处理请求
- Adapter:对应 AXI Width Converter/Clock Converter/AXI4 to AXI3/AXI4 to AHB bridge 等,会修改 AXI 的参数,然后每个输入对应一个输出
- Nexus:对应 AXI Crossbar,多个输入和多个输出
每个 Node 可能作为 Manager 连接上游的 Client,这个叫做入边(Inward Edge);同样地,也可以作为 Client 连接下游的 Manager,这个是出边(Outward Edge)。想象成一个 DAG,从若干个 Client 流向 Manager。
连接方式采用的是 :=
:=*
:*=
:*=*
操作符,左侧是 Client,右侧是 Manager。
Rocket Chip 总线结构¶
Rocket Chip 主要有以下几个总线:
- sbus: System Bus
- mbus: Memory Bus
- cbus: Control Bus
- pbus: Periphery Bus
- fbus: Frontend Bus
图示可以见参考文档中的链接,不过链接中的结构和实际的有一些区别。目前的 Rocket Chip 内存结构大致是这样:
主要是 pbus 的位置从连接 sbus 移动到了连接 cbus。
相关代码:
/** Parameterization of a topology containing three additional, optional buses for attaching MMIO devices. */
case class HierarchicalBusTopologyParams(
pbus: PeripheryBusParams,
fbus: FrontBusParams,
cbus: PeripheryBusParams,
xTypes: SubsystemCrossingParams,
driveClocksFromSBus: Boolean = true
) extends TLBusWrapperTopology(
instantiations = List(
(PBUS, pbus),
(FBUS, fbus),
(CBUS, cbus)),
connections = List(
(SBUS, CBUS, TLBusWrapperConnection .crossTo(xTypes.sbusToCbusXType, if (driveClocksFromSBus) Some(true) else None)),
(CBUS, PBUS, TLBusWrapperConnection .crossTo(xTypes.cbusToPbusXType, if (driveClocksFromSBus) Some(true) else None)),
(FBUS, SBUS, TLBusWrapperConnection.crossFrom(xTypes.fbusToSbusXType, if (driveClocksFromSBus) Some(false) else None)))
)
当然了,也有简化版的 JustOneBusTopology,那就只有 SystemBus 了。如果再配置了 CoherentBusTopology,那么 SBUS 和 MBUS 之间还有一层 L2:
/** Parameterization of a topology containing a banked coherence manager and a bus for attaching memory devices. */
case class CoherentBusTopologyParams(
sbus: SystemBusParams, // TODO remove this after better width propagation
mbus: MemoryBusParams,
l2: BankedL2Params,
sbusToMbusXType: ClockCrossingType = NoCrossing,
driveMBusClockFromSBus: Boolean = true
) extends TLBusWrapperTopology(
instantiations = (if (l2.nBanks == 0) Nil else List(
(MBUS, mbus),
(L2, CoherenceManagerWrapperParams(mbus.blockBytes, mbus.beatBytes, l2.nBanks, L2.name, sbus.dtsFrequency)(l2.coherenceManager)))),
connections = if (l2.nBanks == 0) Nil else List(
(SBUS, L2, TLBusWrapperConnection(driveClockFromMaster = Some(true), nodeBinding = BIND_STAR)()),
(L2, MBUS, TLBusWrapperConnection.crossTo(
xType = sbusToMbusXType,
driveClockFromMaster = if (driveMBusClockFromSBus) Some(true) else None,
nodeBinding = BIND_QUERY))
)
)