Line data Source code
1 : /**
2 : * Copyright (c) 2026 Huawei Technologies Co., Ltd.
3 : * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4 : * CANN Open Software License Agreement Version 2.0 (the "License").
5 : * Please refer to the License for details. You may not use this file except in compliance with the License.
6 : * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7 : * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8 : * See LICENSE in the root of the software repository for the full text of the License.
9 : */
10 :
11 : #include "ccu_res.h"
12 :
13 : #include <array>
14 :
15 : #include "ccu_device_res.h"
16 : #include "ccu_device_pub.h"
17 :
18 : #include "ccu_log.h"
19 :
20 : #include "hcom_common.h"
21 : #include "op_base.h"
22 :
23 : #include "ccu_kernel_mgr.h"
24 : #include "ccu_instance_mgr.h"
25 : #include "ccu_res_desc.h"
26 : #include "ccu_res_desc_mgr.h"
27 : #include "ccu_res_type_converter.h"
28 :
29 132 : CcuResult HcommCcuInsResDescCreate(uint32_t dieId, HcommCcuResDescHandle *handle)
30 : {
31 132 : if (dieId >= hcomm::CCU_MAX_IODIE_NUM) {
32 1 : HCCL_ERROR("[%s] dieId[%u] is invalid, dieId should in [0, %u).", __func__, dieId, hcomm::CCU_MAX_IODIE_NUM);
33 1 : return CcuResult::CCU_E_PARA;
34 : }
35 :
36 131 : CCU_CHK_PTR_NULL(handle);
37 :
38 130 : int32_t devLogicId = INVALID_INT;
39 130 : CCU_CHK_RET(HcclDeviceRefresh(devLogicId));
40 129 : CCU_CHK_RET(hcomm::CcuInstanceMgr::GetInstance(devLogicId).GetResDescMgr().Create(dieId, *handle));
41 128 : HCCL_INFO("[%s] success, handle[0x%llx] dieId[%u]", __func__, *handle, dieId);
42 128 : return CcuResult::CCU_SUCCESS;
43 : }
44 :
45 132 : CcuResult HcommCcuInsResDescDestroy(HcommCcuResDescHandle handle)
46 : {
47 132 : int32_t devLogicId = INVALID_INT;
48 132 : CCU_CHK_RET(HcclDeviceRefresh(devLogicId));
49 131 : CCU_CHK_RET(hcomm::CcuInstanceMgr::GetInstance(devLogicId).GetResDescMgr().Destroy(handle));
50 128 : HCCL_INFO("[%s] success, handle[0x%llx]", __func__, handle);
51 128 : return CcuResult::CCU_SUCCESS;
52 : }
53 :
54 674 : CcuResult HcommCcuInsResDescSetNum(HcommCcuResDescHandle handle, HcommCcuResType resType, uint32_t resNum)
55 : {
56 674 : hcomm::ResType ccuResType{hcomm::ResType::INVALID};
57 674 : CCU_CHK_RET(hcomm::ConvertHcommCcuResTypeToHcclResType(resType, ccuResType));
58 :
59 673 : int32_t devLogicId = INVALID_INT;
60 673 : CCU_CHK_RET(HcclDeviceRefresh(devLogicId));
61 672 : CCU_CHK_RET(hcomm::CcuInstanceMgr::GetInstance(devLogicId).GetResDescMgr().SetResNum(handle, ccuResType, resNum));
62 670 : HCCL_INFO("[%s] success, handle[0x%llx] resType[%d] resNum[%u]", __func__, handle, resType, resNum);
63 670 : return CcuResult::CCU_SUCCESS;
64 : }
65 :
66 22 : CcuResult HcommCcuInsResDescQueryNum(HcommCcuResDescHandle handle, HcommCcuResType resType, uint32_t *num)
67 : {
68 22 : CCU_CHK_PTR_NULL(num);
69 21 : hcomm::ResType ccuResType{hcomm::ResType::INVALID};
70 21 : CCU_CHK_RET(hcomm::ConvertHcommCcuResTypeToHcclResType(resType, ccuResType));
71 :
72 20 : int32_t devLogicId = INVALID_INT;
73 20 : CCU_CHK_RET(HcclDeviceRefresh(devLogicId));
74 19 : CCU_CHK_RET(hcomm::CcuInstanceMgr::GetInstance(devLogicId).GetResDescMgr().QueryResNum(handle, ccuResType, *num));
75 17 : HCCL_INFO("[%s] success, handle[0x%llx] resType[%d] resNum[%u]", __func__, handle, resType, *num);
76 17 : return CcuResult::CCU_SUCCESS;
77 : }
78 :
79 8 : CcuResult HcommCcuInsResDescQueryDieId(HcommCcuResDescHandle handle, uint32_t *dieId)
80 : {
81 8 : CCU_CHK_PTR_NULL(dieId);
82 7 : int32_t devLogicId = INVALID_INT;
83 7 : CCU_CHK_RET(HcclDeviceRefresh(devLogicId));
84 6 : CCU_CHK_RET(hcomm::CcuInstanceMgr::GetInstance(devLogicId).GetResDescMgr().QueryDieId(handle, *dieId));
85 4 : HCCL_INFO("[%s] success, handle[0x%llx] dieId[%u]", __func__, handle, *dieId);
86 4 : return CcuResult::CCU_SUCCESS;
87 : }
88 :
89 8 : CcuResult HcommCcuQueryRemainResDesc(HcommCcuResDescHandle handle)
90 : {
91 8 : int32_t devLogicId = INVALID_INT;
92 8 : CCU_CHK_RET(HcclDeviceRefresh(devLogicId));
93 :
94 : // CCU 驱动未拉起时无法查询硬件资源, 提前返回
95 7 : if (!hcomm::CcuIsInited(devLogicId)) {
96 1 : HCCL_WARNING("[%s] failed, CCU feature is not inited, devLogicId[%d].",
97 : __func__, devLogicId);
98 1 : return CcuResult::CCU_E_UNAVAIL;
99 : }
100 :
101 6 : auto &resDescMgr = hcomm::CcuInstanceMgr::GetInstance(devLogicId).GetResDescMgr();
102 :
103 : // die 合法性前置校验
104 6 : uint32_t dieId = 0;
105 6 : CCU_CHK_RET(resDescMgr.QueryDieId(handle, dieId));
106 4 : bool enableFlag = false;
107 : // CcuGetDieEnableInfo 中会做dieId合法性校验以及查询是否使能
108 4 : CCU_CHK_RET(hcomm::CcuGetDieEnableInfo(devLogicId, static_cast<uint8_t>(dieId), enableFlag));
109 4 : if (!enableFlag) {
110 1 : HCCL_WARNING("[%s] failed, dieId[%u] is not enabled.", __func__, dieId);
111 1 : return CcuResult::CCU_E_UNAVAIL;
112 : }
113 :
114 : // 委托 CcuResDescMgr 在锁内查询剩余资源,防止 Get→Destroy 的 use-after-free
115 3 : CCU_CHK_RET(resDescMgr.QueryRemainRes(handle, devLogicId));
116 :
117 3 : HCCL_INFO("[%s] success, handle[0x%llx] dieId[%u]", __func__, handle, dieId);
118 3 : return CcuResult::CCU_SUCCESS;
119 : }
120 :
121 10 : static CcuResult ConvertCcuResReqToResDesc(hcomm::CcuResDescMgr &resDescMgr,
122 : HcommCcuResDescHandle resDesc, const hcomm::CcuResReq &resReq, uint32_t instrCount, uint32_t selectedDie)
123 : {
124 10 : const uint32_t loopNum = resReq.loopEngineReq[selectedDie] + resReq.blockLoopEngineReq[selectedDie];
125 10 : const uint32_t msNum = resReq.msReq[selectedDie] + resReq.blockMsReq[selectedDie];
126 10 : const uint32_t xnNum = resReq.xnReq[selectedDie] + resReq.blockXnReq[selectedDie];
127 10 : const uint32_t gsaNum = resReq.gsaReq[selectedDie] + resReq.blockGsaReq[selectedDie];
128 10 : const uint32_t ckeNum = resReq.ckeReq[selectedDie] + resReq.blockCkeReq[selectedDie];
129 10 : const uint32_t missionNum = resReq.missionReq.req[selectedDie];
130 :
131 10 : CCU_CHK_RET(resDescMgr.SetResNum(resDesc, hcomm::ResType::LOOP, loopNum));
132 10 : CCU_CHK_RET(resDescMgr.SetResNum(resDesc, hcomm::ResType::MS, msNum));
133 10 : CCU_CHK_RET(resDescMgr.SetResNum(resDesc, hcomm::ResType::XN, xnNum));
134 10 : CCU_CHK_RET(resDescMgr.SetResNum(resDesc, hcomm::ResType::GSA, gsaNum));
135 9 : CCU_CHK_RET(resDescMgr.SetResNum(resDesc, hcomm::ResType::CKE, ckeNum));
136 9 : CCU_CHK_RET(resDescMgr.SetResNum(resDesc, hcomm::ResType::MISSION, missionNum));
137 9 : CCU_CHK_RET(resDescMgr.SetResNum(resDesc, hcomm::ResType::INS, instrCount));
138 :
139 9 : HCCL_INFO("[HcommCcuKernelQueryResReq] success, aggregated resource request, not allocated resource, "
140 : "resDesc[0x%llx], dieId[%u], loop[%u], ms[%u], xn[%u], gsa[%u], cke[%u], mission[%u], ins[%u].",
141 : static_cast<unsigned long long>(resDesc), selectedDie, loopNum, msNum, xnNum, gsaNum, ckeNum, missionNum,
142 : instrCount);
143 9 : return CcuResult::CCU_SUCCESS;
144 : }
145 :
146 24 : CcuResult HcommCcuKernelQueryResReq(const void *kernelFunc, const void **kernelArgs,
147 : uint32_t argNum, HcommCcuResDescHandle resDesc)
148 : {
149 24 : HCCL_INFO("[%s] begin, argNum[%u], resDesc[0x%llx], kernelFunc[%p].",
150 : __func__, argNum, static_cast<unsigned long long>(resDesc), kernelFunc);
151 24 : CCU_CHK_PTR_NULL(kernelFunc);
152 23 : if (resDesc == 0 || argNum > 1) {
153 2 : HCCL_ERROR("[%s] failed, resDesc[0x%llx], argNum[%u].",
154 : __func__, static_cast<unsigned long long>(resDesc), argNum);
155 2 : return CcuResult::CCU_E_PARA;
156 : }
157 21 : if (argNum == 1) {
158 9 : CHK_PRT_RET(kernelArgs == nullptr,
159 : HCCL_ERROR("[%s] failed, kernelArgs is nullptr while argNum[%u].", __func__, argNum),
160 : CcuResult::CCU_E_PTR);
161 8 : CHK_PRT_RET(kernelArgs[0] == nullptr,
162 : HCCL_ERROR("[%s] failed, kernelArgs[0] is nullptr while argNum[%u].", __func__, argNum),
163 : CcuResult::CCU_E_PTR);
164 : }
165 :
166 19 : int32_t devLogicId = INVALID_INT;
167 19 : CCU_CHK_RET(HcclDeviceRefresh(devLogicId));
168 18 : auto &resDescMgr = hcomm::CcuInstanceMgr::GetInstance(devLogicId).GetResDescMgr();
169 18 : uint32_t descriptorDieId = hcomm::CCU_MAX_IODIE_NUM;
170 18 : CCU_CHK_RET(resDescMgr.QueryDieId(resDesc, descriptorDieId));
171 16 : HCCL_INFO("[%s] descriptor queried, resDesc[0x%llx], descriptorDieId[%u].",
172 : __func__, static_cast<unsigned long long>(resDesc), descriptorDieId);
173 16 : if (descriptorDieId >= hcomm::CCU_MAX_IODIE_NUM) {
174 1 : HCCL_ERROR("[%s] failed, descriptor dieId[%u] is invalid.", __func__, descriptorDieId);
175 1 : return CcuResult::CCU_E_PARA;
176 : }
177 :
178 : CCU_EXCEPTION_HANDLE_BEGIN
179 15 : hcomm::CcuResReq resReq{};
180 15 : uint32_t instrCount = 0;
181 15 : auto &kernelMgr = hcomm::CcuKernelMgr::GetInstance(devLogicId);
182 16 : CCU_CHK_RET(kernelMgr.GetKernelResourceRequest(
183 : descriptorDieId, "KernelForHcommCcuKernelQueryResReq",
184 : kernelFunc, kernelArgs, argNum, resReq, instrCount));
185 10 : CCU_CHK_RET(ConvertCcuResReqToResDesc(
186 : resDescMgr, resDesc, resReq, instrCount, descriptorDieId));
187 1 : CCU_EXCEPTION_HANDLE_END
188 :
189 9 : return CcuResult::CCU_SUCCESS;
190 : }
191 :
192 : // Deprecated: legacy internal CCU instance creation path.
193 3 : CcuResult HcommCcuInsCreateLegacy(const CcuInstanceType insType, CcuInsHandle *ccuInsHandle)
194 : {
195 3 : CCU_CHK_PTR_NULL(ccuInsHandle);
196 :
197 3 : int32_t devLogicId = INVALID_INT;
198 3 : CCU_CHK_RET(HcclDeviceRefresh(devLogicId));
199 2 : auto &insMgr = hcomm::CcuInstanceMgr::GetInstance(devLogicId);
200 :
201 2 : CCU_CHK_RET(insMgr.CreateByInsType(insType, *ccuInsHandle));
202 :
203 2 : return CcuResult::CCU_SUCCESS;
204 : }
205 :
206 56 : CcuResult HcommCcuInsCreate(
207 : const HcommCcuResDescHandle *resDescs, uint32_t resDescNum, CcuInsHandle *ccuInsHandle)
208 : {
209 56 : CCU_CHK_PTR_NULL(resDescs);
210 56 : CCU_CHK_PTR_NULL(ccuInsHandle);
211 55 : if (resDescNum == 0 || resDescNum > hcomm::CCU_MAX_IODIE_NUM) {
212 1 : HCCL_ERROR("[%s] failed, resDescNum[%u] is invalid, should be in (0, %u].",
213 : __func__, resDescNum, hcomm::CCU_MAX_IODIE_NUM);
214 1 : return CcuResult::CCU_E_PARA;
215 : }
216 :
217 54 : int32_t devLogicId = INVALID_INT;
218 54 : CCU_CHK_RET(HcclDeviceRefresh(devLogicId));
219 53 : auto &insMgr = hcomm::CcuInstanceMgr::GetInstance(devLogicId);
220 :
221 : // 从 CcuResDescMgr 中用 resDesc 数组里的 Handle Get 获得 CcuResDesc,构造指针数组
222 53 : std::array<const hcomm::CcuResDesc *, hcomm::CCU_MAX_IODIE_NUM> descPtrs{};
223 159 : for (uint32_t i = 0; i < resDescNum; i++) {
224 106 : descPtrs[i] = insMgr.GetResDescMgr().Get(resDescs[i]);
225 106 : CCU_CHK_PTR_NULL(descPtrs[i]);
226 : }
227 :
228 : // 如果入参为 2 个 resDesc,里面的 dieId 不能重复
229 53 : if (resDescNum == 2 && descPtrs[0]->dieId == descPtrs[1]->dieId) {
230 1 : HCCL_ERROR("[%s] failed, dieId[%u] duplicated in resDescs.", __func__, descPtrs[0]->dieId);
231 1 : return CcuResult::CCU_E_PARA;
232 : }
233 :
234 52 : CCU_CHK_RET(insMgr.CreateByResDescs(descPtrs.data(), resDescNum, *ccuInsHandle));
235 49 : return CcuResult::CCU_SUCCESS;
236 : }
237 :
238 5 : CcuResult HcommCcuInsCreateDefault(
239 : const uint32_t *dieIds, uint32_t dieNum, CcuInsHandle *ccuInsHandle)
240 : {
241 : (void)dieIds;
242 : (void)dieNum;
243 : // dieIds/dieNum 为保留参数,当前版本申请当前 Device 上所有已使能 ioDie 的全部资源
244 5 : CCU_CHK_PTR_NULL(ccuInsHandle);
245 :
246 4 : int32_t devLogicId = INVALID_INT;
247 4 : CCU_CHK_RET(HcclDeviceRefresh(devLogicId));
248 3 : CCU_CHK_RET(hcomm::CcuInstanceMgr::GetInstance(devLogicId).CreateByAllRes(*ccuInsHandle));
249 1 : return CcuResult::CCU_SUCCESS;
250 : }
251 :
252 5 : CcuResult HcommCcuInsQueryResDesc(CcuInsHandle ccuInsHandle, HcommCcuResDescHandle resDesc)
253 : {
254 5 : if (ccuInsHandle == 0 || resDesc == 0) {
255 2 : HCCL_ERROR("[%s] failed, invalid ccuInsHandle[%llu] resDesc[%llu].",
256 : __func__, ccuInsHandle, resDesc);
257 2 : return CcuResult::CCU_E_PARA;
258 : }
259 :
260 3 : int32_t devLogicId = INVALID_INT;
261 3 : CCU_CHK_RET(HcclDeviceRefresh(devLogicId));
262 2 : auto &insMgr = hcomm::CcuInstanceMgr::GetInstance(devLogicId);
263 :
264 2 : auto &resDescMgr = insMgr.GetResDescMgr();
265 2 : uint32_t descriptorDieId = hcomm::CCU_MAX_IODIE_NUM;
266 2 : CCU_CHK_RET(resDescMgr.QueryDieId(resDesc, descriptorDieId));
267 2 : const uint8_t dieId = static_cast<uint8_t>(descriptorDieId);
268 2 : if (dieId >= hcomm::CCU_MAX_IODIE_NUM) {
269 0 : HCCL_ERROR("[%s] failed, dieId[%u] is invalid.", __func__, dieId);
270 0 : return CcuResult::CCU_E_PARA;
271 : }
272 :
273 2 : CCU_CHK_RET(insMgr.QueryInsResDesc(ccuInsHandle, dieId, resDesc));
274 :
275 2 : return CcuResult::CCU_SUCCESS;
276 : }
277 :
278 56 : CcuResult HcommCcuInsDestroy(CcuInsHandle insHandle)
279 : {
280 56 : int32_t devLogicId = INVALID_INT;
281 56 : CCU_CHK_RET(HcclDeviceRefresh(devLogicId));
282 55 : CCU_CHK_RET(hcomm::CcuInstanceMgr::GetInstance(devLogicId).Destroy(insHandle));
283 :
284 51 : return CcuResult::CCU_SUCCESS;
285 : }
|