summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/abstract_hardware_model.h56
-rw-r--r--src/cuda-sim/cuda-sim.cc21
-rw-r--r--src/gpgpu-sim/gpu-sim.cc114
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);
+ }
+}