summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAyub Gubran <[email protected]>2012-01-09 13:17:24 -0800
committerAndrew Boktor <[email protected]>2014-08-14 13:19:02 -0700
commit167c866742713f32807dd10e3ebe796ea23e9645 (patch)
treedaad065d47f963c1b244f427611db01fd3e179fb /src
parent753bcd50c00dda1481585e2fef1ba314c72e7c57 (diff)
Integrating the pure functional simulation
Merging //depot/gpgpu_sim_research/fermi_ayoub/distribution/src/abstract_hardware_model.cc //depot/gpgpu_sim_research/fermi_ayoub/distribution/src/abstract_hardware_model.h //depot/gpgpu_sim_research/fermi_ayoub/distribution/src/gpgpusim_entrypoint.cc to //depot/gpgpu_sim_research/fermi/distribution/src/... [git-p4: depot-paths = "//depot/gpgpu_sim_research/fermi/distribution/": change = 11286]
Diffstat (limited to 'src')
-rw-r--r--src/abstract_hardware_model.cc209
-rw-r--r--src/abstract_hardware_model.h66
-rw-r--r--src/gpgpusim_entrypoint.cc11
3 files changed, 270 insertions, 16 deletions
diff --git a/src/abstract_hardware_model.cc b/src/abstract_hardware_model.cc
index 1a06001..ed62177 100644
--- a/src/abstract_hardware_model.cc
+++ b/src/abstract_hardware_model.cc
@@ -30,6 +30,8 @@
#include "option_parser.h"
#include "cuda-sim/ptx_ir.h"
#include "cuda-sim/ptx-stats.h"
+#include "cuda-sim/cuda-sim.h"
+#include "gpgpu-sim/gpu-sim.h"
#include <algorithm>
unsigned mem_access_t::sm_next_access_uid = 0;
@@ -119,12 +121,12 @@ void warp_inst_t::set_active( const active_mask_t &active ) {
}
}
-void warp_inst_t::do_atomic() {
- do_atomic( m_warp_active_mask );
+void warp_inst_t::do_atomic(bool forceDo) {
+ do_atomic( m_warp_active_mask,forceDo );
}
-void warp_inst_t::do_atomic( const active_mask_t& access_mask ) {
- assert( m_isatomic && !m_empty );
+void warp_inst_t::do_atomic( const active_mask_t& access_mask,bool forceDo ) {
+ assert( m_isatomic && (!m_empty||forceDo) );
for( unsigned i=0; i < m_config->warp_size; i++ )
{
if( access_mask.test(i) )
@@ -511,3 +513,202 @@ std::string kernel_info_t::name() const
{
return m_kernel_entry->get_name();
}
+
+simt_stack::simt_stack( unsigned wid, unsigned warpSize)
+{
+ m_warp_id=wid;
+ m_warp_size = warpSize;
+ m_stack_top = 0;
+ m_pc = (address_type*)calloc(m_warp_size * 2, sizeof(address_type));
+ m_calldepth = (unsigned int*)calloc(m_warp_size * 2, sizeof(unsigned int));
+ m_active_mask = new simt_mask_t[m_warp_size * 2];
+ m_recvg_pc = (address_type*)calloc(m_warp_size * 2, sizeof(address_type));
+ m_branch_div_cycle = (unsigned long long *)calloc(m_warp_size * 2, sizeof(unsigned long long ));
+ reset();
+}
+
+void simt_stack::reset()
+{
+ m_stack_top = 0;
+ memset(m_pc, -1, m_warp_size * 2 * sizeof(address_type));
+ memset(m_calldepth, 0, m_warp_size * 2 * sizeof(unsigned int));
+ memset(m_recvg_pc, -1, m_warp_size * 2 * sizeof(address_type));
+ memset(m_branch_div_cycle, 0, m_warp_size * 2 * sizeof(unsigned long long ));
+ for( unsigned i=0; i < 2*m_warp_size; i++ )
+ m_active_mask[i].reset();
+}
+
+void simt_stack::launch( address_type start_pc, const simt_mask_t &active_mask )
+{
+ reset();
+ m_pc[0] = start_pc;
+ m_calldepth[0] = 1;
+ m_active_mask[0] = active_mask;
+}
+
+const simt_mask_t &simt_stack::get_active_mask() const
+{
+ return m_active_mask[m_stack_top];
+}
+
+void simt_stack::get_pdom_stack_top_info( unsigned *pc, unsigned *rpc ) const
+{
+ *pc = m_pc[m_stack_top];
+ *rpc = m_recvg_pc[m_stack_top];
+}
+
+unsigned simt_stack::get_rp() const
+{
+ return m_recvg_pc[m_stack_top];
+}
+
+void simt_stack::print (FILE *fout) const
+{
+ const simt_stack *warp=this;
+ for ( unsigned k=0; k <= warp->m_stack_top; k++ ) {
+ if ( k==0 ) {
+ fprintf(fout, "w%02d %1u ", m_warp_id, k );
+ } else {
+ fprintf(fout, " %1u ", k );
+ }
+ for (unsigned j=0; j<m_warp_size; j++)
+ fprintf(fout, "%c", (warp->m_active_mask[k].test(j)?'1':'0') );
+ fprintf(fout, " pc: 0x%03x", warp->m_pc[k] );
+ if ( warp->m_recvg_pc[k] == (unsigned)-1 ) {
+ fprintf(fout," rp: ---- cd: %2u ", warp->m_calldepth[k] );
+ } else {
+ fprintf(fout," rp: %4u cd: %2u ", warp->m_recvg_pc[k], warp->m_calldepth[k] );
+ }
+ if ( warp->m_branch_div_cycle[k] != 0 ) {
+ fprintf(fout," bd@%6u ", (unsigned) warp->m_branch_div_cycle[k] );
+ } else {
+ fprintf(fout," " );
+ }
+ ptx_print_insn( warp->m_pc[k], fout );
+ fprintf(fout,"\n");
+ }
+}
+
+void simt_stack::update( simt_mask_t &thread_done, addr_vector_t &next_pc, address_type recvg_pc )
+{
+ int stack_top = m_stack_top;
+
+ assert( next_pc.size() == m_warp_size );
+
+ simt_mask_t top_active_mask = m_active_mask[stack_top];
+ address_type top_recvg_pc = m_recvg_pc[stack_top];
+
+ assert(top_active_mask.any());
+
+ const address_type null_pc = 0;
+ bool warp_diverged = false;
+ address_type new_recvg_pc = null_pc;
+ while (top_active_mask.any()) {
+
+ // extract a group of threads with the same next PC among the active threads in the warp
+ address_type tmp_next_pc = null_pc;
+ simt_mask_t tmp_active_mask;
+ for (int i = m_warp_size - 1; i >= 0; i--) {
+ if ( top_active_mask.test(i) ) { // is this thread active?
+ if (thread_done.test(i)) {
+ top_active_mask.reset(i); // remove completed thread from active mask
+ } else if (tmp_next_pc == null_pc) {
+ tmp_next_pc = next_pc[i];
+ tmp_active_mask.set(i);
+ top_active_mask.reset(i);
+ } else if (tmp_next_pc == next_pc[i]) {
+ tmp_active_mask.set(i);
+ top_active_mask.reset(i);
+ }
+ }
+ }
+
+ // discard the new entry if its PC matches with reconvergence PC
+ // that automatically reconverges the entry
+ if (tmp_next_pc == top_recvg_pc) continue;
+
+ // this new entry is not converging
+ // if this entry does not include thread from the warp, divergence occurs
+ if (top_active_mask.any() && !warp_diverged ) {
+ warp_diverged = true;
+ // modify the existing top entry into a reconvergence entry in the pdom stack
+ new_recvg_pc = recvg_pc;
+ if (new_recvg_pc != top_recvg_pc) {
+ m_pc[stack_top] = new_recvg_pc;
+ m_branch_div_cycle[stack_top] = gpu_sim_cycle;
+ stack_top += 1;
+ m_branch_div_cycle[stack_top] = 0;
+ }
+ }
+
+ // discard the new entry if its PC matches with reconvergence PC
+ if (warp_diverged && tmp_next_pc == new_recvg_pc) continue;
+
+ // update the current top of pdom stack
+ m_pc[stack_top] = tmp_next_pc;
+ m_active_mask[stack_top] = tmp_active_mask;
+ if (warp_diverged) {
+ m_calldepth[stack_top] = 0;
+ m_recvg_pc[stack_top] = new_recvg_pc;
+ } else {
+ m_recvg_pc[stack_top] = top_recvg_pc;
+ }
+ stack_top += 1; // set top to next entry in the pdom stack
+ }
+ m_stack_top = stack_top - 1;
+
+ assert(m_stack_top >= 0);
+ assert(m_stack_top < m_warp_size * 2);
+}
+
+void core_t::execute_warp_inst_t(warp_inst_t &inst, unsigned warpSize, unsigned warpId){
+ for ( unsigned t=0; t < warpSize; t++ ) {
+ if( inst.active(t) ) {
+ if(warpId==(unsigned (-1)))
+ warpId = inst.warp_id();
+ unsigned tid=warpSize*warpId+t;
+ m_thread[tid]->ptx_exec_inst(inst,t);
+
+ //virtual function
+ checkExecutionStatusAndUpdate(inst,t,tid);
+ }
+ }
+}
+
+bool core_t::ptx_thread_done( unsigned hw_thread_id ) const
+{
+ return ((m_thread[ hw_thread_id ]==NULL) || m_thread[ hw_thread_id ]->is_done());
+}
+
+void core_t::updateSIMTStack(unsigned warpId, unsigned warpSize, warp_inst_t * inst){
+simt_mask_t thread_done;
+addr_vector_t next_pc;
+unsigned wtid = warpId * warpSize;
+for (unsigned i = 0; i < warpSize; i++) {
+ if( ptx_thread_done(wtid+i) ) {
+ thread_done.set(i);
+ next_pc.push_back( (address_type)-1 );
+ } else {
+ if( inst->reconvergence_pc == RECONVERGE_RETURN_PC )
+ inst->reconvergence_pc = get_return_pc(m_thread[wtid+i]);
+ next_pc.push_back( m_thread[wtid+i]->get_pc() );
+ }
+}
+m_simt_stack[warpId]->update(thread_done,next_pc,inst->reconvergence_pc);
+}
+
+//! Get the warp to be executed using the data taken form the SIMT stack
+warp_inst_t core_t::getExecuteWarp(unsigned warpId){
+ unsigned pc,rpc;
+ m_simt_stack[warpId]->get_pdom_stack_top_info(&pc,&rpc);
+ warp_inst_t wi= *ptx_fetch_inst(pc);
+ wi.set_active(m_simt_stack[warpId]->get_active_mask());
+ return wi;
+}
+
+void core_t::initilizeSIMTStack(unsigned warps, unsigned warpsSize)
+{
+m_simt_stack = new simt_stack*[warps];
+ for (unsigned i = 0; i < warps; ++i)
+ m_simt_stack[i] = new simt_stack(i,warpsSize);
+}
diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h
index 97b243e..229d6a1 100644
--- a/src/abstract_hardware_model.h
+++ b/src/abstract_hardware_model.h
@@ -232,12 +232,37 @@ struct core_config {
unsigned gpgpu_max_insn_issue_per_warp;
};
-class core_t {
+// bounded stack that implements simt reconvergence using pdom mechanism from MICRO'07 paper
+const unsigned MAX_WARP_SIZE = 32;
+typedef std::bitset<MAX_WARP_SIZE> active_mask_t;
+#define MAX_WARP_SIZE_SIMT_STACK MAX_WARP_SIZE
+typedef std::bitset<MAX_WARP_SIZE_SIMT_STACK> simt_mask_t;
+typedef std::vector<address_type> addr_vector_t;
+
+class simt_stack {
public:
- virtual ~core_t() {}
- virtual void warp_exit( unsigned warp_id ) = 0;
- virtual bool warp_waiting_at_barrier( unsigned warp_id ) const = 0;
- virtual class gpgpu_sim *get_gpu() = 0;
+ simt_stack( unsigned wid, unsigned warpSize);
+
+ void reset();
+ void launch( address_type start_pc, const simt_mask_t &active_mask );
+ void update( simt_mask_t &thread_done, addr_vector_t &next_pc, address_type recvg_pc );
+
+ const simt_mask_t &get_active_mask() const;
+ void get_pdom_stack_top_info( unsigned *pc, unsigned *rpc ) const;
+ unsigned get_rp() const;
+ void print(FILE*fp) const;
+
+protected:
+ unsigned m_warp_id;
+ unsigned m_stack_top;
+ unsigned m_warp_size;
+
+ address_type *m_pc;
+ simt_mask_t *m_active_mask;
+ address_type *m_recvg_pc;
+ unsigned int *m_calldepth;
+
+ unsigned long long *m_branch_div_cycle;
};
#define GLOBAL_HEAP_START 0x80000000
@@ -445,9 +470,6 @@ const unsigned MAX_MEMORY_ACCESS_SIZE = 128;
typedef std::bitset<MAX_MEMORY_ACCESS_SIZE> mem_access_byte_mask_t;
#define NO_PARTIAL_WRITE (mem_access_byte_mask_t())
-const unsigned MAX_WARP_SIZE = 32;
-typedef std::bitset<MAX_WARP_SIZE> active_mask_t;
-
enum mem_access_type {
GLOBAL_ACC_R,
LOCAL_ACC_R,
@@ -656,8 +678,8 @@ public:
}
// modifiers
- void do_atomic();
- void do_atomic( const active_mask_t& access_mask );
+ void do_atomic(bool forceDo=false);
+ void do_atomic( const active_mask_t& access_mask, bool forceDo=false );
void clear()
{
m_empty=true;
@@ -803,6 +825,30 @@ void move_warp( warp_inst_t *&dst, warp_inst_t *&src );
size_t get_kernel_code_size( class function_info *entry );
+/*
+ * This abstract class used as a base for functional and performance and simulation, it has basic functional simulation
+ * data structures and procedures.
+ */
+class core_t {
+ public:
+ virtual ~core_t() {}
+ virtual void warp_exit( unsigned warp_id ) = 0;
+ virtual bool warp_waiting_at_barrier( unsigned warp_id ) const = 0;
+ virtual void checkExecutionStatusAndUpdate(warp_inst_t &inst, unsigned t, unsigned tid)=0;
+ class gpgpu_sim * get_gpu() {return m_gpu;}
+ void execute_warp_inst_t(warp_inst_t &inst, unsigned warpSize, unsigned warpId =(unsigned)-1);
+ bool ptx_thread_done( unsigned hw_thread_id ) const ;
+ void updateSIMTStack(unsigned warpId, unsigned warpSize, warp_inst_t * inst);
+ void initilizeSIMTStack(unsigned warps, unsigned warpsSize);
+ warp_inst_t getExecuteWarp(unsigned warpId);
+
+ protected:
+ class gpgpu_sim *m_gpu;
+ kernel_info_t *m_kernel;
+ simt_stack **m_simt_stack; // pdom based reconvergence context for each warp
+ class ptx_thread_info ** m_thread;
+};
+
#endif // #ifdef __cplusplus
#endif // #ifndef ABSTRACT_HARDWARE_MODEL_INCLUDED
diff --git a/src/gpgpusim_entrypoint.cc b/src/gpgpusim_entrypoint.cc
index add9a22..e18b088 100644
--- a/src/gpgpusim_entrypoint.cc
+++ b/src/gpgpusim_entrypoint.cc
@@ -238,8 +238,15 @@ int gpgpu_opencl_ptx_sim_main_perf( kernel_info_t *grid )
return 0;
}
+//! Functional simulation of OpenCL
+/*!
+ * This function call the CUDA PTX functional simulator
+ */
int gpgpu_opencl_ptx_sim_main_func( kernel_info_t *grid )
{
- printf("GPGPU-Sim PTX API: OpenCL functional-only simulation not yet implemented (use performance simulation)\n");
- exit(1);
+ //calling the CUDA PTX simulator, sending the kernel by reference and a flag set to true,
+ //the flag used by the function to distinguish OpenCL calls from the CUDA simulation calls which
+ //it is needed by the called function to not register the exit the exit of OpenCL kernel as it doesn't register entering in the first place as the CUDA kernels does
+ gpgpu_cuda_ptx_sim_main_func( *grid, true );
+ return 0;
}