DiplomacyのXbarについて理解を深めるためにソースコードを読んでみよう。とりまOCPの実装をしたいのだが、何せ内部を理解しないとどうも改造できそうにない気がしてきた。どうにかしてソースコードを理解しなければ。
NexusNodeについて
NexusNodeは複数のSlaveと複数のMasterを接続することのできるノードだ。接続中に、ノードの信号情報を変更することもできる。
val node = TLNexusNode( clientFn = { seq => seq(0).copy( minLatency = seq.map(_.minLatency).min, clients = (TLXbar.mapInputIds(seq) zip seq) flatMap { case (range, port) => port.clients map { client => client.copy( sourceId = client.sourceId.shift(range.start) )} } ) }, managerFn = { seq => val fifoIdFactory = TLXbar.relabeler() seq(0).copy( minLatency = seq.map(_.minLatency).min, endSinkId = TLXbar.mapOutputIds(seq).map(_.end).max, managers = seq.flatMap { port => require (port.beatBytes == seq(0).beatBytes, s"Xbar data widths don't match: ${port.managers.map(_.name)} has ${port.beatBytes}B vs ${seq(0).managers.map(_.name)} has ${seq(0).beatBytes}B") val fifoIdMapper = fifoIdFactory() port.managers map { manager => manager.copy( fifoId = manager.fifoId.map(fifoIdMapper(_)) )} } ) })
The clientFn
is a function that takes the TLClientPortParameters
of the input as an argument and returns the corresponding parameters for the output. The managerFn
takes the TLManagerPortParameters
of the output as an argument and returns the corresponding parameters for the input.
clientFn
はTLClientPortParameter
を引数に取る関数で、出力に対して相当するパラメータを返す。
managerFn
はTLManagerPortParameters
を引数に取る関数で、入力に対して相当するパラメータを返す。
例えば、2つのMasterを接続した場合には以下のようにsourceIdが設定された。
sourceId = IdRange(1,2) sourceId = IdRange(0,1)
次に、requestAIO
について調べていく。Xbarには、リクエストがどのターゲットに対してリクエストを発行しているのかを示すrequestAIO
などという信号が定義されている。
val requestAIO = (connectAIO zip addressA) map { case (c, i) => outputPortFns(c).map { o => unique(c) || o(i) } } val requestCIO = (connectCIO zip addressC) map { case (c, i) => outputPortFns(c).map { o => unique(c) || o(i) } } val requestBOI = out.map { o => inputIdRanges.map { i => i.contains(o.b.bits.source) } } val requestDOI = out.map { o => inputIdRanges.map { i => i.contains(o.d.bits.source) } } val requestEIO = in.map { i => outputIdRanges.map { o => o.contains(i.e.bits.sink) } }
requestAIO
は、縦方向がマスター側、横方向がスレーブ側となる。これはリクエストの発行状況を示しているのか?
slave ~~~~~~~~~ requestAIO[0] = 1,1,1,1,1, | requestAIO[1] = 1,1,1,1,1, | requestAIO[2] = 1,1,1,1,1, | masters requestAIO[3] = 1,1,1,1,1, |
requestDOI
は、逆に縦方向がスレーブ側、横方向がマスター側となる。これはレスポンスの発行状況を示しているのか?
master ~~~~~~~~ requestDOI[0] = 1,0,0,0, | requestDOI[1] = 0,0,0,1, | requestDOI[2] = 0,0,0,1, | slave requestDOI[3] = 0,0,0,1, | requestDOI[4] = 0,0,0,1, |