Blackhole の中では Tensix, DRAM, PCIe, Ethernet, CPU, ARC,,, などのタイルが NoC でつながっています。ここでは Tenstorrent が公開しているドキュメントから NoC の仕様を整理します。
ネットワークトポロジ
Blackhole の NoC は全二重のトーラストポロジとなっています。NoC0 と NoC1 の2つがあり、NoC0は右下方向(XYが増加する)に、NoC1は左上方向(XYが減少する)にデータを流します。トーラスなので、端部まで行ったら先頭に戻ります。
格子状に見えますが、左右の端と上下の端がつながっています。 packet は NIU から出発し、router を経由して、宛先タイルの NIU に到着します。
パケット
1 回の transaction は 1 個以上の packet で構成されます。packet は 1 個の header flit と、最大 256 個の data flit で構成されます。Blackhole の flit は 512 bit (64 byte) です。
transaction
└─ packet
├─ header flit : 64 byte
└─ data flit xN : 64 byte x 0..256
リクエスト
NoC に流せるリクエストは3種類です。
- Read: 宛先のアドレス空間から連続データを読み、戻り先のアドレス空間に書き込む
- Write: 送信元のアドレス空間または 32 bit immediate を、宛先のアドレス空間に書き込む
- Atomic: 宛先 L1 の 128 bit に対して atomic operation を実行し、必要なら 32 bit の結果を返す
Write は posted にできます。posted write では、宛先が書き込み完了後に acknowledgement を返しません。逆に完了を確認したい場合は response を要求します。
Write と Atomic は broadcast できます。ただし broadcast の宛先は Tensix タイルに限られると考えたほうがよさそうです。NoC overlay に到着 write を通知する機能もあります。
NIU (NoC Interface Unit)
NIU は NoC Interface Unit です。Tensix や Ethernet の NIU はタイルのアドレス空間につながっていて、Baby RISC-V から MMIO レジスタ経由で NoC transaction を発行できます。DRAM タイルの NIU は主に GDDR6 につながっています。PCIe タイルは PCIe transaction と NoC transaction を相互変換します。CPU タイルでは、x280 から見えるアドレス空間と NoC の間を橋渡しします。
NIU の MMIO
Tensix、Ethernet、DRAM タイルでは、Baby RISC-V が NIU の MMIO レジスタを書いて NoC request を発行します。 各タイルには 2 個の NIU があります。 NIU #0 は NoC #0 に、NIU #1 は NoC #1 に接続されています。
Tensix と Ethernet では、NIU の base address は次のようになります。
| NoC | NIU_BASE |
|---|---|
| NoC #0 | 0x0000_0000_FFB2_0000 |
| NoC #1 | 0x0000_0000_FFB3_0000 |
各 NIU には request initiator が 4 個あります。
software は initiator のレジスタに宛先、戻り先、長さ、request 種別、flag などを書き、最後に NOC_CMD_CTRL の low bit に 1 を書いて request を開始します。
hardware は request を開始できる状態になると、この bit を 0 に戻します。
そのため、同じ initiator を再利用する前に NOC_CMD_CTRL の low bit を確認する必要があります。
主要なレジスタは次のような役割です。
| レジスタ | 役割 |
|---|---|
NOC_TARG_ADDR_LO/MID/HI | target address と target X/Y |
NOC_RET_ADDR_LO/MID/HI | return address と return X/Y |
NOC_PACKET_TAG | transaction ID、overlay への通知など |
NOC_CTRL | request type と主要 flag |
NOC_AT_LEN_BE | atomic opcode、read/write length、byte enable |
NOC_AT_DATA | inline write や atomic immediate |
NOC_CMD_CTRL | request 開始 |
ここで少しややこしいのは、NOC_TARG_ADDR と NOC_RET_ADDR の意味が request type で変わることです。
Read では target から読み、return にデータが戻ります。
Atomic では target に atomic request が届き、response が必要なら return に結果が戻ります。
通常の non-inline write では、initiator 側の NOC_TARG_ADDR からデータを読み、宛先である NOC_RET_ADDR に書き込みます。
アドレス仮想化
これが Blackhole スケーラブルな NoC の肝となる機能です。 NIU が物理アドレスと仮想アドレス
NIU は座標変換機能があります。これが有効な場合、NOC_TARG_ADDR_HI や NOC_RET_ADDR_HI に書く X/Y は raw NoC 座標ではありません。いったん論理座標として解釈され、ハードウェアが物理座標に変換します。
この変換は、だいたい次の目的で firmware によって設定されます。
- NoC #0 と NoC #1 でなるべく同じ座標系を使う
- 同じ種類のタイルを連続した座標範囲に寄せる
- harvesting されたタイルがあっても、ソフトウェアから見える番号付けを安定させる
Blackhole では Wormhole と違い、X 軸と Y 軸を完全に独立して変換するのではなく、組み合わせで変換します。
たとえば Tensix は主に Y = 2..11 の範囲に置かれますが、DDR、Ethernet、PCIe、L2CPU、Security などは別の論理座標領域に寄せられます。
このため、ソフトウェアを書くときは「物理配置図の座標」と「NIU に書く座標」を同一視しないほうが安全です。
tt-metal の SocDescriptor や CoordinateManager がやっていることは、このずれを扱いやすくするための層だと見られます。
仮想チャネル
経路
パケットの経路は一位に決まります。
NoC #0 と NoC #1 では、進む方向も曲がり方も違います。
NoC #0 の unicast は、必要なだけ X 方向へ進み、最大 1 回曲がってから Y 方向へ進みます。 NoC #1 の unicast は逆で、必要なだけ Y 方向へ進み、最大 1 回曲がってから X 方向へ進みます。
broadcast は矩形領域を宛先にします。ただし、矩形内のすべてのタイルが受信するわけではありません。firmware は Tensix 以外の NIU を broadcast 受信から外すように設定します。
NoC router は cut-through で動作します。つまり packet 全体を受信し終わる前に、届いた flit から次の router へ転送を開始できます。これにより latency を抑えられますが、同じ link を複数 packet が使いたい場合は congestion が起きます。
仮想チャネル
packet が router 間、または router と NIU の間の link を通るとき、virtual channel number が割り当てられます。この番号は 4 bit で、次の要素から構成されます。
- dateline bit
- class bit 2 個
- buddy bit
class bit は用途が固定されています。
| class | 用途 |
|---|---|
0b00 | unicast request |
0b01 | unicast request |
0b10 | broadcast request |
0b11 | response |
同じ transaction に複数 request packet が含まれる場合は少し特殊です。 各 request packet は hop ごとに同じ virtual channel number を使い、最後の request packet が通過するまで、その hop の virtual channel は同じ transaction の後続 packet のために予約されます。
これは ordering を強める一方で、使い方を間違えると NoC 全体を詰まらせます。
NOC_CMD_VC_LINKED を使う場合は、同じ宛先に対する一連の request を速やかに完了させる必要があります。
Ordering と完了確認
NoC transaction はデフォルトでは弱い ordering です。 Baby RISC-V が MMIO 経由で request を発行しても、RISC-V の実行とは非同期に進みます。
完了確認には counter または interrupt を使います。
NOC_PACKET_TAG の transaction ID は counter と結びついていて、request 発行時に outstanding counter が増え、response や acknowledgement によって減ります。
ソフトウェア側で強い ordering を作りたい場合は、次の flag が関係します。
NOC_CMD_VC_LINKEDNOC_CMD_VC_STATICNOC_CMD_PATH_RESERVENOC_CMD_ARB_PRIORITY
ただし、これらは性能や deadlock freedom に影響します。
特に broadcast で path reservation を使わない場合や、priority を 0 以外にする場合は、software が deadlock を作らないように設計する責任を持ちます。
性能感
NoC の link は、基本的に 1 cycle に 1 flit を流せます。Blackhole の 1 flit は 512 bit なので、1 hop あたりの生帯域はかなり太いです。ドキュメントにある代表値は次の通りです。
| hop | throughput | latency |
|---|---|---|
| NIU → router | 1 flit / cycle | 約 5 cycle |
| router → router | 1 flit / cycle / axis | 9 cycle |
| router → NIU | 1 flit / cycle | 約 5 cycle |
ただし、実効 throughput は payload の長さに依存します。短い packet では header flit の割合が大きく、長い packet では 1 header flit と最大 256 data flit で最大 16384 byte を運べます。
また、congestion があると latency は伸びます。NOC_CMD_VC_LINKED や NOC_CMD_VC_STATIC で ordering を強めると、空いている帯域があっても packet が待たされることがあります。
まとめ
NoC は単なる配線ではなく、Blackhole の各タイルを結ぶ分散した transaction engine です。 Tensix や Ethernet から見ると、NIU の MMIO レジスタに request を積んで、read、write、atomic、broadcast を発行する仕組みです。
重要なのは次の 3 点だと思います。
- NoC #0 と NoC #1 は同じタイルを結ぶが、物理的に独立していて流れる向きが逆
- software から見える座標は raw 座標とは限らず、firmware が設定した coordinate translation を通る
- request は非同期で、完了確認、ordering、deadlock freedom は flag の使い方に依存する
Blackhole の演算性能を理解するには Tensix core の中身を見る必要がありますが、実際にデータを運ぶのは NoC です。行列演算器だけでなく、NoC と NIU まで含めて読むと、Tenstorrent が「たくさんの小さな計算機を NoC で束ねたチップ」だという見方がしやすくなります。