summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorspeverel <[email protected]>2017-08-17 16:08:03 -0700
committerspeverel <[email protected]>2017-08-17 16:08:03 -0700
commite247912d9e8fc3ab779b58eb99721b6f536a6b35 (patch)
tree964f6b1fe349723a4c70241ce84e8e32d30a2563 /src
parent45f95f05a11e916933480422b9075767a4cfdf90 (diff)
parent21ad40b4918f08bf8508487b9aab700948fe8c84 (diff)
Merged all work on the dev branch since the divergence point into the dnn branch, incorporating Dynamic Parallelism and many bug fixes.
Diffstat (limited to 'src')
-rw-r--r--src/abstract_hardware_model.cc110
-rw-r--r--src/abstract_hardware_model.h55
-rw-r--r--src/cuda-sim/Makefile7
-rw-r--r--src/cuda-sim/cuda-sim.cc80
-rw-r--r--src/cuda-sim/cuda_device_runtime.cc320
-rw-r--r--src/cuda-sim/cuda_device_runtime.h11
-rw-r--r--src/cuda-sim/instructions.cc98
-rw-r--r--src/cuda-sim/opcodes.def1
-rw-r--r--src/cuda-sim/ptx.l7
-rw-r--r--src/cuda-sim/ptx.y16
-rw-r--r--src/cuda-sim/ptx_ir.cc55
-rw-r--r--src/cuda-sim/ptx_ir.h19
-rw-r--r--src/cuda-sim/ptx_loader.cc6
-rw-r--r--src/cuda-sim/ptx_parser.cc25
-rw-r--r--src/cuda-sim/ptx_parser.h4
-rw-r--r--src/cuda-sim/ptx_sim.h3
-rw-r--r--src/cuda-sim/ptxinfo.y4
-rw-r--r--src/gpgpu-sim/Makefile1
-rw-r--r--src/gpgpu-sim/gpu-sim.cc195
-rw-r--r--src/gpgpu-sim/gpu-sim.h22
-rw-r--r--src/gpgpu-sim/shader.cc114
-rw-r--r--src/gpgpu-sim/shader.h38
-rw-r--r--src/gpgpusim_entrypoint.cc12
-rw-r--r--src/intersim2/Makefile10
-rw-r--r--src/stream_manager.cc109
-rw-r--r--src/stream_manager.h3
26 files changed, 1238 insertions, 87 deletions
diff --git a/src/abstract_hardware_model.cc b/src/abstract_hardware_model.cc
index ab83ba4..d668de7 100644
--- a/src/abstract_hardware_model.cc
+++ b/src/abstract_hardware_model.cc
@@ -552,6 +552,9 @@ void warp_inst_t::completed( unsigned long long cycle ) const
ptx_file_line_stats_add_latency(pc, latency * active_count());
}
+//Jin: CDP support
+bool g_cdp_enabled;
+unsigned g_kernel_launch_latency;
unsigned kernel_info_t::m_next_uid = 1;
@@ -567,11 +570,18 @@ kernel_info_t::kernel_info_t( dim3 gridDim, dim3 blockDim, class function_info *
m_num_cores_running=0;
m_uid = m_next_uid++;
m_param_mem = new memory_space_impl<8192>("param",64*1024);
+
+ //Jin: parent and child kernel management for CDP
+ m_parent_kernel = NULL;
+
+ //Jin: launch latency management
+ m_launch_latency = g_kernel_launch_latency;
}
kernel_info_t::~kernel_info_t()
{
assert( m_active_threads.empty() );
+ destroy_cta_streams();
delete m_param_mem;
}
@@ -580,6 +590,106 @@ std::string kernel_info_t::name() const
return m_kernel_entry->get_name();
}
+//Jin: parent and child kernel management for CDP
+void kernel_info_t::set_parent(kernel_info_t * parent,
+ dim3 parent_ctaid, dim3 parent_tid) {
+ m_parent_kernel = parent;
+ m_parent_ctaid = parent_ctaid;
+ m_parent_tid = parent_tid;
+ parent->set_child(this);
+}
+
+void kernel_info_t::set_child(kernel_info_t * child) {
+ m_child_kernels.push_back(child);
+}
+
+void kernel_info_t::remove_child(kernel_info_t * child) {
+ assert(std::find(m_child_kernels.begin(), m_child_kernels.end(), child)
+ != m_child_kernels.end());
+ m_child_kernels.remove(child);
+}
+
+bool kernel_info_t::is_finished() {
+ if(done() && children_all_finished())
+ return true;
+ else
+ return false;
+}
+
+bool kernel_info_t::children_all_finished() {
+ if(!m_child_kernels.empty())
+ return false;
+
+ return true;
+}
+
+void kernel_info_t::notify_parent_finished() {
+ if(m_parent_kernel) {
+ extern unsigned long long g_total_param_size;
+ g_total_param_size -= ((m_kernel_entry->get_args_aligned_size() + 255)/256*256);
+ m_parent_kernel->remove_child(this);
+ g_stream_manager->register_finished_kernel(m_parent_kernel->get_uid());
+ }
+}
+
+CUstream_st * kernel_info_t::create_stream_cta(dim3 ctaid) {
+ assert(get_default_stream_cta(ctaid));
+ CUstream_st * stream = new CUstream_st();
+ g_stream_manager->add_stream(stream);
+ assert(m_cta_streams.find(ctaid) != m_cta_streams.end());
+ assert(m_cta_streams[ctaid].size() >= 1); //must have default stream
+ m_cta_streams[ctaid].push_back(stream);
+
+ return stream;
+}
+
+CUstream_st * kernel_info_t::get_default_stream_cta(dim3 ctaid) {
+ if(m_cta_streams.find(ctaid) != m_cta_streams.end()) {
+ assert(m_cta_streams[ctaid].size() >= 1); //already created, must have default stream
+ return *(m_cta_streams[ctaid].begin());
+ }
+ else {
+ m_cta_streams[ctaid] = std::list<CUstream_st *>();
+ CUstream_st * stream = new CUstream_st();
+ g_stream_manager->add_stream(stream);
+ m_cta_streams[ctaid].push_back(stream);
+ return stream;
+ }
+}
+
+bool kernel_info_t::cta_has_stream(dim3 ctaid, CUstream_st* stream) {
+ if(m_cta_streams.find(ctaid) == m_cta_streams.end())
+ return false;
+
+ std::list<CUstream_st *> &stream_list = m_cta_streams[ctaid];
+ if(std::find(stream_list.begin(), stream_list.end(), stream)
+ == stream_list.end())
+ return false;
+ else
+ return true;
+}
+
+void kernel_info_t::print_parent_info() {
+ if(m_parent_kernel) {
+ printf("Parent %d: \'%s\', Block (%d, %d, %d), Thread (%d, %d, %d)\n",
+ m_parent_kernel->get_uid(), m_parent_kernel->name().c_str(),
+ m_parent_ctaid.x, m_parent_ctaid.y, m_parent_ctaid.z,
+ m_parent_tid.x, m_parent_tid.y, m_parent_tid.z);
+ }
+}
+
+void kernel_info_t::destroy_cta_streams() {
+ printf("Destroy streams for kernel %d: ", get_uid()); size_t stream_size = 0;
+ for(auto s = m_cta_streams.begin(); s != m_cta_streams.end(); s++) {
+ stream_size += s->second.size();
+ for(auto ss = s->second.begin(); ss != s->second.end(); ss++)
+ g_stream_manager->destroy_stream(*ss);
+ s->second.clear();
+ }
+ printf("size %lu\n", stream_size);
+ m_cta_streams.clear();
+}
+
simt_stack::simt_stack( unsigned wid, unsigned warpSize)
{
m_warp_id=wid;
diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h
index c009276..607eda7 100644
--- a/src/abstract_hardware_model.h
+++ b/src/abstract_hardware_model.h
@@ -155,15 +155,35 @@ enum _memory_op_t {
#include <stdlib.h>
#include <map>
#include <deque>
+#include <algorithm>
#if !defined(__VECTOR_TYPES_H__)
struct dim3 {
unsigned int x, y, z;
};
#endif
+struct dim3comp {
+ bool operator() (const dim3 & a, const dim3 & b) const
+ {
+ if(a.z < b.z)
+ return true;
+ else if(a.y < b.y)
+ return true;
+ else if (a.x < b.x)
+ return true;
+ else
+ return false;
+ }
+};
void increment_x_then_y_then_z( dim3 &i, const dim3 &bound);
+//Jin: child kernel information for CDP
+#include "stream_manager.h"
+class stream_manager;
+struct CUstream_st;
+extern stream_manager * g_stream_manager;
+
class kernel_info_t {
public:
// kernel_info_t()
@@ -251,6 +271,35 @@ private:
std::list<class ptx_thread_info *> m_active_threads;
class memory_space *m_param_mem;
+
+public:
+ //Jin: parent and child kernel management for CDP
+ void set_parent(kernel_info_t * parent, dim3 parent_ctaid, dim3 parent_tid);
+ void set_child(kernel_info_t * child);
+ void remove_child(kernel_info_t * child);
+ bool is_finished();
+ bool children_all_finished();
+ void notify_parent_finished();
+ CUstream_st * create_stream_cta(dim3 ctaid);
+ CUstream_st * get_default_stream_cta(dim3 ctaid);
+ bool cta_has_stream(dim3 ctaid, CUstream_st* stream);
+ void destroy_cta_streams();
+ void print_parent_info();
+ kernel_info_t * get_parent() { return m_parent_kernel; }
+
+private:
+ kernel_info_t * m_parent_kernel;
+ dim3 m_parent_ctaid;
+ dim3 m_parent_tid;
+ std::list<kernel_info_t *> m_child_kernels; //child kernel launched
+ std::map< dim3, std::list<CUstream_st *>, dim3comp > m_cta_streams; //streams created in each CTA
+
+//Jin: kernel timing
+public:
+ unsigned long long launch_cycle;
+ unsigned long long start_cycle;
+ unsigned long long end_cycle;
+ unsigned m_launch_latency;
};
struct core_config {
@@ -827,6 +876,7 @@ public:
m_mem_accesses_created=false;
m_cache_hit=false;
m_is_printf=false;
+ m_is_cdp = 0;
}
virtual ~warp_inst_t(){
}
@@ -999,6 +1049,11 @@ protected:
std::list<mem_access_t> m_accessq;
static unsigned sm_next_uid;
+
+ //Jin: cdp support
+public:
+ int m_is_cdp;
+
};
void move_warp( warp_inst_t *&dst, warp_inst_t *&src );
diff --git a/src/cuda-sim/Makefile b/src/cuda-sim/Makefile
index 166e256..999dad7 100644
--- a/src/cuda-sim/Makefile
+++ b/src/cuda-sim/Makefile
@@ -46,7 +46,7 @@ OPT := -O3 -g3 -Wall -Wno-unused-function -Wno-sign-compare
ifeq ($(DEBUG),1)
OPT := -g3 -Wall -Wno-unused-function -Wno-sign-compare
endif
-OPT += -I$(CUDA_INSTALL_PATH)/include -I$(OUTPUT_DIR)/ -I.
+OPT += -I$(CUDA_INSTALL_PATH)/include -I$(OUTPUT_DIR)/ -I. -I$(SIM_OBJ_FILES_DIR)
OPT += -fPIC
ifeq ($(TRACE),1)
@@ -62,7 +62,7 @@ ifeq ($(GNUC_CPP0X),1)
endif
endif
-OBJS := $(OUTPUT_DIR)/ptx_parser.o $(OUTPUT_DIR)/ptx_loader.o $(OUTPUT_DIR)/cuda_device_printf.o $(OUTPUT_DIR)/instructions.o $(OUTPUT_DIR)/cuda-sim.o $(OUTPUT_DIR)/ptx_ir.o $(OUTPUT_DIR)/ptx_sim.o $(OUTPUT_DIR)/memory.o $(OUTPUT_DIR)/ptx-stats.o $(OUTPUT_DIR)/decuda_pred_table/decuda_pred_table.o $(OUTPUT_DIR)/ptx.tab.o $(OUTPUT_DIR)/lex.ptx_.o $(OUTPUT_DIR)/ptxinfo.tab.o $(OUTPUT_DIR)/lex.ptxinfo_.o
+OBJS := $(OUTPUT_DIR)/ptx_parser.o $(OUTPUT_DIR)/ptx_loader.o $(OUTPUT_DIR)/cuda_device_printf.o $(OUTPUT_DIR)/instructions.o $(OUTPUT_DIR)/cuda-sim.o $(OUTPUT_DIR)/ptx_ir.o $(OUTPUT_DIR)/ptx_sim.o $(OUTPUT_DIR)/memory.o $(OUTPUT_DIR)/ptx-stats.o $(OUTPUT_DIR)/decuda_pred_table/decuda_pred_table.o $(OUTPUT_DIR)/ptx.tab.o $(OUTPUT_DIR)/lex.ptx_.o $(OUTPUT_DIR)/ptxinfo.tab.o $(OUTPUT_DIR)/lex.ptxinfo_.o $(OUTPUT_DIR)/cuda_device_runtime.o
OPT += -DCUDART_VERSION=$(CUDART_VERSION)
@@ -142,8 +142,9 @@ $(OUTPUT_DIR)/ptx_parser.o: $(OUTPUT_DIR)/ptx.tab.c $(OUTPUT_DIR)/ptx_parser_dec
$(OUTPUT_DIR)/ptxinfo.tab.o: $(OUTPUT_DIR)/ptx.tab.c
$(OUTPUT_DIR)/ptx-stats.o: $(OUTPUT_DIR)/ptx.tab.c
$(OUTPUT_DIR)/ptx_sim.o: $(OUTPUT_DIR)/ptx.tab.c
-$(OUTPUT_DIR)/cuda-sim.o: $(OUTPUT_DIR)/ptx.tab.c
+$(OUTPUT_DIR)/cuda-sim.o: $(OUTPUT_DIR)/ptx.tab.c $(SIM_OBJ_FILES_DIR)/detailed_version
$(OUTPUT_DIR)/lex.ptxinfo_.o: $(OUTPUT_DIR)/ptx.tab.c
$(OUTPUT_DIR)/lex.ptx_.o: $(OUTPUT_DIR)/ptx.tab.c
+$(OUTPUT_DIR)/cuda_device_runtime.o: $(OUTPUT_DIR)/ptx.tab.c
include $(OUTPUT_DIR)/Makefile.makedepend
diff --git a/src/cuda-sim/cuda-sim.cc b/src/cuda-sim/cuda-sim.cc
index 4bae236..b5b79e7 100644
--- a/src/cuda-sim/cuda-sim.cc
+++ b/src/cuda-sim/cuda-sim.cc
@@ -48,6 +48,7 @@
#include "../gpgpusim_entrypoint.h"
#include "decuda_pred_table/decuda_pred_table.h"
#include "../stream_manager.h"
+#include "cuda_device_runtime.h"
int gpgpu_ptx_instruction_classification;
void ** g_inst_classification_stat = NULL;
@@ -63,6 +64,8 @@ unsigned gpgpu_param_num_shaders = 0;
char *opcode_latency_int, *opcode_latency_fp, *opcode_latency_dp;
char *opcode_initiation_int, *opcode_initiation_fp, *opcode_initiation_dp;
+char *cdp_latency_str;
+unsigned cdp_latency[5];
void ptx_opcocde_latency_options (option_parser_t opp) {
option_parser_register(opp, "-ptx_opcode_latency_int", OPT_CSTR, &opcode_latency_int,
@@ -89,6 +92,12 @@ void ptx_opcocde_latency_options (option_parser_t opp) {
"Opcode initiation intervals for double precision floating points <ADD,MAX,MUL,MAD,DIV>"
"Default 8,8,8,8,130",
"8,8,8,8,130");
+ option_parser_register(opp, "-cdp_latency", OPT_CSTR, &cdp_latency_str,
+ "CDP API latency <cudaStreamCreateWithFlags, \
+cudaGetParameterBufferV2_init_perWarp, cudaGetParameterBufferV2_perKernel, \
+cudaLaunchDeviceV2_init_perWarp, cudaLaunchDevicV2_perKernel>"
+ "Default 7200,8000,100,12000,1600",
+ "7200,8000,100,12000,1600");
}
static address_type get_converge_point(address_type pc);
@@ -612,6 +621,9 @@ void ptx_instruction::set_opcode_and_latency()
sscanf(opcode_initiation_dp, "%u,%u,%u,%u,%u",
&dp_init[0],&dp_init[1],&dp_init[2],
&dp_init[3],&dp_init[4]);
+ sscanf(cdp_latency_str, "%u,%u,%u,%u,%u",
+ &cdp_latency[0],&cdp_latency[1],&cdp_latency[2],
+ &cdp_latency[3],&cdp_latency[4]);
if(!m_operands.empty()){
std::vector<operand_info>::iterator it;
@@ -643,19 +655,21 @@ void ptx_instruction::set_opcode_and_latency()
case MEMBAR_OP: op = MEMORY_BARRIER_OP; break;
case CALL_OP:
{
- if(m_is_printf)
+ if(m_is_printf || m_is_cdp) {
op = ALU_OP;
+ }
else
op = CALL_OPS;
break;
}
case CALLP_OP:
{
- if(m_is_printf)
+ if(m_is_printf || m_is_cdp) {
op = ALU_OP;
- else
- op = CALL_OPS;
- break;
+ }
+ else
+ op = CALL_OPS;
+ break;
}
case RET_OP: case RETP_OP: op = RET_OPS;break;
case ADD_OP: case ADDP_OP: case ADDC_OP: case SUB_OP: case SUBC_OP:
@@ -778,6 +792,10 @@ void ptx_instruction::set_opcode_and_latency()
latency = int_latency[5];
initiation_interval = int_init[5];
break;
+ case SHFL_OP:
+ latency = 32;
+ initiation_interval = 15;
+ break;
default:
break;
}
@@ -1076,6 +1094,32 @@ void function_info::add_param_data( unsigned argn, struct gpgpu_ptx_sim_arg *arg
}
}
+unsigned function_info::get_args_aligned_size() {
+
+ if(m_args_aligned_size >= 0)
+ return m_args_aligned_size;
+
+ unsigned param_address = 0;
+ unsigned int total_size = 0;
+ for( std::map<unsigned,param_info>::iterator i=m_ptx_kernel_param_info.begin(); i!=m_ptx_kernel_param_info.end(); i++ ) {
+ param_info &p = i->second;
+ std::string name = p.get_name();
+ symbol *param = m_symtab->lookup(name.c_str());
+
+ size_t arg_size = p.get_size() / 8; // size of param in bytes
+ total_size = (total_size + arg_size - 1) / arg_size * arg_size; //aligned
+ p.add_offset(total_size);
+ param->set_address(param_address + total_size);
+ total_size += arg_size;
+ }
+
+ m_args_aligned_size = (total_size + 3) / 4 * 4; //final size aligned to word
+
+ return m_args_aligned_size;
+
+}
+
+
void function_info::finalize( memory_space *param_mem )
{
unsigned param_address = 0;
@@ -1098,13 +1142,17 @@ void function_info::finalize( memory_space *param_mem )
size = (size<(p.get_size()/8))?size:(p.get_size()/8);
}
// copy the parameter over word-by-word so that parameter that crosses a memory page can be copied over
+ //Jin: copy parameter using aligned rules
const size_t word_size = 4;
+ param_address = (param_address + size - 1) / size * size; //aligned with size
for (size_t idx = 0; idx < size; idx += word_size) {
const char *pdata = reinterpret_cast<const char*>(param_value.pdata) + idx; // cast to char * for ptr arithmetic
param_mem->write(param_address + idx, word_size, pdata,NULL,NULL);
}
+ unsigned offset = p.get_offset();
+ assert(offset == param_address);
param->set_address(param_address);
- param_address += size;
+ param_address += size;
}
}
@@ -1471,7 +1519,8 @@ unsigned ptx_sim_init_thread( kernel_info_t &kernel,
unsigned max_cta_per_sm = num_threads/cta_size; // e.g., 256 / 48 = 5
assert( max_cta_per_sm > 0 );
- unsigned sm_idx = (tid/cta_size)*gpgpu_param_num_shaders + sid;
+ //unsigned sm_idx = (tid/cta_size)*gpgpu_param_num_shaders + sid;
+ unsigned sm_idx = hw_cta_id*gpgpu_param_num_shaders + sid;
if ( shared_memory_lookup.find(sm_idx) == shared_memory_lookup.end() ) {
if ( g_debug_execution >= 1 ) {
@@ -1506,7 +1555,6 @@ unsigned ptx_sim_init_thread( kernel_info_t &kernel,
kernel.increment_thread_id();
new_tid += tid;
ptx_thread_info *thd = new ptx_thread_info(kernel);
-
ptx_warp_info *warp_info = NULL;
if ( ptx_warp_lookup.find(hw_warp_id) == ptx_warp_lookup.end() ) {
warp_info = new ptx_warp_info();
@@ -1591,14 +1639,13 @@ kernel_info_t *gpgpu_opencl_ptx_sim_init_grid(class function_info *entry,
}
#include "../../version"
+#include "detailed_version"
void print_splash()
{
static int splash_printed=0;
if ( !splash_printed ) {
- unsigned build=0;
- sscanf(g_gpgpusim_build_string, "$Change"": %u $", &build);
- fprintf(stdout, "\n\n *** %s [build %u] ***\n\n\n", g_gpgpusim_version_string, build );
+ fprintf(stdout, "\n\n *** %s [build %s] ***\n\n\n", g_gpgpusim_version_string, g_gpgpusim_build_string );
splash_printed=1;
}
}
@@ -1777,14 +1824,19 @@ void gpgpu_cuda_ptx_sim_main_func( kernel_info_t &kernel, bool openCL )
g_the_gpu->getShaderCoreConfig()->warp_size
);
cta.execute();
+
+#if (CUDART_VERSION >= 5000)
+ launch_all_device_kernels();
+#endif
}
//registering this kernel as done
- extern stream_manager *g_stream_manager;
//openCL kernel simulation calls don't register the kernel so we don't register its exit
- if(!openCL)
- g_stream_manager->register_finished_kernel(kernel.get_uid());
+ if(!openCL) {
+ extern stream_manager *g_stream_manager;
+ g_stream_manager->register_finished_kernel(kernel.get_uid());
+ }
//******PRINTING*******
printf( "GPGPU-Sim: Done functional simulation (%u instructions simulated).\n", g_ptx_sim_num_insn );
diff --git a/src/cuda-sim/cuda_device_runtime.cc b/src/cuda-sim/cuda_device_runtime.cc
new file mode 100644
index 0000000..4a8ffe5
--- /dev/null
+++ b/src/cuda-sim/cuda_device_runtime.cc
@@ -0,0 +1,320 @@
+//Jin: cuda_device_runtime.cc
+//Defines CUDA device runtime APIs for CDP support
+
+
+#include <iostream>
+#include <map>
+
+unsigned long long g_total_param_size = 0;
+unsigned long long g_max_total_param_size = 0;
+
+
+#if (CUDART_VERSION >= 5000)
+#define __CUDA_RUNTIME_API_H__
+
+#include <builtin_types.h>
+#include <driver_types.h>
+#include "../gpgpu-sim/gpu-sim.h"
+#include "cuda-sim.h"
+#include "ptx_ir.h"
+#include "../stream_manager.h"
+#include "cuda_device_runtime.h"
+
+#define DEV_RUNTIME_REPORT(a) \
+ if( g_debug_execution ) { \
+ std::cout << __FILE__ << ", " << __LINE__ << ": " << a << "\n"; \
+ std::cout.flush(); \
+ }
+
+class device_launch_config_t {
+
+public:
+ device_launch_config_t() {}
+
+ device_launch_config_t(dim3 _grid_dim,
+ dim3 _block_dim,
+ unsigned int _shared_mem,
+ function_info * _entry):
+ grid_dim(_grid_dim),
+ block_dim(_block_dim),
+ shared_mem(_shared_mem),
+ entry(_entry) {}
+
+ dim3 grid_dim;
+ dim3 block_dim;
+ unsigned int shared_mem;
+ function_info * entry;
+
+};
+
+class device_launch_operation_t {
+
+public:
+ device_launch_operation_t() {}
+ device_launch_operation_t(kernel_info_t *_grid,
+ CUstream_st * _stream) :
+ grid(_grid), stream(_stream) {}
+
+ kernel_info_t * grid; //a new child grid
+
+ CUstream_st * stream;
+
+};
+
+
+std::map<void *, device_launch_config_t> g_cuda_device_launch_param_map;
+std::list<device_launch_operation_t> g_cuda_device_launch_op;
+extern stream_manager *g_stream_manager;
+
+//Handling device runtime api:
+//void * cudaGetParameterBufferV2(void *func, dim3 gridDimension, dim3 blockDimension, unsigned int sharedMemSize)
+void gpgpusim_cuda_getParameterBufferV2(const ptx_instruction * pI, ptx_thread_info * thread, const function_info * target_func)
+{
+ DEV_RUNTIME_REPORT("Calling cudaGetParameterBufferV2");
+
+ unsigned n_return = target_func->has_return();
+ assert(n_return);
+ unsigned n_args = target_func->num_args();
+ assert( n_args == 4 );
+
+ function_info * child_kernel_entry;
+ struct dim3 grid_dim, block_dim;
+ unsigned int shared_mem;
+
+ for( unsigned arg=0; arg < n_args; arg ++ ) {
+ const operand_info &actual_param_op = pI->operand_lookup(n_return+1+arg); //param#
+ const symbol *formal_param = target_func->get_arg(arg); //cudaGetParameterBufferV2_param_#
+ unsigned size=formal_param->get_size_in_bytes();
+ assert( formal_param->is_param_local() );
+ assert( actual_param_op.is_param_local() );
+ addr_t from_addr = actual_param_op.get_symbol()->get_address();
+
+ if(arg == 0) {//function_info* for the child kernel
+ unsigned long long buf;
+ assert(size == sizeof(function_info *));
+ thread->m_local_mem->read(from_addr, size, &buf);
+ child_kernel_entry = (function_info *)buf;
+ assert(child_kernel_entry);
+ DEV_RUNTIME_REPORT("child kernel name " << child_kernel_entry->get_name());
+ }
+ else if(arg == 1) { //dim3 grid_dim for the child kernel
+ assert(size == sizeof(struct dim3));
+ thread->m_local_mem->read(from_addr, size, & grid_dim);
+ DEV_RUNTIME_REPORT("grid (" << grid_dim.x << ", " << grid_dim.y << ", " << grid_dim.z << ")");
+ }
+ else if(arg == 2) { //dim3 block_dim for the child kernel
+ assert(size == sizeof(struct dim3));
+ thread->m_local_mem->read(from_addr, size, & block_dim);
+ DEV_RUNTIME_REPORT("block (" << block_dim.x << ", " << block_dim.y << ", " << block_dim.z << ")");
+ }
+ else if(arg == 3) { //unsigned int shared_mem
+ assert(size == sizeof(unsigned int));
+ thread->m_local_mem->read(from_addr, size, & shared_mem);
+ DEV_RUNTIME_REPORT("shared memory " << shared_mem);
+ }
+ }
+
+ //get total child kernel argument size and malloc buffer in global memory
+ unsigned child_kernel_arg_size = child_kernel_entry->get_args_aligned_size();
+ void * param_buffer = thread->get_gpu()->gpu_malloc(child_kernel_arg_size);
+ g_total_param_size += ((child_kernel_arg_size + 255) / 256 * 256);
+ DEV_RUNTIME_REPORT("child kernel arg size total " << child_kernel_arg_size << ", parameter buffer allocated at " << param_buffer);
+ if(g_total_param_size > g_max_total_param_size)
+ g_max_total_param_size = g_total_param_size;
+
+ //store param buffer address and launch config
+ device_launch_config_t device_launch_config(grid_dim, block_dim, shared_mem, child_kernel_entry);
+ assert(g_cuda_device_launch_param_map.find(param_buffer) == g_cuda_device_launch_param_map.end());
+ g_cuda_device_launch_param_map[param_buffer] = device_launch_config;
+
+ //copy the buffer address to retval0
+ const operand_info &actual_return_op = pI->operand_lookup(0); //retval0
+ const symbol *formal_return = target_func->get_return_var(); //void *
+ unsigned int return_size = formal_return->get_size_in_bytes();
+ DEV_RUNTIME_REPORT("cudaGetParameterBufferV2 return value has size of " << return_size);
+ assert(actual_return_op.is_param_local());
+ assert(actual_return_op.get_symbol()->get_size_in_bytes() == return_size && return_size == sizeof(void *));
+ addr_t ret_param_addr = actual_return_op.get_symbol()->get_address();
+ thread->m_local_mem->write(ret_param_addr, return_size, &param_buffer, NULL, NULL);
+
+}
+
+//Handling device runtime api:
+//cudaError_t cudaLaunchDeviceV2(void *parameterBuffer, cudaStream_t stream)
+void gpgpusim_cuda_launchDeviceV2(const ptx_instruction * pI, ptx_thread_info * thread, const function_info * target_func) {
+ DEV_RUNTIME_REPORT("Calling cudaLaunchDeviceV2");
+
+ unsigned n_return = target_func->has_return();
+ assert(n_return);
+ unsigned n_args = target_func->num_args();
+ assert( n_args == 2 );
+
+ kernel_info_t * device_grid = NULL;
+ function_info * device_kernel_entry = NULL;
+ void * parameter_buffer;
+ struct CUstream_st * child_stream;
+ device_launch_config_t config;
+ device_launch_operation_t device_launch_op;
+
+ for( unsigned arg=0; arg < n_args; arg ++ ) {
+ const operand_info &actual_param_op = pI->operand_lookup(n_return+1+arg); //param#
+ const symbol *formal_param = target_func->get_arg(arg); //cudaLaunchDeviceV2_param_#
+ unsigned size=formal_param->get_size_in_bytes();
+ assert( formal_param->is_param_local() );
+ assert( actual_param_op.is_param_local() );
+ addr_t from_addr = actual_param_op.get_symbol()->get_address();
+
+ if(arg == 0) {//paramter buffer for child kernel (in global memory)
+ //get parameter_buffer from the cudaLaunchDeviceV2_param0
+ assert(size == sizeof(void *));
+ thread->m_local_mem->read(from_addr, size, &parameter_buffer);
+ assert((size_t)parameter_buffer >= GLOBAL_HEAP_START);
+ DEV_RUNTIME_REPORT("Parameter buffer locating at global memory " << parameter_buffer);
+
+ //get child grid info through parameter_buffer address
+ assert(g_cuda_device_launch_param_map.find(parameter_buffer) != g_cuda_device_launch_param_map.end());
+ config = g_cuda_device_launch_param_map[parameter_buffer];
+ //device_grid = op.grid;
+ device_kernel_entry = config.entry;
+ DEV_RUNTIME_REPORT("find device kernel " << device_kernel_entry->get_name());
+
+ //copy data in parameter_buffer to device kernel param memory
+ unsigned device_kernel_arg_size = device_kernel_entry->get_args_aligned_size();
+ DEV_RUNTIME_REPORT("device_kernel_arg_size " << device_kernel_arg_size);
+ memory_space *device_kernel_param_mem;
+
+ //create child kernel_info_t and index it with parameter_buffer address
+ device_grid = new kernel_info_t(config.grid_dim, config.block_dim, device_kernel_entry);
+ device_grid->launch_cycle = gpu_sim_cycle + gpu_tot_sim_cycle;
+ kernel_info_t & parent_grid = thread->get_kernel();
+ DEV_RUNTIME_REPORT("child kernel launched by " << parent_grid.name() << ", cta (" <<
+ thread->get_ctaid().x << ", " << thread->get_ctaid().y << ", " << thread->get_ctaid().z <<
+ "), thread (" << thread->get_tid().x << ", " << thread->get_tid().y << ", " << thread->get_tid().z <<
+ ")");
+ device_grid->set_parent(&parent_grid, thread->get_ctaid(), thread->get_tid());
+ device_launch_op = device_launch_operation_t(device_grid, NULL);
+ device_kernel_param_mem = device_grid->get_param_memory(); //kernel param
+ size_t param_start_address = 0;
+ //copy in word
+ for(unsigned n = 0; n < device_kernel_arg_size; n += 4) {
+ unsigned int oneword;
+ thread->get_gpu()->get_global_memory()->read((size_t)parameter_buffer + n, 4, &oneword);
+ device_kernel_param_mem->write(param_start_address + n, 4, &oneword, NULL, NULL);
+ }
+ }
+ else if(arg == 1) { //cudaStream for the child kernel
+
+ assert(size == sizeof(cudaStream_t));
+ thread->m_local_mem->read(from_addr, size, &child_stream);
+
+ kernel_info_t & parent_kernel = thread->get_kernel();
+ if(child_stream == 0) { //default stream on device for current CTA
+ child_stream = parent_kernel.get_default_stream_cta(thread->get_ctaid());
+ DEV_RUNTIME_REPORT("launching child kernel " << device_grid->get_uid() <<
+ " to default stream of the cta " << child_stream->get_uid() << ": " << child_stream);
+ }
+ else {
+ assert(parent_kernel.cta_has_stream(thread->get_ctaid(), child_stream));
+ DEV_RUNTIME_REPORT("launching child kernel " << device_grid->get_uid() <<
+ " to stream " << child_stream->get_uid() << ": " << child_stream);
+ }
+
+ device_launch_op.stream = child_stream;
+ }
+
+ }
+
+
+ //launch child kernel
+ g_cuda_device_launch_op.push_back(device_launch_op);
+ g_cuda_device_launch_param_map.erase(parameter_buffer);
+
+ //set retval0
+ const operand_info &actual_return_op = pI->operand_lookup(0); //retval0
+ const symbol *formal_return = target_func->get_return_var(); //cudaError_t
+ unsigned int return_size = formal_return->get_size_in_bytes();
+ DEV_RUNTIME_REPORT("cudaLaunchDeviceV2 return value has size of " << return_size);
+ assert(actual_return_op.is_param_local());
+ assert(actual_return_op.get_symbol()->get_size_in_bytes() == return_size
+ && return_size == sizeof(cudaError_t));
+ cudaError_t error = cudaSuccess;
+ addr_t ret_param_addr = actual_return_op.get_symbol()->get_address();
+ thread->m_local_mem->write(ret_param_addr, return_size, &error, NULL, NULL);
+
+}
+
+
+//Handling device runtime api:
+//cudaError_t cudaStreamCreateWithFlags ( cudaStream_t* pStream, unsigned int flags)
+//flags can only be cudaStreamNonBlocking
+void gpgpusim_cuda_streamCreateWithFlags(const ptx_instruction * pI, ptx_thread_info * thread, const function_info * target_func) {
+ DEV_RUNTIME_REPORT("Calling cudaStreamCreateWithFlags");
+
+ unsigned n_return = target_func->has_return();
+ assert(n_return);
+ unsigned n_args = target_func->num_args();
+ assert( n_args == 2 );
+
+ size_t generic_pStream_addr;
+ addr_t pStream_addr;
+ unsigned int flags;
+ for( unsigned arg=0; arg < n_args; arg ++ ) {
+ const operand_info &actual_param_op = pI->operand_lookup(n_return+1+arg); //param#
+ const symbol *formal_param = target_func->get_arg(arg); //cudaStreamCreateWithFlags_param_#
+ unsigned size=formal_param->get_size_in_bytes();
+ assert( formal_param->is_param_local() );
+ assert( actual_param_op.is_param_local() );
+ addr_t from_addr = actual_param_op.get_symbol()->get_address();
+
+ if(arg == 0) {//cudaStream_t * pStream, address of cudaStream_t
+ assert(size == sizeof(cudaStream_t *));
+ thread->m_local_mem->read(from_addr, size, &generic_pStream_addr);
+
+ //pStream should be non-zero address in local memory
+ pStream_addr = generic_to_local(thread->get_hw_sid(), thread->get_hw_tid(), generic_pStream_addr);
+
+ DEV_RUNTIME_REPORT("pStream locating at local memory " << pStream_addr);
+ }
+ else if(arg == 1) { //unsigned int flags, should be cudaStreamNonBlocking
+ assert(size == sizeof(unsigned int));
+ thread->m_local_mem->read(from_addr, size, &flags);
+ assert(flags == cudaStreamNonBlocking);
+ }
+ }
+
+ //create stream and write back to param0
+ CUstream_st * stream = thread->get_kernel().create_stream_cta(thread->get_ctaid());
+ DEV_RUNTIME_REPORT("Create stream " << stream->get_uid() << ": " << stream);
+ thread->m_local_mem->write(pStream_addr, sizeof(cudaStream_t), &stream, NULL, NULL);
+
+ //set retval0
+ const operand_info &actual_return_op = pI->operand_lookup(0); //retval0
+ const symbol *formal_return = target_func->get_return_var(); //cudaError_t
+ unsigned int return_size = formal_return->get_size_in_bytes();
+ DEV_RUNTIME_REPORT("cudaStreamCreateWithFlags return value has size of " << return_size);
+ assert(actual_return_op.is_param_local());
+ assert(actual_return_op.get_symbol()->get_size_in_bytes() == return_size
+ && return_size == sizeof(cudaError_t));
+ cudaError_t error = cudaSuccess;
+ addr_t ret_param_addr = actual_return_op.get_symbol()->get_address();
+ thread->m_local_mem->write(ret_param_addr, return_size, &error, NULL, NULL);
+
+}
+
+
+void launch_one_device_kernel() {
+ if(!g_cuda_device_launch_op.empty()) {
+ device_launch_operation_t &op = g_cuda_device_launch_op.front();
+
+ stream_operation stream_op = stream_operation(op.grid, g_ptx_sim_mode, op.stream);
+ g_stream_manager->push(stream_op);
+ g_cuda_device_launch_op.pop_front();
+ }
+}
+
+void launch_all_device_kernels() {
+ while(!g_cuda_device_launch_op.empty()) {
+ launch_one_device_kernel();
+ }
+}
+#endif
diff --git a/src/cuda-sim/cuda_device_runtime.h b/src/cuda-sim/cuda_device_runtime.h
new file mode 100644
index 0000000..6dbcd71
--- /dev/null
+++ b/src/cuda-sim/cuda_device_runtime.h
@@ -0,0 +1,11 @@
+//Jin: cuda_device_runtime.h
+//Defines CUDA device runtime APIs for CDP support
+#if (CUDART_VERSION >= 5000)
+#pragma once
+
+void gpgpusim_cuda_getParameterBufferV2(const ptx_instruction * pI, ptx_thread_info * thread, const function_info * target_func);
+void gpgpusim_cuda_launchDeviceV2(const ptx_instruction * pI, ptx_thread_info * thread, const function_info * target_func);
+void gpgpusim_cuda_streamCreateWithFlags(const ptx_instruction * pI, ptx_thread_info * thread, const function_info * target_func);
+void launch_all_device_kernels();
+void launch_one_device_kernel();
+#endif
diff --git a/src/cuda-sim/instructions.cc b/src/cuda-sim/instructions.cc
index bb15621..159fd4c 100644
--- a/src/cuda-sim/instructions.cc
+++ b/src/cuda-sim/instructions.cc
@@ -41,6 +41,9 @@
#include "../gpgpu-sim/gpu-sim.h"
#include "../gpgpu-sim/shader.h"
+//Jin: include device runtime for CDP
+#include "cuda_device_runtime.h"
+
#include <stdarg.h>
unsigned ptx_instruction::g_num_ptx_inst_uid=0;
@@ -154,6 +157,8 @@ ptx_reg_t ptx_thread_info::get_operand_value( const operand_info &op, operand_in
result.u64 = op.get_symbol()->get_address();
} else if ( op.is_local() ) {
result.u64 = op.get_symbol()->get_address();
+ } else if ( op.is_function_address() ) {
+ result.u64 = (size_t)op.get_symbol()->get_pc();
} else {
const char *name = op.name().c_str();
printf("GPGPU-Sim PTX: ERROR ** get_operand_value : unknown operand type for %s\n", name );
@@ -1639,7 +1644,23 @@ void call_impl( const ptx_instruction *pI, ptx_thread_info *thread )
if( fname == "vprintf" ) {
gpgpusim_cuda_vprintf(pI, thread, target_func);
return;
- }
+ }
+
+#if (CUDART_VERSION >= 5000)
+ //Jin: handle device runtime apis for CDP
+ else if(fname == "cudaGetParameterBufferV2") {
+ gpgpusim_cuda_getParameterBufferV2(pI, thread, target_func);
+ return;
+ }
+ else if(fname == "cudaLaunchDeviceV2") {
+ gpgpusim_cuda_launchDeviceV2(pI, thread, target_func);
+ return;
+ }
+ else if(fname == "cudaStreamCreateWithFlags") {
+ gpgpusim_cuda_streamCreateWithFlags(pI, thread, target_func);
+ return;
+ }
+#endif
// read source arguements into register specified in declaration of function
arg_buffer_list_t arg_values;
@@ -3674,6 +3695,81 @@ void set_impl( const ptx_instruction *pI, ptx_thread_info *thread )
}
+void shfl_impl( const ptx_instruction *pI, core_t *core, warp_inst_t inst )
+{
+ unsigned i_type = pI->get_type();
+ int tid = inst.warp_id() * core->get_warp_size();
+ ptx_thread_info *thread = core->get_thread_info()[tid];
+ ptx_warp_info *warp_info = thread->m_warp_info;
+ int lane = warp_info->get_done_threads();
+ thread = core->get_thread_info()[tid + lane];
+
+ const operand_info &dst = pI->dst();
+ const operand_info &src1 = pI->src1();
+ const operand_info &src2 = pI->src2();
+ const operand_info &src3 = pI->src3();
+ int bval = (thread->get_operand_value(src2, dst, i_type, thread, 1)).u32;
+ int cval = (thread->get_operand_value(src3, dst, i_type, thread, 1)).u32;
+ int mask = cval >> 8;
+ bval &= 0x1F;
+ cval &= 0x1F;
+
+ int maxLane = (lane & mask) | (cval & ~mask);
+ int minLane = lane & mask;
+
+ int src_idx;
+ unsigned p;
+ switch(pI->shfl_op()) {
+ case UP_OPTION:
+ src_idx = lane - bval;
+ p = (src_idx >= maxLane);
+ break;
+ case DOWN_OPTION:
+ src_idx = lane + bval;
+ p = (src_idx <= maxLane);
+ break;
+ case BFLY_OPTION:
+ src_idx = lane ^ bval;
+ p = (src_idx <= maxLane);
+ break;
+ case IDX_OPTION:
+ src_idx = minLane | (bval & ~mask);
+ p = (src_idx <= maxLane);
+ break;
+ default:
+ printf("GPGPU-Sim PTX: ERROR: Invalid shfl option\n");
+ assert(0);
+ break;
+ }
+ // copy from own lane
+ if (!p) src_idx = lane;
+
+ // copy input from lane src_idx
+ ptx_reg_t data;
+ if (inst.active(src_idx)) {
+ ptx_thread_info *source = core->get_thread_info()[tid + src_idx];
+ data = source->get_operand_value(src1, dst, i_type, source, 1);
+ } else {
+ printf("GPGPU-Sim PTX: WARNING: shfl input value unpredictable for inactive threads in a warp\n");
+ data.u32 = 0;
+ }
+ thread->set_operand_value(dst, data, i_type, thread, pI);
+
+ /*
+ TODO: deal with predicates appropriately using the following pseudocode:
+ if (!isGuardPredicateTrue(src_idx)) {
+ printf("GPGPU-Sim PTX: WARNING: shfl input value unpredictable for predicated-off threads in a warp\n");
+ }
+ if (dest predicate selected) data.pred = p;
+ */
+
+ // keep track of the number of threads that have executed in the warp
+ warp_info->inc_done_threads();
+ if (warp_info->get_done_threads() == inst.active_count()) {
+ warp_info->reset_done_threads();
+ }
+}
+
void shl_impl( const ptx_instruction *pI, ptx_thread_info *thread )
{
ptx_reg_t a, b, d;
diff --git a/src/cuda-sim/opcodes.def b/src/cuda-sim/opcodes.def
index b363dca..41f2f22 100644
--- a/src/cuda-sim/opcodes.def
+++ b/src/cuda-sim/opcodes.def
@@ -99,6 +99,7 @@ OP_DEF(SAD_OP,sad_impl,"sad",1,1)
OP_DEF(SELP_OP,selp_impl,"selp",1,1)
OP_DEF(SETP_OP,setp_impl,"setp",1,1)
OP_DEF(SET_OP,set_impl,"set",1,1)
+OP_W_DEF(SHFL_OP,shfl_impl,"shfl",1,10)
OP_DEF(SHL_OP,shl_impl,"shl",1,1)
OP_DEF(SHR_OP,shr_impl,"shr",1,1)
OP_DEF(SIN_OP,sin_impl,"sin",1,4)
diff --git a/src/cuda-sim/ptx.l b/src/cuda-sim/ptx.l
index 001ec04..7620134 100644
--- a/src/cuda-sim/ptx.l
+++ b/src/cuda-sim/ptx.l
@@ -116,6 +116,7 @@ sad TC; ptx_lval.int_value = SAD_OP; return OPCODE;
selp TC; ptx_lval.int_value = SELP_OP; return OPCODE;
setp TC; ptx_lval.int_value = SETP_OP; return OPCODE;
set TC; ptx_lval.int_value = SET_OP; return OPCODE;
+shfl TC; ptx_lval.int_value = SHFL_OP; return OPCODE;
shl TC; ptx_lval.int_value = SHL_OP; return OPCODE;
shr TC; ptx_lval.int_value = SHR_OP; return OPCODE;
sin TC; ptx_lval.int_value = SIN_OP; return OPCODE;
@@ -186,6 +187,7 @@ breakaddr TC; ptx_lval.int_value = BREAKADDR_OP; return OPCODE;
\.union TC; return UNION_DIRECTIVE; /* not in PTX 2.1 */
\.version TC; return VERSION_DIRECTIVE;
\.visible TC; return VISIBLE_DIRECTIVE;
+\.weak TC; return WEAK_DIRECTIVE;
\.address_size TC; return ADDRESS_SIZE_DIRECTIVE;
\.weak TC; return WEAK_DIRECTIVE;
@@ -334,6 +336,11 @@ breakaddr TC; ptx_lval.int_value = BREAKADDR_OP; return OPCODE;
\.nc TC; return NC_OPTION;
+\.up TC; return UP_OPTION;
+\.down TC; return DOWN_OPTION;
+\.bfly TC; return BFLY_OPTION;
+\.idx TC; return IDX_OPTION;
+
\.popc TC; return ATOMIC_POPC;
\.and TC; return ATOMIC_AND;
\.or TC; return ATOMIC_OR;
diff --git a/src/cuda-sim/ptx.y b/src/cuda-sim/ptx.y
index 97f4ff2..3360c55 100644
--- a/src/cuda-sim/ptx.y
+++ b/src/cuda-sim/ptx.y
@@ -73,6 +73,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
%token VERSION_DIRECTIVE
%token ADDRESS_SIZE_DIRECTIVE
%token VISIBLE_DIRECTIVE
+%token WEAK_DIRECTIVE
%token <string_value> IDENTIFIER
%token <int_value> INT_OPERAND
%token <float_value> FLOAT_OPERAND
@@ -195,6 +196,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
%token WB_OPTION;
%token WT_OPTION;
%token NC_OPTION;
+%token UP_OPTION;
+%token DOWN_OPTION;
+%token BFLY_OPTION;
+%token IDX_OPTION;
%type <int_value> function_decl_header
%type <ptr_value> function_decl
@@ -244,10 +249,12 @@ function_ident_param: IDENTIFIER { add_function_name($1); } LEFT_PAREN {func_hea
function_decl_header: ENTRY_DIRECTIVE { $$ = 1; g_func_decl=1; func_header(".entry"); }
| VISIBLE_DIRECTIVE ENTRY_DIRECTIVE { $$ = 1; g_func_decl=1; func_header(".entry"); }
+ | WEAK_DIRECTIVE ENTRY_DIRECTIVE { $$ = 1; g_func_decl=1; func_header(".entry"); }
| FUNC_DIRECTIVE { $$ = 0; g_func_decl=1; func_header(".func"); }
| VISIBLE_DIRECTIVE FUNC_DIRECTIVE { $$ = 0; g_func_decl=1; func_header(".func"); }
| WEAK_DIRECTIVE FUNC_DIRECTIVE { $$ = 0; g_func_decl=1; func_header(".func"); }
| EXTERN_DIRECTIVE FUNC_DIRECTIVE { $$ = 2; g_func_decl=1; func_header(".func"); }
+ | WEAK_DIRECTIVE FUNC_DIRECTIVE { $$ = 0; g_func_decl=1; func_header(".func"); }
;
param_list: /*empty*/
@@ -273,8 +280,8 @@ statement_list: directive_statement { add_directive(); }
| instruction_statement { add_instruction(); }
| statement_list directive_statement { add_directive(); }
| statement_list instruction_statement { add_instruction(); }
- | statement_list statement_block
- | statement_block
+ | statement_list {start_inst_group();} statement_block {end_inst_group();}
+ | {start_inst_group();} statement_block {end_inst_group();}
;
directive_statement: variable_declaration SEMI_COLON
@@ -326,6 +333,7 @@ var_spec: space_spec
| type_spec
| align_spec
| EXTERN_DIRECTIVE { add_extern_spec(); }
+ | WEAK_DIRECTIVE
;
align_spec: ALIGN_DIRECTIVE INT_OPERAND { add_alignment_spec($2); }
@@ -453,6 +461,10 @@ option: type_spec
| WB_OPTION { add_option(WB_OPTION); }
| WT_OPTION { add_option(WT_OPTION); }
| NC_OPTION { add_option(NC_OPTION); }
+ | UP_OPTION { add_option(UP_OPTION); }
+ | DOWN_OPTION { add_option(DOWN_OPTION); }
+ | BFLY_OPTION { add_option(BFLY_OPTION); }
+ | IDX_OPTION { add_option(IDX_OPTION); }
;
atomic_operation_spec: ATOMIC_AND { add_option(ATOMIC_AND); }
diff --git a/src/cuda-sim/ptx_ir.cc b/src/cuda-sim/ptx_ir.cc
index 2eccabc..8ebdcf8 100644
--- a/src/cuda-sim/ptx_ir.cc
+++ b/src/cuda-sim/ptx_ir.cc
@@ -90,6 +90,11 @@ symbol_table::symbol_table( const char *scope_name, unsigned entry_point, symbol
m_const_next = 0;
m_global_next = 0x100;
m_local_next = 0;
+ m_tex_next = 0;
+
+ //Jin: handle instruction group for cdp
+ m_inst_group_id = 0;
+
m_parent = parent;
if ( m_parent ) {
m_shared_next = m_parent->m_shared_next;
@@ -170,6 +175,41 @@ void symbol_table::add_function( function_info *func, const char *filename, unsi
m_symbols[ func->get_name() ] = s;
}
+//Jin: handle instruction group for cdp
+symbol_table* symbol_table::start_inst_group() {
+ char inst_group_name[1024];
+ snprintf(inst_group_name, 1024, "%s_inst_group_%u", m_scope_name.c_str(), m_inst_group_id);
+
+ //previous added
+ assert(m_inst_group_symtab.find(std::string(inst_group_name)) == m_inst_group_symtab.end());
+ symbol_table *sym_table = new symbol_table(inst_group_name, 3/*inst group*/, this );
+
+ sym_table->m_global_next = m_global_next;
+ sym_table->m_shared_next = m_shared_next;
+ sym_table->m_local_next = m_local_next;
+ sym_table->m_reg_allocator = m_reg_allocator;
+ sym_table->m_tex_next = m_tex_next;
+ sym_table->m_const_next = m_const_next;
+
+ m_inst_group_symtab[std::string(inst_group_name)] = sym_table;
+
+ return sym_table;
+}
+
+symbol_table * symbol_table::end_inst_group() {
+ symbol_table * sym_table = m_parent;
+
+ sym_table->m_global_next = m_global_next;
+ sym_table->m_shared_next = m_shared_next;
+ sym_table->m_local_next = m_local_next;
+ sym_table->m_reg_allocator = m_reg_allocator;
+ sym_table->m_tex_next = m_tex_next;
+ sym_table->m_const_next = m_const_next;
+ sym_table->m_inst_group_id++;
+
+ return sym_table;
+}
+
void register_ptx_function( const char *name, function_info *impl ); // either libcuda or libopencl
bool symbol_table::add_function_decl( const char *name, int entry_point, function_info **func_info, symbol_table **sym_table )
@@ -458,7 +498,7 @@ void function_info::connect_basic_blocks( ) //iterate across m_basic_blocks of f
if( pI->has_pred() ) {
printf("GPGPU-Sim PTX: Warning detected predicated return/exit.\n");
// if predicated, add link to next block
- unsigned next_addr = pI->get_m_instr_mem_index() + 1;
+ unsigned next_addr = pI->get_m_instr_mem_index() + pI->inst_size();
if( next_addr < m_instr_mem_size && m_instr_mem[next_addr] ) {
basic_block_t *next_bb = m_instr_mem[next_addr]->get_bb();
(*bb_itr)->successor_ids.insert(next_bb->bb_id);
@@ -1171,6 +1211,12 @@ ptx_instruction::ptx_instruction( int opcode,
break;
case NC_OPTION:
break;
+ case UP_OPTION:
+ case DOWN_OPTION:
+ case BFLY_OPTION:
+ case IDX_OPTION:
+ m_shfl_op = last_ptx_inst_option;
+ break;
default:
assert(0);
break;
@@ -1205,6 +1251,12 @@ ptx_instruction::ptx_instruction( int opcode,
if (fname =="vprintf"){
m_is_printf = true;
}
+ if(fname == "cudaStreamCreateWithFlags")
+ m_is_cdp = 1;
+ if(fname == "cudaGetParameterBufferV2")
+ m_is_cdp = 2;
+ if(fname == "cudaLaunchDeviceV2")
+ m_is_cdp = 4;
}
}
@@ -1252,6 +1304,7 @@ function_info::function_info(int entry_point )
m_kernel_info.regs = 0;
m_kernel_info.smem = 0;
m_local_mem_framesize = 0;
+ m_args_aligned_size = -1;
}
unsigned function_info::print_insn( unsigned pc, FILE * fp ) const
diff --git a/src/cuda-sim/ptx_ir.h b/src/cuda-sim/ptx_ir.h
index 7724443..4c10373 100644
--- a/src/cuda-sim/ptx_ir.h
+++ b/src/cuda-sim/ptx_ir.h
@@ -293,6 +293,7 @@ private:
std::list<operand_info> m_initializer;
static unsigned sm_next_uid;
+
};
class symbol_table {
@@ -334,6 +335,11 @@ public:
iterator const_iterator_end() { return m_consts.end();}
void dump();
+
+ //Jin: handle instruction group for cdp
+ symbol_table* start_inst_group();
+ symbol_table* end_inst_group();
+
private:
unsigned m_reg_allocator;
unsigned m_shared_next;
@@ -352,6 +358,10 @@ private:
std::list<symbol*> m_consts;
std::map<std::string,function_info*> m_function_info_lookup;
std::map<std::string,symbol_table*> m_function_symtab_lookup;
+
+ //Jin: handle instruction group for cdp
+ unsigned m_inst_group_id;
+ std::map<std::string,symbol_table*> m_inst_group_symtab;
};
class operand_info {
@@ -695,7 +705,7 @@ public:
}
bool is_immediate_address() const {
- return m_immediate_address;
+ return m_immediate_address;
}
bool is_literal() const { return m_type == int_t ||
@@ -999,6 +1009,7 @@ public:
unsigned saturation_mode() const { return m_saturation_mode;}
unsigned dimension() const { return m_geom_spec;}
unsigned barrier_op() const {return m_barrier_op;}
+ unsigned shfl_op() const {return m_shfl_op;}
enum vote_mode_t { vote_any, vote_all, vote_uni, vote_ballot };
enum vote_mode_t vote_mode() const { return m_vote_mode; }
@@ -1064,6 +1075,7 @@ private:
unsigned m_compare_op;
unsigned m_saturation_mode;
unsigned m_barrier_op;
+ unsigned m_shfl_op;
std::list<int> m_scalar_type;
memory_space_t m_space_spec;
@@ -1206,6 +1218,8 @@ public:
{
return m_args.size();
}
+ unsigned get_args_aligned_size();
+
const symbol* get_arg( unsigned n ) const
{
assert( n < m_args.size() );
@@ -1294,6 +1308,9 @@ private:
static std::vector<ptx_instruction*> s_g_pc_to_insn; // a direct mapping from PC to instruction
static unsigned sm_next_uid;
+
+ //parameter size for device kernels
+ int m_args_aligned_size;
};
class arg_buffer_t {
diff --git a/src/cuda-sim/ptx_loader.cc b/src/cuda-sim/ptx_loader.cc
index 9bb5008..6c1b595 100644
--- a/src/cuda-sim/ptx_loader.cc
+++ b/src/cuda-sim/ptx_loader.cc
@@ -322,7 +322,11 @@ void gpgpu_ptxinfo_load_from_string( const char *p_for_info, unsigned source_num
#if CUDART_VERSION >= 3000
if (sm_version == 0) sm_version = 20;
- snprintf(extra_flags,1024,"--gpu-name=sm_%u",sm_version);
+ extern bool g_cdp_enabled;
+ if(!g_cdp_enabled)
+ snprintf(extra_flags,1024,"--gpu-name=sm_%u",sm_version);
+ else
+ snprintf(extra_flags,1024,"--compile-only --gpu-name=sm_%u",sm_version);
#endif
snprintf(commandline,1024,"$CUDA_INSTALL_PATH/bin/ptxas %s -v %s --output-file /dev/null 2> %s",
diff --git a/src/cuda-sim/ptx_parser.cc b/src/cuda-sim/ptx_parser.cc
index a53a8fe..7fc54e9 100644
--- a/src/cuda-sim/ptx_parser.cc
+++ b/src/cuda-sim/ptx_parser.cc
@@ -120,6 +120,20 @@ symbol_table *init_parser( const char *ptx_filename )
#define DEF(X,Y) g_ptx_token_decode[X] = Y;
#include "ptx_parser_decode.def"
#undef DEF
+ g_ptx_token_decode[undefined_space] = "undefined_space";
+ g_ptx_token_decode[undefined_space] = "undefined_space=0";
+ g_ptx_token_decode[reg_space] = "reg_space";
+ g_ptx_token_decode[local_space] = "local_space";
+ g_ptx_token_decode[shared_space] = "shared_space";
+ g_ptx_token_decode[param_space_unclassified] = "param_space_unclassified";
+ g_ptx_token_decode[param_space_kernel] = "param_space_kernel";
+ g_ptx_token_decode[param_space_local] = "param_space_local";
+ g_ptx_token_decode[const_space] = "const_space";
+ g_ptx_token_decode[tex_space] = "tex_space";
+ g_ptx_token_decode[surf_space] = "surf_space";
+ g_ptx_token_decode[global_space] = "global_space";
+ g_ptx_token_decode[generic_space] = "generic_space";
+ g_ptx_token_decode[instruction_space] = "instruction_space";
return g_global_symbol_table;
}
@@ -187,6 +201,17 @@ void add_function_name( const char *name )
g_global_symbol_table->add_function( g_func_info, g_filename, ptx_lineno );
}
+//Jin: handle instruction group for cdp
+void start_inst_group() {
+ PTX_PARSE_DPRINTF("start_instruction_group");
+ g_current_symbol_table = g_current_symbol_table->start_inst_group();
+}
+
+void end_inst_group() {
+ PTX_PARSE_DPRINTF("end_instruction_group");
+ g_current_symbol_table = g_current_symbol_table->end_inst_group();
+}
+
void add_directive()
{
PTX_PARSE_DPRINTF("add_directive");
diff --git a/src/cuda-sim/ptx_parser.h b/src/cuda-sim/ptx_parser.h
index fef7635..32f3903 100644
--- a/src/cuda-sim/ptx_parser.h
+++ b/src/cuda-sim/ptx_parser.h
@@ -94,6 +94,10 @@ void change_operand_neg( );
void set_immediate_operand_type( );
void version_header(double a);
+//Jin: handle instructino group for cdp
+void start_inst_group();
+void end_inst_group();
+
#define NON_ARRAY_IDENTIFIER 1
#define ARRAY_IDENTIFIER_NO_DIM 2
#define ARRAY_IDENTIFIER 3
diff --git a/src/cuda-sim/ptx_sim.h b/src/cuda-sim/ptx_sim.h
index c62fa57..05acf20 100644
--- a/src/cuda-sim/ptx_sim.h
+++ b/src/cuda-sim/ptx_sim.h
@@ -433,6 +433,9 @@ public:
void or_reduction(unsigned ctaid, unsigned barid, bool value) {m_core->or_reduction(ctaid,barid,value);}
void popc_reduction(unsigned ctaid, unsigned barid, bool value) {m_core->popc_reduction(ctaid,barid,value);}
+ //Jin: get corresponding kernel grid for CDP purpose
+ kernel_info_t & get_kernel() { return m_kernel; }
+
public:
addr_t m_last_effective_address;
bool m_branch_taken;
diff --git a/src/cuda-sim/ptxinfo.y b/src/cuda-sim/ptxinfo.y
index 37092f4..d241d8c 100644
--- a/src/cuda-sim/ptxinfo.y
+++ b/src/cuda-sim/ptxinfo.y
@@ -94,6 +94,7 @@ line: HEADER INFO COLON line_info
line_info: function_name
| function_info { ptxinfo_addinfo(); }
+ | gmem_info
;
function_name: FUNC QUOTE IDENTIFIER QUOTE { ptxinfo_function($3); }
@@ -104,6 +105,9 @@ function_info: info
| function_info COMMA info
;
+gmem_info: INT_OPERAND BYTES GMEM
+ ;
+
info: USED INT_OPERAND REGS { ptxinfo_regs($2); }
| tuple LMEM { ptxinfo_lmem(g_declared,g_system); }
| tuple SMEM { ptxinfo_smem(g_declared,g_system); }
diff --git a/src/gpgpu-sim/Makefile b/src/gpgpu-sim/Makefile
index bead38a..f10a8a4 100644
--- a/src/gpgpu-sim/Makefile
+++ b/src/gpgpu-sim/Makefile
@@ -59,6 +59,7 @@ ifneq ($(GPGPUSIM_POWER_MODEL),)
endif
OPTFLAGS += -g3 -fPIC
+OPTFLAGS += -DCUDART_VERSION=$(CUDART_VERSION)
CPP = g++ $(SNOW)
OEXT = o
diff --git a/src/gpgpu-sim/gpu-sim.cc b/src/gpgpu-sim/gpu-sim.cc
index e7ba8e5..3bd1892 100644
--- a/src/gpgpu-sim/gpu-sim.cc
+++ b/src/gpgpu-sim/gpu-sim.cc
@@ -61,6 +61,7 @@
#include "power_stat.h"
#include "visualizer.h"
#include "stats.h"
+#include "../cuda-sim/cuda_device_runtime.h"
#ifdef GPGPUSIM_POWER_MODEL
#include "power_interface.h"
@@ -366,6 +367,10 @@ void shader_core_config::reg_options(class OptionParser * opp)
"For complete list of prioritization values see shader.h enum scheduler_prioritization_type"
"Default: gto",
"gto");
+
+ option_parser_register(opp, "-gpgpu_concurrent_kernel_sm", OPT_BOOL, &gpgpu_concurrent_kernel_sm,
+ "Support concurrent kernels on a SM (default = disabled)",
+ "0");
}
void gpgpu_sim_config::reg_options(option_parser_t opp)
@@ -438,6 +443,16 @@ void gpgpu_sim_config::reg_options(option_parser_t opp)
&Trace::sampling_memory_partition, "The memory partition which is printed using MEMPART_DPRINTF. Default -1 (i.e. all)",
"-1");
ptx_file_line_stats_options(opp);
+
+ //Jin: kernel launch latency
+ extern unsigned g_kernel_launch_latency;
+ option_parser_register(opp, "-gpgpu_kernel_launch_latency", OPT_INT32,
+ &g_kernel_launch_latency, "Kernel launch latency in cycles. Default: 0",
+ "0");
+ extern bool g_cdp_enabled;
+ option_parser_register(opp, "-gpgpu_cdp_enabled", OPT_BOOL,
+ &g_cdp_enabled, "Turn on CDP",
+ "0");
}
/////////////////////////////////////////////////////////////////////////////
@@ -518,16 +533,27 @@ bool gpgpu_sim::get_more_cta_left() const
kernel_info_t *gpgpu_sim::select_kernel()
{
+ if(m_running_kernels[m_last_issued_kernel] &&
+ !m_running_kernels[m_last_issued_kernel]->no_more_ctas_to_run()) {
+ unsigned launch_uid = m_running_kernels[m_last_issued_kernel]->get_uid();
+ if(std::find(m_executed_kernel_uids.begin(), m_executed_kernel_uids.end(), launch_uid) == m_executed_kernel_uids.end()) {
+ m_running_kernels[m_last_issued_kernel]->start_cycle = gpu_sim_cycle + gpu_tot_sim_cycle;
+ m_executed_kernel_uids.push_back(launch_uid);
+ m_executed_kernel_names.push_back(m_running_kernels[m_last_issued_kernel]->name());
+ }
+ return m_running_kernels[m_last_issued_kernel];
+ }
+
for(unsigned n=0; n < m_running_kernels.size(); n++ ) {
unsigned idx = (n+m_last_issued_kernel+1)%m_config.max_concurrent_kernel;
if( kernel_more_cta_left(m_running_kernels[idx]) ){
m_last_issued_kernel=idx;
+ m_running_kernels[idx]->start_cycle = gpu_sim_cycle + gpu_tot_sim_cycle;
// record this kernel for stat print if it is the first time this kernel is selected for execution
unsigned launch_uid = m_running_kernels[idx]->get_uid();
- if (std::find(m_executed_kernel_uids.begin(), m_executed_kernel_uids.end(), launch_uid) == m_executed_kernel_uids.end()) {
- m_executed_kernel_uids.push_back(launch_uid);
- m_executed_kernel_names.push_back(m_running_kernels[idx]->name());
- }
+ assert(std::find(m_executed_kernel_uids.begin(), m_executed_kernel_uids.end(), launch_uid) == m_executed_kernel_uids.end());
+ m_executed_kernel_uids.push_back(launch_uid);
+ m_executed_kernel_names.push_back(m_running_kernels[idx]->name());
return m_running_kernels[idx];
}
@@ -551,6 +577,7 @@ void gpgpu_sim::set_kernel_done( kernel_info_t *kernel )
std::vector<kernel_info_t*>::iterator k;
for( k=m_running_kernels.begin(); k!=m_running_kernels.end(); k++ ) {
if( *k == kernel ) {
+ kernel->end_cycle = gpu_sim_cycle + gpu_tot_sim_cycle;
*k = NULL;
break;
}
@@ -622,6 +649,10 @@ gpgpu_sim::gpgpu_sim( const gpgpu_sim_config &config )
*active_sms=0;
last_liveness_message_time = 0;
+
+ //Jin: functional simulation for CDP
+ m_functional_sim = false;
+ m_functional_sim_kernel = NULL;
}
int gpgpu_sim::shared_mem_size() const
@@ -927,7 +958,8 @@ void gpgpu_sim::gpu_print_stat()
printf("gpu_tot_ipc = %12.4f\n", (float)(gpu_tot_sim_insn+gpu_sim_insn) / (gpu_tot_sim_cycle+gpu_sim_cycle));
printf("gpu_tot_issued_cta = %lld\n", gpu_tot_issued_cta + m_total_cta_launched);
-
+ extern unsigned long long g_max_total_param_size;
+ fprintf(statfout, "max_total_param_size = %llu\n", g_max_total_param_size);
// performance counter for stalls due to congestion.
printf("gpu_stall_dramfull = %d\n", gpu_stall_dramfull);
@@ -1073,7 +1105,119 @@ void shader_core_ctx::mem_instruction_stats(const warp_inst_t &inst)
abort();
}
}
+bool shader_core_ctx::can_issue_1block(kernel_info_t & kernel) {
+
+ //Jin: concurrent kernels on one SM
+ if(m_config->gpgpu_concurrent_kernel_sm) {
+ if(m_config->max_cta(kernel) < 1)
+ return false;
+
+ return occupy_shader_resource_1block(kernel, false);
+ }
+ else {
+ return (get_n_active_cta() < m_config->max_cta(kernel));
+ }
+}
+
+int shader_core_ctx::find_available_hwtid(unsigned int cta_size, bool occupy) {
+
+ unsigned int step;
+ for(step = 0; step < m_config->n_thread_per_shader;
+ step += cta_size) {
+
+ unsigned int hw_tid;
+ for(hw_tid = step; hw_tid < step + cta_size;
+ hw_tid++) {
+ if(m_occupied_hwtid.test(hw_tid))
+ break;
+ }
+ if(hw_tid == step + cta_size) //consecutive non-active
+ break;
+ }
+ if(step >= m_config->n_thread_per_shader) //didn't find
+ return -1;
+ else {
+ if(occupy) {
+ for(unsigned hw_tid = step; hw_tid < step + cta_size;
+ hw_tid++)
+ m_occupied_hwtid.set(hw_tid);
+ }
+ return step;
+ }
+}
+
+bool shader_core_ctx::occupy_shader_resource_1block(kernel_info_t & k, bool occupy) {
+ unsigned threads_per_cta = k.threads_per_cta();
+ const class function_info *kernel = k.entry();
+ unsigned int padded_cta_size = threads_per_cta;
+ unsigned int warp_size = m_config->warp_size;
+ if (padded_cta_size%warp_size)
+ padded_cta_size = ((padded_cta_size/warp_size)+1)*(warp_size);
+
+ if(m_occupied_n_threads + padded_cta_size > m_config->n_thread_per_shader)
+ return false;
+ if(find_available_hwtid(padded_cta_size, false) == -1)
+ return false;
+
+ const struct gpgpu_ptx_sim_info *kernel_info = ptx_sim_kernel_info(kernel);
+
+ if(m_occupied_shmem + kernel_info->smem > m_config->gpgpu_shmem_size)
+ return false;
+
+ unsigned int used_regs = padded_cta_size * ((kernel_info->regs+3)&~3);
+ if(m_occupied_regs + used_regs > m_config->gpgpu_shader_registers)
+ return false;
+
+ if(m_occupied_ctas +1 > m_config->max_cta_per_core)
+ return false;
+
+ if(occupy) {
+ m_occupied_n_threads += padded_cta_size;
+ m_occupied_shmem += kernel_info->smem;
+ m_occupied_regs += (padded_cta_size * ((kernel_info->regs+3)&~3));
+ m_occupied_ctas++;
+
+ printf("GPGPU-Sim uArch: Shader %d occupied %d threads, %d shared mem, %d registers, %d ctas\n",
+ m_sid, m_occupied_n_threads, m_occupied_shmem, m_occupied_regs, m_occupied_ctas);
+ }
+
+ return true;
+}
+
+void shader_core_ctx::release_shader_resource_1block(unsigned hw_ctaid, kernel_info_t & k) {
+
+ if(m_config->gpgpu_concurrent_kernel_sm) {
+ unsigned threads_per_cta = k.threads_per_cta();
+ const class function_info *kernel = k.entry();
+ unsigned int padded_cta_size = threads_per_cta;
+ unsigned int warp_size = m_config->warp_size;
+ if (padded_cta_size%warp_size)
+ padded_cta_size = ((padded_cta_size/warp_size)+1)*(warp_size);
+
+ assert(m_occupied_n_threads >= padded_cta_size);
+ m_occupied_n_threads -= padded_cta_size;
+
+ int start_thread = m_occupied_cta_to_hwtid[hw_ctaid];
+
+ for(unsigned hwtid = start_thread; hwtid < start_thread + padded_cta_size;
+ hwtid++)
+ m_occupied_hwtid.reset(hwtid);
+ m_occupied_cta_to_hwtid.erase(hw_ctaid);
+
+ const struct gpgpu_ptx_sim_info *kernel_info = ptx_sim_kernel_info(kernel);
+
+ assert(m_occupied_shmem >= (unsigned int)kernel_info->smem);
+ m_occupied_shmem -= kernel_info->smem;
+
+ unsigned int used_regs = padded_cta_size * ((kernel_info->regs+3)&~3);
+ assert(m_occupied_regs >= used_regs);
+ m_occupied_regs -= used_regs;
+
+ assert(m_occupied_ctas >= 1);
+ m_occupied_ctas--;
+ }
+}
////////////////////////////////////////////////////////////////////////////////////////////////
@@ -1086,11 +1230,23 @@ void shader_core_ctx::mem_instruction_stats(const warp_inst_t &inst)
void shader_core_ctx::issue_block2core( kernel_info_t &kernel )
{
- set_max_cta(kernel);
+
+ if(!m_config->gpgpu_concurrent_kernel_sm)
+ set_max_cta(kernel);
+ else
+ assert(occupy_shader_resource_1block(kernel, true));
+
+ kernel.inc_running();
// find a free CTA context
unsigned free_cta_hw_id=(unsigned)-1;
- for (unsigned i=0;i<kernel_max_cta_per_shader;i++ ) {
+
+ unsigned max_cta_per_core;
+ if(!m_config->gpgpu_concurrent_kernel_sm)
+ max_cta_per_core = kernel_max_cta_per_shader;
+ else
+ max_cta_per_core = m_config->max_cta_per_core;
+ for (unsigned i=0;i<max_cta_per_core;i++ ) {
if( m_cta_status[i]==0 ) {
free_cta_hw_id=i;
break;
@@ -1107,8 +1263,20 @@ void shader_core_ctx::issue_block2core( kernel_info_t &kernel )
int padded_cta_size = cta_size;
if (cta_size%m_config->warp_size)
padded_cta_size = ((cta_size/m_config->warp_size)+1)*(m_config->warp_size);
- unsigned start_thread = free_cta_hw_id * padded_cta_size;
- unsigned end_thread = start_thread + cta_size;
+
+ unsigned int start_thread, end_thread;
+
+ if(!m_config->gpgpu_concurrent_kernel_sm) {
+ start_thread = free_cta_hw_id * padded_cta_size;
+ end_thread = start_thread + cta_size;
+ }
+ else {
+ start_thread = find_available_hwtid(padded_cta_size, true);
+ assert((int)start_thread != -1);
+ end_thread = start_thread + cta_size;
+ assert(m_occupied_cta_to_hwtid.find(free_cta_hw_id) == m_occupied_cta_to_hwtid.end());
+ m_occupied_cta_to_hwtid[free_cta_hw_id]= start_thread;
+ }
// reset the microarchitecture state of the selected hardware thread and warp contexts
reinit(start_thread, end_thread,false);
@@ -1136,7 +1304,9 @@ void shader_core_ctx::issue_block2core( kernel_info_t &kernel )
m_n_active_cta++;
shader_CTA_count_log(m_sid, 1);
- printf("GPGPU-Sim uArch: core:%3d, cta:%2u initialized @(%lld,%lld)\n", m_sid, free_cta_hw_id, gpu_sim_cycle, gpu_tot_sim_cycle );
+ printf("GPGPU-Sim uArch: core:%3d, cta:%2u, start_tid:%4u, end_tid:%4u, initialized @(%lld,%lld)\n",
+ m_sid, free_cta_hw_id, start_thread, end_thread, gpu_sim_cycle, gpu_tot_sim_cycle );
+
}
///////////////////////////////////////////////////////////////////////////////////////////
@@ -1369,6 +1539,11 @@ void gpgpu_sim::cycle()
}
try_snap_shot(gpu_sim_cycle);
spill_log_to_file (stdout, 0, gpu_sim_cycle);
+
+#if (CUDART_VERSION >= 5000)
+ //launch device kernel
+ launch_one_device_kernel();
+#endif
}
}
diff --git a/src/gpgpu-sim/gpu-sim.h b/src/gpgpu-sim/gpu-sim.h
index 33fffd3..7d92c66 100644
--- a/src/gpgpu-sim/gpu-sim.h
+++ b/src/gpgpu-sim/gpu-sim.h
@@ -195,7 +195,7 @@ struct memory_config {
for (i=0; nbkt>0; i++) {
nbkt = nbkt>>1;
}
- bk_tag_length = i;
+ bk_tag_length = i-1;
assert(nbkgrp>0 && "Number of bank groups cannot be zero");
tRCDWR = tRCD-(WL+1);
tRTW = (CL+(BL/data_command_freq_ratio)+2-WL);
@@ -492,6 +492,7 @@ private:
std::string executed_kernel_info_string(); //< format the kernel information into a string for stat printout
void clear_executed_kernel_info(); //< clear the kernel information after stat printout
+
public:
unsigned long long gpu_sim_insn;
unsigned long long gpu_tot_sim_insn;
@@ -504,6 +505,25 @@ public:
void change_cache_config(FuncCache cache_config);
void set_cache_config(std::string kernel_name);
+ //Jin: functional simulation for CDP
+private:
+ //set by stream operation every time a functoinal simulation is done
+ bool m_functional_sim;
+ kernel_info_t * m_functional_sim_kernel;
+
+public:
+ bool is_functional_sim() { return m_functional_sim; }
+ kernel_info_t * get_functional_kernel() { return m_functional_sim_kernel; }
+ void functional_launch(kernel_info_t * k) {
+ m_functional_sim = true;
+ m_functional_sim_kernel = k;
+ }
+ void finish_functional_sim(kernel_info_t * k) {
+ assert(m_functional_sim);
+ assert(m_functional_sim_kernel == k);
+ m_functional_sim = false;
+ m_functional_sim_kernel = NULL;
+ }
};
#endif
diff --git a/src/gpgpu-sim/shader.cc b/src/gpgpu-sim/shader.cc
index 9c3f816..92cdb5b 100644
--- a/src/gpgpu-sim/shader.cc
+++ b/src/gpgpu-sim/shader.cc
@@ -296,6 +296,14 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu,
m_last_inst_gpu_sim_cycle = 0;
m_last_inst_gpu_tot_sim_cycle = 0;
+
+ //Jin: for concurrent kernels on a SM
+ m_occupied_n_threads = 0;
+ m_occupied_shmem = 0;
+ m_occupied_regs = 0;
+ m_occupied_ctas = 0;
+ m_occupied_hwtid.reset();
+ m_occupied_cta_to_hwtid.clear();
}
void shader_core_ctx::reinit(unsigned start_thread, unsigned end_thread, bool reset_not_completed )
@@ -303,6 +311,15 @@ void shader_core_ctx::reinit(unsigned start_thread, unsigned end_thread, bool re
if( reset_not_completed ) {
m_not_completed = 0;
m_active_threads.reset();
+
+ //Jin: for concurrent kernels on a SM
+ m_occupied_n_threads = 0;
+ m_occupied_shmem = 0;
+ m_occupied_regs = 0;
+ m_occupied_ctas = 0;
+ m_occupied_hwtid.reset();
+ m_occupied_cta_to_hwtid.clear();
+
}
for (unsigned i = start_thread; i<end_thread; i++) {
m_threadState[i].n_insn = 0;
@@ -621,7 +638,7 @@ void shader_core_ctx::fetch()
if( m_threadState[tid].m_active == true ) {
m_threadState[tid].m_active = false;
unsigned cta_id = m_warp[warp_id].get_cta_id();
- register_cta_thread_exit(cta_id);
+ register_cta_thread_exit(cta_id, &(m_thread[tid]->get_kernel()));
m_not_completed -= 1;
m_active_threads.reset(tid);
assert( m_thread[tid]!= NULL );
@@ -829,6 +846,13 @@ void scheduler_unit::cycle()
unsigned max_issue = m_shader->m_config->gpgpu_max_insn_issue_per_warp;
while( !warp(warp_id).waiting() && !warp(warp_id).ibuffer_empty() && (checked < max_issue) && (checked <= issued) && (issued < max_issue) ) {
const warp_inst_t *pI = warp(warp_id).ibuffer_next_inst();
+ //Jin: handle cdp latency;
+ if(pI && pI->m_is_cdp && warp(warp_id).m_cdp_latency > 0) {
+ assert(warp(warp_id).m_cdp_dummy);
+ warp(warp_id).m_cdp_latency--;
+ break;
+ }
+
bool valid = warp(warp_id).ibuffer_next_valid();
bool warp_inst_issued = false;
unsigned pc,rpc;
@@ -863,6 +887,25 @@ void scheduler_unit::cycle()
bool sp_pipe_avail = m_sp_out->has_free();
bool sfu_pipe_avail = m_sfu_out->has_free();
if( sp_pipe_avail && (pI->op != SFU_OP) ) {
+
+ //Jin: special for CDP api
+ if(pI->m_is_cdp && !warp(warp_id).m_cdp_dummy) {
+ assert(warp(warp_id).m_cdp_latency == 0);
+
+ extern unsigned cdp_latency[5];
+ if(pI->m_is_cdp == 1)
+ warp(warp_id).m_cdp_latency = cdp_latency[pI->m_is_cdp - 1];
+ else //cudaLaunchDeviceV2 and cudaGetParameterBufferV2
+ warp(warp_id).m_cdp_latency = cdp_latency[pI->m_is_cdp - 1]
+ + cdp_latency[pI->m_is_cdp] * active_mask.count();
+ warp(warp_id).m_cdp_dummy = true;
+ break;
+ }
+ else if(pI->m_is_cdp && warp(warp_id).m_cdp_dummy) {
+ assert(warp(warp_id).m_cdp_latency == 0);
+ warp(warp_id).m_cdp_dummy = false;
+ }
+
// always prefer SP pipe for operations that can use both SP and SFU pipelines
m_shader->issue_warp(*m_sp_out,pI,active_mask,warp_id);
issued++;
@@ -1918,7 +1961,7 @@ void ldst_unit::cycle()
}
}
-void shader_core_ctx::register_cta_thread_exit( unsigned cta_num )
+void shader_core_ctx::register_cta_thread_exit( unsigned cta_num, kernel_info_t * kernel)
{
assert( m_cta_status[cta_num] > 0 );
m_cta_status[cta_num]--;
@@ -1926,22 +1969,35 @@ void shader_core_ctx::register_cta_thread_exit( unsigned cta_num )
m_n_active_cta--;
m_barriers.deallocate_barrier(cta_num);
shader_CTA_count_unlog(m_sid, 1);
+
printf("GPGPU-Sim uArch: Shader %d finished CTA #%d (%lld,%lld), %u CTAs running\n", m_sid, cta_num, gpu_sim_cycle, gpu_tot_sim_cycle,
m_n_active_cta );
+
if( m_n_active_cta == 0 ) {
- assert( m_kernel != NULL );
- m_kernel->dec_running();
- printf("GPGPU-Sim uArch: Shader %u empty (release kernel %u \'%s\').\n", m_sid, m_kernel->get_uid(),
- m_kernel->name().c_str() );
- if( !m_gpu->kernel_more_cta_left(m_kernel) ) {
- if( !m_kernel->running() ) {
- printf("GPGPU-Sim uArch: GPU detected kernel \'%s\' finished on shader %u.\n", m_kernel->name().c_str(), m_sid );
- m_gpu->set_kernel_done( m_kernel );
- }
- }
- m_kernel=NULL;
+ printf("GPGPU-Sim uArch: Shader %u empty (last released kernel %u \'%s\').\n", m_sid, kernel->get_uid(),
+ kernel->name().c_str() );
fflush(stdout);
+
+ //Shader can only be empty when no more cta are dispatched
+ if(kernel != m_kernel) {
+ assert(m_kernel == NULL || !m_gpu->kernel_more_cta_left(m_kernel));
+ }
+ m_kernel = NULL;
+ }
+
+ //Jin: for concurrent kernels on sm
+ release_shader_resource_1block(cta_num, *kernel);
+ kernel->dec_running();
+ if( !m_gpu->kernel_more_cta_left(kernel) ) {
+ if( !kernel->running() ) {
+ printf("GPGPU-Sim uArch: GPU detected kernel %u \'%s\' finished on shader %u.\n", kernel->get_uid(),
+ kernel->name().c_str(), m_sid );
+ if(m_kernel == kernel)
+ m_kernel = NULL;
+ m_gpu->set_kernel_done( kernel );
+ }
}
+
}
}
@@ -3239,15 +3295,33 @@ unsigned simt_core_cluster::issue_block2core()
unsigned num_blocks_issued=0;
for( unsigned i=0; i < m_config->n_simt_cores_per_cluster; i++ ) {
unsigned core = (i+m_cta_issue_next_core+1)%m_config->n_simt_cores_per_cluster;
- if( m_core[core]->get_not_completed() == 0 ) {
- if( m_core[core]->get_kernel() == NULL ) {
- kernel_info_t *k = m_gpu->select_kernel();
- if( k )
- m_core[core]->set_kernel(k);
+
+ kernel_info_t * kernel;
+ //Jin: fetch kernel according to concurrent kernel setting
+ if(m_config->gpgpu_concurrent_kernel_sm) {//concurrent kernel on sm
+ //always select latest issued kernel
+ kernel_info_t *k = m_gpu->select_kernel();
+ kernel = k;
+ }
+ else {
+ //first select core kernel, if no more cta, get a new kernel
+ //only when core completes
+ kernel = m_core[core]->get_kernel();
+ if( !m_gpu->kernel_more_cta_left(kernel) ) {
+ //wait till current kernel finishes
+ if(m_core[core]->get_not_completed() == 0)
+ {
+ kernel_info_t *k = m_gpu->select_kernel();
+ if( k )
+ m_core[core]->set_kernel(k);
+ kernel = k;
+ }
}
}
- kernel_info_t *kernel = m_core[core]->get_kernel();
- if( m_gpu->kernel_more_cta_left(kernel) && (m_core[core]->get_n_active_cta() < m_config->max_cta(*kernel)) ) {
+
+ if( m_gpu->kernel_more_cta_left(kernel) &&
+// (m_core[core]->get_n_active_cta() < m_config->max_cta(*kernel)) ) {
+ m_core[core]->can_issue_1block(*kernel)) {
m_core[core]->issue_block2core(*kernel);
num_blocks_issued++;
m_cta_issue_next_core=core;
diff --git a/src/gpgpu-sim/shader.h b/src/gpgpu-sim/shader.h
index 3b9859f..db2af01 100644
--- a/src/gpgpu-sim/shader.h
+++ b/src/gpgpu-sim/shader.h
@@ -108,6 +108,10 @@ public:
m_last_fetch=0;
m_next=0;
m_inst_at_barrier=NULL;
+
+ //Jin: cdp support
+ m_cdp_latency = 0;
+ m_cdp_dummy = false;
}
void init( address_type start_pc,
unsigned cta_id,
@@ -124,6 +128,10 @@ public:
n_completed -= active.count(); // active threads are not yet completed
m_active_threads = active;
m_done_exit=false;
+
+ //Jin: cdp support
+ m_cdp_latency = 0;
+ m_cdp_dummy = false;
}
bool functional_done() const;
@@ -260,6 +268,11 @@ private:
unsigned m_stores_outstanding; // number of store requests sent but not yet acknowledged
unsigned m_inst_in_pipeline;
+
+ //Jin: cdp support
+public:
+ unsigned int m_cdp_latency;
+ bool m_cdp_dummy;
};
@@ -1327,6 +1340,9 @@ struct shader_core_config : public core_config
int simt_core_sim_order;
unsigned mem2device(unsigned memid) const { return memid + n_simt_clusters; }
+
+ //Jin: concurrent kernel on sm
+ bool gpgpu_concurrent_kernel_sm;
};
struct shader_core_stats_pod {
@@ -1575,6 +1591,7 @@ public:
void cycle();
void reinit(unsigned start_thread, unsigned end_thread, bool reset_not_completed );
void issue_block2core( class kernel_info_t &kernel );
+
void cache_flush();
void accept_fetch_response( mem_fetch *mf );
void accept_ldst_unit_response( class mem_fetch * mf );
@@ -1583,7 +1600,7 @@ public:
{
assert(k);
m_kernel=k;
- k->inc_running();
+// k->inc_running();
printf("GPGPU-Sim uArch: Shader %d bind to kernel %u \'%s\'\n", m_sid, m_kernel->get_uid(),
m_kernel->name().c_str() );
}
@@ -1750,7 +1767,7 @@ public:
virtual void checkExecutionStatusAndUpdate(warp_inst_t &inst, unsigned t, unsigned tid);
address_type next_pc( int tid ) const;
void fetch();
- void register_cta_thread_exit( unsigned cta_num );
+ void register_cta_thread_exit(unsigned cta_num, kernel_info_t * kernel );
void decode();
@@ -1832,6 +1849,22 @@ public:
// is that the dynamic_warp_id is a running number unique to every warp
// run on this shader, where the warp_id is the static warp slot.
unsigned m_dynamic_warp_id;
+
+ //Jin: concurrent kernels on a sm
+public:
+ bool can_issue_1block(kernel_info_t & kernel);
+ bool occupy_shader_resource_1block(kernel_info_t & kernel, bool occupy);
+ void release_shader_resource_1block(unsigned hw_ctaid, kernel_info_t & kernel);
+ int find_available_hwtid(unsigned int cta_size, bool occupy);
+private:
+ unsigned int m_occupied_n_threads;
+ unsigned int m_occupied_shmem;
+ unsigned int m_occupied_regs;
+ unsigned int m_occupied_ctas;
+ std::bitset<MAX_THREAD_PER_SM> m_occupied_hwtid;
+ std::map<unsigned int, unsigned int> m_occupied_cta_to_hwtid;
+
+
};
class simt_core_cluster {
@@ -1852,6 +1885,7 @@ public:
bool icnt_injection_buffer_full(unsigned size, bool write);
void icnt_inject_request_packet(class mem_fetch *mf);
+
// for perfect memory interface
bool response_queue_full() {
return ( m_response_fifo.size() >= m_config->n_simt_ejection_buffer_size );
diff --git a/src/gpgpusim_entrypoint.cc b/src/gpgpusim_entrypoint.cc
index 6ba38eb..04845e7 100644
--- a/src/gpgpusim_entrypoint.cc
+++ b/src/gpgpusim_entrypoint.cc
@@ -100,7 +100,7 @@ void *gpgpu_sim_thread_concurrent(void*)
printf("GPGPU-Sim: *** simulation thread starting and spinning waiting for work ***\n");
fflush(stdout);
}
- while( g_stream_manager->empty_protected() && !g_sim_done )
+ while( g_stream_manager->empty() && !g_sim_done )
;
if(g_debug_execution >= 3) {
printf("GPGPU-Sim: ** START simulation thread (detected work) **\n");
@@ -127,6 +127,15 @@ void *gpgpu_sim_thread_concurrent(void*)
if(g_stream_manager->operation(&sim_cycles) && !g_the_gpu->active())
break;
+ //functional simulation
+ if( g_the_gpu->is_functional_sim()) {
+ kernel_info_t * kernel = g_the_gpu->get_functional_kernel();
+ assert(kernel);
+ gpgpu_cuda_ptx_sim_main_func(*kernel);
+ g_the_gpu->finish_functional_sim(kernel);
+ }
+
+ //performance simulation
if( g_the_gpu->active() ) {
g_the_gpu->cycle();
sim_cycles = true;
@@ -144,6 +153,7 @@ void *gpgpu_sim_thread_concurrent(void*)
printf("GPGPU-Sim: ** STOP simulation thread (no work) **\n");
fflush(stdout);
}
+ g_the_gpu->print_stats();
if(sim_cycles) {
g_the_gpu->update_stats();
print_simulation_time();
diff --git a/src/intersim2/Makefile b/src/intersim2/Makefile
index ef948d6..bd42000 100644
--- a/src/intersim2/Makefile
+++ b/src/intersim2/Makefile
@@ -125,6 +125,14 @@ endif
# rules to compile simulator
+$(OBJDIR)/Makefile.makedepend: depend
+
+ALL_SRCS = $(CPP_SRCS)
+ALL_SRCS += $(shell ls **/*.cpp)
+
+depend:
+ touch $(OBJDIR)/Makefile.makedepend
+ makedepend -f$(OBJDIR)/Makefile.makedepend -I$(INCPATH) -p$(OBJDIR)/ $(ALL_SRCS) 2> /dev/null
${LEX_OBJS}: $(OBJDIR)/lex.yy.c $(OBJDIR)/y.tab.h
$(CC) $(CPPFLAGS) -c $< -o $@
@@ -173,3 +181,5 @@ $(OBJDIR)/y.tab.c $(OBJDIR)/y.tab.h: config.y
$(OBJDIR)/lex.yy.c: config.l
$(LEX) -o$@ $<
+
+include $(OBJDIR)/Makefile.makedepend
diff --git a/src/stream_manager.cc b/src/stream_manager.cc
index dd42f0a..3b6cbd5 100644
--- a/src/stream_manager.cc
+++ b/src/stream_manager.cc
@@ -95,6 +95,15 @@ stream_operation CUstream_st::next()
return result;
}
+void CUstream_st::cancel_front()
+{
+ pthread_mutex_lock(&m_lock);
+ assert(m_pending);
+ m_pending = false;
+ pthread_mutex_unlock(&m_lock);
+
+}
+
void CUstream_st::print(FILE *fp)
{
pthread_mutex_lock(&m_lock);
@@ -111,10 +120,10 @@ void CUstream_st::print(FILE *fp)
}
-void stream_operation::do_operation( gpgpu_sim *gpu )
+bool stream_operation::do_operation( gpgpu_sim *gpu )
{
if( is_noop() )
- return;
+ return true;
assert(!m_done && m_stream);
if(g_debug_execution >= 3)
@@ -151,17 +160,36 @@ void stream_operation::do_operation( gpgpu_sim *gpu )
m_stream->record_next_done();
break;
case stream_kernel_launch:
- if( gpu->can_start_kernel() ) {
- gpu->set_cache_config(m_kernel->name());
- printf("kernel \'%s\' transfer to GPU hardware scheduler\n", m_kernel->name().c_str() );
- if( m_sim_mode )
- gpgpu_cuda_ptx_sim_main_func( *m_kernel );
- else
+ if( m_sim_mode ) { //Functional Sim
+ if(g_debug_execution >= 3) {
+ printf("kernel %d: \'%s\' transfer to GPU hardware scheduler\n", m_kernel->get_uid(), m_kernel->name().c_str() );
+ m_kernel->print_parent_info();
+ }
+ gpu->set_cache_config(m_kernel->name());
+ gpu->functional_launch( m_kernel );
+ }
+ else { //Performance Sim
+ if( gpu->can_start_kernel() && m_kernel->m_launch_latency == 0) {
+ if(g_debug_execution >= 3) {
+ printf("kernel %d: \'%s\' transfer to GPU hardware scheduler\n", m_kernel->get_uid(), m_kernel->name().c_str() );
+ m_kernel->print_parent_info();
+ }
+ gpu->set_cache_config(m_kernel->name());
gpu->launch( m_kernel );
+ }
+ else {
+ if(m_kernel->m_launch_latency)
+ m_kernel->m_launch_latency--;
+ if(g_debug_execution >= 3)
+ printf("kernel %d: \'%s\', latency %u not ready to transfer to GPU hardware scheduler\n",
+ m_kernel->get_uid(), m_kernel->name().c_str(), m_kernel->m_launch_latency);
+ return false;
+ }
}
break;
case stream_event: {
- printf("event update\n");
+ if(g_debug_execution >= 3)
+ printf("event update\n");
time_t wallclock = time((time_t *)NULL);
m_event->update( gpu_tot_sim_cycle, wallclock );
m_stream->record_next_done();
@@ -172,6 +200,7 @@ void stream_operation::do_operation( gpgpu_sim *gpu )
}
m_done=true;
fflush(stdout);
+ return true;
}
void stream_operation::print( FILE *fp ) const
@@ -199,11 +228,20 @@ stream_manager::stream_manager( gpgpu_sim *gpu, bool cuda_launch_blocking )
bool stream_manager::operation( bool * sim)
{
- pthread_mutex_lock(&m_lock);
bool check=check_finished_kernel();
- if(check)m_gpu->print_stats();
+ pthread_mutex_lock(&m_lock);
+// if(check)m_gpu->print_stats();
stream_operation op =front();
- op.do_operation( m_gpu );
+ if(!op.do_operation( m_gpu )) //not ready to execute
+ {
+ //cancel operation
+ if( op.is_kernel() ) {
+ unsigned grid_uid = op.get_kernel()->get_uid();
+ m_grid_id_to_stream.erase(grid_uid);
+ }
+ op.get_stream()->cancel_front();
+
+ }
pthread_mutex_unlock(&m_lock);
//pthread_mutex_lock(&m_lock);
// simulate a clock cycle on the GPU
@@ -212,11 +250,9 @@ bool stream_manager::operation( bool * sim)
bool stream_manager::check_finished_kernel()
{
-
- unsigned grid_uid = m_gpu->finished_kernel();
- bool check=register_finished_kernel(grid_uid);
- return check;
-
+ unsigned grid_uid = m_gpu->finished_kernel();
+ bool check=register_finished_kernel(grid_uid);
+ return check;
}
bool stream_manager::register_finished_kernel(unsigned grid_uid)
@@ -226,13 +262,27 @@ bool stream_manager::register_finished_kernel(unsigned grid_uid)
CUstream_st *stream = m_grid_id_to_stream[grid_uid];
kernel_info_t *kernel = stream->front().get_kernel();
assert( grid_uid == kernel->get_uid() );
- stream->record_next_done();
- m_grid_id_to_stream.erase(grid_uid);
- delete kernel;
- return true;
- }else{
- return false;
+
+ //Jin: should check children kernels for CDP
+ if(kernel->is_finished()) {
+// std::ofstream kernel_stat("kernel_stat.txt", std::ofstream::out | std::ofstream::app);
+// kernel_stat<< " kernel " << grid_uid << ": " << kernel->name();
+// if(kernel->get_parent())
+// kernel_stat << ", parent " << kernel->get_parent()->get_uid() <<
+// ", launch " << kernel->launch_cycle;
+// kernel_stat<< ", start " << kernel->start_cycle <<
+// ", end " << kernel->end_cycle << ", retire " << gpu_sim_cycle + gpu_tot_sim_cycle << "\n";
+// printf("kernel %d finishes, retires from stream %d\n", grid_uid, stream->get_uid());
+// kernel_stat.flush();
+// kernel_stat.close();
+ stream->record_next_done();
+ m_grid_id_to_stream.erase(grid_uid);
+ kernel->notify_parent_finished();
+ delete kernel;
+ return true;
+ }
}
+
return false;
}
@@ -259,21 +309,22 @@ stream_operation stream_manager::front()
{
// called by gpu simulation thread
stream_operation result;
- if( concurrent_streams_empty() )
- m_service_stream_zero = true;
+// if( concurrent_streams_empty() )
+ m_service_stream_zero = true;
if( m_service_stream_zero ) {
- if( !m_stream_zero.empty() ) {
- if( !m_stream_zero.busy() ) {
+ if( !m_stream_zero.empty() && !m_stream_zero.busy() ) {
result = m_stream_zero.next();
if( result.is_kernel() ) {
unsigned grid_id = result.get_kernel()->get_uid();
m_grid_id_to_stream[grid_id] = &m_stream_zero;
}
- }
} else {
m_service_stream_zero = false;
}
- } else {
+ }
+
+ if(!m_service_stream_zero)
+ {
std::list<struct CUstream_st*>::iterator s;
for( s=m_streams.begin(); s != m_streams.end(); s++) {
CUstream_st *stream = *s;
diff --git a/src/stream_manager.h b/src/stream_manager.h
index 701b33c..222a1b2 100644
--- a/src/stream_manager.h
+++ b/src/stream_manager.h
@@ -150,7 +150,7 @@ public:
bool is_noop() const { return m_type == stream_no_op; }
bool is_done() const { return m_done; }
kernel_info_t *get_kernel() { return m_kernel; }
- void do_operation( gpgpu_sim *gpu );
+ bool do_operation( gpgpu_sim *gpu );
void print( FILE *fp ) const;
struct CUstream_st *get_stream() { return m_stream; }
void set_stream( CUstream_st *stream ) { m_stream = stream; }
@@ -218,6 +218,7 @@ public:
void push( const stream_operation &op );
void record_next_done();
stream_operation next();
+ void cancel_front(); //front operation fails, cancle the pending status
stream_operation &front() { return m_operations.front(); }
void print( FILE *fp );
unsigned get_uid() const { return m_uid; }