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