diff options
Diffstat (limited to 'src/cuda-sim')
| -rw-r--r-- | src/cuda-sim/instructions.cc | 69 | ||||
| -rw-r--r-- | src/cuda-sim/ptx.l | 1 | ||||
| -rw-r--r-- | src/cuda-sim/ptx.y | 2 | ||||
| -rw-r--r-- | src/cuda-sim/ptx_ir.cc | 2 | ||||
| -rw-r--r-- | src/cuda-sim/ptx_ir.h | 2 |
5 files changed, 61 insertions, 15 deletions
diff --git a/src/cuda-sim/instructions.cc b/src/cuda-sim/instructions.cc index 1c3bf4f..ab2d9f3 100644 --- a/src/cuda-sim/instructions.cc +++ b/src/cuda-sim/instructions.cc @@ -2824,7 +2824,32 @@ void orn_impl( const ptx_instruction *pI, ptx_thread_info *thread ) } void pmevent_impl( const ptx_instruction *pI, ptx_thread_info *thread ) { inst_not_implemented(pI); } -void popc_impl( const ptx_instruction *pI, ptx_thread_info *thread ) { inst_not_implemented(pI); } +void popc_impl( const ptx_instruction *pI, ptx_thread_info *thread ) +{ + ptx_reg_t src_data, data; + const operand_info &dst = pI->dst(); + const operand_info &src = pI->src1(); + + unsigned i_type = pI->get_type(); + src_data = thread->get_operand_value(src, dst, i_type, thread, 1); + + switch ( i_type ) { + case B32_TYPE: { + std::bitset<32> mask(src_data.u32); + data.u32 = mask.count(); + } break; + case B64_TYPE: { + std::bitset<64> mask(src_data.u64); + data.u32 = mask.count(); + } break; + default: + printf("Execution error: type mismatch with instruction\n"); + assert(0); + break; + } + + thread->set_operand_value(dst,data, i_type, thread, pI); +} void prefetch_impl( const ptx_instruction *pI, ptx_thread_info *thread ) { inst_not_implemented(pI); } void prefetchu_impl( const ptx_instruction *pI, ptx_thread_info *thread ) { inst_not_implemented(pI); } void prmt_impl( const ptx_instruction *pI, ptx_thread_info *thread ) { inst_not_implemented(pI); } @@ -3976,6 +4001,7 @@ void vote_impl( const ptx_instruction *pI, ptx_thread_info *thread ) static bool first_in_warp = true; static bool and_all; static bool or_all; + static unsigned int ballot_result; static std::list<ptx_thread_info*> threads_in_warp; static unsigned last_tid; @@ -3984,6 +4010,7 @@ void vote_impl( const ptx_instruction *pI, ptx_thread_info *thread ) threads_in_warp.clear(); and_all = true; or_all = false; + ballot_result = 0; int offset=31; while( (offset>=0) && !pI->active(offset) ) offset--; @@ -4004,22 +4031,36 @@ void vote_impl( const ptx_instruction *pI, ptx_thread_info *thread ) and_all &= (invert ^ pred_value); or_all |= (invert ^ pred_value); + // vote.ballot + if (invert ^ pred_value) { + int lane_id = thread->get_hw_tid() % pI->warp_size(); + ballot_result |= (1 << lane_id); + } + if( thread->get_hw_tid() == last_tid ) { - bool pred_value = false; + if (pI->vote_mode() == ptx_instruction::vote_ballot) { + ptx_reg_t data = ballot_result; + for( std::list<ptx_thread_info*>::iterator t=threads_in_warp.begin(); t!=threads_in_warp.end(); ++t ) { + const operand_info &dst = pI->dst(); + (*t)->set_operand_value(dst,data, pI->get_type(), (*t), pI); + } + } else { + bool pred_value = false; - switch( pI->vote_mode() ) { - case ptx_instruction::vote_any: pred_value = or_all; break; - case ptx_instruction::vote_all: pred_value = and_all; break; - case ptx_instruction::vote_uni: pred_value = (or_all ^ and_all); break; - default: - abort(); - } - ptx_reg_t data; - data.pred = pred_value?0:1; //the way ptxplus handles the zero flag, 1 = false and 0 = true + switch( pI->vote_mode() ) { + case ptx_instruction::vote_any: pred_value = or_all; break; + case ptx_instruction::vote_all: pred_value = and_all; break; + case ptx_instruction::vote_uni: pred_value = (or_all ^ and_all); break; + default: + abort(); + } + ptx_reg_t data; + data.pred = pred_value?0:1; //the way ptxplus handles the zero flag, 1 = false and 0 = true - for( std::list<ptx_thread_info*>::iterator t=threads_in_warp.begin(); t!=threads_in_warp.end(); ++t ) { - const operand_info &dst = pI->dst(); - (*t)->set_operand_value(dst,data, PRED_TYPE, (*t), pI); + for( std::list<ptx_thread_info*>::iterator t=threads_in_warp.begin(); t!=threads_in_warp.end(); ++t ) { + const operand_info &dst = pI->dst(); + (*t)->set_operand_value(dst,data, PRED_TYPE, (*t), pI); + } } first_in_warp = true; } diff --git a/src/cuda-sim/ptx.l b/src/cuda-sim/ptx.l index 1f4d88c..04100c8 100644 --- a/src/cuda-sim/ptx.l +++ b/src/cuda-sim/ptx.l @@ -297,6 +297,7 @@ breakaddr TC; ptx_lval.int_value = BREAKADDR_OP; return OPCODE; \.any TC; return ANY_OPTION; \.all TC; return ALL_OPTION; +\.ballot TC; return BALLOT_OPTION; \.gl TC; return GLOBAL_OPTION; \.cta TC; return CTA_OPTION; \.sys TC; return SYS_OPTION; diff --git a/src/cuda-sim/ptx.y b/src/cuda-sim/ptx.y index d9c9267..6e39e50 100644 --- a/src/cuda-sim/ptx.y +++ b/src/cuda-sim/ptx.y @@ -172,6 +172,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. %token FULL_OPTION %token ANY_OPTION %token ALL_OPTION +%token BALLOT_OPTION %token GLOBAL_OPTION %token CTA_OPTION %token SYS_OPTION @@ -398,6 +399,7 @@ option: type_spec | WIDE_OPTION { add_option(WIDE_OPTION); } | ANY_OPTION { add_option(ANY_OPTION); } | ALL_OPTION { add_option(ALL_OPTION); } + | BALLOT_OPTION { add_option(BALLOT_OPTION); } | GLOBAL_OPTION { add_option(GLOBAL_OPTION); } | CTA_OPTION { add_option(CTA_OPTION); } | SYS_OPTION { add_option(SYS_OPTION); } diff --git a/src/cuda-sim/ptx_ir.cc b/src/cuda-sim/ptx_ir.cc index 61b45e3..f8b7314 100644 --- a/src/cuda-sim/ptx_ir.cc +++ b/src/cuda-sim/ptx_ir.cc @@ -1111,6 +1111,8 @@ ptx_instruction::ptx_instruction( int opcode, break; case ALL_OPTION: m_vote_mode = vote_all; + case BALLOT_OPTION: + m_vote_mode = vote_ballot; break; case GLOBAL_OPTION: m_membar_level = GLOBAL_OPTION; diff --git a/src/cuda-sim/ptx_ir.h b/src/cuda-sim/ptx_ir.h index 4078e6b..09c9ade 100644 --- a/src/cuda-sim/ptx_ir.h +++ b/src/cuda-sim/ptx_ir.h @@ -916,7 +916,7 @@ public: unsigned rounding_mode() const { return m_rounding_mode;} unsigned saturation_mode() const { return m_saturation_mode;} unsigned dimension() const { return m_geom_spec;} - enum vote_mode_t { vote_any, vote_all, vote_uni }; + enum vote_mode_t { vote_any, vote_all, vote_uni, vote_ballot }; enum vote_mode_t vote_mode() const { return m_vote_mode; } int membar_level() const { return m_membar_level; } |
