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