gem5 v24.0.0.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
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
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
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
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();
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();
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
Base class for predicated macro-operations.
Definition pred_inst.hh:343
StaticInstPtr * microOps
Definition pred_inst.hh:347
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
bool isLastMicroop() const
#define panic(...)
This implements a cprintf based panic() function.
Definition logging.hh:188
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 - Pranith Kumar Copyright (c) 2020 Inria 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
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 Tue Jun 18 2024 16:23:56 for gem5 by doxygen 1.11.0