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