gem5  v20.0.0.2
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
operand.hh
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017 Advanced Micro Devices, Inc.
3  * All rights reserved.
4  *
5  * For use for simulation and test purposes only
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright notice,
11  * this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright notice,
14  * this list of conditions and the following disclaimer in the documentation
15  * and/or other materials provided with the distribution.
16  *
17  * 3. Neither the name of the copyright holder nor the names of its
18  * contributors may be used to endorse or promote products derived from this
19  * software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  * Authors: Anthony Gutierrez
34  */
35 
36 #ifndef __ARCH_GCN3_OPERAND_HH__
37 #define __ARCH_GCN3_OPERAND_HH__
38 
39 #include <array>
40 
41 #include "arch/gcn3/registers.hh"
42 #include "arch/generic/vec_reg.hh"
43 #include "gpu-compute/scalar_register_file.hh"
45 #include "gpu-compute/wavefront.hh"
46 
53 namespace Gcn3ISA
54 {
60  template<typename T> struct OpTraits { typedef float FloatT; };
61  template<> struct OpTraits<ScalarRegF64> { typedef double FloatT; };
62  template<> struct OpTraits<ScalarRegU64> { typedef double FloatT; };
63 
64  class Operand
65  {
66  public:
67  Operand() = delete;
68 
69  Operand(GPUDynInstPtr gpuDynInst, int opIdx)
70  : _gpuDynInst(gpuDynInst), _opIdx(opIdx)
71  {
72  assert(_gpuDynInst);
73  assert(_opIdx >= 0);
74  }
75 
80  virtual void read() = 0;
81  virtual void write() = 0;
82 
83  protected:
94  int _opIdx;
95  };
96 
97  template<typename DataType, bool Const, size_t NumDwords>
99 
100  template<typename DataType, bool Const,
101  size_t NumDwords = sizeof(DataType) / sizeof(VecElemU32)>
102  class VecOperand final : public Operand
103  {
104  static_assert(NumDwords >= 1 && NumDwords <= MaxOperandDwords,
105  "Incorrect number of DWORDS for GCN3 operand.");
106 
107  public:
108  VecOperand() = delete;
109 
110  VecOperand(GPUDynInstPtr gpuDynInst, int opIdx)
111  : Operand(gpuDynInst, opIdx), scalar(false), absMod(false),
112  negMod(false), scRegData(gpuDynInst, _opIdx),
113  vrfData{{ nullptr }}
114  {
115  vecReg.zero();
116  }
117 
119  {
120  }
121 
130  void
132  {
133  if (isVectorReg(_opIdx)) {
134  _opIdx = opSelectorToRegIdx(_opIdx, _gpuDynInst->wavefront()
135  ->reservedScalarRegs);
136  read();
137  } else {
138  readScalar();
139  }
140  }
141 
146  void
147  read() override
148  {
149  assert(_gpuDynInst);
150  assert(_gpuDynInst->wavefront());
151  assert(_gpuDynInst->computeUnit());
152  Wavefront *wf = _gpuDynInst->wavefront();
153  ComputeUnit *cu = _gpuDynInst->computeUnit();
154 
155  for (auto i = 0; i < NumDwords; ++i) {
156  int vgprIdx = cu->registerManager.mapVgpr(wf, _opIdx + i);
157  vrfData[i] = &cu->vrf[wf->simdId]->readWriteable(vgprIdx);
158 
159  DPRINTF(GPUVRF, "Read v[%d]\n", vgprIdx);
160  cu->vrf[wf->simdId]->printReg(wf, vgprIdx);
161  }
162 
163  if (NumDwords == 1) {
164  assert(vrfData[0]);
165  auto vgpr = vecReg.template as<DataType>();
166  auto reg_file_vgpr = vrfData[0]->template as<VecElemU32>();
167  for (int lane = 0; lane < NumVecElemPerVecReg; ++lane) {
168  std::memcpy((void*)&vgpr[lane],
169  (void*)&reg_file_vgpr[lane], sizeof(DataType));
170  }
171  } else if (NumDwords == 2) {
172  assert(vrfData[0]);
173  assert(vrfData[1]);
174  auto vgpr = vecReg.template as<VecElemU64>();
175  auto reg_file_vgpr0 = vrfData[0]->template as<VecElemU32>();
176  auto reg_file_vgpr1 = vrfData[1]->template as<VecElemU32>();
177 
178  for (int lane = 0; lane < NumVecElemPerVecReg; ++lane) {
179  VecElemU64 tmp_val(0);
180  ((VecElemU32*)&tmp_val)[0] = reg_file_vgpr0[lane];
181  ((VecElemU32*)&tmp_val)[1] = reg_file_vgpr1[lane];
182  vgpr[lane] = tmp_val;
183  }
184  }
185  }
186 
198  void
199  write() override
200  {
201  assert(_gpuDynInst);
202  assert(_gpuDynInst->wavefront());
203  assert(_gpuDynInst->computeUnit());
204  Wavefront *wf = _gpuDynInst->wavefront();
205  ComputeUnit *cu = _gpuDynInst->computeUnit();
206  VectorMask &exec_mask = _gpuDynInst->isLoad()
207  ? _gpuDynInst->exec_mask : wf->execMask();
208 
209  if (NumDwords == 1) {
210  int vgprIdx = cu->registerManager.mapVgpr(wf, _opIdx);
211  vrfData[0] = &cu->vrf[wf->simdId]->readWriteable(vgprIdx);
212  assert(vrfData[0]);
213  auto reg_file_vgpr = vrfData[0]->template as<VecElemU32>();
214  auto vgpr = vecReg.template as<DataType>();
215 
216  for (int lane = 0; lane < NumVecElemPerVecReg; ++lane) {
217  if (exec_mask[lane] || _gpuDynInst->ignoreExec()) {
218  std::memcpy((void*)&reg_file_vgpr[lane],
219  (void*)&vgpr[lane], sizeof(DataType));
220  }
221  }
222 
223  DPRINTF(GPUVRF, "Write v[%d]\n", vgprIdx);
224  cu->vrf[wf->simdId]->printReg(wf, vgprIdx);
225  } else if (NumDwords == 2) {
226  int vgprIdx0 = cu->registerManager.mapVgpr(wf, _opIdx);
227  int vgprIdx1 = cu->registerManager.mapVgpr(wf, _opIdx + 1);
228  vrfData[0] = &cu->vrf[wf->simdId]->readWriteable(vgprIdx0);
229  vrfData[1] = &cu->vrf[wf->simdId]->readWriteable(vgprIdx1);
230  assert(vrfData[0]);
231  assert(vrfData[1]);
232  auto reg_file_vgpr0 = vrfData[0]->template as<VecElemU32>();
233  auto reg_file_vgpr1 = vrfData[1]->template as<VecElemU32>();
234  auto vgpr = vecReg.template as<VecElemU64>();
235 
236  for (int lane = 0; lane < NumVecElemPerVecReg; ++lane) {
237  if (exec_mask[lane] || _gpuDynInst->ignoreExec()) {
238  reg_file_vgpr0[lane] = ((VecElemU32*)&vgpr[lane])[0];
239  reg_file_vgpr1[lane] = ((VecElemU32*)&vgpr[lane])[1];
240  }
241  }
242 
243  DPRINTF(GPUVRF, "Write v[%d:%d]\n", vgprIdx0, vgprIdx1);
244  cu->vrf[wf->simdId]->printReg(wf, vgprIdx0);
245  cu->vrf[wf->simdId]->printReg(wf, vgprIdx1);
246  }
247  }
248 
249  void
251  {
252  negMod = true;
253  }
254 
255  void
257  {
258  absMod = true;
259  }
260 
266  template<bool Condition = (NumDwords == 1 || NumDwords == 2) && Const>
268  operator[](size_t idx) const
269  {
270  assert(idx < NumVecElemPerVecReg);
271 
272  if (scalar) {
273  DataType ret_val = scRegData.rawData();
274 
275  if (absMod) {
276  assert(std::is_floating_point<DataType>::value);
277  ret_val = std::fabs(ret_val);
278  }
279 
280  if (negMod) {
281  assert(std::is_floating_point<DataType>::value);
282  ret_val = -ret_val;
283  }
284 
285  return ret_val;
286  } else {
287  auto vgpr = vecReg.template as<DataType>();
288  DataType ret_val = vgpr[idx];
289 
290  if (absMod) {
291  assert(std::is_floating_point<DataType>::value);
292  ret_val = std::fabs(ret_val);
293  }
294 
295  if (negMod) {
296  assert(std::is_floating_point<DataType>::value);
297  ret_val = -ret_val;
298  }
299 
300  return ret_val;
301  }
302  }
303 
309  template<bool Condition = (NumDwords == 1 || NumDwords == 2) && !Const>
311  operator[](size_t idx)
312  {
313  assert(!scalar);
314  assert(idx < NumVecElemPerVecReg);
315 
316  return vecReg.template as<DataType>()[idx];
317  }
318 
319  private:
324  void
326  {
327  scalar = true;
328  scRegData.read();
329  }
330 
331  using VecRegCont = typename std::conditional<NumDwords == 2,
332  VecRegContainerU64, typename std::conditional<sizeof(DataType)
333  == sizeof(VecElemU16), VecRegContainerU16,
334  typename std::conditional<sizeof(DataType)
335  == sizeof(VecElemU8), VecRegContainerU8,
337 
341  bool scalar;
348  bool absMod;
349  bool negMod;
365  std::array<VecRegContainerU32*, NumDwords> vrfData;
366  };
367 
368  template<typename DataType, bool Const,
369  size_t NumDwords = sizeof(DataType) / sizeof(ScalarRegU32)>
370  class ScalarOperand final : public Operand
371  {
372  static_assert(NumDwords >= 1 && NumDwords <= MaxOperandDwords,
373  "Incorrect number of DWORDS for GCN3 operand.");
374  public:
375  ScalarOperand() = delete;
376 
377  ScalarOperand(GPUDynInstPtr gpuDynInst, int opIdx)
378  : Operand(gpuDynInst, opIdx)
379  {
380  std::memset(srfData.data(), 0, NumDwords * sizeof(ScalarRegU32));
381  }
382 
384  {
385  }
386 
394  template<bool Condition = NumDwords == 1 || NumDwords == 2>
396  rawData() const
397  {
398  assert(sizeof(DataType) <= sizeof(srfData));
399  DataType raw_data((DataType)0);
400  std::memcpy((void*)&raw_data, (void*)srfData.data(),
401  sizeof(DataType));
402 
403  return raw_data;
404  }
405 
406  void*
408  {
409  return (void*)srfData.data();
410  }
411 
412  void
413  read() override
414  {
415  Wavefront *wf = _gpuDynInst->wavefront();
416  ComputeUnit *cu = _gpuDynInst->computeUnit();
417 
418  if (!isScalarReg(_opIdx)) {
419  readSpecialVal();
420  } else {
421  for (auto i = 0; i < NumDwords; ++i) {
422  int sgprIdx = regIdx(i);
423  srfData[i] = cu->srf[wf->simdId]->read(sgprIdx);
424  DPRINTF(GPUSRF, "Read s[%d]\n", sgprIdx);
425  cu->srf[wf->simdId]->printReg(wf, sgprIdx);
426  }
427  }
428  }
429 
430  void
431  write() override
432  {
433  Wavefront *wf = _gpuDynInst->wavefront();
434  ComputeUnit *cu = _gpuDynInst->computeUnit();
435 
436  if (!isScalarReg(_opIdx)) {
437  if (_opIdx == REG_EXEC_LO) {
438  uint64_t new_exec_mask_val(0);
439  std::memcpy((void*)&new_exec_mask_val,
440  (void*)srfData.data(), sizeof(new_exec_mask_val));
441  VectorMask new_exec_mask(new_exec_mask_val);
442  wf->execMask() = new_exec_mask;
443  DPRINTF(GPUSRF, "Write EXEC\n");
444  DPRINTF(GPUSRF, "EXEC = %#x\n", new_exec_mask_val);
445  } else {
446  _gpuDynInst->writeMiscReg(_opIdx, srfData[0]);
447  }
448  } else {
449  for (auto i = 0; i < NumDwords; ++i) {
450  int sgprIdx = regIdx(i);
451  auto &sgpr = cu->srf[wf->simdId]->readWriteable(sgprIdx);
452  if (_gpuDynInst->isLoad()) {
453  assert(sizeof(DataType) <= sizeof(ScalarRegU64));
454  sgpr = reinterpret_cast<ScalarRegU32*>(
455  _gpuDynInst->scalar_data)[i];
456  } else {
457  sgpr = srfData[i];
458  }
459  DPRINTF(GPUSRF, "Write s[%d]\n", sgprIdx);
460  cu->srf[wf->simdId]->printReg(wf, sgprIdx);
461  }
462  }
463  }
464 
468  template<bool Condition = NumDwords == 1 || NumDwords == 2>
470  setBit(int bit, int bit_val)
471  {
472  DataType &sgpr = *((DataType*)srfData.data());
473  replaceBits(sgpr, bit, bit_val);
474  }
475 
476  template<bool Condition = (NumDwords == 1 || NumDwords == 2) && !Const>
478  operator=(DataType rhs)
479  {
480  std::memcpy((void*)srfData.data(), (void*)&rhs, sizeof(DataType));
481  return *this;
482  }
483 
484  private:
491  void
493  {
494  assert(NumDwords == 1 || NumDwords == 2);
495 
496  switch(_opIdx) {
497  case REG_EXEC_LO:
498  {
499  assert(NumDwords == 2);
500  ScalarRegU64 exec_mask = _gpuDynInst->wavefront()->
501  execMask().to_ullong();
502  std::memcpy((void*)srfData.data(), (void*)&exec_mask,
503  sizeof(srfData));
504  DPRINTF(GPUSRF, "Read EXEC\n");
505  DPRINTF(GPUSRF, "EXEC = %#x\n", exec_mask);
506  }
507  break;
508  case REG_SRC_SWDA:
509  case REG_SRC_DPP:
510  case REG_SRC_LITERAL:
511  assert(NumDwords == 1);
512  srfData[0] = _gpuDynInst->srcLiteral();
513  break;
514  case REG_POS_HALF:
515  {
516  typename OpTraits<DataType>::FloatT pos_half = 0.5;
517  std::memcpy((void*)srfData.data(), (void*)&pos_half,
518  sizeof(srfData));
519 
520  }
521  break;
522  case REG_NEG_HALF:
523  {
524  typename OpTraits<DataType>::FloatT neg_half = -0.5;
525  std::memcpy((void*)srfData.data(), (void*)&neg_half,
526  sizeof(srfData));
527  }
528  break;
529  case REG_POS_ONE:
530  {
531  typename OpTraits<DataType>::FloatT pos_one = 1.0;
532  std::memcpy(srfData.data(), &pos_one, sizeof(srfData));
533  }
534  break;
535  case REG_NEG_ONE:
536  {
537  typename OpTraits<DataType>::FloatT neg_one = -1.0;
538  std::memcpy(srfData.data(), &neg_one, sizeof(srfData));
539  }
540  break;
541  case REG_POS_TWO:
542  {
543  typename OpTraits<DataType>::FloatT pos_two = 2.0;
544  std::memcpy(srfData.data(), &pos_two, sizeof(srfData));
545  }
546  break;
547  case REG_NEG_TWO:
548  {
549  typename OpTraits<DataType>::FloatT neg_two = -2.0;
550  std::memcpy(srfData.data(), &neg_two, sizeof(srfData));
551  }
552  break;
553  case REG_POS_FOUR:
554  {
555  typename OpTraits<DataType>::FloatT pos_four = 4.0;
556  std::memcpy(srfData.data(), &pos_four, sizeof(srfData));
557  }
558  break;
559  case REG_NEG_FOUR:
560  {
561  typename OpTraits<DataType>::FloatT neg_four = -4.0;
562  std::memcpy((void*)srfData.data(), (void*)&neg_four ,
563  sizeof(srfData));
564  }
565  break;
566  case REG_PI:
567  {
568  assert(sizeof(DataType) == sizeof(ScalarRegF64)
569  || sizeof(DataType) == sizeof(ScalarRegF32));
570 
571  const ScalarRegU32 pi_u32(0x3e22f983UL);
572  const ScalarRegU64 pi_u64(0x3fc45f306dc9c882ULL);
573 
574  if (sizeof(DataType) == sizeof(ScalarRegF64)) {
575  std::memcpy((void*)srfData.data(),
576  (void*)&pi_u64, sizeof(srfData));
577  } else {
578  std::memcpy((void*)srfData.data(),
579  (void*)&pi_u32, sizeof(srfData));
580  }
581  }
582  break;
583  default:
584  {
585  assert(sizeof(DataType) <= sizeof(srfData));
586  DataType misc_val
587  = (DataType)_gpuDynInst->readMiscReg(_opIdx);
588  std::memcpy((void*)srfData.data(), (void*)&misc_val,
589  sizeof(DataType));
590  }
591  }
592  }
593 
599  int
600  regIdx(int dword) const
601  {
602  Wavefront *wf = _gpuDynInst->wavefront();
603  ComputeUnit *cu = _gpuDynInst->computeUnit();
604  int sgprIdx(-1);
605 
606  if (_opIdx == REG_VCC_LO) {
607  sgprIdx = cu->registerManager
608  .mapSgpr(wf, wf->reservedScalarRegs - 2 + dword);
609  } else if (_opIdx == REG_FLAT_SCRATCH_HI) {
610  sgprIdx = cu->registerManager
611  .mapSgpr(wf, wf->reservedScalarRegs - 3 + dword);
612  } else if (_opIdx == REG_FLAT_SCRATCH_LO) {
613  assert(NumDwords == 1);
614  sgprIdx = cu->registerManager
615  .mapSgpr(wf, wf->reservedScalarRegs - 4 + dword);
616  } else {
617  sgprIdx = cu->registerManager.mapSgpr(wf, _opIdx + dword);
618  }
619 
620  assert(sgprIdx > -1);
621 
622  return sgprIdx;
623  }
624 
633  std::array<ScalarRegU32, NumDwords> srfData;
634  };
635 
636  // typedefs for the various sizes/types of scalar operands
650  // non-writeable versions of scalar operands
664  // typedefs for the various sizes/types of vector operands
679  // non-writeable versions of vector operands
694 }
695 
696 #endif // __ARCH_GCN3_OPERAND_HH__
#define DPRINTF(x,...)
Definition: trace.hh:222
Operand(GPUDynInstPtr gpuDynInst, int opIdx)
Definition: operand.hh:69
double ScalarRegF64
Definition: registers.hh:159
uint16_t VecElemU16
Definition: registers.hh:164
bool isScalarReg(int opIdx)
Definition: registers.cc:190
Bitfield< 7 > i
std::bitset< std::numeric_limits< unsigned long long >::digits > VectorMask
Definition: misc.hh:43
VecRegCont vecReg
this holds all the operand data in a single vector register object (i.e., if an operand is 64b...
Definition: operand.hh:355
int simdId
Definition: wavefront.hh:163
float ScalarRegF32
Definition: registers.hh:156
std::array< ScalarRegU32, NumDwords > srfData
in GCN3 each register is represented as a 32b unsigned value, however operands may require up to 16 r...
Definition: operand.hh:633
ScalarOperand< DataType, Const, NumDwords > scRegData
for src operands that read scalars (i.e., scalar regs or a scalar constant).
Definition: operand.hh:360
std::enable_if< Condition, void >::type setBit(int bit, int bit_val)
bit access to scalar data.
Definition: operand.hh:470
uint64_t ScalarRegU64
Definition: registers.hh:157
uint32_t VecElemU32
Definition: registers.hh:166
typename std::conditional< NumDwords==2, VecRegContainerU64, typename std::conditional< sizeof(DataType)==sizeof(VecElemU16), VecRegContainerU16, typename std::conditional< sizeof(DataType)==sizeof(VecElemU8), VecRegContainerU8, VecRegContainerU32 >::type >::type >::type VecRegCont
Definition: operand.hh:336
ScalarOperand(GPUDynInstPtr gpuDynInst, int opIdx)
Definition: operand.hh:377
void write() override
Definition: operand.hh:431
bool isVectorReg(int opIdx)
Definition: registers.cc:203
std::shared_ptr< GPUDynInst > GPUDynInstPtr
Definition: misc.hh:46
std::array< VecRegContainerU32 *, NumDwords > vrfData
pointers to the underlyding registers (i.e., the actual registers in the register file)...
Definition: operand.hh:365
uint8_t type
Definition: inet.hh:328
void read() override
read from and write to the underlying register(s) that this operand is referring to.
Definition: operand.hh:413
VecRegU64::Container VecRegContainerU64
Definition: registers.hh:199
classes that represnt vector/scalar operands in GCN3 ISA.
Definition: decoder.cc:44
void readSpecialVal()
we have determined that we are not reading our scalar operand data from the register file...
Definition: operand.hh:492
void replaceBits(T &val, int first, int last, B bit_val)
A convenience function to replace bits first to last of val with bit_val in place.
Definition: bitfield.hh:156
int opSelectorToRegIdx(int idx, int numScalarRegs)
Definition: registers.cc:123
void read() override
read from the vrf.
Definition: operand.hh:147
VecRegU16::Container VecRegContainerU16
Definition: registers.hh:197
void write() override
write to the vrf.
Definition: operand.hh:199
bool scalar
whether this operand a scalar or not.
Definition: operand.hh:341
void readSrc()
certain vector operands can read from the vrf/srf or constants.
Definition: operand.hh:131
GPUDynInstPtr _gpuDynInst
instruction object that owns this operand
Definition: operand.hh:87
uint32_t ScalarRegU32
Definition: registers.hh:154
std::enable_if< Condition, ScalarOperand & >::type operator=(DataType rhs)
Definition: operand.hh:478
std::vector< VectorRegisterFile * > vrf
Vector Registers layout specification.
VectorMask execMask() const
Definition: wavefront.cc:837
convenience traits so we can automatically infer the correct FP type without looking at the number of...
Definition: operand.hh:60
std::enable_if< Condition, const DataType >::type operator[](size_t idx) const
getter [] operator.
Definition: operand.hh:268
std::enable_if< Condition, DataType >::type rawData() const
we store scalar data in a std::array, however if we need the full operand data we use this method to ...
Definition: operand.hh:396
int _opIdx
op selector value for this operand.
Definition: operand.hh:94
uint8_t VecElemU8
Definition: registers.hh:162
VecRegU8::Container VecRegContainerU8
Definition: registers.hh:196
VecRegU32::Container VecRegContainerU32
Definition: registers.hh:198
uint64_t VecElemU64
Definition: registers.hh:169
VecOperand(GPUDynInstPtr gpuDynInst, int opIdx)
Definition: operand.hh:110
bool absMod
absolute value and negative modifiers.
Definition: operand.hh:348
const int NumVecElemPerVecReg(64)
int regIdx(int dword) const
for scalars we need to do some extra work to figure out how to map the op selector to the sgpr idx be...
Definition: operand.hh:600
constexpr size_t MaxOperandDwords(16)
std::enable_if< Condition, DataType & >::type operator[](size_t idx)
setter [] operator.
Definition: operand.hh:311
void readScalar()
if we determine that this operand is a scalar (reg or constant) then we read the scalar data into the...
Definition: operand.hh:325

Generated on Mon Jun 8 2020 15:45:06 for gem5 by doxygen 1.8.13