summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTim Rogers <[email protected]>2020-07-12 23:07:43 -0400
committerTim Rogers <[email protected]>2020-07-12 23:07:43 -0400
commit4192a5df8c400d9fc19d15a9eaca74191e45d08e (patch)
treead6787a77c25f47a47faa7f195da9a011ff18bdc /src
parent4d64f31587569d4e8800aa81ececb9e809817d78 (diff)
parent78a52b027e7ca30860fdf8366c08c0590f857810 (diff)
Merge remote-tracking branch 'gpgpu/dev' into dev-4.x
Diffstat (limited to 'src')
-rw-r--r--src/abstract_hardware_model.h1
-rw-r--r--src/cuda-sim/cuda-sim.cc2
-rw-r--r--src/cuda-sim/instructions.cc138
-rw-r--r--src/cuda-sim/opcodes.def1
-rw-r--r--src/cuda-sim/ptx.l1
-rw-r--r--src/cuda-sim/ptx_ir.cc3
-rw-r--r--src/cuda-sim/ptx_ir.h3
-rw-r--r--src/cuda-sim/ptx_parser.cc5
8 files changed, 144 insertions, 10 deletions
diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h
index 45e7843..49f3e9f 100644
--- a/src/abstract_hardware_model.h
+++ b/src/abstract_hardware_model.h
@@ -1150,6 +1150,7 @@ class warp_inst_t : public inst_t {
void print(FILE *fout) const;
unsigned get_uid() const { return m_uid; }
unsigned get_schd_id() const { return m_scheduler_id; }
+ active_mask_t get_warp_active_mask() const { return m_warp_active_mask; }
protected:
unsigned m_uid;
diff --git a/src/cuda-sim/cuda-sim.cc b/src/cuda-sim/cuda-sim.cc
index 75dd3c8..71f0703 100644
--- a/src/cuda-sim/cuda-sim.cc
+++ b/src/cuda-sim/cuda-sim.cc
@@ -1741,7 +1741,7 @@ void ptx_thread_info::ptx_exec_inst(warp_inst_t &inst, unsigned lane_id) {
} else {
const ptx_instruction *pI_saved = pI;
ptx_instruction *pJ = NULL;
- if (pI->get_opcode() == VOTE_OP) {
+ if (pI->get_opcode() == VOTE_OP || pI->get_opcode() == ACTIVEMASK_OP) {
pJ = new ptx_instruction(*pI);
*((warp_inst_t *)pJ) = inst; // copy active mask information
pI = pJ;
diff --git a/src/cuda-sim/instructions.cc b/src/cuda-sim/instructions.cc
index bf9a040..8936fa8 100644
--- a/src/cuda-sim/instructions.cc
+++ b/src/cuda-sim/instructions.cc
@@ -166,6 +166,8 @@ void inst_not_implemented(const ptx_instruction *pI);
ptx_reg_t srcOperandModifiers(ptx_reg_t opData, operand_info opInfo,
operand_info dstInfo, unsigned type,
ptx_thread_info *thread);
+
+void video_mem_instruction(const ptx_instruction *pI, ptx_thread_info *thread, int op_code);
void sign_extend(ptx_reg_t &data, unsigned src_size, const operand_info &dst);
@@ -1709,8 +1711,40 @@ void bfi_impl(const ptx_instruction *pI, ptx_thread_info *thread) {
}
thread->set_operand_value(dst, data, i_type, thread, pI);
}
-void bfind_impl(const ptx_instruction *pI, ptx_thread_info *thread) {
- inst_not_implemented(pI);
+void bfind_impl(const ptx_instruction *pI, ptx_thread_info *thread)
+{
+ const operand_info &dst = pI->dst();
+ const operand_info &src1 = pI->src1();
+ const unsigned i_type = pI->get_type();
+
+ const ptx_reg_t src1_data = thread->get_operand_value(src1, dst, i_type, thread, 1);
+ const int msb = ( i_type == U32_TYPE || i_type == S32_TYPE) ? 31 : 63;
+
+ unsigned long a = 0;
+ switch (i_type)
+ {
+ case S32_TYPE: a = src1_data.s32; break;
+ case U32_TYPE: a = src1_data.u32; break;
+ case S64_TYPE: a = src1_data.s64; break;
+ case U64_TYPE: a = src1_data.u64; break;
+ default: assert(false); abort();
+ }
+
+ // negate negative signed inputs
+ if ( ( i_type == S32_TYPE || i_type == S64_TYPE ) && ( a & ( 1 << msb ) ) ) {
+ a = ~a;
+ }
+ uint32_t d_data = 0xffffffff;
+ for (uint32_t i = msb; i >= 0; i--) {
+ if (a & (1<<i)) { d_data = i; break; }
+ }
+
+ // if (.shiftamt && d != 0xffffffff) { d = msb - d; }
+
+ // store d
+ thread->set_operand_value(dst, d_data, U32_TYPE, thread, pI);
+
+
}
void bra_impl(const ptx_instruction *pI, ptx_thread_info *thread) {
@@ -6301,11 +6335,17 @@ void vadd_impl(const ptx_instruction *pI, ptx_thread_info *thread) {
void vmad_impl(const ptx_instruction *pI, ptx_thread_info *thread) {
inst_not_implemented(pI);
}
-void vmax_impl(const ptx_instruction *pI, ptx_thread_info *thread) {
- inst_not_implemented(pI);
+
+#define VMAX 0
+#define VMIN 1
+
+void vmax_impl(const ptx_instruction *pI, ptx_thread_info *thread)
+{
+ video_mem_instruction(pI, thread, VMAX);
}
-void vmin_impl(const ptx_instruction *pI, ptx_thread_info *thread) {
- inst_not_implemented(pI);
+void vmin_impl(const ptx_instruction *pI, ptx_thread_info *thread)
+{
+ video_mem_instruction(pI, thread, VMIN);
}
void vset_impl(const ptx_instruction *pI, ptx_thread_info *thread) {
inst_not_implemented(pI);
@@ -6400,6 +6440,15 @@ void vote_impl(const ptx_instruction *pI, ptx_thread_info *thread) {
}
}
+void activemask_impl( const ptx_instruction *pI, ptx_thread_info *thread )
+{
+ active_mask_t l_activemask_bitset = pI->get_warp_active_mask();
+ uint32_t l_activemask_uint = static_cast<uint32_t>(l_activemask_bitset.to_ulong());
+
+ const operand_info &dst = pI->dst();
+ thread->set_operand_value(dst, l_activemask_uint, U32_TYPE, thread, pI);
+}
+
void xor_impl(const ptx_instruction *pI, ptx_thread_info *thread) {
ptx_reg_t src1_data, src2_data, data;
@@ -6477,3 +6526,80 @@ ptx_reg_t srcOperandModifiers(ptx_reg_t opData, operand_info opInfo,
return result;
}
+
+void video_mem_instruction(const ptx_instruction *pI, ptx_thread_info *thread, int op_code)
+{
+ const operand_info &dst = pI->dst(); // d
+ const operand_info &src1 = pI->src1(); // a
+ const operand_info &src2 = pI->src2(); // b
+ const operand_info &src3 = pI->src3(); // c
+
+ const unsigned i_type = pI->get_type();
+
+ std::list<int> scalar_type;
+ std::list<int> options;
+
+ ptx_reg_t a, b, ta, tb, c, data;
+
+ a = thread->get_operand_value(src1, dst, i_type, thread, 1);
+ b = thread->get_operand_value(src2, dst, i_type, thread, 1);
+ c = thread->get_operand_value(src3, dst, i_type, thread, 1);
+
+ // TODO: implement this
+ // ta = partSelectSignExtend( a, atype );
+ // tb = partSelectSignExtend( b, btype );
+ ta = a;
+ tb = b;
+
+ options = pI->get_options();
+ assert(options.size() == 1);
+
+ auto option = options.begin();
+ assert(*option == ATOMIC_MAX || *option == ATOMIC_MIN);
+
+ switch ( i_type ) {
+ case S32_TYPE: {
+ // assert all operands are S32_TYPE:
+ scalar_type = pI->get_scalar_type();
+ for (std::list<int>::iterator scalar = scalar_type.begin(); scalar != scalar_type.end(); scalar++)
+ {
+ assert(*scalar == S32_TYPE);
+ }
+ assert(scalar_type.size() == 3);
+ scalar_type.clear();
+
+ switch (op_code)
+ {
+ case VMAX:
+ data.s32 = MY_MAX_I(ta.s32, tb.s32);
+ break;
+ case VMIN:
+ data.s32 = MY_MIN_I(ta.s32, tb.s32);
+ break;
+ default:
+ assert(0);
+ }
+
+ switch (*option)
+ {
+ case ATOMIC_MAX:
+ data.s32 = MY_MAX_I(data.s32, c.s32);
+ break;
+ case ATOMIC_MIN:
+ data.s32 = MY_MIN_I(data.s32, c.s32);
+ break;
+ default:
+ assert(0); // not yet implemented
+ }
+ break;
+
+ }
+ default:
+ assert(0); // not yet implemented
+ }
+
+ thread->set_operand_value(dst, data, i_type, thread, pI);
+
+ return;
+}
+
diff --git a/src/cuda-sim/opcodes.def b/src/cuda-sim/opcodes.def
index c4d6a83..f5bf156 100644
--- a/src/cuda-sim/opcodes.def
+++ b/src/cuda-sim/opcodes.def
@@ -129,6 +129,7 @@ OP_DEF(VSHL_OP,vshl_impl,"vshl",0,11)
OP_DEF(VSHR_OP,vshr_impl,"vshr",0,11)
OP_DEF(VSUB_OP,vsub_impl,"vsub",0,11)
OP_DEF(VOTE_OP,vote_impl,"vote",0,3)
+OP_DEF(ACTIVEMASK_OP,activemask_impl,"activemask",1,3)
OP_DEF(XOR_OP,xor_impl,"xor",1,1)
OP_DEF(NOP_OP,nop_impl,"nop",0,7)
OP_DEF(BREAK_OP,break_impl,"break",0,3)
diff --git a/src/cuda-sim/ptx.l b/src/cuda-sim/ptx.l
index 2dadda4..6754045 100644
--- a/src/cuda-sim/ptx.l
+++ b/src/cuda-sim/ptx.l
@@ -158,6 +158,7 @@ vshl TC; yylval->int_value = VSHL_OP; return OPCODE;
vshr TC; yylval->int_value = VSHR_OP; return OPCODE;
vsub TC; yylval->int_value = VSUB_OP; return OPCODE;
vote TC; yylval->int_value = VOTE_OP; return OPCODE;
+activemask TC; yylval->int_value = ACTIVEMASK_OP; return OPCODE;
xor TC; yylval->int_value = XOR_OP; return OPCODE;
nop TC; yylval->int_value = NOP_OP; return OPCODE;
break TC; yylval->int_value = BREAK_OP; return OPCODE;
diff --git a/src/cuda-sim/ptx_ir.cc b/src/cuda-sim/ptx_ir.cc
index aa1c25a..e5b5fb7 100644
--- a/src/cuda-sim/ptx_ir.cc
+++ b/src/cuda-sim/ptx_ir.cc
@@ -1147,7 +1147,8 @@ static std::list<operand_info> check_operands(
const std::list<operand_info> &operands, gpgpu_context *ctx) {
static int g_warn_literal_operands_two_type_inst;
if ((opcode == CVT_OP) || (opcode == SET_OP) || (opcode == SLCT_OP) ||
- (opcode == TEX_OP) || (opcode == MMA_OP) || (opcode == DP4A_OP)) {
+ (opcode == TEX_OP) || (opcode == MMA_OP) || (opcode == DP4A_OP) ||
+ (opcode == VMIN_OP) || (opcode == VMAX_OP) ) {
// just make sure these do not have have const operands...
if (!g_warn_literal_operands_two_type_inst) {
std::list<operand_info>::const_iterator o;
diff --git a/src/cuda-sim/ptx_ir.h b/src/cuda-sim/ptx_ir.h
index c649702..4243941 100644
--- a/src/cuda-sim/ptx_ir.h
+++ b/src/cuda-sim/ptx_ir.h
@@ -966,6 +966,9 @@ class ptx_instruction : public warp_inst_t {
int get_pred_mod() const { return m_pred_mod; }
const char *get_source() const { return m_source.c_str(); }
+ const std::list<int> get_scalar_type() const {return m_scalar_type;}
+ const std::list<int> get_options() const {return m_options;}
+
typedef std::vector<operand_info>::const_iterator const_iterator;
const_iterator op_iter_begin() const { return m_operands.begin(); }
diff --git a/src/cuda-sim/ptx_parser.cc b/src/cuda-sim/ptx_parser.cc
index 2265587..afdb41b 100644
--- a/src/cuda-sim/ptx_parser.cc
+++ b/src/cuda-sim/ptx_parser.cc
@@ -625,8 +625,9 @@ void ptx_recognizer::add_scalar_type_spec(int type_spec) {
parse_assert((g_opcode == -1) || (g_opcode == CVT_OP) ||
(g_opcode == SET_OP) || (g_opcode == SLCT_OP) ||
(g_opcode == TEX_OP) || (g_opcode == MMA_OP) ||
- (g_opcode == DP4A_OP),
- "only cvt, set, slct, tex and dp4a can have more than one "
+ (g_opcode == DP4A_OP) || (g_opcode == VMIN_OP) ||
+ (g_opcode == VMAX_OP),
+ "only cvt, set, slct, tex, vmin, vmax and dp4a can have more than one "
"type specifier.");
}
g_scalar_type_spec = type_spec;