gem5  v19.0.0.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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  * Authors: Giacomo Gabrielli
38  */
39 
40 #ifndef __ARCH_ARM_SVE_MACROMEM_HH__
41 #define __ARCH_ARM_SVE_MACROMEM_HH__
42 
43 #include "arch/arm/generated/decoder.hh"
45 
46 namespace ArmISA {
47 
48 template <typename Element,
49  template <typename> class MicroopLdMemType,
50  template <typename> class MicroopDeIntrlvType>
51 class SveLdStructSS : public PredMacroOp
52 {
53  protected:
58  uint8_t numregs;
59 
60  public:
61  SveLdStructSS(const char* mnem, ExtMachInst machInst, OpClass __opClass,
62  IntRegIndex _dest, IntRegIndex _gp, IntRegIndex _base,
63  IntRegIndex _offset, uint8_t _numregs)
64  : PredMacroOp(mnem, machInst, __opClass),
65  dest(_dest), gp(_gp), base(_base), offset(_offset), numregs(_numregs)
66  {
67  numMicroops = numregs * 2;
68 
70 
71  for (int i = 0; i < numregs; ++i) {
72  microOps[i] = new MicroopLdMemType<Element>(
73  mnem, machInst, static_cast<IntRegIndex>(INTRLVREG0 + i),
74  _gp, _base, _offset, _numregs, i);
75  }
76  for (int i = 0; i < numregs; ++i) {
77  microOps[i + numregs] = new MicroopDeIntrlvType<Element>(
78  mnem, machInst, static_cast<IntRegIndex>((_dest + i) % 32),
79  _numregs, i, this);
80  }
81 
84 
85  for (StaticInstPtr *uop = microOps; !(*uop)->isLastMicroop(); uop++) {
86  (*uop)->setDelayedCommit();
87  }
88  }
89 
90  Fault
92  {
93  panic("Execute method called when it shouldn't!");
94  return NoFault;
95  }
96 
97  std::string
98  generateDisassembly(Addr pc, const SymbolTable *symtab) const
99  {
100  std::stringstream ss;
101  printMnemonic(ss, "", false);
102  ccprintf(ss, "{");
103  for (int i = 0; i < numregs; ++i) {
104  printVecReg(ss, (dest + i) % 32, true);
105  if (i < numregs - 1)
106  ccprintf(ss, ", ");
107  }
108  ccprintf(ss, "}, ");
109  printVecPredReg(ss, gp);
110  ccprintf(ss, "/z, [");
111  printIntReg(ss, base);
112  ccprintf(ss, ", ");
113  printIntReg(ss, offset);
114  ccprintf(ss, "]");
115  return ss.str();
116  }
117 };
118 
119 template <typename Element,
120  template <typename> class MicroopStMemType,
121  template <typename> class MicroopIntrlvType>
123 {
124  protected:
129  uint8_t numregs;
130 
131  public:
132  SveStStructSS(const char* mnem, ExtMachInst machInst, OpClass __opClass,
133  IntRegIndex _dest, IntRegIndex _gp, IntRegIndex _base,
134  IntRegIndex _offset, uint8_t _numregs)
135  : PredMacroOp(mnem, machInst, __opClass),
136  dest(_dest), gp(_gp), base(_base), offset(_offset), numregs(_numregs)
137  {
138  numMicroops = numregs * 2;
139 
141 
142  for (int i = 0; i < numregs; ++i) {
143  microOps[i] = new MicroopIntrlvType<Element>(
144  mnem, machInst, static_cast<IntRegIndex>(INTRLVREG0 + i),
145  _dest, _numregs, i, this);
146  }
147 
148  for (int i = 0; i < numregs; ++i) {
149  microOps[i + numregs] = new MicroopStMemType<Element>(
150  mnem, machInst, static_cast<IntRegIndex>(INTRLVREG0 + i),
151  _gp, _base, _offset, _numregs, i);
152  }
153 
156 
157  for (StaticInstPtr *uop = microOps; !(*uop)->isLastMicroop(); uop++) {
158  (*uop)->setDelayedCommit();
159  }
160  }
161 
162  Fault
164  {
165  panic("Execute method called when it shouldn't!");
166  return NoFault;
167  }
168 
169  std::string
170  generateDisassembly(Addr pc, const SymbolTable *symtab) const
171  {
172  std::stringstream ss;
173  printMnemonic(ss, "", false);
174  ccprintf(ss, "{");
175  for (int i = 0; i < numregs; ++i) {
176  printVecReg(ss, (dest + i) % 32, true);
177  if (i < numregs - 1)
178  ccprintf(ss, ", ");
179  }
180  ccprintf(ss, "}, ");
181  printVecPredReg(ss, gp);
182  ccprintf(ss, ", [");
183  printIntReg(ss, base);
184  ccprintf(ss, ", ");
185  printIntReg(ss, offset);
186  ccprintf(ss, "]");
187  return ss.str();
188  }
189 };
190 
191 
192 template <typename Element,
193  template <typename> class MicroopLdMemType,
194  template <typename> class MicroopDeIntrlvType>
196 {
197  protected:
201  int64_t imm;
202  uint8_t numregs;
203 
204  public:
205  SveLdStructSI(const char* mnem, ExtMachInst machInst, OpClass __opClass,
206  IntRegIndex _dest, IntRegIndex _gp, IntRegIndex _base,
207  int64_t _imm, uint8_t _numregs)
208  : PredMacroOp(mnem, machInst, __opClass),
209  dest(_dest), gp(_gp), base(_base), imm(_imm), numregs(_numregs)
210  {
211  numMicroops = numregs * 2;
212 
214 
215  for (int i = 0; i < numregs; ++i) {
216  microOps[i] = new MicroopLdMemType<Element>(
217  mnem, machInst, static_cast<IntRegIndex>(INTRLVREG0 + i),
218  _gp, _base, _imm, _numregs, i);
219  }
220  for (int i = 0; i < numregs; ++i) {
221  microOps[i + numregs] = new MicroopDeIntrlvType<Element>(
222  mnem, machInst, static_cast<IntRegIndex>((_dest + i) % 32),
223  _numregs, i, this);
224  }
225 
228 
229  for (StaticInstPtr *uop = microOps; !(*uop)->isLastMicroop(); uop++) {
230  (*uop)->setDelayedCommit();
231  }
232  }
233 
234  Fault
236  {
237  panic("Execute method called when it shouldn't!");
238  return NoFault;
239  }
240 
241  std::string
242  generateDisassembly(Addr pc, const SymbolTable *symtab) const
243  {
244  std::stringstream ss;
245  printMnemonic(ss, "", false);
246  ccprintf(ss, "{");
247  for (int i = 0; i < numregs; ++i) {
248  printVecReg(ss, (dest + i) % 32, true);
249  if (i < numregs - 1)
250  ccprintf(ss, ", ");
251  }
252  ccprintf(ss, "}, ");
253  printVecPredReg(ss, gp);
254  ccprintf(ss, "/z, [");
255  printIntReg(ss, base);
256  if (imm != 0) {
257  ccprintf(ss, ", #%d, MUL VL", imm);
258  }
259  ccprintf(ss, "]");
260  return ss.str();
261  }
262 };
263 
264 template <typename Element,
265  template <typename> class MicroopStMemType,
266  template <typename> class MicroopIntrlvType>
268 {
269  protected:
273  int64_t imm;
274  uint8_t numregs;
275 
276  public:
277  SveStStructSI(const char* mnem, ExtMachInst machInst, OpClass __opClass,
278  IntRegIndex _dest, IntRegIndex _gp, IntRegIndex _base,
279  int64_t _imm, uint8_t _numregs)
280  : PredMacroOp(mnem, machInst, __opClass),
281  dest(_dest), gp(_gp), base(_base), imm(_imm), numregs(_numregs)
282  {
283  numMicroops = numregs * 2;
284 
286 
287  for (int i = 0; i < numregs; ++i) {
288  microOps[i] = new MicroopIntrlvType<Element>(
289  mnem, machInst, static_cast<IntRegIndex>(INTRLVREG0 + i),
290  _dest, _numregs, i, this);
291  }
292 
293  for (int i = 0; i < numregs; ++i) {
294  microOps[i + numregs] = new MicroopStMemType<Element>(
295  mnem, machInst, static_cast<IntRegIndex>(INTRLVREG0 + i),
296  _gp, _base, _imm, _numregs, i);
297  }
298 
301 
302  for (StaticInstPtr *uop = microOps; !(*uop)->isLastMicroop(); uop++) {
303  (*uop)->setDelayedCommit();
304  }
305  }
306 
307  Fault
309  {
310  panic("Execute method called when it shouldn't!");
311  return NoFault;
312  }
313 
314  std::string
315  generateDisassembly(Addr pc, const SymbolTable *symtab) const
316  {
317  std::stringstream ss;
318  printMnemonic(ss, "", false);
319  ccprintf(ss, "{");
320  for (int i = 0; i < numregs; ++i) {
321  printVecReg(ss, (dest + i) % 32, true);
322  if (i < numregs - 1)
323  ccprintf(ss, ", ");
324  }
325  ccprintf(ss, "}, ");
326  printVecPredReg(ss, gp);
327  ccprintf(ss, ", [");
328  printIntReg(ss, base);
329  if (imm != 0) {
330  ccprintf(ss, ", #%d, MUL VL", imm);
331  }
332  ccprintf(ss, "]");
333  return ss.str();
334  }
335 };
336 
337 template <typename RegElemType, typename MemElemType,
338  template <typename, typename> class MicroopType,
339  template <typename> class FirstFaultWritebackMicroopType>
341 {
342  protected:
346  uint64_t imm;
347 
348  public:
349  SveIndexedMemVI(const char *mnem, ExtMachInst machInst, OpClass __opClass,
350  IntRegIndex _dest, IntRegIndex _gp, IntRegIndex _base,
351  uint64_t _imm, bool firstFault)
352  : PredMacroOp(mnem, machInst, __opClass),
353  dest(_dest), gp(_gp), base(_base), imm(_imm)
354  {
355  bool isLoad = (__opClass == MemReadOp);
356  assert(!firstFault || isLoad);
357 
358  int num_elems = ((machInst.sveLen + 1) * 16) / sizeof(RegElemType);
359 
360  numMicroops = num_elems;
361  if (isLoad) {
362  if (firstFault) {
363  numMicroops += 2;
364  } else {
365  numMicroops++;
366  }
367  }
368 
370 
371  StaticInstPtr *uop = microOps;
372 
373  if (isLoad) {
374  // The first microop of a gather load copies the source vector
375  // register used for address calculation to an auxiliary register,
376  // with all subsequent microops reading from the latter. This is
377  // needed to properly handle cases where the source vector
378  // register is the same as the destination register
379  *uop = new ArmISAInst::SveGatherLoadCpySrcVecMicroop(
380  mnem, machInst, _base, this);
381  uop++;
382  }
383 
384  for (int i = 0; i < num_elems; i++, uop++) {
385  *uop = new MicroopType<RegElemType, MemElemType>(
386  mnem, machInst, __opClass, _dest, _gp,
387  isLoad ? (IntRegIndex) VECREG_UREG0 : _base, _imm, i,
388  num_elems, firstFault);
389  }
390 
391  if (firstFault) {
392  *uop = new FirstFaultWritebackMicroopType<RegElemType>(
393  mnem, machInst, __opClass, num_elems, this);
394  } else {
395  --uop;
396  }
397 
398  (*uop)->setLastMicroop();
400 
401  for (StaticInstPtr *uop = microOps; !(*uop)->isLastMicroop(); uop++) {
402  (*uop)->setDelayedCommit();
403  }
404  }
405 
406  Fault
408  {
409  panic("Execute method called when it shouldn't!");
410  return NoFault;
411  }
412 
413  std::string
414  generateDisassembly(Addr pc, const SymbolTable *symtab) const
415  {
416  // TODO: add suffix to transfer and base registers
417  std::stringstream ss;
418  printMnemonic(ss, "", false);
419  ccprintf(ss, "{");
420  printVecReg(ss, dest, true);
421  ccprintf(ss, "}, ");
422  printVecPredReg(ss, gp);
423  ccprintf(ss, "/z, [");
424  printVecReg(ss, base, true);
425  if (imm != 0) {
426  ccprintf(ss, ", #%d", imm * sizeof(MemElemType));
427  }
428  ccprintf(ss, "]");
429  return ss.str();
430  }
431 };
432 
433 template <typename RegElemType, typename MemElemType,
434  template <typename, typename> class MicroopType,
435  template <typename> class FirstFaultWritebackMicroopType>
437 {
438  protected:
443 
447 
448  public:
449  SveIndexedMemSV(const char *mnem, ExtMachInst machInst, OpClass __opClass,
450  IntRegIndex _dest, IntRegIndex _gp, IntRegIndex _base,
451  IntRegIndex _offset, bool _offsetIs32,
452  bool _offsetIsSigned, bool _offsetIsScaled,
453  bool firstFault)
454  : PredMacroOp(mnem, machInst, __opClass),
455  dest(_dest), gp(_gp), base(_base), offset(_offset),
456  offsetIs32(_offsetIs32), offsetIsSigned(_offsetIsSigned),
457  offsetIsScaled(_offsetIsScaled)
458  {
459  bool isLoad = (__opClass == MemReadOp);
460  assert(!firstFault || isLoad);
461 
462  int num_elems = ((machInst.sveLen + 1) * 16) / sizeof(RegElemType);
463 
464  numMicroops = num_elems;
465  if (isLoad) {
466  if (firstFault) {
467  numMicroops += 2;
468  } else {
469  numMicroops++;
470  }
471  }
472 
474 
475  StaticInstPtr *uop = microOps;
476 
477  if (isLoad) {
478  // The first microop of a gather load copies the source vector
479  // register used for address calculation to an auxiliary register,
480  // with all subsequent microops reading from the latter. This is
481  // needed to properly handle cases where the source vector
482  // register is the same as the destination register
483  *uop = new ArmISAInst::SveGatherLoadCpySrcVecMicroop(
484  mnem, machInst, _offset, this);
485  uop++;
486  }
487 
488  for (int i = 0; i < num_elems; i++, uop++) {
489  *uop = new MicroopType<RegElemType, MemElemType>(
490  mnem, machInst, __opClass, _dest, _gp, _base,
491  isLoad ? (IntRegIndex) VECREG_UREG0 : _offset, _offsetIs32,
492  _offsetIsSigned, _offsetIsScaled, i, num_elems, firstFault);
493  }
494 
495  if (firstFault) {
496  *uop = new FirstFaultWritebackMicroopType<RegElemType>(
497  mnem, machInst, __opClass, num_elems, this);
498  } else {
499  --uop;
500  }
501 
502  (*uop)->setLastMicroop();
504 
505  for (StaticInstPtr *uop = microOps; !(*uop)->isLastMicroop(); uop++) {
506  (*uop)->setDelayedCommit();
507  }
508  }
509 
510  Fault
512  {
513  panic("Execute method called when it shouldn't!");
514  return NoFault;
515  }
516 
517  std::string
518  generateDisassembly(Addr pc, const SymbolTable *symtab) const
519  {
520  // TODO: add suffix to transfer and base registers
521  std::stringstream ss;
522  printMnemonic(ss, "", false);
523  ccprintf(ss, "{");
524  printVecReg(ss, dest, true);
525  ccprintf(ss, "}, ");
526  printVecPredReg(ss, gp);
527  ccprintf(ss, "/z, [");
528  printIntReg(ss, base);
529  ccprintf(ss, ", ");
530  printVecReg(ss, offset, true);
531  ccprintf(ss, "]");
532  return ss.str();
533  }
534 };
535 
536 } // namespace ArmISA
537 
538 #endif // __ARCH_ARM_SVE_MACROMEM_HH__
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:167
void ccprintf(cp::Print &print)
Definition: cprintf.hh:131
const int VECREG_UREG0
Definition: registers.hh:128
void printMnemonic(std::ostream &os, const std::string &suffix="", bool withPred=true, bool withCond64=false, ConditionCode cond64=COND_UC) const
Definition: static_inst.cc:374
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const
Internal function to generate disassembly string.
decltype(nullptr) constexpr NoFault
Definition: types.hh:245
IntRegIndex
Definition: intregs.hh:53
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const
Internal function to generate disassembly string.
Fault execute(ExecContext *, Trace::InstRecord *) const
Bitfield< 7 > i
Fault execute(ExecContext *, Trace::InstRecord *) const
bool isLoad() const
Definition: static_inst.hh:159
SveLdStructSS(const char *mnem, ExtMachInst machInst, OpClass __opClass, IntRegIndex _dest, IntRegIndex _gp, IntRegIndex _base, IntRegIndex _offset, uint8_t _numregs)
Definition: sve_macromem.hh:61
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const
Internal function to generate disassembly string.
SveStStructSI(const char *mnem, ExtMachInst machInst, OpClass __opClass, IntRegIndex _dest, IntRegIndex _gp, IntRegIndex _base, int64_t _imm, uint8_t _numregs)
Definition: ccregs.hh:42
Fault execute(ExecContext *, Trace::InstRecord *) const
const int INTRLVREG0
Definition: registers.hh:124
SveStStructSS(const char *mnem, ExtMachInst machInst, OpClass __opClass, IntRegIndex _dest, IntRegIndex _gp, IntRegIndex _base, IntRegIndex _offset, uint8_t _numregs)
void printVecPredReg(std::ostream &os, RegIndex reg_idx) const
Definition: static_inst.cc:355
const ExtMachInst machInst
The binary machine instruction.
Definition: static_inst.hh:229
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const
Internal function to generate disassembly string.
The ExecContext is an abstract base class the provides the interface used by the ISA to manipulate th...
Definition: exec_context.hh:73
Bitfield< 4 > pc
void printVecReg(std::ostream &os, RegIndex reg_idx, bool isSveVecReg=false) const
Definition: static_inst.cc:348
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)...
Definition: static_inst.cc:296
uint32_t numMicroops
Definition: pred_inst.hh:341
Bitfield< 21 > ss
void setFirstMicroop()
Definition: static_inst.hh:205
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const
Internal function to generate disassembly string.
Definition: sve_macromem.hh:98
Fault execute(ExecContext *, Trace::InstRecord *) const
void setLastMicroop()
Definition: static_inst.hh:206
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
SveIndexedMemVI(const char *mnem, ExtMachInst machInst, OpClass __opClass, IntRegIndex _dest, IntRegIndex _gp, IntRegIndex _base, uint64_t _imm, bool firstFault)
static const OpClass MemReadOp
Definition: op_class.hh:101
SveLdStructSI(const char *mnem, ExtMachInst machInst, OpClass __opClass, IntRegIndex _dest, IntRegIndex _gp, IntRegIndex _base, int64_t _imm, uint8_t _numregs)
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const
Internal function to generate disassembly string.
Fault execute(ExecContext *, Trace::InstRecord *) const
Base class for predicated macro-operations.
Definition: pred_inst.hh:337
Fault execute(ExecContext *, Trace::InstRecord *) const
Definition: sve_macromem.hh:91
TheISA::ExtMachInst ExtMachInst
Binary extended machine instruction type.
Definition: static_inst.hh:87
StaticInstPtr * microOps
Definition: pred_inst.hh:342
std::shared_ptr< FaultBase > Fault
Definition: types.hh:240
SveIndexedMemSV(const char *mnem, ExtMachInst machInst, OpClass __opClass, IntRegIndex _dest, IntRegIndex _gp, IntRegIndex _base, IntRegIndex _offset, bool _offsetIs32, bool _offsetIsSigned, bool _offsetIsScaled, bool firstFault)
bool isLastMicroop() const
Definition: static_inst.hh:199

Generated on Fri Feb 28 2020 16:26:57 for gem5 by doxygen 1.8.13