32#ifndef __ARCH_VEGA_OPERAND_HH__
33#define __ARCH_VEGA_OPERAND_HH__
39#include "debug/GPUTrace.hh"
98 template<
typename DataType,
bool Const,
size_t NumDwords>
101 template<
typename DataType,
bool Const,
102 size_t NumDwords =
sizeof(DataType) /
sizeof(
VecElemU32)>
106 "Incorrect number of DWORDS for VEGA operand.");
136 ->reservedScalarRegs);
156 for (
auto i = 0;
i < NumDwords; ++
i) {
160 DPRINTF(GPUVRF,
"Read v[%d]\n", vgprIdx);
161 DPRINTF(GPUTrace,
"wave[%d] Read v[%d] by instruction %s\n",
164 cu->
vrf[wf->
simdId]->printReg(wf, vgprIdx);
167 if (NumDwords == 1) {
172 std::memcpy((
void*)&vgpr[lane],
173 (
void*)®_file_vgpr[lane],
sizeof(DataType));
175 }
else if (NumDwords == 2) {
184 ((
VecElemU32*)&tmp_val)[0] = reg_file_vgpr0[lane];
185 ((
VecElemU32*)&tmp_val)[1] = reg_file_vgpr1[lane];
186 vgpr[lane] = tmp_val;
213 if (NumDwords == 1) {
221 if (exec_mask[lane] ||
_gpuDynInst->ignoreExec()) {
222 std::memcpy((
void*)®_file_vgpr[lane],
223 (
void*)&vgpr[lane],
sizeof(DataType));
227 DPRINTF(GPUVRF,
"Write v[%d]\n", vgprIdx);
228 DPRINTF(GPUTrace,
"wave[%d] Write v[%d] by instruction %s\n",
231 cu->
vrf[wf->
simdId]->printReg(wf, vgprIdx);
232 }
else if (NumDwords == 2) {
244 if (exec_mask[lane] ||
_gpuDynInst->ignoreExec()) {
245 reg_file_vgpr0[lane] = ((
VecElemU32*)&vgpr[lane])[0];
246 reg_file_vgpr1[lane] = ((
VecElemU32*)&vgpr[lane])[1];
250 DPRINTF(GPUVRF,
"Write v[%d:%d]\n", vgprIdx0, vgprIdx1);
251 DPRINTF(GPUTrace,
"wave[%d] Write v[%d:%d] by instruction "
252 "%s\n", wf->
wfDynId, vgprIdx0, vgprIdx1,
254 cu->
vrf[wf->
simdId]->printReg(wf, vgprIdx0);
255 cu->
vrf[wf->
simdId]->printReg(wf, vgprIdx1);
276 template<
bool Condition = (NumDwords == 1 || NumDwords == 2) && Const>
277 typename std::enable_if<Condition, const DataType>::type
286 assert(std::is_floating_point_v<DataType>);
287 ret_val = std::fabs(ret_val);
291 assert(std::is_floating_point_v<DataType>);
298 DataType ret_val = vgpr[idx];
301 assert(std::is_floating_point_v<DataType>);
302 ret_val = std::fabs(ret_val);
306 assert(std::is_floating_point_v<DataType>);
319 template<
bool Condition = (NumDwords == 1 || NumDwords == 2) && !Const>
320 typename std::enable_if<Condition, DataType&>::type
371 std::array<VecRegContainerU32*, NumDwords>
vrfData;
374 template<
typename DataType,
bool Const,
375 size_t NumDwords =
sizeof(DataType) /
sizeof(
ScalarRegU32)>
379 "Incorrect number of DWORDS for VEGA operand.");
386 std::memset(srfData.data(), 0, NumDwords *
sizeof(
ScalarRegU32));
400 template<
bool Condition = NumDwords == 1 || NumDwords == 2>
401 typename std::enable_if<Condition, DataType>::type
404 assert(
sizeof(DataType) <=
sizeof(srfData));
405 DataType raw_data((DataType)0);
406 std::memcpy((
void*)&raw_data, (
void*)srfData.data(),
415 return (
void*)srfData.data();
427 for (
auto i = 0;
i < NumDwords; ++
i) {
429 srfData[
i] = cu->
srf[wf->
simdId]->read(sgprIdx);
430 DPRINTF(GPUSRF,
"Read s[%d]\n", sgprIdx);
431 DPRINTF(GPUTrace,
"wave[%d] Read s[%d] by instruction "
434 cu->
srf[wf->
simdId]->printReg(wf, sgprIdx);
449 if (NumDwords == 1) {
450 std::memcpy((
void*)&new_exec_mask_val,
452 }
else if (NumDwords == 2) {
453 std::memcpy((
void*)&new_exec_mask_val,
456 panic(
"Trying to write more than 2 DWORDS to EXEC\n");
460 DPRINTF(GPUSRF,
"Write EXEC\n");
461 DPRINTF(GPUSRF,
"EXEC = %#x\n", new_exec_mask_val);
467 assert(NumDwords == 1);
471 std::memcpy((
void*)&new_exec_mask_hi_val,
472 (
void*)srfData.data(),
sizeof(new_exec_mask_hi_val));
474 new_exec_mask_hi_val);
477 DPRINTF(GPUSRF,
"Write EXEC\n");
478 DPRINTF(GPUSRF,
"EXEC = %#x\n", new_exec_mask_val);
483 for (
auto i = 0;
i < NumDwords; ++
i) {
485 auto &sgpr = cu->
srf[wf->
simdId]->readWriteable(sgprIdx);
493 DPRINTF(GPUSRF,
"Write s[%d]\n", sgprIdx);
494 DPRINTF(GPUTrace,
"wave[%d] Write s[%d] by instruction "
497 cu->
srf[wf->
simdId]->printReg(wf, sgprIdx);
505 template<
bool Condition = NumDwords == 1 || NumDwords == 2>
506 typename std::enable_if<Condition, void>::type
509 GEM5_ALIGNED(8) DataType &sgpr = *((DataType*)srfData.data());
513 template<
bool Condition = (NumDwords == 1 || NumDwords == 2) && !Const>
514 typename std::enable_if<Condition, ScalarOperand&>::type
517 std::memcpy((
void*)srfData.data(), (
void*)&rhs,
sizeof(DataType));
531 assert(NumDwords == 1 || NumDwords == 2);
535 assert(
sizeof(DataType) <=
sizeof(srfData));
536 DataType misc_val(0);
539 ->readConstVal<DataType>(
_opIdx);
540 std::memcpy((
void*)srfData.data(), (
void*)&misc_val,
547 assert(
sizeof(DataType) <=
sizeof(srfData));
548 DataType misc_val(0);
550 std::memcpy((
void*)srfData.data(), (
void*)&misc_val,
559 if constexpr (NumDwords == 2) {
561 execMask().to_ullong();
562 std::memcpy((
void*)srfData.data(), (
void*)&exec_mask,
564 DPRINTF(GPUSRF,
"Read EXEC\n");
565 DPRINTF(GPUSRF,
"EXEC = %#x\n", exec_mask);
568 execMask().to_ullong();
571 std::memcpy((
void*)srfData.data(),
572 (
void*)&exec_mask_lo,
sizeof(exec_mask_lo));
573 DPRINTF(GPUSRF,
"Read EXEC_LO\n");
574 DPRINTF(GPUSRF,
"EXEC_LO = %#x\n", exec_mask_lo);
584 assert(NumDwords == 1);
586 ->execMask().to_ullong();
589 std::memcpy((
void*)srfData.data(), (
void*)&exec_mask_hi,
590 sizeof(exec_mask_hi));
591 DPRINTF(GPUSRF,
"Read EXEC_HI\n");
592 DPRINTF(GPUSRF,
"EXEC_HI = %#x\n", exec_mask_hi);
606 if constexpr (NumDwords == 2) {
607 if constexpr (std::is_integral_v<DataType>) {
608 if constexpr (std::is_signed_v<DataType>) {
609 if (
bits(srfData[0], 31, 31) == 1) {
610 srfData[1] = 0xffffffff;
625 assert(NumDwords == 2);
626 if constexpr (NumDwords == 2) {
629 std::memcpy((
void*)srfData.data(), (
void*)&shared_base,
631 DPRINTF(GPUSRF,
"Read SHARED_BASE = %#x\n",
638 assert(NumDwords == 2);
639 if constexpr (NumDwords == 2) {
642 std::memcpy((
void*)srfData.data(),
643 (
void*)&shared_limit,
sizeof(srfData));
644 DPRINTF(GPUSRF,
"Read SHARED_LIMIT = %#x\n",
651 assert(NumDwords == 2);
652 if constexpr (NumDwords == 2) {
655 std::memcpy((
void*)srfData.data(), (
void*)&priv_base,
657 DPRINTF(GPUSRF,
"Read PRIVATE_BASE = %#x\n",
664 assert(NumDwords == 2);
665 if constexpr (NumDwords == 2) {
669 std::memcpy((
void*)srfData.data(), (
void*)&priv_limit,
671 DPRINTF(GPUSRF,
"Read PRIVATE_LIMIT = %#x\n",
679 std::memcpy((
void*)srfData.data(), (
void*)&pos_half,
687 std::memcpy((
void*)srfData.data(), (
void*)&neg_half,
694 std::memcpy(srfData.data(), &pos_one,
sizeof(pos_one));
700 std::memcpy(srfData.data(), &neg_one,
sizeof(neg_one));
706 std::memcpy(srfData.data(), &pos_two,
sizeof(pos_two));
712 std::memcpy(srfData.data(), &neg_two,
sizeof(neg_two));
718 std::memcpy(srfData.data(), &pos_four,
sizeof(pos_four));
724 std::memcpy((
void*)srfData.data(), (
void*)&neg_four ,
737 std::memcpy((
void*)srfData.data(),
738 (
void*)&pi_u64,
sizeof(pi_u64));
740 std::memcpy((
void*)srfData.data(),
741 (
void*)&pi_u32,
sizeof(pi_u32));
746 panic(
"Invalid special register index: %d\n",
_opIdx);
773 assert(NumDwords == 1);
780 assert(sgprIdx > -1);
858template<
int BITS,
int ELEM_SIZE>
867 static_assert(BITS % 32 == 0);
868 static_assert(BITS % ELEM_SIZE == 0);
869 static_assert(ELEM_SIZE <= 32);
894 assert(elem < (BITS / ELEM_SIZE));
898 ubit = elem * ELEM_SIZE + (ELEM_SIZE - 1);
899 lbit = elem * ELEM_SIZE;
907 assert(udw == ldw || udw == ldw + 1);
911 int dw_lbit = lbit % 32;
913 uint32_t
elem_mask = (1UL << ELEM_SIZE) - 1;
924 int qw_lbit = lbit % 32;
926 uint64_t
elem_mask = (1ULL << ELEM_SIZE) - 1;
927 uint32_t rv = uint32_t((qword >> qw_lbit) &
elem_mask);
935 assert(elem < (BITS / ELEM_SIZE));
939 ubit = elem * ELEM_SIZE + (ELEM_SIZE - 1);
940 lbit = elem * ELEM_SIZE;
948 assert(udw == ldw || udw == ldw + 1);
952 int dw_lbit = lbit % 32;
955 uint32_t
elem_mask = (1UL << ELEM_SIZE) - 1;
973 int qw_lbit = lbit % 32;
976 uint64_t
elem_mask = (1ULL << ELEM_SIZE) - 1;
984 uint64_t value64 = value;
988 dwords[udw] = uint32_t(qword >> 32);
std::vector< ScalarRegisterFile * > srf
RegisterManager * registerManager
std::vector< VectorRegisterFile * > vrf
int mapVgpr(Wavefront *w, int vgprIndex)
int mapSgpr(Wavefront *w, int sgprIndex)
const ApertureRegister & scratchApe() const
const ApertureRegister & ldsApe() const
Vector Register Abstraction This generic class is the model in a particularization of MVC,...
Operand(GPUDynInstPtr gpuDynInst, int opIdx)
GPUDynInstPtr _gpuDynInst
instruction object that owns this operand
int _opIdx
op selector value for this operand.
virtual void read()=0
read from and write to the underlying register(s) that this operand is referring to.
uint32_t dwords[NumDwords]
uint32_t getElem(int elem)
void setDword(int dw, uint32_t value)
static constexpr int NumDwords
void setElem(int elem, uint32_t value)
uint32_t getDword(int dw)
int regIdx(int dword) const
void read() override
read from and write to the underlying register(s) that this operand is referring to.
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 ...
ScalarOperand(GPUDynInstPtr gpuDynInst, int opIdx)
std::enable_if< Condition, ScalarOperand & >::type operator=(DataType rhs)
std::enable_if< Condition, void >::type setBit(int bit, int bit_val)
bit access to scalar data.
void readSrc()
certain vector operands can read from the vrf/srf or constants.
std::array< VecRegContainerU32 *, NumDwords > vrfData
std::enable_if< Condition, DataType & >::type operator[](size_t idx)
setter [] operator.
void write() override
write to the vrf.
VecRegContainer< sizeof(DataType) *NumVecElemPerVecReg > VecRegCont
std::enable_if< Condition, constDataType >::type operator[](size_t idx) const
getter [] operator.
ScalarOperand< VecElemU8, Const, NumDwords > scRegData
VecOperand(GPUDynInstPtr gpuDynInst, int opIdx)
constexpr T bits(T val, unsigned first, unsigned last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it.
constexpr void replaceBits(T &val, unsigned first, unsigned last, B bit_val)
A convenience function to replace bits first to last of val with bit_val in place.
#define panic(...)
This implements a cprintf based panic() function.
int elem_mask(const T *vs, const int index)
classes that represnt vector/scalar operands in VEGA ISA.
ScalarOperand< ScalarRegU32, false, 4 > ScalarOperandU128
bool isVectorReg(int opIdx)
ScalarOperand< ScalarRegU64, false > ScalarOperandU64
ScalarOperand< ScalarRegI8, true, 1 > ConstScalarOperandI8
ScalarOperand< ScalarRegU8, false, 1 > ScalarOperandU8
ScalarOperand< ScalarRegU32, false, 8 > ScalarOperandU256
VecOperand< VecElemF32, true > ConstVecOperandF32
VecOperand< VecElemU32, true, 8 > ConstVecOperandU256
ScalarOperand< ScalarRegI32, false > ScalarOperandI32
VecOperand< VecElemU32, false, 4 > VecOperandU128
VecOperand< VecElemU32, false > VecOperandU32
ScalarOperand< ScalarRegU32, true > ConstScalarOperandU32
VecOperand< VecElemF64, true > ConstVecOperandF64
int opSelectorToRegIdx(int idx, int numScalarRegs)
ScalarOperand< ScalarRegI8, false, 1 > ScalarOperandI8
VecOperand< VecElemI16, false, 1 > VecOperandI16
VecOperand< VecElemU8, true, 1 > ConstVecOperandU8
ScalarOperand< ScalarRegU32, true, 8 > ConstScalarOperandU256
VecOperand< VecElemU32, false, 8 > VecOperandU256
VecOperand< VecElemU32, true, 16 > ConstVecOperandU512
VecOperand< VecElemU32, true, 4 > ConstVecOperandU128
VecOperand< VecElemI32, true > ConstVecOperandI32
VecOperand< VecElemU32, true > ConstVecOperandU32
ScalarOperand< ScalarRegF64, false > ScalarOperandF64
VecOperand< VecElemI8, false, 1 > VecOperandI8
VecOperand< VecElemI8, true, 1 > ConstVecOperandI8
ScalarOperand< ScalarRegU32, true, 4 > ConstScalarOperandU128
VecOperand< VecElemI64, true > ConstVecOperandI64
ScalarOperand< ScalarRegI64, true > ConstScalarOperandI64
bool isConstVal(int opIdx)
VecOperand< VecElemU32, false, 3 > VecOperandU96
ScalarOperand< ScalarRegI16, true, 1 > ConstScalarOperandI16
VecOperand< VecElemU16, false, 1 > VecOperandU16
ScalarOperand< ScalarRegU64, true > ConstScalarOperandU64
VecOperand< VecElemU16, true, 1 > ConstVecOperandU16
ScalarOperand< ScalarRegF32, true > ConstScalarOperandF32
ScalarOperand< ScalarRegI64, false > ScalarOperandI64
ScalarOperand< ScalarRegU16, false, 1 > ScalarOperandU16
ScalarOperand< ScalarRegU32, false > ScalarOperandU32
ScalarOperand< ScalarRegU32, true, 16 > ConstScalarOperandU512
VecOperand< VecElemI64, false > VecOperandI64
const int NumVecElemPerVecReg(64)
ScalarOperand< ScalarRegF32, false > ScalarOperandF32
ScalarOperand< ScalarRegU32, false, 16 > ScalarOperandU512
VecOperand< VecElemU32, false, 16 > VecOperandU512
bool isScalarReg(int opIdx)
VecOperand< VecElemU64, false > VecOperandU64
VecOperand< VecElemI32, false > VecOperandI32
VecOperand< VecElemU32, true, 3 > ConstVecOperandU96
VecOperand< VecElemI16, true, 1 > ConstVecOperandI16
constexpr size_t MaxOperandDwords(16)
ScalarOperand< ScalarRegF64, true > ConstScalarOperandF64
ScalarOperand< ScalarRegU16, true, 1 > ConstScalarOperandU16
VecOperand< VecElemU64, true > ConstVecOperandU64
ScalarOperand< ScalarRegU8, true, 1 > ConstScalarOperandU8
VecOperand< VecElemF64, false > VecOperandF64
ScalarOperand< ScalarRegI32, true > ConstScalarOperandI32
ScalarOperand< ScalarRegI16, false, 1 > ScalarOperandI16
VecOperand< VecElemF32, false > VecOperandF32
VecOperand< VecElemU8, false, 1 > VecOperandU8
Copyright (c) 2024 Arm Limited All rights reserved.
typedef GEM5_ALIGNED(8) uint64_t uint64_ta
std::shared_ptr< GPUDynInst > GPUDynInstPtr
std::bitset< std::numeric_limits< unsigned long long >::digits > VectorMask
Overload hash function for BasicBlockRange type.
convenience traits so we can automatically infer the correct FP type without looking at the number of...
Vector Registers layout specification.