Line data Source code
1 : /*
2 : * Copyright (c) Huawei Technologies Co., Ltd. 2025-2025. All rights reserved.
3 : * Description: ccu rep translator implement file
4 : * Create: 2025-02-20
5 : */
6 :
7 : #include "ccu_rep_translator_v1.h"
8 :
9 : #include <algorithm>
10 :
11 : #include "exception_util.h"
12 : #include "ccu_api_exception.h"
13 : #include "ccu_rep_loopcall_v1.h"
14 : #include "ccu_rep_funccall_v1.h"
15 : #include "ccu_rep_type_v1.h"
16 : #include "ccu_rep_loop_v1.h"
17 : #include "ccu_rep_loadarg_v1.h"
18 : #include "ccu_assist_v1.h"
19 :
20 : #include "ccu_dev_mgr_imp.h"
21 : #include "dtype_common.h"
22 :
23 : #include "ccu_ins_generater_base.h"
24 : #include "ccu_ins_generater_v1.h"
25 : #include "../../../ccu_device/ccu_res_specs.h"
26 :
27 : #include "unified_platform/pub_inc/config_plf_log.h"
28 :
29 : namespace hcomm {
30 : namespace CcuRep {
31 :
32 : using Hccl::PLF_TASK;
33 :
34 : CcuVersion CcuRepTranslator::ccuVersion = CcuVersion::CCU_INVALID;
35 :
36 : template <typename T> bool CheckType(const std::shared_ptr<CcuRepBlock> &refer)
37 : {
38 : if (refer == nullptr) {
39 : HCCL_ERROR("input refer is nullptr");
40 : return false;
41 : }
42 : HCCL_INFO("[CheckType] refer->Type() = %d", refer->Type());
43 : return false;
44 : }
45 :
46 5 : template <> bool CheckType<CcuRepFuncBlock>(const std::shared_ptr<CcuRepBlock> &refer)
47 : {
48 5 : if (refer == nullptr) {
49 0 : HCCL_ERROR("input refer is nullptr");
50 0 : return false;
51 : }
52 5 : return refer->Type() == CcuRepType::FUNC_BLOCK ? true : false;
53 : }
54 :
55 0 : template <> bool CheckType<CcuRepLoopBlock>(const std::shared_ptr<CcuRepBlock> &refer)
56 : {
57 0 : if (refer == nullptr) {
58 0 : HCCL_ERROR("input refer is nullptr");
59 0 : return false;
60 : }
61 0 : return refer->Type() == CcuRepType::LOOP_BLOCK ? true : false;
62 : }
63 :
64 5 : template <typename T1, typename T2> void CcuRepTranslator::BuildReference(const std::shared_ptr<CcuRepBase> &rep)
65 : {
66 5 : auto caller = std::static_pointer_cast<T1>(rep);
67 5 : auto label = caller->GetLabel();
68 : // 特例:针对函数地址调用,不需要依靠函数名索引
69 5 : if (label == "") {
70 0 : return;
71 : }
72 5 : auto refer = refManager->GetRefBlock(label);
73 5 : if (CheckType<T2>(refer)) {
74 5 : caller->Reference(std::static_pointer_cast<T2>(refer));
75 : } else {
76 0 : Hccl::THROW<Hccl::CcuApiException>("Invalid Reference: %s", label.c_str());
77 : }
78 5 : }
79 :
80 864 : CcuRepTranslator::CcuRepTranslator(int32_t deviceLogicId, uint8_t dieId,
81 : std::shared_ptr<CcuRepReferenceManager> refManager,
82 : std::array<uint16_t, CCU_MAX_IODIE_NUM>& reserverChannalId,
83 864 : std::pair<uint64_t, uint64_t>& ccuTokenInfo, uint64_t hbmTokenInfo)
84 8640 : : refManager(refManager)
85 : {
86 864 : transDep.logicalId = deviceLogicId;
87 864 : transDep.dieId = dieId;
88 864 : s32 result = memcpy_s(transDep.reserveChannalId, sizeof(transDep.reserveChannalId), reserverChannalId.data(), sizeof(reserverChannalId));
89 864 : if (result != 0) {
90 0 : Hccl::THROW<Hccl::InternalException>(Hccl::StringFormat("[NsRecovery] CcuRepTranslator::CcuRepTranslator: memcpy_s failed, ret = %d", result));
91 : }
92 : // 获取xn起始地址
93 864 : HcclResult ret = CcuDevMgrImp::GetXnBaseAddr(deviceLogicId, dieId, transDep.xnBaseAddr[dieId]);
94 864 : if (ret != HcclResult::HCCL_SUCCESS) {
95 0 : Hccl::THROW<Hccl::CcuApiException>("Failed to get xn base address. deviceLogicId = %d, dieId = %u, ret = %d",
96 : deviceLogicId, dieId, ret);
97 : }
98 864 : transDep.ccuResSpaceTokenInfo = CcuRep::GetToken(ccuTokenInfo.first, ccuTokenInfo.second, 1);
99 : // 获取hbm token信息
100 864 : transDep.memTokenInfo = hbmTokenInfo;
101 :
102 864 : ret = CcuDevMgrImp::GetCcuVersion(transDep.logicalId, ccuVersion);
103 864 : if (ret != HcclResult::HCCL_SUCCESS || ccuVersion == CcuVersion::CCU_INVALID) {
104 0 : Hccl::THROW<Hccl::CcuApiException>("[CcuRepTranslator] Constructor: Invalid CCU Type!");
105 : }
106 :
107 : // 单Udie环境下暂不获取另一个die的信息
108 : #ifdef OPEN_GET_ANOTHER_DIE_XN_ADDR
109 : if (ccuVersion == CcuVersion::CCU_V2) {
110 : uint8_t anotherDieId = dieId == 0 ? 1 : 0;
111 : ret = CcuDevMgrImp::GetXnBaseAddr(deviceLogicId, anotherDieId, transDep.xnBaseAddr[anotherDieId]);
112 : if (ret != HcclResult::HCCL_SUCCESS) {
113 : Hccl::THROW<Hccl::CcuApiException>("Failed to get xn base address. deviceLogicId = %d, dieId = %u, "
114 : "ret = %d", deviceLogicId, anotherDieId, ret);
115 : }
116 : }
117 : #endif
118 864 : }
119 :
120 4 : CcuRepTranslator::CcuRepTranslator(std::shared_ptr<CcuRepReferenceManager> refManager, const TransDep &transDep)
121 40 : : refManager(refManager), transDep(transDep)
122 : {
123 4 : HcclResult ret = CcuDevMgrImp::GetCcuVersion(transDep.logicalId, ccuVersion);
124 4 : if (ret != HcclResult::HCCL_SUCCESS || ccuVersion == CcuVersion::CCU_INVALID) {
125 0 : Hccl::THROW<Hccl::CcuApiException>("[CcuRepTranslator] Constructor: Invalid CCU Type!");
126 : }
127 4 : }
128 :
129 38 : uint32_t CcuRepTranslator::GetInstrNum()
130 : {
131 38 : return ccuVersion == CcuVersion::CCU_V1 ?
132 : 4 // 4:翻译器翻译过程中额外需要的指令空间大小(插入3条通用操作指令+1条终止指令)
133 : :
134 38 : 13; // 13:翻译器翻译过程中额外需要的指令空间大小(插入3条通用操作指令+1条终止指令+9条repJump)
135 : }
136 :
137 864 : CcuResReq CcuRepTranslator::GetResReq(uint8_t dieId)
138 : {
139 : // xn 资源统一从 continuousXn 池子申请,离散 xn 帐户已废弃
140 : // 需要申请若干xn、gsa、cke设置为固定值用于通用操作
141 864 : CcuResReq resReq;
142 864 : int varNum = XN_NUM;
143 864 : int gsaNum = ccuVersion == CcuVersion::CCU_V1 ? GSA_NUM : 0;
144 864 : resReq.continuousXnReq[dieId] = varNum;
145 864 : resReq.gsaReq[dieId] = gsaNum;
146 864 : resReq.ckeReq[dieId] = CKE_NUM;
147 864 : return resReq;
148 : }
149 :
150 864 : void CcuRepTranslator::GetRes(CcuRepResource &res)
151 : {
152 864 : int varNum = XN_NUM;
153 864 : int gsaNum = ccuVersion == CcuVersion::CCU_V1 ? GSA_NUM : 0;
154 4320 : for (int i = 0; i < varNum; i++) {
155 3456 : res.continuousVariable[transDep.dieId].push_back(var[i]);
156 : }
157 3264 : for (int i = 0; i < gsaNum; i++) {
158 2400 : res.address[transDep.dieId].push_back(addr[i]);
159 : }
160 2592 : for (int i = 0; i < CKE_NUM; i++) {
161 1728 : res.localNotify[transDep.dieId].push_back(signal[i]);
162 : }
163 864 : }
164 :
165 434 : void CcuRepTranslator::PreProcess(std::shared_ptr<CcuRepBase> rep)
166 : {
167 434 : auto repType = rep->Type();
168 434 : if (repType == CcuRepType::FUNC_BLOCK) {
169 4 : auto funcBlock = std::static_pointer_cast<CcuRepFuncBlock>(rep);
170 4 : refManager->SetRefBlock(funcBlock->GetLabel(), funcBlock);
171 4 : funcBlock->SetFuncManager(refManager.get());
172 434 : } else if (repType == CcuRepType::LOOP_BLOCK) {
173 24 : auto loopBlock = std::static_pointer_cast<CcuRepLoopBlock>(rep);
174 24 : refManager->SetRefBlock(loopBlock->GetLabel(), loopBlock);
175 430 : } else if (repType == CcuRepType::FUNC_CALL) {
176 5 : BuildReference<CcuRepFuncCall, CcuRepFuncBlock>(rep);
177 5 : auto funcCall = std::static_pointer_cast<CcuRepFuncCall>(rep);
178 5 : funcCall->SetFuncManager(refManager.get());
179 406 : } else if (repType == CcuRepType::LOOP_CALL) {
180 0 : BuildReference<CcuRepLoopCall, CcuRepLoopBlock>(rep);
181 401 : } else if (repType == CcuRepType::LOOP) {
182 0 : BuildReference<CcuRepLoop, CcuRepLoopBlock>(rep);
183 : }
184 434 : }
185 :
186 80 : void CcuRepTranslator::Translate(CcuKernel* ccuKernel, const std::vector<std::shared_ptr<CcuRepBase>> &repVec, CcuInstr *&instr,
187 : uint16_t &instrId, std::function<bool(std::shared_ptr<CcuRepBase>)> filter)
188 : {
189 80 : constexpr uint32_t maxTryCount = 10; // 最大尝试次数10
190 80 : uint32_t tryCount = 0;
191 80 : uint32_t restCount = 0;
192 :
193 80 : auto funcInVar = refManager.get()->GetFuncIn();
194 80 : int funcArgIndex = 0;
195 :
196 : do {
197 86 : restCount = 0;
198 1625 : for (uint32_t index = 0; index < repVec.size(); index++) {
199 1539 : if (!filter(repVec[index])) {
200 790 : continue;
201 : }
202 :
203 749 : if (repVec[index]->Translated()) {
204 315 : continue;
205 : }
206 :
207 434 : if (repVec[index]->Type() == CcuRepType::LOAD_ARG && transDep.isFuncBlock) {
208 0 : transDep.loadXnId = funcInVar[funcArgIndex++].Id();
209 : }
210 :
211 434 : PreProcess(repVec[index]);
212 434 : bool flag = repVec[index]->Translate(ccuKernel, instr, instrId, transDep);
213 434 : if (!flag) {
214 20 : restCount++;
215 : }
216 : }
217 86 : tryCount++;
218 86 : HCCL_INFO("tryCount = %u, remaining representation = %u", tryCount, restCount);
219 86 : } while (restCount > 0 && tryCount < maxTryCount);
220 :
221 80 : if (tryCount == maxTryCount && restCount > 0) {
222 0 : HCCL_ERROR("After translation, remaining representation: tryCount = %u, restCount = %u ", tryCount, restCount);
223 0 : for (uint32_t index = 0; index < repVec.size(); index++) {
224 0 : if (!repVec[index]->Translated()) {
225 0 : HCCL_ERROR("index[%u], %s", index, repVec[index]->Describe().c_str());
226 : }
227 : }
228 0 : Hccl::THROW<Hccl::CcuApiException>("Translation Failed");
229 : }
230 80 : }
231 :
232 19 : CcuInstrInfo CcuRepTranslator::Translate(CcuKernel* ccuKernel, const std::vector<std::shared_ptr<CcuRepBase>> &repVec,
233 : uint16_t startInstrId, bool isFuncBlock)
234 : {
235 19 : constexpr uint32_t defaultInstrCapacity = 32 * 1024; // 默认最大容量32 * 1024条
236 19 : CcuInstrInfo instrInfo;
237 19 : instrInfo.instrVec.resize(defaultInstrCapacity);
238 19 : CcuInstr *instr = instrInfo.instrVec.data();
239 19 : uint16_t curInstrId = startInstrId;
240 :
241 19 : BindResource(isFuncBlock);
242 :
243 : // 翻译LoopBlock
244 19 : Translate(ccuKernel, repVec, instr, curInstrId, [](std::shared_ptr<CcuRepBase> rep) -> bool {
245 409 : return rep->Type() == CcuRepType::LOOP_BLOCK;
246 : });
247 :
248 : // 翻译funcBlock
249 19 : Translate(ccuKernel, repVec, instr, curInstrId, [](std::shared_ptr<CcuRepBase> rep) -> bool {
250 409 : return rep->Type() == CcuRepType::FUNC_BLOCK;
251 : });
252 :
253 19 : uint16_t missionStartInstrId = curInstrId;
254 :
255 : // 翻译Load:按全局 argId 升序排序后再翻译,确保 LoadSqeArgs 指令在 mission 切分时
256 : // 落入与其 slot id 匹配的 mission(避免用户乱序 LoadArg 导致取参错位)
257 19 : std::vector<std::shared_ptr<CcuRepBase>> sortedLoadArgReps;
258 19 : sortedLoadArgReps.reserve(repVec.size());
259 428 : for (const auto &rep : repVec) {
260 409 : if (rep->Type() == CcuRepType::LOAD_ARG) {
261 32 : sortedLoadArgReps.push_back(rep);
262 : }
263 : }
264 19 : std::stable_sort(sortedLoadArgReps.begin(), sortedLoadArgReps.end(),
265 77 : [](const std::shared_ptr<CcuRepBase> &a, const std::shared_ptr<CcuRepBase> &b) {
266 154 : return std::static_pointer_cast<CcuRepLoadArg>(a)->GetFullArgId()
267 77 : < std::static_pointer_cast<CcuRepLoadArg>(b)->GetFullArgId();
268 : });
269 19 : Translate(ccuKernel, sortedLoadArgReps, instr, curInstrId,
270 32 : [](std::shared_ptr<CcuRepBase> rep) -> bool { return rep->Type() == CcuRepType::LOAD_ARG; });
271 :
272 : // 插入通用操作
273 19 : CommonProcess(ccuKernel, instr, curInstrId);
274 :
275 : // 翻译主体
276 703 : Translate(ccuKernel, repVec, instr, curInstrId, [](std::shared_ptr<CcuRepBase> rep) -> bool { return true; });
277 :
278 19 : FinishMainBlock(instr, curInstrId);
279 :
280 19 : instrInfo.startInstrId = startInstrId;
281 19 : instrInfo.instrCount = curInstrId - startInstrId;
282 19 : instrInfo.missionStartInstrId = missionStartInstrId;
283 19 : instrInfo.missionInstrCount = curInstrId - missionStartInstrId;
284 19 : instrInfo.instrVec.resize(instrInfo.instrCount);
285 :
286 19 : DumpRep(repVec, instrInfo);
287 19 : DumpInstruction(instrInfo);
288 :
289 19 : return instrInfo;
290 19 : }
291 :
292 19 : void CcuRepTranslator::CommonProcess(CcuKernel* ccuKernel, CcuInstr *&instr, uint16_t &instrId)
293 : {
294 19 : LoadImdToXnInstr(instr++, var[0].Id(), 0);
295 19 : LoadImdToGSAInstr(instr++, addr[0].Id(), 0);
296 19 : SetCKEInstr(instr++, signal[0].Id(), 0xffff, 0, 0, 1);
297 :
298 : // 遍历需要赋值的常量,A5场景下暂为空表
299 19 : std::unordered_map<uint64_t, CcuRep::Variable>& constValue2VarMap = ccuKernel->GetConstValue2VarMap();
300 19 : u32 constValueNum = constValue2VarMap.size();
301 19 : for (auto elem : constValue2VarMap) {
302 0 : uint64_t constValue = elem.first;
303 0 : CcuRep::Variable curVariable = elem.second;
304 0 : LoadImdToXnInstr(instr++, curVariable.Id(), constValue);
305 0 : }
306 :
307 19 : u32 instrNum = 3 + constValueNum;
308 19 : if (instrId > UINT16_MAX - instrNum) {
309 0 : Hccl::THROW<Hccl::InternalException>("integer overflow occurs");
310 : }
311 19 : instrId += instrNum; // 插入3条指令
312 19 : }
313 :
314 19 : void CcuRepTranslator::FinishMainBlock(CcuInstr *&instr, uint16_t &instrId)
315 : {
316 19 : if (transDep.isFuncBlock) {
317 0 : JumpInstr(instr++, refManager.get()->GetFuncRet(FUNC_NEST_MAX).Id(), transDep.reserveXnId, 1);
318 : } else {
319 19 : LoadImdToXnInstr(instr++, var[0].Id(), 0);
320 : }
321 19 : instrId++;
322 :
323 19 : if (instrId > UINT16_MAX - 1) {
324 0 : Hccl::THROW<Hccl::InternalException>("integer overflow occurs");
325 : }
326 19 : }
327 :
328 19 : void CcuRepTranslator::DumpInstruction(const CcuInstrInfo &instrInfo) const
329 : {
330 19 : HCCL_INFO("CcuInstrInfo: startInstrId = %u, instrCount = %u, missionStartInstrId = %u, missionInstrCount = %u",
331 : instrInfo.startInstrId, instrInfo.instrCount, instrInfo.missionStartInstrId, instrInfo.missionInstrCount);
332 814 : for (uint16_t index = 0; index < instrInfo.instrVec.size(); index++) {
333 795 : HCCL_INFO("%d: %s", instrInfo.startInstrId + index, ParseInstr(instrInfo.instrVec.data() + index).c_str());
334 : }
335 19 : }
336 :
337 19 : void CcuRepTranslator::DumpRep(const std::vector<std::shared_ptr<CcuRepBase>> &repVec,
338 : const CcuInstrInfo &instrInfo) const
339 : {
340 19 : PLF_CONFIG_INFO(PLF_TASK, "Translated Ccu Rep:");
341 428 : for (uint32_t index = 0; index < repVec.size(); index++) {
342 409 : uint16_t startInstrId = repVec[index]->StartInstrId();
343 409 : uint32_t sum = static_cast<uint32_t>(startInstrId) + repVec[index]->InstrCount();
344 409 : if (sum > UINT16_MAX) {
345 0 : HCCL_ERROR("instrId overflow: startInstrId[%u] + InstrCount[%u] = %u exceeds UINT16_MAX",
346 : startInstrId, repVec[index]->InstrCount(), sum);
347 0 : continue;
348 : }
349 409 : uint16_t endInstrId = static_cast<uint16_t>(sum);
350 409 : PLF_CONFIG_INFO(PLF_TASK, "rep[%u]: %s Instr[%u--%u]", index, repVec[index]->Describe().c_str(), startInstrId, endInstrId);
351 1134 : for (uint16_t instrId = startInstrId; instrId < endInstrId; instrId++) {
352 725 : if (instrId < instrInfo.startInstrId) {
353 0 : HCCL_ERROR("instrId[%u] less than startInstrId[%u]", instrId, instrInfo.startInstrId);
354 0 : continue;
355 : }
356 725 : PLF_CONFIG_INFO(PLF_TASK, "microcode[%u]: %s", instrId,
357 : ParseInstr(instrInfo.instrVec.data() + (instrId - instrInfo.startInstrId)).c_str());
358 : }
359 : }
360 19 : }
361 :
362 19 : void CcuRepTranslator::BindResource(bool isFuncBlock)
363 : {
364 19 : transDep.reserveXnId = var[0].Id();
365 19 : transDep.reserveGsaId = addr[0].Id();
366 19 : transDep.reserveCkeId = signal[0].Id();
367 76 : for (int i = 0; i < XN_NUM - 1; i++) {
368 57 : transDep.commXn[i] = var[i + 1].Id();
369 : }
370 57 : for (int i = 0; i < GSA_NUM - 1; i++) {
371 38 : transDep.commGsa[i] = addr[i + 1].Id();
372 : }
373 19 : transDep.commSignal = signal[1].Id();
374 19 : transDep.isFuncBlock = isFuncBlock;
375 19 : HCCL_INFO("TransDep info: logicalId = %d, dieId = %u, reserveXnId = %u, reserveGsaId = %u, reserveCkeId = %u, "
376 : "innerDieChannelId = %u, interDieChannelId = %u",
377 : transDep.logicalId, transDep.dieId, transDep.reserveXnId, transDep.reserveGsaId, transDep.reserveCkeId,
378 : transDep.reserveChannalId[0], transDep.reserveChannalId[1]);
379 19 : }
380 : }; // namespace CcuRep
381 : }; // namespace hcomm
|