summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cuda-sim/instructions.cc69
-rw-r--r--src/cuda-sim/ptx.l1
-rw-r--r--src/cuda-sim/ptx.y2
-rw-r--r--src/cuda-sim/ptx_ir.cc2
-rw-r--r--src/cuda-sim/ptx_ir.h2
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; }