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