diff options
| author | Tor Aamodt <[email protected]> | 2010-08-04 08:18:26 -0800 |
|---|---|---|
| committer | Tor Aamodt <[email protected]> | 2010-08-04 08:18:26 -0800 |
| commit | 0ef446ceb7b5045030724f6906fc011296623d2d (patch) | |
| tree | 834f97ece6c91e5fb11cfebb2bc44dc22c5eec38 | |
| parent | a5fb09084b9783b3fb86ca42bd6a12800361ff85 (diff) | |
intial support for integrated interactive debugger (for debugging PTX assembly)
[git-p4: depot-paths = "//depot/gpgpu_sim_research/fermi/distribution/": change = 7137]
| -rw-r--r-- | src/abstract_hardware_model.h | 56 | ||||
| -rw-r--r-- | src/cuda-sim/cuda-sim.cc | 21 | ||||
| -rw-r--r-- | src/gpgpu-sim/gpu-sim.cc | 114 |
3 files changed, 191 insertions, 0 deletions
diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index 3b3d07e..98d934c 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -67,6 +67,62 @@ private: unsigned m_bank; // n in ".const[n]"; note .const == .const[0] (see PTX 2.1 manual, sec. 5.1.3) }; +#include <string> + +class brk_pt { +public: + brk_pt() { m_valid=false; } + brk_pt( const char *fileline, unsigned uid ) + { + m_valid = true; + m_watch = false; + m_fileline = std::string(fileline); + m_thread_uid=uid; + } + brk_pt( unsigned addr, unsigned value ) + { + m_valid = true; + m_watch = true; + m_addr = addr; + m_value = value; + } + + unsigned get_value() const { return m_value; } + addr_t get_addr() const { return m_addr; } + bool is_valid() const { return m_valid; } + bool is_watchpoint() const { return m_watch; } + bool is_equal( const std::string &fileline, unsigned uid ) const + { + if( m_watch ) + return false; + if( (m_thread_uid != (unsigned)-1) && (uid != m_thread_uid) ) + return false; + return m_fileline == fileline; + } + std::string location() const + { + char buffer[1024]; + sprintf(buffer,"%s thread uid = %u", m_fileline.c_str(), m_thread_uid); + return buffer; + } + + unsigned set_value( unsigned val ) { return m_value=val; } +private: + bool m_valid; + bool m_watch; + + // break point + std::string m_fileline; + unsigned m_thread_uid; + + // watch point + unsigned m_addr; + unsigned m_value; +}; + +bool thread_at_brkpt( void *ptx_thd_info, const struct brk_pt &b ); +unsigned read_location( addr_t addr ); + #endif #endif diff --git a/src/cuda-sim/cuda-sim.cc b/src/cuda-sim/cuda-sim.cc index bf90938..adc9e98 100644 --- a/src/cuda-sim/cuda-sim.cc +++ b/src/cuda-sim/cuda-sim.cc @@ -77,6 +77,7 @@ #include "memory.h" #include "ptx-stats.h" +extern bool g_interactive_debugger_enabled; int gpgpu_ptx_instruction_classification=0; void ** g_inst_classification_stat = NULL; @@ -1708,6 +1709,7 @@ void read_environment_variables() ptx_debug = 0; g_debug_execution = 0; g_debug_ir_generation = false; + g_interactive_debugger_enabled = false; char *mode = getenv("PTX_SIM_MODE_FUNC"); if ( mode ) @@ -1715,6 +1717,12 @@ void read_environment_variables() printf("GPGPU-Sim PTX: simulation mode %d (can change with PTX_SIM_MODE_FUNC environment variable:\n", g_ptx_sim_mode); printf(" 1=functional simulation only, 0=detailed performance simulator)\n"); g_filename = getenv("PTX_SIM_KERNELFILE"); + char *dbg_inter = getenv("GPGPUSIM_DEBUG"); + if ( dbg_inter && strlen(dbg_inter) ) { + printf("GPGPU-Sim PTX: enabling interactive debugger\n"); + fflush(stdout); + g_interactive_debugger_enabled = true; + } char *dbg_level = getenv("PTX_SIM_DEBUG"); if ( dbg_level && strlen(dbg_level) ) { printf("GPGPU-Sim PTX: setting debug level to %s\n", dbg_level ); @@ -2348,3 +2356,16 @@ void *gpgpusim_opencl_getkernel_Object( const char *kernel_name ) } return i->second; } + +bool thread_at_brkpt( void *thd, const struct brk_pt &b ) +{ + ptx_thread_info *thread = (ptx_thread_info *) thd; + return b.is_equal(thread->get_location(),thread->get_uid()); +} + +unsigned read_location( addr_t addr ) +{ + unsigned result=0; + g_global_mem->read(addr,4,&result); + return result; +} diff --git a/src/gpgpu-sim/gpu-sim.cc b/src/gpgpu-sim/gpu-sim.cc index 4da76f9..2b4ebe3 100644 --- a/src/gpgpu-sim/gpu-sim.cc +++ b/src/gpgpu-sim/gpu-sim.cc @@ -87,6 +87,8 @@ #include <string.h> #define MAX(a,b) (((a)>(b))?(a):(b)) +bool g_interactive_debugger_enabled=false; + extern unsigned L2_write_miss; extern unsigned L2_write_hit; extern unsigned L2_read_hit; @@ -204,6 +206,7 @@ void check_time_vector_update(unsigned int uid,int slot ,long int latency,int ty void node_req_hist_clear(void *p); void node_req_hist_dump(void *p); void node_req_hist_update(void * p,int node, long long cycle); +static void gpgpu_debug(); /* functionally simulated memory */ extern struct mem_t *mem; @@ -1549,6 +1552,8 @@ void gpu_sim_loop( int grid_num ) sc[i]->gpu_cycle++; } gpu_sim_cycle++; + if( g_interactive_debugger_enabled ) + gpgpu_debug(); for (unsigned i=0;i<gpu_n_shader && more_thread;i++) { if (gpgpu_spread_blocks_across_cores) { @@ -1759,3 +1764,112 @@ void dump_pipeline() { dump_pipeline_impl(0,-1,-1); } + +/// interactive debugger + +static void gpgpu_debug() +{ + bool done=true; + + static bool single_step=true; + static unsigned next_brkpt=1; + static std::map<unsigned,brk_pt> breakpoints; + + /// if single stepping, go to interactive debugger + + if( single_step ) + done=false; + + /// check if we've reached a breakpoint + + for( std::map<unsigned,brk_pt>::iterator i=breakpoints.begin(); i!=breakpoints.end(); i++) { + unsigned num=i->first; + brk_pt &b=i->second; + if( b.is_watchpoint() ) { + unsigned addr = b.get_addr(); + unsigned new_value = read_location(addr); + if( new_value != b.get_value() ) { + printf( "GPGPU-Sim DBG: watch point %u triggered (old value=%x, new value=%x)\n", + num,b.get_value(),new_value ); + b.set_value(new_value); + done = false; + } + } else { + for( unsigned sid=0; sid < gpu_n_shader; sid++ ) { + inst_t *fvi = first_valid_thread(sc[sid]->pipeline_reg[IF_ID]); + if( !fvi ) continue; + if( thread_at_brkpt(fvi->ptx_thd_info, b) ) { + done = false; + printf("GPGPU-Sim DBG: reached breakpoint %u at %s (sm=%u, hwtid=%u)\n", + num, b.location().c_str(), sid, fvi->hw_thread_id ); + } + } + } + } + + /// enter interactive debugger loop + + while (!done) { + printf("(gpgpu-sim dbg) "); + fflush(stdout); + + char line[1024]; + fgets(line,1024,stdin); + + char *tok = strtok(line," \t\n"); + if( !strcmp(tok,"dp") ) { + int shader_num = 0; + tok = strtok(NULL," \t\n"); + sscanf(tok,"%d",&shader_num); + dump_pipeline_impl((0x40|0x4|0x1),shader_num,0); + printf("\n"); + fflush(stdout); + } else if( !strcmp(tok,"q") || !strcmp(tok,"quit") ) { + printf("\nreally quit GPGPU-Sim (y/n)?\n"); + fgets(line,1024,stdin); + tok = strtok(NULL," \t\n"); + if( !strcmp(tok,"y") ) { + exit(0); + } else { + printf("not quiting.\n"); + } + } else if( !strcmp(tok,"b") ) { + tok = strtok(NULL," \t\n"); + char brkpt[1024]; + sscanf(tok,"%s",brkpt); + tok = strtok(NULL," \t\n"); + unsigned uid; + sscanf(tok,"%u",&uid); + breakpoints[next_brkpt++] = brk_pt(brkpt,uid); + } else if( !strcmp(tok,"d") ) { + tok = strtok(NULL," \t\n"); + unsigned uid; + sscanf(tok,"%u",&uid); + breakpoints.erase(uid); + } else if( !strcmp(tok,"s") ) { + done = true; + } else if( !strcmp(tok,"c") ) { + single_step=false; + done = true; + } else if( !strcmp(tok,"w") ) { + tok = strtok(NULL," \t\n"); + unsigned addr; + sscanf(tok,"%x",&addr); + unsigned value = read_location(addr); + breakpoints[next_brkpt++] = brk_pt(addr,value); + } else if( !strcmp(tok,"h") ) { + printf("commands:\n"); + printf(" q - quit GPGPU-Sim\n"); + printf(" b <file>:<line> <thead uid> - set breakpoint\n"); + printf(" w <global address> - set watchpoint\n"); + printf(" del <n> - delete breakpoint\n"); + printf(" s - single step one shader cycle (all cores)\n"); + printf(" c - continue simulation without single stepping\n"); + printf(" dp <n> - display pipeline contents on SM <n>\n"); + printf(" h - print this message\n"); + } else { + printf("\ncommand not understood.\n"); + } + fflush(stdout); + } +} |
