summaryrefslogtreecommitdiff
path: root/src/cuda-sim/instructions.cc
diff options
context:
space:
mode:
authorgpgpu-sim <[email protected]>2016-09-06 06:43:14 -0700
committerGitHub <[email protected]>2016-09-06 06:43:14 -0700
commit3e9c0b4308ad32f381dc90f7763df46fa9ba721c (patch)
treed77c8320f986a1c64d2018a7e50d09f8e4dd6a40 /src/cuda-sim/instructions.cc
parentbab2a234abfadc50cb14dadb01c10595ce6ad1ef (diff)
parent0afe825c212560c3b473366d005a50c2568cad1a (diff)
Merge pull request #30 from sspenst/dev
shfl instruction implemented
Diffstat (limited to 'src/cuda-sim/instructions.cc')
-rw-r--r--src/cuda-sim/instructions.cc77
1 files changed, 77 insertions, 0 deletions
diff --git a/src/cuda-sim/instructions.cc b/src/cuda-sim/instructions.cc
index b7a4a99..011c285 100644
--- a/src/cuda-sim/instructions.cc
+++ b/src/cuda-sim/instructions.cc
@@ -50,8 +50,10 @@ unsigned ptx_instruction::g_num_ptx_inst_uid=0;
const char *g_opcode_string[NUM_OPCODES] = {
#define OP_DEF(OP,FUNC,STR,DST,CLASSIFICATION) STR,
+#define OP_W_DEF(OP,FUNC,STR,DST,CLASSIFICATION) STR,
#include "opcodes.def"
#undef OP_DEF
+#undef OP_W_DEF
};
void inst_not_implemented( const ptx_instruction * pI ) ;
@@ -3537,6 +3539,81 @@ void set_impl( const ptx_instruction *pI, ptx_thread_info *thread )
}
+void shfl_impl( const ptx_instruction *pI, core_t *core, warp_inst_t inst )
+{
+ unsigned i_type = pI->get_type();
+ int tid = inst.warp_id() * core->get_warp_size();
+ ptx_thread_info *thread = core->get_thread_info()[tid];
+ ptx_warp_info *warp_info = thread->m_warp_info;
+ int lane = warp_info->get_done_threads();
+ thread = core->get_thread_info()[tid + lane];
+
+ const operand_info &dst = pI->dst();
+ const operand_info &src1 = pI->src1();
+ const operand_info &src2 = pI->src2();
+ const operand_info &src3 = pI->src3();
+ int bval = (thread->get_operand_value(src2, dst, i_type, thread, 1)).u32;
+ int cval = (thread->get_operand_value(src3, dst, i_type, thread, 1)).u32;
+ int mask = cval >> 8;
+ bval &= 0x1F;
+ cval &= 0x1F;
+
+ int maxLane = (lane & mask) | (cval & ~mask);
+ int minLane = lane & mask;
+
+ int src_idx;
+ unsigned p;
+ switch(pI->shfl_op()) {
+ case UP_OPTION:
+ src_idx = lane - bval;
+ p = (src_idx >= maxLane);
+ break;
+ case DOWN_OPTION:
+ src_idx = lane + bval;
+ p = (src_idx <= maxLane);
+ break;
+ case BFLY_OPTION:
+ src_idx = lane ^ bval;
+ p = (src_idx <= maxLane);
+ break;
+ case IDX_OPTION:
+ src_idx = minLane | (bval & ~mask);
+ p = (src_idx <= maxLane);
+ break;
+ default:
+ printf("GPGPU-Sim PTX: ERROR: Invalid shfl option\n");
+ assert(0);
+ break;
+ }
+ // copy from own lane
+ if (!p) src_idx = lane;
+
+ // copy input from lane src_idx
+ ptx_reg_t data;
+ if (inst.active(src_idx)) {
+ ptx_thread_info *source = core->get_thread_info()[tid + src_idx];
+ data = source->get_operand_value(src1, dst, i_type, source, 1);
+ } else {
+ printf("GPGPU-Sim PTX: WARNING: shfl input value unpredictable for inactive threads in a warp\n");
+ data.u32 = 0;
+ }
+ thread->set_operand_value(dst, data, i_type, thread, pI);
+
+ /*
+ TODO: deal with predicates appropriately using the following pseudocode:
+ if (!isGuardPredicateTrue(src_idx)) {
+ printf("GPGPU-Sim PTX: WARNING: shfl input value unpredictable for predicated-off threads in a warp\n");
+ }
+ if (dest predicate selected) data.pred = p;
+ */
+
+ // keep track of the number of threads that have executed in the warp
+ warp_info->inc_done_threads();
+ if (warp_info->get_done_threads() == inst.active_count()) {
+ warp_info->reset_done_threads();
+ }
+}
+
void shl_impl( const ptx_instruction *pI, ptx_thread_info *thread )
{
ptx_reg_t a, b, d;