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 33 : template <> bool CheckType<CcuRepLoopBlock>(const std::shared_ptr<CcuRepBlock> &refer)
35 : {
36 33 : return refer->Type() == CcuRepType::LOOP_BLOCK ? true : false;
37 : }
38 :
39 38 : template <typename T1, typename T2> void CcuRepTranslator::BuildReference(const std::shared_ptr<CcuRepBase> &rep)
40 : {
41 38 : auto caller = std::static_pointer_cast<T1>(rep);
42 38 : auto label = caller->GetLabel();
43 : // 特例:针对函数地址调用,不需要依靠函数名索引
44 38 : if (label == "") {
45 2 : return;
46 : }
47 36 : auto refer = refManager->GetRefBlock(label);
48 35 : if (CheckType<T2>(refer)) {
49 35 : caller->Reference(std::static_pointer_cast<T2>(refer));
50 : } else {
51 0 : THROW<CcuApiException>("Invalid Reference: %s", label.c_str());
52 : }
53 41 : }
54 :
55 67 : 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 67 : std::pair<uint64_t, uint64_t>& ccuTokenInfo, uint64_t hbmTokenInfo)
59 670 : : refManager(refManager)
60 : {
61 67 : transDep.logicalId = deviceLogicId;
62 67 : transDep.dieId = dieId;
63 67 : s32 result = memcpy_s(transDep.reserveChannalId, sizeof(transDep.reserveChannalId), reserverChannalId.data(), sizeof(reserverChannalId));
64 67 : if (result != 0) {
65 0 : THROW<InternalException>(StringFormat("[NsRecovery] CcuRepTranslator::CcuRepTranslator: memcpy_s failed, ret = %d", result));
66 : }
67 : // 获取xn起始地址
68 67 : HcclResult ret = CcuDeviceManager::GetXnBaseAddr(deviceLogicId, dieId, transDep.xnBaseAddr);
69 67 : 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 67 : transDep.ccuResSpaceTokenInfo = CcuRep::GetToken(ccuTokenInfo.first, ccuTokenInfo.second, 1);
74 : // 获取hbm token信息
75 67 : transDep.memTokenInfo = hbmTokenInfo;
76 67 : }
77 :
78 3 : CcuRepTranslator::CcuRepTranslator(std::shared_ptr<CcuRepReferenceManager> refManager, const TransDep &transDep)
79 30 : : refManager(refManager), transDep(transDep)
80 : {
81 3 : }
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 913 : void CcuRepTranslator::PreProcess(std::shared_ptr<CcuRepBase> rep)
112 : {
113 913 : auto repType = rep->Type();
114 913 : if (repType == CcuRepType::FUNC_BLOCK) {
115 3 : auto funcBlock = std::static_pointer_cast<CcuRepFuncBlock>(rep);
116 3 : refManager->SetRefBlock(funcBlock->GetLabel(), funcBlock);
117 3 : funcBlock->SetFuncManager(refManager.get());
118 913 : } else if (repType == CcuRepType::LOOP_BLOCK) {
119 15 : auto loopBlock = std::static_pointer_cast<CcuRepLoopBlock>(rep);
120 16 : refManager->SetRefBlock(loopBlock->GetLabel(), loopBlock);
121 910 : } 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 895 : } else if (repType == CcuRepType::LOOP_CALL) {
126 19 : BuildReference<CcuRepLoopCall, CcuRepLoopBlock>(rep);
127 872 : } else if (repType == CcuRepType::LOOP) {
128 15 : BuildReference<CcuRepLoop, CcuRepLoopBlock>(rep);
129 : }
130 911 : }
131 :
132 104 : 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 104 : constexpr uint32_t maxTryCount = 10; // 最大尝试次数10
136 104 : uint32_t tryCount = 0;
137 104 : uint32_t restCount = 0;
138 :
139 104 : auto funcInVar = refManager.get()->GetFuncIn();
140 104 : int funcArgIndex = 0;
141 :
142 : do {
143 116 : restCount = 0;
144 4362 : for (uint32_t index = 0; index < repVec.size(); index++) {
145 4248 : if (!filter(repVec[index])) {
146 2439 : continue;
147 : }
148 :
149 1809 : if (repVec[index]->Translated()) {
150 896 : continue;
151 : }
152 :
153 913 : if (repVec[index]->Type() == CcuRepType::LOAD_ARG && transDep.isFuncBlock) {
154 0 : transDep.loadXnId = funcInVar[funcArgIndex++].Id();
155 : }
156 :
157 915 : PreProcess(repVec[index]);
158 911 : bool flag = repVec[index]->Translate(instr, instrId, transDep);
159 911 : if (!flag) {
160 44 : restCount++;
161 : }
162 2733 : HCCL_DEBUG("index[%u], Try to translate: %s", index, flag ? "OK" : "Skip");
163 : }
164 114 : tryCount++;
165 342 : HCCL_INFO("tryCount = %u, remaining representation = %u", tryCount, restCount);
166 114 : } while (restCount > 0 && tryCount < maxTryCount);
167 :
168 102 : 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 104 : }
178 :
179 26 : CcuInstrInfo CcuRepTranslator::Translate(const std::vector<std::shared_ptr<CcuRepBase>> &repVec, uint16_t startInstrId, bool isFuncBlock)
180 : {
181 26 : constexpr uint32_t defaultInstrCapacity = 32 * 1024; // 默认最大容量32 * 1024条
182 26 : CcuInstrInfo instrInfo;
183 26 : instrInfo.instrVec.resize(defaultInstrCapacity);
184 26 : CcuInstr *instr = instrInfo.instrVec.data();
185 26 : uint16_t curInstrId = startInstrId;
186 :
187 26 : BindResource(isFuncBlock);
188 :
189 : // 翻译LoopBlock
190 27 : Translate(repVec, instr, curInstrId, [](std::shared_ptr<CcuRepBase> rep) -> bool {
191 856 : return rep->Type() == CcuRepType::LOOP_BLOCK;
192 : });
193 :
194 : // 翻译funcBlock
195 25 : Translate(repVec, instr, curInstrId, [](std::shared_ptr<CcuRepBase> rep) -> bool {
196 853 : return rep->Type() == CcuRepType::FUNC_BLOCK;
197 : });
198 :
199 25 : uint16_t missionStartInstrId = curInstrId;
200 :
201 : // 翻译Load
202 25 : Translate(repVec, instr, curInstrId, [](std::shared_ptr<CcuRepBase> rep) -> bool {
203 853 : return rep->Type() == CcuRepType::LOAD_ARG;
204 : });
205 :
206 : // 插入通用操作
207 25 : CommonProcess(instr, curInstrId);
208 :
209 : // 翻译主体
210 26 : Translate(repVec, instr, curInstrId, [](std::shared_ptr<CcuRepBase> rep) -> bool {
211 1658 : return true;
212 : });
213 :
214 24 : FinishMainBlock(instr, curInstrId);
215 :
216 24 : instrInfo.startInstrId = startInstrId;
217 24 : instrInfo.instrCount = curInstrId - startInstrId;
218 24 : instrInfo.missionStartInstrId = missionStartInstrId;
219 24 : instrInfo.missionInstrCount = curInstrId - missionStartInstrId;
220 24 : instrInfo.instrVec.resize(instrInfo.instrCount);
221 :
222 24 : DumpInstruction(instrInfo);
223 24 : DumpRep(repVec, instrInfo);
224 :
225 24 : return instrInfo;
226 2 : }
227 :
228 25 : void CcuRepTranslator::CommonProcess(CcuInstr *&instr, uint16_t &instrId)
229 : {
230 25 : LoadImdToXnInstr(instr++, var[0].Id(), 0);
231 25 : LoadImdToGSAInstr(instr++, addr[0].Id(), 0);
232 25 : SetCKEInstr(instr++, signal[0].Id(), 0xffff, 0, 0, 1);
233 25 : u32 instrNum = 3;
234 25 : if (instrId > UINT16_MAX - instrNum) {
235 0 : THROW<InternalException>("integer overflow occurs");
236 : }
237 25 : instrId += instrNum; // 插入3条指令
238 25 : }
239 :
240 24 : void CcuRepTranslator::FinishMainBlock(CcuInstr *&instr, uint16_t &instrId)
241 : {
242 24 : if (transDep.isFuncBlock) {
243 0 : JumpInstr(instr++, refManager.get()->GetFuncRet(FUNC_NEST_MAX).Id(), transDep.reserveXnId, 1);
244 : } else {
245 24 : LoadImdToXnInstr(instr++, var[0].Id(), 0);
246 : }
247 24 : if (instrId > UINT16_MAX - 1) {
248 0 : THROW<InternalException>("integer overflow occurs");
249 : }
250 24 : instrId++;
251 24 : }
252 :
253 24 : void CcuRepTranslator::DumpInstruction(const CcuInstrInfo &instrInfo) const
254 : {
255 72 : HCCL_INFO("CcuInstrInfo: startInstrId = %u, instrCount = %u, missionStartInstrId = %u, missionInstrCount = %u",
256 : instrInfo.startInstrId, instrInfo.instrCount, instrInfo.missionStartInstrId, instrInfo.missionInstrCount);
257 1510 : for (uint16_t index = 0; index < instrInfo.instrVec.size(); index++) {
258 4458 : HCCL_INFO("%d: %s", instrInfo.startInstrId + index, ParseInstr(instrInfo.instrVec.data() + index).c_str());
259 : }
260 24 : }
261 :
262 24 : void CcuRepTranslator::DumpRep(const std::vector<std::shared_ptr<CcuRepBase>> &repVec,
263 : const CcuInstrInfo &instrInfo) const
264 : {
265 72 : HCCL_INFO("Translated Ccu Rep:");
266 875 : for (uint32_t index = 0; index < repVec.size(); index++) {
267 2553 : HCCL_INFO("rep[%u]: %s", index, repVec[index]->Describe().c_str());
268 851 : uint16_t startInstrId = repVec[index]->StartInstrId();
269 851 : uint16_t endInstrId = startInstrId + repVec[index]->InstrCount();
270 2241 : for (uint16_t instrId = startInstrId; instrId < endInstrId; instrId++) {
271 4170 : HCCL_INFO("microcode[%u]: %s", instrId,
272 : ParseInstr(instrInfo.instrVec.data() + (instrId - instrInfo.startInstrId)).c_str());
273 : }
274 : }
275 24 : }
276 :
277 26 : void CcuRepTranslator::BindResource(bool isFuncBlock)
278 : {
279 26 : transDep.reserveXnId = var[0].Id();
280 26 : transDep.reserveGsaId = addr[0].Id();
281 26 : transDep.reserveCkeId = signal[0].Id();
282 104 : for (int i = 0; i < XN_NUM - 1; i++) {
283 78 : transDep.commXn[i] = var[i + 1].Id();
284 : }
285 78 : for (int i = 0; i < GSA_NUM - 1; i++) {
286 52 : transDep.commGsa[i] = addr[i + 1].Id();
287 : }
288 26 : transDep.commSignal = signal[1].Id();
289 26 : transDep.isFuncBlock = isFuncBlock;
290 78 : 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 26 : }
295 : }; // namespace CcuRep
296 : }; // namespace Hccl
|