はじめて
Intel Habana Gaudi/Gaudi2 の linux デバイスドライバは公開されています。Gaudiについては、下記のブログにちょっとだけ書きました。
追記)、2024.04.10 : v6.2 までしか存在しません。ので、master から v6.2 にURLを修正しました。
今回は、Intel Habana Gaudi2 のlinuxデバイスドライバを眺めてみました。
Gaudi2 の Gaudi と内部の構成が違う
下図は、Gadui2(左側)とGaudi(右側)です。説明のために引用します。
上記の図だけを見ると、Media Engineが追加されて、各要素が増えた感じです。
しかしながら、デバイスドライバのソースコードを眺めたら、かなり違うことがわかりました。
ここを見ると、TPC_ID_DCOREX_TPCY という感じになっています。
enum gaudi2_tpc_id { TPC_ID_DCORE0_TPC0, TPC_ID_DCORE0_TPC1, TPC_ID_DCORE0_TPC2, TPC_ID_DCORE0_TPC3, TPC_ID_DCORE0_TPC4, TPC_ID_DCORE0_TPC5, TPC_ID_DCORE1_TPC0, TPC_ID_DCORE1_TPC1, TPC_ID_DCORE1_TPC2, TPC_ID_DCORE1_TPC3, TPC_ID_DCORE1_TPC4, TPC_ID_DCORE1_TPC5, TPC_ID_DCORE2_TPC0, TPC_ID_DCORE2_TPC1, TPC_ID_DCORE2_TPC2, TPC_ID_DCORE2_TPC3, TPC_ID_DCORE2_TPC4, TPC_ID_DCORE2_TPC5, TPC_ID_DCORE3_TPC0, TPC_ID_DCORE3_TPC1, TPC_ID_DCORE3_TPC2, TPC_ID_DCORE3_TPC3, TPC_ID_DCORE3_TPC4, TPC_ID_DCORE3_TPC5, /* the PCI TPC is placed last (mapped liked HW) */ TPC_ID_DCORE0_TPC6, TPC_ID_SIZE, };
DCOREは0-3で、各DCOREには6個のTPC(TPC0-TPC5) があります。Gaudi2にはTPCが24個入っているので、DCORE(4) x TPC(6) = 24 であっています。
各DCOREには、TPC以外に以下のものが入っているようです。
- EDMA(各DCOREに2個)
- KDMA(DCORE0のみ1個)
- PDMA (DCORE0のみ2個)
- Decoder (MediaEngine)
- MME (Matrix Engine)
この他にも
- PCIE には、VDECに2個
- ROTATORが2個
MESHタイプのNoCがあるみたい
PLLの情報を得る関数では、MESH なるものがあります。
static int gaudi2_map_pll_idx_to_fw_idx(u32 pll_idx) { switch (pll_idx) { case HL_GAUDI2_CPU_PLL: return CPU_PLL; case HL_GAUDI2_PCI_PLL: return PCI_PLL; case HL_GAUDI2_NIC_PLL: return NIC_PLL; case HL_GAUDI2_DMA_PLL: return DMA_PLL; case HL_GAUDI2_MESH_PLL: return MESH_PLL; case HL_GAUDI2_MME_PLL: return MME_PLL; case HL_GAUDI2_TPC_PLL: return TPC_PLL; case HL_GAUDI2_IF_PLL: return IF_PLL; case HL_GAUDI2_SRAM_PLL: return SRAM_PLL; case HL_GAUDI2_HBM_PLL: return HBM_PLL; case HL_GAUDI2_VID_PLL: return VID_PLL; case HL_GAUDI2_MSS_PLL: return MSS_PLL; default: return -EINVAL; } }
ここには、RAZWIなるものがあります。X方向に5ビット(最大32個)、Y方向に4ビット(最大16個)が接続するようになっています。RTR_ID_X_YというマクロでMESHの位置を決められるようです。実際には、X方向は0-17、Y方向は0-11になっているようです。
/* RAZWI initiator coordinates- X- 5 bits, Y- 4 bits */ #define RAZWI_INITIATOR_X_SHIFT 0 #define RAZWI_INITIATOR_X_MASK 0x1F #define RAZWI_INITIATOR_Y_SHIFT 5 #define RAZWI_INITIATOR_Y_MASK 0xF #define RTR_ID_X_Y(x, y) \ ((((y) & RAZWI_INITIATOR_Y_MASK) << RAZWI_INITIATOR_Y_SHIFT) | \ (((x) & RAZWI_INITIATOR_X_MASK) << RAZWI_INITIATOR_X_SHIFT))
MESHの中は、この部分で分かりそう。
static const u32 rtr_coordinates_to_rtr_id[NUM_OF_RTR_PER_DCORE * NUM_OF_DCORES] = { RTR_ID_X_Y(2, 4), RTR_ID_X_Y(3, 4), RTR_ID_X_Y(4, 4), RTR_ID_X_Y(5, 4), RTR_ID_X_Y(6, 4), RTR_ID_X_Y(7, 4), RTR_ID_X_Y(8, 4), RTR_ID_X_Y(9, 4), RTR_ID_X_Y(10, 4), RTR_ID_X_Y(11, 4), RTR_ID_X_Y(12, 4), RTR_ID_X_Y(13, 4), RTR_ID_X_Y(14, 4), RTR_ID_X_Y(15, 4), RTR_ID_X_Y(16, 4), RTR_ID_X_Y(17, 4), RTR_ID_X_Y(2, 11), RTR_ID_X_Y(3, 11), RTR_ID_X_Y(4, 11), RTR_ID_X_Y(5, 11), RTR_ID_X_Y(6, 11), RTR_ID_X_Y(7, 11), RTR_ID_X_Y(8, 11), RTR_ID_X_Y(9, 11), RTR_ID_X_Y(0, 0),/* 24 no id */ RTR_ID_X_Y(0, 0),/* 25 no id */ RTR_ID_X_Y(0, 0),/* 26 no id */ RTR_ID_X_Y(0, 0),/* 27 no id */ RTR_ID_X_Y(14, 11), RTR_ID_X_Y(15, 11), RTR_ID_X_Y(16, 11), RTR_ID_X_Y(17, 11) };
32個あります。
この部分で DCOREX_RTRY に何が居るのがわかります。
static const char *gaudi2_get_initiators_name(u32 rtr_id) { switch (rtr_id) { case DCORE0_RTR0: return "DEC0/1/8/9, TPC24, PDMA0/1, PMMU, PCIE_IF, EDMA0/2, HMMU0/2/4/6, CPU"; case DCORE0_RTR1: return "TPC0/1"; case DCORE0_RTR2: return "TPC2/3"; case DCORE0_RTR3: return "TPC4/5"; case DCORE0_RTR4: return "MME0_SBTE0/1"; case DCORE0_RTR5: return "MME0_WAP0/SBTE2"; case DCORE0_RTR6: return "MME0_CTRL_WR/SBTE3"; case DCORE0_RTR7: return "MME0_WAP1/CTRL_RD/SBTE4"; case DCORE1_RTR0: return "MME1_WAP1/CTRL_RD/SBTE4"; case DCORE1_RTR1: return "MME1_CTRL_WR/SBTE3"; case DCORE1_RTR2: return "MME1_WAP0/SBTE2"; case DCORE1_RTR3: return "MME1_SBTE0/1"; case DCORE1_RTR4: return "TPC10/11"; case DCORE1_RTR5: return "TPC8/9"; case DCORE1_RTR6: return "TPC6/7"; case DCORE1_RTR7: return "DEC2/3, NIC0/1/2/3/4, ARC_FARM, KDMA, EDMA1/3, HMMU1/3/5/7"; case DCORE2_RTR0: return "DEC4/5, NIC5/6/7/8, EDMA4/6, HMMU8/10/12/14, ROT0"; case DCORE2_RTR1: return "TPC16/17"; case DCORE2_RTR2: return "TPC14/15"; case DCORE2_RTR3: return "TPC12/13"; case DCORE2_RTR4: return "MME2_SBTE0/1"; case DCORE2_RTR5: return "MME2_WAP0/SBTE2"; case DCORE2_RTR6: return "MME2_CTRL_WR/SBTE3"; case DCORE2_RTR7: return "MME2_WAP1/CTRL_RD/SBTE4"; case DCORE3_RTR0: return "MME3_WAP1/CTRL_RD/SBTE4"; case DCORE3_RTR1: return "MME3_CTRL_WR/SBTE3"; case DCORE3_RTR2: return "MME3_WAP0/SBTE2"; case DCORE3_RTR3: return "MME3_SBTE0/1"; case DCORE3_RTR4: return "TPC18/19"; case DCORE3_RTR5: return "TPC20/21"; case DCORE3_RTR6: return "TPC22/23"; case DCORE3_RTR7: return "DEC6/7, NIC9/10/11, EDMA5/7, HMMU9/11/13/15, ROT1, PSOC"; default: return "N/A"; } }
歩留まり対策
/* * Gaudi2 subtitute TPCs Numbering * At most- two faulty TPCs are allowed * First replacement to a faulty TPC will be TPC24, second- TPC23 */ enum substitude_tpc { FAULTY_TPC_SUBTS_1_TPC_24, FAULTY_TPC_SUBTS_2_TPC_23, MAX_FAULTY_TPCS };
ARC CPU がたくさん?
このヘッダーを見ると、ARC CPUがいっぱい入っているようです。
/* * CPU IDs for each ARC CPUs */ #define CPU_ID_SCHED_ARC0 0 /* FARM_ARC0 */ #define CPU_ID_SCHED_ARC1 1 /* FARM_ARC1 */ #define CPU_ID_SCHED_ARC2 2 /* FARM_ARC2 */ #define CPU_ID_SCHED_ARC3 3 /* FARM_ARC3 */ /* Dcore1 MME Engine ARC instance used as scheduler */ #define CPU_ID_SCHED_ARC4 4 /* DCORE1_MME0 */ /* Dcore3 MME Engine ARC instance used as scheduler */ #define CPU_ID_SCHED_ARC5 5 /* DCORE3_MME0 */ #define CPU_ID_TPC_QMAN_ARC0 6 /* DCORE0_TPC0 */ #define CPU_ID_TPC_QMAN_ARC1 7 /* DCORE0_TPC1 */ #define CPU_ID_TPC_QMAN_ARC2 8 /* DCORE0_TPC2 */ #define CPU_ID_TPC_QMAN_ARC3 9 /* DCORE0_TPC3 */ #define CPU_ID_TPC_QMAN_ARC4 10 /* DCORE0_TPC4 */ #define CPU_ID_TPC_QMAN_ARC5 11 /* DCORE0_TPC5 */ #define CPU_ID_TPC_QMAN_ARC6 12 /* DCORE1_TPC0 */ #define CPU_ID_TPC_QMAN_ARC7 13 /* DCORE1_TPC1 */ #define CPU_ID_TPC_QMAN_ARC8 14 /* DCORE1_TPC2 */ #define CPU_ID_TPC_QMAN_ARC9 15 /* DCORE1_TPC3 */ #define CPU_ID_TPC_QMAN_ARC10 16 /* DCORE1_TPC4 */ #define CPU_ID_TPC_QMAN_ARC11 17 /* DCORE1_TPC5 */ #define CPU_ID_TPC_QMAN_ARC12 18 /* DCORE2_TPC0 */ #define CPU_ID_TPC_QMAN_ARC13 19 /* DCORE2_TPC1 */ #define CPU_ID_TPC_QMAN_ARC14 20 /* DCORE2_TPC2 */ #define CPU_ID_TPC_QMAN_ARC15 21 /* DCORE2_TPC3 */ #define CPU_ID_TPC_QMAN_ARC16 22 /* DCORE2_TPC4 */ #define CPU_ID_TPC_QMAN_ARC17 23 /* DCORE2_TPC5 */ #define CPU_ID_TPC_QMAN_ARC18 24 /* DCORE3_TPC0 */ #define CPU_ID_TPC_QMAN_ARC19 25 /* DCORE3_TPC1 */ #define CPU_ID_TPC_QMAN_ARC20 26 /* DCORE3_TPC2 */ #define CPU_ID_TPC_QMAN_ARC21 27 /* DCORE3_TPC3 */ #define CPU_ID_TPC_QMAN_ARC22 28 /* DCORE3_TPC4 */ #define CPU_ID_TPC_QMAN_ARC23 29 /* DCORE3_TPC5 */ #define CPU_ID_TPC_QMAN_ARC24 30 /* DCORE0_TPC6 - Never present */ #define CPU_ID_MME_QMAN_ARC0 31 /* DCORE0_MME0 */ #define CPU_ID_MME_QMAN_ARC1 32 /* DCORE2_MME0 */ #define CPU_ID_EDMA_QMAN_ARC0 33 /* DCORE0_EDMA0 */ #define CPU_ID_EDMA_QMAN_ARC1 34 /* DCORE0_EDMA1 */ #define CPU_ID_EDMA_QMAN_ARC2 35 /* DCORE1_EDMA0 */ #define CPU_ID_EDMA_QMAN_ARC3 36 /* DCORE1_EDMA1 */ #define CPU_ID_EDMA_QMAN_ARC4 37 /* DCORE2_EDMA0 */ #define CPU_ID_EDMA_QMAN_ARC5 38 /* DCORE2_EDMA1 */ #define CPU_ID_EDMA_QMAN_ARC6 39 /* DCORE3_EDMA0 */ #define CPU_ID_EDMA_QMAN_ARC7 40 /* DCORE3_EDMA1 */ #define CPU_ID_PDMA_QMAN_ARC0 41 /* DCORE0_PDMA0 */ #define CPU_ID_PDMA_QMAN_ARC1 42 /* DCORE0_PDMA1 */ #define CPU_ID_ROT_QMAN_ARC0 43 /* ROT0 */ #define CPU_ID_ROT_QMAN_ARC1 44 /* ROT1 */ #define CPU_ID_NIC_QMAN_ARC0 45 /* NIC0_0 */ #define CPU_ID_NIC_QMAN_ARC1 46 /* NIC0_1 */ #define CPU_ID_NIC_QMAN_ARC2 47 /* NIC1_0 */ #define CPU_ID_NIC_QMAN_ARC3 48 /* NIC1_1 */ #define CPU_ID_NIC_QMAN_ARC4 49 /* NIC2_0 */ #define CPU_ID_NIC_QMAN_ARC5 50 /* NIC2_1 */ #define CPU_ID_NIC_QMAN_ARC6 51 /* NIC3_0 */ #define CPU_ID_NIC_QMAN_ARC7 52 /* NIC3_1 */ #define CPU_ID_NIC_QMAN_ARC8 53 /* NIC4_0 */ #define CPU_ID_NIC_QMAN_ARC9 54 /* NIC4_1 */ #define CPU_ID_NIC_QMAN_ARC10 55 /* NIC5_0 */ #define CPU_ID_NIC_QMAN_ARC11 56 /* NIC5_1 */ #define CPU_ID_NIC_QMAN_ARC12 57 /* NIC6_0 */ #define CPU_ID_NIC_QMAN_ARC13 58 /* NIC6_1 */ #define CPU_ID_NIC_QMAN_ARC14 59 /* NIC7_0 */ #define CPU_ID_NIC_QMAN_ARC15 60 /* NIC7_1 */ #define CPU_ID_NIC_QMAN_ARC16 61 /* NIC8_0 */ #define CPU_ID_NIC_QMAN_ARC17 62 /* NIC8_1 */ #define CPU_ID_NIC_QMAN_ARC18 63 /* NIC9_0 */ #define CPU_ID_NIC_QMAN_ARC19 64 /* NIC9_1 */ #define CPU_ID_NIC_QMAN_ARC20 65 /* NIC10_0 */ #define CPU_ID_NIC_QMAN_ARC21 66 /* NIC10_1 */ #define CPU_ID_NIC_QMAN_ARC22 67 /* NIC11_0 */ #define CPU_ID_NIC_QMAN_ARC23 68 /* NIC11_1 */
ここに、
#define NUM_ARC_CPUS 69
とあるので、69個も ARC CPU が載っているんですね。
おわりに
Gaudi => Gauid2 になって、TPCが8個から24個。MMEが1個から2個、MediaEngine(DecoderとRotator)が追加されただけでなく、内部構造もかなり変わったようです。
関連ブログ