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_instance.h"
12 :
13 : #include <algorithm>
14 :
15 : #include "log.h"
16 : #include "ccu_log.h"
17 :
18 : #include "hcom_common.h"
19 :
20 : #include "ccu_res_pack.h"
21 : #include "ccu_kernel_mgr.h"
22 : #include "ccu_res_specs.h"
23 : #include "ccu_dev_mgr_imp.h"
24 :
25 : namespace hcomm {
26 :
27 61 : CcuInstance::~CcuInstance()
28 : {
29 : // 主动释放资源保证时序,不得随意调整顺序
30 94 : for (auto &kernelHandle : kernelHandles_) {
31 33 : if (kernelHandle != 0) {
32 33 : (void)CcuKernelMgr::GetInstance(devLogicId_).UnRegister(kernelHandle);
33 33 : kernelHandle = 0;
34 : }
35 : }
36 61 : kernelHandles_.clear();
37 :
38 61 : resPack_ = nullptr; // 释放instance持有的CCU资源
39 61 : if (ccuDrvHandle_) {
40 53 : ccuDrvHandle_ = nullptr; // 先减少引用计数,再尝试关闭
41 53 : (void)CcuDeinitFeature(devLogicId_);
42 : // 尝试关闭CCU功能,最后一个调用时会关闭CCU驱动
43 : }
44 61 : }
45 :
46 2 : CcuResult CcuInstance::InitByInsType(const CcuInstanceType insType)
47 : {
48 2 : if (insType >= CcuInstanceType::CCU_UNUSED) {
49 0 : HCCL_ERROR("[CcuInstance][%s] failed, CcuInstanceType[%d] is invalid.",
50 : __func__, insType);
51 0 : return CcuResult::CCU_E_PARA;
52 : }
53 :
54 2 : devLogicId_ = HcclGetThreadDeviceId();
55 :
56 2 : if (!ccuDrvHandle_) {
57 2 : CCU_CHK_RET(CcuInitFeature(devLogicId_, ccuDrvHandle_));
58 : }
59 :
60 2 : if (!resPack_) {
61 2 : resPack_.reset(new (std::nothrow) CcuResPack());
62 2 : CCU_CHK_PTR_NULL(resPack_);
63 2 : CCU_CHK_RET(resPack_->InitByInsType(insType));
64 2 : CCU_CHK_RET(FillTotalResDescs());
65 : }
66 :
67 2 : return CcuResult::CCU_SUCCESS;
68 : }
69 :
70 51 : CcuResult CcuInstance::InitByResDescs(const CcuResDesc *descs[], uint32_t descNum)
71 : {
72 51 : if (descs == nullptr || descNum == 0 || descNum > hcomm::CCU_MAX_IODIE_NUM) {
73 0 : HCCL_ERROR("[CcuInstance][%s] failed, invalid descs[%p] descNum[%u].",
74 : __func__, descs, descNum);
75 0 : return CcuResult::CCU_E_PARA;
76 : }
77 :
78 51 : devLogicId_ = HcclGetThreadDeviceId();
79 :
80 51 : if (!ccuDrvHandle_) {
81 51 : CCU_CHK_RET(CcuInitFeature(devLogicId_, ccuDrvHandle_));
82 : }
83 :
84 50 : if (!resPack_) {
85 50 : resPack_.reset(new (std::nothrow) CcuResPack());
86 50 : CCU_CHK_PTR_NULL(resPack_);
87 50 : CCU_CHK_RET(resPack_->InitByResDescs(descs, descNum));
88 49 : CCU_CHK_RET(FillTotalResDescs());
89 : }
90 :
91 49 : return CcuResult::CCU_SUCCESS;
92 : }
93 :
94 2 : CcuResult CcuInstance::InitByAllRes()
95 : {
96 2 : devLogicId_ = HcclGetThreadDeviceId();
97 :
98 2 : if (!ccuDrvHandle_) {
99 2 : CCU_CHK_RET(CcuInitFeature(devLogicId_, ccuDrvHandle_));
100 : }
101 :
102 : // 申请当前 Device 上所有已使能 ioDie 的全部资源:
103 : // 先查询各 die 是否启用,仅对已使能的 die 调用 CcuGetXXXNum 获取资源总量,
104 : // 未启用的 die 其 resNum 保持 0(resNum 默认初始化为 0)
105 2 : std::array<hcomm::CcuResDesc, hcomm::CCU_MAX_IODIE_NUM> descs{};
106 1 : std::array<const hcomm::CcuResDesc *, hcomm::CCU_MAX_IODIE_NUM> descPtrs{};
107 3 : for (uint8_t i = 0; i < hcomm::CCU_MAX_IODIE_NUM; i++) {
108 2 : descs[i].dieId = i;
109 2 : descPtrs[i] = &descs[i];
110 : }
111 :
112 3 : for (uint8_t dieId = 0; dieId < hcomm::CCU_MAX_IODIE_NUM; dieId++) {
113 2 : bool dieEnable = false;
114 2 : CCU_CHK_RET(CcuGetDieEnableInfo(devLogicId_, dieId, dieEnable));
115 2 : if (!dieEnable) {
116 0 : continue; // 未启用的 die,resNum 保持 0
117 : }
118 :
119 2 : uint32_t num = 0;
120 : // 各资源类型总量查询(per-die),按块分的资源查的是块大小*块总数
121 2 : CCU_CHK_RET(CcuGetLoopEngineNum(devLogicId_, dieId, num));
122 2 : CCU_CHK_RET(descs[dieId].SetResNum(ResType::LOOP, num));
123 2 : CCU_CHK_RET(CcuGetMsNum(devLogicId_, dieId, num));
124 2 : CCU_CHK_RET(descs[dieId].SetResNum(ResType::MS, num));
125 2 : CCU_CHK_RET(CcuGetCkeNum(devLogicId_, dieId, num));
126 2 : CCU_CHK_RET(descs[dieId].SetResNum(ResType::CKE, num));
127 2 : CCU_CHK_RET(CcuGetXnNum(devLogicId_, dieId, num));
128 2 : CCU_CHK_RET(descs[dieId].SetResNum(ResType::XN, num));
129 2 : CCU_CHK_RET(CcuGetGsaNum(devLogicId_, dieId, num));
130 2 : CCU_CHK_RET(descs[dieId].SetResNum(ResType::GSA, num));
131 2 : CCU_CHK_RET(CcuGetInstructionNum(devLogicId_, dieId, num));
132 2 : CCU_CHK_RET(descs[dieId].SetResNum(ResType::INS, num));
133 2 : CCU_CHK_RET(CcuGetMissionNum(devLogicId_, dieId, num));
134 2 : CCU_CHK_RET(descs[dieId].SetResNum(ResType::MISSION, num));
135 : }
136 :
137 1 : if (!resPack_) {
138 1 : resPack_.reset(new (std::nothrow) CcuResPack());
139 1 : CCU_CHK_PTR_NULL(resPack_);
140 2 : CCU_CHK_RET(resPack_->InitByResDescs(descPtrs.data(), hcomm::CCU_MAX_IODIE_NUM));
141 1 : CCU_CHK_RET(FillTotalResDescs());
142 : }
143 :
144 1 : return CcuResult::CCU_SUCCESS;
145 : }
146 :
147 44 : CcuResult CcuInstance::Reset()
148 : {
149 44 : if (!resPack_) {
150 0 : return CcuResult::CCU_SUCCESS;
151 : }
152 :
153 44 : untranslatedKernelHandles_.clear();
154 44 : CCU_CHK_RET(resPack_->Reset());
155 44 : return CcuResult::CCU_SUCCESS;
156 : }
157 :
158 44 : CcuResPack *CcuInstance::GetResPack()
159 : {
160 44 : return resPack_.get();
161 : }
162 :
163 : // 累加某 die 上某资源 vector 中各 ResInfo::num,得到该 die 该资源的占用数量
164 1144 : static uint32_t SumResNum(const std::vector<ResInfo> &resInfos, std::string resName)
165 : {
166 1144 : uint32_t total = 0;
167 1740 : for (const auto &info : resInfos) {
168 596 : total += info.num;
169 : }
170 1144 : HCCL_INFO("[CcuInstance][FillTotalResDescs] resType: %s, resNum: %u", resName.c_str(), total);
171 1144 : return total;
172 : }
173 :
174 52 : CcuResult CcuInstance::FillTotalResDescs()
175 : {
176 52 : if (resPack_ == nullptr) {
177 0 : HCCL_ERROR("[CcuInstance][%s] failed, resPack_ is nullptr.", __func__);
178 0 : return CcuResult::CCU_E_INTERNAL;
179 : }
180 52 : const auto &resRepo = resPack_->GetCcuResRepo();
181 :
182 156 : for (uint8_t dieId = 0; dieId < CCU_MAX_IODIE_NUM; dieId++) {
183 104 : totalResDescs_[dieId].dieId = dieId;
184 : // 各资源类型占用数量 = block 路径 + 非 block 连续路径之和
185 520 : CCU_CHK_RET(totalResDescs_[dieId].SetResNum(ResType::LOOP,
186 : SumResNum(resRepo.blockLoopEngine[dieId], "blockLoopEngine") + SumResNum(resRepo.loopEngine[dieId], "loopEngine")));
187 520 : CCU_CHK_RET(totalResDescs_[dieId].SetResNum(ResType::MS,
188 : SumResNum(resRepo.blockMs[dieId], "blockMs") + SumResNum(resRepo.ms[dieId], "ms")));
189 520 : CCU_CHK_RET(totalResDescs_[dieId].SetResNum(ResType::CKE,
190 : SumResNum(resRepo.blockCke[dieId], "blockCke") + SumResNum(resRepo.cke[dieId], "cke")));
191 520 : CCU_CHK_RET(totalResDescs_[dieId].SetResNum(ResType::XN,
192 : SumResNum(resRepo.blockXn[dieId], "blockXn") + SumResNum(resRepo.xn[dieId], "xn")));
193 520 : CCU_CHK_RET(totalResDescs_[dieId].SetResNum(ResType::GSA,
194 : SumResNum(resRepo.blockGsa[dieId], "blockGsa") + SumResNum(resRepo.gsa[dieId], "gsa")));
195 312 : CCU_CHK_RET(totalResDescs_[dieId].SetResNum(ResType::MISSION, SumResNum(resRepo.mission.mission[dieId], "mission")));
196 : // INS 当前无对应占用资源项,写 0
197 104 : CCU_CHK_RET(totalResDescs_[dieId].SetResNum(ResType::INS, 0));
198 : }
199 52 : return CcuResult::CCU_SUCCESS;
200 : }
201 :
202 2 : const CcuResDesc &CcuInstance::GetTotalResDescs(uint8_t dieId) const
203 : {
204 2 : return totalResDescs_[dieId];
205 : }
206 :
207 33 : CcuResult CcuInstance::SaveKernel(const CcuKernelHandle kernelHandle)
208 : {
209 33 : kernelHandles_.push_back(kernelHandle);
210 33 : untranslatedKernelHandles_.push_back(kernelHandle);
211 33 : return CcuResult::CCU_SUCCESS;
212 : }
213 :
214 34 : const std::vector<CcuKernelHandle> &CcuInstance::GetUntranslatedKernels()
215 : {
216 34 : return untranslatedKernelHandles_;
217 : }
218 :
219 44 : CcuResult CcuInstance::BeginRegister()
220 : {
221 44 : if (registerState_ == RegisterState::REGISTERING) {
222 0 : HCCL_ERROR("[CcuInstance][%s] failed, previous register round is not ended, "
223 : "HcommCcuKernelRegisterEnd is missing before a new HcommCcuKernelRegisterStart.", __func__);
224 0 : return CcuResult::CCU_E_INTERNAL;
225 : }
226 44 : registerState_ = RegisterState::REGISTERING;
227 44 : return CcuResult::CCU_SUCCESS;
228 : }
229 :
230 44 : CcuResult CcuInstance::CheckRegistering() const
231 : {
232 44 : if (registerState_ != RegisterState::REGISTERING) {
233 0 : HCCL_ERROR("[CcuInstance][%s] failed, HcommCcuKernelRegister must be called between "
234 : "HcommCcuKernelRegisterStart and HcommCcuKernelRegisterEnd.", __func__);
235 0 : return CcuResult::CCU_E_INTERNAL;
236 : }
237 44 : return CcuResult::CCU_SUCCESS;
238 : }
239 :
240 34 : CcuResult CcuInstance::EndRegister()
241 : {
242 34 : if (registerState_ == RegisterState::IDLE) {
243 0 : HCCL_ERROR("[CcuInstance][%s] failed, HcommCcuKernelRegisterEnd is called without a matching "
244 : "HcommCcuKernelRegisterStart.", __func__);
245 0 : return CcuResult::CCU_E_INTERNAL;
246 : }
247 34 : if (registerState_ == RegisterState::REGISTER_ABORTED) {
248 1 : HCCL_WARNING("[CcuInstance][%s] previous register round was aborted due to error, "
249 : "close it to keep Start/End paired, no kernel will be translated.", __func__);
250 : }
251 34 : registerState_ = RegisterState::IDLE;
252 34 : return CcuResult::CCU_SUCCESS;
253 : }
254 :
255 11 : void CcuInstance::AbortRegister()
256 : {
257 11 : for (auto kernelHandle : untranslatedKernelHandles_) {
258 0 : if (kernelHandle == 0) {
259 0 : continue;
260 : }
261 0 : (void)CcuKernelMgr::GetInstance(devLogicId_).UnRegister(kernelHandle);
262 0 : auto it = std::find(kernelHandles_.begin(), kernelHandles_.end(), kernelHandle);
263 0 : if (it != kernelHandles_.end()) {
264 0 : kernelHandles_.erase(it);
265 : }
266 : }
267 11 : untranslatedKernelHandles_.clear();
268 11 : registerState_ = RegisterState::REGISTER_ABORTED;
269 11 : }
270 :
271 : } // namespace hcomm
|