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 <unordered_map>
12 :
13 : #include "string_util.h"
14 : #include "ccu_microcode.h"
15 :
16 : namespace {
17 : constexpr uint16_t LOAD_TYPE = 0x0;
18 :
19 : constexpr uint16_t LOADSQEARGSTOX_CODE = 0x1;
20 : constexpr uint16_t LOADIMDTOX_CODE = 0x2;
21 : constexpr uint16_t LOADX_CODE = 0x6;
22 : constexpr uint16_t STOREX_CODE = 0x7;
23 : constexpr uint16_t CLEARX_CODE = 0x8;
24 : constexpr uint16_t NOP_CODE = 0x9;
25 : constexpr uint16_t LOAD_CODE = 0xA;
26 : constexpr uint16_t STORE_CODE = 0xB;
27 : constexpr uint16_t ADD_CODE = 0xD;
28 : constexpr uint16_t SUB_CODE = 0xE;
29 : constexpr uint16_t MUL_CODE = 0xF;
30 : constexpr uint16_t AND_CODE = 0x10;
31 : constexpr uint16_t OR_CODE = 0x11;
32 : constexpr uint16_t NOT_CODE = 0x12;
33 : constexpr uint16_t XOR_CODE = 0x13;
34 : constexpr uint16_t SHL_CODE = 0x14;
35 : constexpr uint16_t SHR_CODE = 0x15;
36 : constexpr uint16_t POPCNT_CODE = 0x16;
37 :
38 : constexpr uint16_t CTRL_TYPE = 0x1;
39 :
40 : constexpr uint16_t LOOP_CODE = 0x0;
41 : constexpr uint16_t LOOPGROUP_CODE = 0x1;
42 : constexpr uint16_t SETCKBIT_CODE = 0x2;
43 : constexpr uint16_t CLEARCKBIT_CODE = 0x4;
44 : constexpr uint16_t JMP_CODE = 0x5;
45 : constexpr uint16_t WAIT_CODE = 0x7;
46 : constexpr uint16_t FENCE_CODE = 0x8;
47 :
48 : constexpr uint16_t TRANS_TYPE = 0x2;
49 :
50 : constexpr uint16_t TRANSLOCMEMTOLOCMS_CODE = 0x0;
51 : constexpr uint16_t TRANSLOCMSTOLOCMEM_CODE = 0x2;
52 : constexpr uint16_t TRANSLOCMSTOLOCMS_CODE = 0x5;
53 : constexpr uint16_t TRANSLOCMEMTOLOCMEM_CODE = 0x6;
54 : constexpr uint16_t TRANSMEM_CODE = 0x10;
55 : constexpr uint16_t SYNCWTX_CODE = 0xD;
56 : constexpr uint16_t SYNCATX_CODE = 0xE;
57 :
58 : constexpr uint16_t REDUCE_TYPE = 0x3;
59 :
60 : constexpr uint16_t REDUCE_ADD_CODE = 0x0;
61 : constexpr uint16_t REDUCE_MAX_CODE = 0x1;
62 : constexpr uint16_t REDUCE_MIN_CODE = 0x2;
63 : } // namespace
64 :
65 : namespace Hccl {
66 : namespace CcuRep {
67 : namespace CcuV2 {
68 : // *XnId = *sqeArgsId
69 1 : void LoadSqeArgsToX(CcuInstr* instr, uint16_t xnId, uint16_t sqeArgsId, uint16_t setCKEId, uint16_t setCKEMask)
70 : {
71 1 : instr->header = InstrHeader(LOAD_TYPE, LOADSQEARGSTOX_CODE);
72 1 : instr->v2.loadSqeArgsToX.xnId = xnId;
73 1 : instr->v2.loadSqeArgsToX.sqeArgsId = sqeArgsId;
74 1 : instr->v2.loadSqeArgsToX.setCKEId = setCKEId;
75 1 : instr->v2.loadSqeArgsToX.setCKEMask = setCKEMask;
76 1 : }
77 :
78 : // *XnId = immediate
79 1 : void LoadImdToXn(CcuInstr* instr, uint16_t xnId, uint64_t immediate, uint16_t setCKEId, uint16_t setCKEMask)
80 : {
81 1 : instr->header = InstrHeader(LOAD_TYPE, LOADIMDTOX_CODE);
82 1 : instr->v2.loadImdToX.xnId = xnId;
83 1 : instr->v2.loadImdToX.immediate = immediate;
84 1 : instr->v2.loadImdToX.setCKEId = setCKEId;
85 1 : instr->v2.loadImdToX.setCKEMask = setCKEMask;
86 1 : }
87 :
88 1 : void Nop(CcuInstr* instr) { instr->header = InstrHeader(LOAD_TYPE, NOP_CODE); }
89 :
90 : inline void
91 5 : Operator(CcuInstr* instr, uint16_t xdId, uint16_t xnId, uint16_t xmId, uint16_t setCKEId, uint16_t setCKEMask)
92 : {
93 5 : instr->v2.operate.xdId = xdId;
94 5 : instr->v2.operate.xnId = xnId;
95 5 : instr->v2.operate.xmId = xmId;
96 5 : instr->v2.operate.setCKEId = setCKEId;
97 5 : instr->v2.operate.setCKEMask = setCKEMask;
98 5 : }
99 :
100 1 : void Assign(CcuInstr* instr, uint16_t result, uint16_t operand, uint16_t setCKEId, uint16_t setCKEMask)
101 : {
102 1 : AddI(instr, result, operand, 0, setCKEId, setCKEMask);
103 1 : }
104 :
105 : void
106 1 : Add(CcuInstr* instr, uint16_t result, uint16_t operand1, uint16_t operand2, uint16_t setCKEId,
107 : uint16_t setCKEMask)
108 : {
109 1 : instr->header = InstrHeader(LOAD_TYPE, ADD_CODE);
110 1 : instr->v2.operate.parMode = 1;
111 1 : Operator(instr, result, operand1, operand2, setCKEId, setCKEMask);
112 1 : }
113 :
114 : void
115 2 : AddI(CcuInstr* instr, uint16_t result, uint16_t operand, uint16_t imm, uint16_t setCKEId, uint16_t setCKEMask)
116 : {
117 2 : instr->header = InstrHeader(LOAD_TYPE, ADD_CODE);
118 2 : instr->v2.operate.parMode = 0;
119 2 : Operator(instr, result, operand, imm, setCKEId, setCKEMask);
120 2 : }
121 :
122 : void
123 1 : Mul(CcuInstr* instr, uint16_t result, uint16_t operand1, uint16_t operand2, uint16_t setCKEId,
124 : uint16_t setCKEMask)
125 : {
126 1 : instr->header = InstrHeader(LOAD_TYPE, MUL_CODE);
127 1 : instr->v2.operate.parMode = 1;
128 1 : Operator(instr, result, operand1, operand2, setCKEId, setCKEMask);
129 1 : }
130 :
131 : void
132 1 : MulI(CcuInstr* instr, uint16_t result, uint16_t operand, uint16_t imm, uint16_t setCKEId, uint16_t setCKEMask)
133 : {
134 1 : instr->header = InstrHeader(LOAD_TYPE, MUL_CODE);
135 1 : instr->v2.operate.parMode = 0;
136 1 : Operator(instr, result, operand, imm, setCKEId, setCKEMask);
137 1 : }
138 :
139 : // LoadChannel、LoadInstruction暂不实现
140 :
141 1 : void LoadFromMem(
142 : CcuInstr* instr, uint16_t dst, uint16_t src, uint16_t srcToken, uint16_t len,
143 : const CacheConfig& cacheConfig, uint16_t setCKEId, uint16_t setCKEMask)
144 : {
145 1 : instr->header = InstrHeader(LOAD_TYPE, LOAD_CODE);
146 1 : instr->v2.load.xdId = dst;
147 1 : instr->v2.load.xsId = src;
148 1 : instr->v2.load.xstId = srcToken;
149 1 : instr->v2.load.xlId = len;
150 :
151 1 : instr->v2.load.allocHint = cacheConfig.allocHint & 0x3;
152 1 : instr->v2.load.victimHint = cacheConfig.victimHint & 0x3;
153 :
154 1 : instr->v2.load.setCKEId = setCKEId;
155 1 : instr->v2.load.setCKEMask = setCKEMask;
156 1 : }
157 :
158 1 : void LoadXFromMem(
159 : CcuInstr* instr, uint16_t dst, uint16_t src, uint16_t srcToken, uint16_t len,
160 : const CacheConfig& cacheConfig, uint16_t setCKEId, uint16_t setCKEMask)
161 : {
162 1 : if (instr == nullptr) {
163 0 : HCCL_ERROR("[CcuV2::LoadXFromMem] instr is nullptr!");
164 0 : return;
165 : }
166 1 : LoadFromMem(instr, dst, src, srcToken, len, cacheConfig, setCKEId, setCKEMask);
167 1 : instr->v2.load.dstType = 0x0;
168 : }
169 :
170 : // HSCB Store暂不实现
171 :
172 1 : void StoreXToMem(
173 : CcuInstr* instr, uint16_t dst, uint16_t dstToken, uint16_t src, uint16_t len,
174 : const CacheConfig& cacheConfig, uint16_t setCKEId, uint16_t setCKEMask)
175 : {
176 1 : instr->header = InstrHeader(LOAD_TYPE, STORE_CODE);
177 1 : instr->v2.store.xdId = dst;
178 1 : instr->v2.store.xdtId = dstToken;
179 1 : instr->v2.store.xsId = src;
180 1 : instr->v2.store.xlId = len;
181 :
182 1 : instr->v2.store.srcType = 0x0;
183 :
184 1 : instr->v2.store.allocHint = cacheConfig.allocHint & 0x3;
185 1 : instr->v2.store.victimHint = cacheConfig.victimHint & 0x3;
186 :
187 1 : instr->v2.store.setCKEId = setCKEId;
188 1 : instr->v2.store.setCKEMask = setCKEMask;
189 1 : }
190 :
191 : // startInstrId ~ endInstrId之间的指令构成loop
192 : // Xm寄存器中的内容:LoopCtxId[52:45], Offset[44:13], IterNum[12:0]
193 : // IterNum[12:0] loop执行IterNum次 loop每次执行, 地址偏移为Offset loop在第LoopCtxId个LoopEngine上执行
194 1 : void Loop(
195 : CcuInstr* instr, uint16_t startInstrId, uint16_t endInstrId, uint16_t iterNum, uint16_t offset,
196 : uint16_t contextId)
197 : {
198 1 : instr->header = InstrHeader(CTRL_TYPE, LOOP_CODE);
199 1 : instr->v2.loop.startInstrId = startInstrId;
200 1 : instr->v2.loop.endInstrId = endInstrId;
201 1 : instr->v2.loop.xmId = iterNum;
202 1 : instr->v2.loop.xnId = offset;
203 1 : instr->v2.loop.xpId = contextId;
204 1 : instr->v2.loop.mode = 0;
205 1 : instr->v2.loop.wishCKEBit = 0;
206 1 : }
207 :
208 : // startLoopInstrId为LoopGroup所包含的Loop的起始地址
209 : // Xn寄存器中的内容:ExtendNum[22:16], RepeatLoopIndex[15:9], LoopNum[8:0]
210 : // Xm寄存器中的内容:gsaOffset[52:21], MSOffset[20:10], ckeOffset[9:0]
211 : // xnOffset[52:21], xnOffset[31:0]
212 : // 从startLoopInstrId开始,共LoopNum个Loop,并且从RepeatLoopIndex个开始,展开ExtendNum次
213 : // 每个展开的Loop,使用的MSId偏移为msOffset,使用的CKEId偏移为ckeOffset,使用的地址偏移为gsaOffset,
214 : // 使用的XnId偏移为xnOffset
215 1 : void LoopGroup(
216 : CcuInstr* instr, uint16_t startLoopInstrId, uint16_t loopGroupConfig, uint16_t resOffset, uint16_t xnOffset)
217 : {
218 1 : instr->header = InstrHeader(CTRL_TYPE, LOOPGROUP_CODE);
219 1 : instr->v2.loopGroup.startLoopInstrId = startLoopInstrId;
220 1 : instr->v2.loopGroup.xnId = loopGroupConfig;
221 1 : instr->v2.loopGroup.xmId = resOffset;
222 1 : instr->v2.loopGroup.xpId = xnOffset;
223 1 : }
224 :
225 : // 后续函数中, 均需要wait到<waitCKEId, waitCKEMask>后, 再执行相关操作, 执行完之后再set<setCKEId, setCKEMask>
226 : // clearType = 1时, wait到之后需要对<waitCKEId, waitCKEMask>清零, 否则不清零
227 :
228 1 : void SetCKE(
229 : CcuInstr* instr, uint16_t setCKEId, uint16_t setCKEMask, uint16_t waitCKEId, uint16_t waitCKEMask,
230 : uint16_t clearType)
231 : {
232 1 : instr->header = InstrHeader(CTRL_TYPE, SETCKBIT_CODE);
233 1 : instr->v2.setCKE.clearType = clearType & 0x1;
234 1 : instr->v2.setCKE.setCKEId = setCKEId;
235 1 : instr->v2.setCKE.setCKEMask = setCKEMask;
236 1 : instr->v2.setCKE.waitCKEId = waitCKEId;
237 1 : instr->v2.setCKE.waitCKEMask = waitCKEMask;
238 1 : }
239 :
240 1 : void ClearCKE(
241 : CcuInstr* instr, uint16_t clearCKEId, uint16_t clearMask, uint16_t waitCKEId, uint16_t waitCKEMask,
242 : uint16_t clearType)
243 : {
244 1 : instr->header = InstrHeader(CTRL_TYPE, CLEARCKBIT_CODE);
245 1 : instr->v2.clearCKE.clearType = clearType & 0x1;
246 1 : instr->v2.clearCKE.clearCKEId = clearCKEId;
247 1 : instr->v2.clearCKE.clearMask = clearMask;
248 1 : instr->v2.clearCKE.waitCKEId = waitCKEId;
249 1 : instr->v2.clearCKE.waitCKEMask = waitCKEMask;
250 1 : }
251 :
252 1 : void Jump(
253 : CcuInstr* instr, uint16_t relTarInstrXnId, uint16_t conditionXnId, uint16_t expectedXnId,
254 : uint16_t conditionType)
255 : {
256 1 : instr->header = InstrHeader(CTRL_TYPE, JMP_CODE);
257 1 : instr->v2.jmp.expectedXnId = expectedXnId;
258 1 : instr->v2.jmp.conditionXnId = conditionXnId;
259 1 : instr->v2.jmp.relTarInstrXnId = relTarInstrXnId;
260 1 : instr->v2.jmp.conditionType = conditionType & 0xF;
261 1 : }
262 :
263 : // Wait暂不实现
264 : // Fence暂不实现
265 :
266 : // 本端Memory传输到本端MS
267 1 : void TransLocMemToLocMS(
268 : CcuInstr* instr, uint16_t ms, uint16_t src, uint16_t srcToken, uint16_t len, uint16_t offset,
269 : uint16_t setCKEId, uint16_t setCKEMask, const CacheConfig& cacheConfig)
270 : {
271 1 : instr->header = InstrHeader(TRANS_TYPE, TRANSLOCMEMTOLOCMS_CODE);
272 1 : instr->v2.transLocMemToLocMS.msId = ms;
273 1 : instr->v2.transLocMemToLocMS.xsId = src;
274 1 : instr->v2.transLocMemToLocMS.xstId = srcToken;
275 1 : instr->v2.transLocMemToLocMS.xlId = len;
276 1 : instr->v2.transLocMemToLocMS.xoId = offset;
277 1 : instr->v2.transLocMemToLocMS.allocHint = cacheConfig.allocHint & 0x3;
278 1 : instr->v2.transLocMemToLocMS.victimHint = cacheConfig.victimHint & 0x3;
279 1 : instr->v2.transLocMemToLocMS.setCKEId = setCKEId;
280 1 : instr->v2.transLocMemToLocMS.setCKEMask = setCKEMask;
281 1 : }
282 :
283 : // 本端MS传输到本端Memory
284 1 : void TransLocMSToLocMem(
285 : CcuInstr* instr, uint16_t dst, uint16_t dstToken, uint16_t ms, uint16_t len, uint16_t offset,
286 : uint16_t setCKEId, uint16_t setCKEMask, const CacheConfig& cacheConfig)
287 : {
288 1 : instr->header = InstrHeader(TRANS_TYPE, TRANSLOCMSTOLOCMEM_CODE);
289 1 : instr->v2.transLocMSToLocMem.xdId = dst;
290 1 : instr->v2.transLocMSToLocMem.xdtId = dstToken;
291 1 : instr->v2.transLocMSToLocMem.msId = ms;
292 1 : instr->v2.transLocMSToLocMem.xlId = len;
293 1 : instr->v2.transLocMSToLocMem.xoId = offset;
294 1 : instr->v2.transLocMSToLocMem.allocHint = cacheConfig.allocHint & 0x3;
295 1 : instr->v2.transLocMSToLocMem.victimHint = cacheConfig.victimHint & 0x3;
296 1 : instr->v2.transLocMSToLocMem.setCKEId = setCKEId;
297 1 : instr->v2.transLocMSToLocMem.setCKEMask = setCKEMask;
298 1 : }
299 :
300 1 : void TransLocMemToLocMem(
301 : CcuInstr* instr, uint16_t dst, uint16_t dstToken, uint16_t src, uint16_t srcToken, uint16_t len,
302 : uint16_t usedMSId, uint16_t setCKEId, uint16_t setCKEMask, const CacheConfig& srcCacheConfig,
303 : const CacheConfig& dstcacheConfig)
304 : {
305 1 : instr->header = InstrHeader(TRANS_TYPE, TRANSLOCMEMTOLOCMEM_CODE);
306 1 : instr->v2.transLocMemToLocMem.xdId = dst;
307 1 : instr->v2.transLocMemToLocMem.xdtId = dstToken;
308 1 : instr->v2.transLocMemToLocMem.xsId = src;
309 1 : instr->v2.transLocMemToLocMem.xstId = srcToken;
310 1 : instr->v2.transLocMemToLocMem.xlId = len;
311 1 : instr->v2.transLocMemToLocMem.usedMSId = usedMSId;
312 1 : instr->v2.transLocMemToLocMem.msNum = CCU_MS_INTERLEAVE;
313 :
314 1 : instr->v2.transLocMemToLocMem.srcAllocHint = srcCacheConfig.allocHint & 0x3;
315 1 : instr->v2.transLocMemToLocMem.srcVictimHint = srcCacheConfig.victimHint & 0x3;
316 1 : instr->v2.transLocMemToLocMem.dstAllocHint = dstcacheConfig.allocHint & 0x3;
317 1 : instr->v2.transLocMemToLocMem.dstVictimHint = dstcacheConfig.victimHint & 0x3;
318 :
319 1 : instr->v2.transLocMemToLocMem.setCKEId = setCKEId;
320 1 : instr->v2.transLocMemToLocMem.setCKEMask = setCKEMask;
321 1 : }
322 :
323 1 : void TransMem(
324 : CcuInstr* instr, uint16_t dst, uint16_t dstToken, uint16_t src, uint16_t srcToken, uint16_t len,
325 : uint16_t channel, const TransMemNotifyInfo& notify, const TransMemReduceInfo& reduce,
326 : const TransMemConfig& config, uint16_t setCKEId, uint16_t setCKEMask)
327 : {
328 1 : instr->header = InstrHeader(TRANS_TYPE, TRANSMEM_CODE);
329 1 : instr->v2.transMem.xdId = dst;
330 1 : instr->v2.transMem.xdtId = dstToken;
331 1 : instr->v2.transMem.xsId = src;
332 1 : instr->v2.transMem.xstId = srcToken;
333 1 : instr->v2.transMem.xlId = len;
334 1 : instr->v2.transMem.xcId = channel;
335 1 : instr->v2.transMem.xnId = notify.xnId;
336 1 : instr->v2.transMem.xntId = notify.xntId;
337 1 : instr->v2.transMem.value = notify.value;
338 1 : instr->v2.transMem.udfType = reduce.udfType & 0xFF;
339 1 : instr->v2.transMem.reduceDataType = reduce.reduceDataType & 0xF;
340 1 : instr->v2.transMem.reduceOpCode = reduce.reduceOpCode & 0xF;
341 :
342 1 : instr->v2.transMem.order = config.order & 0x7;
343 1 : instr->v2.transMem.fence = config.fence & 0x1;
344 1 : instr->v2.transMem.cqe = config.cqe & 0x1;
345 1 : instr->v2.transMem.nf = config.nf & 0x1;
346 1 : instr->v2.transMem.udfEnable = config.udfEnable & 0x1;
347 1 : instr->v2.transMem.splitMode = config.splitMode & 0x1;
348 1 : instr->v2.transMem.se = config.se & 0x1;
349 1 : instr->v2.transMem.rmtJettyType = config.rmtJettyType & 0x3;
350 :
351 1 : instr->v2.transMem.setCKEId = setCKEId;
352 1 : instr->v2.transMem.setCKEMask = setCKEMask;
353 1 : }
354 :
355 : // 将本端Xn的值写入远端8B地址
356 3 : inline void SyncWtX(
357 : CcuInstr* instr, uint16_t dst, uint16_t dstToken, uint16_t xn, uint16_t channelId, uint16_t setCKEId,
358 : uint16_t setCKEMask)
359 : {
360 3 : instr->header = InstrHeader(TRANS_TYPE, SYNCWTX_CODE);
361 3 : instr->v2.syncWtX.xdId = dst;
362 3 : instr->v2.syncWtX.xdtId = dstToken;
363 3 : instr->v2.syncWtX.xsId = xn;
364 3 : instr->v2.syncWtX.xcId = channelId;
365 :
366 3 : instr->v2.syncWtX.setCKEId = setCKEId;
367 3 : instr->v2.syncWtX.setCKEMask = setCKEMask;
368 3 : }
369 :
370 : // 将本端Xn的值写入远端8B地址并置位远端CKE
371 1 : void SyncWtX(
372 : CcuInstr* instr, uint16_t dst, uint16_t dstToken, uint16_t xn, uint16_t channelId,
373 : const TransMemNotifyInfo& notify, uint16_t setCKEId, uint16_t setCKEMask)
374 : {
375 1 : SyncWtX(instr, dst, dstToken, xn, channelId, setCKEId, setCKEMask);
376 1 : instr->v2.syncWtX.xnId = notify.xnId;
377 1 : instr->v2.syncWtX.xntId = notify.xntId;
378 1 : instr->v2.syncWtX.value = notify.value;
379 :
380 1 : instr->v2.syncWtX.notifyValid = 1;
381 1 : instr->v2.syncWtX.parMode = 1;
382 1 : }
383 :
384 : // 置位远端CKE
385 1 : void SyncWtX(
386 : CcuInstr* instr, const TransMemNotifyInfo& notify, uint16_t channelId, uint16_t setCKEId,
387 : uint16_t setCKEMask)
388 : {
389 1 : SyncWtX(instr, notify.xnId, notify.xntId, notify.value, channelId, setCKEId, setCKEMask);
390 :
391 1 : instr->v2.syncWtX.notifyValid = 0;
392 1 : instr->v2.syncWtX.parMode = 0;
393 1 : }
394 :
395 : // 将本端Xn的值以atomic store add的方式写入远端8B地址
396 1 : void SyncAtX(
397 : CcuInstr* instr, uint16_t dst, uint16_t dstToken, uint16_t mask, uint16_t channelId, uint16_t setCKEId,
398 : uint16_t setCKEMask)
399 : {
400 1 : instr->header = InstrHeader(TRANS_TYPE, SYNCATX_CODE);
401 1 : instr->v2.syncAtX.xdId = dst;
402 1 : instr->v2.syncAtX.xdtId = dstToken;
403 1 : instr->v2.syncAtX.xsId = mask;
404 1 : instr->v2.syncAtX.xcId = channelId;
405 :
406 1 : instr->v2.syncAtX.parMode = 1;
407 :
408 1 : instr->v2.syncAtX.setCKEId = setCKEId;
409 1 : instr->v2.syncAtX.setCKEMask = setCKEMask;
410 1 : }
411 :
412 : // MSA~MSH Reduce到 MSA
413 3 : inline void Reduce(
414 : CcuInstr* instr, uint16_t* ms, uint16_t count, uint16_t castEn, uint16_t dataType, uint16_t setCKEId,
415 : uint16_t setCKEMask)
416 : {
417 : // 由调用者保证传入的count >= 2(reduce的数据源)
418 3 : count -= 2; // CCU指令中指定count数为实际参与运算的MS数减2
419 :
420 27 : for (uint16_t index = 0; index < CCU_REDUCE_MAX_MS; index++) {
421 24 : instr->v2.reduce.msId[index] = ms[index];
422 : }
423 3 : instr->v2.reduce.count = count & 0x7;
424 3 : instr->v2.reduce.castEn = castEn & 0x3;
425 3 : instr->v2.reduce.dataType = dataType & 0x1f;
426 3 : instr->v2.reduce.setCKEId = setCKEId;
427 3 : instr->v2.reduce.setCKEMask = setCKEMask;
428 3 : }
429 :
430 1 : void ReduceAdd(
431 : CcuInstr* instr, uint16_t* ms, uint16_t count, uint16_t castEn, uint16_t dataType, uint16_t setCKEId,
432 : uint16_t setCKEMask)
433 : {
434 1 : if (instr == nullptr) {
435 0 : HCCL_ERROR("[CcuV2::ReduceAdd] instr is nullptr!");
436 0 : return;
437 : }
438 1 : instr->header = InstrHeader(REDUCE_TYPE, REDUCE_ADD_CODE);
439 1 : Reduce(instr, ms, count, castEn, dataType, setCKEId, setCKEMask);
440 : }
441 :
442 1 : void ReduceMax(
443 : CcuInstr* instr, uint16_t* ms, uint16_t count, uint16_t dataType, uint16_t setCKEId, uint16_t setCKEMask)
444 : {
445 1 : instr->header = InstrHeader(REDUCE_TYPE, REDUCE_MAX_CODE);
446 1 : Reduce(instr, ms, count, 0, dataType, setCKEId, setCKEMask);
447 1 : }
448 :
449 1 : void ReduceMin(
450 : CcuInstr* instr, uint16_t* ms, uint16_t count, uint16_t dataType, uint16_t setCKEId, uint16_t setCKEMask)
451 : {
452 1 : instr->header = InstrHeader(REDUCE_TYPE, REDUCE_MIN_CODE);
453 1 : Reduce(instr, ms, count, 0, dataType, setCKEId, setCKEMask);
454 1 : }
455 : }; // namespace CcuV2
456 :
457 : }; // namespace CcuRep
458 : }; // namespace Hccl
|