Line data Source code
1 : /**
2 : * Copyright (c) 2025 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_rep_translator.h"
12 : #include "exception_util.h"
13 : #include "ccu_api_exception.h"
14 : #include "ccu_rep_loopcall.h"
15 : #include "ccu_rep_funccall.h"
16 : #include "ccu_rep_type.h"
17 : #include "ccu_rep_loop.h"
18 : #include "ccu_assist.h"
19 :
20 : namespace Hccl {
21 : namespace CcuRep {
22 :
23 : template <typename T>
24 : bool CheckType(const std::shared_ptr<CcuRepBlock>& refer)
25 : {
26 : HCCL_INFO("[CheckType] refer->Type() = %d", refer->Type());
27 : return false;
28 : }
29 :
30 : template <>
31 2 : bool CheckType<CcuRepFuncBlock>(const std::shared_ptr<CcuRepBlock>& refer)
32 : {
33 2 : return refer->Type() == CcuRepType::FUNC_BLOCK ? true : false;
34 : }
35 :
36 : template <>
37 21 : bool CheckType<CcuRepLoopBlock>(const std::shared_ptr<CcuRepBlock>& refer)
38 : {
39 21 : return refer->Type() == CcuRepType::LOOP_BLOCK ? true : false;
40 : }
41 :
42 : template <typename T1, typename T2>
43 26 : void CcuRepTranslator::BuildReference(const std::shared_ptr<CcuRepBase>& rep)
44 : {
45 26 : auto caller = std::static_pointer_cast<T1>(rep);
46 26 : auto label = caller->GetLabel();
47 : // 特例:针对函数地址调用,不需要依靠函数名索引
48 26 : if (label == "") {
49 2 : return;
50 : }
51 24 : auto refer = refManager->GetRefBlock(label);
52 23 : if (CheckType<T2>(refer)) {
53 23 : caller->Reference(std::static_pointer_cast<T2>(refer));
54 : } else {
55 0 : THROW<CcuApiException>("Invalid Reference: %s", label.c_str());
56 : }
57 29 : }
58 :
59 64 : CcuRepTranslator::CcuRepTranslator(
60 : int32_t deviceLogicId, uint8_t dieId, std::shared_ptr<CcuRepReferenceManager> refManager,
61 : std::array<uint16_t, MAX_CCU_IODIE_NUM>& reserverChannalId, std::pair<uint64_t, uint64_t>& ccuTokenInfo,
62 64 : uint64_t hbmTokenInfo)
63 640 : : refManager(refManager)
64 : {
65 64 : transDep.logicalId = deviceLogicId;
66 64 : transDep.dieId = dieId;
67 128 : s32 result = memcpy_s(
68 64 : transDep.reserveChannalId, sizeof(transDep.reserveChannalId), reserverChannalId.data(),
69 : sizeof(reserverChannalId));
70 64 : if (result != 0) {
71 0 : THROW<InternalException>(
72 0 : StringFormat("[NsRecovery] CcuRepTranslator::CcuRepTranslator: memcpy_s failed, ret = %d", result));
73 : }
74 : // 获取xn起始地址
75 64 : HcclResult ret = CcuDeviceManager::GetXnBaseAddr(deviceLogicId, dieId, transDep.xnBaseAddr);
76 64 : if (ret != HcclResult::HCCL_SUCCESS) {
77 0 : THROW<CcuApiException>(
78 : "Failed to get xn base address. deviceLogicId = %d, dieId = %u, ret = %d", deviceLogicId, dieId, ret);
79 : }
80 64 : transDep.ccuResSpaceTokenInfo = CcuRep::GetToken(ccuTokenInfo.first, ccuTokenInfo.second, 1);
81 : // 获取hbm token信息
82 64 : transDep.memTokenInfo = hbmTokenInfo;
83 64 : }
84 :
85 2 : CcuRepTranslator::CcuRepTranslator(std::shared_ptr<CcuRepReferenceManager> refManager, const TransDep& transDep)
86 2 : : refManager(refManager),
87 20 : transDep(transDep)
88 2 : {}
89 :
90 10 : uint32_t CcuRepTranslator::GetInstrNum()
91 : {
92 10 : return 4; // 4:翻译器翻译过程中额外需要的指令空间大小(插入3条通用操作指令+1条终止指令)
93 : }
94 :
95 49 : CcuResReq CcuRepTranslator::GetResReq(uint8_t dieId)
96 : {
97 : // 需要申请若干xn、gsa、cke设置为固定值用于通用操作
98 49 : CcuResReq resReq;
99 49 : resReq.xnReq[dieId] = XN_NUM; // 4个Xn资源
100 49 : resReq.gsaReq[dieId] = GSA_NUM; // 3个GSA资源
101 49 : resReq.ckeReq[dieId] = CKE_NUM; // 2个CKE资源
102 49 : return resReq;
103 : }
104 :
105 53 : void CcuRepTranslator::GetRes(CcuRepResource& res)
106 : {
107 265 : for (int i = 0; i < XN_NUM; i++) {
108 212 : res.variable[transDep.dieId].push_back(var[i]);
109 : }
110 212 : for (int i = 0; i < GSA_NUM; i++) {
111 159 : res.address[transDep.dieId].push_back(addr[i]);
112 : }
113 159 : for (int i = 0; i < CKE_NUM; i++) {
114 106 : res.maskSignal[transDep.dieId].push_back(signal[i]);
115 : }
116 53 : }
117 :
118 664 : void CcuRepTranslator::PreProcess(std::shared_ptr<CcuRepBase> rep)
119 : {
120 664 : auto repType = rep->Type();
121 664 : if (repType == CcuRepType::FUNC_BLOCK) {
122 2 : auto funcBlock = std::static_pointer_cast<CcuRepFuncBlock>(rep);
123 2 : refManager->SetRefBlock(funcBlock->GetLabel(), funcBlock);
124 2 : funcBlock->SetFuncManager(refManager.get());
125 664 : } else if (repType == CcuRepType::LOOP_BLOCK) {
126 11 : auto loopBlock = std::static_pointer_cast<CcuRepLoopBlock>(rep);
127 12 : refManager->SetRefBlock(loopBlock->GetLabel(), loopBlock);
128 662 : } else if (repType == CcuRepType::FUNC_CALL) {
129 4 : BuildReference<CcuRepFuncCall, CcuRepFuncBlock>(rep);
130 4 : auto funcCall = std::static_pointer_cast<CcuRepFuncCall>(rep);
131 4 : funcCall->SetFuncManager(refManager.get());
132 651 : } else if (repType == CcuRepType::LOOP_CALL) {
133 13 : BuildReference<CcuRepLoopCall, CcuRepLoopBlock>(rep);
134 634 : } else if (repType == CcuRepType::LOOP) {
135 9 : BuildReference<CcuRepLoop, CcuRepLoopBlock>(rep);
136 : }
137 662 : }
138 :
139 91 : void CcuRepTranslator::Translate(
140 : const std::vector<std::shared_ptr<CcuRepBase>>& repVec, CcuInstr*& instr, uint16_t& instrId,
141 : std::function<bool(std::shared_ptr<CcuRepBase>)> filter)
142 : {
143 91 : constexpr uint32_t maxTryCount = 10; // 最大尝试次数10
144 91 : uint32_t tryCount = 0;
145 91 : uint32_t restCount = 0;
146 :
147 91 : auto funcInVar = refManager.get()->GetFuncIn();
148 91 : int funcArgIndex = 0;
149 :
150 : do {
151 101 : restCount = 0;
152 3143 : for (uint32_t index = 0; index < repVec.size(); index++) {
153 3044 : if (!filter(repVec[index])) {
154 1737 : continue;
155 : }
156 :
157 1307 : if (repVec[index]->Translated()) {
158 643 : continue;
159 : }
160 :
161 664 : if (repVec[index]->Type() == CcuRepType::LOAD_ARG && transDep.isFuncBlock) {
162 0 : transDep.loadXnId = funcInVar[funcArgIndex++].Id();
163 : }
164 :
165 666 : PreProcess(repVec[index]);
166 662 : bool flag = repVec[index]->Translate(instr, instrId, transDep);
167 662 : if (!flag) {
168 36 : restCount++;
169 : }
170 1986 : HCCL_DEBUG("index[%u], Try to translate: %s", index, flag ? "OK" : "Skip");
171 : }
172 99 : tryCount++;
173 297 : HCCL_INFO("tryCount = %u, remaining representation = %u", tryCount, restCount);
174 99 : } while (restCount > 0 && tryCount < maxTryCount);
175 :
176 89 : if (tryCount == maxTryCount && restCount > 0) {
177 0 : HCCL_ERROR(
178 : "After translation, remaining representation: tryCount = %u, restCount = %u ", tryCount, restCount);
179 0 : for (uint32_t index = 0; index < repVec.size(); index++) {
180 0 : if (!repVec[index]->Translated()) {
181 0 : HCCL_ERROR("index[%u], %s", index, repVec[index]->Describe().c_str());
182 : }
183 : }
184 0 : THROW<CcuApiException>("Translation Failed");
185 : }
186 91 : }
187 :
188 23 : CcuInstrInfo CcuRepTranslator::Translate(
189 : const std::vector<std::shared_ptr<CcuRepBase>>& repVec, uint16_t startInstrId, bool isFuncBlock)
190 : {
191 23 : constexpr uint32_t defaultInstrCapacity = 32 * 1024; // 默认最大容量32 * 1024条
192 23 : CcuInstrInfo instrInfo;
193 23 : instrInfo.instrVec.resize(defaultInstrCapacity);
194 23 : CcuInstr* instr = instrInfo.instrVec.data();
195 23 : uint16_t curInstrId = startInstrId;
196 :
197 23 : BindResource(isFuncBlock);
198 :
199 : // 翻译LoopBlock
200 24 : Translate(repVec, instr, curInstrId, [](std::shared_ptr<CcuRepBase> rep) -> bool {
201 615 : return rep->Type() == CcuRepType::LOOP_BLOCK;
202 : });
203 :
204 : // 翻译funcBlock
205 22 : Translate(repVec, instr, curInstrId, [](std::shared_ptr<CcuRepBase> rep) -> bool {
206 612 : return rep->Type() == CcuRepType::FUNC_BLOCK;
207 : });
208 :
209 22 : uint16_t missionStartInstrId = curInstrId;
210 :
211 : // 翻译Load
212 22 : Translate(repVec, instr, curInstrId, [](std::shared_ptr<CcuRepBase> rep) -> bool {
213 612 : return rep->Type() == CcuRepType::LOAD_ARG;
214 : });
215 :
216 : // 插入通用操作
217 22 : CommonProcess(instr, curInstrId);
218 :
219 : // 翻译主体
220 23 : Translate(repVec, instr, curInstrId, []([[maybe_unused]] std::shared_ptr<CcuRepBase> rep) -> bool {
221 1177 : return true;
222 : });
223 :
224 21 : FinishMainBlock(instr, curInstrId);
225 :
226 21 : instrInfo.startInstrId = startInstrId;
227 21 : instrInfo.instrCount = curInstrId - startInstrId;
228 21 : instrInfo.missionStartInstrId = missionStartInstrId;
229 21 : instrInfo.missionInstrCount = curInstrId - missionStartInstrId;
230 21 : instrInfo.instrVec.resize(instrInfo.instrCount);
231 :
232 21 : DumpInstruction(instrInfo);
233 21 : DumpRep(repVec, instrInfo);
234 :
235 21 : return instrInfo;
236 2 : }
237 :
238 22 : void CcuRepTranslator::CommonProcess(CcuInstr*& instr, uint16_t& instrId)
239 : {
240 22 : LoadImdToXnInstr(instr++, var[0].Id(), 0);
241 22 : LoadImdToGSAInstr(instr++, addr[0].Id(), 0);
242 22 : SetCKEInstr(instr++, signal[0].Id(), 0xffff, 0, 0, 1);
243 22 : u32 instrNum = 3;
244 22 : if (instrId > UINT16_MAX - instrNum) {
245 0 : THROW<InternalException>("integer overflow occurs");
246 : }
247 22 : instrId += instrNum; // 插入3条指令
248 22 : }
249 :
250 21 : void CcuRepTranslator::FinishMainBlock(CcuInstr*& instr, uint16_t& instrId)
251 : {
252 21 : if (transDep.isFuncBlock) {
253 0 : JumpInstr(instr++, refManager.get()->GetFuncRet(FUNC_NEST_MAX).Id(), transDep.reserveXnId, 1);
254 : } else {
255 21 : LoadImdToXnInstr(instr++, var[0].Id(), 0);
256 : }
257 21 : if (instrId > UINT16_MAX - 1) {
258 0 : THROW<InternalException>("integer overflow occurs");
259 : }
260 21 : instrId++;
261 21 : }
262 :
263 21 : void CcuRepTranslator::DumpInstruction(const CcuInstrInfo& instrInfo) const
264 : {
265 63 : HCCL_INFO(
266 : "CcuInstrInfo: startInstrId = %u, instrCount = %u, missionStartInstrId = %u, missionInstrCount = %u",
267 : instrInfo.startInstrId, instrInfo.instrCount, instrInfo.missionStartInstrId, instrInfo.missionInstrCount);
268 1066 : for (uint16_t index = 0; index < instrInfo.instrVec.size(); index++) {
269 3135 : HCCL_INFO("%d: %s", instrInfo.startInstrId + index, ParseInstr(instrInfo.instrVec.data() + index).c_str());
270 : }
271 21 : }
272 :
273 21 : void CcuRepTranslator::DumpRep(
274 : const std::vector<std::shared_ptr<CcuRepBase>>& repVec, const CcuInstrInfo& instrInfo) const
275 : {
276 63 : HCCL_INFO("Translated Ccu Rep:");
277 631 : for (uint32_t index = 0; index < repVec.size(); index++) {
278 1830 : HCCL_INFO("rep[%u]: %s", index, repVec[index]->Describe().c_str());
279 610 : uint16_t startInstrId = repVec[index]->StartInstrId();
280 610 : uint16_t endInstrId = startInstrId + repVec[index]->InstrCount();
281 1571 : for (uint16_t instrId = startInstrId; instrId < endInstrId; instrId++) {
282 2883 : HCCL_INFO(
283 : "microcode[%u]: %s", instrId,
284 : ParseInstr(instrInfo.instrVec.data() + (instrId - instrInfo.startInstrId)).c_str());
285 : }
286 : }
287 21 : }
288 :
289 23 : void CcuRepTranslator::BindResource(bool isFuncBlock)
290 : {
291 23 : transDep.reserveXnId = var[0].Id();
292 23 : transDep.reserveGsaId = addr[0].Id();
293 23 : transDep.reserveCkeId = signal[0].Id();
294 92 : for (int i = 0; i < XN_NUM - 1; i++) {
295 69 : transDep.commXn[i] = var[i + 1].Id();
296 : }
297 69 : for (int i = 0; i < GSA_NUM - 1; i++) {
298 46 : transDep.commGsa[i] = addr[i + 1].Id();
299 : }
300 23 : transDep.commSignal = signal[1].Id();
301 23 : transDep.isFuncBlock = isFuncBlock;
302 69 : HCCL_INFO(
303 : "TransDep info: logicalId = %d, dieId = %u, reserveXnId = %u, reserveGsaId = %u, reserveCkeId = %u, "
304 : "innerDieChannelId = %u, interDieChannelId = %u",
305 : transDep.logicalId, transDep.dieId, transDep.reserveXnId, transDep.reserveGsaId, transDep.reserveCkeId,
306 : transDep.reserveChannalId[0], transDep.reserveChannalId[1]);
307 23 : }
308 : }; // namespace CcuRep
309 : }; // namespace Hccl
|