MI IPU CASCADE API¶
REVISION HISTORY¶
| Revision No. | Description |
Date |
|---|---|---|
| 1.0 | Initial release. | 01/07/2025 |
| 1.1 | 02/28/2026 |
1. OVERVIEW¶
1.1. Module Description¶
The IPU Cascade API is designed for application scenarios where multiple IPUs process the same LLM (Large Language Model) in parallel. Its main function is to accelerate the inference of LLM models on the board. The IPU Cascade API maintains a consistent style with the general MI IPU interface, facilitating the extension of PCIe cascade capabilities in existing projects.
1.2. Basic Structure¶
- RC (Root Complex) Application: Responsible for reading cascade offline models, creating devices/channels, preparing input/output Tensors, and controlling EP-side service programs to execute model inference.
- EP (Endpoint) Service: Runs on IPU boards connected via the PCIe bus, responsible for responding to RC commands and calling IPU Cascade API to complete model inference.
1.3. Module Functions¶
The IPU Cascade API supports the following features:
-
Supports collaborative inference of cascade models across local and remote IPU boards
-
Supports controlling remote IPU boards for non-cascade model inference
-
Supports multiple channels
-
Supports specifying priority for IPU inference tasks
-
Supports single-input inference and multi-input inference per batch
1.4. Application Scenarios¶
- Large Model Cascade: Splits cascade large models into multiple sub-networks and distributes them across multiple IPUs to improve throughput and capacity.
- Remote Inference Acceleration: Models run entirely on EP, while RC is responsible for data scheduling.
1.5. Working Principle¶
Before calling the IPU Cascade module for model inference, users first need to use the IPU SDK toolchain to convert the original large language model into an offline cascade model file supported by the hardware. Then, by calling the IPU Cascade API, load the offline cascade model locally on the board and control the remote board to accelerate the offline cascade model inference.
1.6. Interface Call Flow¶
MI_IPU_PCIECasWrapper_GetOfflineStaticInfoMI_IPU_PCIECasWrapper_CreateDeviceMI_IPU_PCIECasWrapper_CreateCHNMI_IPU_GetInOutTensorDescMI_IPU_PCIECasWrapper_SubNetInvokeMI_IPU_PCIECasWrapper_DestroyCHNMI_IPU_PCIECasWrapper_DestroyDevice
1.7. Example¶
The SDK provides examples at sdk/release_feature/source/ipu/ipu_client/ (RC) and sdk/release_feature/source/ipu/ipu_service/ (EP). You can directly refer to how they organize parameters and call public APIs.
-
ipu_client#include <fcntl.h> #include <sgs_rpmsg.h> #include <string.h> #include <sys/ioctl.h> #include <sys/types.h> #include <sys/mman.h> #include <unistd.h> #include <stdio.h> #include <errno.h> #include <pthread.h> #include <getopt.h> #include <stdbool.h> #include <stdlib.h> #include "mi_sys.h" #include "mi_ipu.h" #include "mi_ipu_pcie_cascade_datatype.h" #include "mi_ipu_pcie_cascade.h" #include "ipu_client.h" static void _showUsage(void) { printf("Usage: ./prog_ipu_ipu_client [-m] [-i][...]\n"); printf(" -m, model file\n"); printf(" -i, input tensor file\n"); printf(" -l, loop count, if not set, only invoke once\n"); printf(" -n, nbatch\n"); printf(" -j, subnet id\n"); printf(" -a, ipu affinity, multi core use\n"); printf(" -p, invoke priority, -10~39\n"); } static MI_S32 IPU_Client_GetInputTensorData(char *InputPath, void **pInput, int *filelen_in) { int fd1; void *pmem = NULL; off_t filelen1; if (!InputPath){ return -1; } fd1 = open(InputPath, O_RDONLY, 0644); if (fd1 < 0) return -1; filelen1 = lseek(fd1, 0L, SEEK_END); if (filelen1 <= 0){ return -1; } lseek(fd1, 0L, SEEK_SET); pmem = mmap(NULL, filelen1, PROT_READ, MAP_SHARED, fd1, 0); close(fd1); if (pmem == MAP_FAILED) return -1; *pInput = pmem; *filelen_in = filelen1; return MI_SUCCESS; } static MI_S32 IPU_Client_InsertInputNbatch(void *pInput, MI_IPU_SubNet_InputOutputDesc_t *pDesc, MI_IPU_BatchInvokeParam_t *pInvokeParam) { int cnt, batch_cnt; int total_cnt = 0; char *_pInput = (char *)pInput; for (batch_cnt = 0; batch_cnt < pInvokeParam->u32BatchN; batch_cnt++) { for (cnt = 0; cnt < pDesc->u32InputTensorCount; cnt++) { memcpy(pInvokeParam->astArrayTensors[total_cnt].ptTensorData[0], (void *)_pInput, pDesc->astMI_InputTensorDescs[cnt].s32AlignedBufSize); MI_SYS_FlushInvCache(pInvokeParam->astArrayTensors[total_cnt].ptTensorData[0], pDesc->astMI_InputTensorDescs[cnt].s32AlignedBufSize); _pInput += pDesc->astMI_InputTensorDescs[cnt].s32AlignedBufSize; total_cnt++; } } return MI_SUCCESS; } MI_S32 IPU_Client_AllocTensors(MI_IPU_SubNet_InputOutputDesc_t *pDesc, IpuClientTestParam_t *pstTestParam, IpuClientRunbufInfo_t *pstIpuRuntimeInfo, IpuClientTensorAddrInfo_t *pstTensorAddrInfo, EN_IpuBufType eBufType, MI_U32 u32DeviatonBytes) { int i, j, s32Ret; MI_U32 u32RequireBufSize = 0, u32Nbatch; MI_U32 u32InCnt; MI_PHY *pu64TensorPA; void **ppTensorVA; MI_PHY u64PABase; void *pVABase; u32Nbatch = pstTestParam->u32Nbatch; if (!u32Nbatch) { u32Nbatch = 1; } switch (eBufType) { case EN_INPUT_BUF: for (j = 0; j < u32Nbatch; j++) { for (i = 0; i < pDesc->u32InputTensorCount; i++) { u32RequireBufSize += pDesc->astMI_InputTensorDescs[i].s32AlignedBufSize; u32RequireBufSize += ALIGN_UP(u32DeviatonBytes, ALIGN_SIZE); u32RequireBufSize += u32DeviatonBytes; } } pu64TensorPA = &pstIpuRuntimeInfo->u64InTensorPA; ppTensorVA = &pstIpuRuntimeInfo->pInTensorVA; pstIpuRuntimeInfo->u32InTensorSize = u32RequireBufSize; break; case EN_OUTPUT_BUF: for (j = 0; j < u32Nbatch; j++) { for (i = 0; i < pDesc->u32OutputTensorCount; i++) { u32RequireBufSize += pDesc->astMI_OutputTensorDescs[i].s32AlignedBufSize; u32RequireBufSize += ALIGN_UP(u32DeviatonBytes, ALIGN_SIZE); u32RequireBufSize += u32DeviatonBytes; } } pu64TensorPA = &pstIpuRuntimeInfo->u64OutTensorPA; ppTensorVA = &pstIpuRuntimeInfo->pOutTensorVA; pstIpuRuntimeInfo->u32OutTensorSize = u32RequireBufSize; break; default: u32RequireBufSize = 0; printf("error: don't support tensor type: %d\n", eBufType); return -1; } s32Ret = MI_SYS_MMA_Alloc(0, NULL, u32RequireBufSize, pu64TensorPA); if (s32Ret != MI_SUCCESS) { printf("fail to allocate %s buffer\n", eBufType==EN_INPUT_BUF?"input":"output"); return -1; } s32Ret = MI_SYS_Mmap(*pu64TensorPA, u32RequireBufSize, ppTensorVA, TRUE); if (s32Ret != MI_SUCCESS) { printf("Error: fail to map %s address, error=%d\n", eBufType==EN_INPUT_BUF?"input":"output", s32Ret); return -1; } if (u32DeviatonBytes != 0) { u64PABase = ALIGN_UP(*pu64TensorPA, ALIGN_SIZE) + u32DeviatonBytes; } else { u64PABase = *pu64TensorPA; } pVABase = *ppTensorVA + (u64PABase - *pu64TensorPA); if (eBufType == EN_INPUT_BUF) { pstTensorAddrInfo->u32InCnt = pDesc->u32InputTensorCount * u32Nbatch; for (i = 0; i < u32Nbatch; i++) { for (j = 0; j < pDesc->u32InputTensorCount; j++) { pstTensorAddrInfo->astArrayTensors[i*pDesc->u32InputTensorCount+j].phyTensorAddr[0] = u64PABase; pstTensorAddrInfo->astArrayTensors[i*pDesc->u32InputTensorCount+j].ptTensorData[0] = pVABase; u64PABase += pDesc->astMI_InputTensorDescs[j].s32AlignedBufSize; if (u32DeviatonBytes != 0) { u64PABase = ALIGN_UP(u64PABase, ALIGN_SIZE) + u32DeviatonBytes; } pVABase = *ppTensorVA + (u64PABase - *pu64TensorPA); } } } else { u32InCnt = pDesc->u32InputTensorCount * u32Nbatch; pstTensorAddrInfo->u32OutCnt = pDesc->u32OutputTensorCount * u32Nbatch; for (i = 0; i < u32Nbatch; i++) { for (j = 0; j < pDesc->u32OutputTensorCount; j++) { pstTensorAddrInfo->astArrayTensors[u32InCnt+i*pDesc->u32OutputTensorCount+j].phyTensorAddr[0] = u64PABase; pstTensorAddrInfo->astArrayTensors[u32InCnt+i*pDesc->u32OutputTensorCount+j].ptTensorData[0] = pVABase; u64PABase += pDesc->astMI_OutputTensorDescs[j].s32AlignedBufSize; if (u32DeviatonBytes != 0) { u64PABase = ALIGN_UP(u64PABase, ALIGN_SIZE) + u32DeviatonBytes; } pVABase = *ppTensorVA + (u64PABase - *pu64TensorPA); } } } return 0; } void IPU_Client_FreeTensors(IpuClientRunbufInfo_t *pstIpuRuntimeInfo, EN_IpuBufType eBufType) { if (eBufType == EN_INPUT_BUF) { MI_SYS_Munmap(pstIpuRuntimeInfo->pInTensorVA, pstIpuRuntimeInfo->u32InTensorSize); MI_SYS_MMA_Free(0, pstIpuRuntimeInfo->u64InTensorPA); } else { MI_SYS_Munmap(pstIpuRuntimeInfo->pOutTensorVA, pstIpuRuntimeInfo->u32OutTensorSize); MI_SYS_MMA_Free(0, pstIpuRuntimeInfo->u64OutTensorPA); } } int main(int argc, char * argv[]) { int opt; int count = 0; double linux_time = 0, total_linux_time = 0, total_ipu_time = 0; MI_U64 total_bw = 0, total_bw_rd = 0, total_bw_wr = 0; int file_len_in = 0; void *pInput = NULL; MI_U32 u32ChnId; MI_S32 s32Ret; int cnt, batch_cnt; int total_cnt; struct timespec invoke_start, invoke_end; IpuClientTestParam_t stTestParam; MI_IPU_PCIECasDevAttr_t stCASDevAttr; MI_IPU_PCIECasOfflineModelStaticInfo_t stCASOfflineModelInfo; MI_IPU_ModelDesc_t *pstModelDesc; MI_IPU_SubNet_InputOutputDesc_t *pstTensorDesc; MI_IPU_SubNetBatchInvokeParam_t stSubNetInvokeParam; MI_IPU_BatchInvokeParam_t stInvokParam; MI_IPU_PCIECasSubNetBatchInvokeParam_t stIPUCASInvokeParam; MI_IPU_RuntimeInfo_t stRuntimeInfo; IpuClientTensorAddrInfo_t stTensorAddrInfo; IpuClientRunbufInfo_t stIpuRunBufInfo; MI_IPU_DevAttr_t stIPUDevAttr; MI_IPUChnAttr_t stIPUChnAttr; memset(&stTestParam, 0, sizeof(stTestParam)); while (true) { int option_index = 0; static struct option long_options[] = { {"model", required_argument, 0, 'm' }, {"input", required_argument, 0, 'i' }, {"loop_count", required_argument, 0, 'l' }, {"nbatch", required_argument, 0, 'n' }, {"sub_net_id", required_argument, 0, 'j' }, {"affinity", required_argument, 0, 'a' }, {"priority", required_argument, 0, 'p' } }; opt = getopt_long(argc, argv, "m:i:o:l:n:j:a:p", long_options, &option_index); if (opt == -1) { break; } switch (opt) { case 'm': stTestParam.ModelPath = optarg; break; case 'i': stTestParam.InputPath = optarg; break; break; case 'l': stTestParam.u32LoopCount = strtoul(optarg, NULL, 16); break; case 'n': stTestParam.u32Nbatch = strtoul(optarg, NULL, 16); break; case 'j': stTestParam.u32SubNetId = strtoul(optarg, NULL, 10); stTestParam.u32SubNetInvoke = 1; break; case 'a': stTestParam.u32IpuAffinity = strtoul(optarg, NULL, 10); break; case 'p': stTestParam.s32TaskPrio = strtoul(optarg, NULL, 10); break; default: _showUsage(); return 0; } } if (argc <= 2 || !stTestParam.ModelPath || !stTestParam.InputPath) { _showUsage(); goto SYS_EXIT; } if (stTestParam.u32LoopCount == 0) stTestParam.u32LoopCount = 1; if (stTestParam.u32Nbatch == 0) stTestParam.u32Nbatch = 1; if (stTestParam.u32SubNetInvoke == 0) stTestParam.u32SubNetInvoke = 1; MI_SYS_Init(0); s32Ret = MI_IPU_PCIECasWrapper_GetOfflineStaticInfo(NULL, stTestParam.ModelPath, &stCASOfflineModelInfo); if (s32Ret != MI_SUCCESS) { printf("fail to get %s static info\n", stTestParam.ModelPath); goto SYS_EXIT; } memset(&stIPUDevAttr, 0, sizeof(stIPUDevAttr)); memset(&stCASDevAttr, 0, sizeof(stCASDevAttr)); stIPUDevAttr.u32CoreMask = stTestParam.u32IpuAffinity; stIPUDevAttr.u32MaxVariableBufSize = stCASOfflineModelInfo.au32VariableBufferSize[E_MI_IPU_PCIE_CAS_LOCAL_VARIABLE_BUFFER_IDX]; memcpy(&stCASDevAttr.stIPUDevAttr, &stIPUDevAttr, sizeof(stIPUDevAttr)); memcpy(stCASDevAttr.au32MaxVariableBufSize, stCASOfflineModelInfo.au32VariableBufferSize, sizeof(MI_U32)*stCASOfflineModelInfo.u32SocNum); stCASDevAttr.u32SocNum = stCASOfflineModelInfo.u32SocNum; s32Ret = MI_IPU_PCIECasWrapper_CreateDevice(&stCASDevAttr, NULL, NULL, E_MI_IPU_PCIE_CAS_WORK_MODE_RC); if (s32Ret != MI_SUCCESS) { printf("Fail to Create Device, ret=%d\n", s32Ret); goto SYS_EXIT; } memset(&stIPUChnAttr, 0, sizeof(stIPUChnAttr)); stIPUChnAttr.u32InputBufDepth = 0; stIPUChnAttr.u32OutputBufDepth = 0; stIPUChnAttr.u32BatchMax = stTestParam.u32Nbatch; stIPUChnAttr.u32SubNetId = stTestParam.u32SubNetId; s32Ret = MI_IPU_PCIECasWrapper_CreateCHN(&u32ChnId, &stIPUChnAttr, NULL, stTestParam.ModelPath, E_MI_IPU_PCIE_CAS_WORK_MODE_RC); if (s32Ret != MI_SUCCESS) { printf("Fail to Create CHN, ret=%d\n", s32Ret); goto DESTROY_DEV; } pstModelDesc = malloc(sizeof(MI_IPU_ModelDesc_t)); if (!pstModelDesc) { printf("Fail to malloc model description\n"); goto DESTROY_CHN; } memset(pstModelDesc, 0, sizeof(MI_IPU_ModelDesc_t)); s32Ret = MI_IPU_GetSubNetDesc(u32ChnId, pstModelDesc); if (s32Ret != MI_SUCCESS) { printf("Get model desc failed!\n"); goto DESTROY_CHN; } if (stTestParam.u32SubNetId >= pstModelDesc->u32SubNetNum) { printf("This model(sub net num %u) not support sub net id %u!\n", pstModelDesc->u32SubNetNum, stTestParam.u32SubNetId); goto DESTROY_CHN; } pstTensorDesc = &pstModelDesc->astSubNetDesc[stTestParam.u32SubNetId].stSubNetInputOutputDesc; // allocate input/output buffers memset(&stIpuRunBufInfo, 0, sizeof(stIpuRunBufInfo)); s32Ret = IPU_Client_AllocTensors(pstTensorDesc, &stTestParam, &stIpuRunBufInfo, &stTensorAddrInfo, EN_INPUT_BUF, 0); if (s32Ret) { goto DESTROY_CHN; } s32Ret = IPU_Client_AllocTensors(pstTensorDesc, &stTestParam, &stIpuRunBufInfo, &stTensorAddrInfo, EN_OUTPUT_BUF, 0); if (s32Ret) { IPU_Client_FreeTensors(&stIpuRunBufInfo, EN_INPUT_BUF); goto DESTROY_CHN; } s32Ret = IPU_Client_GetInputTensorData(stTestParam.InputPath, &pInput, &file_len_in); if (s32Ret != MI_SUCCESS) { printf("Get input data failed!\n"); goto FREE_TENSOR; } memset(&stInvokParam, 0, sizeof(stInvokParam)); memset(&stSubNetInvokeParam, 0, sizeof(MI_IPU_SubNetBatchInvokeParam_t)); memset(&stIPUCASInvokeParam, 0, sizeof(MI_IPU_PCIECasSubNetBatchInvokeParam_t)); stInvokParam.u32BatchN = stTestParam.u32Nbatch; stInvokParam.s32TaskPrio = stTestParam.s32TaskPrio; stInvokParam.u32IpuAffinity = stTestParam.u32IpuAffinity; for (int i = 0; i < stTensorAddrInfo.u32InCnt + stTensorAddrInfo.u32OutCnt; i++) { stInvokParam.astArrayTensors[i] = stTensorAddrInfo.astArrayTensors[i]; } stSubNetInvokeParam.eBatchMode = E_IPU_BATCH_N_BUF_MODE; stSubNetInvokeParam.stInvokeParam = stInvokParam; stIPUCASInvokeParam.stSubnNetBatchInvokeParam = stSubNetInvokeParam; s32Ret = IPU_Client_InsertInputNbatch(pInput, pstTensorDesc, &stInvokParam); if (s32Ret != MI_SUCCESS) { printf("Insert input failed\n"); goto MUNMAP; } total_cnt = stInvokParam.u32BatchN * pstTensorDesc->u32InputTensorCount; // invalid output buffer for (batch_cnt = 0; batch_cnt < stInvokParam.u32BatchN; batch_cnt++) { for (cnt = 0; cnt < pstTensorDesc->u32OutputTensorCount; cnt++) { memset(stInvokParam.astArrayTensors[total_cnt].ptTensorData[0], 0, pstTensorDesc->astMI_OutputTensorDescs[cnt].s32AlignedBufSize); MI_SYS_FlushInvCache(stInvokParam.astArrayTensors[total_cnt].ptTensorData[0], pstTensorDesc->astMI_OutputTensorDescs[cnt].s32AlignedBufSize); total_cnt++; } } memset(&stRuntimeInfo, 0, sizeof(stRuntimeInfo)); while (count < stTestParam.u32LoopCount) { clock_gettime(CLOCK_MONOTONIC, &invoke_start); s32Ret = MI_IPU_PCIECasWrapper_SubNetInvoke(u32ChnId, &stIPUCASInvokeParam, &stRuntimeInfo, stTestParam.u32SubNetId, E_MI_IPU_PCIE_CAS_WORK_MODE_RC); if (s32Ret != MI_SUCCESS) { printf("Invoke failed\n"); goto FREE_TENSOR; } clock_gettime(CLOCK_MONOTONIC, &invoke_end); linux_time = (invoke_end.tv_sec * 1000000 + invoke_end.tv_nsec / 1000) - (invoke_start.tv_sec * 1000000 + invoke_start.tv_nsec / 1000); printf("Run model %s loop%d success, invoke time: %f us\n", stTestParam.ModelPath, count, linux_time); printf("============ Loop%d ipu_time=%lluus\n", count, stRuntimeInfo.u64IpuTime); total_linux_time += linux_time; total_ipu_time += stRuntimeInfo.u64IpuTime; total_bw += stRuntimeInfo.u64BandWidth; total_bw_rd += stRuntimeInfo.u64BandWidthRead; total_bw_wr += stRuntimeInfo.u64BandWidthWrite; count++; } printf("cycles=%lfus linux_fps=%lffps ipu_fps=%lffps bandwidth_total=%llubytes bandwidth_rd=%llubytes bandwidth_wr=%llubytes\n", total_ipu_time/stTestParam.u32LoopCount, 1/(total_linux_time/stTestParam.u32Nbatch/stTestParam.u32LoopCount/1000000), 1/(total_ipu_time/stTestParam.u32LoopCount/1000000), total_bw/stTestParam.u32LoopCount, total_bw_rd/stTestParam.u32LoopCount, total_bw_wr/stTestParam.u32LoopCount); MUNMAP: if (stTestParam.InputPath) munmap(pInput, file_len_in); FREE_TENSOR: IPU_Client_FreeTensors(&stIpuRunBufInfo, EN_INPUT_BUF); IPU_Client_FreeTensors(&stIpuRunBufInfo, EN_OUTPUT_BUF); DESTROY_CHN: MI_IPU_PCIECasWrapper_DestroyCHN(u32ChnId, E_MI_IPU_PCIE_CAS_WORK_MODE_RC); DESTROY_DEV: MI_IPU_PCIECasWrapper_DestroyDevice(E_MI_IPU_PCIE_CAS_WORK_MODE_RC); SYS_EXIT: MI_SYS_Exit(0); return s32Ret; } -
ipu_service#include <stdio.h> #include <stdlib.h> #include <error.h> #include <sys/mman.h> #include <fcntl.h> #include <string.h> #include <sys/ioctl.h> #include <sys/types.h> #include <unistd.h> #include <errno.h> #include <pthread.h> #include <stdbool.h> #include <poll.h> #include <assert.h> #include <signal.h> #include <getopt.h> #include "mi_sys.h" #include "ipu_service.h" static MI_U32 g_u32MaxWorkThread = 0; static void _IPU_Service_ShowUsage(const char *progName) { printf("Usage: %s [options]\n", progName); printf("Options:\n"); printf(" -t show number of work thread\n"); printf(" -h show this help message\n"); } static MI_S32 _IPU_Service_ParseArgs(int argc, char *argv[]) { int opt; int option_index = 0; static struct option long_options[] = { {"t", required_argument, 0, 't'}, {"help", no_argument, 0, 'h'}, {0, 0, 0, 0} }; while ((opt = getopt_long(argc, argv, "t:h", long_options, &option_index)) != -1) { switch (opt) { case 't': { MI_U32 u32ThreadCount = strtoul(optarg, NULL, 10); g_u32MaxWorkThread = u32ThreadCount; break; } case 'h': _IPU_Service_ShowUsage(argv[0]); return 1; // Signal to exit after showing help default: printf("Unknown option: %c\n", opt); _IPU_Service_ShowUsage(argv[0]); return -1; } } // Check for remaining non-option arguments if (optind < argc) { printf("Unknown arguments: "); for (int i = optind; i < argc; i++) { printf("%s ", argv[i]); } printf("\n"); _IPU_Service_ShowUsage(argv[0]); return -1; } return 0; } int main(int argc, char *argv[]) { MI_S32 s32Ret; MI_IPU_PCIECasServiceConfig_t stCasServiceCfg; // Parse command line arguments s32Ret = _IPU_Service_ParseArgs(argc, argv); if (s32Ret < 0) { return -1; } else if (s32Ret > 0) { return 0; // Help was shown, exit normally } printf("IPU Service starting with thread number: %u\n", g_u32MaxWorkThread); MI_SYS_Init(0); memset(&stCasServiceCfg, 0, sizeof(stCasServiceCfg)); stCasServiceCfg.u32MaxWorkThread = g_u32MaxWorkThread; if (MI_IPU_PCIECasWrapper_RunService(&stCasServiceCfg) != MI_SUCCESS) { printf("Failed to start EP service\n"); return -1; } MI_IPU_PCIECasWrapper_StopService(); MI_SYS_Exit(0); printf("Service exited cleanly\n"); return 0; }
2. API REFERENCE¶
2.1. Functional Module APIs¶
| API Name | Function |
|---|---|
| MI_IPU_PCIECasWrapper_GetOfflineStaticInfo | Read static information of cascade offline model |
| MI_IPU_PCIECasWrapper_CreateDevice | Create cascade device |
| MI_IPU_PCIECasWrapper_CreateCHN | Create cascade channel |
| MI_IPU_PCIECasWrapper_SubNetInvoke | Trigger cascade model inference |
| MI_IPU_PCIECasWrapper_QueryRemoteInputBufInfo | Query remote input buffer info |
| MI_IPU_PCIECasWrapper_SetRemoteInputBuf | Write remote input buffers |
| MI_IPU_PCIECasWrapper_GetRemoteInputBuf | Read remote input buffers |
| MI_IPU_PCIECasWrapper_DestroyCHN | Destroy cascade channel |
| MI_IPU_PCIECasWrapper_DestroyDevice | Destroy cascade device |
| MI_IPU_PCIECasWrapper_RunService | Start EP-side service |
| MI_IPU_PCIECasWrapper_StopService | Stop EP-side service |
2.2. MI_IPU_PCIECasWrapper_GetOfflineStaticInfo¶
-
Function
Parse the offline model header information to obtain the number of SoCs, model size, and variable buffer requirements.
-
Syntax
MI_S32 MI_IPU_PCIECasWrapper_GetOfflineStaticInfo(SerializedReadFunc pReadFunc, char *pReadCtx, MI_IPU_PCIECasOfflineModelStaticInfo_t *pStaticInfo); -
Parameters
Parameter Name Description Input/Output pReadFunc User-defined file reading function (set to NULL to use the default file reading function provided by IPU Cascade API) Input pReadCtx Model path Input pStaticInfo Pointer to the offline cascade model static information structure Output -
Return Value
-
MI_SUCCESS indicates success
-
Non-MI_SUCCESS indicates failure. Refer to Error Codes
-
-
Dependencies
-
Header file: mi_ipu_pcie_cascade.h
-
Library file: libmi_ipu.so
-
-
Example
MI_IPU_PCIECasOfflineModelStaticInfo_t stStaticInfo; memset(&stStaticInfo, 0, sizeof(stStaticInfo)); if (MI_IPU_PCIECasWrapper_GetOfflineStaticInfo(NULL, stTestParam.ModelPath, &stStaticInfo) != MI_SUCCESS) { printf("fail to read cascade model info\n"); return -1; }
2.3. MI_IPU_PCIECasWrapper_CreateDevice¶
-
Function
Create a cascade device and initialize the cascade runtime environment.
-
Syntax
MI_S32 MI_IPU_PCIECasWrapper_CreateDevice(MI_IPU_PCIECasDevAttr_t *pstIPUDevAttr, SerializedReadFunc pReadFunc, char *pReadCtx, MI_IPU_PCIECasWorkMode_e eWorkMode); -
Parameters
Parameter Name Description Input/Output pstIPUDevAttr Cascade device attributes, including SoC count and variable buffer limits for each SoC Input pReadFunc Optional firmware reading function Input pReadCtx Firmware path or context Input eWorkMode Work mode: E_MI_IPU_PCIE_CAS_WORK_MODE_RCorE_MI_IPU_PCIE_CAS_WORK_MODE_EPInput -
Return Value
-
MI_SUCCESS indicates success
-
Non-MI_SUCCESS indicates failure. Refer to Error Codes
-
-
Dependencies
-
Header file: mi_ipu_pcie_cascade.h
-
Library file: libmi_ipu.so
-
-
Example
MI_IPU_PCIECasDevAttr_t stCasAttr; memset(&stCasAttr, 0, sizeof(stCasAttr)); stCasAttr.u32SocNum = stStaticInfo.u32SocNum; memcpy(stCasAttr.au32MaxVariableBufSize, stStaticInfo.au32VariableBufferSize, sizeof(stCasAttr.au32MaxVariableBufSize)); if (MI_IPU_PCIECasWrapper_CreateDevice(&stCasAttr, NULL, NULL, E_MI_IPU_PCIE_CAS_WORK_MODE_RC) != MI_SUCCESS) { printf("create cascade device failed\n"); return -1; }
2.4. MI_IPU_PCIECasWrapper_CreateCHN¶
-
Function
Create a cascade channel.
-
Syntax
MI_S32 MI_IPU_PCIECasWrapper_CreateCHN(MI_IPU_CHN *ptChnId, MI_IPUChnAttr_t *pstChnAttr, SerializedReadFunc pReadFunc, char *pReadCtx, MI_IPU_PCIECasWorkMode_e eWorkMode); -
Parameters
Parameter Name Description Input/Output ptChnId Returns the successfully created channel ID Output pstChnAttr Channel attributes (input/output queue depth, subnet ID, etc.) Input pReadFunc Model reading function, can be NULL Input pReadCtx RC: model path; EP: model physical address context Input eWorkMode Work mode: RC/EP Input -
Return Value
-
MI_SUCCESS indicates success
-
Non-MI_SUCCESS indicates failure. Refer to Error Codes
-
-
Dependencies
-
Header file: mi_ipu_pcie_cascade.h
-
Library file: libmi_ipu.so
-
-
Example
MI_IPU_CHN u32ChnId = 0; MI_IPUChnAttr_t stChnAttr; memset(&stChnAttr, 0, sizeof(stChnAttr)); stChnAttr.u32InputBufDepth = 2; stChnAttr.u32OutputBufDepth = 2; if (MI_IPU_PCIECasWrapper_CreateCHN(&u32ChnId, &stChnAttr, NULL, stTestParam.ModelPath, E_MI_IPU_PCIE_CAS_WORK_MODE_RC) != MI_SUCCESS) { printf("create cascade channel failed\n"); return -1; }
2.5. MI_IPU_PCIECasWrapper_SubNetInvoke¶
-
Function
Execute cascade model inference.
-
Syntax
MI_S32 MI_IPU_PCIECasWrapper_SubNetInvoke(MI_IPU_CHN u32ChnId, MI_IPU_PCIECasSubNetBatchInvokeParam_t *pstInvokeParam, MI_IPU_RuntimeInfo_t *pstRuntimeInfo, MI_U32 u32SubNetId, MI_IPU_PCIECasWorkMode_e eWorkMode); -
Parameters
Parameter Name Description Input/Output u32ChnId Channel ID to execute Input pstInvokeParam Cascade batch parameters, including input/output Tensor information and shared output position Input pstRuntimeInfo Inference runtime information (time, bandwidth, etc.) Output u32SubNetId Target subnet ID Input eWorkMode Work mode: RC/EP Input -
Return Value
-
MI_SUCCESS indicates success
-
Non-MI_SUCCESS indicates failure. Refer to Error Codes
-
-
Dependencies
-
Header file: mi_ipu_pcie_cascade.h
-
Library file: libmi_ipu.so
-
-
Example
MI_IPU_PCIECasSubNetBatchInvokeParam_t stInvokeParam; memset(&stInvokeParam, 0, sizeof(stInvokeParam)); stInvokeParam.stSubnNetBatchInvokeParam.u32BatchN = stTestParam.u32Nbatch; /* Fill input/output Tensors according to model */ if (MI_IPU_PCIECasWrapper_SubNetInvoke(u32ChnId, &stInvokeParam, &stRuntimeInfo, stTestParam.u32SubNetId, E_MI_IPU_PCIE_CAS_WORK_MODE_RC) != MI_SUCCESS) { printf("invoke cascade subnet failed\n"); return -1; }
2.6. MI_IPU_PCIECasWrapper_QueryRemoteInputBufInfo¶
-
Function
Query the input tensor buffer information (count, size, and physical address) of a specific EP so that the RC side can build transfer linklists based on the real layout.
-
Syntax
MI_S32 MI_IPU_PCIECasWrapper_QueryRemoteInputBufInfo(MI_IPU_CHN u32ChnId, MI_U32 u32EpId, MI_IPU_PCIECasInputDesc_t *pstCasInputDesc); -
Parameters
Parameter Name Description Input/Output u32ChnId Channel ID to execute Input u32EpId Target EP board index Input pstCasInputDesc Returned remote input tensor descriptor pointer, containing u32TensorCountand each tensor buffer size/addressOutput -
Return Value
-
MI_SUCCESS indicates success
-
Non-MI_SUCCESS indicates failure. Refer to Error Codes
-
-
Dependencies
-
Header file: mi_ipu_pcie_cascade.h
-
Library file: libmi_ipu.so
-
-
Example
MI_IPU_PCIECasInputDesc_t stRemoteInputDesc; memset(&stRemoteInputDesc, 0, sizeof(stRemoteInputDesc)); if (MI_IPU_PCIECasWrapper_QueryRemoteInputBufInfo(u32ChnId, 0, &stRemoteInputDesc) != MI_SUCCESS) { printf("query remote input buffer failed\n"); return -1; }
2.7. MI_IPU_PCIECasWrapper_SetRemoteInputBuf¶
-
Function
Write local tensor data to the remote EP input buffer according to the provided linklist descriptor.
-
Syntax
MI_S32 MI_IPU_PCIECasWrapper_SetRemoteInputBuf(MI_IPU_CHN u32ChnId, MI_U32 u32EpId, MI_IPU_PCIECasTransferDesc_t *pstCasTransferDesc); -
Parameters
Parameter Name Description Input/Output u32ChnId Channel ID to execute Input u32EpId Target EP board index Input pstCasTransferDesc Transfer descriptor, containing u32LinklistCountentries (up toMI_IPU_PCIE_CASCADE_MAX_LINKLIST_CNT)Input -
Return Value
-
MI_SUCCESS indicates success
-
Non-MI_SUCCESS indicates failure. Refer to Error Codes
-
-
Dependencies
-
Header file: mi_ipu_pcie_cascade.h
-
Library file: libmi_ipu.so
-
-
Example
MI_IPU_PCIECasTransferDesc_t stTransferDesc; memset(&stTransferDesc, 0, sizeof(stTransferDesc)); stTransferDesc.u32LinklistCount = 1; stTransferDesc.astTransferLinklist[0].phySrcAddr = stLocalTensor.phyTensorAddr[0]; stTransferDesc.astTransferLinklist[0].phyDstAddr = stRemoteInputDesc.astInputTensroDesc[0].phyTensorAddr; stTransferDesc.astTransferLinklist[0].u64TransferSize = stRemoteInputDesc.astInputTensroDesc[0].u64TensorBufSize; if (MI_IPU_PCIECasWrapper_SetRemoteInputBuf(u32ChnId, 0, &stTransferDesc) != MI_SUCCESS) { printf("set remote input buffer failed\n"); return -1; }
2.8. MI_IPU_PCIECasWrapper_GetRemoteInputBuf¶
-
Function
Read data from the remote EP input buffer according to the linklist descriptor.
-
Syntax
MI_S32 MI_IPU_PCIECasWrapper_GetRemoteInputBuf(MI_IPU_CHN u32ChnId, MI_U32 u32EpId, MI_IPU_PCIECasTransferDesc_t *pstCasTransferDesc); -
Parameters
Parameter Name Description Input/Output u32ChnId Channel ID to execute Input u32EpId Target EP board index Input pstCasTransferDesc Transfer descriptor. Each entry specifies remote source address ( phySrcAddr), local destination (phyDstAddr), and transfer sizeInput -
Return Value
-
MI_SUCCESS indicates success
-
Non-MI_SUCCESS indicates failure. Refer to Error Codes
-
-
Dependencies
- Header file: mi_ipu_pcie_cascade.h
-
Example
MI_IPU_PCIECasTransferDesc_t stPullDesc; memset(&stPullDesc, 0, sizeof(stPullDesc)); stPullDesc.u32LinklistCount = 1; stPullDesc.astTransferLinklist[0].phySrcAddr = stRemoteInputDesc.astInputTensroDesc[0].phyTensorAddr; stPullDesc.astTransferLinklist[0].phyDstAddr = stLocalTensor.phyTensorAddr[0]; stPullDesc.astTransferLinklist[0].u64TransferSize = stRemoteInputDesc.astInputTensroDesc[0].u64TensorBufSize; if (MI_IPU_PCIECasWrapper_GetRemoteInputBuf(u32ChnId, 0, &stPullDesc) != MI_SUCCESS) { printf("get remote input buffer failed\n"); }
2.9. MI_IPU_PCIECasWrapper_DestroyCHN¶
-
Function
Destroy the specified cascade channel.
-
Syntax
MI_S32 MI_IPU_PCIECasWrapper_DestroyCHN(MI_IPU_CHN u32ChnId, MI_IPU_PCIECasWorkMode_e eWorkMode); -
Parameters
Parameter Name Description Input/Output u32ChnId Channel ID to destroy Input eWorkMode Work mode: RC/EP Input -
Return Value
-
MI_SUCCESS indicates success
-
Non-MI_SUCCESS indicates failure. Refer to Error Codes
-
-
Dependencies
-
Header file: mi_ipu_pcie_cascade.h
-
Library file: libmi_ipu.so
-
-
Example
MI_IPU_PCIECasWrapper_DestroyCHN(u32ChnId, E_MI_IPU_PCIE_CAS_WORK_MODE_RC);
2.10. MI_IPU_PCIECasWrapper_DestroyDevice¶
-
Function
Destroy the cascade device.
-
Syntax
MI_S32 MI_IPU_PCIECasWrapper_DestroyDevice(MI_IPU_PCIECasWorkMode_e eWorkMode); -
Parameters
Parameter Name Description Input/Output eWorkMode Work mode: RC/EP Input -
Return Value
-
MI_SUCCESS indicates success
-
Non-MI_SUCCESS indicates failure. Refer to Error Codes
-
-
Dependencies
-
Header file: mi_ipu_pcie_cascade.h
-
Library file: libmi_ipu.so
-
-
Example
MI_IPU_PCIECasWrapper_DestroyDevice(E_MI_IPU_PCIE_CAS_WORK_MODE_RC);
2.11. MI_IPU_PCIECasWrapper_RunService¶
-
Function
Start the cascade service loop on the EP side, establishing PCIe channels, heartbeat checking, and request handling threads.
-
Syntax
MI_S32 MI_IPU_PCIECasWrapper_RunService(const MI_IPU_PCIECasServiceConfig_t *pstConfig); -
Parameters
Parameter Name Description Input/Output pstConfig EP service configuration, including max worker threads ( u32MaxWorkThread), PCIe controller ID (u32PcieId), heartbeat timeout threshold (u32HeartbeatTimeoutCountThreshold), and heartbeat interval (s32HeartbeatTimeoutMs)Input -
Return Value
-
MI_SUCCESS indicates success
-
Non-MI_SUCCESS indicates failure. Refer to Error Codes
-
-
Dependencies
-
Header file: mi_ipu_pcie_cascade.h
-
Library file: libmi_ipu.so
-
-
Example
MI_IPU_PCIECasServiceConfig_t stServiceCfg = { .u32MaxWorkThread = 4, .u32PcieId = 0, .u32HeartbeatTimeoutCountThreshold = 30, .s32HeartbeatTimeoutMs = 1000, }; if (MI_IPU_PCIECasWrapper_RunService(&stServiceCfg) != MI_SUCCESS) { printf("run pcie cascade service failed\n"); return -1; }
2.12. MI_IPU_PCIECasWrapper_StopService¶
-
Function
Stop EP-side service threads and release related resources.
-
Syntax
MI_S32 MI_IPU_PCIECasWrapper_StopService(void); -
Parameters
None.
-
Return Value
-
MI_SUCCESS indicates success
-
Non-MI_SUCCESS indicates failure. Refer to Error Codes
-
-
Dependencies
-
Header file: mi_ipu_pcie_cascade.h
-
Library file: libmi_ipu.so
-
-
Example
MI_IPU_PCIECasWrapper_StopService();
3. DATA TYPES¶
3.1. Data Type Definitions¶
| Data Type | Function |
|---|---|
| MI_IPU_PCIECasWorkMode_e | Define RC/EP work modes |
| MI_IPU_PCIECasOfflineModelStaticInfo_t | Define IPU offline cascade model static information structure |
| MI_IPU_PCIECasDevAttr_t | Define IPU cascade device attribute structure |
| MI_IPU_PCIECasPosition_t | Define model output position and offset structure |
| MI_IPU_PCIECasSubNetBatchInvokeParam_t | Define cascade model subnet batch parameter structure |
| MI_IPU_PCIECasServiceConfig_t | Define EP service runtime configuration |
| MI_IPU_PCIECasTensorDesc_t | Define remote tensor buffer descriptor |
| MI_IPU_PCIECasInputDesc_t | Define remote input tensor collection descriptor |
| MI_IPU_PCIECasTransferLinklist_t | Define transfer linklist node structure |
| MI_IPU_PCIECasTransferDesc_t | Define transfer linklist descriptor |
3.2. MI_IPU_PCIECasWorkMode_e¶
-
Description
Define the work modes supported by IPU Cascade API, distinguishing between RC and EP side interface calls
-
Syntax
typedef enum { E_MI_IPU_PCIE_CAS_WORK_MODE_RC = 0, E_MI_IPU_PCIE_CAS_WORK_MODE_EP, } MI_IPU_PCIECasWorkMode_e; -
Members
Member Name Description E_MI_IPU_PCIE_CAS_WORK_MODE_RC Call API in RC mode E_MI_IPU_PCIE_CAS_WORK_MODE_EP Call API in EP mode
3.3. MI_IPU_PCIECasOfflineModelStaticInfo_t¶
-
Description
Define the IPU offline cascade model static information structure
-
Syntax
typedef struct MI_IPU_PCIECasOfflineModelStaticInfo_s { MI_U32 u32SocNum; MI_U64 u64OfflineModelSize; MI_U32 au32VariableBufferSize[SGS_MULTI_SOC_NUM]; } MI_IPU_PCIECasOfflineModelStaticInfo_t; -
Members
Member Name Description u32SocNum Number of SoCs required to run the offline cascade model u64OfflineModelSize Size of the offline cascade model au32VariableBufferSize Variable buffer size required by the offline model on each SoC
3.4. MI_IPU_PCIECasDevAttr_t¶
-
Description
Define the IPU cascade device attribute structure
-
Syntax
typedef struct MI_IPU_PCIECasDevAttr_s { MI_U32 u32SocNum; MI_U32 au32MaxVariableBufSize[SGS_MULTI_SOC_NUM]; MI_IPU_DevAttr_t stIPUDevAttr; MI_U32 au32Reserve[8]; } MI_IPU_PCIECasDevAttr_t; -
Members
Member Name Description u32SocNum Number of SoCs required to run the offline cascade model au32MaxVariableBufSize Variable buffer size required by the offline model on each SoC stIPUDevAttr MI IPU device attribute au32Reserve Reserved field
3.5. MI_IPU_PCIECasPosition_t¶
-
Description
Define the cascade offline model output offset information structure
-
Syntax
typedef struct MI_IPU_PCIECasPosition_s { MI_U32 u32OutIndex; MI_U64 u64OffsetByBytes; } MI_IPU_PCIECasPosition_t; -
Members
Member Name Description u32OutIndex Index of the output requiring offset u64OffsetByBytes Byte offset relative to the output start address
3.6. MI_IPU_PCIECasSubNetBatchInvokeParam_t¶
-
Description
Define batch parameter information for inference of cascade offline models
-
Syntax
typedef struct MI_IPU_PCIECasSubNetBatchInvokeParam_s { MI_IPU_SubNetBatchInvokeParam_t stSubnNetBatchInvokeParam; MI_IPU_PCIECasPosition_t * pstPosition; MI_U32 u32PositionNum; } MI_IPU_PCIECasSubNetBatchInvokeParam_t; -
Members
Member Name Description stSubnNetBatchInvokeParam Standard subnet batch parameter, inherited from MI IPU pstPosition Pointer to array of cascade offline model output offset information u32PositionNum Number of outputs requiring offset in the cascade offline model
3.7. MI_IPU_PCIECasServiceConfig_t¶
-
Description
Define the EP-side service runtime configuration.
-
Syntax
typedef struct MI_IPU_PCIECasServiceConfig_s { MI_U32 u32MaxWorkThread; MI_U32 u32PcieId; MI_U32 u32HeartbeatTimeoutCountThreshold; MI_S32 s32HeartbeatTimeoutMs; MI_U32 au32Reserve[8]; } MI_IPU_PCIECasServiceConfig_t; -
Members
Member Name Description u32MaxWorkThread Maximum number of worker threads on EP u32PcieId Selected PCIe controller/link ID u32HeartbeatTimeoutCountThreshold Heartbeat timeout counter threshold indicating RC disconnect s32HeartbeatTimeoutMs Heartbeat interval in milliseconds au32Reserve Reserved
3.8. MI_IPU_PCIECasTensorDesc_t¶
-
Description
Define a remote input tensor buffer descriptor.
-
Syntax
typedef struct MI_IPU_PCIECasTensorDesc_s { MI_U64 u64TensorBufSize; MI_PHY phyTensorAddr; } MI_IPU_PCIECasTensorDesc_t; -
Members
Member Name Description u64TensorBufSize Tensor buffer size in bytes phyTensorAddr Physical address of the buffer (EP view)
3.9. MI_IPU_PCIECasInputDesc_t¶
-
Description
Define the input tensor collection information on the remote EP.
-
Syntax
typedef struct MI_IPU_PCIECasInputDesc_s { MI_U32 u32TensorCount; MI_IPU_PCIECasTensorDesc_t astInputTensroDesc[MI_IPU_MAX_TENSOR_CNT]; } MI_IPU_PCIECasInputDesc_t; -
Members
Member Name Description u32TensorCount Number of input tensors astInputTensroDesc Array that describes each tensor's physical address and buffer size (up to MI_IPU_MAX_TENSOR_CNT)
3.10. MI_IPU_PCIECasTransferLinklist_t¶
-
Description
Define a linklist node for a transfer operation.
-
Syntax
typedef struct MI_IPU_PCIECasTransferLinkList_s { MI_PHY phySrcAddr; MI_PHY phyDstAddr; MI_U64 u64TransferSize; } MI_IPU_PCIECasTransferLinklist_t; -
Members
Member Name Description phySrcAddr Source physical address (RC or EP) phyDstAddr Destination physical address (RC or EP) u64TransferSize Bytes transferred in this node
3.11. MI_IPU_PCIECasTransferDesc_t¶
-
Description
Define the chain of transfer operations.
-
Syntax
typedef struct MI_IPU_PCIECasTransferDesc_s { MI_U32 u32LinklistCount; MI_IPU_PCIECasTransferLinklist_t astTransferLinklist[MI_IPU_PCIE_CASCADE_MAX_LINKLIST_CNT]; } MI_IPU_PCIECasTransferDesc_t; -
Members
Member Name Description u32LinklistCount Number of transfer nodes, up to MI_IPU_PCIE_CASCADE_MAX_LINKLIST_CNTastTransferLinklist Array describing each transfer's source/destination/size
4. ERROR CODES¶
Table 4-1 IPU Cascade Error Codes
| Error Code | Macro Definition | Description |
|---|---|---|
| 0 | MI_SUCCESS | Success |
| 1 | E_MI_IPU_PCIE_CAS_ERR_INVALID_PARAM | Invalid or missing parameter |
| 2 | E_MI_IPU_PCIE_CAS_ERR_NOMEM | Insufficient system memory |
| 3 | E_MI_IPU_PCIE_CAS_ERR_NOBUF | Cascade buffer unavailable or not allocated |
| 4 | E_MI_IPU_PCIE_CAS_ERR_TIMEOUT | Operation timeout |
| 5 | E_MI_IPU_PCIE_CAS_ERR_PCIE_INIT_FAIL | PCIe / communication initialization failure |
| 6 | E_MI_IPU_PCIE_CAS_ERR_MISMATCH_MODEL | Offline model mismatch with platform/mode |
| 7 | E_MI_IPU_PCIE_CAS_ERR_INVALID_SOC_NUM | Invalid SoC count declared by the model |
| 8 | E_MI_IPU_PCIE_CAS_ERR_RC_INVOKE_FAIL | RC-side inference failure |
| 9 | E_MI_IPU_PCIE_CAS_ERR_EP_INVOKE_FAIL | EP-side inference failure |
| 10 | E_MI_IPU_PCIE_CAS_ERR_FAIL | Unknown or general failure |
| 11 | E_MI_IPU_PCIE_CAS_ERR_FILE_OPERATION | File read/write failure |
| 12 | E_MI_IPU_PCIE_CAS_ERR_CONNECTION_FAIL | RC–EP connection failure |
| 13 | E_MI_IPU_PCIE_CAS_ERR_MISMATCH_MSG | Message type/content mismatch |
| 14 | E_MI_IPU_PCIE_CAS_ERR_CONNECTION_TIMEOUT | Heartbeat or connection timeout |
| 15 | E_MI_IPU_PCIE_CAS_ERR_RESPONSE_THREAD_FAIL | Response-thread creation/runtime failure |
| 16 | E_MI_IPU_PCIE_CAS_ERR_NO_ENOUGH_EP | Not enough active EPs |
| 17 | E_MI_IPU_PCIE_CAS_ERR_INVALID_CHNID | Invalid or nonexistent channel ID |
| 18 | E_MI_IPU_PCIE_CAS_ERR_INVALID_SUBNET_ID | Invalid subnet ID requested by RC |
| 19 | E_MI_IPU_PCIE_CAS_ERR_MODEL_CORRUPTED | Offline model is corrupted |
| 20 | E_MI_IPU_PCIE_CAS_ERR_MAP | Address mapping failure (MMU/MAP error) |
| 21 | E_MI_IPU_PCIE_CAS_ERR_DEVICE_NOT_READY | Device is not ready for the requested operation |