gem5 [DEVELOP-FOR-25.0]
Loading...
Searching...
No Matches
sve_macromem.hh
Go to the documentation of this file.
1/*
2 * Copyright (c) 2018 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 */
37
38#ifndef __ARCH_ARM_SVE_MACROMEM_HH__
39#define __ARCH_ARM_SVE_MACROMEM_HH__
40
41#include "arch/arm/generated/decoder.hh"
43
44namespace gem5
45{
46
47namespace ArmISA {
48
49template <typename Element,
50 template <typename> class MicroopLdMemType,
51 template <typename> class MicroopDeIntrlvType>
53{
54 protected:
59 uint8_t numregs;
60
61 public:
62 SveLdStructSS(const char* mnem, ExtMachInst machInst, OpClass __opClass,
63 RegIndex _dest, RegIndex _gp, RegIndex _base,
64 RegIndex _offset, uint8_t _numregs)
65 : PredMacroOp(mnem, machInst, __opClass),
66 dest(_dest), gp(_gp), base(_base), offset(_offset), numregs(_numregs)
67 {
68 numMicroops = numregs * 2;
69
71
72 for (int i = 0; i < numregs; ++i) {
73 microOps[i] = new MicroopLdMemType<Element>(
74 mnem, machInst, static_cast<RegIndex>(INTRLVREG0 + i),
75 _gp, _base, _offset, _numregs, i);
76 }
77 for (int i = 0; i < numregs; ++i) {
78 microOps[i + numregs] = new MicroopDeIntrlvType<Element>(
79 mnem, machInst, static_cast<RegIndex>((_dest + i) % 32),
80 _numregs, i, this);
81 }
82
83 microOps[0]->setFirstMicroop();
84 microOps[numMicroops - 1]->setLastMicroop();
85
86 for (StaticInstPtr *uop = microOps; !(*uop)->isLastMicroop(); uop++) {
87 (*uop)->setDelayedCommit();
88 }
89 }
90
91 Fault
93 {
94 panic("Execute method called when it shouldn't!");
95 return NoFault;
96 }
97
98 std::string
100 const loader::SymbolTable *symtab) const override
101 {
102 std::stringstream ss;
103 printMnemonic(ss, "", false);
104 ccprintf(ss, "{");
105 for (int i = 0; i < numregs; ++i) {
106 printVecReg(ss, (dest + i) % 32, true);
107 if (i < numregs - 1)
108 ccprintf(ss, ", ");
109 }
110 ccprintf(ss, "}, ");
112 ccprintf(ss, "/z, [");
114 ccprintf(ss, ", ");
116 ccprintf(ss, "]");
117 return ss.str();
118 }
119};
120
121template <typename Element,
122 template <typename> class MicroopStMemType,
123 template <typename> class MicroopIntrlvType>
125{
126 protected:
131 uint8_t numregs;
132
133 public:
134 SveStStructSS(const char* mnem, ExtMachInst machInst, OpClass __opClass,
135 RegIndex _dest, RegIndex _gp, RegIndex _base,
136 RegIndex _offset, uint8_t _numregs)
137 : PredMacroOp(mnem, machInst, __opClass),
138 dest(_dest), gp(_gp), base(_base), offset(_offset), numregs(_numregs)
139 {
140 numMicroops = numregs * 2;
141
143
144 for (int i = 0; i < numregs; ++i) {
145 microOps[i] = new MicroopIntrlvType<Element>(
146 mnem, machInst, static_cast<RegIndex>(INTRLVREG0 + i),
147 _dest, _numregs, i, this);
148 }
149
150 for (int i = 0; i < numregs; ++i) {
151 microOps[i + numregs] = new MicroopStMemType<Element>(
152 mnem, machInst, static_cast<RegIndex>(INTRLVREG0 + i),
153 _gp, _base, _offset, _numregs, i);
154 }
155
156 microOps[0]->setFirstMicroop();
157 microOps[numMicroops - 1]->setLastMicroop();
158
159 for (StaticInstPtr *uop = microOps; !(*uop)->isLastMicroop(); uop++) {
160 (*uop)->setDelayedCommit();
161 }
162 }
163
164 Fault
166 {
167 panic("Execute method called when it shouldn't!");
168 return NoFault;
169 }
170
171 std::string
173 const loader::SymbolTable *symtab) const override
174 {
175 std::stringstream ss;
176 printMnemonic(ss, "", false);
177 ccprintf(ss, "{");
178 for (int i = 0; i < numregs; ++i) {
179 printVecReg(ss, (dest + i) % 32, true);
180 if (i < numregs - 1)
181 ccprintf(ss, ", ");
182 }
183 ccprintf(ss, "}, ");
185 ccprintf(ss, ", [");
187 ccprintf(ss, ", ");
189 ccprintf(ss, "]");
190 return ss.str();
191 }
192};
193
194
195template <typename Element,
196 template <typename> class MicroopLdMemType,
197 template <typename> class MicroopDeIntrlvType>
199{
200 protected:
204 int64_t imm;
205 uint8_t numregs;
206
207 public:
208 SveLdStructSI(const char* mnem, ExtMachInst machInst, OpClass __opClass,
209 RegIndex _dest, RegIndex _gp, RegIndex _base,
210 int64_t _imm, uint8_t _numregs)
211 : PredMacroOp(mnem, machInst, __opClass),
212 dest(_dest), gp(_gp), base(_base), imm(_imm), numregs(_numregs)
213 {
214 numMicroops = numregs * 2;
215
217
218 for (int i = 0; i < numregs; ++i) {
219 microOps[i] = new MicroopLdMemType<Element>(
220 mnem, machInst, static_cast<RegIndex>(INTRLVREG0 + i),
221 _gp, _base, _imm, _numregs, i);
222 }
223 for (int i = 0; i < numregs; ++i) {
224 microOps[i + numregs] = new MicroopDeIntrlvType<Element>(
225 mnem, machInst, static_cast<RegIndex>((_dest + i) % 32),
226 _numregs, i, this);
227 }
228
229 microOps[0]->setFirstMicroop();
230 microOps[numMicroops - 1]->setLastMicroop();
231
232 for (StaticInstPtr *uop = microOps; !(*uop)->isLastMicroop(); uop++) {
233 (*uop)->setDelayedCommit();
234 }
235 }
236
237 Fault
239 {
240 panic("Execute method called when it shouldn't!");
241 return NoFault;
242 }
243
244 std::string
246 const loader::SymbolTable *symtab) const override
247 {
248 std::stringstream ss;
249 printMnemonic(ss, "", false);
250 ccprintf(ss, "{");
251 for (int i = 0; i < numregs; ++i) {
252 printVecReg(ss, (dest + i) % 32, true);
253 if (i < numregs - 1)
254 ccprintf(ss, ", ");
255 }
256 ccprintf(ss, "}, ");
258 ccprintf(ss, "/z, [");
260 if (imm != 0) {
261 ccprintf(ss, ", #%d, MUL VL", imm);
262 }
263 ccprintf(ss, "]");
264 return ss.str();
265 }
266};
267
268template <typename Element,
269 template <typename> class MicroopStMemType,
270 template <typename> class MicroopIntrlvType>
272{
273 protected:
277 int64_t imm;
278 uint8_t numregs;
279
280 public:
281 SveStStructSI(const char* mnem, ExtMachInst machInst, OpClass __opClass,
282 RegIndex _dest, RegIndex _gp, RegIndex _base,
283 int64_t _imm, uint8_t _numregs)
284 : PredMacroOp(mnem, machInst, __opClass),
285 dest(_dest), gp(_gp), base(_base), imm(_imm), numregs(_numregs)
286 {
287 numMicroops = numregs * 2;
288
290
291 for (int i = 0; i < numregs; ++i) {
292 microOps[i] = new MicroopIntrlvType<Element>(
293 mnem, machInst, static_cast<RegIndex>(INTRLVREG0 + i),
294 _dest, _numregs, i, this);
295 }
296
297 for (int i = 0; i < numregs; ++i) {
298 microOps[i + numregs] = new MicroopStMemType<Element>(
299 mnem, machInst, static_cast<RegIndex>(INTRLVREG0 + i),
300 _gp, _base, _imm, _numregs, i);
301 }
302
303 microOps[0]->setFirstMicroop();
304 microOps[numMicroops - 1]->setLastMicroop();
305
306 for (StaticInstPtr *uop = microOps; !(*uop)->isLastMicroop(); uop++) {
307 (*uop)->setDelayedCommit();
308 }
309 }
310
311 Fault
313 {
314 panic("Execute method called when it shouldn't!");
315 return NoFault;
316 }
317
318 std::string
320 const loader::SymbolTable *symtab) const override
321 {
322 std::stringstream ss;
323 printMnemonic(ss, "", false);
324 ccprintf(ss, "{");
325 for (int i = 0; i < numregs; ++i) {
326 printVecReg(ss, (dest + i) % 32, true);
327 if (i < numregs - 1)
328 ccprintf(ss, ", ");
329 }
330 ccprintf(ss, "}, ");
332 ccprintf(ss, ", [");
334 if (imm != 0) {
335 ccprintf(ss, ", #%d, MUL VL", imm);
336 }
337 ccprintf(ss, "]");
338 return ss.str();
339 }
340};
341
342template <typename RegElemType, typename MemElemType,
343 template <typename, typename> class MicroopType,
344 template <typename> class FirstFaultWritebackMicroopType>
346{
347 protected:
351 uint64_t imm;
352
353 public:
354 SveIndexedMemVI(const char *mnem, ExtMachInst machInst, OpClass __opClass,
355 RegIndex _dest, RegIndex _gp, RegIndex _base,
356 uint64_t _imm, bool firstFault)
357 : PredMacroOp(mnem, machInst, __opClass),
358 dest(_dest), gp(_gp), base(_base), imm(_imm)
359 {
360 bool isLoad = (__opClass == MemReadOp);
361 assert(!firstFault || isLoad);
362
363 int num_elems = ((machInst.sveLen + 1) * 16) / sizeof(RegElemType);
364
365 numMicroops = num_elems;
366 if (isLoad) {
367 if (firstFault) {
368 numMicroops += 2;
369 } else {
370 numMicroops++;
371 }
372 }
373
375
376 StaticInstPtr *uop = microOps;
377
378 if (isLoad) {
379 // The first microop of a gather load copies the source vector
380 // register used for address calculation to an auxiliary register,
381 // with all subsequent microops reading from the latter. This is
382 // needed to properly handle cases where the source vector
383 // register is the same as the destination register
384 *uop = new ArmISAInst::SveGatherLoadCpySrcVecMicroop(
385 mnem, machInst, _base, this);
386 uop++;
387 }
388
389 for (int i = 0; i < num_elems; i++, uop++) {
390 *uop = new MicroopType<RegElemType, MemElemType>(
391 mnem, machInst, __opClass, _dest, _gp,
392 isLoad ? (RegIndex) VECREG_UREG0 : _base, _imm, i,
393 num_elems, firstFault);
394 }
395
396 if (firstFault) {
397 *uop = new FirstFaultWritebackMicroopType<RegElemType>(
398 mnem, machInst, __opClass, num_elems, this);
399 } else {
400 --uop;
401 }
402
403 (*uop)->setLastMicroop();
404 microOps[0]->setFirstMicroop();
405
406 for (StaticInstPtr *uop = microOps; !(*uop)->isLastMicroop(); uop++) {
407 (*uop)->setDelayedCommit();
408 }
409 }
410
411 Fault
413 {
414 panic("Execute method called when it shouldn't!");
415 return NoFault;
416 }
417
418 std::string
420 const loader::SymbolTable *symtab) const override
421 {
422 // TODO: add suffix to transfer and base registers
423 std::stringstream ss;
424 printMnemonic(ss, "", false);
425 ccprintf(ss, "{");
426 printVecReg(ss, dest, true);
427 ccprintf(ss, "}, ");
429 ccprintf(ss, "/z, [");
430 printVecReg(ss, base, true);
431 if (imm != 0) {
432 ccprintf(ss, ", #%d", imm * sizeof(MemElemType));
433 }
434 ccprintf(ss, "]");
435 return ss.str();
436 }
437};
438
439template <typename RegElemType, typename MemElemType,
440 template <typename, typename> class MicroopType,
441 template <typename> class FirstFaultWritebackMicroopType>
443{
444 protected:
449
453
454 public:
455 SveIndexedMemSV(const char *mnem, ExtMachInst machInst, OpClass __opClass,
456 RegIndex _dest, RegIndex _gp, RegIndex _base,
457 RegIndex _offset, bool _offsetIs32,
458 bool _offsetIsSigned, bool _offsetIsScaled,
459 bool firstFault)
460 : PredMacroOp(mnem, machInst, __opClass),
461 dest(_dest), gp(_gp), base(_base), offset(_offset),
462 offsetIs32(_offsetIs32), offsetIsSigned(_offsetIsSigned),
463 offsetIsScaled(_offsetIsScaled)
464 {
465 bool isLoad = (__opClass == MemReadOp);
466 assert(!firstFault || isLoad);
467
468 int num_elems = ((machInst.sveLen + 1) * 16) / sizeof(RegElemType);
469
470 numMicroops = num_elems;
471 if (isLoad) {
472 if (firstFault) {
473 numMicroops += 2;
474 } else {
475 numMicroops++;
476 }
477 }
478
480
481 StaticInstPtr *uop = microOps;
482
483 if (isLoad) {
484 // The first microop of a gather load copies the source vector
485 // register used for address calculation to an auxiliary register,
486 // with all subsequent microops reading from the latter. This is
487 // needed to properly handle cases where the source vector
488 // register is the same as the destination register
489 *uop = new ArmISAInst::SveGatherLoadCpySrcVecMicroop(
490 mnem, machInst, _offset, this);
491 uop++;
492 }
493
494 for (int i = 0; i < num_elems; i++, uop++) {
495 *uop = new MicroopType<RegElemType, MemElemType>(
496 mnem, machInst, __opClass, _dest, _gp, _base,
497 isLoad ? (RegIndex) VECREG_UREG0 : _offset, _offsetIs32,
498 _offsetIsSigned, _offsetIsScaled, i, num_elems, firstFault);
499 }
500
501 if (firstFault) {
502 *uop = new FirstFaultWritebackMicroopType<RegElemType>(
503 mnem, machInst, __opClass, num_elems, this);
504 } else {
505 --uop;
506 }
507
508 (*uop)->setLastMicroop();
509 microOps[0]->setFirstMicroop();
510
511 for (StaticInstPtr *uop = microOps; !(*uop)->isLastMicroop(); uop++) {
512 (*uop)->setDelayedCommit();
513 }
514 }
515
516 Fault
518 {
519 panic("Execute method called when it shouldn't!");
520 return NoFault;
521 }
522
523 std::string
525 const loader::SymbolTable *symtab) const override
526 {
527 // TODO: add suffix to transfer and base registers
528 std::stringstream ss;
529 printMnemonic(ss, "", false);
530 ccprintf(ss, "{");
531 printVecReg(ss, dest, true);
532 ccprintf(ss, "}, ");
534 ccprintf(ss, "/z, [");
536 ccprintf(ss, ", ");
537 printVecReg(ss, offset, true);
538 ccprintf(ss, "]");
539 return ss.str();
540 }
541};
542
543} // namespace ArmISA
544} // namespace gem5
545
546#endif // __ARCH_ARM_SVE_MACROMEM_HH__
void printMnemonic(std::ostream &os, const std::string &suffix="", bool withPred=true, bool withCond64=false, ConditionCode cond64=COND_UC) const
void printVecReg(std::ostream &os, RegIndex reg_idx, bool isSveVecReg=false) const
void printIntReg(std::ostream &os, RegIndex reg_idx, uint8_t opWidth=0) const
Print a register name for disassembly given the unique dependence tag number (FP or int).
void printVecPredReg(std::ostream &os, RegIndex reg_idx) const
StaticInstPtr * microOps
Definition pred_inst.hh:347
PredMacroOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
Constructor.
Definition pred_inst.hh:350
std::string generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
SveIndexedMemSV(const char *mnem, ExtMachInst machInst, OpClass __opClass, RegIndex _dest, RegIndex _gp, RegIndex _base, RegIndex _offset, bool _offsetIs32, bool _offsetIsSigned, bool _offsetIsScaled, bool firstFault)
Fault execute(ExecContext *, trace::InstRecord *) const override
std::string generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
SveIndexedMemVI(const char *mnem, ExtMachInst machInst, OpClass __opClass, RegIndex _dest, RegIndex _gp, RegIndex _base, uint64_t _imm, bool firstFault)
Fault execute(ExecContext *, trace::InstRecord *) const override
SveLdStructSI(const char *mnem, ExtMachInst machInst, OpClass __opClass, RegIndex _dest, RegIndex _gp, RegIndex _base, int64_t _imm, uint8_t _numregs)
Fault execute(ExecContext *, trace::InstRecord *) const override
std::string generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
SveLdStructSS(const char *mnem, ExtMachInst machInst, OpClass __opClass, RegIndex _dest, RegIndex _gp, RegIndex _base, RegIndex _offset, uint8_t _numregs)
Fault execute(ExecContext *, trace::InstRecord *) const override
std::string generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
SveStStructSI(const char *mnem, ExtMachInst machInst, OpClass __opClass, RegIndex _dest, RegIndex _gp, RegIndex _base, int64_t _imm, uint8_t _numregs)
Fault execute(ExecContext *, trace::InstRecord *) const override
std::string generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
Fault execute(ExecContext *, trace::InstRecord *) const override
SveStStructSS(const char *mnem, ExtMachInst machInst, OpClass __opClass, RegIndex _dest, RegIndex _gp, RegIndex _base, RegIndex _offset, uint8_t _numregs)
std::string generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
The ExecContext is an abstract base class the provides the interface used by the ISA to manipulate th...
bool isLoad() const
#define panic(...)
This implements a cprintf based panic() function.
Definition logging.hh:220
Bitfield< 7 > i
Definition misc_types.hh:67
const int VECREG_UREG0
Definition vec.hh:92
Bitfield< 21 > ss
Definition misc_types.hh:60
const int INTRLVREG0
Definition vec.hh:88
Bitfield< 4 > pc
Copyright (c) 2024 Arm Limited All rights reserved.
Definition binary32.hh:36
uint16_t RegIndex
Definition types.hh:176
std::shared_ptr< FaultBase > Fault
Definition types.hh:249
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition types.hh:147
RefCountingPtr< StaticInst > StaticInstPtr
constexpr decltype(nullptr) NoFault
Definition types.hh:253
void ccprintf(cp::Print &print)
Definition cprintf.hh:130
static const OpClass MemReadOp
Definition op_class.hh:107

Generated on Mon May 26 2025 09:18:57 for gem5 by doxygen 1.13.2