From 35cf76f383ec8de6de901bbbcd8fb478f69e46e4 Mon Sep 17 00:00:00 2001 From: sspenst Date: Wed, 6 Jul 2016 13:56:52 -0700 Subject: Added sstarr memory, which works the same as shared memory --- src/abstract_hardware_model.h | 1 + 1 file changed, 1 insertion(+) (limited to 'src/abstract_hardware_model.h') diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index b29f918..750eb6a 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -41,6 +41,7 @@ enum _memory_space_t { reg_space, local_space, shared_space, + sstarr_space, param_space_unclassified, param_space_kernel, /* global to all threads in a kernel : read-only */ param_space_local, /* local to a thread : read-writable */ -- cgit v1.3 From 19595382f05235b8887955c76794a976fad04833 Mon Sep 17 00:00:00 2001 From: sspenst Date: Thu, 7 Jul 2016 11:53:56 -0700 Subject: SST instruction now updates the original array instead of storing the result in sstarr memory --- src/abstract_hardware_model.h | 1 + src/cuda-sim/instructions.cc | 49 ++++++++++++++++++++++++------------------- 2 files changed, 28 insertions(+), 22 deletions(-) (limited to 'src/abstract_hardware_model.h') diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index 750eb6a..6ed9b8e 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -554,6 +554,7 @@ public: return false; } enum _memory_space_t get_type() const { return m_type; } + void set_type( enum _memory_space_t t ) { m_type = t; } unsigned get_bank() const { return m_bank; } void set_bank( unsigned b ) { m_bank = b; } bool is_const() const { return (m_type == const_space) || (m_type == param_space_kernel); } diff --git a/src/cuda-sim/instructions.cc b/src/cuda-sim/instructions.cc index 47f7075..d4b74fa 100644 --- a/src/cuda-sim/instructions.cc +++ b/src/cuda-sim/instructions.cc @@ -3747,10 +3747,11 @@ void sst_impl( const ptx_instruction *pI, ptx_thread_info *thread ) const operand_info &src3 = pI->src3(); unsigned type = pI->get_type(); ptx_reg_t src1_data = thread->get_operand_value(src1, src1, type, thread, 1); - ptx_reg_t src2_data, src3_data; + ptx_reg_t src2_data = thread->get_operand_value(src2, src1, type, thread, 1); + ptx_reg_t src3_data = thread->get_operand_value(src3, src1, type, thread, 1); memory_space_t space = pI->get_space(); memory_space *mem = NULL; - addr_t addr = src1_data.u32; + addr_t addr = src2_data.u32 * 4; // this assumes sstarr memory starts at address 0 decode_space(space,thread,src1,mem,addr); @@ -3758,13 +3759,8 @@ void sst_impl( const ptx_instruction *pI, ptx_thread_info *thread ) int t; type_info_key::type_decode(type,size,t); - src2_data = thread->get_operand_value(src2, src1, type, thread, 1); - src3_data = thread->get_operand_value(src3, src1, type, thread, 1); mem->write(addr,size/8,&src3_data.s64,thread,pI); - thread->m_last_effective_address = addr; - thread->m_last_memory_space = space; - // Step 2: __syncthreads() to make sure all data is stored in sstarr memory // (function must be called with dst = 0 so that all threads execute bar.sync 0) ptx_instruction * cpI = const_cast(pI); @@ -3776,35 +3772,44 @@ void sst_impl( const ptx_instruction *pI, ptx_thread_info *thread ) thread->m_last_dram_callback.function = bar_callback; thread->m_last_dram_callback.instruction = pI; - // Step 3: pick only one thread to load all of the data back from sstarr memory - // rearrange the data so that zeros are at the end of the array - // store this data back in the original array (each thread can maybe do this after another sync?) - int NUM_THREADS = 8; + + int NUM_THREADS = 8; // (how do you get this dynamically?) if (src2_data.s64 == NUM_THREADS-1) { - addr -= (NUM_THREADS-1)*4; + // Step 3: pick only one thread to load all of the data back from sstarr memory unsigned offset = 0; + addr -= (NUM_THREADS-1)*4; ptx_reg_t data; - // loop through all of the threads (how do you do this dynamically?) + float sstarr_fdata[NUM_THREADS]; + signed long long sstarr_ldata[NUM_THREADS]; + // loop through all of the threads for (int tid = 0; tid < NUM_THREADS; tid++) { data.u64=0; mem->read(addr+(tid*4),size/8,&data.s64); + sstarr_fdata[tid] = data.f32; + sstarr_ldata[tid] = data.s64; + } - // store nonzero entries - if (data.s64 != 0) { - mem->write(addr+(offset*4),size/8,&data.s64,thread,pI); - thread->m_last_effective_address = addr+(offset*4); + // Step 4: squeeze the zeros out of the array and store data back into original array + mem = NULL; + addr = src1_data.u32; + space.set_type(global_space); + decode_space(space,thread,src1,mem,addr); + // store nonzero entries + for (int tid = 0; tid < NUM_THREADS; tid++) { + if (sstarr_fdata[tid] != 0) { + mem->write(addr+(offset*4),size/8,&sstarr_ldata[tid],thread,pI); offset++; } } - // fill the rest of the array with zeros + + // fill the rest of the array with zeros (dst should always have a 0 in it) while (offset < NUM_THREADS) { - mem->write(addr+(offset*4),size/8,&src2_data.s64,thread,pI); - thread->m_last_effective_address = addr+(offset*4); + mem->write(addr+(offset*4),size/8,&dst_data.s64,thread,pI); offset++; } - // Step 4: load from sstarr memory and store data back into original array - + thread->m_last_effective_address = addr+(NUM_THREADS-1)*4; + thread->m_last_memory_space = space; } //if( type == S16_TYPE || type == S32_TYPE ) sign_extend(data,size,dst); -- cgit v1.3 From 6c1fb702e17b00fd7de72ac7dd4a31584d5978b9 Mon Sep 17 00:00:00 2001 From: sspenst Date: Fri, 8 Jul 2016 14:51:44 -0700 Subject: Made gridDim and blockDim global variables so that they can be accessed from sst_impl --- libcuda/cuda_runtime_api.cc | 7 +++++-- src/abstract_hardware_model.h | 3 +++ src/cuda-sim/instructions.cc | 3 +-- src/cuda-sim/opcodes.def | 2 +- 4 files changed, 10 insertions(+), 5 deletions(-) (limited to 'src/abstract_hardware_model.h') diff --git a/libcuda/cuda_runtime_api.cc b/libcuda/cuda_runtime_api.cc index e8a0e91..3eff4af 100644 --- a/libcuda/cuda_runtime_api.cc +++ b/libcuda/cuda_runtime_api.cc @@ -180,6 +180,9 @@ cudaError_t g_last_cudaError = cudaSuccess; extern stream_manager *g_stream_manager; +dim3 gridDim = (dim3){1,1,1}; +dim3 blockDim = (dim3){1,1,1}; + void register_ptx_function( const char *name, function_info *impl ) { // no longer need this @@ -959,8 +962,8 @@ __host__ cudaError_t CUDARTAPI cudaLaunch( const char *hostFun ) g_ptx_sim_mode?"functional simulation":"performance simulation", stream?stream->get_uid():0 ); kernel_info_t *grid = gpgpu_cuda_ptx_sim_init_grid(hostFun,config.get_args(),config.grid_dim(),config.block_dim(),context); std::string kname = grid->name(); - dim3 gridDim = config.grid_dim(); - dim3 blockDim = config.block_dim(); + gridDim = config.grid_dim(); + blockDim = config.block_dim(); printf("GPGPU-Sim PTX: pushing kernel \'%s\' to stream %u, gridDim= (%u,%u,%u) blockDim = (%u,%u,%u) \n", kname.c_str(), stream?stream->get_uid():0, gridDim.x,gridDim.y,gridDim.z,blockDim.x,blockDim.y,blockDim.z ); stream_operation op(grid,g_ptx_sim_mode,stream); diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index 6ed9b8e..46c3279 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -162,6 +162,9 @@ struct dim3 { }; #endif +extern dim3 gridDim; +extern dim3 blockDim; + void increment_x_then_y_then_z( dim3 &i, const dim3 &bound); class kernel_info_t { diff --git a/src/cuda-sim/instructions.cc b/src/cuda-sim/instructions.cc index 8bdb94f..fd3b1fa 100644 --- a/src/cuda-sim/instructions.cc +++ b/src/cuda-sim/instructions.cc @@ -3772,7 +3772,7 @@ void sst_impl( const ptx_instruction *pI, ptx_thread_info *thread ) thread->m_last_dram_callback.function = bar_callback; thread->m_last_dram_callback.instruction = cpI; - int NUM_THREADS = 8; // (how do you get this dynamically?) + int NUM_THREADS = blockDim.x * blockDim.y * blockDim.z; if (src2_data.s64 == NUM_THREADS-1) { // pick only one thread to load all of the data back from sstarr memory unsigned offset = 0; @@ -3809,7 +3809,6 @@ void sst_impl( const ptx_instruction *pI, ptx_thread_info *thread ) // fill the rest of the array with zeros (dst should always have a 0 in it) while (offset < NUM_THREADS) { mem->write(addr+(offset*4),size/8,&dst_data.s64,thread,pI); - mem->write(addr+((NUM_THREADS+offset)*4),size/8,&dst_data.s64,thread,pI); offset++; } diff --git a/src/cuda-sim/opcodes.def b/src/cuda-sim/opcodes.def index 0c0eda9..1af04ea 100644 --- a/src/cuda-sim/opcodes.def +++ b/src/cuda-sim/opcodes.def @@ -103,7 +103,7 @@ OP_DEF(SHR_OP,shr_impl,"shr",1,1) OP_DEF(SIN_OP,sin_impl,"sin",1,4) OP_DEF(SLCT_OP,slct_impl,"slct",1,1) OP_DEF(SQRT_OP,sqrt_impl,"sqrt",1,4) -OP_DEF(SST_OP,sst_impl,"sst",1,1) +OP_DEF(SST_OP,sst_impl,"sst",1,5) OP_DEF(SSY_OP,ssy_impl,"ssy",0,3) OP_DEF(ST_OP,st_impl,"st",0,5) OP_DEF(SUB_OP,sub_impl,"sub",1,1) -- cgit v1.3 From adc311951d67b0685ebf2fab4ce6410f96f0039a Mon Sep 17 00:00:00 2001 From: sspenst Date: Mon, 11 Jul 2016 11:16:46 -0700 Subject: Reverted the previous commit to add a cleaner way of getting NUM_THREADS. Now, sst_impl doesn't functionally execute on the last indexed element of an array, but instead on the actual last thread that executes --- libcuda/cuda_runtime_api.cc | 7 ++----- src/abstract_hardware_model.h | 3 --- src/cuda-sim/instructions.cc | 13 ++++++++----- src/cuda-sim/ptx_sim.cc | 16 ++++++++++++++++ src/cuda-sim/ptx_sim.h | 4 ++++ 5 files changed, 30 insertions(+), 13 deletions(-) (limited to 'src/abstract_hardware_model.h') diff --git a/libcuda/cuda_runtime_api.cc b/libcuda/cuda_runtime_api.cc index 3eff4af..e8a0e91 100644 --- a/libcuda/cuda_runtime_api.cc +++ b/libcuda/cuda_runtime_api.cc @@ -180,9 +180,6 @@ cudaError_t g_last_cudaError = cudaSuccess; extern stream_manager *g_stream_manager; -dim3 gridDim = (dim3){1,1,1}; -dim3 blockDim = (dim3){1,1,1}; - void register_ptx_function( const char *name, function_info *impl ) { // no longer need this @@ -962,8 +959,8 @@ __host__ cudaError_t CUDARTAPI cudaLaunch( const char *hostFun ) g_ptx_sim_mode?"functional simulation":"performance simulation", stream?stream->get_uid():0 ); kernel_info_t *grid = gpgpu_cuda_ptx_sim_init_grid(hostFun,config.get_args(),config.grid_dim(),config.block_dim(),context); std::string kname = grid->name(); - gridDim = config.grid_dim(); - blockDim = config.block_dim(); + dim3 gridDim = config.grid_dim(); + dim3 blockDim = config.block_dim(); printf("GPGPU-Sim PTX: pushing kernel \'%s\' to stream %u, gridDim= (%u,%u,%u) blockDim = (%u,%u,%u) \n", kname.c_str(), stream?stream->get_uid():0, gridDim.x,gridDim.y,gridDim.z,blockDim.x,blockDim.y,blockDim.z ); stream_operation op(grid,g_ptx_sim_mode,stream); diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index 46c3279..6ed9b8e 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -162,9 +162,6 @@ struct dim3 { }; #endif -extern dim3 gridDim; -extern dim3 blockDim; - void increment_x_then_y_then_z( dim3 &i, const dim3 &bound); class kernel_info_t { diff --git a/src/cuda-sim/instructions.cc b/src/cuda-sim/instructions.cc index fd3b1fa..b5a3db4 100644 --- a/src/cuda-sim/instructions.cc +++ b/src/cuda-sim/instructions.cc @@ -3754,6 +3754,7 @@ void sst_impl( const ptx_instruction *pI, ptx_thread_info *thread ) memory_space_t space = pI->get_space(); memory_space *mem = NULL; addr_t addr = src2_data.u32 * 4; // this assumes sstarr memory starts at address 0 + ptx_cta_info *cta_info = thread->m_cta_info; decode_space(space,thread,src1,mem,addr); @@ -3765,18 +3766,19 @@ void sst_impl( const ptx_instruction *pI, ptx_thread_info *thread ) mem->write(addr,size/8,&src3_data.s64,thread,pI); // sync threads - cpI->set_bar_id(dst_data.u32); + cpI->set_bar_id(16); // use 16 for sst because bar uses an int from 0-15 thread->m_last_effective_address = addr; thread->m_last_memory_space = space; thread->m_last_dram_callback.function = bar_callback; thread->m_last_dram_callback.instruction = cpI; - int NUM_THREADS = blockDim.x * blockDim.y * blockDim.z; - if (src2_data.s64 == NUM_THREADS-1) { - // pick only one thread to load all of the data back from sstarr memory + // the last thread that executes loads all of the data back from sstarr memory + int NUM_THREADS = cta_info->num_threads(); + cta_info->inc_bar_threads(); + if (NUM_THREADS == cta_info->get_bar_threads()) { unsigned offset = 0; - addr -= (NUM_THREADS-1)*4; + addr = 0; ptx_reg_t data; float sstarr_fdata[NUM_THREADS]; signed long long sstarr_ldata[NUM_THREADS]; @@ -3812,6 +3814,7 @@ void sst_impl( const ptx_instruction *pI, ptx_thread_info *thread ) offset++; } + cta_info->reset_bar_threads(); thread->m_last_effective_address = addr+(NUM_THREADS-1)*4; thread->m_last_memory_space = space; } diff --git a/src/cuda-sim/ptx_sim.cc b/src/cuda-sim/ptx_sim.cc index 511e8d6..f48115b 100644 --- a/src/cuda-sim/ptx_sim.cc +++ b/src/cuda-sim/ptx_sim.cc @@ -44,6 +44,7 @@ ptx_cta_info::ptx_cta_info( unsigned sm_idx ) m_sm_idx = sm_idx; m_uid = g_ptx_cta_info_uid++; + m_bar_threads = 0; } void ptx_cta_info::add_thread( ptx_thread_info *thd ) @@ -128,6 +129,21 @@ unsigned ptx_cta_info::get_sm_idx() const return m_sm_idx; } +unsigned ptx_cta_info::get_bar_threads() const +{ + return m_bar_threads; +} + +void ptx_cta_info::inc_bar_threads() +{ + m_bar_threads++; +} + +void ptx_cta_info::reset_bar_threads() +{ + m_bar_threads = 0; +} + unsigned g_ptx_thread_info_uid_next=1; unsigned g_ptx_thread_info_delete_count=0; diff --git a/src/cuda-sim/ptx_sim.h b/src/cuda-sim/ptx_sim.h index c66b68c..4e748e9 100644 --- a/src/cuda-sim/ptx_sim.h +++ b/src/cuda-sim/ptx_sim.h @@ -158,8 +158,12 @@ public: void register_thread_exit( ptx_thread_info *thd ); void register_deleted_thread( ptx_thread_info *thd ); unsigned get_sm_idx() const; + unsigned get_bar_threads() const; + void inc_bar_threads(); + void reset_bar_threads(); private: + unsigned m_bar_threads; unsigned long long m_uid; unsigned m_sm_idx; std::set m_threads_in_cta; -- cgit v1.3 From feda07a5e0053ef2f2bfa382f5ba9a7a0b6c6bf5 Mon Sep 17 00:00:00 2001 From: sspenst Date: Thu, 4 Aug 2016 13:09:41 -0700 Subject: A thread executing BSMAD is now able to access information from all threads in its warp --- src/abstract_hardware_model.h | 1 + src/cuda-sim/cuda-sim.cc | 14 ++++ src/cuda-sim/instructions.cc | 158 ++++++++++++++++++++++++++++++++++++++++++ src/cuda-sim/opcodes.def | 3 + src/cuda-sim/opcodes.h | 4 +- src/cuda-sim/ptx.l | 3 + 6 files changed, 182 insertions(+), 1 deletion(-) (limited to 'src/abstract_hardware_model.h') diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index 6ed9b8e..13dfce3 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -1053,6 +1053,7 @@ class core_t { warp_inst_t getExecuteWarp(unsigned warpId); void get_pdom_stack_top_info( unsigned warpId, unsigned *pc, unsigned *rpc ) const; kernel_info_t * get_kernel_info(){ return m_kernel;} + class ptx_thread_info ** get_thread_info() { return m_thread; } unsigned get_warp_size() const { return m_warp_size; } void and_reduction(unsigned ctaid, unsigned barid, bool value) { reduction_storage[ctaid][barid] &= value; } void or_reduction(unsigned ctaid, unsigned barid, bool value) { reduction_storage[ctaid][barid] |= value; } diff --git a/src/cuda-sim/cuda-sim.cc b/src/cuda-sim/cuda-sim.cc index e194a2a..059fbe2 100644 --- a/src/cuda-sim/cuda-sim.cc +++ b/src/cuda-sim/cuda-sim.cc @@ -849,8 +849,10 @@ void ptx_instruction::pre_decode() switch ( get_opcode() ) { #define OP_DEF(OP,FUNC,STR,DST,CLASSIFICATION) case OP: has_dst = (DST!=0); break; +#define OP_W_DEF(OP,FUNC,STR,DST,CLASSIFICATION) case OP: has_dst = (DST!=0); break; #include "opcodes.def" #undef OP_DEF +#undef OP_W_DEF default: printf( "Execution error: Invalid opcode (0x%x)\n", get_opcode() ); break; @@ -1242,10 +1244,22 @@ void ptx_thread_info::ptx_exec_inst( warp_inst_t &inst, unsigned lane_id) *((warp_inst_t*)pJ) = inst; // copy active mask information pI = pJ; } + /*const ptx_instruction **pA; + if( pI->get_opcode() == BSMAD_OP ) { + //pA = (const ptx_instruction**)malloc(get_core()->get_warp_size()*(sizeof(ptx_instruction*))); + pA = (const ptx_instruction**)malloc(8*(sizeof(ptx_instruction*))); + for (int i = 0; i < get_core()->get_warp_size() && inst.active(i); i++) { + //pA[i] = get_core()->get_thread_info()[inst.warp_id() * get_core()->get_warp_size() + i]->func_info()->get_instruction(pc+(i-lane_id)*(pI->inst_size())); + int tid = inst.warp_id() * get_core()->get_warp_size() + i; + pA[i] = get_core()->get_thread_info()[tid]->func_info()->get_instruction(pc); + } + }*/ switch ( pI->get_opcode() ) { #define OP_DEF(OP,FUNC,STR,DST,CLASSIFICATION) case OP: FUNC(pI,this); op_classification = CLASSIFICATION; break; +#define OP_W_DEF(OP,FUNC,STR,DST,CLASSIFICATION) case OP: FUNC(pI,get_core(),inst); op_classification = CLASSIFICATION; break; #include "opcodes.def" #undef OP_DEF +#undef OP_W_DEF default: printf( "Execution error: Invalid opcode (0x%x)\n", pI->get_opcode() ); break; } delete pJ; diff --git a/src/cuda-sim/instructions.cc b/src/cuda-sim/instructions.cc index b401bef..618add1 100644 --- a/src/cuda-sim/instructions.cc +++ b/src/cuda-sim/instructions.cc @@ -47,8 +47,10 @@ unsigned ptx_instruction::g_num_ptx_inst_uid=0; const char *g_opcode_string[NUM_OPCODES] = { #define OP_DEF(OP,FUNC,STR,DST,CLASSIFICATION) STR, +#define OP_W_DEF(OP,FUNC,STR,DST,CLASSIFICATION) STR, #include "opcodes.def" #undef OP_DEF +#undef OP_W_DEF }; void inst_not_implemented( const ptx_instruction * pI ) ; @@ -1456,6 +1458,162 @@ void breakaddr_impl( const ptx_instruction *pI, ptx_thread_info *thread ) void brev_impl( const ptx_instruction *pI, ptx_thread_info *thread ) { inst_not_implemented(pI); } void brkpt_impl( const ptx_instruction *pI, ptx_thread_info *thread ) { inst_not_implemented(pI); } +void bsmad_impl( const ptx_instruction *pI, core_t *core, warp_inst_t inst ) +{ + for (int i = 0; i < core->get_warp_size() && inst.active(i); i++) { + const operand_info &dst = pI->dst(); + unsigned type = pI->get_type(); + + int tid = inst.warp_id() * core->get_warp_size() + i; + ptx_thread_info *thread = core->get_thread_info()[tid]; + ptx_reg_t data = thread->get_operand_value(dst, dst, type, thread, 1); + printf("BSMAD - DATA FROM THREAD %d: %d\n", i, data.u32); + } + printf("\n"); + /*const unsigned OPERANDS = 9; + // 0 = output + // 1 = input precision + // 2 = output precision + // 3 = buffer0 + // 4 = buffer1 + // 5 = buffer2 + // 6 = buffer3 + // 7 = synapse value + // 8 = output value + // as a temporary solution, let 0 be the base address of output, which is an array of shared memory + // that will be filled when the last thread completes the bsmad instruction + // maybe you can store the addresses of other ptx_instruction in sstarr memory and then update dst later? + // not sure if that works + + //ptx_instruction * cpI = const_cast(pI); + const operand_info &src[OPERANDS]; + ptx_reg_t src_data[OPERANDS]; + unsigned type = pI->get_type(); + + for (int i = 0; i < OPERANDS; i++) { + src[i] = pI->operand_lookup(i); + src_data[i] = thread->get_operand_value(src[i], src[0], type, thread, 1); + } + + memory_space_t space = pI->get_space(); + memory_space *mem = NULL; + addr_t addr = thread->get_tid().x * 24; // 4 bytes per register * 6 registers per thread = 24 bytes + + decode_space(space,thread,src[0],mem,addr); + + size_t size; + int t; + type_info_key::type_decode(type,size,t); + + // store src_data[1:4] in sstarr memory + for (int i = 0; i < 6; i++) { + mem->write(addr + i*4,size/8,&src_data[i+3].s64,thread,pI); + } + + // sync threads + //cpI->set_bar_id(16); // use 16 for sst because bar uses an int from 0-15 + + thread->m_last_effective_address = addr; + thread->m_last_memory_space = space; + thread->m_last_dram_callback.function = bar_callback; + thread->m_last_dram_callback.instruction = cpI; + + // the last thread that executes loads all of the data back from sstarr memory + ptx_cta_info *cta_info = thread->m_cta_info;((32/ip)*4)/(32/op) + const int NUM_THREADS = cta_info->num_threads(); + cta_info->inc_bar_threads(); + if (NUM_THREADS == cta_info->get_bar_threads()) { + // load all things from sstarr memory + addr = 0; + ptx_reg_t data; + unsigned sstarr_data[NUM_THREADS*6]; + for (int i = 0; i < NUM_THREADS*6; i++) { + data.u64 = 0; + mem->read(addr+(i*4),size/8,&data.s64); + sstarr_data[i] = data.u32; + } + + // unpack registers, add data from across threads + unsigned ip = src_data[1].u32; + unsigned op = src_data[2].u32; + unsigned unpacked_output[(32/ip)*4]; + + for (unsigned i = 0; i < (32/ip)*4; i++) { + unsigned buf = i/(32/ip); + unsigned pos = i%(32/ip); + + unsigned mask = 0; + for (int b = 0; b < ip; b++) { + mask |= (1 << b); + } + mask <<= (pos*ip); + + int sum = 0; + for (int j = 0; j < NUM_THREADS; j++) { + sum += mask & sstarr_data[j*6 + buf]; + } + unpacked_output[i] = sum; + } + + // truncate result, repack, store in shared mem + unsigned output_regs[((32/ip)*4)/(32/op) + (((32/ip)*4)%(32/op) != 0)]; + + + + unsigned offset = 0; + addr = 0; + ptx_reg_t data; + float sstarr_fdata[NUM_THREADS]; + signed long long sstarr_ldata[NUM_THREADS]; + // loop through all of the threads + for (int tid = 0; tid < NUM_THREADS; tid++) { + data.u64=0; + mem->read(addr+(tid*4),size/8,&data.s64); + sstarr_fdata[tid] = data.f32; + sstarr_ldata[tid] = data.s64; + } + + // squeeze the zeros out of the array and store data back into original array + mem = NULL; + addr = src1_data.u32; + space.set_type(global_space); + decode_space(space,thread,src1,mem,addr); + // store nonzero entries and indices + for (int tid = 0; tid < NUM_THREADS; tid++) { + if (sstarr_fdata[tid] != 0) { + float ftid = (float)tid; + mem->write(addr+(offset*4),size/8,&sstarr_ldata[tid],thread,pI); + mem->write(addr+((NUM_THREADS+offset)*4),size/8,&ftid,thread,pI); + offset++; + } + } + // store the number of nonzero elements in the array + data = thread->get_op((32/ip)*4)/(32/op)erand_value(src1, dst, type, thread, 1); + data.s64 += 4*(offset-1); + thread->set_operand_value(dst, data, type, thread, pI); + + // fill the rest of the array with zeros (dst should always have a 0 in it) + while (offset < NUM_THREADS) { + mem->write(addr+(offset*4),size/8,&dst_data.s64,thread,pI); + offset++; + } + + cta_info->reset_bar_threads(); + thread->m_last_effective_address = addr+(NUM_THREADS-1)*4; + thread->m_last_memory_space = space; + }*/ +} + +void bsmul_impl( const ptx_instruction *pI, ptx_thread_info *thread ) +{ + printf("BSMUL instruction found.\n"); +} + +void buf_impl( const ptx_instruction *pI, ptx_thread_info *thread ) +{ + printf("BUF instruction found.\n"); +} + void call_impl( const ptx_instruction *pI, ptx_thread_info *thread ) { static unsigned call_uid_next = 1; diff --git a/src/cuda-sim/opcodes.def b/src/cuda-sim/opcodes.def index 1af04ea..d0e6f25 100644 --- a/src/cuda-sim/opcodes.def +++ b/src/cuda-sim/opcodes.def @@ -52,6 +52,9 @@ OP_DEF(BRA_OP,bra_impl,"bra",0,3) OP_DEF(BRX_OP,brx_impl,"brx",0,3) OP_DEF(BREV_OP,brev_impl,"brev",1,1) OP_DEF(BRKPT_OP,brkpt_impl,"brkpt",1,9) +OP_W_DEF(BSMAD_OP,bsmad_impl,"bsmad",0,1) +OP_DEF(BSMUL_OP,bsmul_impl,"bsmul",1,1) +OP_DEF(BUF_OP,buf_impl,"buf",0,5) OP_DEF(CALL_OP,call_impl,"call",1,3) OP_DEF(CALLP_OP,callp_impl,"callp",1,3) OP_DEF(CLZ_OP,clz_impl,"clz",1,1) diff --git a/src/cuda-sim/opcodes.h b/src/cuda-sim/opcodes.h index 871091c..aa133da 100644 --- a/src/cuda-sim/opcodes.h +++ b/src/cuda-sim/opcodes.h @@ -30,9 +30,11 @@ enum opcode_t { #define OP_DEF(OP,FUNC,STR,DST,CLASSIFICATION) OP, +#define OP_W_DEF(OP,FUNC,STR,DST,CLASSIFICATION) OP, #include "opcodes.def" - NUM_OPCODES + NUM_OPCODES #undef OP_DEF +#undef OP_W_DEF }; enum special_regs { diff --git a/src/cuda-sim/ptx.l b/src/cuda-sim/ptx.l index 69349a0..e0d7b9d 100644 --- a/src/cuda-sim/ptx.l +++ b/src/cuda-sim/ptx.l @@ -68,6 +68,9 @@ bra TC; ptx_lval.int_value = BRA_OP; return OPCODE; brx TC; ptx_lval.int_value = BRX_OP; return OPCODE; brev TC; ptx_lval.int_value = BREV_OP; return OPCODE; brkpt TC; ptx_lval.int_value = BRKPT_OP; return OPCODE; +bsmad TC; ptx_lval.int_value = BSMAD_OP; return OPCODE; +bsmul TC; ptx_lval.int_value = BSMUL_OP; return OPCODE; +buf TC; ptx_lval.int_value = BUF_OP; return OPCODE; call TC; BEGIN(NOT_OPCODE); ptx_lval.int_value = CALL_OP; return OPCODE; // blocking opcode token in case the callee has the same name as an opcode callp TC; BEGIN(NOT_OPCODE); ptx_lval.int_value = CALLP_OP; return OPCODE; clz TC; ptx_lval.int_value = CLZ_OP; return OPCODE; -- cgit v1.3 From d1b45cf53a39261663a3eff0d409d6c1220d923d Mon Sep 17 00:00:00 2001 From: sspenst Date: Fri, 5 Aug 2016 14:45:56 -0700 Subject: Added ptx_warp_info to know how many threads within a warp have executed --- src/abstract_hardware_model.h | 2 + src/cuda-sim/cuda-sim.cc | 10 +++++ src/cuda-sim/instructions.cc | 95 +++++++++++++++++++++++-------------------- src/cuda-sim/ptx_sim.cc | 21 ++++++++++ src/cuda-sim/ptx_sim.h | 12 ++++++ 5 files changed, 95 insertions(+), 45 deletions(-) (limited to 'src/abstract_hardware_model.h') diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index 13dfce3..cfa8c9f 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -1028,6 +1028,7 @@ class core_t { m_warp_count += 1; } assert( m_warp_count * m_warp_size > 0 ); + //m_warp = ( ptx_warp_info** )calloc( m_warp_count, sizeof( ptx_warp_info* ) ); m_thread = ( ptx_thread_info** ) calloc( m_warp_count * m_warp_size, sizeof( ptx_thread_info* ) ); @@ -1063,6 +1064,7 @@ class core_t { class gpgpu_sim *m_gpu; kernel_info_t *m_kernel; simt_stack **m_simt_stack; // pdom based reconvergence context for each warp + //class ptx_warp_info ** m_warp; class ptx_thread_info ** m_thread; unsigned m_warp_size; unsigned m_warp_count; diff --git a/src/cuda-sim/cuda-sim.cc b/src/cuda-sim/cuda-sim.cc index 337463b..ba0d00b 100644 --- a/src/cuda-sim/cuda-sim.cc +++ b/src/cuda-sim/cuda-sim.cc @@ -1417,6 +1417,7 @@ unsigned ptx_sim_init_thread( kernel_info_t &kernel, static std::map shared_memory_lookup; static std::map sstarr_memory_lookup; static std::map ptx_cta_lookup; + static std::map ptx_warp_lookup; static std::map > local_memory_lookup; if ( *thread_info != NULL ) { @@ -1501,6 +1502,15 @@ unsigned ptx_sim_init_thread( kernel_info_t &kernel, 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(); // num_threads should be threads in the warp + ptx_warp_lookup[hw_warp_id] = warp_info; + } else { + warp_info = ptx_warp_lookup[hw_warp_id]; + } + thd->m_warp_info = warp_info; + memory_space *local_mem = NULL; std::map::iterator l = local_mem_lookup.find(new_tid); if ( l != local_mem_lookup.end() ) { diff --git a/src/cuda-sim/instructions.cc b/src/cuda-sim/instructions.cc index f58c4f5..9dcc25c 100644 --- a/src/cuda-sim/instructions.cc +++ b/src/cuda-sim/instructions.cc @@ -1471,74 +1471,81 @@ void bsmad_impl( const ptx_instruction *pI, core_t *core, warp_inst_t inst ) // 7 = synapse value // 8 = output value - // TODO: what should happen when the output precision is larger than the input precision? - // TODO: create a ptx_warp_info that can do the same thing that ptx_cta_info does here - ptx_cta_info *cta_info = core->get_thread_info()[inst.warp_id() * core->get_warp_size()]->m_cta_info; - const int NUM_THREADS = cta_info->num_threads(); - const int NUM_BUFFERS = 4; - cta_info->inc_bar_threads(); + const operand_info &dst = pI->dst(); + const operand_info &src1 = pI->src1(); + const operand_info &src2 = pI->src2(); + unsigned type = pI->get_type(); + int tid = inst.warp_id() * core->get_warp_size(); + ptx_thread_info *thread = core->get_thread_info()[tid]; + const int ip = (thread->get_operand_value(src1, dst, type, thread, 1)).u32; + const int op = (thread->get_operand_value(src2, dst, type, thread, 1)).u32; + const int THREADS = inst.active_count(); + const int INBUFFERS = 4; + const int OUTBUFFERS = (((32/ip)*INBUFFERS) / (32/op)) + ((((32/ip)*INBUFFERS) % (32/op)) != 0); + if (OUTBUFFERS > THREADS) { + printf("GPGPU-Sim PTX: BSMAD ERROR - Number of output registers required (%d) is greater than the number available (%d)\n", OUTBUFFERS, THREADS); + abort(); + } + ptx_warp_info *warp_info = core->get_thread_info()[inst.warp_id() * core->get_warp_size()]->m_warp_info; + warp_info->inc_done_threads(); // threads within the warp are executed sequentially by the simulator, store output in first four registers - if (cta_info->get_bar_threads() <= NUM_BUFFERS) { - unsigned ip, op; // only get these when i = 0 - unsigned buffer[inst.active_count()][NUM_BUFFERS]; + if (warp_info->get_done_threads() <= OUTBUFFERS) { + unsigned buffer[inst.active_count()][INBUFFERS]; unsigned synapse[inst.active_count()]; - unsigned output[NUM_BUFFERS]; + unsigned output; // loop through all threads in the warp and get all data for (unsigned i = 0, j = 0; i < core->get_warp_size(); i++) { if (inst.active(i)) { - const operand_info dst = pI->dst(); - const operand_info src1 = pI->operand_lookup(1); - const operand_info src2 = pI->operand_lookup(2); - const operand_info src3 = pI->operand_lookup(3); - const operand_info src4 = pI->operand_lookup(4); - const operand_info src5 = pI->operand_lookup(5); - const operand_info src6 = pI->operand_lookup(6); - const operand_info src7 = pI->operand_lookup(7); - const operand_info src8 = pI->operand_lookup(8); - unsigned type = pI->get_type(); - - int tid = inst.warp_id() * core->get_warp_size() + i; - ptx_thread_info *thread = core->get_thread_info()[tid]; - - // only get precision data once - if (j == 0) { - ip = (thread->get_operand_value(src1, dst, type, thread, 1)).u32; - op = (thread->get_operand_value(src2, dst, type, thread, 1)).u32; - } + const operand_info &src3 = pI->operand_lookup(3); + const operand_info &src4 = pI->operand_lookup(4); + const operand_info &src5 = pI->operand_lookup(5); + const operand_info &src6 = pI->operand_lookup(6); + const operand_info &src7 = pI->operand_lookup(7); + const operand_info &src8 = pI->operand_lookup(8); + + thread = core->get_thread_info()[tid+i]; // get buffer data and synapse data from each thread buffer[j][0] = (thread->get_operand_value(src3, dst, type, thread, 1)).u32; buffer[j][1] = (thread->get_operand_value(src4, dst, type, thread, 1)).u32; buffer[j][2] = (thread->get_operand_value(src5, dst, type, thread, 1)).u32; buffer[j][3] = (thread->get_operand_value(src6, dst, type, thread, 1)).u32; synapse[j] = (thread->get_operand_value(src7, dst, type, thread, 1)).u32; + j++; // get output data from the first 4 threads - if (j < NUM_BUFFERS) { - output[j] = (thread->get_operand_value(src8, dst, type, thread, 1)).u32; + if (j == warp_info->get_done_threads()) { + output = (thread->get_operand_value(src8, dst, type, thread, 1)).u32; } - j++; } } // unpack registers, compute enough outputs to fill an output register unsigned *unpacked_output = (unsigned*)calloc(32/op,sizeof(unsigned)); - unsigned buffer_data_start = (32/op)*(cta_info->get_bar_threads()-1); - for (unsigned i = buffer_data_start; i < (32/op + buffer_data_start) && i < (32/ip)*NUM_BUFFERS; i++) { + unsigned buffer_data_start = (32/op)*(warp_info->get_done_threads()-1); + for (unsigned i = buffer_data_start; i < (32/op + buffer_data_start) && i < (32/ip)*INBUFFERS; i++) { unsigned buf = i/(32/ip); unsigned pos = i%(32/ip); - unsigned mask = 0; + int sum = 0; + // sum values from the buffers for (int b = 0; b < ip; b++) { mask |= (1 << b); } mask <<= (pos*ip); - int sum = 0; - for (int j = 0; j < NUM_THREADS; j++) { + for (int j = 0; j < THREADS; j++) { sum += (mask & buffer[j][buf]) >> (pos*ip); } - unpacked_output[i - buffer_data_start] = sum; + // get the previous output + mask = 0; + for (int b = 0; b < op; b++) { + mask |= (1 << b); + } + mask <<= (op*(i-buffer_data_start)); + int past_output = (mask & output) >> (op*(i-buffer_data_start)); + + unpacked_output[i-buffer_data_start] = sum + past_output; } // truncate output @@ -1575,11 +1582,8 @@ void bsmad_impl( const ptx_instruction *pI, core_t *core, warp_inst_t inst ) // store the result in the correct thread's output register for (unsigned i = 0, j = 0; i < core->get_warp_size(); i++) { if (inst.active(i)) j++; - if (j == cta_info->get_bar_threads()) { - const operand_info &dst = pI->dst(); - unsigned type = pI->get_type(); - int tid = inst.warp_id() * core->get_warp_size() + i; - ptx_thread_info *thread = core->get_thread_info()[tid]; + if (j == warp_info->get_done_threads()) { + thread = core->get_thread_info()[tid+i]; ptx_reg_t data; data.u32 = output_data; thread->set_operand_value(dst, data, type, thread, pI); @@ -1588,8 +1592,9 @@ void bsmad_impl( const ptx_instruction *pI, core_t *core, warp_inst_t inst ) } } - if (cta_info->get_bar_threads() == NUM_THREADS) { - cta_info->reset_bar_threads(); + // once the warp has finished, set the number of completed threads back to 0 for the next warp + if (warp_info->get_done_threads() == THREADS) { + warp_info->reset_done_threads(); } } diff --git a/src/cuda-sim/ptx_sim.cc b/src/cuda-sim/ptx_sim.cc index f48115b..820287d 100644 --- a/src/cuda-sim/ptx_sim.cc +++ b/src/cuda-sim/ptx_sim.cc @@ -144,6 +144,26 @@ void ptx_cta_info::reset_bar_threads() m_bar_threads = 0; } +ptx_warp_info::ptx_warp_info() +{ + reset_done_threads(); +} + +unsigned ptx_warp_info::get_done_threads() const +{ + return m_done_threads; +} + +void ptx_warp_info::inc_done_threads() +{ + m_done_threads++; +} + +void ptx_warp_info::reset_done_threads() +{ + m_done_threads = 0; +} + unsigned g_ptx_thread_info_uid_next=1; unsigned g_ptx_thread_info_delete_count=0; @@ -170,6 +190,7 @@ ptx_thread_info::ptx_thread_info( kernel_info_t &kernel ) m_branch_taken = 0; m_shared_mem = NULL; m_sstarr_mem = NULL; + m_warp_info = NULL; m_cta_info = NULL; m_local_mem = NULL; m_symbol_table = NULL; diff --git a/src/cuda-sim/ptx_sim.h b/src/cuda-sim/ptx_sim.h index 4e748e9..c62fa57 100644 --- a/src/cuda-sim/ptx_sim.h +++ b/src/cuda-sim/ptx_sim.h @@ -171,6 +171,17 @@ private: std::set m_dangling_pointers; }; +class ptx_warp_info { +public: + ptx_warp_info(); // add get_core or something, or threads? + unsigned get_done_threads() const; + void inc_done_threads(); + void reset_done_threads(); + +private: + unsigned m_done_threads; +}; + class symbol; struct stack_entry { @@ -430,6 +441,7 @@ public: memory_space *m_shared_mem; memory_space *m_sstarr_mem; memory_space *m_local_mem; + ptx_warp_info *m_warp_info; ptx_cta_info *m_cta_info; ptx_reg_t m_last_set_operand_value; -- cgit v1.3 From de21c009ca25fbbfd460047c3ae8a3cf59c31454 Mon Sep 17 00:00:00 2001 From: sspenst Date: Fri, 5 Aug 2016 14:50:37 -0700 Subject: Deleted useless comments --- src/abstract_hardware_model.h | 2 -- src/cuda-sim/cuda-sim.cc | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) (limited to 'src/abstract_hardware_model.h') diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index cfa8c9f..13dfce3 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -1028,7 +1028,6 @@ class core_t { m_warp_count += 1; } assert( m_warp_count * m_warp_size > 0 ); - //m_warp = ( ptx_warp_info** )calloc( m_warp_count, sizeof( ptx_warp_info* ) ); m_thread = ( ptx_thread_info** ) calloc( m_warp_count * m_warp_size, sizeof( ptx_thread_info* ) ); @@ -1064,7 +1063,6 @@ class core_t { class gpgpu_sim *m_gpu; kernel_info_t *m_kernel; simt_stack **m_simt_stack; // pdom based reconvergence context for each warp - //class ptx_warp_info ** m_warp; class ptx_thread_info ** m_thread; unsigned m_warp_size; unsigned m_warp_count; diff --git a/src/cuda-sim/cuda-sim.cc b/src/cuda-sim/cuda-sim.cc index ba0d00b..53ee25b 100644 --- a/src/cuda-sim/cuda-sim.cc +++ b/src/cuda-sim/cuda-sim.cc @@ -1504,7 +1504,7 @@ unsigned ptx_sim_init_thread( kernel_info_t &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(); // num_threads should be threads in the warp + warp_info = new ptx_warp_info(); ptx_warp_lookup[hw_warp_id] = warp_info; } else { warp_info = ptx_warp_lookup[hw_warp_id]; -- cgit v1.3 From 8c264f2e77fe628987416269a925bb9930a1b813 Mon Sep 17 00:00:00 2001 From: sspenst Date: Mon, 8 Aug 2016 16:10:43 -0700 Subject: Forgot to multiply by the synapse --- src/abstract_hardware_model.h | 2 +- src/cuda-sim/instructions.cc | 35 ++++++++++++----------------------- 2 files changed, 13 insertions(+), 24 deletions(-) (limited to 'src/abstract_hardware_model.h') diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index 13dfce3..c009276 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -788,7 +788,7 @@ public: int src[MAX_REG_OPERANDS]; } arch_reg; //int arch_reg[MAX_REG_OPERANDS]; // register number for bank conflict evaluation - unsigned latency; // operation latency + unsigned latency; // operation latency unsigned initiation_interval; unsigned data_size; // what is the size of the word being operated on? diff --git a/src/cuda-sim/instructions.cc b/src/cuda-sim/instructions.cc index 9dcc25c..3b938bb 100644 --- a/src/cuda-sim/instructions.cc +++ b/src/cuda-sim/instructions.cc @@ -1486,13 +1486,13 @@ void bsmad_impl( const ptx_instruction *pI, core_t *core, warp_inst_t inst ) printf("GPGPU-Sim PTX: BSMAD ERROR - Number of output registers required (%d) is greater than the number available (%d)\n", OUTBUFFERS, THREADS); abort(); } - ptx_warp_info *warp_info = core->get_thread_info()[inst.warp_id() * core->get_warp_size()]->m_warp_info; + ptx_warp_info *warp_info = thread->m_warp_info; warp_info->inc_done_threads(); // threads within the warp are executed sequentially by the simulator, store output in first four registers if (warp_info->get_done_threads() <= OUTBUFFERS) { - unsigned buffer[inst.active_count()][INBUFFERS]; - unsigned synapse[inst.active_count()]; + unsigned buffer[THREADS][INBUFFERS]; + unsigned synapse[THREADS]; unsigned output; // loop through all threads in the warp and get all data @@ -1526,25 +1526,15 @@ void bsmad_impl( const ptx_instruction *pI, core_t *core, warp_inst_t inst ) for (unsigned i = buffer_data_start; i < (32/op + buffer_data_start) && i < (32/ip)*INBUFFERS; i++) { unsigned buf = i/(32/ip); unsigned pos = i%(32/ip); - unsigned mask = 0; - int sum = 0; // sum values from the buffers - for (int b = 0; b < ip; b++) { - mask |= (1 << b); - } - mask <<= (pos*ip); - + int sum = 0; + unsigned mask = (unsigned)(pow(2,ip)-1) << (pos*ip); for (int j = 0; j < THREADS; j++) { - sum += (mask & buffer[j][buf]) >> (pos*ip); + sum += ((mask & buffer[j][buf]) >> (pos*ip)) * synapse[j]; } // get the previous output - mask = 0; - for (int b = 0; b < op; b++) { - mask |= (1 << b); - } - mask <<= (op*(i-buffer_data_start)); + mask = (unsigned)(pow(2,op)-1) << (op*(i-buffer_data_start)); int past_output = (mask & output) >> (op*(i-buffer_data_start)); - unpacked_output[i-buffer_data_start] = sum + past_output; } @@ -1567,13 +1557,8 @@ void bsmad_impl( const ptx_instruction *pI, core_t *core, warp_inst_t inst ) } } - // create mask of 1s - unsigned mask = 0; - for (int b = 0; b < op; b++) { - mask |= (1 << b); - } - // pack the outputs into one register + unsigned mask = pow(2,op)-1; unsigned output_data = 0; for (int i = 0; i < 32/op; i++) { output_data |= (unpacked_output[i] & mask) << (op*i); @@ -1596,6 +1581,10 @@ void bsmad_impl( const ptx_instruction *pI, core_t *core, warp_inst_t inst ) if (warp_info->get_done_threads() == THREADS) { warp_info->reset_done_threads(); } + + // set the latency assuming 4 bits of each input get processed every cycle + // mutable latency variable??? + //pI->latency = (ip+3)/4; } void call_impl( const ptx_instruction *pI, ptx_thread_info *thread ) -- cgit v1.3 From 0751c1489add70d7494521c7f9d65f462e4391c6 Mon Sep 17 00:00:00 2001 From: speverel Date: Sun, 24 Sep 2017 21:12:40 -0700 Subject: Changed how warp level instructions are handled to avoid an assert that is guaranteed to fail in functional simulation only mode. Hopefully this shouldn't introduce any new issues. --- src/abstract_hardware_model.h | 4 ++++ src/cuda-sim/instructions.cc | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'src/abstract_hardware_model.h') diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index 607eda7..cdd9cf3 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -980,6 +980,10 @@ public: assert( !m_empty ); return m_warp_id; } + unsigned warp_id_func() const // to be used in functional simulations only + { + return m_warp_id; + } unsigned dynamic_warp_id() const { assert( !m_empty ); diff --git a/src/cuda-sim/instructions.cc b/src/cuda-sim/instructions.cc index 159fd4c..493e307 100644 --- a/src/cuda-sim/instructions.cc +++ b/src/cuda-sim/instructions.cc @@ -1500,7 +1500,7 @@ void bsmad_impl( const ptx_instruction *pI, core_t *core, warp_inst_t inst ) const operand_info &src1 = pI->src1(); const operand_info &src2 = pI->src2(); unsigned type = pI->get_type(); - int tid = inst.warp_id() * core->get_warp_size(); + int tid = inst.warp_id_func() * core->get_warp_size(); ptx_thread_info *thread = core->get_thread_info()[tid]; const int ip = (thread->get_operand_value(src1, dst, type, thread, 1)).u32; const int op = (thread->get_operand_value(src2, dst, type, thread, 1)).u32; @@ -3698,7 +3698,7 @@ 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(); + int tid = inst.warp_id_func() * 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(); -- cgit v1.3 From 5e8b10d9a0ea518dcb6c3c88b0a9cfd143363bcd Mon Sep 17 00:00:00 2001 From: Amruth Date: Tue, 27 Mar 2018 14:12:05 -0700 Subject: support for pinned memories - temporary fix --- libcuda/cuda_runtime_api.cc | 53 +++++++++++++++++++++++++++++++++++++++++-- src/abstract_hardware_model.h | 3 +++ src/cuda-sim/ptx_ir.cc | 6 +++-- 3 files changed, 58 insertions(+), 4 deletions(-) (limited to 'src/abstract_hardware_model.h') diff --git a/libcuda/cuda_runtime_api.cc b/libcuda/cuda_runtime_api.cc index f74c4eb..97d702c 100644 --- a/libcuda/cuda_runtime_api.cc +++ b/libcuda/cuda_runtime_api.cc @@ -145,6 +145,8 @@ #include #endif +std::map pinned_memory; //support for pinned memories added +std::map pinned_memory_size; int no_of_ptx=0; extern void synchronize(); @@ -476,6 +478,8 @@ __host__ cudaError_t CUDARTAPI cudaMallocHost(void **ptr, size_t size) GPGPUSim_Context(); *ptr = malloc(size); if ( *ptr ) { + //track pinned memory size allocated in the host so that same amount of memory is also allocated in GPU. + pinned_memory_size[*ptr]=size; return g_last_cudaError = cudaSuccess; } else { return g_last_cudaError = cudaErrorMemoryAllocation; @@ -766,6 +770,16 @@ __host__ cudaError_t CUDARTAPI cudaMemset(void *mem, int c, size_t count) return g_last_cudaError = cudaSuccess; } +//memset operation is done but i think its not async? +__host__ cudaError_t CUDARTAPI cudaMemsetAsync(void *mem, int c, size_t count, cudaStream_t stream=0) +{ + printf("GPGPU-Sim PTX: WARNING: Asynchronous memset not supported (%s)\n", __my_func__); + CUctx_st *context = GPGPUSim_Context(); + gpgpu_t *gpu = context->get_device()->get_gpgpu(); + gpu->gpu_memset((size_t)mem, c, count); + return g_last_cudaError = cudaSuccess; +} + __host__ cudaError_t CUDARTAPI cudaMemset2D(void *mem, size_t pitch, int c, size_t width, size_t height) { cuda_not_implemented(__my_func__,__LINE__); @@ -855,6 +869,12 @@ __host__ cudaError_t CUDARTAPI cudaDeviceGetAttribute(int *value, enum cudaDevic case 76: *value= 3 ; break; + case 78: + *value= 0 ; //TODO: as of now, we dont support stream priorities. + break; + default: + printf("ERROR: implement the attribute numbered %d \n",attr); + abort(); } return g_last_cudaError = cudaSuccess; } else { @@ -1054,6 +1074,15 @@ __host__ cudaError_t CUDARTAPI cudaStreamCreate(cudaStream_t *stream) return g_last_cudaError = cudaSuccess; } +//TODO: introduce priorities +__host__ __device__ cudaError_t CUDARTAPI cudaStreamCreateWithPriority(cudaStream_t *stream, unsigned int flags, int priority) { + return cudaStreamCreate(stream); +} + +__host__ __device__ cudaError_t CUDARTAPI cudaDeviceGetStreamPriorityRange(int* leastPriority, int* greatestPriority) { + return cudaSuccess; +} + __host__ __device__ cudaError_t CUDARTAPI cudaStreamCreateWithFlags(cudaStream_t *stream, unsigned int flags) { return cudaStreamCreate(stream); } @@ -2206,6 +2235,9 @@ cudaError_t cudaGLUnregisterBufferObject(GLuint bufferObj) cudaError_t CUDARTAPI cudaHostAlloc(void **pHost, size_t bytes, unsigned int flags) { *pHost = malloc(bytes); + //need to track the size allocated so that cudaHostGetDevicePointer() can function properly. + //TODO: vary this function behavior based on flags value (following nvidia documentation) + pinned_memory_size[*pHost]=bytes; if( *pHost ) return g_last_cudaError = cudaSuccess; else @@ -2214,8 +2246,25 @@ cudaError_t CUDARTAPI cudaHostAlloc(void **pHost, size_t bytes, unsigned int fl cudaError_t CUDARTAPI cudaHostGetDevicePointer(void **pDevice, void *pHost, unsigned int flags) { - cuda_not_implemented(__my_func__,__LINE__); - return g_last_cudaError = cudaErrorUnknown; + //only cpu memory allocation happens in cudaHostAlloc. Linking with device pointer to pinned memory happens here. + //TODO: once kernel is executed, the contents in global pointer of GPU must be copied back to CPU host pointer! + flags=0; + CUctx_st* context = GPGPUSim_Context(); + gpgpu_t *gpu = context->get_device()->get_gpgpu(); + std::map::const_iterator i = pinned_memory_size.find(pHost); + assert(i != pinned_memory_size.end()); + size_t size = i->second; + *pDevice = gpu->gpu_malloc(size); + if(g_debug_execution >= 3) + printf("GPGPU-Sim PTX: cudaMallocing %zu bytes starting at 0x%llx..\n",size, (unsigned long long) *pDevice); + if ( *pDevice ) { + pinned_memory[pHost]=pDevice; + //Copy contents in cpu to gpu + gpu->memcpy_to_gpu((size_t)*pDevice,pHost,size); + return g_last_cudaError = cudaSuccess; + } else { + return g_last_cudaError = cudaErrorMemoryAllocation; + } } cudaError_t CUDARTAPI cudaSetValidDevices(int *device_arr, int len) diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index aaa4b00..67b36c7 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -182,6 +182,9 @@ void increment_x_then_y_then_z( dim3 &i, const dim3 &bound); class stream_manager; struct CUstream_st; extern stream_manager * g_stream_manager; +//support for pinned memories added +extern std::map pinned_memory; +extern std::map pinned_memory_size; class kernel_info_t { public: diff --git a/src/cuda-sim/ptx_ir.cc b/src/cuda-sim/ptx_ir.cc index 6a17eaf..17e91df 100644 --- a/src/cuda-sim/ptx_ir.cc +++ b/src/cuda-sim/ptx_ir.cc @@ -280,8 +280,10 @@ type_info *symbol_table::get_array_type( type_info *base_type, unsigned array_di { type_info_key t = base_type->get_key(); t.set_array_dim(array_dim); - type_info *pt; - pt = m_types[t] = new type_info(this,t); + type_info *pt = new type_info(this,t); + //Where else is m_types being used? As of now, I dont find any use of it and causing seg fault. So disabling m_types. + //TODO: find where m_types can be used in future and solve the seg fault. + //pt = m_types[t] = new type_info(this,t); return pt; } -- cgit v1.3 From 635366fe3e9b596318647b9c5bcdd546c522d52a Mon Sep 17 00:00:00 2001 From: Tor Aamodt Date: Wed, 28 Mar 2018 14:37:43 -0700 Subject: fix compile errors on Ubuntu LTS 16.04 --- libcuda/cuda_runtime_api.cc | 18 +++++++++++------- src/abstract_hardware_model.h | 2 +- src/cuda-sim/cuda-math.h | 2 +- src/cuda-sim/instructions.cc | 8 ++++---- 4 files changed, 17 insertions(+), 13 deletions(-) (limited to 'src/abstract_hardware_model.h') diff --git a/libcuda/cuda_runtime_api.cc b/libcuda/cuda_runtime_api.cc index cbe8a11..b7f25bf 100644 --- a/libcuda/cuda_runtime_api.cc +++ b/libcuda/cuda_runtime_api.cc @@ -1406,7 +1406,7 @@ void extract_code_using_cuobjdump(){ cmd << "ldd " << app_binary << " | grep $CUDA_INSTALL_PATH | awk \'{print $3}\' > _tempfile_.txt"; int result = system(cmd.str().c_str()); if(result){ - std::cout << "Failed to execute: " << cmd << std::endl; + std::cout << "Failed to execute: " << cmd.str() << std::endl; exit(1); } std::ifstream libsf; @@ -1438,7 +1438,7 @@ void extract_code_using_cuobjdump(){ if(result) {printf("ERROR: Failed to execute: %s\n", command); exit(1);} std::cout << "Done" << std::endl; - std::cout << "Trying to parse " << libcodfn << std::endl; + std::cout << "Trying to parse " << libcodfn.str() << std::endl; cuobjdump_in = fopen(libcodfn.str().c_str(), "r"); cuobjdump_parse(); fclose(cuobjdump_in); @@ -1540,7 +1540,7 @@ std::list pruneSectionList(std::list cuobj //! Merge all PTX sections that have a specific identifier into one file std::list mergeMatchingSections(std::list cuobjdumpSectionList, std::string identifier){ - char *ptxcode = ""; + const char *ptxcode = ""; std::list::iterator old_iter; cuobjdumpPTXSection* old_ptxsection = NULL; cuobjdumpPTXSection* ptxsection; @@ -1689,7 +1689,7 @@ std::mapfatbin_registered; std::map name_symtab; //! Keep track of the association between filename and cubin handle -void cuobjdumpRegisterFatBinary(unsigned int handle, char* filename){ +void cuobjdumpRegisterFatBinary(unsigned int handle, const char* filename){ fatbinmap[handle] = filename; } @@ -1764,6 +1764,7 @@ void** CUDARTAPI __cudaRegisterFatBinary( void *fatCubin ) if (sizeof(void*) == 4) printf("GPGPU-Sim PTX: FatBin file name extraction has not been tested on 32-bit system.\n"); + #if (CUDART_VERSION <= 6000) // FatBin handle from the .fatbin.c file (one of the intermediate files generated by NVCC) typedef struct {int m; int v; const unsigned long long* d; char* f;} __fatDeviceText __attribute__ ((aligned (8))); __fatDeviceText * fatDeviceText = (__fatDeviceText *) fatCubin; @@ -1772,12 +1773,11 @@ void** CUDARTAPI __cudaRegisterFatBinary( void *fatCubin ) // - Obtains the pointer to the actual fatbin structure from the FatBin handle (fatCubin). // - An integer inside the fatbin structure contains the relative offset to the source code file name. // - This offset differs among different CUDA and GCC versions. - #if (CUDART_VERSION <= 6000) char * pfatbin = (char*) fatDeviceText->d; int offset = *((int*)(pfatbin+48)); char * filename = (pfatbin+16+offset); #else - char * filename = "default"; + const char * filename = "default"; #endif // The extracted file name is associated with a fat_cubin_handle passed // into cudaLaunch(). Inside cudaLaunch(), the associated file name is @@ -1798,7 +1798,7 @@ void** CUDARTAPI __cudaRegisterFatBinary( void *fatCubin ) return (void**)fat_cubin_handle; } - #if (CUDART_VERSION < 8000) +#if (CUDART_VERSION < 8000) else { static unsigned source_num=1; unsigned long long fat_cubin_handle = next_fat_bin_handle++; @@ -1857,6 +1857,10 @@ void** CUDARTAPI __cudaRegisterFatBinary( void *fatCubin ) return (void**)fat_cubin_handle; } #endif + else { + printf("ERROR ** __cudaRegisterFatBinary() needs to be updated\n"); + abort(); + } } void __cudaUnregisterFatBinary(void **fatCubinHandle) diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index aaa4b00..7125b6b 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -383,7 +383,7 @@ protected: std::deque m_stack; }; -#define GLOBAL_HEAP_START 0x703E20000 +#define GLOBAL_HEAP_START 0xC0000000 // start allocating from this address (lower values used for allocating globals in .ptx file) #define SHARED_MEM_SIZE_MAX (64*1024) #define LOCAL_MEM_SIZE_MAX (8*1024) diff --git a/src/cuda-sim/cuda-math.h b/src/cuda-sim/cuda-math.h index 4721e8a..a3db0df 100644 --- a/src/cuda-sim/cuda-math.h +++ b/src/cuda-sim/cuda-math.h @@ -321,7 +321,7 @@ float __internal_accurate_fdividef(float a, float b) float __saturatef(float a) { float b; - if (isnan(a)) b = 0.0f; + if (std::isnan(a)) b = 0.0f; else if (a >= 1.0f) b = 1.0f; else if (a <= 0.0f) b = 0.0f; else b = a; diff --git a/src/cuda-sim/instructions.cc b/src/cuda-sim/instructions.cc index 011c285..71286c9 100644 --- a/src/cuda-sim/instructions.cc +++ b/src/cuda-sim/instructions.cc @@ -1961,7 +1961,7 @@ ptx_reg_t d2d( ptx_reg_t x, unsigned from_width, unsigned to_width, int to_sign, y.f64 = x.f64; break; } - if (isnan(y.f64)) { + if (std::isnan(y.f64)) { y.u64 = 0xfff8000000000000ull; } else if (saturation_mode) { y.f64 = cuda_math::__saturatef(y.f64); @@ -2086,7 +2086,7 @@ void ptx_round(ptx_reg_t& data, int rounding_mode, int type) } } if ((type == F64_TYPE)||(type == FF64_TYPE)) { - if (isnan(data.f64)) { + if (std::isnan(data.f64)) { data.u64 = 0xfff8000000000000ull; } } @@ -2648,12 +2648,12 @@ void mad_def( const ptx_instruction *pI, ptx_thread_info *thread, bool use_carry bool isNaN(float x) { - return isnan(x); + return std::isnan(x); } bool isNaN(double x) { - return isnan(x); + return std::isnan(x); } void max_impl( const ptx_instruction *pI, ptx_thread_info *thread ) -- cgit v1.3 From 68674d4ba230df0d3bf9f4e5b035f4cf9cfc185b Mon Sep 17 00:00:00 2001 From: negargoli93 Date: Sat, 12 May 2018 16:09:04 -0700 Subject: commit for eece527project --- src/abstract_hardware_model.h | 6 +- src/cuda-sim/cuda-sim.cc | 11 ++- src/cuda-sim/instructions.cc | 213 +++++++++++++++++++----------------------- src/cuda-sim/opcodes.def | 2 +- src/cuda-sim/ptx.l | 2 +- src/cuda-sim/ptx_ir.h | 25 +++++ src/gpgpu-sim/scoreboard.cc | 4 + src/gpgpusim_entrypoint.cc | 1 - 8 files changed, 136 insertions(+), 128 deletions(-) (limited to 'src/abstract_hardware_model.h') diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index cdd9cf3..9dc58d4 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -750,7 +750,7 @@ public: }; // the maximum number of destination, source, or address uarch operands in a instruction -#define MAX_REG_OPERANDS 8 +#define MAX_REG_OPERANDS 32 struct dram_callback_t { dram_callback_t() { function=NULL; instruction=NULL; thread=NULL; } @@ -825,8 +825,8 @@ public: address_type reconvergence_pc; // -1 => not a branch, -2 => use function return address - unsigned out[4]; - unsigned in[4]; + unsigned out[8]; + unsigned in[8]; unsigned char is_vectorin; unsigned char is_vectorout; int pred; // predicate register number diff --git a/src/cuda-sim/cuda-sim.cc b/src/cuda-sim/cuda-sim.cc index 54d8796..006738a 100644 --- a/src/cuda-sim/cuda-sim.cc +++ b/src/cuda-sim/cuda-sim.cc @@ -792,9 +792,9 @@ void ptx_instruction::set_opcode_and_latency() initiation_interval = dp_init[2]; op = SFU_OP; break; - case BSMAD_OP: - latency = int_precision/int_lane_width; - initiation_interval = int_init_precision/int_init_lane_width; + case MMA_OP: + latency = 64; + initiation_interval = 64; break; case SHFL_OP: latency = 32; @@ -1301,6 +1301,7 @@ void ptx_thread_info::ptx_exec_inst( warp_inst_t &inst, unsigned lane_id) *((warp_inst_t*)pJ) = inst; // copy active mask information pI = pJ; } + if((pI->get_opcode()!=MMA_OP)||((pI->get_opcode()==MMA_OP)&&(lane_id==0))){ switch ( pI->get_opcode() ) { #define OP_DEF(OP,FUNC,STR,DST,CLASSIFICATION) case OP: FUNC(pI,this); op_classification = CLASSIFICATION; break; #define OP_W_DEF(OP,FUNC,STR,DST,CLASSIFICATION) case OP: FUNC(pI,get_core(),inst); op_classification = CLASSIFICATION; break; @@ -1308,7 +1309,7 @@ void ptx_thread_info::ptx_exec_inst( warp_inst_t &inst, unsigned lane_id) #undef OP_DEF #undef OP_W_DEF default: printf( "Execution error: Invalid opcode (0x%x)\n", pI->get_opcode() ); break; - } + }} delete pJ; pI = pI_saved; @@ -1930,7 +1931,7 @@ void functionalCoreSim::executeWarp(unsigned i, bool &allAtBarrier, bool & someO { if(!m_warpAtBarrier[i] && m_liveThreadCount[i]!=0){ warp_inst_t inst =getExecuteWarp(i); - execute_warp_inst_t(inst,i); + execute_warp_inst_t(inst,i); if(inst.isatomic()) inst.do_atomic(true); if(inst.op==BARRIER_OP || inst.op==MEMORY_BARRIER_OP ) m_warpAtBarrier[i]=true; updateSIMTStack( i, &inst ); diff --git a/src/cuda-sim/instructions.cc b/src/cuda-sim/instructions.cc index 493e307..7903343 100644 --- a/src/cuda-sim/instructions.cc +++ b/src/cuda-sim/instructions.cc @@ -771,6 +771,17 @@ void add_impl( const ptx_instruction *pI, ptx_thread_info *thread ) unsigned i_type = pI->get_type(); src1_data = thread->get_operand_value(src1, dst, i_type, thread, 1); src2_data = thread->get_operand_value(src2, dst, i_type, thread, 1); + //unsigned warpId_aa,warp_size_aa; + //warpId_aa = pI->warp_id(); + //warp_size_aa=32; + //dim3 t=thread->get_tid(); + //unsigned tid_aa=warp_size_aa*warpId_aa; + + ptx_thread_info *thread2; + thread2=thread; + src1_data = thread2->get_operand_value(src1, dst, i_type, thread2, 1); + src2_data = thread2->get_operand_value(src2, dst, i_type, thread2, 1); + unsigned rounding_mode = pI->rounding_mode(); int orig_rm = fegetround(); @@ -1483,135 +1494,102 @@ unsigned trunc(unsigned num, unsigned precision) { return num; } -void bsmad_impl( const ptx_instruction *pI, core_t *core, warp_inst_t inst ) +void mma_impl( const ptx_instruction *pI, core_t *core, warp_inst_t inst ) { - // operands: - // 0 = output - // 1 = input precision - // 2 = output precision - // 3 = buffer0 - // 4 = buffer1 - // 5 = buffer2 - // 6 = buffer3 - // 7 = synapse value - // 8 = output value + int i,j,k,thrd; + int row,offset; + printf("mmaWorld\n"); + ptx_reg_t matrix_a[16][16]; + ptx_reg_t matrix_b[16][16]; + ptx_reg_t matrix_c[16][16]; + ptx_reg_t matrix_d[16][16]; + ptx_reg_t src_data; + ptx_thread_info *thread; - const operand_info &dst = pI->dst(); - const operand_info &src1 = pI->src1(); - const operand_info &src2 = pI->src2(); unsigned type = pI->get_type(); int tid = inst.warp_id_func() * core->get_warp_size(); - ptx_thread_info *thread = core->get_thread_info()[tid]; - const int ip = (thread->get_operand_value(src1, dst, type, thread, 1)).u32; - const int op = (thread->get_operand_value(src2, dst, type, thread, 1)).u32; - const int THREADS = inst.active_count(); - const int INBUFFERS = 4; - const int OUTBUFFERS = (((32/ip)*INBUFFERS) / (32/op)) + ((((32/ip)*INBUFFERS) % (32/op)) != 0); - if (OUTBUFFERS > THREADS) { - printf("GPGPU-Sim PTX: BSMAD ERROR - Number of output registers required (%d) is greater than the number available (%d)\n", OUTBUFFERS, THREADS); - abort(); - } - ptx_warp_info *warp_info = thread->m_warp_info; - warp_info->inc_done_threads(); + const operand_info &dst = pI->operand_lookup(0); + +//NOT WOR thread = core->get_thread_info()[tid]; +//NOT WOR const operand_info &src_a= pI->operand_lookup(1); +//NOT WOR src_data= (thread->get_operand_value(src_a, dst, type, thread, 1)); +//NOT WOR thread->set_operand_value(dst, src_data, type, thread, pI); + for (thrd=0; thrd < core->get_warp_size(); thrd++){ + row=thrd/2; + offset=8*(thrd%2); + thread = core->get_thread_info()[tid+thrd]; + printf("thread=%d:",thrd); + for(i=8;i<=31;i++){ + const operand_info &src_a= pI->operand_lookup(i); + src_data= (thread->get_operand_value(src_a, dst, type, thread, 1)); + printf("%f ",src_data.f32); + if(i<=15) + matrix_a[row][offset+(i)%8]=src_data; + else if((i>15)&&(i<=23)) + matrix_b[row][offset+(i)%8]=src_data; + else if(i>23) + matrix_c[row][offset+(i)%8]=src_data; + - // threads within the warp are executed sequentially by the simulator, store output in first four registers - if (warp_info->get_done_threads() <= OUTBUFFERS) { - unsigned buffer[THREADS][INBUFFERS]; - unsigned synapse[THREADS]; - unsigned output; - - // loop through all threads in the warp and get all data - for (unsigned i = 0, j = 0; i < core->get_warp_size(); i++) { - if (inst.active(i)) { - const operand_info &src3 = pI->operand_lookup(3); - const operand_info &src4 = pI->operand_lookup(4); - const operand_info &src5 = pI->operand_lookup(5); - const operand_info &src6 = pI->operand_lookup(6); - const operand_info &src7 = pI->operand_lookup(7); - const operand_info &src8 = pI->operand_lookup(8); - - thread = core->get_thread_info()[tid+i]; - // get buffer data and synapse data from each thread - buffer[j][0] = (thread->get_operand_value(src3, dst, type, thread, 1)).u32; - buffer[j][1] = (thread->get_operand_value(src4, dst, type, thread, 1)).u32; - buffer[j][2] = (thread->get_operand_value(src5, dst, type, thread, 1)).u32; - buffer[j][3] = (thread->get_operand_value(src6, dst, type, thread, 1)).u32; - synapse[j] = (thread->get_operand_value(src7, dst, type, thread, 1)).u32; - j++; - // get output data from the first 4 threads - if (j == warp_info->get_done_threads()) { - output = (thread->get_operand_value(src8, dst, type, thread, 1)).u32; - } - } } + printf("\n"); + } - // unpack registers, compute enough outputs to fill an output register - unsigned *unpacked_output = (unsigned*)calloc(32/op,sizeof(unsigned)); - unsigned buffer_data_start = (32/op)*(warp_info->get_done_threads()-1); - for (unsigned i = buffer_data_start; i < (32/op + buffer_data_start) && i < (32/ip)*INBUFFERS; i++) { - unsigned buf = i/(32/ip); - unsigned pos = i%(32/ip); - // sum values from the buffers - int sum = 0; - unsigned mask = (unsigned)(pow(2,ip)-1) << (pos*ip); - for (int j = 0; j < THREADS; j++) { - //sum += ((mask & buffer[j][buf]) >> (pos*ip)) * synapse[j]; - sum += trunc(((mask & buffer[j][buf]) >> (pos*ip)) * synapse[j], op); - } - // get the previous output - mask = (unsigned)(pow(2,op)-1) << (op*(i-buffer_data_start)); - int past_output = (mask & output) >> (op*(i-buffer_data_start)); - unpacked_output[i-buffer_data_start] = trunc(trunc(sum,op) + past_output,op); - // truncate sum, truncate (truncated sum + past_output) + printf("MATRIX_A\n"); + for (i=0;i<16;i++){ + for(j=0;j<16;j++){ + printf("%f ",matrix_a[i][j].f32); } - - // truncate output - /*for (unsigned i = 0; i < 32/op; i++) { - int mask = 1, latest_one = -1; - unsigned data = unpacked_output[i]; - for (unsigned j = 0; j < sizeof(unsigned)*8; j++) { - int bit = data & mask; - if (bit == 1) latest_one = j; - data >>= 1; - } - if (latest_one >= op) { - // round_up is 1 if the most significant truncated digit is a 1, otherwise it is 0 - int round_up = (unpacked_output[i] & (1 << (latest_one-op))) >> (latest_one-op); - unsigned shifted_output = unpacked_output[i] >> (latest_one-op+1); - // if shifted_output is a number like 1111, don't round up - if (shifted_output == (pow(2,op)-1)) round_up = 0; - unpacked_output[i] = shifted_output + round_up; - } - }*/ - - // pack the outputs into one register - unsigned mask = pow(2,op)-1; - unsigned output_data = 0; - for (int i = 0; i < 32/op; i++) { - output_data |= (unpacked_output[i] & mask) << (op*i); + printf("\n"); + } + printf("MATRIX_B\n"); + for (i=0;i<16;i++){ + for(j=0;j<16;j++){ + printf("%f ",matrix_b[i][j].f32); } - - // store the result in the correct thread's output register - for (unsigned i = 0, j = 0; i < core->get_warp_size(); i++) { - if (inst.active(i)) j++; - if (j == warp_info->get_done_threads()) { - thread = core->get_thread_info()[tid+i]; - ptx_reg_t data; - data.u32 = output_data; - thread->set_operand_value(dst, data, type, thread, pI); - break; + printf("\n"); + } + printf("MATRIX_C\n"); + for (i=0;i<16;i++){ + for(j=0;j<16;j++){ + printf("%f ",matrix_c[i][j].f32); + } + printf("\n"); + } + for (i=0;i<16;i++){ + for(j=0;j<16;j++){ + matrix_d[i][j].f32=0; + } + } + + for (i=0;i<16;i++){ + for(j=0;j<16;j++){ + for(k=0;k<16;k++){ + matrix_d[i][j].f32=matrix_d[i][j].f32+matrix_a[i][k].f32*matrix_b[j][k].f32; } + matrix_d[i][j].f32+=matrix_c[i][j].f32; } } - - // once the warp has finished, set the number of completed threads back to 0 for the next warp - if (warp_info->get_done_threads() == THREADS) { - warp_info->reset_done_threads(); + printf("MATRIX_D\n"); + for (i=0;i<16;i++){ + for(j=0;j<16;j++){ + printf("%f ",matrix_d[i][j].f32); + } + printf("\n"); + } + for (thrd=0; thrd < core->get_warp_size(); thrd++){ + thread = core->get_thread_info()[tid+thrd]; + row=thrd/2; + offset=8*(thrd%2); + for(i=0;i<8;i++){ + const operand_info &dst = pI->operand_lookup(i); + const symbol *r2; + r2=dst.get_symbol(); + printf("thrd=%d,i=%d,register%s, data=%f\n",thrd,i,(r2->name()).c_str(),matrix_d[row][offset+i].f32); + thread->set_operand_value(dst, matrix_d[row][offset+i], type, thread, pI); + } } - - // set the latency assuming 4 bits of each input get processed every cycle - // mutable latency variable??? - //pI->latency = (ip+3)/4; + } void call_impl( const ptx_instruction *pI, ptx_thread_info *thread ) @@ -4098,7 +4076,8 @@ void st_impl( const ptx_instruction *pI, ptx_thread_info *thread ) if (!vector_spec) { data = thread->get_operand_value(src1, dst, type, thread, 1); mem->write(addr,size/8,&data.s64,thread,pI); - } else { + printf("addr=%d data=%d\n",addr,data.s64); + } else { if (vector_spec == V2_TYPE) { ptx_reg_t* ptx_regs = new ptx_reg_t[2]; thread->get_vector_operand_values(src1, ptx_regs, 2); diff --git a/src/cuda-sim/opcodes.def b/src/cuda-sim/opcodes.def index 41f2f22..a3cc83f 100644 --- a/src/cuda-sim/opcodes.def +++ b/src/cuda-sim/opcodes.def @@ -52,7 +52,7 @@ OP_DEF(BRA_OP,bra_impl,"bra",0,3) OP_DEF(BRX_OP,brx_impl,"brx",0,3) OP_DEF(BREV_OP,brev_impl,"brev",1,1) OP_DEF(BRKPT_OP,brkpt_impl,"brkpt",1,9) -OP_W_DEF(BSMAD_OP,bsmad_impl,"bsmad",1,1) +OP_W_DEF(MMA_OP,mma_impl,"mma",1,1) OP_DEF(CALL_OP,call_impl,"call",1,3) OP_DEF(CALLP_OP,callp_impl,"callp",1,3) OP_DEF(CLZ_OP,clz_impl,"clz",1,1) diff --git a/src/cuda-sim/ptx.l b/src/cuda-sim/ptx.l index 7620134..e07e339 100644 --- a/src/cuda-sim/ptx.l +++ b/src/cuda-sim/ptx.l @@ -68,7 +68,7 @@ bra TC; ptx_lval.int_value = BRA_OP; return OPCODE; brx TC; ptx_lval.int_value = BRX_OP; return OPCODE; brev TC; ptx_lval.int_value = BREV_OP; return OPCODE; brkpt TC; ptx_lval.int_value = BRKPT_OP; return OPCODE; -bsmad TC; ptx_lval.int_value = BSMAD_OP; return OPCODE; +mma TC; ptx_lval.int_value = MMA_OP; return OPCODE; call TC; BEGIN(NOT_OPCODE); ptx_lval.int_value = CALL_OP; return OPCODE; // blocking opcode token in case the callee has the same name as an opcode callp TC; BEGIN(NOT_OPCODE); ptx_lval.int_value = CALLP_OP; return OPCODE; clz TC; ptx_lval.int_value = CLZ_OP; return OPCODE; diff --git a/src/cuda-sim/ptx_ir.h b/src/cuda-sim/ptx_ir.h index 4c10373..0601b97 100644 --- a/src/cuda-sim/ptx_ir.h +++ b/src/cuda-sim/ptx_ir.h @@ -948,6 +948,31 @@ public: assert( m_operands.size() > 3 ); return m_operands[3]; } + const operand_info &src4() const + { + assert( m_operands.size() > 4 ); + return m_operands[4]; + } + const operand_info &src5() const + { + assert( m_operands.size() > 5 ); + return m_operands[5]; + } + const operand_info &src6() const + { + assert( m_operands.size() > 6 ); + return m_operands[6]; + } + const operand_info &src7() const + { + assert( m_operands.size() > 7 ); + return m_operands[7]; + } + const operand_info &src8() const + { + assert( m_operands.size() > 8 ); + return m_operands[8]; + } const operand_info &operand_lookup( unsigned n ) const { diff --git a/src/gpgpu-sim/scoreboard.cc b/src/gpgpu-sim/scoreboard.cc index f412054..b538fdf 100644 --- a/src/gpgpu-sim/scoreboard.cc +++ b/src/gpgpu-sim/scoreboard.cc @@ -146,6 +146,10 @@ bool Scoreboard::checkCollision( unsigned wid, const class inst_t *inst ) const if(inst->in[1] > 0) inst_regs.insert(inst->in[1]); if(inst->in[2] > 0) inst_regs.insert(inst->in[2]); if(inst->in[3] > 0) inst_regs.insert(inst->in[3]); + if(inst->in[3] > 0) inst_regs.insert(inst->in[4]); + if(inst->in[3] > 0) inst_regs.insert(inst->in[5]); + if(inst->in[3] > 0) inst_regs.insert(inst->in[6]); + if(inst->in[3] > 0) inst_regs.insert(inst->in[7]); if(inst->pred > 0) inst_regs.insert(inst->pred); if(inst->ar1 > 0) inst_regs.insert(inst->ar1); if(inst->ar2 > 0) inst_regs.insert(inst->ar2); diff --git a/src/gpgpusim_entrypoint.cc b/src/gpgpusim_entrypoint.cc index 04845e7..a6d7eb4 100644 --- a/src/gpgpusim_entrypoint.cc +++ b/src/gpgpusim_entrypoint.cc @@ -134,7 +134,6 @@ void *gpgpu_sim_thread_concurrent(void*) 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(); -- cgit v1.3 From 4fb2d23f350bd8921417f5c09bde73594e5c8a0b Mon Sep 17 00:00:00 2001 From: Jonathan Date: Thu, 17 May 2018 09:27:07 -0700 Subject: allows gpgpusim to select a set of texture array,attr,info but maybe not the right one --- src/abstract_hardware_model.h | 73 +++++++++++++++++++++++++++++++++++++------ src/cuda-sim/cuda-sim.cc | 30 ++++++++++++++++++ 2 files changed, 94 insertions(+), 9 deletions(-) (limited to 'src/abstract_hardware_model.h') diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index f5708bc..ca41e68 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -522,22 +522,77 @@ public: } const struct cudaArray* get_texarray( const struct textureReference *texref ) const { - std::map::const_iterator t=m_TextureRefToCudaArray.find(texref); - assert(t != m_TextureRefToCudaArray.end()); - return t->second; + + for (std::map::const_iterator kv = m_TextureRefToCudaArray.begin(); kv!= m_TextureRefToCudaArray.end(); kv ++){ + const struct textureReference* tr = kv->first; + if (tr->normalized==texref->normalized&& + tr->filterMode==texref->filterMode&& + tr->addressMode[0]==texref->addressMode[0]&& + tr->addressMode[1]==texref->addressMode[1]&& + tr->addressMode[2]==texref->addressMode[2]&& + tr->channelDesc.x==texref->channelDesc.x&& + tr->channelDesc.y==texref->channelDesc.y&& + tr->channelDesc.z==texref->channelDesc.z&& + tr->channelDesc.w==texref->channelDesc.w&& + tr->channelDesc.f==texref->channelDesc.f){ + + return kv->second; + } + } + + assert(false); +// std::map::const_iterator t=m_TextureRefToCudaArray.find(texref); +// assert(t != m_TextureRefToCudaArray.end()); +// return t->second; } const struct textureInfo* get_texinfo( const struct textureReference *texref ) const { - std::map::const_iterator t=m_TextureRefToTexureInfo.find(texref); - assert(t != m_TextureRefToTexureInfo.end()); - return t->second; + for (std::map::const_iterator kv = m_TextureRefToTexureInfo.begin(); kv!= m_TextureRefToTexureInfo.end(); kv ++){ + const struct textureReference* tr = kv->first; + if (tr->normalized==texref->normalized&& + tr->filterMode==texref->filterMode&& + tr->addressMode[0]==texref->addressMode[0]&& + tr->addressMode[1]==texref->addressMode[1]&& + tr->addressMode[2]==texref->addressMode[2]&& + tr->channelDesc.x==texref->channelDesc.x&& + tr->channelDesc.y==texref->channelDesc.y&& + tr->channelDesc.z==texref->channelDesc.z&& + tr->channelDesc.w==texref->channelDesc.w&& + tr->channelDesc.f==texref->channelDesc.f){ + + return kv->second; + } + } + + assert(false); +// std::map::const_iterator t=m_TextureRefToTexureInfo.find(texref); +// assert(t != m_TextureRefToTexureInfo.end()); +// return t->second; } const struct textureReferenceAttr* get_texattr( const struct textureReference *texref ) const { - std::map::const_iterator t=m_TextureRefToAttribute.find(texref); - assert(t != m_TextureRefToAttribute.end()); - return t->second; + for (std::map::const_iterator kv = m_TextureRefToAttribute.begin(); kv!= m_TextureRefToAttribute.end(); kv ++){ + const struct textureReference* tr = kv->first; + if (tr->normalized==texref->normalized&& + tr->filterMode==texref->filterMode&& + tr->addressMode[0]==texref->addressMode[0]&& + tr->addressMode[1]==texref->addressMode[1]&& + tr->addressMode[2]==texref->addressMode[2]&& + tr->channelDesc.x==texref->channelDesc.x&& + tr->channelDesc.y==texref->channelDesc.y&& + tr->channelDesc.z==texref->channelDesc.z&& + tr->channelDesc.w==texref->channelDesc.w&& + tr->channelDesc.f==texref->channelDesc.f){ + + return kv->second; + } + } + + assert(false); +// std::map::const_iterator t=m_TextureRefToAttribute.find(texref); +// assert(t != m_TextureRefToAttribute.end()); +// return t->second; } const gpgpu_functional_sim_config &get_config() const { return m_function_model_config; } diff --git a/src/cuda-sim/cuda-sim.cc b/src/cuda-sim/cuda-sim.cc index 946043a..6e04ca8 100644 --- a/src/cuda-sim/cuda-sim.cc +++ b/src/cuda-sim/cuda-sim.cc @@ -140,6 +140,36 @@ unsigned int intLOGB2( unsigned int v ) { void gpgpu_t::gpgpu_ptx_sim_bindTextureToArray(const struct textureReference* texref, const struct cudaArray* array) { + // counts number of matches +// int normalized; +// enum cudaTextureFilterMode filterMode; +// enum cudaTextureAddressMode addressMode[3]; +// struct cudaChannelFormatDesc channelDesc; +// int x; +// int y; +// int z; +// int w; +// enum cudaChannelFormatKind f; +// int trMatches = 0; +// for (auto& kv : m_NameToTextureRef){ +// const struct textureReference* tr = kv.second; +// if (tr->normalized==texref->normalized&& +// tr->filterMode==texref->filterMode&& +// tr->addressMode[0]==texref->addressMode[0]&& +// tr->addressMode[1]==texref->addressMode[1]&& +// tr->addressMode[2]==texref->addressMode[2]&& +// tr->channelDesc.x==texref->channelDesc.x&& +// tr->channelDesc.y==texref->channelDesc.y&& +// tr->channelDesc.z==texref->channelDesc.z&& +// tr->channelDesc.w==texref->channelDesc.w&& +// tr->channelDesc.f==texref->channelDesc.f){ +// +// m_TextureRefToCudaArray[tr] = array; +// trMatches++; +// } +// } +// printf("GPGPU-Sim PTX: matches to texref = %d\n", trMatches); +// assert(trMatches==1); m_TextureRefToCudaArray[texref] = array; unsigned int texel_size_bits = array->desc.w + array->desc.x + array->desc.y + array->desc.z; unsigned int texel_size = texel_size_bits/8; -- cgit v1.3 From d36216db7a9d1d2360acf00afb5303b1f76fb7c7 Mon Sep 17 00:00:00 2001 From: Jonathan Date: Thu, 17 May 2018 16:24:41 -0700 Subject: counting matches with same texref contents, added cuda8 fields to texref struct --- src/abstract_hardware_model.h | 143 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 130 insertions(+), 13 deletions(-) (limited to 'src/abstract_hardware_model.h') diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index ca41e68..c21ff6d 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -25,6 +25,11 @@ // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef VERSION_EIGHT +#define VERSION_EIGHT +#endif + #ifndef ABSTRACT_HARDWARE_MODEL_INCLUDED #define ABSTRACT_HARDWARE_MODEL_INCLUDED @@ -445,6 +450,35 @@ struct textureReference { enum cudaTextureFilterMode filterMode; enum cudaTextureAddressMode addressMode[3]; struct cudaChannelFormatDesc channelDesc; + +#ifdef VERSION_EIGHT + /** + * Perform sRGB->linear conversion during texture read + */ + int sRGB; + /** + * Limit to the anisotropy ratio + */ + unsigned int maxAnisotropy; + /** + * Mipmap filter mode + */ + enum cudaTextureFilterMode mipmapFilterMode; + /** + * Offset applied to the supplied mipmap level + */ + float mipmapLevelBias; + /** + * Lower end of the mipmap level range to clamp access to + */ + float minMipmapLevelClamp; + /** + * Upper end of the mipmap level range to clamp access to + */ + float maxMipmapLevelClamp; + int __cudaReserved[15]; +#endif + }; #endif @@ -522,7 +556,8 @@ public: } const struct cudaArray* get_texarray( const struct textureReference *texref ) const { - + int matches = 0; + const struct cudaArray* t = NULL; for (std::map::const_iterator kv = m_TextureRefToCudaArray.begin(); kv!= m_TextureRefToCudaArray.end(); kv ++){ const struct textureReference* tr = kv->first; if (tr->normalized==texref->normalized&& @@ -534,19 +569,49 @@ public: tr->channelDesc.y==texref->channelDesc.y&& tr->channelDesc.z==texref->channelDesc.z&& tr->channelDesc.w==texref->channelDesc.w&& - tr->channelDesc.f==texref->channelDesc.f){ - - return kv->second; + tr->channelDesc.f==texref->channelDesc.f && + tr->sRGB==texref->sRGB&& + tr->maxAnisotropy==texref->maxAnisotropy&& + tr->mipmapFilterMode==texref->mipmapFilterMode&& + tr->mipmapLevelBias==texref->mipmapLevelBias&& + tr->minMipmapLevelClamp==texref->minMipmapLevelClamp&& + tr->maxMipmapLevelClamp==texref->maxMipmapLevelClamp&& + tr->__cudaReserved[0] ==texref->__cudaReserved[0]&& + tr->__cudaReserved[1] ==texref->__cudaReserved[1]&& + tr->__cudaReserved[2] ==texref->__cudaReserved[2]&& + tr->__cudaReserved[3] ==texref->__cudaReserved[3]&& + tr->__cudaReserved[4] ==texref->__cudaReserved[4]&& + tr->__cudaReserved[5] ==texref->__cudaReserved[5]&& + tr->__cudaReserved[6] ==texref->__cudaReserved[6]&& + tr->__cudaReserved[7] ==texref->__cudaReserved[7]&& + tr->__cudaReserved[8] ==texref->__cudaReserved[8]&& + tr->__cudaReserved[9] ==texref->__cudaReserved[9]&& + tr->__cudaReserved[10]==texref->__cudaReserved[10]&& + tr->__cudaReserved[11]==texref->__cudaReserved[11]&& + tr->__cudaReserved[12]==texref->__cudaReserved[12]&& + tr->__cudaReserved[13]==texref->__cudaReserved[13]&& + tr->__cudaReserved[14]==texref->__cudaReserved[14] + ){ + matches++; + t = kv->second; + //return kv->second; } } - assert(false); + printf("matches (texarray) = %d\n", matches); + //assert(matches==1); + return t; + + //assert(false); + // std::map::const_iterator t=m_TextureRefToCudaArray.find(texref); // assert(t != m_TextureRefToCudaArray.end()); // return t->second; } const struct textureInfo* get_texinfo( const struct textureReference *texref ) const { + int matches = 0; + const struct textureInfo* t = NULL; for (std::map::const_iterator kv = m_TextureRefToTexureInfo.begin(); kv!= m_TextureRefToTexureInfo.end(); kv ++){ const struct textureReference* tr = kv->first; if (tr->normalized==texref->normalized&& @@ -558,13 +623,38 @@ public: tr->channelDesc.y==texref->channelDesc.y&& tr->channelDesc.z==texref->channelDesc.z&& tr->channelDesc.w==texref->channelDesc.w&& - tr->channelDesc.f==texref->channelDesc.f){ - - return kv->second; + tr->channelDesc.f==texref->channelDesc.f&& + tr->sRGB==texref->sRGB&& + tr->maxAnisotropy==texref->maxAnisotropy&& + tr->mipmapFilterMode==texref->mipmapFilterMode&& + tr->mipmapLevelBias==texref->mipmapLevelBias&& + tr->minMipmapLevelClamp==texref->minMipmapLevelClamp&& + tr->maxMipmapLevelClamp==texref->maxMipmapLevelClamp&& + tr->__cudaReserved[0] ==texref->__cudaReserved[0]&& + tr->__cudaReserved[1] ==texref->__cudaReserved[1]&& + tr->__cudaReserved[2] ==texref->__cudaReserved[2]&& + tr->__cudaReserved[3] ==texref->__cudaReserved[3]&& + tr->__cudaReserved[4] ==texref->__cudaReserved[4]&& + tr->__cudaReserved[5] ==texref->__cudaReserved[5]&& + tr->__cudaReserved[6] ==texref->__cudaReserved[6]&& + tr->__cudaReserved[7] ==texref->__cudaReserved[7]&& + tr->__cudaReserved[8] ==texref->__cudaReserved[8]&& + tr->__cudaReserved[9] ==texref->__cudaReserved[9]&& + tr->__cudaReserved[10]==texref->__cudaReserved[10]&& + tr->__cudaReserved[11]==texref->__cudaReserved[11]&& + tr->__cudaReserved[12]==texref->__cudaReserved[12]&& + tr->__cudaReserved[13]==texref->__cudaReserved[13]&& + tr->__cudaReserved[14]==texref->__cudaReserved[14]){ + matches++; + t = kv->second; + //return kv->second; } } - assert(false); + printf("matches (texinfo) = %d\n", matches); + //assert(matches==1); + return t; + // std::map::const_iterator t=m_TextureRefToTexureInfo.find(texref); // assert(t != m_TextureRefToTexureInfo.end()); // return t->second; @@ -572,6 +662,8 @@ public: const struct textureReferenceAttr* get_texattr( const struct textureReference *texref ) const { + int matches = 0; + const struct textureReferenceAttr* t = NULL; for (std::map::const_iterator kv = m_TextureRefToAttribute.begin(); kv!= m_TextureRefToAttribute.end(); kv ++){ const struct textureReference* tr = kv->first; if (tr->normalized==texref->normalized&& @@ -583,13 +675,38 @@ public: tr->channelDesc.y==texref->channelDesc.y&& tr->channelDesc.z==texref->channelDesc.z&& tr->channelDesc.w==texref->channelDesc.w&& - tr->channelDesc.f==texref->channelDesc.f){ - - return kv->second; + tr->channelDesc.f==texref->channelDesc.f&& + tr->sRGB==texref->sRGB&& + tr->maxAnisotropy==texref->maxAnisotropy&& + tr->mipmapFilterMode==texref->mipmapFilterMode&& + tr->mipmapLevelBias==texref->mipmapLevelBias&& + tr->minMipmapLevelClamp==texref->minMipmapLevelClamp&& + tr->maxMipmapLevelClamp==texref->maxMipmapLevelClamp&& + tr->__cudaReserved[0] ==texref->__cudaReserved[0]&& + tr->__cudaReserved[1] ==texref->__cudaReserved[1]&& + tr->__cudaReserved[2] ==texref->__cudaReserved[2]&& + tr->__cudaReserved[3] ==texref->__cudaReserved[3]&& + tr->__cudaReserved[4] ==texref->__cudaReserved[4]&& + tr->__cudaReserved[5] ==texref->__cudaReserved[5]&& + tr->__cudaReserved[6] ==texref->__cudaReserved[6]&& + tr->__cudaReserved[7] ==texref->__cudaReserved[7]&& + tr->__cudaReserved[8] ==texref->__cudaReserved[8]&& + tr->__cudaReserved[9] ==texref->__cudaReserved[9]&& + tr->__cudaReserved[10]==texref->__cudaReserved[10]&& + tr->__cudaReserved[11]==texref->__cudaReserved[11]&& + tr->__cudaReserved[12]==texref->__cudaReserved[12]&& + tr->__cudaReserved[13]==texref->__cudaReserved[13]&& + tr->__cudaReserved[14]==texref->__cudaReserved[14]){ + matches++; + t = kv->second; + //return kv->second; } } - assert(false); + printf("matches (texattr) = %d\n", matches); + //assert(matches==1); + return t; + // std::map::const_iterator t=m_TextureRefToAttribute.find(texref); // assert(t != m_TextureRefToAttribute.end()); // return t->second; -- cgit v1.3 From d75898c2bf867ac6ea45594f3da9f18525f2ad6f Mon Sep 17 00:00:00 2001 From: Jonathan Date: Thu, 17 May 2018 16:26:55 -0700 Subject: abstract_hardware_model.h:texrefAttr is different and can be searched via pointer cuda-sim.cc: counts matches between cudaBinTextureToArray texref param (pointer) to texref pointers in m_NameToTextureRef --- src/abstract_hardware_model.h | 94 +++++++++++++++++++++---------------------- src/cuda-sim/cuda-sim.cc | 47 +++++++++++++++++----- 2 files changed, 84 insertions(+), 57 deletions(-) (limited to 'src/abstract_hardware_model.h') diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index c21ff6d..608a7e2 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -662,54 +662,54 @@ public: const struct textureReferenceAttr* get_texattr( const struct textureReference *texref ) const { - int matches = 0; - const struct textureReferenceAttr* t = NULL; - for (std::map::const_iterator kv = m_TextureRefToAttribute.begin(); kv!= m_TextureRefToAttribute.end(); kv ++){ - const struct textureReference* tr = kv->first; - if (tr->normalized==texref->normalized&& - tr->filterMode==texref->filterMode&& - tr->addressMode[0]==texref->addressMode[0]&& - tr->addressMode[1]==texref->addressMode[1]&& - tr->addressMode[2]==texref->addressMode[2]&& - tr->channelDesc.x==texref->channelDesc.x&& - tr->channelDesc.y==texref->channelDesc.y&& - tr->channelDesc.z==texref->channelDesc.z&& - tr->channelDesc.w==texref->channelDesc.w&& - tr->channelDesc.f==texref->channelDesc.f&& - tr->sRGB==texref->sRGB&& - tr->maxAnisotropy==texref->maxAnisotropy&& - tr->mipmapFilterMode==texref->mipmapFilterMode&& - tr->mipmapLevelBias==texref->mipmapLevelBias&& - tr->minMipmapLevelClamp==texref->minMipmapLevelClamp&& - tr->maxMipmapLevelClamp==texref->maxMipmapLevelClamp&& - tr->__cudaReserved[0] ==texref->__cudaReserved[0]&& - tr->__cudaReserved[1] ==texref->__cudaReserved[1]&& - tr->__cudaReserved[2] ==texref->__cudaReserved[2]&& - tr->__cudaReserved[3] ==texref->__cudaReserved[3]&& - tr->__cudaReserved[4] ==texref->__cudaReserved[4]&& - tr->__cudaReserved[5] ==texref->__cudaReserved[5]&& - tr->__cudaReserved[6] ==texref->__cudaReserved[6]&& - tr->__cudaReserved[7] ==texref->__cudaReserved[7]&& - tr->__cudaReserved[8] ==texref->__cudaReserved[8]&& - tr->__cudaReserved[9] ==texref->__cudaReserved[9]&& - tr->__cudaReserved[10]==texref->__cudaReserved[10]&& - tr->__cudaReserved[11]==texref->__cudaReserved[11]&& - tr->__cudaReserved[12]==texref->__cudaReserved[12]&& - tr->__cudaReserved[13]==texref->__cudaReserved[13]&& - tr->__cudaReserved[14]==texref->__cudaReserved[14]){ - matches++; - t = kv->second; - //return kv->second; - } - } - - printf("matches (texattr) = %d\n", matches); - //assert(matches==1); - return t; +// int matches = 0; +// const struct textureReferenceAttr* t = NULL; +// for (std::map::const_iterator kv = m_TextureRefToAttribute.begin(); kv!= m_TextureRefToAttribute.end(); kv ++){ +// const struct textureReference* tr = kv->first; +// if (tr->normalized==texref->normalized&& +// tr->filterMode==texref->filterMode&& +// tr->addressMode[0]==texref->addressMode[0]&& +// tr->addressMode[1]==texref->addressMode[1]&& +// tr->addressMode[2]==texref->addressMode[2]&& +// tr->channelDesc.x==texref->channelDesc.x&& +// tr->channelDesc.y==texref->channelDesc.y&& +// tr->channelDesc.z==texref->channelDesc.z&& +// tr->channelDesc.w==texref->channelDesc.w&& +// tr->channelDesc.f==texref->channelDesc.f&& +// tr->sRGB==texref->sRGB&& +// tr->maxAnisotropy==texref->maxAnisotropy&& +// tr->mipmapFilterMode==texref->mipmapFilterMode&& +// tr->mipmapLevelBias==texref->mipmapLevelBias&& +// tr->minMipmapLevelClamp==texref->minMipmapLevelClamp&& +// tr->maxMipmapLevelClamp==texref->maxMipmapLevelClamp&& +// tr->__cudaReserved[0] ==texref->__cudaReserved[0]&& +// tr->__cudaReserved[1] ==texref->__cudaReserved[1]&& +// tr->__cudaReserved[2] ==texref->__cudaReserved[2]&& +// tr->__cudaReserved[3] ==texref->__cudaReserved[3]&& +// tr->__cudaReserved[4] ==texref->__cudaReserved[4]&& +// tr->__cudaReserved[5] ==texref->__cudaReserved[5]&& +// tr->__cudaReserved[6] ==texref->__cudaReserved[6]&& +// tr->__cudaReserved[7] ==texref->__cudaReserved[7]&& +// tr->__cudaReserved[8] ==texref->__cudaReserved[8]&& +// tr->__cudaReserved[9] ==texref->__cudaReserved[9]&& +// tr->__cudaReserved[10]==texref->__cudaReserved[10]&& +// tr->__cudaReserved[11]==texref->__cudaReserved[11]&& +// tr->__cudaReserved[12]==texref->__cudaReserved[12]&& +// tr->__cudaReserved[13]==texref->__cudaReserved[13]&& +// tr->__cudaReserved[14]==texref->__cudaReserved[14]){ +// matches++; +// t = kv->second; +// //return kv->second; +// } +// } +// +// printf("matches (texattr) = %d\n", matches); +// //assert(matches==1); +// return t; -// std::map::const_iterator t=m_TextureRefToAttribute.find(texref); -// assert(t != m_TextureRefToAttribute.end()); -// return t->second; + std::map::const_iterator t=m_TextureRefToAttribute.find(texref); + assert(t != m_TextureRefToAttribute.end()); + return t->second; } const gpgpu_functional_sim_config &get_config() const { return m_function_model_config; } diff --git a/src/cuda-sim/cuda-sim.cc b/src/cuda-sim/cuda-sim.cc index 6e04ca8..39ffa63 100644 --- a/src/cuda-sim/cuda-sim.cc +++ b/src/cuda-sim/cuda-sim.cc @@ -26,6 +26,10 @@ // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#ifndef VERSION_EIGHT +#define VERSION_EIGHT +#endif + #include "cuda-sim.h" #include "instructions.h" @@ -104,6 +108,16 @@ static address_type get_converge_point(address_type pc); void gpgpu_t::gpgpu_ptx_sim_bindNameToTexture(const char* name, const struct textureReference* texref, int dim, int readmode, int ext) { + +//#ifdef VERSION_EIGHT +// int i; +// printf("%s ", name); +// printf("__cudaReserved:"); +// for (i = 0; i<15; i++){ +// printf(" %i", texref->__cudaReserved[i]); +// } +// printf("\n"); +//#endif std::string texname(name); m_NameToTextureRef[texname] = texref; const textureReferenceAttr *texAttr = new textureReferenceAttr(texref, dim, (enum cudaTextureReadMode)readmode, ext); @@ -140,16 +154,15 @@ unsigned int intLOGB2( unsigned int v ) { void gpgpu_t::gpgpu_ptx_sim_bindTextureToArray(const struct textureReference* texref, const struct cudaArray* array) { +//#ifdef VERSION_EIGHT +// int i; +// printf("__cudaReserved:"); +// for (i = 0; i<15; i++){ +// printf(" %i", texref->__cudaReserved[i]); +// } +// printf("\n"); +//#endif // counts number of matches -// int normalized; -// enum cudaTextureFilterMode filterMode; -// enum cudaTextureAddressMode addressMode[3]; -// struct cudaChannelFormatDesc channelDesc; -// int x; -// int y; -// int z; -// int w; -// enum cudaChannelFormatKind f; // int trMatches = 0; // for (auto& kv : m_NameToTextureRef){ // const struct textureReference* tr = kv.second; @@ -170,7 +183,21 @@ void gpgpu_t::gpgpu_ptx_sim_bindTextureToArray(const struct textureReference* te // } // printf("GPGPU-Sim PTX: matches to texref = %d\n", trMatches); // assert(trMatches==1); - m_TextureRefToCudaArray[texref] = array; + + //tests if texref pointer matches any pointer in m_NameToTextureRef map + int trMatches = 0; + for (auto& kv : m_NameToTextureRef){ + const struct textureReference* tr = kv.second; + if (tr==texref){ + m_TextureRefToCudaArray[tr] = array; + //printf("%s\n", kv.first); + trMatches++; + } + } + printf("GPGPU-Sim PTX: matches to texref = %d\n", trMatches); + //assert(trMatches==1); + + //m_TextureRefToCudaArray[texref] = array; unsigned int texel_size_bits = array->desc.w + array->desc.x + array->desc.y + array->desc.z; unsigned int texel_size = texel_size_bits/8; unsigned int Tx, Ty; -- cgit v1.3 From 3b4c3898771ac5e774bca9445a5a4a81670b7b17 Mon Sep 17 00:00:00 2001 From: Jonathan Date: Fri, 18 May 2018 10:50:19 -0700 Subject: reverted cuda8 changes (extra fields) and assert texture bug fix's assumption --- src/abstract_hardware_model.h | 134 ++++++++++++++---------------------------- src/cuda-sim/cuda-sim.cc | 59 +------------------ 2 files changed, 45 insertions(+), 148 deletions(-) (limited to 'src/abstract_hardware_model.h') diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index 608a7e2..412c0a8 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -451,33 +451,32 @@ struct textureReference { enum cudaTextureAddressMode addressMode[3]; struct cudaChannelFormatDesc channelDesc; -#ifdef VERSION_EIGHT - /** - * Perform sRGB->linear conversion during texture read - */ - int sRGB; - /** - * Limit to the anisotropy ratio - */ - unsigned int maxAnisotropy; - /** - * Mipmap filter mode - */ - enum cudaTextureFilterMode mipmapFilterMode; - /** - * Offset applied to the supplied mipmap level - */ - float mipmapLevelBias; - /** - * Lower end of the mipmap level range to clamp access to - */ - float minMipmapLevelClamp; - /** - * Upper end of the mipmap level range to clamp access to - */ - float maxMipmapLevelClamp; - int __cudaReserved[15]; -#endif +//following commented section applies only to CUDA_VERSION 8+ +// /** +// * Perform sRGB->linear conversion during texture read +// */ +// int sRGB; +// /** +// * Limit to the anisotropy ratio +// */ +// unsigned int maxAnisotropy; +// /** +// * Mipmap filter mode +// */ +// enum cudaTextureFilterMode mipmapFilterMode; +// /** +// * Offset applied to the supplied mipmap level +// */ +// float mipmapLevelBias; +// /** +// * Lower end of the mipmap level range to clamp access to +// */ +// float minMipmapLevelClamp; +// /** +// * Upper end of the mipmap level range to clamp access to +// */ +// float maxMipmapLevelClamp; +// int __cudaReserved[15]; }; @@ -569,7 +568,10 @@ public: tr->channelDesc.y==texref->channelDesc.y&& tr->channelDesc.z==texref->channelDesc.z&& tr->channelDesc.w==texref->channelDesc.w&& - tr->channelDesc.f==texref->channelDesc.f && + tr->channelDesc.f==texref->channelDesc.f + //following commented section applies only to CUDA_VERSION 8+ + /* + && tr->sRGB==texref->sRGB&& tr->maxAnisotropy==texref->maxAnisotropy&& tr->mipmapFilterMode==texref->mipmapFilterMode&& @@ -591,6 +593,7 @@ public: tr->__cudaReserved[12]==texref->__cudaReserved[12]&& tr->__cudaReserved[13]==texref->__cudaReserved[13]&& tr->__cudaReserved[14]==texref->__cudaReserved[14] + */ ){ matches++; t = kv->second; @@ -598,15 +601,9 @@ public: } } - printf("matches (texarray) = %d\n", matches); - //assert(matches==1); + //printf("matches (texarray) = %d\n", matches); + assert(matches==1); return t; - - //assert(false); - -// std::map::const_iterator t=m_TextureRefToCudaArray.find(texref); -// assert(t != m_TextureRefToCudaArray.end()); -// return t->second; } const struct textureInfo* get_texinfo( const struct textureReference *texref ) const { @@ -623,7 +620,10 @@ public: tr->channelDesc.y==texref->channelDesc.y&& tr->channelDesc.z==texref->channelDesc.z&& tr->channelDesc.w==texref->channelDesc.w&& - tr->channelDesc.f==texref->channelDesc.f&& + tr->channelDesc.f==texref->channelDesc.f + //following commented section applies only to CUDA_VERSION 8+ + /* + && tr->sRGB==texref->sRGB&& tr->maxAnisotropy==texref->maxAnisotropy&& tr->mipmapFilterMode==texref->mipmapFilterMode&& @@ -644,69 +644,23 @@ public: tr->__cudaReserved[11]==texref->__cudaReserved[11]&& tr->__cudaReserved[12]==texref->__cudaReserved[12]&& tr->__cudaReserved[13]==texref->__cudaReserved[13]&& - tr->__cudaReserved[14]==texref->__cudaReserved[14]){ + tr->__cudaReserved[14]==texref->__cudaReserved[14] + */ + ){ matches++; t = kv->second; - //return kv->second; } } - printf("matches (texinfo) = %d\n", matches); - //assert(matches==1); + //printf("matches (texinfo) = %d\n", matches); + assert(matches==1); return t; - -// std::map::const_iterator t=m_TextureRefToTexureInfo.find(texref); -// assert(t != m_TextureRefToTexureInfo.end()); -// return t->second; } const struct textureReferenceAttr* get_texattr( const struct textureReference *texref ) const { -// int matches = 0; -// const struct textureReferenceAttr* t = NULL; -// for (std::map::const_iterator kv = m_TextureRefToAttribute.begin(); kv!= m_TextureRefToAttribute.end(); kv ++){ -// const struct textureReference* tr = kv->first; -// if (tr->normalized==texref->normalized&& -// tr->filterMode==texref->filterMode&& -// tr->addressMode[0]==texref->addressMode[0]&& -// tr->addressMode[1]==texref->addressMode[1]&& -// tr->addressMode[2]==texref->addressMode[2]&& -// tr->channelDesc.x==texref->channelDesc.x&& -// tr->channelDesc.y==texref->channelDesc.y&& -// tr->channelDesc.z==texref->channelDesc.z&& -// tr->channelDesc.w==texref->channelDesc.w&& -// tr->channelDesc.f==texref->channelDesc.f&& -// tr->sRGB==texref->sRGB&& -// tr->maxAnisotropy==texref->maxAnisotropy&& -// tr->mipmapFilterMode==texref->mipmapFilterMode&& -// tr->mipmapLevelBias==texref->mipmapLevelBias&& -// tr->minMipmapLevelClamp==texref->minMipmapLevelClamp&& -// tr->maxMipmapLevelClamp==texref->maxMipmapLevelClamp&& -// tr->__cudaReserved[0] ==texref->__cudaReserved[0]&& -// tr->__cudaReserved[1] ==texref->__cudaReserved[1]&& -// tr->__cudaReserved[2] ==texref->__cudaReserved[2]&& -// tr->__cudaReserved[3] ==texref->__cudaReserved[3]&& -// tr->__cudaReserved[4] ==texref->__cudaReserved[4]&& -// tr->__cudaReserved[5] ==texref->__cudaReserved[5]&& -// tr->__cudaReserved[6] ==texref->__cudaReserved[6]&& -// tr->__cudaReserved[7] ==texref->__cudaReserved[7]&& -// tr->__cudaReserved[8] ==texref->__cudaReserved[8]&& -// tr->__cudaReserved[9] ==texref->__cudaReserved[9]&& -// tr->__cudaReserved[10]==texref->__cudaReserved[10]&& -// tr->__cudaReserved[11]==texref->__cudaReserved[11]&& -// tr->__cudaReserved[12]==texref->__cudaReserved[12]&& -// tr->__cudaReserved[13]==texref->__cudaReserved[13]&& -// tr->__cudaReserved[14]==texref->__cudaReserved[14]){ -// matches++; -// t = kv->second; -// //return kv->second; -// } -// } -// -// printf("matches (texattr) = %d\n", matches); -// //assert(matches==1); -// return t; - + //note textureReferenceAttr map behaves differently from cudaArray and + //textureInfo maps std::map::const_iterator t=m_TextureRefToAttribute.find(texref); assert(t != m_TextureRefToAttribute.end()); return t->second; diff --git a/src/cuda-sim/cuda-sim.cc b/src/cuda-sim/cuda-sim.cc index 656091c..946043a 100644 --- a/src/cuda-sim/cuda-sim.cc +++ b/src/cuda-sim/cuda-sim.cc @@ -26,10 +26,6 @@ // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#ifndef VERSION_EIGHT -#define VERSION_EIGHT -#endif - #include "cuda-sim.h" #include "instructions.h" @@ -108,16 +104,6 @@ static address_type get_converge_point(address_type pc); void gpgpu_t::gpgpu_ptx_sim_bindNameToTexture(const char* name, const struct textureReference* texref, int dim, int readmode, int ext) { - -//#ifdef VERSION_EIGHT -// int i; -// printf("%s ", name); -// printf("__cudaReserved:"); -// for (i = 0; i<15; i++){ -// printf(" %i", texref->__cudaReserved[i]); -// } -// printf("\n"); -//#endif std::string texname(name); m_NameToTextureRef[texname] = texref; const textureReferenceAttr *texAttr = new textureReferenceAttr(texref, dim, (enum cudaTextureReadMode)readmode, ext); @@ -154,50 +140,7 @@ unsigned int intLOGB2( unsigned int v ) { void gpgpu_t::gpgpu_ptx_sim_bindTextureToArray(const struct textureReference* texref, const struct cudaArray* array) { -//#ifdef VERSION_EIGHT -// int i; -// printf("__cudaReserved:"); -// for (i = 0; i<15; i++){ -// printf(" %i", texref->__cudaReserved[i]); -// } -// printf("\n"); -//#endif - // counts number of matches -// int trMatches = 0; -// for (auto& kv : m_NameToTextureRef){ -// const struct textureReference* tr = kv.second; -// if (tr->normalized==texref->normalized&& -// tr->filterMode==texref->filterMode&& -// tr->addressMode[0]==texref->addressMode[0]&& -// tr->addressMode[1]==texref->addressMode[1]&& -// tr->addressMode[2]==texref->addressMode[2]&& -// tr->channelDesc.x==texref->channelDesc.x&& -// tr->channelDesc.y==texref->channelDesc.y&& -// tr->channelDesc.z==texref->channelDesc.z&& -// tr->channelDesc.w==texref->channelDesc.w&& -// tr->channelDesc.f==texref->channelDesc.f){ -// -// m_TextureRefToCudaArray[tr] = array; -// trMatches++; -// } -// } -// printf("GPGPU-Sim PTX: matches to texref = %d\n", trMatches); -// assert(trMatches==1); - - //tests if texref pointer matches any pointer in m_NameToTextureRef map - int trMatches = 0; - for (std::map::const_iterator kv = m_NameToTextureRef.begin(); kv!= m_NameToTextureRef.end(); kv ++){ - const struct textureReference* tr = kv->second; - if (tr==texref){ - m_TextureRefToCudaArray[tr] = array; - printf("%s\n", kv->first.c_str()); - trMatches++; - } - } - printf("GPGPU-Sim PTX: matches to texref = %d\n", trMatches); - //assert(trMatches==1); - - //m_TextureRefToCudaArray[texref] = array; + m_TextureRefToCudaArray[texref] = array; unsigned int texel_size_bits = array->desc.w + array->desc.x + array->desc.y + array->desc.z; unsigned int texel_size = texel_size_bits/8; unsigned int Tx, Ty; -- cgit v1.3 From 6a39e5c5964f23a97dafaa6a66f2a9d9c37bbfdd Mon Sep 17 00:00:00 2001 From: Jonathan Date: Fri, 18 May 2018 11:52:31 -0700 Subject: implemented unbind, currently only affects cudaArray map --- 0517_13-24cudaReserved.log | 0 517-1418cudaReserved.log | 0 libcuda/cuda_runtime_api.cc | 11 +++++++++++ src/abstract_hardware_model.h | 1 + src/cuda-sim/cuda-sim.cc | 5 +++++ 5 files changed, 17 insertions(+) delete mode 100644 0517_13-24cudaReserved.log delete mode 100644 517-1418cudaReserved.log (limited to 'src/abstract_hardware_model.h') diff --git a/0517_13-24cudaReserved.log b/0517_13-24cudaReserved.log deleted file mode 100644 index e69de29..0000000 diff --git a/517-1418cudaReserved.log b/517-1418cudaReserved.log deleted file mode 100644 index e69de29..0000000 diff --git a/libcuda/cuda_runtime_api.cc b/libcuda/cuda_runtime_api.cc index e3c2542..71926f8 100644 --- a/libcuda/cuda_runtime_api.cc +++ b/libcuda/cuda_runtime_api.cc @@ -991,6 +991,14 @@ __host__ cudaError_t CUDARTAPI cudaBindTextureToArray(const struct textureRefere __host__ cudaError_t CUDARTAPI cudaUnbindTexture(const struct textureReference *texref) { + CUctx_st *context = GPGPUSim_Context(); + gpgpu_t *gpu = context->get_device()->get_gpgpu(); + printf("GPGPU-Sim PTX: in cudaUnbindTexture: sizeof(struct textureReference) = %zu\n", sizeof(struct textureReference)); + printf("GPGPU-Sim PTX: Name corresponding to textureReference: %s\n", gpu->gpgpu_ptx_sim_findNamefromTexture(texref)); + const struct cudaArray* array = gpu->get_texarray(texref); + printf("GPGPU-Sim PTX: texref = %p, array = %p\n", texref, array); + + gpu->gpgpu_ptx_sim_unbindTexture(texref); return g_last_cudaError = cudaSuccess; } @@ -2073,10 +2081,12 @@ void __cudaUnregisterFatBinary(void **fatCubinHandle) cudaError_t cudaDeviceReset ( void ) { // Should reset the simulated GPU + // TODO: Implement return g_last_cudaError = cudaSuccess; } cudaError_t CUDARTAPI cudaDeviceSynchronize(void){ // I don't know what this should do + // TODO: Implement return g_last_cudaError = cudaSuccess; } @@ -2178,6 +2188,7 @@ typedef unsigned long GLuint; cudaError_t cudaGLRegisterBufferObject(GLuint bufferObj) { printf("GPGPU-Sim PTX: Execution warning: ignoring call to \"%s\"\n", __my_func__ ); + // TODO: Implement return g_last_cudaError = cudaSuccess; } diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index 412c0a8..3ef450e 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -544,6 +544,7 @@ public: class memory_space *get_surf_memory() { return m_surf_mem; } void gpgpu_ptx_sim_bindTextureToArray(const struct textureReference* texref, const struct cudaArray* array); + void gpgpu_ptx_sim_unbindTexture(const struct textureReference* texref); void gpgpu_ptx_sim_bindNameToTexture(const char* name, const struct textureReference* texref, int dim, int readmode, int ext); const char* gpgpu_ptx_sim_findNamefromTexture(const struct textureReference* texref); diff --git a/src/cuda-sim/cuda-sim.cc b/src/cuda-sim/cuda-sim.cc index 946043a..ef16f43 100644 --- a/src/cuda-sim/cuda-sim.cc +++ b/src/cuda-sim/cuda-sim.cc @@ -183,6 +183,11 @@ void gpgpu_t::gpgpu_ptx_sim_bindTextureToArray(const struct textureReference* te m_TextureRefToTexureInfo[texref] = texInfo; } +void gpgpu_t::gpgpu_ptx_sim_unbindTexture(const struct textureReference* texref) +{ + m_TextureRefToCudaArray.erase(texref); +} + unsigned g_assemble_code_next_pc=0; std::map g_pc_to_finfo; std::vector function_info::s_g_pc_to_insn; -- cgit v1.3 From a93aa28a94140ee912c0cba0d9414d9da1588d54 Mon Sep 17 00:00:00 2001 From: Jonathan Date: Fri, 18 May 2018 14:41:23 -0700 Subject: erase texinfo in unbind and disable assert --- src/abstract_hardware_model.h | 195 ++++++++++++++++++++++-------------------- src/cuda-sim/cuda-sim.cc | 2 + 2 files changed, 104 insertions(+), 93 deletions(-) (limited to 'src/abstract_hardware_model.h') diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index 3ef450e..6dd5436 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -556,106 +556,115 @@ public: } const struct cudaArray* get_texarray( const struct textureReference *texref ) const { - int matches = 0; - const struct cudaArray* t = NULL; - for (std::map::const_iterator kv = m_TextureRefToCudaArray.begin(); kv!= m_TextureRefToCudaArray.end(); kv ++){ - const struct textureReference* tr = kv->first; - if (tr->normalized==texref->normalized&& - tr->filterMode==texref->filterMode&& - tr->addressMode[0]==texref->addressMode[0]&& - tr->addressMode[1]==texref->addressMode[1]&& - tr->addressMode[2]==texref->addressMode[2]&& - tr->channelDesc.x==texref->channelDesc.x&& - tr->channelDesc.y==texref->channelDesc.y&& - tr->channelDesc.z==texref->channelDesc.z&& - tr->channelDesc.w==texref->channelDesc.w&& - tr->channelDesc.f==texref->channelDesc.f - //following commented section applies only to CUDA_VERSION 8+ - /* - && - tr->sRGB==texref->sRGB&& - tr->maxAnisotropy==texref->maxAnisotropy&& - tr->mipmapFilterMode==texref->mipmapFilterMode&& - tr->mipmapLevelBias==texref->mipmapLevelBias&& - tr->minMipmapLevelClamp==texref->minMipmapLevelClamp&& - tr->maxMipmapLevelClamp==texref->maxMipmapLevelClamp&& - tr->__cudaReserved[0] ==texref->__cudaReserved[0]&& - tr->__cudaReserved[1] ==texref->__cudaReserved[1]&& - tr->__cudaReserved[2] ==texref->__cudaReserved[2]&& - tr->__cudaReserved[3] ==texref->__cudaReserved[3]&& - tr->__cudaReserved[4] ==texref->__cudaReserved[4]&& - tr->__cudaReserved[5] ==texref->__cudaReserved[5]&& - tr->__cudaReserved[6] ==texref->__cudaReserved[6]&& - tr->__cudaReserved[7] ==texref->__cudaReserved[7]&& - tr->__cudaReserved[8] ==texref->__cudaReserved[8]&& - tr->__cudaReserved[9] ==texref->__cudaReserved[9]&& - tr->__cudaReserved[10]==texref->__cudaReserved[10]&& - tr->__cudaReserved[11]==texref->__cudaReserved[11]&& - tr->__cudaReserved[12]==texref->__cudaReserved[12]&& - tr->__cudaReserved[13]==texref->__cudaReserved[13]&& - tr->__cudaReserved[14]==texref->__cudaReserved[14] - */ - ){ - matches++; - t = kv->second; - //return kv->second; + + std::map::const_iterator t=m_TextureRefToCudaArray.find(texref); + if(t != m_TextureRefToCudaArray.end()){ + return t->second; + } else{ + int matches = 0; + const struct cudaArray* t = NULL; + for (std::map::const_iterator kv = m_TextureRefToCudaArray.begin(); + kv!= m_TextureRefToCudaArray.end(); kv ++){ + const struct textureReference* tr = kv->first; + if (tr->normalized==texref->normalized&& + tr->filterMode==texref->filterMode&& + tr->addressMode[0]==texref->addressMode[0]&& + tr->addressMode[1]==texref->addressMode[1]&& + tr->addressMode[2]==texref->addressMode[2]&& + tr->channelDesc.x==texref->channelDesc.x&& + tr->channelDesc.y==texref->channelDesc.y&& + tr->channelDesc.z==texref->channelDesc.z&& + tr->channelDesc.w==texref->channelDesc.w&& + tr->channelDesc.f==texref->channelDesc.f + //following commented section applies only to CUDA_VERSION 8+ + /* + && + tr->sRGB==texref->sRGB&& + tr->maxAnisotropy==texref->maxAnisotropy&& + tr->mipmapFilterMode==texref->mipmapFilterMode&& + tr->mipmapLevelBias==texref->mipmapLevelBias&& + tr->minMipmapLevelClamp==texref->minMipmapLevelClamp&& + tr->maxMipmapLevelClamp==texref->maxMipmapLevelClamp&& + tr->__cudaReserved[0] ==texref->__cudaReserved[0]&& + tr->__cudaReserved[1] ==texref->__cudaReserved[1]&& + tr->__cudaReserved[2] ==texref->__cudaReserved[2]&& + tr->__cudaReserved[3] ==texref->__cudaReserved[3]&& + tr->__cudaReserved[4] ==texref->__cudaReserved[4]&& + tr->__cudaReserved[5] ==texref->__cudaReserved[5]&& + tr->__cudaReserved[6] ==texref->__cudaReserved[6]&& + tr->__cudaReserved[7] ==texref->__cudaReserved[7]&& + tr->__cudaReserved[8] ==texref->__cudaReserved[8]&& + tr->__cudaReserved[9] ==texref->__cudaReserved[9]&& + tr->__cudaReserved[10]==texref->__cudaReserved[10]&& + tr->__cudaReserved[11]==texref->__cudaReserved[11]&& + tr->__cudaReserved[12]==texref->__cudaReserved[12]&& + tr->__cudaReserved[13]==texref->__cudaReserved[13]&& + tr->__cudaReserved[14]==texref->__cudaReserved[14] + */ + ){ + matches++; + t = kv->second; + } } + + //assert(matches==1); + return t; } - - //printf("matches (texarray) = %d\n", matches); - assert(matches==1); - return t; } const struct textureInfo* get_texinfo( const struct textureReference *texref ) const { - int matches = 0; - const struct textureInfo* t = NULL; - for (std::map::const_iterator kv = m_TextureRefToTexureInfo.begin(); kv!= m_TextureRefToTexureInfo.end(); kv ++){ - const struct textureReference* tr = kv->first; - if (tr->normalized==texref->normalized&& - tr->filterMode==texref->filterMode&& - tr->addressMode[0]==texref->addressMode[0]&& - tr->addressMode[1]==texref->addressMode[1]&& - tr->addressMode[2]==texref->addressMode[2]&& - tr->channelDesc.x==texref->channelDesc.x&& - tr->channelDesc.y==texref->channelDesc.y&& - tr->channelDesc.z==texref->channelDesc.z&& - tr->channelDesc.w==texref->channelDesc.w&& - tr->channelDesc.f==texref->channelDesc.f - //following commented section applies only to CUDA_VERSION 8+ - /* - && - tr->sRGB==texref->sRGB&& - tr->maxAnisotropy==texref->maxAnisotropy&& - tr->mipmapFilterMode==texref->mipmapFilterMode&& - tr->mipmapLevelBias==texref->mipmapLevelBias&& - tr->minMipmapLevelClamp==texref->minMipmapLevelClamp&& - tr->maxMipmapLevelClamp==texref->maxMipmapLevelClamp&& - tr->__cudaReserved[0] ==texref->__cudaReserved[0]&& - tr->__cudaReserved[1] ==texref->__cudaReserved[1]&& - tr->__cudaReserved[2] ==texref->__cudaReserved[2]&& - tr->__cudaReserved[3] ==texref->__cudaReserved[3]&& - tr->__cudaReserved[4] ==texref->__cudaReserved[4]&& - tr->__cudaReserved[5] ==texref->__cudaReserved[5]&& - tr->__cudaReserved[6] ==texref->__cudaReserved[6]&& - tr->__cudaReserved[7] ==texref->__cudaReserved[7]&& - tr->__cudaReserved[8] ==texref->__cudaReserved[8]&& - tr->__cudaReserved[9] ==texref->__cudaReserved[9]&& - tr->__cudaReserved[10]==texref->__cudaReserved[10]&& - tr->__cudaReserved[11]==texref->__cudaReserved[11]&& - tr->__cudaReserved[12]==texref->__cudaReserved[12]&& - tr->__cudaReserved[13]==texref->__cudaReserved[13]&& - tr->__cudaReserved[14]==texref->__cudaReserved[14] - */ - ){ - matches++; - t = kv->second; + std::map::const_iterator t=m_TextureRefToTexureInfo.find(texref); + if(t != m_TextureRefToTexureInfo.end()){ + return t->second; + }else{ + int matches = 0; + const struct textureInfo* t = NULL; + for (std::map::const_iterator kv = m_TextureRefToTexureInfo.begin(); + kv!= m_TextureRefToTexureInfo.end(); kv ++){ + const struct textureReference* tr = kv->first; + if (tr->normalized==texref->normalized&& + tr->filterMode==texref->filterMode&& + tr->addressMode[0]==texref->addressMode[0]&& + tr->addressMode[1]==texref->addressMode[1]&& + tr->addressMode[2]==texref->addressMode[2]&& + tr->channelDesc.x==texref->channelDesc.x&& + tr->channelDesc.y==texref->channelDesc.y&& + tr->channelDesc.z==texref->channelDesc.z&& + tr->channelDesc.w==texref->channelDesc.w&& + tr->channelDesc.f==texref->channelDesc.f + //following commented section applies only to CUDA_VERSION 8+ + /* + && + tr->sRGB==texref->sRGB&& + tr->maxAnisotropy==texref->maxAnisotropy&& + tr->mipmapFilterMode==texref->mipmapFilterMode&& + tr->mipmapLevelBias==texref->mipmapLevelBias&& + tr->minMipmapLevelClamp==texref->minMipmapLevelClamp&& + tr->maxMipmapLevelClamp==texref->maxMipmapLevelClamp&& + tr->__cudaReserved[0] ==texref->__cudaReserved[0]&& + tr->__cudaReserved[1] ==texref->__cudaReserved[1]&& + tr->__cudaReserved[2] ==texref->__cudaReserved[2]&& + tr->__cudaReserved[3] ==texref->__cudaReserved[3]&& + tr->__cudaReserved[4] ==texref->__cudaReserved[4]&& + tr->__cudaReserved[5] ==texref->__cudaReserved[5]&& + tr->__cudaReserved[6] ==texref->__cudaReserved[6]&& + tr->__cudaReserved[7] ==texref->__cudaReserved[7]&& + tr->__cudaReserved[8] ==texref->__cudaReserved[8]&& + tr->__cudaReserved[9] ==texref->__cudaReserved[9]&& + tr->__cudaReserved[10]==texref->__cudaReserved[10]&& + tr->__cudaReserved[11]==texref->__cudaReserved[11]&& + tr->__cudaReserved[12]==texref->__cudaReserved[12]&& + tr->__cudaReserved[13]==texref->__cudaReserved[13]&& + tr->__cudaReserved[14]==texref->__cudaReserved[14] + */ + ){ + matches++; + t = kv->second; + } } + //assert(matches==1); + return t; } - - //printf("matches (texinfo) = %d\n", matches); - assert(matches==1); - return t; } const struct textureReferenceAttr* get_texattr( const struct textureReference *texref ) const diff --git a/src/cuda-sim/cuda-sim.cc b/src/cuda-sim/cuda-sim.cc index ef16f43..6bdf75f 100644 --- a/src/cuda-sim/cuda-sim.cc +++ b/src/cuda-sim/cuda-sim.cc @@ -140,6 +140,7 @@ unsigned int intLOGB2( unsigned int v ) { void gpgpu_t::gpgpu_ptx_sim_bindTextureToArray(const struct textureReference* texref, const struct cudaArray* array) { + printf("GPGPU-Simm PTX: name from texture = %s\n", gpgpu_ptx_sim_findNamefromTexture(texref)); m_TextureRefToCudaArray[texref] = array; unsigned int texel_size_bits = array->desc.w + array->desc.x + array->desc.y + array->desc.z; unsigned int texel_size = texel_size_bits/8; @@ -186,6 +187,7 @@ void gpgpu_t::gpgpu_ptx_sim_bindTextureToArray(const struct textureReference* te void gpgpu_t::gpgpu_ptx_sim_unbindTexture(const struct textureReference* texref) { m_TextureRefToCudaArray.erase(texref); + m_TextureRefToTexureInfo.erase(texref); } unsigned g_assemble_code_next_pc=0; -- cgit v1.3 From 958e430266cb3de73033a7e0aab6e7c697fdc6bc Mon Sep 17 00:00:00 2001 From: Jonathan Date: Tue, 22 May 2018 09:49:26 -0700 Subject: revert to before texture bug --- libcuda/cuda_runtime_api.cc | 11 ---- src/abstract_hardware_model.h | 144 ++---------------------------------------- src/cuda-sim/cuda-sim.cc | 7 -- 3 files changed, 4 insertions(+), 158 deletions(-) (limited to 'src/abstract_hardware_model.h') diff --git a/libcuda/cuda_runtime_api.cc b/libcuda/cuda_runtime_api.cc index 71926f8..e3c2542 100644 --- a/libcuda/cuda_runtime_api.cc +++ b/libcuda/cuda_runtime_api.cc @@ -991,14 +991,6 @@ __host__ cudaError_t CUDARTAPI cudaBindTextureToArray(const struct textureRefere __host__ cudaError_t CUDARTAPI cudaUnbindTexture(const struct textureReference *texref) { - CUctx_st *context = GPGPUSim_Context(); - gpgpu_t *gpu = context->get_device()->get_gpgpu(); - printf("GPGPU-Sim PTX: in cudaUnbindTexture: sizeof(struct textureReference) = %zu\n", sizeof(struct textureReference)); - printf("GPGPU-Sim PTX: Name corresponding to textureReference: %s\n", gpu->gpgpu_ptx_sim_findNamefromTexture(texref)); - const struct cudaArray* array = gpu->get_texarray(texref); - printf("GPGPU-Sim PTX: texref = %p, array = %p\n", texref, array); - - gpu->gpgpu_ptx_sim_unbindTexture(texref); return g_last_cudaError = cudaSuccess; } @@ -2081,12 +2073,10 @@ void __cudaUnregisterFatBinary(void **fatCubinHandle) cudaError_t cudaDeviceReset ( void ) { // Should reset the simulated GPU - // TODO: Implement return g_last_cudaError = cudaSuccess; } cudaError_t CUDARTAPI cudaDeviceSynchronize(void){ // I don't know what this should do - // TODO: Implement return g_last_cudaError = cudaSuccess; } @@ -2188,7 +2178,6 @@ typedef unsigned long GLuint; cudaError_t cudaGLRegisterBufferObject(GLuint bufferObj) { printf("GPGPU-Sim PTX: Execution warning: ignoring call to \"%s\"\n", __my_func__ ); - // TODO: Implement return g_last_cudaError = cudaSuccess; } diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index 6dd5436..f5708bc 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -25,11 +25,6 @@ // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef VERSION_EIGHT -#define VERSION_EIGHT -#endif - #ifndef ABSTRACT_HARDWARE_MODEL_INCLUDED #define ABSTRACT_HARDWARE_MODEL_INCLUDED @@ -450,34 +445,6 @@ struct textureReference { enum cudaTextureFilterMode filterMode; enum cudaTextureAddressMode addressMode[3]; struct cudaChannelFormatDesc channelDesc; - -//following commented section applies only to CUDA_VERSION 8+ -// /** -// * Perform sRGB->linear conversion during texture read -// */ -// int sRGB; -// /** -// * Limit to the anisotropy ratio -// */ -// unsigned int maxAnisotropy; -// /** -// * Mipmap filter mode -// */ -// enum cudaTextureFilterMode mipmapFilterMode; -// /** -// * Offset applied to the supplied mipmap level -// */ -// float mipmapLevelBias; -// /** -// * Lower end of the mipmap level range to clamp access to -// */ -// float minMipmapLevelClamp; -// /** -// * Upper end of the mipmap level range to clamp access to -// */ -// float maxMipmapLevelClamp; -// int __cudaReserved[15]; - }; #endif @@ -544,7 +511,6 @@ public: class memory_space *get_surf_memory() { return m_surf_mem; } void gpgpu_ptx_sim_bindTextureToArray(const struct textureReference* texref, const struct cudaArray* array); - void gpgpu_ptx_sim_unbindTexture(const struct textureReference* texref); void gpgpu_ptx_sim_bindNameToTexture(const char* name, const struct textureReference* texref, int dim, int readmode, int ext); const char* gpgpu_ptx_sim_findNamefromTexture(const struct textureReference* texref); @@ -556,121 +522,19 @@ public: } const struct cudaArray* get_texarray( const struct textureReference *texref ) const { - std::map::const_iterator t=m_TextureRefToCudaArray.find(texref); - if(t != m_TextureRefToCudaArray.end()){ - return t->second; - } else{ - int matches = 0; - const struct cudaArray* t = NULL; - for (std::map::const_iterator kv = m_TextureRefToCudaArray.begin(); - kv!= m_TextureRefToCudaArray.end(); kv ++){ - const struct textureReference* tr = kv->first; - if (tr->normalized==texref->normalized&& - tr->filterMode==texref->filterMode&& - tr->addressMode[0]==texref->addressMode[0]&& - tr->addressMode[1]==texref->addressMode[1]&& - tr->addressMode[2]==texref->addressMode[2]&& - tr->channelDesc.x==texref->channelDesc.x&& - tr->channelDesc.y==texref->channelDesc.y&& - tr->channelDesc.z==texref->channelDesc.z&& - tr->channelDesc.w==texref->channelDesc.w&& - tr->channelDesc.f==texref->channelDesc.f - //following commented section applies only to CUDA_VERSION 8+ - /* - && - tr->sRGB==texref->sRGB&& - tr->maxAnisotropy==texref->maxAnisotropy&& - tr->mipmapFilterMode==texref->mipmapFilterMode&& - tr->mipmapLevelBias==texref->mipmapLevelBias&& - tr->minMipmapLevelClamp==texref->minMipmapLevelClamp&& - tr->maxMipmapLevelClamp==texref->maxMipmapLevelClamp&& - tr->__cudaReserved[0] ==texref->__cudaReserved[0]&& - tr->__cudaReserved[1] ==texref->__cudaReserved[1]&& - tr->__cudaReserved[2] ==texref->__cudaReserved[2]&& - tr->__cudaReserved[3] ==texref->__cudaReserved[3]&& - tr->__cudaReserved[4] ==texref->__cudaReserved[4]&& - tr->__cudaReserved[5] ==texref->__cudaReserved[5]&& - tr->__cudaReserved[6] ==texref->__cudaReserved[6]&& - tr->__cudaReserved[7] ==texref->__cudaReserved[7]&& - tr->__cudaReserved[8] ==texref->__cudaReserved[8]&& - tr->__cudaReserved[9] ==texref->__cudaReserved[9]&& - tr->__cudaReserved[10]==texref->__cudaReserved[10]&& - tr->__cudaReserved[11]==texref->__cudaReserved[11]&& - tr->__cudaReserved[12]==texref->__cudaReserved[12]&& - tr->__cudaReserved[13]==texref->__cudaReserved[13]&& - tr->__cudaReserved[14]==texref->__cudaReserved[14] - */ - ){ - matches++; - t = kv->second; - } - } - - //assert(matches==1); - return t; - } + assert(t != m_TextureRefToCudaArray.end()); + return t->second; } const struct textureInfo* get_texinfo( const struct textureReference *texref ) const { std::map::const_iterator t=m_TextureRefToTexureInfo.find(texref); - if(t != m_TextureRefToTexureInfo.end()){ - return t->second; - }else{ - int matches = 0; - const struct textureInfo* t = NULL; - for (std::map::const_iterator kv = m_TextureRefToTexureInfo.begin(); - kv!= m_TextureRefToTexureInfo.end(); kv ++){ - const struct textureReference* tr = kv->first; - if (tr->normalized==texref->normalized&& - tr->filterMode==texref->filterMode&& - tr->addressMode[0]==texref->addressMode[0]&& - tr->addressMode[1]==texref->addressMode[1]&& - tr->addressMode[2]==texref->addressMode[2]&& - tr->channelDesc.x==texref->channelDesc.x&& - tr->channelDesc.y==texref->channelDesc.y&& - tr->channelDesc.z==texref->channelDesc.z&& - tr->channelDesc.w==texref->channelDesc.w&& - tr->channelDesc.f==texref->channelDesc.f - //following commented section applies only to CUDA_VERSION 8+ - /* - && - tr->sRGB==texref->sRGB&& - tr->maxAnisotropy==texref->maxAnisotropy&& - tr->mipmapFilterMode==texref->mipmapFilterMode&& - tr->mipmapLevelBias==texref->mipmapLevelBias&& - tr->minMipmapLevelClamp==texref->minMipmapLevelClamp&& - tr->maxMipmapLevelClamp==texref->maxMipmapLevelClamp&& - tr->__cudaReserved[0] ==texref->__cudaReserved[0]&& - tr->__cudaReserved[1] ==texref->__cudaReserved[1]&& - tr->__cudaReserved[2] ==texref->__cudaReserved[2]&& - tr->__cudaReserved[3] ==texref->__cudaReserved[3]&& - tr->__cudaReserved[4] ==texref->__cudaReserved[4]&& - tr->__cudaReserved[5] ==texref->__cudaReserved[5]&& - tr->__cudaReserved[6] ==texref->__cudaReserved[6]&& - tr->__cudaReserved[7] ==texref->__cudaReserved[7]&& - tr->__cudaReserved[8] ==texref->__cudaReserved[8]&& - tr->__cudaReserved[9] ==texref->__cudaReserved[9]&& - tr->__cudaReserved[10]==texref->__cudaReserved[10]&& - tr->__cudaReserved[11]==texref->__cudaReserved[11]&& - tr->__cudaReserved[12]==texref->__cudaReserved[12]&& - tr->__cudaReserved[13]==texref->__cudaReserved[13]&& - tr->__cudaReserved[14]==texref->__cudaReserved[14] - */ - ){ - matches++; - t = kv->second; - } - } - //assert(matches==1); - return t; - } + assert(t != m_TextureRefToTexureInfo.end()); + return t->second; } const struct textureReferenceAttr* get_texattr( const struct textureReference *texref ) const { - //note textureReferenceAttr map behaves differently from cudaArray and - //textureInfo maps std::map::const_iterator t=m_TextureRefToAttribute.find(texref); assert(t != m_TextureRefToAttribute.end()); return t->second; diff --git a/src/cuda-sim/cuda-sim.cc b/src/cuda-sim/cuda-sim.cc index 6bdf75f..946043a 100644 --- a/src/cuda-sim/cuda-sim.cc +++ b/src/cuda-sim/cuda-sim.cc @@ -140,7 +140,6 @@ unsigned int intLOGB2( unsigned int v ) { void gpgpu_t::gpgpu_ptx_sim_bindTextureToArray(const struct textureReference* texref, const struct cudaArray* array) { - printf("GPGPU-Simm PTX: name from texture = %s\n", gpgpu_ptx_sim_findNamefromTexture(texref)); m_TextureRefToCudaArray[texref] = array; unsigned int texel_size_bits = array->desc.w + array->desc.x + array->desc.y + array->desc.z; unsigned int texel_size = texel_size_bits/8; @@ -184,12 +183,6 @@ void gpgpu_t::gpgpu_ptx_sim_bindTextureToArray(const struct textureReference* te m_TextureRefToTexureInfo[texref] = texInfo; } -void gpgpu_t::gpgpu_ptx_sim_unbindTexture(const struct textureReference* texref) -{ - m_TextureRefToCudaArray.erase(texref); - m_TextureRefToTexureInfo.erase(texref); -} - unsigned g_assemble_code_next_pc=0; std::map g_pc_to_finfo; std::vector function_info::s_g_pc_to_insn; -- cgit v1.3 From 4a567a94aca58fdd2298b50ae9e9da3a889e2173 Mon Sep 17 00:00:00 2001 From: Jonathan Date: Tue, 22 May 2018 09:56:07 -0700 Subject: unbind implementation --- libcuda/cuda_runtime_api.cc | 11 ++++++++--- src/abstract_hardware_model.h | 1 + src/cuda-sim/cuda-sim.cc | 6 ++++++ 3 files changed, 15 insertions(+), 3 deletions(-) (limited to 'src/abstract_hardware_model.h') diff --git a/libcuda/cuda_runtime_api.cc b/libcuda/cuda_runtime_api.cc index e3c2542..d971222 100644 --- a/libcuda/cuda_runtime_api.cc +++ b/libcuda/cuda_runtime_api.cc @@ -989,9 +989,14 @@ __host__ cudaError_t CUDARTAPI cudaBindTextureToArray(const struct textureRefere return g_last_cudaError = cudaSuccess; } -__host__ cudaError_t CUDARTAPI cudaUnbindTexture(const struct textureReference *texref) -{ - return g_last_cudaError = cudaSuccess; +__host__ cudaError_t CUDARTAPI cudaUnbindTexture(const struct textureReference *texref) { + CUctx_st *context = GPGPUSim_Context(); + gpgpu_t *gpu = context->get_device()->get_gpgpu(); + printf("GPGPU-Sim PTX: in cudaUnbindTexture: sizeof(struct textureReference) = %zu\n", sizeof(struct textureReference)); + printf("GPGPU-Sim PTX: Name corresponding to textureReference: %s\n", gpu->gpgpu_ptx_sim_findNamefromTexture(texref)); + + gpu->gpgpu_ptx_sim_unbindTexture(texref); + return g_last_cudaError = cudaSuccess; } __host__ cudaError_t CUDARTAPI cudaGetTextureAlignmentOffset(size_t *offset, const struct textureReference *texref) diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index f5708bc..ab94ded 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -512,6 +512,7 @@ public: void gpgpu_ptx_sim_bindTextureToArray(const struct textureReference* texref, const struct cudaArray* array); void gpgpu_ptx_sim_bindNameToTexture(const char* name, const struct textureReference* texref, int dim, int readmode, int ext); + void gpgpu_ptx_sim_unbindTexture(const struct textureReference* texref); const char* gpgpu_ptx_sim_findNamefromTexture(const struct textureReference* texref); const struct textureReference* get_texref(const std::string &texname) const diff --git a/src/cuda-sim/cuda-sim.cc b/src/cuda-sim/cuda-sim.cc index 946043a..6125422 100644 --- a/src/cuda-sim/cuda-sim.cc +++ b/src/cuda-sim/cuda-sim.cc @@ -183,6 +183,12 @@ void gpgpu_t::gpgpu_ptx_sim_bindTextureToArray(const struct textureReference* te m_TextureRefToTexureInfo[texref] = texInfo; } +void gpgpu_t::gpgpu_ptx_sim_unbindTexture(const struct textureReference* texref) +{ + m_TextureRefToCudaArray.erase(texref); + m_TextureRefToTexureInfo.erase(texref); +} + unsigned g_assemble_code_next_pc=0; std::map g_pc_to_finfo; std::vector function_info::s_g_pc_to_insn; -- cgit v1.3 From ff958f36689c9c217eb099326ceb8f70ed3ac447 Mon Sep 17 00:00:00 2001 From: Jonathan Date: Tue, 22 May 2018 14:00:59 -0700 Subject: restructured texref maps to fix texture bug --- src/abstract_hardware_model.h | 36 +++++++++++++++++-------------- src/cuda-sim/cuda-sim.cc | 49 ++++++++++++++++++++++++++++--------------- src/cuda-sim/instructions.cc | 6 +++--- 3 files changed, 55 insertions(+), 36 deletions(-) (limited to 'src/abstract_hardware_model.h') diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index ab94ded..d0af1ea 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -65,6 +65,7 @@ enum FuncCache #include #include +#include typedef unsigned long long new_addr_type; typedef unsigned address_type; @@ -515,29 +516,31 @@ public: void gpgpu_ptx_sim_unbindTexture(const struct textureReference* texref); const char* gpgpu_ptx_sim_findNamefromTexture(const struct textureReference* texref); - const struct textureReference* get_texref(const std::string &texname) const + const struct textureReference* get_texref( const std::string &texname ) const { - std::map::const_iterator t=m_NameToTextureRef.find(texname); + std::map >::const_iterator t=m_NameToTextureRef.find(texname); assert( t != m_NameToTextureRef.end() ); - return t->second; + return *(t->second.begin()); } - const struct cudaArray* get_texarray( const struct textureReference *texref ) const + + const struct cudaArray* get_texarray( const std::string &texname ) const { - std::map::const_iterator t=m_TextureRefToCudaArray.find(texref); - assert(t != m_TextureRefToCudaArray.end()); + std::map::const_iterator t=m_NameToCudaArray.find(texname); + assert(t != m_NameToCudaArray.end()); return t->second; } - const struct textureInfo* get_texinfo( const struct textureReference *texref ) const + + const struct textureInfo* get_texinfo( const std::string &texname ) const { - std::map::const_iterator t=m_TextureRefToTexureInfo.find(texref); - assert(t != m_TextureRefToTexureInfo.end()); + std::map::const_iterator t=m_NameToTexureInfo.find(texname); + assert(t != m_NameToTexureInfo.end()); return t->second; } - const struct textureReferenceAttr* get_texattr( const struct textureReference *texref ) const + const struct textureReferenceAttr* get_texattr( const std::string &texname ) const { - std::map::const_iterator t=m_TextureRefToAttribute.find(texref); - assert(t != m_TextureRefToAttribute.end()); + std::map::const_iterator t=m_NameToAttribute.find(texname); + assert(t != m_NameToAttribute.end()); return t->second; } @@ -554,10 +557,11 @@ protected: unsigned long long m_dev_malloc; - std::map m_NameToTextureRef; - std::map m_TextureRefToCudaArray; - std::map m_TextureRefToTexureInfo; - std::map m_TextureRefToAttribute; + std::map > m_NameToTextureRef; + std::map m_TextureRefToName; + std::map m_NameToCudaArray; + std::map m_NameToTexureInfo; + std::map m_NameToAttribute; }; struct gpgpu_ptx_sim_info diff --git a/src/cuda-sim/cuda-sim.cc b/src/cuda-sim/cuda-sim.cc index 6125422..05b6201 100644 --- a/src/cuda-sim/cuda-sim.cc +++ b/src/cuda-sim/cuda-sim.cc @@ -105,22 +105,36 @@ static address_type get_converge_point(address_type pc); void gpgpu_t::gpgpu_ptx_sim_bindNameToTexture(const char* name, const struct textureReference* texref, int dim, int readmode, int ext) { std::string texname(name); - m_NameToTextureRef[texname] = texref; + if (m_NameToTextureRef.find(texname)==m_NameToTextureRef.end()){ + m_NameToTextureRef[texname] = std::set(); + m_NameToTextureRef[texname].insert(texref); + }else{ + const struct textureReference* tr = *m_NameToTextureRef[texname].begin(); + assert(tr!=NULL); + //asserts that all texrefs in set have same fields + assert(tr->normalized==texref->normalized&& + tr->filterMode==texref->filterMode&& + tr->addressMode[0]==texref->addressMode[0]&& + tr->addressMode[1]==texref->addressMode[1]&& + tr->addressMode[2]==texref->addressMode[2]&& + tr->channelDesc.x==texref->channelDesc.x&& + tr->channelDesc.y==texref->channelDesc.y&& + tr->channelDesc.z==texref->channelDesc.z&& + tr->channelDesc.w==texref->channelDesc.w&& + tr->channelDesc.f==texref->channelDesc.f + ); + m_NameToTextureRef[texname].insert(texref); + } + m_TextureRefToName[texref] = texname; const textureReferenceAttr *texAttr = new textureReferenceAttr(texref, dim, (enum cudaTextureReadMode)readmode, ext); - m_TextureRefToAttribute[texref] = texAttr; + m_NameToAttribute[texname] = texAttr; } const char* gpgpu_t::gpgpu_ptx_sim_findNamefromTexture(const struct textureReference* texref) { - std::map::iterator itr = m_NameToTextureRef.begin(); - while (itr != m_NameToTextureRef.end()) { - if ((*itr).second == texref) { - const char *p = ((*itr).first).c_str(); - return p; - } - itr++; - } - return NULL; + std::map::const_iterator t=m_TextureRefToName.find(texref); + assert( t != m_TextureRefToName.end() ); + return t->second.c_str(); } unsigned int intLOGB2( unsigned int v ) { @@ -140,7 +154,8 @@ unsigned int intLOGB2( unsigned int v ) { void gpgpu_t::gpgpu_ptx_sim_bindTextureToArray(const struct textureReference* texref, const struct cudaArray* array) { - m_TextureRefToCudaArray[texref] = array; + std::string texname = gpgpu_ptx_sim_findNamefromTexture(texref); + m_NameToCudaArray[texname] = array; unsigned int texel_size_bits = array->desc.w + array->desc.x + array->desc.y + array->desc.z; unsigned int texel_size = texel_size_bits/8; unsigned int Tx, Ty; @@ -180,13 +195,14 @@ void gpgpu_t::gpgpu_ptx_sim_bindTextureToArray(const struct textureReference* te texInfo->Ty_numbits = intLOGB2(Ty); texInfo->texel_size = texel_size; texInfo->texel_size_numbits = intLOGB2(texel_size); - m_TextureRefToTexureInfo[texref] = texInfo; + m_NameToTexureInfo[texname] = texInfo; } void gpgpu_t::gpgpu_ptx_sim_unbindTexture(const struct textureReference* texref) { - m_TextureRefToCudaArray.erase(texref); - m_TextureRefToTexureInfo.erase(texref); + std::string texname = gpgpu_ptx_sim_findNamefromTexture(texref); + m_NameToCudaArray.erase(texname); + m_NameToTexureInfo.erase(texname); } unsigned g_assemble_code_next_pc=0; @@ -1246,8 +1262,7 @@ static unsigned get_tex_datasize( const ptx_instruction *pI, ptx_thread_info *th std::string texname = src1.name(); gpgpu_t *gpu = thread->get_gpu(); - const struct textureReference* texref = gpu->get_texref(texname); - const struct textureInfo* texInfo = gpu->get_texinfo(texref); + const struct textureInfo* texInfo = gpu->get_texinfo(texname); unsigned data_size = texInfo->texel_size; return data_size; diff --git a/src/cuda-sim/instructions.cc b/src/cuda-sim/instructions.cc index 86951ed..d362231 100644 --- a/src/cuda-sim/instructions.cc +++ b/src/cuda-sim/instructions.cc @@ -4100,9 +4100,9 @@ void tex_impl( const ptx_instruction *pI, ptx_thread_info *thread ) gpgpu_t *gpu = thread->get_gpu(); const struct textureReference* texref = gpu->get_texref(texname); - const struct cudaArray* cuArray = gpu->get_texarray(texref); - const struct textureInfo* texInfo = gpu->get_texinfo(texref); - const struct textureReferenceAttr* texAttr = gpu->get_texattr(texref); + const struct cudaArray* cuArray = gpu->get_texarray(texname); + const struct textureInfo* texInfo = gpu->get_texinfo(texname); + const struct textureReferenceAttr* texAttr = gpu->get_texattr(texname); //assume always 2D f32 input //access array with src2 coordinates -- cgit v1.3 From 5b1ba75a3d5d02fbc12b5218abaaae4fcf2b5c2d Mon Sep 17 00:00:00 2001 From: aamir Date: Wed, 30 May 2018 17:34:14 -0700 Subject: changes for vector operands --- src/abstract_hardware_model.h | 2 +- src/cuda-sim/cuda-sim.cc | 24 +++++++++---- src/cuda-sim/instructions.cc | 80 +++++++++++++++++++++++++++++++++---------- src/cuda-sim/ptx_ir.h | 10 +++++- 4 files changed, 88 insertions(+), 28 deletions(-) (limited to 'src/abstract_hardware_model.h') diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index 9dc58d4..e00c941 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -826,7 +826,7 @@ public: address_type reconvergence_pc; // -1 => not a branch, -2 => use function return address unsigned out[8]; - unsigned in[8]; + unsigned in[24]; unsigned char is_vectorin; unsigned char is_vectorout; int pred; // predicate register number diff --git a/src/cuda-sim/cuda-sim.cc b/src/cuda-sim/cuda-sim.cc index 006738a..62077e6 100644 --- a/src/cuda-sim/cuda-sim.cc +++ b/src/cuda-sim/cuda-sim.cc @@ -852,8 +852,10 @@ void ptx_instruction::pre_decode() { pc = m_PC; isize = m_inst_size; - for( unsigned i=0; i<4; i++) { + for(unsigned i=0; i<8; i++) { out[i] = 0; + } + for(unsigned i=0; i<24; i++) { in[i] = 0; } is_vectorin = 0; @@ -922,6 +924,10 @@ void ptx_instruction::pre_decode() if( num_elem >= 2 ) out[1] = o.reg2_num(); if( num_elem >= 3 ) out[2] = o.reg3_num(); if( num_elem >= 4 ) out[3] = o.reg4_num(); + if( num_elem >= 5 ) out[4] = o.reg5_num(); + if( num_elem >= 6 ) out[5] = o.reg6_num(); + if( num_elem >= 7 ) out[6] = o.reg7_num(); + if( num_elem >= 8 ) out[7] = o.reg8_num(); for (int i = 0; i < num_elem; i++) arch_reg.dst[i] = o.arch_reg_num(i); } @@ -940,13 +946,17 @@ void ptx_instruction::pre_decode() //assert(m == 0); //only support 1 vector operand (for textures) right now is_vectorout = 1; unsigned num_elem = o.get_vect_nelem(); - if( num_elem >= 1 ) in[0] = o.reg1_num(); - if( num_elem >= 2 ) in[1] = o.reg2_num(); - if( num_elem >= 3 ) in[2] = o.reg3_num(); - if( num_elem >= 4 ) in[3] = o.reg4_num(); + if( num_elem >= 1 ) in[m+0] = o.reg1_num(); + if( num_elem >= 2 ) in[m+1] = o.reg2_num(); + if( num_elem >= 3 ) in[m+2] = o.reg3_num(); + if( num_elem >= 4 ) in[m+3] = o.reg4_num(); + if( num_elem >= 5 ) in[m+4] = o.reg5_num(); + if( num_elem >= 6 ) in[m+5] = o.reg6_num(); + if( num_elem >= 7 ) in[m+6] = o.reg7_num(); + if( num_elem >= 8 ) in[m+7] = o.reg8_num(); for (int i = 0; i < num_elem; i++) - arch_reg.src[i] = o.arch_reg_num(i); - m+=4; + arch_reg.src[m+i] = o.arch_reg_num(i); + m+=num_elem; } } } diff --git a/src/cuda-sim/instructions.cc b/src/cuda-sim/instructions.cc index 7407269..446cdbf 100644 --- a/src/cuda-sim/instructions.cc +++ b/src/cuda-sim/instructions.cc @@ -748,7 +748,7 @@ void addp_impl( const ptx_instruction *pI, ptx_thread_info *thread ) case U64_TYPE: data.s64 = src1_data.s64 + src2_data.s64 + (src3_data.pred & 0x4); break; - case F16_TYPE: assert(0); break; + case F16_TYPE: data.f16=src1_data.f16+src2_data.f16; break;//assert(0); break; case F32_TYPE: data.f32 = src1_data.f32 + src2_data.f32; break; case F64_TYPE: case FF64_TYPE: data.f64 = src1_data.f64 + src2_data.f64; break; default: assert(0); break; @@ -826,7 +826,7 @@ void add_impl( const ptx_instruction *pI, ptx_thread_info *thread ) case U64_TYPE: data.u64 = src1_data.u64 + src2_data.u64; break; - case F16_TYPE: assert(0); break; + case F16_TYPE: data.f16=src1_data.f16+src2_data.f16; break;//assert(0); break; case F32_TYPE: data.f32 = src1_data.f32 + src2_data.f32; break; case F64_TYPE: case FF64_TYPE: data.f64 = src1_data.f64 + src2_data.f64; break; default: assert(0); break; @@ -1878,7 +1878,9 @@ ptx_reg_t f2x( ptx_reg_t x, unsigned from_width, unsigned to_width, int to_sign, } } else { switch ( to_width ) { - case 16: assert(0); break; + case 16: //assert(0); break; + y.f16 = x.f32; + break; case 32: assert(0); break; // handled by f2f case 64: y.f64 = x.f32; @@ -2140,7 +2142,7 @@ void ptx_round(ptx_reg_t& data, int rounding_mode, int type) case U32_TYPE: case U64_TYPE: printf("Trying to round an integer??\n"); assert(0); break; - case F16_TYPE: assert(0); break; + case F16_TYPE: data.f16=truncf(data.f16);break;//assert(0); break; case F32_TYPE: data.f32 = truncf(data.f32); break; @@ -2163,7 +2165,13 @@ void ptx_round(ptx_reg_t& data, int rounding_mode, int type) case U32_TYPE: case U64_TYPE: printf("Trying to round an integer??\n"); assert(0); break; - case F16_TYPE: assert(0); break; + case F16_TYPE:// assert(0); break; +#if CUDART_VERSION >= 3000 + data.f16 = nearbyintf(data.f16); +#else + data.f16 = cuda_math::__cuda_nearbyintf(data.f16); +#endif + break; case F32_TYPE: #if CUDART_VERSION >= 3000 data.f32 = nearbyintf(data.f32); @@ -2186,7 +2194,7 @@ void ptx_round(ptx_reg_t& data, int rounding_mode, int type) case U32_TYPE: case U64_TYPE: printf("Trying to round an integer??\n"); assert(0); break; - case F16_TYPE: assert(0); break; + case F16_TYPE: data.f16=floorf(data.f16);break;//assert(0); break; case F32_TYPE: data.f32 = floorf(data.f32); break; @@ -2205,7 +2213,7 @@ void ptx_round(ptx_reg_t& data, int rounding_mode, int type) case U32_TYPE: case U64_TYPE: printf("Trying to round an integer??\n"); assert(0); break; - case F16_TYPE: assert(0); break; + case F16_TYPE: data.f16 = ceilf(data.f16); break; //assert(0); break; case F32_TYPE: data.f32 = ceilf(data.f32); break; case F64_TYPE: case FF64_TYPE: data.f64 = ceil(data.f64); break; default: assert(0); break; @@ -2246,7 +2254,10 @@ void ptx_saturate(ptx_reg_t& data, int saturation_mode, int type) case U32_TYPE: case U64_TYPE: printf("Trying to clamp an integer to 1??\n"); assert(0); break; - case F16_TYPE: assert(0); break; + case F16_TYPE: //assert(0); break; + if (data.f16 > 1.0f) data.f16 = 1.0f; //negative + if (data.f16 < 0.0f) data.f16 = 0.0f; //positive + break; case F32_TYPE: if (data.f32 > 1.0f) data.f32 = 1.0f; //negative if (data.f32 < 0.0f) data.f32 = 0.0f; //positive @@ -2270,8 +2281,8 @@ void cvt_impl( const ptx_instruction *pI, ptx_thread_info *thread ) unsigned rounding_mode = pI->rounding_mode(); unsigned saturation_mode = pI->saturation_mode(); - if ( to_type == F16_TYPE || from_type == F16_TYPE ) - abort(); +// if ( to_type == F16_TYPE || from_type == F16_TYPE ) +// abort(); int to_sign, from_sign; size_t from_width, to_width; @@ -2406,7 +2417,7 @@ void div_impl( const ptx_instruction *pI, ptx_thread_info *thread ) data.u32 = src1_data.u32 / src2_data.u32; break; case B64_TYPE: data.u64 = src1_data.u64 / src2_data.u64; break; - case F16_TYPE: assert(0); break; + case F16_TYPE: data.f16 = src1_data.f16 / src2_data.f16; break;//assert(0); break; case F32_TYPE: data.f32 = src1_data.f32 / src2_data.f32; break; case F64_TYPE: case FF64_TYPE: data.f64 = src1_data.f64 / src2_data.f64; break; default: assert(0); break; @@ -2744,9 +2755,24 @@ void mad_def( const ptx_instruction *pI, ptx_thread_info *thread, bool use_carry if ( pI->is_lo() ) d.u64 = t.u64 + c.u64 + carry_bit.pred; else assert(0); break; - case F16_TYPE: - assert(0); - break; + case F16_TYPE:{ + // assert(0); + // break; + assert( use_carry == false); + int orig_rm = fegetround(); + switch ( rounding_mode ) { + case RN_OPTION: break; + case RZ_OPTION: fesetround( FE_TOWARDZERO ); break; + default: assert(0); break; + } + d.f16 = a.f16 * b.f16 + c.f16; + if ( pI->saturation_mode() ) { + if ( d.f16 < 0 ) d.f16 = 0; + else if ( d.f16 > 1.0f ) d.f16 = 1.0f; + } + fesetround( orig_rm ); + break; + } case F32_TYPE: { assert( use_carry == false); int orig_rm = fegetround(); @@ -3046,9 +3072,25 @@ void mul_impl( const ptx_instruction *pI, ptx_thread_info *thread ) if ( pI->is_lo() ) d.u64 = t.u64; else assert(0); break; - case F16_TYPE: - assert(0); - break; + case F16_TYPE:{ + //assert(0); + //break; + int orig_rm = fegetround(); + switch ( rounding_mode ) { + case RN_OPTION: break; + case RZ_OPTION: fesetround( FE_TOWARDZERO ); break; + default: assert(0); break; + } + + d.f16 = a.f16 * b.f16; + + if ( pI->saturation_mode() ) { + if ( d.f16 < 0 ) d.f16 = 0; + else if ( d.f16 > 1.0f ) d.f16 = 1.0f; + } + fesetround( orig_rm ); + break; + } case F32_TYPE: { int orig_rm = fegetround(); switch ( rounding_mode ) { @@ -3111,7 +3153,7 @@ void neg_impl( const ptx_instruction *pI, ptx_thread_info *thread ) case U32_TYPE: case U64_TYPE: assert(0); break; - case F16_TYPE: assert(0); break; + case F16_TYPE: data.f16 =0.0f - src1_data.f16; break;//assert(0); break; case F32_TYPE: data.f32 = 0.0f - src1_data.f32; break; case F64_TYPE: case FF64_TYPE: data.f64 = 0.0f - src1_data.f64; break; default: assert(0); break; @@ -4165,7 +4207,7 @@ void sub_impl( const ptx_instruction *pI, ptx_thread_info *thread ) case B64_TYPE: case U64_TYPE: data.u64 = src1_data.u64 - src2_data.u64; break; - case F16_TYPE: assert(0); break; + case F16_TYPE: data.f16 = src1_data.f16 - src2_data.f16; break;//assert(0); break; case F32_TYPE: data.f32 = src1_data.f32 - src2_data.f32; break; case F64_TYPE: case FF64_TYPE: data.f64 = src1_data.f64 - src2_data.f64; break; default: assert(0); break; diff --git a/src/cuda-sim/ptx_ir.h b/src/cuda-sim/ptx_ir.h index ff24a66..833f175 100644 --- a/src/cuda-sim/ptx_ir.h +++ b/src/cuda-sim/ptx_ir.h @@ -656,7 +656,11 @@ public: if( !m_value.m_vector_symbolic[1] ) return 1; if( !m_value.m_vector_symbolic[2] ) return 2; if( !m_value.m_vector_symbolic[3] ) return 3; - return 4; + if( !m_value.m_vector_symbolic[4] ) return 4; + if( !m_value.m_vector_symbolic[5] ) return 5; + if( !m_value.m_vector_symbolic[6] ) return 6; + if( !m_value.m_vector_symbolic[7] ) return 7; + return 8; } const symbol* vec_symbol(int idx) const @@ -718,6 +722,10 @@ public: int reg2_num() const { return m_value.m_vector_symbolic[1]->reg_num();} int reg3_num() const { return m_value.m_vector_symbolic[2]?m_value.m_vector_symbolic[2]->reg_num():0; } int reg4_num() const { return m_value.m_vector_symbolic[3]?m_value.m_vector_symbolic[3]->reg_num():0; } + int reg5_num() const { return m_value.m_vector_symbolic[4]?m_value.m_vector_symbolic[4]->reg_num():0; } + int reg6_num() const { return m_value.m_vector_symbolic[5]?m_value.m_vector_symbolic[5]->reg_num():0; } + int reg7_num() const { return m_value.m_vector_symbolic[6]?m_value.m_vector_symbolic[6]->reg_num():0; } + int reg8_num() const { return m_value.m_vector_symbolic[7]?m_value.m_vector_symbolic[7]->reg_num():0; } int arch_reg_num() const { return m_value.m_symbolic->arch_reg_num(); } int arch_reg_num(unsigned n) const { return (m_value.m_vector_symbolic[n])? m_value.m_vector_symbolic[n]->arch_reg_num() : -1; } bool is_label() const { return m_type == label_t;} -- cgit v1.3 From 262663ac90d2aa801d6af1eb9bf8a75ee9a5bb18 Mon Sep 17 00:00:00 2001 From: negargoli93 Date: Wed, 20 Jun 2018 18:20:05 -0700 Subject: Tensor core timing model --- cuda-kernels/gpgpusim.config | 7 +++-- src/abstract_hardware_model.h | 2 ++ src/cuda-sim/cuda-sim.cc | 5 ++-- src/gpgpu-sim/gpu-sim.cc | 16 ++++++++-- src/gpgpu-sim/scoreboard.cc | 40 +++++++++++++++++++------ src/gpgpu-sim/shader.cc | 70 +++++++++++++++++++++++++++++++++++++++---- src/gpgpu-sim/shader.h | 47 ++++++++++++++++++++++++++--- 7 files changed, 163 insertions(+), 24 deletions(-) (limited to 'src/abstract_hardware_model.h') diff --git a/cuda-kernels/gpgpusim.config b/cuda-kernels/gpgpusim.config index 306d7f9..69a110f 100755 --- a/cuda-kernels/gpgpusim.config +++ b/cuda-kernels/gpgpusim.config @@ -33,10 +33,10 @@ # ID_OC_SP,ID_OC_SFU,ID_OC_MEM,OC_EX_SP,OC_EX_SFU,OC_EX_MEM,EX_WB ## Pascal GP102 has 4 SP SIMD units and 1 SFU unit ## we need to scale the number of pipeline registers to be equal to the number of SP units --gpgpu_pipeline_widths 4,1,1,4,1,1,6 +-gpgpu_pipeline_widths 4,1,1,1,4,1,1,1,,6 -gpgpu_num_sp_units 4 -gpgpu_num_sfu_units 1 - +-gpgpu_num_tensor_core_units 1 # Instruction latencies and initiation intervals # "ADD,MAX,MUL,MAD,DIV" # SFU is 32-width in pascal, then dp units initiation is 1 cycle @@ -72,11 +72,14 @@ ## larger operand collectors and reg_banks are needed for the 4 warp schedulers and 4 SIMD units -gpgpu_operand_collector_num_units_sp 20 -gpgpu_operand_collector_num_units_sfu 4 +-gpgpu_operand_collector_num_units_tensor_core 24 -gpgpu_operand_collector_num_units_mem 8 -gpgpu_operand_collector_num_in_ports_sp 4 -gpgpu_operand_collector_num_out_ports_sp 4 -gpgpu_operand_collector_num_in_ports_sfu 1 -gpgpu_operand_collector_num_out_ports_sfu 1 +-gpgpu_operand_collector_num_in_ports_tensor_core 1 +-gpgpu_operand_collector_num_out_ports_tensor_core 1 -gpgpu_operand_collector_num_in_ports_mem 1 -gpgpu_operand_collector_num_out_ports_mem 1 # gpgpu_num_reg_banks should be increased to 32, but it gives an error! diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index e00c941..e2e116e 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -77,6 +77,7 @@ enum uarch_op_t { NO_OP=-1, ALU_OP=1, SFU_OP, + TENSOR_CORE_OP, ALU_SFU_OP, LOAD_OP, STORE_OP, @@ -133,6 +134,7 @@ enum operation_pipeline_t { UNKOWN_OP, SP__OP, SFU__OP, + TENSOR_CORE__OP, MEM__OP }; typedef enum operation_pipeline_t operation_pipeline; diff --git a/src/cuda-sim/cuda-sim.cc b/src/cuda-sim/cuda-sim.cc index 7552acf..6da0840 100644 --- a/src/cuda-sim/cuda-sim.cc +++ b/src/cuda-sim/cuda-sim.cc @@ -520,7 +520,7 @@ void ptx_instruction::set_mul_div_or_other_archop(){ sp_op=FP_EXP_OP; break; default: - if(op==ALU_OP) + if((op==ALU_OP)||(op==TENSOR_CORE_OP)) sp_op=FP__OP; break; @@ -542,7 +542,7 @@ void ptx_instruction::set_mul_div_or_other_archop(){ sp_op=INT_DIV_OP; break; default: - if(op==ALU_OP) + if((op==ALU_OP)||(op==TENSOR_CORE_OP)) sp_op=INT__OP; break; } @@ -795,6 +795,7 @@ void ptx_instruction::set_opcode_and_latency() case MMA_OP: latency = 64; initiation_interval = 64; + op=TENSOR_CORE_OP; break; case SHFL_OP: latency = 32; diff --git a/src/gpgpu-sim/gpu-sim.cc b/src/gpgpu-sim/gpu-sim.cc index 3bd1892..cc23051 100644 --- a/src/gpgpu-sim/gpu-sim.cc +++ b/src/gpgpu-sim/gpu-sim.cc @@ -306,6 +306,9 @@ void shader_core_config::reg_options(class OptionParser * opp) option_parser_register(opp, "-gpgpu_operand_collector_num_units_sfu", OPT_INT32, &gpgpu_operand_collector_num_units_sfu, "number of collector units (default = 4)", "4"); + option_parser_register(opp, "-gpgpu_operand_collector_num_units_tensor_core", OPT_INT32, &gpgpu_operand_collector_num_units_tensor_core, + "number of collector units (default = 4)", + "4"); option_parser_register(opp, "-gpgpu_operand_collector_num_units_mem", OPT_INT32, &gpgpu_operand_collector_num_units_mem, "number of collector units (default = 2)", "2"); @@ -318,6 +321,9 @@ void shader_core_config::reg_options(class OptionParser * opp) option_parser_register(opp, "-gpgpu_operand_collector_num_in_ports_sfu", OPT_INT32, &gpgpu_operand_collector_num_in_ports_sfu, "number of collector unit in ports (default = 1)", "1"); + option_parser_register(opp, "-gpgpu_operand_collector_num_in_ports_tensor_core", OPT_INT32, &gpgpu_operand_collector_num_in_ports_tensor_core, + "number of collector unit in ports (default = 1)", + "1"); option_parser_register(opp, "-gpgpu_operand_collector_num_in_ports_mem", OPT_INT32, &gpgpu_operand_collector_num_in_ports_mem, "number of collector unit in ports (default = 1)", "1"); @@ -330,6 +336,9 @@ void shader_core_config::reg_options(class OptionParser * opp) option_parser_register(opp, "-gpgpu_operand_collector_num_out_ports_sfu", OPT_INT32, &gpgpu_operand_collector_num_out_ports_sfu, "number of collector unit in ports (default = 1)", "1"); + option_parser_register(opp, "-gpgpu_operand_collector_num_out_ports_tensor_core", OPT_INT32, &gpgpu_operand_collector_num_out_ports_tensor_core, + "number of collector unit in ports (default = 1)", + "1"); option_parser_register(opp, "-gpgpu_operand_collector_num_out_ports_mem", OPT_INT32, &gpgpu_operand_collector_num_out_ports_mem, "number of collector unit in ports (default = 1)", "1"); @@ -350,14 +359,17 @@ void shader_core_config::reg_options(class OptionParser * opp) "1"); option_parser_register(opp, "-gpgpu_pipeline_widths", OPT_CSTR, &pipeline_widths_string, "Pipeline widths " - "ID_OC_SP,ID_OC_SFU,ID_OC_MEM,OC_EX_SP,OC_EX_SFU,OC_EX_MEM,EX_WB", - "1,1,1,1,1,1,1" ); + "ID_OC_SP,ID_OC_SFU,ID_OC_TENSOR_CORE,ID_OC_MEM,OC_EX_SP,OC_EX_SFU,OC_EX_TENSOR_CORE,OC_EX_MEM,EX_WB", + "1,1,1,1,1,1,1,1,1" ); option_parser_register(opp, "-gpgpu_num_sp_units", OPT_INT32, &gpgpu_num_sp_units, "Number of SP units (default=1)", "1"); option_parser_register(opp, "-gpgpu_num_sfu_units", OPT_INT32, &gpgpu_num_sfu_units, "Number of SF units (default=1)", "1"); + option_parser_register(opp, "-gpgpu_num_tensor_core_units", OPT_INT32, &gpgpu_num_tensor_core_units, + "Number of tensor_core units (default=1)", + "1"); option_parser_register(opp, "-gpgpu_num_mem_units", OPT_INT32, &gpgpu_num_mem_units, "Number if ldst units (default=1) WARNING: not hooked up to anything", "1"); diff --git a/src/gpgpu-sim/scoreboard.cc b/src/gpgpu-sim/scoreboard.cc index b538fdf..4d1b43a 100644 --- a/src/gpgpu-sim/scoreboard.cc +++ b/src/gpgpu-sim/scoreboard.cc @@ -82,7 +82,7 @@ const bool Scoreboard::islongop (unsigned warp_id,unsigned regnum) { void Scoreboard::reserveRegisters(const class warp_inst_t* inst) { - for( unsigned r=0; r < 4; r++) { + for( unsigned r=0; r < 8; r++) { if(inst->out[r] > 0) { reserveRegister(inst->warp_id(), inst->out[r]); SHADER_DPRINTF( SCOREBOARD, @@ -100,7 +100,7 @@ void Scoreboard::reserveRegisters(const class warp_inst_t* inst) inst->space.get_type() == param_space_local || inst->space.get_type() == param_space_unclassified || inst->space.get_type() == tex_space)){ - for ( unsigned r=0; r<4; r++) { + for ( unsigned r=0; r<8; r++) { if(inst->out[r] > 0) { SHADER_DPRINTF( SCOREBOARD, "New longopreg marked - warp:%d, reg: %d\n", @@ -115,7 +115,7 @@ void Scoreboard::reserveRegisters(const class warp_inst_t* inst) // Release registers for an instruction void Scoreboard::releaseRegisters(const class warp_inst_t *inst) { - for( unsigned r=0; r < 4; r++) { + for( unsigned r=0; r < 8; r++) { if(inst->out[r] > 0) { SHADER_DPRINTF( SCOREBOARD, "Register Released - warp:%d, reg: %d\n", @@ -142,15 +142,37 @@ bool Scoreboard::checkCollision( unsigned wid, const class inst_t *inst ) const if(inst->out[1] > 0) inst_regs.insert(inst->out[1]); if(inst->out[2] > 0) inst_regs.insert(inst->out[2]); if(inst->out[3] > 0) inst_regs.insert(inst->out[3]); - if(inst->in[0] > 0) inst_regs.insert(inst->in[0]); + if(inst->out[4] > 0) inst_regs.insert(inst->out[4]); + if(inst->out[5] > 0) inst_regs.insert(inst->out[5]); + if(inst->out[6] > 0) inst_regs.insert(inst->out[6]); + if(inst->out[7] > 0) inst_regs.insert(inst->out[7]); + + if(inst->in[0] > 0) inst_regs.insert(inst->in[0]); if(inst->in[1] > 0) inst_regs.insert(inst->in[1]); if(inst->in[2] > 0) inst_regs.insert(inst->in[2]); if(inst->in[3] > 0) inst_regs.insert(inst->in[3]); - if(inst->in[3] > 0) inst_regs.insert(inst->in[4]); - if(inst->in[3] > 0) inst_regs.insert(inst->in[5]); - if(inst->in[3] > 0) inst_regs.insert(inst->in[6]); - if(inst->in[3] > 0) inst_regs.insert(inst->in[7]); - if(inst->pred > 0) inst_regs.insert(inst->pred); + if(inst->in[4] > 0) inst_regs.insert(inst->in[4]); + if(inst->in[5] > 0) inst_regs.insert(inst->in[5]); + if(inst->in[6] > 0) inst_regs.insert(inst->in[6]); + if(inst->in[7] > 0) inst_regs.insert(inst->in[7]); + if(inst->in[8] > 0) inst_regs.insert(inst->in[8]); + if(inst->in[9] > 0) inst_regs.insert(inst->in[9]); + if(inst->in[10] > 0) inst_regs.insert(inst->in[10]); + if(inst->in[11] > 0) inst_regs.insert(inst->in[11]); + if(inst->in[12] > 0) inst_regs.insert(inst->in[12]); + if(inst->in[13] > 0) inst_regs.insert(inst->in[13]); + if(inst->in[14] > 0) inst_regs.insert(inst->in[14]); + if(inst->in[15] > 0) inst_regs.insert(inst->in[15]); + if(inst->in[16] > 0) inst_regs.insert(inst->in[16]); + if(inst->in[17] > 0) inst_regs.insert(inst->in[17]); + if(inst->in[18] > 0) inst_regs.insert(inst->in[18]); + if(inst->in[19] > 0) inst_regs.insert(inst->in[19]); + if(inst->in[20] > 0) inst_regs.insert(inst->in[20]); + if(inst->in[21] > 0) inst_regs.insert(inst->in[21]); + if(inst->in[22] > 0) inst_regs.insert(inst->in[22]); + if(inst->in[23] > 0) inst_regs.insert(inst->in[23]); + + if(inst->pred > 0) inst_regs.insert(inst->pred); if(inst->ar1 > 0) inst_regs.insert(inst->ar1); if(inst->ar2 > 0) inst_regs.insert(inst->ar2); diff --git a/src/gpgpu-sim/shader.cc b/src/gpgpu-sim/shader.cc index 92cdb5b..fcac755 100644 --- a/src/gpgpu-sim/shader.cc +++ b/src/gpgpu-sim/shader.cc @@ -148,6 +148,7 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, &m_warp, &m_pipeline_reg[ID_OC_SP], &m_pipeline_reg[ID_OC_SFU], + &m_pipeline_reg[ID_OC_TENSOR_CORE], &m_pipeline_reg[ID_OC_MEM], i ) @@ -162,6 +163,7 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, &m_warp, &m_pipeline_reg[ID_OC_SP], &m_pipeline_reg[ID_OC_SFU], + &m_pipeline_reg[ID_OC_TENSOR_CORE], &m_pipeline_reg[ID_OC_MEM], i, config->gpgpu_scheduler_string @@ -177,6 +179,7 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, &m_warp, &m_pipeline_reg[ID_OC_SP], &m_pipeline_reg[ID_OC_SFU], + &m_pipeline_reg[ID_OC_TENSOR_CORE], &m_pipeline_reg[ID_OC_MEM], i ) @@ -191,6 +194,7 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, &m_warp, &m_pipeline_reg[ID_OC_SP], &m_pipeline_reg[ID_OC_SFU], + &m_pipeline_reg[ID_OC_TENSOR_CORE], &m_pipeline_reg[ID_OC_MEM], i, config->gpgpu_scheduler_string @@ -211,9 +215,10 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, } //op collector configuration - enum { SP_CUS, SFU_CUS, MEM_CUS, GEN_CUS }; + enum { SP_CUS, SFU_CUS, TENSOR_CORE_CUS, MEM_CUS, GEN_CUS }; m_operand_collector.add_cu_set(SP_CUS, m_config->gpgpu_operand_collector_num_units_sp, m_config->gpgpu_operand_collector_num_out_ports_sp); m_operand_collector.add_cu_set(SFU_CUS, m_config->gpgpu_operand_collector_num_units_sfu, m_config->gpgpu_operand_collector_num_out_ports_sfu); + m_operand_collector.add_cu_set(TENSOR_CORE_CUS, m_config->gpgpu_operand_collector_num_units_tensor_core, m_config->gpgpu_operand_collector_num_out_ports_tensor_core); m_operand_collector.add_cu_set(MEM_CUS, m_config->gpgpu_operand_collector_num_units_mem, m_config->gpgpu_operand_collector_num_out_ports_mem); m_operand_collector.add_cu_set(GEN_CUS, m_config->gpgpu_operand_collector_num_units_gen, m_config->gpgpu_operand_collector_num_out_ports_gen); @@ -237,7 +242,17 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, m_operand_collector.add_port(in_ports,out_ports,cu_sets); in_ports.clear(),out_ports.clear(),cu_sets.clear(); } + + for (unsigned i = 0; i < m_config->gpgpu_operand_collector_num_in_ports_tensor_core; i++) { + in_ports.push_back(&m_pipeline_reg[ID_OC_TENSOR_CORE]); + out_ports.push_back(&m_pipeline_reg[OC_EX_TENSOR_CORE]); + cu_sets.push_back((unsigned)TENSOR_CORE_CUS); + cu_sets.push_back((unsigned)GEN_CUS); + m_operand_collector.add_port(in_ports,out_ports,cu_sets); + in_ports.clear(),out_ports.clear(),cu_sets.clear(); + } + for (unsigned i = 0; i < m_config->gpgpu_operand_collector_num_in_ports_mem; i++) { in_ports.push_back(&m_pipeline_reg[ID_OC_MEM]); out_ports.push_back(&m_pipeline_reg[OC_EX_MEM]); @@ -251,9 +266,11 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, for (unsigned i = 0; i < m_config->gpgpu_operand_collector_num_in_ports_gen; i++) { in_ports.push_back(&m_pipeline_reg[ID_OC_SP]); in_ports.push_back(&m_pipeline_reg[ID_OC_SFU]); + in_ports.push_back(&m_pipeline_reg[ID_OC_TENSOR_CORE]); in_ports.push_back(&m_pipeline_reg[ID_OC_MEM]); out_ports.push_back(&m_pipeline_reg[OC_EX_SP]); out_ports.push_back(&m_pipeline_reg[OC_EX_SFU]); + out_ports.push_back(&m_pipeline_reg[OC_EX_TENSOR_CORE]); out_ports.push_back(&m_pipeline_reg[OC_EX_MEM]); cu_sets.push_back((unsigned)GEN_CUS); m_operand_collector.add_port(in_ports,out_ports,cu_sets); @@ -263,7 +280,7 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, m_operand_collector.init( m_config->gpgpu_num_reg_banks, this ); // execute - m_num_function_units = m_config->gpgpu_num_sp_units + m_config->gpgpu_num_sfu_units + 1; // sp_unit, sfu, ldst_unit + m_num_function_units = m_config->gpgpu_num_sp_units + m_config->gpgpu_num_sfu_units + m_config->gpgpu_num_tensor_core_units + 1; // sp_unit, sfu, ldst_unit //m_dispatch_port = new enum pipeline_stage_name_t[ m_num_function_units ]; //m_issue_port = new enum pipeline_stage_name_t[ m_num_function_units ]; @@ -280,6 +297,12 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, m_dispatch_port.push_back(ID_OC_SFU); m_issue_port.push_back(OC_EX_SFU); } + + for (int k = 0; k < m_config->gpgpu_num_tensor_core_units; k++) { + m_fu.push_back(new tensor_core( &m_pipeline_reg[EX_WB], m_config, this )); + m_dispatch_port.push_back(ID_OC_TENSOR_CORE); + m_issue_port.push_back(OC_EX_TENSOR_CORE); + } m_ldst_unit = new ldst_unit( m_icnt, m_mem_fetch_allocator, this, &m_operand_collector, m_scoreboard, config, mem_config, stats, shader_id, tpc_id ); m_fu.push_back(m_ldst_unit); @@ -886,7 +909,8 @@ void scheduler_unit::cycle() } else { 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) ) { + bool tensor_core_pipe_avail = m_tensor_core_out->has_free(); + if( sp_pipe_avail && (pI->op != SFU_OP) && (pI->op != TENSOR_CORE_OP)) { //Jin: special for CDP api if(pI->m_is_cdp && !warp(warp_id).m_cdp_dummy) { @@ -918,6 +942,14 @@ void scheduler_unit::cycle() issued_inst=true; warp_inst_issued = true; } + } + else if ( (pI->op == TENSOR_CORE_OP) ) { + if( tensor_core_pipe_avail ) { + m_shader->issue_warp(*m_tensor_core_out,pI,active_mask,warp_id); + issued++; + issued_inst=true; + warp_inst_issued = true; + } } } } else { SCHED_DPRINTF( "Warp (warp_id %u, dynamic_warp_id %u) fails scoreboard\n", @@ -1083,10 +1115,11 @@ swl_scheduler::swl_scheduler ( shader_core_stats* stats, shader_core_ctx* shader std::vector* warp, register_set* sp_out, register_set* sfu_out, + register_set* tensor_core_out, register_set* mem_out, int id, char* config_string ) - : scheduler_unit ( stats, shader, scoreboard, simt, warp, sp_out, sfu_out, mem_out, id ) + : scheduler_unit ( stats, shader, scoreboard, simt, warp, sp_out, sfu_out, tensor_core_out, mem_out, id ) { unsigned m_prioritization_readin; int ret = sscanf( config_string, @@ -1509,6 +1542,13 @@ sfu:: sfu( register_set* result_port, const shader_core_config *config,shader_c m_name = "SFU"; } +tensor_core:: tensor_core( register_set* result_port, const shader_core_config *config,shader_core_ctx *core ) + : pipelined_simd_unit(result_port,config,config->max_tensor_core_latency,core) +{ + m_name = "TENSOR_CORE"; +} + + void sfu::issue( register_set& source_reg ) { warp_inst_t** ready_reg = source_reg.get_ready(); @@ -1519,6 +1559,17 @@ void sfu::issue( register_set& source_reg ) pipelined_simd_unit::issue(source_reg); } +void tensor_core::issue( register_set& source_reg ) +{ + warp_inst_t** ready_reg = source_reg.get_ready(); + //m_core->incexecstat((*ready_reg)); + + (*ready_reg)->op_pipe= TENSOR_CORE__OP; + m_core->incsfu_stat(m_core->get_config()->warp_size,(*ready_reg)->latency); + pipelined_simd_unit::issue(source_reg); +} + + void ldst_unit::active_lanes_in_pipeline(){ unsigned active_count=pipelined_simd_unit::get_active_lanes_in_pipeline(); assert(active_count<=m_core->get_config()->warp_size); @@ -1540,6 +1591,15 @@ void sfu::active_lanes_in_pipeline(){ m_core->incfumemactivelanes_stat(active_count); } +void tensor_core::active_lanes_in_pipeline(){ + unsigned active_count=pipelined_simd_unit::get_active_lanes_in_pipeline(); + assert(active_count<=m_core->get_config()->warp_size); + m_core->incsfuactivelanes_stat(active_count); + m_core->incfuactivelanes_stat(active_count); + m_core->incfumemactivelanes_stat(active_count); +} + + sp_unit::sp_unit( register_set* result_port, const shader_core_config *config,shader_core_ctx *core) : pipelined_simd_unit(result_port,config,config->max_sp_latency,core) { @@ -2237,7 +2297,7 @@ void shader_core_ctx::incexecstat(warp_inst_t *&inst) switch(inst->sp_op){ case INT__OP: - incialu_stat(inst->active_count(),25); + incialu_stat(inst->active_count(),32); break; case INT_MUL_OP: incimul_stat(inst->active_count(),7.2); diff --git a/src/gpgpu-sim/shader.h b/src/gpgpu-sim/shader.h index db2af01..2c4c43d 100644 --- a/src/gpgpu-sim/shader.h +++ b/src/gpgpu-sim/shader.h @@ -318,11 +318,12 @@ public: std::vector* warp, register_set* sp_out, register_set* sfu_out, + register_set* tensor_core_out, register_set* mem_out, int id) : m_supervised_warps(), m_stats(stats), m_shader(shader), m_scoreboard(scoreboard), m_simt_stack(simt), /*m_pipeline_reg(pipe_regs),*/ m_warp(warp), - m_sp_out(sp_out),m_sfu_out(sfu_out),m_mem_out(mem_out), m_id(id){} + m_sp_out(sp_out),m_sfu_out(sfu_out),m_tensor_core_out(tensor_core_out),m_mem_out(mem_out), m_id(id){} virtual ~scheduler_unit(){} virtual void add_supervised_warp_id(int i) { m_supervised_warps.push_back(&warp(i)); @@ -395,6 +396,7 @@ protected: std::vector* m_warp; register_set* m_sp_out; register_set* m_sfu_out; + register_set* m_tensor_core_out; register_set* m_mem_out; int m_id; @@ -407,9 +409,10 @@ public: std::vector* warp, register_set* sp_out, register_set* sfu_out, + register_set* tensor_core_out, register_set* mem_out, int id ) - : scheduler_unit ( stats, shader, scoreboard, simt, warp, sp_out, sfu_out, mem_out, id ){} + : scheduler_unit ( stats, shader, scoreboard, simt, warp, sp_out, sfu_out, tensor_core_out, mem_out, id ){} virtual ~lrr_scheduler () {} virtual void order_warps (); virtual void done_adding_supervised_warps() { @@ -424,9 +427,10 @@ public: std::vector* warp, register_set* sp_out, register_set* sfu_out, + register_set* tensor_core_out, register_set* mem_out, int id ) - : scheduler_unit ( stats, shader, scoreboard, simt, warp, sp_out, sfu_out, mem_out, id ){} + : scheduler_unit ( stats, shader, scoreboard, simt, warp, sp_out, sfu_out, tensor_core_out, mem_out, id ){} virtual ~gto_scheduler () {} virtual void order_warps (); virtual void done_adding_supervised_warps() { @@ -443,10 +447,11 @@ public: std::vector* warp, register_set* sp_out, register_set* sfu_out, + register_set* tensor_core_out, register_set* mem_out, int id, char* config_str ) - : scheduler_unit ( stats, shader, scoreboard, simt, warp, sp_out, sfu_out, mem_out, id ), + : scheduler_unit ( stats, shader, scoreboard, simt, warp, sp_out, sfu_out, tensor_core_out, mem_out, id ), m_pending_warps() { unsigned inner_level_readin; @@ -493,6 +498,7 @@ public: std::vector* warp, register_set* sp_out, register_set* sfu_out, + register_set* tensor_core_out, register_set* mem_out, int id, char* config_string ); @@ -1062,6 +1068,23 @@ public: virtual void issue( register_set& source_reg ); }; +class tensor_core : public pipelined_simd_unit +{ +public: + tensor_core( register_set* result_port, const shader_core_config *config, shader_core_ctx *core ); + virtual bool can_issue( const warp_inst_t &inst ) const + { + switch(inst.op) { + case TENSOR_CORE_OP: break; + default: return false; + } + return pipelined_simd_unit::can_issue(inst); + } + virtual void active_lanes_in_pipeline(); + virtual void issue( register_set& source_reg ); +}; + + class sp_unit : public pipelined_simd_unit { public: @@ -1201,9 +1224,11 @@ protected: enum pipeline_stage_name_t { ID_OC_SP=0, ID_OC_SFU, + ID_OC_TENSOR_CORE, ID_OC_MEM, OC_EX_SP, OC_EX_SFU, + OC_EX_TENSOR_CORE, OC_EX_MEM, EX_WB, N_PIPELINE_STAGES @@ -1212,9 +1237,11 @@ enum pipeline_stage_name_t { const char* const pipeline_stage_name_decode[] = { "ID_OC_SP", "ID_OC_SFU", + "ID_OC_TENSOR_CORE", "ID_OC_MEM", "OC_EX_SP", "OC_EX_SFU", + "OC_EX_TENSOR_CORE", "OC_EX_MEM", "EX_WB", "N_PIPELINE_STAGES" @@ -1257,6 +1284,7 @@ struct shader_core_config : public core_config max_warps_per_shader = n_thread_per_shader/warp_size; assert( !(n_thread_per_shader % warp_size) ); max_sfu_latency = 512; + max_tensor_core_latency = 512; max_sp_latency = 32; m_L1I_config.init(m_L1I_config.m_config_string,FuncCachePreferNone); m_L1T_config.init(m_L1T_config.m_config_string,FuncCachePreferNone); @@ -1304,21 +1332,25 @@ struct shader_core_config : public core_config //op collector int gpgpu_operand_collector_num_units_sp; int gpgpu_operand_collector_num_units_sfu; + int gpgpu_operand_collector_num_units_tensor_core; int gpgpu_operand_collector_num_units_mem; int gpgpu_operand_collector_num_units_gen; unsigned int gpgpu_operand_collector_num_in_ports_sp; unsigned int gpgpu_operand_collector_num_in_ports_sfu; + unsigned int gpgpu_operand_collector_num_in_ports_tensor_core; unsigned int gpgpu_operand_collector_num_in_ports_mem; unsigned int gpgpu_operand_collector_num_in_ports_gen; unsigned int gpgpu_operand_collector_num_out_ports_sp; unsigned int gpgpu_operand_collector_num_out_ports_sfu; + unsigned int gpgpu_operand_collector_num_out_ports_tensor_core; unsigned int gpgpu_operand_collector_num_out_ports_mem; unsigned int gpgpu_operand_collector_num_out_ports_gen; int gpgpu_num_sp_units; int gpgpu_num_sfu_units; + int gpgpu_num_tensor_core_units; int gpgpu_num_mem_units; //Shader core resources @@ -1331,6 +1363,7 @@ struct shader_core_config : public core_config unsigned max_sp_latency; unsigned max_sfu_latency; + unsigned max_tensor_core_latency; unsigned n_simt_cores_per_cluster; unsigned n_simt_clusters; @@ -1368,12 +1401,14 @@ struct shader_core_stats_pod { unsigned *m_num_fpdiv_acesses; unsigned *m_num_sp_acesses; unsigned *m_num_sfu_acesses; + unsigned *m_num_tensor_core_acesses; unsigned *m_num_trans_acesses; unsigned *m_num_mem_acesses; unsigned *m_num_sp_committed; unsigned *m_num_tlb_hits; unsigned *m_num_tlb_accesses; unsigned *m_num_sfu_committed; + unsigned *m_num_tensor_core_committed; unsigned *m_num_mem_committed; unsigned *m_read_regfile_acesses; unsigned *m_write_regfile_acesses; @@ -1382,6 +1417,7 @@ struct shader_core_stats_pod { unsigned *m_num_imul32_acesses; unsigned *m_active_sp_lanes; unsigned *m_active_sfu_lanes; + unsigned *m_active_tensor_core_lanes; unsigned *m_active_fu_lanes; unsigned *m_active_fu_mem_lanes; unsigned *m_n_diverge; // number of divergence occurring in this shader @@ -1453,6 +1489,7 @@ public: m_num_fpdiv_acesses= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); m_num_sp_acesses= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); m_num_sfu_acesses= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_num_tensor_core_acesses= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); m_num_trans_acesses= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); m_num_mem_acesses= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); m_num_sp_committed= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); @@ -1460,9 +1497,11 @@ public: m_num_tlb_accesses=(unsigned*) calloc(config->num_shader(),sizeof(unsigned)); m_active_sp_lanes= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); m_active_sfu_lanes= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_active_tensor_core_lanes= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); m_active_fu_lanes= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); m_active_fu_mem_lanes= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); m_num_sfu_committed= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_num_tensor_core_committed= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); m_num_mem_committed= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); m_read_regfile_acesses= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); m_write_regfile_acesses= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); -- cgit v1.3 From b3ad8abea43b7d1e8887f57d6e30c5a40cf752a6 Mon Sep 17 00:00:00 2001 From: aamir Date: Sat, 21 Jul 2018 19:21:30 -0700 Subject: merging the changes of cutlass on negar tensorcore branch --- .gitignore | 6 +- cutlass-example | 1 + libcuda/cuda_runtime_api.cc | 42 +++++++++++++- src/abstract_hardware_model.h | 2 +- src/cuda-sim/cuda-sim.cc | 7 +++ src/cuda-sim/instructions.cc | 125 ++++++++++++++++++++++++++++++++---------- 6 files changed, 151 insertions(+), 32 deletions(-) create mode 160000 cutlass-example (limited to 'src/abstract_hardware_model.h') diff --git a/.gitignore b/.gitignore index 53fadb5..b214862 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,7 @@ +*~ +*.swp +*.swo + src/intersim2/lex.yy.c src/intersim2/y.tab.c src/intersim2/y.tab.h @@ -26,4 +30,4 @@ cuobjdump_to_ptxplus/sass_parser.cc cuobjdump_to_ptxplus/sass_parser.hh cuobjdump_to_ptxplus/sass_parser.output -build/* \ No newline at end of file +build/* diff --git a/cutlass-example b/cutlass-example new file mode 160000 index 0000000..e69115d --- /dev/null +++ b/cutlass-example @@ -0,0 +1 @@ +Subproject commit e69115d598bef1e5372c9134322972b2ea450d9f diff --git a/libcuda/cuda_runtime_api.cc b/libcuda/cuda_runtime_api.cc index cbe8a11..aa43ffa 100644 --- a/libcuda/cuda_runtime_api.cc +++ b/libcuda/cuda_runtime_api.cc @@ -952,7 +952,9 @@ __host__ cudaError_t CUDARTAPI cudaSetupArgument(const void *arg, size_t size, s gpgpusim_ptx_assert( !g_cuda_launch_stack.empty(), "empty launch stack" ); kernel_config &config = g_cuda_launch_stack.back(); config.set_arg(arg,size,offset); - + #if 0 + printf("cudaSetupArgument:size%d,offset%d,sizeof(Arg[0])=%d)\n ",size,offset,sizeof(arg)); + #endif return g_last_cudaError = cudaSuccess; } @@ -980,6 +982,44 @@ __host__ cudaError_t CUDARTAPI cudaLaunch( const char *hostFun ) return g_last_cudaError = cudaSuccess; } +__host__ cudaError_t CUDARTAPI cudaLaunchKernel ( const char* hostFun, dim3 gridDim, dim3 blockDim, const void** args, size_t sharedMem, cudaStream_t stream ) +{ + struct CUstream_st *s = (struct CUstream_st *)stream; + g_cuda_launch_stack.push_back( kernel_config(gridDim,blockDim,sharedMem,s) ); + + + printf("cudaLaunchKernel:sizeof(Arg[0])=%d)\n ",sizeof(args[0])); + //gpgpusim_ptx_assert( !g_cuda_launch_stack.empty(), "empty launch stack" ); + kernel_config &config = g_cuda_launch_stack.back(); + config.set_arg(args[0],432,0); + printf("cudaLaunchParameter\n"); + for(int i=0;i<108;i++){ + printf("cudaLaunchParameter:%d:%08x\n",i,*(*((int **)args)+i)); + } + + CUctx_st* context = GPGPUSim_Context(); + char *mode = getenv("PTX_SIM_MODE_FUNC"); + if( mode ) + sscanf(mode,"%u", &g_ptx_sim_mode); + gpgpusim_ptx_assert( !g_cuda_launch_stack.empty(), "empty launch stack" ); + kernel_config config1 = g_cuda_launch_stack.back(); + struct CUstream_st *stream1 = config1.get_stream(); + printf("\nGPGPU-Sim PTX: cudaLaunch for 0x%p (mode=%s) on stream %u\n", hostFun, + g_ptx_sim_mode?"functional simulation":"performance simulation", stream1?stream1->get_uid():0 ); + kernel_info_t *grid = gpgpu_cuda_ptx_sim_init_grid(hostFun,config1.get_args(),config1.grid_dim(),config1.block_dim(),context); + std::string kname = grid->name(); + dim3 gridDim1 = config1.grid_dim(); + dim3 blockDim1 = config1.block_dim(); + printf("GPGPU-Sim PTX: pushing kernel \'%s\' to stream %u, gridDim= (%u,%u,%u) blockDim = (%u,%u,%u) \n", + kname.c_str(), stream1?stream1->get_uid():0, gridDim1.x,gridDim1.y,gridDim1.z,blockDim1.x,blockDim1.y,blockDim1.z ); + stream_operation op(grid,g_ptx_sim_mode,stream1); + g_stream_manager->push(op); + g_cuda_launch_stack.pop_back(); + return g_last_cudaError = cudaSuccess; + + +} + /******************************************************************************* * * * * diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index e2e116e..7fe5d82 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -386,7 +386,7 @@ protected: std::deque m_stack; }; -#define GLOBAL_HEAP_START 0x703E20000 +#define GLOBAL_HEAP_START 0xC0000000 // start allocating from this address (lower values used for allocating globals in .ptx file) #define SHARED_MEM_SIZE_MAX (64*1024) #define LOCAL_MEM_SIZE_MAX (8*1024) diff --git a/src/cuda-sim/cuda-sim.cc b/src/cuda-sim/cuda-sim.cc index 506bc95..8284ad5 100644 --- a/src/cuda-sim/cuda-sim.cc +++ b/src/cuda-sim/cuda-sim.cc @@ -1273,6 +1273,13 @@ void ptx_thread_info::ptx_exec_inst( warp_inst_t &inst, unsigned lane_id) addr_t pc = next_instr(); assert( pc == inst.pc ); // make sure timing model and functional model are in sync const ptx_instruction *pI = m_func_info->get_instruction(pc); + #if 0 + if(lane_id==0){ + printf("EXECUTION_FLOW:LINE_NUM:%d\n",pI->source_line()); + printf("EXECUTION_FLOW:INST:%s\n",pI->get_source()); + } + #endif + set_npc( pc + pI->inst_size() ); diff --git a/src/cuda-sim/instructions.cc b/src/cuda-sim/instructions.cc index cebce1e..7af157f 100644 --- a/src/cuda-sim/instructions.cc +++ b/src/cuda-sim/instructions.cc @@ -48,7 +48,7 @@ using half_float::half; unsigned ptx_instruction::g_num_ptx_inst_uid=0; -bool g_debug_instruction = 0; +bool g_debug_instruction = 1; const char *g_opcode_string[NUM_OPCODES] = { @@ -239,9 +239,9 @@ ptx_reg_t ptx_thread_info::get_operand_value( const operand_info &op, operand_in } else if ( op.is_sstarr() ) { result.u64 = op.get_symbol()->get_address() + op.get_addr_offset(); } else { - const char *name = op.name().c_str(); - printf("GPGPU-Sim PTX: ERROR ** get_operand_value : unknown memory operand type for %s\n", name ); - abort(); + const char *name = op.name().c_str(); + printf("GPGPU-Sim PTX: ERROR ** get_operand_value : unknown memory operand type for %s\n", name ); + abort(); } } else if ( op.is_literal() ) { @@ -260,10 +260,18 @@ 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_function_address() ) { result.u64 = (size_t)op.get_symbol()->get_pc(); - } else { + }else { const char *name = op.name().c_str(); - printf("GPGPU-Sim PTX: ERROR ** get_operand_value : unknown operand type for %s\n", name ); - assert(0); + const symbol *sym2 = op.get_symbol(); + const type_info *type2 = sym2->type(); + const type_info_key &info2 = type2->get_key(); + if ( info2.is_param_kernel() ) { + result.u64 = sym2->get_address()+ op.get_addr_offset(); + } + else{ + printf("GPGPU-Sim PTX: ERROR ** get_operand_value : unknown operand type for %s\n", name ); + assert(0); + } } if(op.get_operand_lohi() == 1) @@ -1551,7 +1559,44 @@ void bfe_impl( const ptx_instruction *pI, ptx_thread_info *thread ) thread->set_operand_value(dst,d, i_type, thread, pI); } -void bfi_impl( const ptx_instruction *pI, ptx_thread_info *thread ) { inst_not_implemented(pI); } +void bfi_impl( const ptx_instruction *pI, ptx_thread_info *thread ) { + int i,max; + ptx_reg_t src1_data, src2_data; + ptx_reg_t src3_data, src4_data, data; + + const operand_info &dst = pI->dst(); //get operand info of sources and destination + const operand_info &src1 = pI->src1(); //use them to determine that they are of type 'register' + const operand_info &src2 = pI->src2(); + const operand_info &src3 = pI->src3(); + const operand_info &src4 = pI->src4(); + + unsigned i_type = pI->get_type(); + src1_data = thread->get_operand_value(src1, dst, i_type, thread, 1); + src2_data = thread->get_operand_value(src2, dst, i_type, thread, 1); + src3_data = thread->get_operand_value(src3, dst, i_type, thread, 1); + src4_data = thread->get_operand_value(src4, dst, i_type, thread, 1); + + switch ( i_type ) { + case B32_TYPE: + max = 32; + break; + case B64_TYPE: + max = 64; + break; + default: + printf("Execution error: type mismatch with instruction\n"); + assert(0); + break; + } + data=src2_data; + unsigned pos = src3_data.u32 & 0xFF; + unsigned len = src4_data.u32 & 0xFF; + for(i=0;iset_operand_value(dst, data, i_type, thread, pI); +} void bfind_impl( const ptx_instruction *pI, ptx_thread_info *thread ) { inst_not_implemented(pI); } void bra_impl( const ptx_instruction *pI, ptx_thread_info *thread ) @@ -2180,16 +2225,19 @@ ptx_reg_t f2x( ptx_reg_t x, unsigned from_width, unsigned to_width, int to_sign, } } else { switch ( to_width ) { - case 16: //assert(0); break; + case 16: mytemp=half(x.f32); myfloat=mytemp; y.f16 =mytemp; - //y.f16 = half(x.f32); + #if 0 printf("f2x: %f\n",myfloat); + #endif break; case 32: - y.f32=float(x.f16); - + y.f32=float(x.f16); + #if 0 + printf("f2xnew:%x:my%f:%f\n",x.f16,y.f32,half_float::detail::half2float(x.u16)); + #endif break; // handled by f2f case 64: y.f64 = x.f32; @@ -2813,7 +2861,12 @@ void decode_space( memory_space_t &space, ptx_thread_info *thread, const operand space = param_space_kernel; else if( ti.is_param_local() ) { space = param_space_local; - } else { + } + //mov r1, param-label + else if (ti.is_reg() ){ + space = param_space_kernel; + } + else { printf("GPGPU-Sim PTX: ERROR ** cannot resolve .param space for '%s'\n", s->name().c_str() ); abort(); } @@ -2908,6 +2961,7 @@ void ldu_impl( const ptx_instruction *pI, ptx_thread_info *thread ) void mma_st_impl( const ptx_instruction *pI, core_t *core, warp_inst_t inst ) { size_t size; + unsigned smid; int t; int thrd,odd,inx,k; ptx_thread_info *thread; @@ -2936,7 +2990,12 @@ void mma_st_impl( const ptx_instruction *pI, core_t *core, warp_inst_t inst ) memory_space *mem = NULL; addr_t addr = addr_reg.u32; - + + smid = thread->get_hw_sid(); + if( whichspace(addr) == shared_space ) { + addr= generic_to_shared(smid,addr); + space = shared_space; + } decode_space(space,thread,src1,mem,addr); type_info_key::type_decode(type,size,t); @@ -2961,7 +3020,7 @@ void mma_st_impl( const ptx_instruction *pI, core_t *core, warp_inst_t inst ) int l; printf("thread=%d:",thrd); for(l=0;l<8;l++){ - temp=v[0].f32; + temp=v[l].f32; printf("%f",temp); } printf("\n"); @@ -2988,6 +3047,7 @@ void mma_ld_impl( const ptx_instruction *pI, core_t *core, warp_inst_t inst ) { size_t size; int t,i; + unsigned smid; const operand_info &dst = pI->dst(); const operand_info &src1 = pI->src1(); const operand_info &src2 = pI->src2(); @@ -3008,9 +3068,16 @@ void mma_ld_impl( const ptx_instruction *pI, core_t *core, warp_inst_t inst ) memory_space *mem = NULL; addr_t addr = src1_data.u32; - decode_space(space,thread,src1,mem,addr); - type_info_key::type_decode(type,size,t); + smid = thread->get_hw_sid(); + if( whichspace(addr) == shared_space ) { + addr= generic_to_shared(smid,addr); + space = shared_space; + } + + decode_space(space,thread,src1,mem,addr); + type_info_key::type_decode(type,size,t); + ptx_reg_t data[16]; if(g_debug_instruction) printf("mma_ld: thrd=%d,addr=%d, fpsize=%d, stride=%d\n",thrd,src1_data.u32,size,src2_data.u32); @@ -3070,13 +3137,13 @@ void mma_ld_impl( const ptx_instruction *pI, core_t *core, warp_inst_t inst ) } if(g_debug_instruction){ if(type==F16_TYPE){ - printf("\nthread%d= ",thrd); + printf("\nmma_ld:thread%d= ",thrd); for(i=0;i<16;i++){ printf("%x ",data[i].u64); } printf("\n"); - printf("\nthread%d= ",thrd); + printf("\nmma_ld:thread%d= ",thrd); float temp; for(i=0;i<16;i++){ temp=data[i].f16; @@ -3085,12 +3152,12 @@ void mma_ld_impl( const ptx_instruction *pI, core_t *core, warp_inst_t inst ) printf("\n"); } else{ - printf("\nthread%d= ",thrd); + printf("\nmma_ld:thread%d= ",thrd); for(i=0;i<8;i++){ printf("%f ",data[i].f32); } printf("\n"); - printf("\nthread%d= ",thrd); + printf("\nmma_ld:thread%d= ",thrd); for(i=0;i<8;i++){ printf("%x ",data[i].u64); } @@ -3119,15 +3186,15 @@ void mma_ld_impl( const ptx_instruction *pI, core_t *core, warp_inst_t inst ) else thread->set_wmma_vector_operand_values(dst,nw_data[0],nw_data[1],nw_data[2],nw_data[3],nw_data[4],nw_data[5],nw_data[6],nw_data[7]); if(g_debug_instruction){ - printf("wmma_load:data[0].s64=%x,data[1].s64=%x,new_data[0].s64=%x\n",data[0].u64,data[1].u64,nw_data[0].u64); - printf("wmma_load:data[2].s64=%x,data[3].s64=%x,new_data[1].s64=%x\n",data[2].u64,data[3].u64,nw_data[1].u64); - printf("wmma_load:data[4].s64=%x,data[5].s64=%x,new_data[2].s64=%x\n",data[4].u64,data[5].u64,nw_data[2].u64); - printf("wmma_load:data[6].s64=%x,data[7].s64=%x,new_data[3].s64=%x\n",data[6].u64,data[7].u64,nw_data[3].u64); + printf("mma_ld:data[0].s64=%x,data[1].s64=%x,new_data[0].s64=%x\n",data[0].u64,data[1].u64,nw_data[0].u64); + printf("mma_ld:data[2].s64=%x,data[3].s64=%x,new_data[1].s64=%x\n",data[2].u64,data[3].u64,nw_data[1].u64); + printf("mma_ld:data[4].s64=%x,data[5].s64=%x,new_data[2].s64=%x\n",data[4].u64,data[5].u64,nw_data[2].u64); + printf("mma_ld:data[6].s64=%x,data[7].s64=%x,new_data[3].s64=%x\n",data[6].u64,data[7].u64,nw_data[3].u64); if(wmma_type!=LOAD_C){ - printf("wmma_load:data[8].s64=%x,data[9].s64=%x,new_data[4].s64=%x\n",data[8].u64,data[9].u64,nw_data[4].s64); - printf("wmma_load:data[10].s64=%x,data[11].s64=%x,new_data[5].s64=%x\n",data[10].u64,data[11].u64,nw_data[5].u64); - printf("wmma_load:data[12].s64=%x,data[13].s64=%x,new_data[6].s64=%x\n",data[12].u64,data[13].u64,nw_data[6].u64); - printf("wmma_load:data[14].s64=%x,data[15].s64=%x,new_data[7].s64=%x\n",data[14].u64,data[15].u64,nw_data[3].u64); + printf("mma_ld:data[8].s64=%x,data[9].s64=%x,new_data[4].s64=%x\n",data[8].u64,data[9].u64,nw_data[4].s64); + printf("mma_ld:data[10].s64=%x,data[11].s64=%x,new_data[5].s64=%x\n",data[10].u64,data[11].u64,nw_data[5].u64); + printf("mma_ld:data[12].s64=%x,data[13].s64=%x,new_data[6].s64=%x\n",data[12].u64,data[13].u64,nw_data[6].u64); + printf("mma_ld:data[14].s64=%x,data[15].s64=%x,new_data[7].s64=%x\n",data[14].u64,data[15].u64,nw_data[3].u64); } } } -- cgit v1.3 From 9e7cd8867d76fb99eadfadfa09947ff057d012d3 Mon Sep 17 00:00:00 2001 From: negargoli93 Date: Thu, 16 Aug 2018 15:20:07 -0700 Subject: Timing model for VCORE --- src/abstract_hardware_model.h | 2 ++ src/cuda-sim/cuda-sim.cc | 28 ++++++++++++++++--- src/cuda-sim/ptx_ir.h | 4 +-- src/gpgpu-sim/gpu-sim.cc | 16 +++++++++-- src/gpgpu-sim/shader.cc | 62 ++++++++++++++++++++++++++++++++++++++++--- src/gpgpu-sim/shader.h | 57 ++++++++++++++++++++++++++++++++++----- 6 files changed, 152 insertions(+), 17 deletions(-) (limited to 'src/abstract_hardware_model.h') diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index 7fe5d82..781509f 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -78,6 +78,7 @@ enum uarch_op_t { ALU_OP=1, SFU_OP, TENSOR_CORE_OP, + VP_CORE_OP, ALU_SFU_OP, LOAD_OP, STORE_OP, @@ -135,6 +136,7 @@ enum operation_pipeline_t { SP__OP, SFU__OP, TENSOR_CORE__OP, + VP_CORE__OP, MEM__OP }; typedef enum operation_pipeline_t operation_pipeline; diff --git a/src/cuda-sim/cuda-sim.cc b/src/cuda-sim/cuda-sim.cc index 2fe5667..1ad12ee 100644 --- a/src/cuda-sim/cuda-sim.cc +++ b/src/cuda-sim/cuda-sim.cc @@ -542,7 +542,7 @@ void ptx_instruction::set_mul_div_or_other_archop(){ sp_op=INT_DIV_OP; break; default: - if((op==ALU_OP)||(op==TENSOR_CORE_OP)) + if((op==ALU_OP)||(op==VP_CORE_OP)) sp_op=INT__OP; break; } @@ -649,9 +649,11 @@ void ptx_instruction::set_opcode_and_latency() break; case LD_OP: op = LOAD_OP; break; case MMA_LD_OP: op = LOAD_OP; break; + case VP_LD_OP: op = LOAD_OP; break; case LDU_OP: op = LOAD_OP; break; case ST_OP: op = STORE_OP; break; case MMA_ST_OP: op = STORE_OP; break; + case VP_ST_OP: op = STORE_OP; break; case BRA_OP: op = BRANCH_OP; break; case BREAKADDR_OP: op = BRANCH_OP; break; case TEX_OP: op = LOAD_OP; mem_op=TEX; break; @@ -799,6 +801,26 @@ void ptx_instruction::set_opcode_and_latency() initiation_interval = 64; op=TENSOR_CORE_OP; break; + case VP_MMA_OP: + if(get_wmma_type()==VP_MMA4) + { + latency = 5; + initiation_interval = 5; + } + if(get_wmma_type()==VP_MMA8) + { + latency = 5; + initiation_interval = 5; + } + if(get_wmma_type()==VP_MMA16) + { + latency = 5; + initiation_interval = 5; + } + op=VP_CORE_OP; + op=VP_CORE_OP; + op=VP_CORE_OP; + break; case SHFL_OP: latency = 32; initiation_interval = 15; @@ -900,10 +922,10 @@ void ptx_instruction::pre_decode() case WT_OPTION: cache_op = CACHE_WRITE_THROUGH; break; default: //if( m_opcode == LD_OP || m_opcode == LDU_OP ) - if( m_opcode == MMA_LD_OP || m_opcode == LD_OP || m_opcode == LDU_OP ) + if( m_opcode ==VP_LD_OP || m_opcode == MMA_LD_OP || m_opcode == LD_OP || m_opcode == LDU_OP ) cache_op = CACHE_ALL; //else if( m_opcode == ST_OP ) - else if( m_opcode == ST_OP || m_opcode == ST_OP ) + else if( m_opcode == VP_ST_OP ||m_opcode == MMA_ST_OP || m_opcode == ST_OP ) cache_op = CACHE_WRITE_BACK; else if( m_opcode == ATOM_OP ) cache_op = CACHE_GLOBAL; diff --git a/src/cuda-sim/ptx_ir.h b/src/cuda-sim/ptx_ir.h index cb4556e..e025013 100644 --- a/src/cuda-sim/ptx_ir.h +++ b/src/cuda-sim/ptx_ir.h @@ -1093,7 +1093,7 @@ public: int membar_level() const { return m_membar_level; } bool has_memory_read() const { - if( m_opcode == LD_OP || m_opcode == LDU_OP || m_opcode == TEX_OP|| m_opcode==MMA_LD_OP) + if( m_opcode == LD_OP || m_opcode == LDU_OP || m_opcode == TEX_OP|| m_opcode==MMA_LD_OP || m_opcode==VP_LD_OP) return true; // Check PTXPlus operand type below // Source operands are memory operands @@ -1105,7 +1105,7 @@ public: return false; } bool has_memory_write() const { - if( m_opcode == ST_OP || m_opcode==MMA_ST_OP ) return true; + if( m_opcode == ST_OP || m_opcode==MMA_ST_OP || m_opcode==VP_ST_OP ) return true; // Check PTXPlus operand type below // Destination operand is a memory operand ptx_instruction::const_iterator op=op_iter_begin(); diff --git a/src/gpgpu-sim/gpu-sim.cc b/src/gpgpu-sim/gpu-sim.cc index 3e064c7..7a797b5 100644 --- a/src/gpgpu-sim/gpu-sim.cc +++ b/src/gpgpu-sim/gpu-sim.cc @@ -309,6 +309,9 @@ void shader_core_config::reg_options(class OptionParser * opp) option_parser_register(opp, "-gpgpu_operand_collector_num_units_tensor_core", OPT_INT32, &gpgpu_operand_collector_num_units_tensor_core, "number of collector units (default = 4)", "4"); + option_parser_register(opp, "-gpgpu_operand_collector_num_units_vp_core", OPT_INT32, &gpgpu_operand_collector_num_units_vp_core, + "number of collector units (default = 4)", + "4"); option_parser_register(opp, "-gpgpu_operand_collector_num_units_mem", OPT_INT32, &gpgpu_operand_collector_num_units_mem, "number of collector units (default = 2)", "2"); @@ -324,6 +327,9 @@ void shader_core_config::reg_options(class OptionParser * opp) option_parser_register(opp, "-gpgpu_operand_collector_num_in_ports_tensor_core", OPT_INT32, &gpgpu_operand_collector_num_in_ports_tensor_core, "number of collector unit in ports (default = 1)", "1"); + option_parser_register(opp, "-gpgpu_operand_collector_num_in_ports_vp_core", OPT_INT32, &gpgpu_operand_collector_num_in_ports_vp_core, + "number of collector unit in ports (default = 1)", + "1"); option_parser_register(opp, "-gpgpu_operand_collector_num_in_ports_mem", OPT_INT32, &gpgpu_operand_collector_num_in_ports_mem, "number of collector unit in ports (default = 1)", "1"); @@ -339,6 +345,9 @@ void shader_core_config::reg_options(class OptionParser * opp) option_parser_register(opp, "-gpgpu_operand_collector_num_out_ports_tensor_core", OPT_INT32, &gpgpu_operand_collector_num_out_ports_tensor_core, "number of collector unit in ports (default = 1)", "1"); + option_parser_register(opp, "-gpgpu_operand_collector_num_out_ports_vp_core", OPT_INT32, &gpgpu_operand_collector_num_out_ports_vp_core, + "number of collector unit in ports (default = 1)", + "1"); option_parser_register(opp, "-gpgpu_operand_collector_num_out_ports_mem", OPT_INT32, &gpgpu_operand_collector_num_out_ports_mem, "number of collector unit in ports (default = 1)", "1"); @@ -359,8 +368,8 @@ void shader_core_config::reg_options(class OptionParser * opp) "1"); option_parser_register(opp, "-gpgpu_pipeline_widths", OPT_CSTR, &pipeline_widths_string, "Pipeline widths " - "ID_OC_SP,ID_OC_SFU,ID_OC_TENSOR_CORE,ID_OC_MEM,OC_EX_SP,OC_EX_SFU,OC_EX_TENSOR_CORE,OC_EX_MEM,EX_WB", - "1,1,1,1,1,1,1,1,1" ); + "ID_OC_SP,ID_OC_SFU,ID_OC_TENSOR_CORE,ID_OC_VP_CORE,ID_OC_MEM,OC_EX_SP,OC_EX_SFU,OC_EX_TENSOR_CORE,OC_EX_TENSOR_CORE,OC_EX_MEM,EX_WB", + "1,1,1,1,1,1,1,1,1,1,1" ); option_parser_register(opp, "-gpgpu_num_sp_units", OPT_INT32, &gpgpu_num_sp_units, "Number of SP units (default=1)", "1"); @@ -370,6 +379,9 @@ void shader_core_config::reg_options(class OptionParser * opp) option_parser_register(opp, "-gpgpu_num_tensor_core_units", OPT_INT32, &gpgpu_num_tensor_core_units, "Number of tensor_core units (default=1)", "1"); + option_parser_register(opp, "-gpgpu_num_vp_core_units", OPT_INT32, &gpgpu_num_vp_core_units, + "Number of vp_core units (default=1)", + "1"); option_parser_register(opp, "-gpgpu_num_mem_units", OPT_INT32, &gpgpu_num_mem_units, "Number if ldst units (default=1) WARNING: not hooked up to anything", "1"); diff --git a/src/gpgpu-sim/shader.cc b/src/gpgpu-sim/shader.cc index 226e7f0..6f11ad9 100644 --- a/src/gpgpu-sim/shader.cc +++ b/src/gpgpu-sim/shader.cc @@ -149,6 +149,7 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, &m_pipeline_reg[ID_OC_SP], &m_pipeline_reg[ID_OC_SFU], &m_pipeline_reg[ID_OC_TENSOR_CORE], + &m_pipeline_reg[ID_OC_VP_CORE], &m_pipeline_reg[ID_OC_MEM], i ) @@ -164,6 +165,7 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, &m_pipeline_reg[ID_OC_SP], &m_pipeline_reg[ID_OC_SFU], &m_pipeline_reg[ID_OC_TENSOR_CORE], + &m_pipeline_reg[ID_OC_VP_CORE], &m_pipeline_reg[ID_OC_MEM], i, config->gpgpu_scheduler_string @@ -180,6 +182,7 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, &m_pipeline_reg[ID_OC_SP], &m_pipeline_reg[ID_OC_SFU], &m_pipeline_reg[ID_OC_TENSOR_CORE], + &m_pipeline_reg[ID_OC_VP_CORE], &m_pipeline_reg[ID_OC_MEM], i ) @@ -195,6 +198,7 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, &m_pipeline_reg[ID_OC_SP], &m_pipeline_reg[ID_OC_SFU], &m_pipeline_reg[ID_OC_TENSOR_CORE], + &m_pipeline_reg[ID_OC_VP_CORE], &m_pipeline_reg[ID_OC_MEM], i, config->gpgpu_scheduler_string @@ -215,10 +219,11 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, } //op collector configuration - enum { SP_CUS, SFU_CUS, TENSOR_CORE_CUS, MEM_CUS, GEN_CUS }; + enum { SP_CUS, SFU_CUS, TENSOR_CORE_CUS, VP_CORE_CUS, MEM_CUS, GEN_CUS }; m_operand_collector.add_cu_set(SP_CUS, m_config->gpgpu_operand_collector_num_units_sp, m_config->gpgpu_operand_collector_num_out_ports_sp); m_operand_collector.add_cu_set(SFU_CUS, m_config->gpgpu_operand_collector_num_units_sfu, m_config->gpgpu_operand_collector_num_out_ports_sfu); m_operand_collector.add_cu_set(TENSOR_CORE_CUS, config->gpgpu_operand_collector_num_units_tensor_core, config->gpgpu_operand_collector_num_out_ports_tensor_core); + m_operand_collector.add_cu_set(VP_CORE_CUS, config->gpgpu_operand_collector_num_units_vp_core, config->gpgpu_operand_collector_num_out_ports_vp_core); m_operand_collector.add_cu_set(MEM_CUS, m_config->gpgpu_operand_collector_num_units_mem, m_config->gpgpu_operand_collector_num_out_ports_mem); m_operand_collector.add_cu_set(GEN_CUS, m_config->gpgpu_operand_collector_num_units_gen, m_config->gpgpu_operand_collector_num_out_ports_gen); @@ -252,6 +257,14 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, in_ports.clear(),out_ports.clear(),cu_sets.clear(); } + for (unsigned i = 0; i < config->gpgpu_operand_collector_num_in_ports_vp_core; i++) { + in_ports.push_back(&m_pipeline_reg[ID_OC_VP_CORE]); + out_ports.push_back(&m_pipeline_reg[OC_EX_VP_CORE]); + cu_sets.push_back((unsigned)VP_CORE_CUS); + cu_sets.push_back((unsigned)GEN_CUS); + m_operand_collector.add_port(in_ports,out_ports,cu_sets); + in_ports.clear(),out_ports.clear(),cu_sets.clear(); + } for (unsigned i = 0; i < m_config->gpgpu_operand_collector_num_in_ports_mem; i++) { in_ports.push_back(&m_pipeline_reg[ID_OC_MEM]); @@ -267,10 +280,12 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, in_ports.push_back(&m_pipeline_reg[ID_OC_SP]); in_ports.push_back(&m_pipeline_reg[ID_OC_SFU]); in_ports.push_back(&m_pipeline_reg[ID_OC_TENSOR_CORE]); + in_ports.push_back(&m_pipeline_reg[ID_OC_VP_CORE]); in_ports.push_back(&m_pipeline_reg[ID_OC_MEM]); out_ports.push_back(&m_pipeline_reg[OC_EX_SP]); out_ports.push_back(&m_pipeline_reg[OC_EX_SFU]); out_ports.push_back(&m_pipeline_reg[OC_EX_TENSOR_CORE]); + out_ports.push_back(&m_pipeline_reg[OC_EX_VP_CORE]); out_ports.push_back(&m_pipeline_reg[OC_EX_MEM]); cu_sets.push_back((unsigned)GEN_CUS); m_operand_collector.add_port(in_ports,out_ports,cu_sets); @@ -280,7 +295,7 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, m_operand_collector.init( m_config->gpgpu_num_reg_banks, this ); // execute - m_num_function_units = m_config->gpgpu_num_sp_units + m_config->gpgpu_num_sfu_units + config->gpgpu_num_tensor_core_units + 1; // sp_unit, sfu, ldst_unit + m_num_function_units = m_config->gpgpu_num_sp_units + m_config->gpgpu_num_sfu_units + config->gpgpu_num_tensor_core_units + config->gpgpu_num_vp_core_units + 1; // sp_unit, sfu, ldst_unit //m_dispatch_port = new enum pipeline_stage_name_t[ m_num_function_units ]; //m_issue_port = new enum pipeline_stage_name_t[ m_num_function_units ]; @@ -304,6 +319,12 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, m_issue_port.push_back(OC_EX_TENSOR_CORE); } + for (int k = 0; k < config->gpgpu_num_vp_core_units; k++) { + m_fu.push_back(new vp_core( &m_pipeline_reg[EX_WB], m_config, this )); + m_dispatch_port.push_back(ID_OC_VP_CORE); + m_issue_port.push_back(OC_EX_VP_CORE); + } + m_ldst_unit = new ldst_unit( m_icnt, m_mem_fetch_allocator, this, &m_operand_collector, m_scoreboard, config, mem_config, stats, shader_id, tpc_id ); m_fu.push_back(m_ldst_unit); m_dispatch_port.push_back(ID_OC_MEM); @@ -910,7 +931,8 @@ void scheduler_unit::cycle() bool sp_pipe_avail = m_sp_out->has_free(); bool sfu_pipe_avail = m_sfu_out->has_free(); bool tensor_core_pipe_avail = m_tensor_core_out->has_free(); - if( sp_pipe_avail && (pI->op != SFU_OP) && (pI->op != TENSOR_CORE_OP)) { + bool vp_core_pipe_avail = m_vp_core_out->has_free(); + if( sp_pipe_avail && (pI->op != SFU_OP) && (pI->op != TENSOR_CORE_OP) && (pI->op !=VP_CORE_OP)) { //Jin: special for CDP api if(pI->m_is_cdp && !warp(warp_id).m_cdp_dummy) { @@ -950,6 +972,14 @@ void scheduler_unit::cycle() issued_inst=true; warp_inst_issued = true; } + } + else if ( (pI->op == VP_CORE_OP) ) { + if( vp_core_pipe_avail ) { + m_shader->issue_warp(*m_vp_core_out,pI,active_mask,warp_id); + issued++; + issued_inst=true; + warp_inst_issued = true; + } } } } else { SCHED_DPRINTF( "Warp (warp_id %u, dynamic_warp_id %u) fails scoreboard\n", @@ -1116,10 +1146,11 @@ swl_scheduler::swl_scheduler ( shader_core_stats* stats, shader_core_ctx* shader register_set* sp_out, register_set* sfu_out, register_set* tensor_core_out, + register_set* vp_core_out, register_set* mem_out, int id, char* config_string ) - : scheduler_unit ( stats, shader, scoreboard, simt, warp, sp_out, sfu_out, tensor_core_out, mem_out, id ) + : scheduler_unit ( stats, shader, scoreboard, simt, warp, sp_out, sfu_out, tensor_core_out, vp_core_out, mem_out, id ) { unsigned m_prioritization_readin; int ret = sscanf( config_string, @@ -1548,6 +1579,12 @@ tensor_core:: tensor_core( register_set* result_port, const shader_core_config m_name = "TENSOR_CORE"; } +vp_core:: vp_core( register_set* result_port, const shader_core_config *config,shader_core_ctx *core ) + : pipelined_simd_unit(result_port,config,config->max_vp_core_latency,core) +{ + m_name = "VP_CORE"; +} + void sfu::issue( register_set& source_reg ) { @@ -1569,6 +1606,16 @@ void tensor_core::issue( register_set& source_reg ) pipelined_simd_unit::issue(source_reg); } +void vp_core::issue( register_set& source_reg ) +{ + warp_inst_t** ready_reg = source_reg.get_ready(); + //m_core->incexecstat((*ready_reg)); + + (*ready_reg)->op_pipe= VP_CORE__OP; + m_core->incsfu_stat(m_core->get_config()->warp_size,(*ready_reg)->latency); + pipelined_simd_unit::issue(source_reg); +} + void ldst_unit::active_lanes_in_pipeline(){ unsigned active_count=pipelined_simd_unit::get_active_lanes_in_pipeline(); @@ -1599,6 +1646,13 @@ void tensor_core::active_lanes_in_pipeline(){ m_core->incfumemactivelanes_stat(active_count); } +void vp_core::active_lanes_in_pipeline(){ + unsigned active_count=pipelined_simd_unit::get_active_lanes_in_pipeline(); + assert(active_count<=m_core->get_config()->warp_size); + m_core->incsfuactivelanes_stat(active_count); + m_core->incfuactivelanes_stat(active_count); + m_core->incfumemactivelanes_stat(active_count); +} sp_unit::sp_unit( register_set* result_port, const shader_core_config *config,shader_core_ctx *core) : pipelined_simd_unit(result_port,config,config->max_sp_latency,core) diff --git a/src/gpgpu-sim/shader.h b/src/gpgpu-sim/shader.h index 90a3134..d292d56 100644 --- a/src/gpgpu-sim/shader.h +++ b/src/gpgpu-sim/shader.h @@ -319,11 +319,12 @@ public: register_set* sp_out, register_set* sfu_out, register_set* tensor_core_out, + register_set* vp_core_out, register_set* mem_out, int id) : m_supervised_warps(), m_stats(stats), m_shader(shader), m_scoreboard(scoreboard), m_simt_stack(simt), /*m_pipeline_reg(pipe_regs),*/ m_warp(warp), - m_sp_out(sp_out),m_sfu_out(sfu_out),m_tensor_core_out(tensor_core_out),m_mem_out(mem_out), m_id(id){} + m_sp_out(sp_out),m_sfu_out(sfu_out),m_tensor_core_out(tensor_core_out),m_vp_core_out(vp_core_out),m_mem_out(mem_out), m_id(id){} virtual ~scheduler_unit(){} virtual void add_supervised_warp_id(int i) { m_supervised_warps.push_back(&warp(i)); @@ -397,6 +398,7 @@ protected: register_set* m_sp_out; register_set* m_sfu_out; register_set* m_tensor_core_out; + register_set* m_vp_core_out; register_set* m_mem_out; int m_id; @@ -410,9 +412,10 @@ public: register_set* sp_out, register_set* sfu_out, register_set* tensor_core_out, + register_set* vp_core_out, register_set* mem_out, int id ) - : scheduler_unit ( stats, shader, scoreboard, simt, warp, sp_out, sfu_out, tensor_core_out, mem_out, id ){} + : scheduler_unit ( stats, shader, scoreboard, simt, warp, sp_out, sfu_out, tensor_core_out, vp_core_out, mem_out, id ){} virtual ~lrr_scheduler () {} virtual void order_warps (); virtual void done_adding_supervised_warps() { @@ -428,9 +431,10 @@ public: register_set* sp_out, register_set* sfu_out, register_set* tensor_core_out, + register_set* vp_core_out, register_set* mem_out, int id ) - : scheduler_unit ( stats, shader, scoreboard, simt, warp, sp_out, sfu_out, tensor_core_out, mem_out, id ){} + : scheduler_unit ( stats, shader, scoreboard, simt, warp, sp_out, sfu_out, tensor_core_out,vp_core_out, mem_out, id ){} virtual ~gto_scheduler () {} virtual void order_warps (); virtual void done_adding_supervised_warps() { @@ -448,10 +452,11 @@ public: register_set* sp_out, register_set* sfu_out, register_set* tensor_core_out, + register_set* vp_core_out, register_set* mem_out, int id, char* config_str ) - : scheduler_unit ( stats, shader, scoreboard, simt, warp, sp_out, sfu_out, tensor_core_out, mem_out, id ), + : scheduler_unit ( stats, shader, scoreboard, simt, warp, sp_out, sfu_out, tensor_core_out, vp_core_out, mem_out, id ), m_pending_warps() { unsigned inner_level_readin; @@ -499,6 +504,7 @@ public: register_set* sp_out, register_set* sfu_out, register_set* tensor_core_out, + register_set* vp_core_out, register_set* mem_out, int id, char* config_string ); @@ -1083,6 +1089,22 @@ public: virtual void active_lanes_in_pipeline(); virtual void issue( register_set& source_reg ); }; +class vp_core : public pipelined_simd_unit +{ +public: + vp_core( register_set* result_port, const shader_core_config *config, shader_core_ctx *core ); + virtual bool can_issue( const warp_inst_t &inst ) const + { + switch(inst.op) { + case VP_CORE_OP: break; + default: return false; + } + return pipelined_simd_unit::can_issue(inst); + } + virtual void active_lanes_in_pipeline(); + virtual void issue( register_set& source_reg ); +}; + class sp_unit : public pipelined_simd_unit @@ -1225,10 +1247,12 @@ enum pipeline_stage_name_t { ID_OC_SP=0, ID_OC_SFU, ID_OC_TENSOR_CORE, + ID_OC_VP_CORE, ID_OC_MEM, OC_EX_SP, OC_EX_SFU, OC_EX_TENSOR_CORE, + OC_EX_VP_CORE, OC_EX_MEM, EX_WB, N_PIPELINE_STAGES @@ -1238,10 +1262,12 @@ const char* const pipeline_stage_name_decode[] = { "ID_OC_SP", "ID_OC_SFU", "ID_OC_TENSOR_CORE", + "ID_OC_VP_CORE", "ID_OC_MEM", "OC_EX_SP", "OC_EX_SFU", "OC_EX_TENSOR_CORE", + "OC_EX_VP_CORE", "OC_EX_MEM", "EX_WB", "N_PIPELINE_STAGES" @@ -1286,13 +1312,21 @@ struct shader_core_config : public core_config max_warps_per_shader = n_thread_per_shader/warp_size; assert( !(n_thread_per_shader % warp_size) ); max_sfu_latency = 512; - max_tensor_core_latency = 64; max_sp_latency = 32; + + max_tensor_core_latency = 64; gpgpu_num_tensor_core_units=8; gpgpu_operand_collector_num_units_tensor_core=24; gpgpu_operand_collector_num_in_ports_tensor_core=8; gpgpu_operand_collector_num_out_ports_tensor_core=8; - m_L1I_config.init(m_L1I_config.m_config_string,FuncCachePreferNone); + + max_vp_core_latency = 64; + gpgpu_num_vp_core_units=8; + gpgpu_operand_collector_num_units_vp_core=24; + gpgpu_operand_collector_num_in_ports_vp_core=8; + gpgpu_operand_collector_num_out_ports_vp_core=8; + + m_L1I_config.init(m_L1I_config.m_config_string,FuncCachePreferNone); m_L1T_config.init(m_L1T_config.m_config_string,FuncCachePreferNone); m_L1C_config.init(m_L1C_config.m_config_string,FuncCachePreferNone); m_L1D_config.init(m_L1D_config.m_config_string,FuncCachePreferNone); @@ -1339,24 +1373,28 @@ struct shader_core_config : public core_config int gpgpu_operand_collector_num_units_sp; int gpgpu_operand_collector_num_units_sfu; int gpgpu_operand_collector_num_units_tensor_core; + int gpgpu_operand_collector_num_units_vp_core; int gpgpu_operand_collector_num_units_mem; int gpgpu_operand_collector_num_units_gen; unsigned int gpgpu_operand_collector_num_in_ports_sp; unsigned int gpgpu_operand_collector_num_in_ports_sfu; unsigned int gpgpu_operand_collector_num_in_ports_tensor_core; + unsigned int gpgpu_operand_collector_num_in_ports_vp_core; unsigned int gpgpu_operand_collector_num_in_ports_mem; unsigned int gpgpu_operand_collector_num_in_ports_gen; unsigned int gpgpu_operand_collector_num_out_ports_sp; unsigned int gpgpu_operand_collector_num_out_ports_sfu; unsigned int gpgpu_operand_collector_num_out_ports_tensor_core; + unsigned int gpgpu_operand_collector_num_out_ports_vp_core; unsigned int gpgpu_operand_collector_num_out_ports_mem; unsigned int gpgpu_operand_collector_num_out_ports_gen; int gpgpu_num_sp_units; int gpgpu_num_sfu_units; int gpgpu_num_tensor_core_units; + int gpgpu_num_vp_core_units; int gpgpu_num_mem_units; //Shader core resources @@ -1370,6 +1408,7 @@ struct shader_core_config : public core_config unsigned max_sp_latency; unsigned max_sfu_latency; unsigned max_tensor_core_latency; + unsigned max_vp_core_latency; unsigned n_simt_cores_per_cluster; unsigned n_simt_clusters; @@ -1408,6 +1447,7 @@ struct shader_core_stats_pod { unsigned *m_num_sp_acesses; unsigned *m_num_sfu_acesses; unsigned *m_num_tensor_core_acesses; + unsigned *m_num_vp_core_acesses; unsigned *m_num_trans_acesses; unsigned *m_num_mem_acesses; unsigned *m_num_sp_committed; @@ -1415,6 +1455,7 @@ struct shader_core_stats_pod { unsigned *m_num_tlb_accesses; unsigned *m_num_sfu_committed; unsigned *m_num_tensor_core_committed; + unsigned *m_num_vp_core_committed; unsigned *m_num_mem_committed; unsigned *m_read_regfile_acesses; unsigned *m_write_regfile_acesses; @@ -1424,6 +1465,7 @@ struct shader_core_stats_pod { unsigned *m_active_sp_lanes; unsigned *m_active_sfu_lanes; unsigned *m_active_tensor_core_lanes; + unsigned *m_active_vp_core_lanes; unsigned *m_active_fu_lanes; unsigned *m_active_fu_mem_lanes; unsigned *m_n_diverge; // number of divergence occurring in this shader @@ -1496,6 +1538,7 @@ public: m_num_sp_acesses= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); m_num_sfu_acesses= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); m_num_tensor_core_acesses= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_num_vp_core_acesses= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); m_num_trans_acesses= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); m_num_mem_acesses= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); m_num_sp_committed= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); @@ -1504,10 +1547,12 @@ public: m_active_sp_lanes= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); m_active_sfu_lanes= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); m_active_tensor_core_lanes= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_active_vp_core_lanes= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); m_active_fu_lanes= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); m_active_fu_mem_lanes= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); m_num_sfu_committed= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); m_num_tensor_core_committed= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_num_vp_core_committed= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); m_num_mem_committed= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); m_read_regfile_acesses= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); m_write_regfile_acesses= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); -- cgit v1.3 From 3082f63e86be2e115e4a071069dda8fe9452d366 Mon Sep 17 00:00:00 2001 From: Mengchi Zhang Date: Thu, 6 Sep 2018 16:33:18 -0400 Subject: Add .nc option Signed-off-by: Mengchi Zhang --- src/abstract_hardware_model.h | 1 + src/cuda-sim/cuda-sim.cc | 1 + src/cuda-sim/ptx_ir.cc | 1 + src/gpgpu-sim/shader.cc | 2 +- 4 files changed, 4 insertions(+), 1 deletion(-) (limited to 'src/abstract_hardware_model.h') diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index 1b764e2..6df7b89 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -664,6 +664,7 @@ enum cache_operator_type { CACHE_ALL, // .ca CACHE_LAST_USE, // .lu CACHE_VOLATILE, // .cv + CACHE_L1, // .nc // loads and stores CACHE_STREAMING, // .cs diff --git a/src/cuda-sim/cuda-sim.cc b/src/cuda-sim/cuda-sim.cc index 9246613..93bbc1d 100644 --- a/src/cuda-sim/cuda-sim.cc +++ b/src/cuda-sim/cuda-sim.cc @@ -898,6 +898,7 @@ void ptx_instruction::pre_decode() switch( m_cache_option ) { case CA_OPTION: cache_op = CACHE_ALL; break; + case NC_OPTION: cache_op = CACHE_L1; break; case CG_OPTION: cache_op = CACHE_GLOBAL; break; case CS_OPTION: cache_op = CACHE_STREAMING; break; case LU_OPTION: cache_op = CACHE_LAST_USE; break; diff --git a/src/cuda-sim/ptx_ir.cc b/src/cuda-sim/ptx_ir.cc index ee36957..ba6d7ed 100644 --- a/src/cuda-sim/ptx_ir.cc +++ b/src/cuda-sim/ptx_ir.cc @@ -1211,6 +1211,7 @@ ptx_instruction::ptx_instruction( int opcode, case EXTP_OPTION: break; case NC_OPTION: + m_cache_option = last_ptx_inst_option; break; case UP_OPTION: case DOWN_OPTION: diff --git a/src/gpgpu-sim/shader.cc b/src/gpgpu-sim/shader.cc index d2f40a1..533c6f9 100644 --- a/src/gpgpu-sim/shader.cc +++ b/src/gpgpu-sim/shader.cc @@ -1537,7 +1537,7 @@ bool ldst_unit::memory_cycle( warp_inst_t &inst, mem_stage_stall_type &stall_rea bypassL1D = true; } else if (inst.space.is_global()) { // global memory access // skip L1 cache if the option is enabled - if (m_core->get_config()->gmem_skip_L1D) + if (m_core->get_config()->gmem_skip_L1D && (CACHE_L1 != inst.cache_op)) bypassL1D = true; } -- cgit v1.3 From f852a7108e691045dd3910065836a817babcde8c Mon Sep 17 00:00:00 2001 From: Mahmoud Date: Fri, 7 Sep 2018 22:01:31 -0400 Subject: adding streamin cache + fixing TEX cache + adding l1 latency and smem latency --- configs/4.x-cfgs/SM2_GTX480/gpgpusim.config | 2 +- configs/4.x-cfgs/SM6_P100/config_fermi_islip.icnt | 73 --------- configs/4.x-cfgs/SM6_P100/gpgpusim.config | 174 --------------------- .../SM6_P100_64SMs/config_fermi_islip.icnt | 73 --------- configs/4.x-cfgs/SM6_P100_64SMs/gpgpusim.config | 174 --------------------- configs/4.x-cfgs/SM6_TITANX/gpgpusim.config | 27 ++-- src/abstract_hardware_model.h | 1 + src/gpgpu-sim/gpu-cache.cc | 20 ++- src/gpgpu-sim/gpu-cache.h | 36 ++++- src/gpgpu-sim/gpu-sim.cc | 6 + src/gpgpu-sim/l2cache.cc | 8 +- src/gpgpu-sim/shader.cc | 126 ++++++++++++++- src/gpgpu-sim/shader.h | 6 + 13 files changed, 207 insertions(+), 519 deletions(-) delete mode 100644 configs/4.x-cfgs/SM6_P100/config_fermi_islip.icnt delete mode 100644 configs/4.x-cfgs/SM6_P100/gpgpusim.config delete mode 100644 configs/4.x-cfgs/SM6_P100_64SMs/config_fermi_islip.icnt delete mode 100644 configs/4.x-cfgs/SM6_P100_64SMs/gpgpusim.config (limited to 'src/abstract_hardware_model.h') diff --git a/configs/4.x-cfgs/SM2_GTX480/gpgpusim.config b/configs/4.x-cfgs/SM2_GTX480/gpgpusim.config index 7f8da49..35341f7 100644 --- a/configs/4.x-cfgs/SM2_GTX480/gpgpusim.config +++ b/configs/4.x-cfgs/SM2_GTX480/gpgpusim.config @@ -67,7 +67,7 @@ -memory_partition_indexing 0 -gpgpu_cache:il1 N:4:128:4,L:R:f:N:L,S:2:32,4 --gpgpu_tex_cache:l1 N:4:128:24,L:R:m:N:L,F:128:4,128:2 +-gpgpu_tex_cache:l1 N:4:128:24,L:R:m:N:L,T:128:4,128:2 -gpgpu_const_cache:l1 N:64:64:2,L:R:f:N:L,S:2:32,4 # enable operand collector diff --git a/configs/4.x-cfgs/SM6_P100/config_fermi_islip.icnt b/configs/4.x-cfgs/SM6_P100/config_fermi_islip.icnt deleted file mode 100644 index e7c2c3b..0000000 --- a/configs/4.x-cfgs/SM6_P100/config_fermi_islip.icnt +++ /dev/null @@ -1,73 +0,0 @@ -//21*1 fly with 32 flits per packet under gpgpusim injection mode -use_map = 0; -flit_size = 40; - -// currently we do not use this, see subnets below -network_count = 2; - -// Topology -topology = fly; -k = 60; -n = 1; - -// Routing - -routing_function = dest_tag; - -// Flow control - -num_vcs = 1; -vc_buf_size = 128; -input_buffer_size = 256; -ejection_buffer_size = 128; -boundary_buffer_size = 128; - -wait_for_tail_credit = 0; - -// Router architecture - -vc_allocator = islip; //separable_input_first; -sw_allocator = islip; //separable_input_first; -alloc_iters = 1; - -credit_delay = 0; -routing_delay = 0; -vc_alloc_delay = 1; -sw_alloc_delay = 1; - -input_speedup = 2; -output_speedup = 1; -internal_speedup = 1.0; - -// Traffic, GPGPU-Sim does not use this - -traffic = uniform; -packet_size ={{1,2,3,4},{10,20}}; -packet_size_rate={{1,1,1,1},{2,1}}; - -// Simulation - Don't change - -sim_type = gpgpusim; -//sim_type = latency; -injection_rate = 0.1; - -subnets = 2; - -// Always use read and write no matter following line -//use_read_write = 1; - - -read_request_subnet = 0; -read_reply_subnet = 1; -write_request_subnet = 0; -write_reply_subnet = 1; - -read_request_begin_vc = 0; -read_request_end_vc = 0; -write_request_begin_vc = 0; -write_request_end_vc = 0; -read_reply_begin_vc = 0; -read_reply_end_vc = 0; -write_reply_begin_vc = 0; -write_reply_end_vc = 0; - diff --git a/configs/4.x-cfgs/SM6_P100/gpgpusim.config b/configs/4.x-cfgs/SM6_P100/gpgpusim.config deleted file mode 100644 index a4e745d..0000000 --- a/configs/4.x-cfgs/SM6_P100/gpgpusim.config +++ /dev/null @@ -1,174 +0,0 @@ -# functional simulator specification --gpgpu_ptx_instruction_classification 0 --gpgpu_ptx_sim_mode 0 --gpgpu_ptx_force_max_capability 60 - -# SASS execution (only supported with CUDA >= 4.0) --gpgpu_ptx_convert_to_ptxplus 0 --gpgpu_ptx_save_converted_ptxplus 0 - -# high level architecture configuration --gpgpu_n_clusters 28 --gpgpu_n_cores_per_cluster 2 --gpgpu_n_mem 32 --gpgpu_n_sub_partition_per_mchannel 1 - -# Pscal clock domains -#-gpgpu_clock_domains ::: -# Pascal NVIDIA GP100 clock domains are adopted from -# https://en.wikipedia.org/wiki/Nvidia_Tesla --gpgpu_clock_domains 1480.0:1480.0:1480.0:715.0 - -# shader core pipeline config --gpgpu_shader_registers 65536 - -# This implies a maximum of 64 warps/SM --gpgpu_shader_core_pipeline 2048:32 --gpgpu_shader_cta 32 --gpgpu_simd_model 1 - -# Pipeline widths and number of FUs -# ID_OC_SP,ID_OC_DP,ID_OC_SFU,ID_OC_MEM,OC_EX_SP,OC_EX_DP,OC_EX_SFU,OC_EX_MEM,EX_WB -## Pascal GP100 has 2 SP SIMD units, 2 SFU units, 2 DP units per core -## we need to scale the number of pipeline registers to be equal to the number of SP units --gpgpu_pipeline_widths 2,2,2,1,2,2,2,1,6 --gpgpu_num_sp_units 2 --gpgpu_num_sfu_units 2 --gpgpu_num_dp_units 2 - -# Instruction latencies and initiation intervals -# "ADD,MAX,MUL,MAD,DIV" -# All Div operations are executed on SFU unit -# Throughput (initiation latency) are adopted from CUDA SDK document V8, section 5.4.1, Table 2 --ptx_opcode_latency_int 4,13,4,5,145 --ptx_opcode_initiation_int 1,1,1,1,4 --ptx_opcode_latency_fp 4,13,4,5,39 --ptx_opcode_initiation_fp 1,2,1,1,4 --ptx_opcode_latency_dp 8,19,8,8,330 --ptx_opcode_initiation_dp 2,2,2,2,130 --ptx_opcode_latency_sfu 8 --ptx_opcode_initiation_sfu 4 - - -# ::,::::,::,:** -# ** Optional parameter - Required when mshr_type==Texture Fifo -# Note: Hashing set index function (H) only applies to a set size of 32 or 64. -# Pascal GP100 has 64KB Shared memory --gpgpu_cache:dl1 S:64:128:6,L:L:f:N:H,A:256:8,16:0,32 --gpgpu_cache:dl1PrefL1 S:64:128:6,L:L:f:N:H,A:256:8,16:0,32 --gpgpu_cache:dl1PrefShared S:64:128:6,L:L:f:N:H,A:256:8,16:0,32 --gpgpu_shmem_size 65536 --gpgpu_shmem_size_PrefL1 65536 --gpgpu_shmem_size_PrefShared 65536 --gmem_skip_L1D 0 --icnt_flit_size 40 --gpgpu_n_cluster_ejection_buffer_size 32 - -# 32 sets, each 128 bytes 16-way for each memory sub partition (128 KB per memory sub partition). This gives 4MB L2 cache --gpgpu_cache:dl2 S:64:128:16,L:B:m:L:L,A:256:4,32:0,32 --gpgpu_cache:dl2_texture_only 0 --gpgpu_dram_partition_queues 64:64:64:64 --perf_sim_memcpy 0 --memory_partition_indexing 2 - -# 4 KB Inst. --gpgpu_cache:il1 N:8:128:4,L:R:f:N:L,S:2:48,4 -# 48 KB Tex --gpgpu_tex_cache:l1 N:16:128:24,L:R:m:N:L,F:128:4,128:2 -# 12 KB Const --gpgpu_const_cache:l1 N:128:64:2,L:R:f:N:L,S:2:64,4 - -# enable operand collector --gpgpu_operand_collector_num_units_sp 12 --gpgpu_operand_collector_num_units_sfu 6 --gpgpu_operand_collector_num_units_mem 8 --gpgpu_operand_collector_num_units_dp 6 --gpgpu_operand_collector_num_in_ports_sp 4 --gpgpu_operand_collector_num_out_ports_sp 4 --gpgpu_operand_collector_num_in_ports_sfu 1 --gpgpu_operand_collector_num_out_ports_sfu 1 --gpgpu_operand_collector_num_in_ports_mem 1 --gpgpu_operand_collector_num_out_ports_mem 1 --gpgpu_operand_collector_num_in_ports_dp 1 --gpgpu_operand_collector_num_out_ports_dp 1 --gpgpu_num_reg_banks 32 - -# shared memory bankconflict detection --gpgpu_shmem_num_banks 32 --gpgpu_shmem_limited_broadcast 0 --gpgpu_shmem_warp_parts 1 --gpgpu_coalesce_arch 60 - -## In Pascal, a warp scheduler can issue 2 insts per cycle using 2 diff execution units --gpgpu_max_insn_issue_per_warp 2 --gpgpu_dual_issue_diff_exec_units 1 - -# interconnection --network_mode 1 --inter_config_file config_fermi_islip.icnt - -# memory partition latency config --rop_latency 120 --dram_latency 100 - -# dram model config --gpgpu_dram_scheduler 1 -# The DRAM return queue and the scheduler queue together should provide buffer -# to sustain the memory level parallelism to tolerate DRAM latency -# To allow 100% DRAM utility, there should at least be enough buffer to sustain -# the minimum DRAM latency (100 core cycles). I.e. -# Total buffer space required = 100 x 924MHz / 700MHz = 132 --gpgpu_frfcfs_dram_sched_queue_size 64 --gpgpu_dram_return_queue_size 192 - -# for HBM, 32 channles, each (128 bits) 16 bytes width --gpgpu_n_mem_per_ctrlr 1 --gpgpu_dram_buswidth 16 --gpgpu_dram_burst_length 2 --dram_data_command_freq_ratio 2 # HBM is DDR --gpgpu_mem_address_mask 1 --gpgpu_mem_addr_mapping dramid@8;00000000.00000000.00000000.00000000.0000RRRR.RRRRRRRR.RBBBBCCC.CCCSSSSS - -# HBM timing are adopted from hynix JESD235 standered and nVidia HPCA 2017 paper (http://www.cs.utah.edu/~nil/pubs/hpca17.pdf) -# Timing for 1 GHZ -# tRRDl and tWTR are missing, need to be added -#-gpgpu_dram_timing_opt "nbk=16:CCD=1:RRD=4:RCD=14:RAS=33:RP=14:RC=47: -# CL=14:WL=2:CDLR=3:WR=12:nbkgrp=4:CCDL=2:RTPL=4" - -# Timing for 715 MHZ, Tesla Pascal P100 HBM runs at 715 MHZ --gpgpu_dram_timing_opt "nbk=16:CCD=1:RRD=3:RCD=10:RAS=24:RP=10:RC=34: - CL=10:WL=2:CDLR=3:WR=9:nbkgrp=4:CCDL=2:RTPL=3" - -# HBM has dual bus interface, in which it can issue two col and row commands at a time --dual_bus_interface 1 -# select lower bits for bnkgrp to increase bnkgrp parallelism --dram_bnk_indexing_policy 0 --dram_bnkgrp_indexing_policy 1 - -#-Seperate_Write_Queue_Enable 1 -#-Write_Queue_Size 64:56:32 - -# Pascal has two schedulers per core --gpgpu_num_sched_per_core 2 -# Two Level Scheduler with active and pending pools -#-gpgpu_scheduler two_level_active:6:0:1 -# Loose round robbin scheduler -#-gpgpu_scheduler lrr -# Greedy then oldest scheduler --gpgpu_scheduler gto - -# stat collection --gpgpu_memlatency_stat 14 --gpgpu_runtime_stat 500 --enable_ptx_file_line_stats 1 --visualizer_enabled 0 - -# power model configs, disable it untill we create a real energy model for Pascal 100 --power_simulation_enabled 0 --gpuwattch_xml_file gpuwattch_gtx480.xml - -# tracing functionality -#-trace_enabled 1 -#-trace_components WARP_SCHEDULER,SCOREBOARD -#-trace_sampling_core 0 - diff --git a/configs/4.x-cfgs/SM6_P100_64SMs/config_fermi_islip.icnt b/configs/4.x-cfgs/SM6_P100_64SMs/config_fermi_islip.icnt deleted file mode 100644 index 81153b0..0000000 --- a/configs/4.x-cfgs/SM6_P100_64SMs/config_fermi_islip.icnt +++ /dev/null @@ -1,73 +0,0 @@ -//21*1 fly with 32 flits per packet under gpgpusim injection mode -use_map = 0; -flit_size = 40; - -// currently we do not use this, see subnets below -network_count = 2; - -// Topology -topology = fly; -k = 64; -n = 1; - -// Routing - -routing_function = dest_tag; - -// Flow control - -num_vcs = 1; -vc_buf_size = 128; -input_buffer_size = 256; -ejection_buffer_size = 128; -boundary_buffer_size = 128; - -wait_for_tail_credit = 0; - -// Router architecture - -vc_allocator = islip; //separable_input_first; -sw_allocator = islip; //separable_input_first; -alloc_iters = 1; - -credit_delay = 0; -routing_delay = 0; -vc_alloc_delay = 1; -sw_alloc_delay = 1; - -input_speedup = 2; -output_speedup = 1; -internal_speedup = 1.0; - -// Traffic, GPGPU-Sim does not use this - -traffic = uniform; -packet_size ={{1,2,3,4},{10,20}}; -packet_size_rate={{1,1,1,1},{2,1}}; - -// Simulation - Don't change - -sim_type = gpgpusim; -//sim_type = latency; -injection_rate = 0.1; - -subnets = 2; - -// Always use read and write no matter following line -//use_read_write = 1; - - -read_request_subnet = 0; -read_reply_subnet = 1; -write_request_subnet = 0; -write_reply_subnet = 1; - -read_request_begin_vc = 0; -read_request_end_vc = 0; -write_request_begin_vc = 0; -write_request_end_vc = 0; -read_reply_begin_vc = 0; -read_reply_end_vc = 0; -write_reply_begin_vc = 0; -write_reply_end_vc = 0; - diff --git a/configs/4.x-cfgs/SM6_P100_64SMs/gpgpusim.config b/configs/4.x-cfgs/SM6_P100_64SMs/gpgpusim.config deleted file mode 100644 index edcd919..0000000 --- a/configs/4.x-cfgs/SM6_P100_64SMs/gpgpusim.config +++ /dev/null @@ -1,174 +0,0 @@ -# functional simulator specification --gpgpu_ptx_instruction_classification 0 --gpgpu_ptx_sim_mode 0 --gpgpu_ptx_force_max_capability 60 - -# SASS execution (only supported with CUDA >= 4.0) --gpgpu_ptx_convert_to_ptxplus 0 --gpgpu_ptx_save_converted_ptxplus 0 - -# high level architecture configuration --gpgpu_n_clusters 32 --gpgpu_n_cores_per_cluster 2 --gpgpu_n_mem 32 --gpgpu_n_sub_partition_per_mchannel 1 - -# Pscal clock domains -#-gpgpu_clock_domains ::: -# Pascal NVIDIA GP100 clock domains are adopted from -# https://en.wikipedia.org/wiki/Nvidia_Tesla --gpgpu_clock_domains 1480.0:1480.0:1480.0:715.0 - -# shader core pipeline config --gpgpu_shader_registers 65536 - -# This implies a maximum of 64 warps/SM --gpgpu_shader_core_pipeline 2048:32 --gpgpu_shader_cta 32 --gpgpu_simd_model 1 - -# Pipeline widths and number of FUs -# ID_OC_SP,ID_OC_DP,ID_OC_SFU,ID_OC_MEM,OC_EX_SP,OC_EX_DP,OC_EX_SFU,OC_EX_MEM,EX_WB -## Pascal GP100 has 2 SP SIMD units, 2 SFU units, 2 DP units per core -## we need to scale the number of pipeline registers to be equal to the number of SP units --gpgpu_pipeline_widths 2,2,2,1,2,2,2,1,6 --gpgpu_num_sp_units 2 --gpgpu_num_sfu_units 2 --gpgpu_num_dp_units 2 - -# Instruction latencies and initiation intervals -# "ADD,MAX,MUL,MAD,DIV" -# All Div operations are executed on SFU unit -# Throughput (initiation latency) are adopted from CUDA SDK document V8, section 5.4.1, Table 2 --ptx_opcode_latency_int 4,13,4,5,145 --ptx_opcode_initiation_int 1,1,1,1,4 --ptx_opcode_latency_fp 4,13,4,5,39 --ptx_opcode_initiation_fp 1,2,1,1,4 --ptx_opcode_latency_dp 8,19,8,8,330 --ptx_opcode_initiation_dp 2,2,2,2,130 --ptx_opcode_latency_sfu 8 --ptx_opcode_initiation_sfu 4 - - -# ::,::::,::,:** -# ** Optional parameter - Required when mshr_type==Texture Fifo -# Note: Hashing set index function (H) only applies to a set size of 32 or 64. -# Pascal GP100 has 64KB Shared memory --gpgpu_cache:dl1 S:64:128:6,L:L:f:N:H,A:256:8,16:0,32 --gpgpu_cache:dl1PrefL1 S:64:128:6,L:L:f:N:H,A:256:8,16:0,32 --gpgpu_cache:dl1PrefShared S:64:128:6,L:L:f:N:H,A:256:8,16:0,32 --gpgpu_shmem_size 65536 --gpgpu_shmem_size_PrefL1 65536 --gpgpu_shmem_size_PrefShared 65536 --gmem_skip_L1D 0 --icnt_flit_size 40 --gpgpu_n_cluster_ejection_buffer_size 32 - -# 32 sets, each 128 bytes 16-way for each memory sub partition (128 KB per memory sub partition). This gives 4MB L2 cache --gpgpu_cache:dl2 S:64:128:16,L:B:m:L:L,A:256:4,32:0,32 --gpgpu_cache:dl2_texture_only 0 --gpgpu_dram_partition_queues 64:64:64:64 --perf_sim_memcpy 0 --memory_partition_indexing 2 - -# 4 KB Inst. --gpgpu_cache:il1 N:8:128:4,L:R:f:N:L,S:2:48,4 -# 48 KB Tex --gpgpu_tex_cache:l1 N:16:128:24,L:R:m:N:L,F:128:4,128:2 -# 12 KB Const --gpgpu_const_cache:l1 N:128:64:2,L:R:f:N:L,S:2:64,4 - -# enable operand collector --gpgpu_operand_collector_num_units_sp 12 --gpgpu_operand_collector_num_units_sfu 6 --gpgpu_operand_collector_num_units_mem 8 --gpgpu_operand_collector_num_units_dp 6 --gpgpu_operand_collector_num_in_ports_sp 4 --gpgpu_operand_collector_num_out_ports_sp 4 --gpgpu_operand_collector_num_in_ports_sfu 1 --gpgpu_operand_collector_num_out_ports_sfu 1 --gpgpu_operand_collector_num_in_ports_mem 1 --gpgpu_operand_collector_num_out_ports_mem 1 --gpgpu_operand_collector_num_in_ports_dp 1 --gpgpu_operand_collector_num_out_ports_dp 1 --gpgpu_num_reg_banks 32 - -# shared memory bankconflict detection --gpgpu_shmem_num_banks 32 --gpgpu_shmem_limited_broadcast 0 --gpgpu_shmem_warp_parts 1 --gpgpu_coalesce_arch 60 - -## In Pascal, a warp scheduler can issue 2 insts per cycle using 2 diff execution units --gpgpu_max_insn_issue_per_warp 2 --gpgpu_dual_issue_diff_exec_units 1 - -# interconnection --network_mode 1 --inter_config_file config_fermi_islip.icnt - -# memory partition latency config --rop_latency 120 --dram_latency 100 - -# dram model config --gpgpu_dram_scheduler 1 -# The DRAM return queue and the scheduler queue together should provide buffer -# to sustain the memory level parallelism to tolerate DRAM latency -# To allow 100% DRAM utility, there should at least be enough buffer to sustain -# the minimum DRAM latency (100 core cycles). I.e. -# Total buffer space required = 100 x 924MHz / 700MHz = 132 --gpgpu_frfcfs_dram_sched_queue_size 64 --gpgpu_dram_return_queue_size 192 - -# for HBM, 32 channles, each (128 bits) 16 bytes width --gpgpu_n_mem_per_ctrlr 1 --gpgpu_dram_buswidth 16 --gpgpu_dram_burst_length 2 --dram_data_command_freq_ratio 2 # HBM is DDR --gpgpu_mem_address_mask 1 --gpgpu_mem_addr_mapping dramid@8;00000000.00000000.00000000.00000000.0000RRRR.RRRRRRRR.RBBBBCCC.CCCSSSSS - -# HBM timing are adopted from hynix JESD235 standered and nVidia HPCA 2017 paper (http://www.cs.utah.edu/~nil/pubs/hpca17.pdf) -# Timing for 1 GHZ -# tRRDl and tWTR are missing, need to be added -#-gpgpu_dram_timing_opt "nbk=16:CCD=1:RRD=4:RCD=14:RAS=33:RP=14:RC=47: -# CL=14:WL=2:CDLR=3:WR=12:nbkgrp=4:CCDL=2:RTPL=4" - -# Timing for 715 MHZ, Tesla Pascal P100 HBM runs at 715 MHZ --gpgpu_dram_timing_opt "nbk=16:CCD=1:RRD=3:RCD=10:RAS=24:RP=10:RC=34: - CL=10:WL=2:CDLR=3:WR=9:nbkgrp=4:CCDL=2:RTPL=3" - -# HBM has dual bus interface, in which it can issue two col and row commands at a time --dual_bus_interface 1 -# select lower bits for bnkgrp to increase bnkgrp parallelism --dram_bnk_indexing_policy 0 --dram_bnkgrp_indexing_policy 1 - -#-Seperate_Write_Queue_Enable 1 -#-Write_Queue_Size 64:56:32 - -# Pascal has two schedulers per core --gpgpu_num_sched_per_core 2 -# Two Level Scheduler with active and pending pools -#-gpgpu_scheduler two_level_active:6:0:1 -# Loose round robbin scheduler -#-gpgpu_scheduler lrr -# Greedy then oldest scheduler --gpgpu_scheduler gto - -# stat collection --gpgpu_memlatency_stat 14 --gpgpu_runtime_stat 500 --enable_ptx_file_line_stats 1 --visualizer_enabled 0 - -# power model configs, disable it untill we create a real energy model for Pascal 100 --power_simulation_enabled 0 --gpuwattch_xml_file gpuwattch_gtx480.xml - -# tracing functionality -#-trace_enabled 1 -#-trace_components WARP_SCHEDULER,SCOREBOARD -#-trace_sampling_core 0 - diff --git a/configs/4.x-cfgs/SM6_TITANX/gpgpusim.config b/configs/4.x-cfgs/SM6_TITANX/gpgpusim.config index 7368882..9ea7202 100644 --- a/configs/4.x-cfgs/SM6_TITANX/gpgpusim.config +++ b/configs/4.x-cfgs/SM6_TITANX/gpgpusim.config @@ -56,24 +56,29 @@ -ptx_opcode_initiation_sfu 4 -ptx_opcode_latency_sfu 8 + +# latencies and cache configs are adopted from: +# https://arxiv.org/pdf/1804.06826.pdf # ::,::::,::,:** # ** Optional parameter - Required when mshr_type==Texture Fifo # Note: Hashing set index function (H) only applies to a set size of 32 or 64. -# Pascal GP102 has 96KB Shared memory -# Pascal GP102 has 24KB L1 cache -# The defulat is to disable the L1 cache, unless cache modifieres is used --gpgpu_cache:dl1 S:32:128:6,L:L:f:N:H,A:256:8,16:0,32 --gpgpu_cache:dl1PrefL1 S:32:128:6,L:L:f:N:H,A:256:8,16:0,32 --gpgpu_cache:dl1PrefShared S:32:128:6,L:L:f:N:H,A:256:8,16:0,32 +# Pascal GP102 has 96KB Shared memory divided over 2 cores, each has 48KB +# Pascal GP102 has 2 banks L1 cache, where each is 24KB L1 cache +# The defulat is to disable the L1 cache, unless cache modifieres are used +-gpgpu_cache:dl1 S:48:128:4,L:L:s:N:H,A:256:8,16:0,32 +-gpgpu_cache:dl1PrefL1 S:48:128:4,L:L:s:N:H,A:256:8,16:0,32 +-gpgpu_cache:dl1PrefShared S:48:128:4,L:L:s:N:H,A:256:8,16:0,32 -gpgpu_shmem_size 49152 -gpgpu_shmem_size_PrefL1 49152 -gpgpu_shmem_size_PrefShared 49152 -gmem_skip_L1D 1 -icnt_flit_size 40 -gpgpu_n_cluster_ejection_buffer_size 32 +-l1_latency 82 +-smem_latency 24 # 64 sets, each 128 bytes 16-way for each memory sub partition (128 KB per memory sub partition). This gives 3MB L2 cache --gpgpu_cache:dl2 S:64:128:16,L:B:m:L:L,A:128:4,16:0,32 +-gpgpu_cache:dl2 S:64:128:16,L:B:m:L:L,A:256:64,16:0,32 -gpgpu_cache:dl2_texture_only 0 -gpgpu_dram_partition_queues 32:32:32:32 -perf_sim_memcpy 0 @@ -81,8 +86,7 @@ # 4 KB Inst. -gpgpu_cache:il1 N:8:128:4,L:R:f:N:L,S:2:48,4 # 48 KB Tex -# this is unused --gpgpu_tex_cache:l1 N:16:128:24,L:R:m:N:L,F:128:4,128:2 +-gpgpu_tex_cache:l1 N:16:128:24,L:R:m:N:L,T:128:4,128:2 # 12 KB Const -gpgpu_const_cache:l1 N:128:64:2,L:R:f:N:L,S:2:64,4 @@ -99,7 +103,6 @@ -gpgpu_operand_collector_num_out_ports_mem 1 -gpgpu_operand_collector_num_in_ports_dp 1 -gpgpu_operand_collector_num_out_ports_dp 1 -# gpgpu_num_reg_banks should be increased to 32 -gpgpu_num_reg_banks 32 # shared memory bankconflict detection @@ -118,7 +121,7 @@ -inter_config_file config_fermi_islip.icnt # memory partition latency config --rop_latency 100 +-rop_latency 120 -dram_latency 100 # dram model config @@ -128,7 +131,7 @@ # To allow 100% DRAM utility, there should at least be enough buffer to sustain # the minimum DRAM latency (100 core cycles). I.e. # Total buffer space required = 100 x 924MHz / 700MHz = 132 --gpgpu_frfcfs_dram_sched_queue_size 16 +-gpgpu_frfcfs_dram_sched_queue_size 64 -gpgpu_dram_return_queue_size 240 # for NVIDIA TITAN X, bus width is 384bits (12 DRAM chips x 32 bits) diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index 1b764e2..a70b077 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -392,6 +392,7 @@ protected: #define LOCAL_MEM_SIZE_MAX (8*1024) #define MAX_STREAMING_MULTIPROCESSORS 64 #define MAX_THREAD_PER_SM 2048 +#define MAX_WARP_PER_SM 64 #define TOTAL_LOCAL_MEM_PER_SM (MAX_THREAD_PER_SM*LOCAL_MEM_SIZE_MAX) #define TOTAL_SHARED_MEM (MAX_STREAMING_MULTIPROCESSORS*SHARED_MEM_SIZE_MAX) #define TOTAL_LOCAL_MEM (MAX_STREAMING_MULTIPROCESSORS*MAX_THREAD_PER_SM*LOCAL_MEM_SIZE_MAX) diff --git a/src/gpgpu-sim/gpu-cache.cc b/src/gpgpu-sim/gpu-cache.cc index f181f20..a11853a 100644 --- a/src/gpgpu-sim/gpu-cache.cc +++ b/src/gpgpu-sim/gpu-cache.cc @@ -71,6 +71,7 @@ unsigned l1d_cache_config::set_index(new_addr_type addr) const{ switch(m_set_index_function){ case FERMI_HASH_SET_FUNCTION: + case BITWISE_XORING_FUNCTION: /* * Set Indexing function from "A Detailed GPU Cache Model Based on Reuse Distance Theory" * Cedric Nugteren et al. @@ -1581,7 +1582,7 @@ enum cache_request_status tex_cache::access( new_addr_type addr, mem_fetch *mf, if ( status == MISS ) { // we need to send a memory request... unsigned rob_index = m_rob.push( rob_entry(cache_index, mf, block_addr) ); - m_extra_mf_fields[mf] = extra_mf_fields(rob_index); + m_extra_mf_fields[mf] = extra_mf_fields(rob_index, m_config); mf->set_data_size(m_config.get_line_sz()); m_tags.fill(cache_index,time,mf); // mark block as valid m_request_fifo.push(mf); @@ -1636,6 +1637,23 @@ void tex_cache::cycle(){ /// Place returning cache block into reorder buffer void tex_cache::fill( mem_fetch *mf, unsigned time ) { + if(m_config.m_mshr_type == SECTOR_TEX_FIFO) { + assert(mf->get_original_mf()); + extra_mf_fields_lookup::iterator e = m_extra_mf_fields.find(mf->get_original_mf()); + assert( e != m_extra_mf_fields.end() ); + e->second.pending_read--; + + if(e->second.pending_read > 0) { + //wait for the other requests to come back + delete mf; + return; + } else { + mem_fetch *temp = mf; + mf = mf->get_original_mf(); + delete temp; + } + } + extra_mf_fields_lookup::iterator e = m_extra_mf_fields.find(mf); assert( e != m_extra_mf_fields.end() ); assert( e->second.m_valid ); diff --git a/src/gpgpu-sim/gpu-cache.h b/src/gpgpu-sim/gpu-cache.h index dee43f2..4ed382c 100644 --- a/src/gpgpu-sim/gpu-cache.h +++ b/src/gpgpu-sim/gpu-cache.h @@ -455,7 +455,8 @@ enum write_policy_t { enum allocation_policy_t { ON_MISS, - ON_FILL + ON_FILL, + STREAMING }; @@ -467,8 +468,9 @@ enum write_allocate_policy_t { }; enum mshr_config_t { - TEX_FIFO, + TEX_FIFO, // Tex cache ASSOC, // normal cache + SECTOR_TEX_FIFO, //Tex cache sends requests to high-level sector cache SECTOR_ASSOC // normal cache sends requests to high-level sector cache }; @@ -485,6 +487,12 @@ enum cache_type{ SECTOR }; +#define MAX_WARP_PER_SHADER 64 +#define INCT_TOTAL_BUFFER 64 +#define L2_TOTAL 64 +#define MAX_WARP_PER_SHADER 64 +#define MAX_WARP_PER_SHADER 64 + class cache_config { public: cache_config() @@ -544,10 +552,27 @@ public: switch (ap) { case 'm': m_alloc_policy = ON_MISS; break; case 'f': m_alloc_policy = ON_FILL; break; + case 's': m_alloc_policy = STREAMING; break; default: exit_parse_error(); } + if(m_alloc_policy == STREAMING) { + //For streaming cache, we set the alloc policy to be on-fill to remove all line_alloc_fail stalls + //we set the MSHRs to be equal to the cache line. This is possible by moving TAG to be shared between cache line and MSHR enrty (i.e. for each cache line, there is an MSHR rntey associated with it) + // This is the easiest think we can think about to model (mimics) L1 streaming cache in Pascal and Volta + //Based on our microbenchmakrs, MSHRs entries have been increasing substantially in Pascal and Volta + //For more information about streaming cache, see: + // http://on-demand.gputechconf.com/gtc/2017/presentation/s7798-luke-durant-inside-volta.pdf + // https://ieeexplore.ieee.org/document/8344474/ + + m_alloc_policy = ON_FILL; + m_mshr_entries = m_nset*m_assoc; + if(m_cache_type == SECTOR) + m_mshr_entries *= SECTOR_CHUNCK_SIZE; + m_mshr_max_merge = MAX_WARP_PER_SM; + } switch (mshr_type) { case 'F': m_mshr_type = TEX_FIFO; assert(ntok==14); break; + case 'T': m_mshr_type = SECTOR_TEX_FIFO; assert(ntok==14); break; case 'A': m_mshr_type = ASSOC; break; case 'S' : m_mshr_type = SECTOR_ASSOC; break; default: exit_parse_error(); @@ -722,6 +747,7 @@ class l1d_cache_config : public cache_config{ public: l1d_cache_config() : cache_config(){} virtual unsigned set_index(new_addr_type addr) const; + unsigned l1_latency; }; class l2_cache_config : public cache_config { @@ -1442,7 +1468,7 @@ public: m_result_fifo(config.m_result_fifo_entries) { m_name = name; - assert(config.m_mshr_type == TEX_FIFO); + assert(config.m_mshr_type == TEX_FIFO || config.m_mshr_type == SECTOR_TEX_FIFO ); assert(config.m_write_policy == READ_ONLY); assert(config.m_alloc_policy == ON_MISS); m_memport=memport; @@ -1595,13 +1621,15 @@ private: struct extra_mf_fields { extra_mf_fields() { m_valid = false;} - extra_mf_fields( unsigned i ) + extra_mf_fields( unsigned i, const cache_config &m_config ) { m_valid = true; m_rob_index = i; + pending_read = m_config.m_mshr_type == SECTOR_TEX_FIFO? m_config.m_line_sz/SECTOR_SIZE : 0; } bool m_valid; unsigned m_rob_index; + unsigned pending_read; }; cache_stats m_stats; diff --git a/src/gpgpu-sim/gpu-sim.cc b/src/gpgpu-sim/gpu-sim.cc index ea2dfba..08d4525 100644 --- a/src/gpgpu-sim/gpu-sim.cc +++ b/src/gpgpu-sim/gpu-sim.cc @@ -250,6 +250,12 @@ void shader_core_config::reg_options(class OptionParser * opp) "per-shader L1 data cache config " " {::,:::,::, | none}", "none" ); + option_parser_register(opp, "-l1_latency", OPT_UINT32, &m_L1D_config.l1_latency, + "L1 Hit Latency", + "0"); + option_parser_register(opp, "-smem_latency", OPT_UINT32, &smem_latency, + "smem Latency", + "3"); option_parser_register(opp, "-gpgpu_cache:dl1PrefL1", OPT_CSTR, &m_L1D_config.m_config_stringPrefL1, "per-shader L1 data cache config " " {::,:::,::, | none}", diff --git a/src/gpgpu-sim/l2cache.cc b/src/gpgpu-sim/l2cache.cc index f42610f..25da107 100644 --- a/src/gpgpu-sim/l2cache.cc +++ b/src/gpgpu-sim/l2cache.cc @@ -609,7 +609,7 @@ std::vector memory_sub_partition::breakdown_request_to_sector_reques } else { printf("Invalid sector received, address = 0x%06x, sector mask = %s, data size = %d", - mf->get_addr(), mf->get_access_sector_mask(), mf->get_data_size(), mf->get_data_size()); + mf->get_addr(), mf->get_access_sector_mask(), mf->get_data_size()); assert(0 && "Undefined sector mask is received"); } @@ -640,7 +640,11 @@ std::vector memory_sub_partition::breakdown_request_to_sector_reques result.push_back(n_mf); byte_sector_mask <<= SECTOR_SIZE; } - } else assert(0 && "Undefined data size is received"); + } else { + printf("Invalid sector received, address = 0x%06x, sector mask = %d, byte mask = , data size = %d", + mf->get_addr(), mf->get_access_sector_mask().count(), mf->get_data_size()); + assert(0 && "Undefined data size is received"); + } return result; } diff --git a/src/gpgpu-sim/shader.cc b/src/gpgpu-sim/shader.cc index b59e5d2..51689e3 100644 --- a/src/gpgpu-sim/shader.cc +++ b/src/gpgpu-sim/shader.cc @@ -1488,6 +1488,111 @@ mem_stage_stall_type ldst_unit::process_memory_access_queue( cache_t *cache, war return process_cache_access( cache, mf->get_addr(), inst, events, mf, status ); } +mem_stage_stall_type ldst_unit::process_memory_access_queue_l1cache( l1_cache *cache, warp_inst_t &inst ) +{ + mem_stage_stall_type result = NO_RC_FAIL; + if( inst.accessq_empty() ) + return result; + + mem_fetch *mf = m_mf_allocator->alloc(inst,inst.accessq_back()); + + if(m_config->m_L1D_config.l1_latency > 0) + { + if((l1_latency_queue[m_config->m_L1D_config.l1_latency-1]) == NULL) + { + l1_latency_queue[m_config->m_L1D_config.l1_latency-1] = mf; + + if( mf->get_inst().is_store() ) { + unsigned inc_ack = (m_config->m_L1D_config.get_mshr_type() == SECTOR_ASSOC)? + (mf->get_data_size()/SECTOR_SIZE) : 1; + + for(unsigned i=0; i< inc_ack; ++i) + m_core->inc_store_req( inst.warp_id() ); + } + + inst.accessq_pop_back(); + } + else + { + result = BK_CONF; + delete mf; + } + if( !inst.accessq_empty() && result !=BK_CONF) + result = COAL_STALL; + return result; + } + else + { + std::list events; + enum cache_request_status status = cache->access(mf->get_addr(),mf,gpu_sim_cycle+gpu_tot_sim_cycle,events); + return process_cache_access( cache, mf->get_addr(), inst, events, mf, status ); + } +} + +void ldst_unit::L1_latency_queue_cycle() +{ + //std::deque< std::pair >::iterator it = m_latency_queue.begin(); + if((l1_latency_queue[0]) != NULL) + { + mem_fetch* mf_next = l1_latency_queue[0]; + std::list events; + enum cache_request_status status = m_L1D->access(mf_next->get_addr(),mf_next,gpu_sim_cycle+gpu_tot_sim_cycle,events); + + bool write_sent = was_write_sent(events); + bool read_sent = was_read_sent(events); + + if ( status == HIT ) { + assert( !read_sent ); + l1_latency_queue[0] = NULL; + if ( mf_next->get_inst().is_load() ) { + for ( unsigned r=0; r < 4; r++) + if (mf_next->get_inst().out[r] > 0) + { + assert(m_pending_writes[mf_next->get_inst().warp_id()][mf_next->get_inst().out[r]]>0); + unsigned still_pending = --m_pending_writes[mf_next->get_inst().warp_id()][mf_next->get_inst().out[r]]; + if(!still_pending) + { + m_pending_writes[mf_next->get_inst().warp_id()].erase(mf_next->get_inst().out[r]); + m_scoreboard->releaseRegister(mf_next->get_inst().warp_id(),mf_next->get_inst().out[r]); + m_core->warp_inst_complete(mf_next->get_inst()); + } + } + } + + //For write hit in WB policy + if(mf_next->get_inst().is_store() && !write_sent) + { + unsigned dec_ack = (m_config->m_L1D_config.get_mshr_type() == SECTOR_ASSOC)? + (mf_next->get_data_size()/SECTOR_SIZE) : 1; + + mf_next->set_reply(); + + for(unsigned i=0; i< dec_ack; ++i) + m_core->store_ack(mf_next); + } + + if( !write_sent ) + delete mf_next; + + } else if ( status == RESERVATION_FAIL ) { + assert( !read_sent ); + assert( !write_sent ); + } else { + assert( status == MISS || status == HIT_RESERVED ); + l1_latency_queue[0] = NULL; + } + } + + for( unsigned stage = 0; stagem_L1D_config.l1_latency-1; ++stage) + if( l1_latency_queue[stage] == NULL) { + l1_latency_queue[stage] = l1_latency_queue[stage+1] ; + l1_latency_queue[stage+1] = NULL; + } + +} + + + bool ldst_unit::constant_cycle( warp_inst_t &inst, mem_stage_stall_type &rc_fail, mem_stage_access_type &fail_type) { if( inst.empty() || ((inst.space.get_type() != const_space) && (inst.space.get_type() != param_space_kernel)) ) @@ -1561,7 +1666,7 @@ bool ldst_unit::memory_cycle( warp_inst_t &inst, mem_stage_stall_type &stall_rea } } else { assert( CACHE_UNDEFINED != inst.cache_op ); - stall_cond = process_memory_access_queue(m_L1D,inst); + stall_cond = process_memory_access_queue_l1cache(m_L1D,inst); } if( !inst.accessq_empty() && stall_cond == NO_RC_FAIL) stall_cond = COAL_STALL; @@ -1771,8 +1876,9 @@ ldst_unit::ldst_unit( mem_fetch_interface *icnt, const memory_config *mem_config, shader_core_stats *stats, unsigned sid, - unsigned tpc ) : pipelined_simd_unit(NULL,config,3,core), m_next_wb(config) + unsigned tpc ) : pipelined_simd_unit(NULL,config,config->smem_latency,core), m_next_wb(config) { + assert(config->smem_latency > 1); init( icnt, mf_allocator, core, @@ -1793,6 +1899,12 @@ ldst_unit::ldst_unit( mem_fetch_interface *icnt, m_icnt, m_mf_allocator, IN_L1D_MISS_QUEUE ); + + if(m_config->m_L1D_config.l1_latency > 0) + { + for(int i=0; im_L1D_config.l1_latency; i++ ) + l1_latency_queue.push_back((mem_fetch*)NULL); + } } } @@ -2019,7 +2131,11 @@ void ldst_unit::cycle() m_L1T->cycle(); m_L1C->cycle(); - if( m_L1D ) m_L1D->cycle(); + if( m_L1D ) { + m_L1D->cycle(); + if(m_config->m_L1D_config.l1_latency > 0) + L1_latency_queue_cycle(); + } warp_inst_t &pipe_reg = *m_dispatch_reg; enum mem_stage_stall_type rc_fail = NO_RC_FAIL; @@ -2042,9 +2158,9 @@ void ldst_unit::cycle() unsigned warp_id = pipe_reg.warp_id(); if( pipe_reg.is_load() ) { if( pipe_reg.space.get_type() == shared_space ) { - if( m_pipeline_reg[2]->empty() ) { + if( m_pipeline_reg[m_config->smem_latency-1]->empty() ) { // new shared memory request - move_warp(m_pipeline_reg[2],m_dispatch_reg); + move_warp(m_pipeline_reg[m_config->smem_latency-1],m_dispatch_reg); m_dispatch_reg->clear(); } } else { diff --git a/src/gpgpu-sim/shader.h b/src/gpgpu-sim/shader.h index cc441b3..e07096e 100644 --- a/src/gpgpu-sim/shader.h +++ b/src/gpgpu-sim/shader.h @@ -1220,6 +1220,7 @@ protected: mem_fetch *mf, enum cache_request_status status ); mem_stage_stall_type process_memory_access_queue( cache_t *cache, warp_inst_t &inst ); + mem_stage_stall_type process_memory_access_queue_l1cache( l1_cache *cache, warp_inst_t &inst ); const memory_config *m_memory_config; class mem_fetch_interface *m_icnt; @@ -1248,6 +1249,9 @@ protected: // for debugging unsigned long long m_last_inst_gpu_sim_cycle; unsigned long long m_last_inst_gpu_tot_sim_cycle; + + std::deque l1_latency_queue; + void L1_latency_queue_cycle(); }; enum pipeline_stage_name_t { @@ -1399,6 +1403,8 @@ struct shader_core_config : public core_config int simt_core_sim_order; + unsigned smem_latency; + unsigned mem2device(unsigned memid) const { return memid + n_simt_clusters; } //Jin: concurrent kernel on sm -- cgit v1.3 From 7a77d951e6a900d61436df12826bb677aeaee6e6 Mon Sep 17 00:00:00 2001 From: aamir Date: Sun, 9 Sep 2018 15:10:06 -0700 Subject: minor changes for generating mem transaction in timing model. NOTE NOT COMPLETED --- cuda-kernels/gpgpusim.config | 2 +- cutlass-example/gpgpusim.config | 2 +- src/abstract_hardware_model.cc | 2 +- src/abstract_hardware_model.h | 8 +++-- src/cuda-sim/cuda-sim.cc | 65 ++++++++++++++++++++++++----------------- src/cuda-sim/instructions.cc | 64 +++++++++++++++++++++++++++++----------- src/gpgpu-sim/shader.cc | 2 +- src/gpgpu-sim/shader.h | 8 +++++ 8 files changed, 104 insertions(+), 49 deletions(-) (limited to 'src/abstract_hardware_model.h') diff --git a/cuda-kernels/gpgpusim.config b/cuda-kernels/gpgpusim.config index 2510d21..3daa539 100755 --- a/cuda-kernels/gpgpusim.config +++ b/cuda-kernels/gpgpusim.config @@ -33,7 +33,7 @@ # ID_OC_SP,ID_OC_SFU,ID_OC_MEM,OC_EX_SP,OC_EX_SFU,OC_EX_MEM,EX_WB ## Pascal GP102 has 4 SP SIMD units and 1 SFU unit ## we need to scale the number of pipeline registers to be equal to the number of SP units --gpgpu_pipeline_widths 4,1,1,1,4,1,1,1,6 +-gpgpu_pipeline_widths 4,1,1,1,1,4,1,1,1,1,6 -gpgpu_num_sp_units 4 -gpgpu_num_sfu_units 1 # Instruction latencies and initiation intervals diff --git a/cutlass-example/gpgpusim.config b/cutlass-example/gpgpusim.config index 2510d21..3daa539 100644 --- a/cutlass-example/gpgpusim.config +++ b/cutlass-example/gpgpusim.config @@ -33,7 +33,7 @@ # ID_OC_SP,ID_OC_SFU,ID_OC_MEM,OC_EX_SP,OC_EX_SFU,OC_EX_MEM,EX_WB ## Pascal GP102 has 4 SP SIMD units and 1 SFU unit ## we need to scale the number of pipeline registers to be equal to the number of SP units --gpgpu_pipeline_widths 4,1,1,1,4,1,1,1,6 +-gpgpu_pipeline_widths 4,1,1,1,1,4,1,1,1,1,6 -gpgpu_num_sp_units 4 -gpgpu_num_sfu_units 1 # Instruction latencies and initiation intervals diff --git a/src/abstract_hardware_model.cc b/src/abstract_hardware_model.cc index d668de7..b24a77e 100644 --- a/src/abstract_hardware_model.cc +++ b/src/abstract_hardware_model.cc @@ -184,7 +184,7 @@ void warp_inst_t::generate_mem_accesses() { if( empty() || op == MEMORY_BARRIER_OP || m_mem_accesses_created ) return; - if ( !((op == LOAD_OP) || (op == STORE_OP)) ) + if (!((op == LOAD_OP) || (op==TENSOR_CORE_LOAD_OP) || (op==VP_LOAD_OP) || (op == STORE_OP)||(op==TENSOR_CORE_STORE_OP)||(op==VP_STORE_OP))) return; if( m_warp_active_mask.count() == 0 ) return; // predicated off diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index 781509f..9c418fa 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -81,6 +81,10 @@ enum uarch_op_t { VP_CORE_OP, ALU_SFU_OP, LOAD_OP, + VP_LOAD_OP, + TENSOR_CORE_LOAD_OP, + TENSOR_CORE_STORE_OP, + VP_STORE_OP, STORE_OP, BRANCH_OP, BARRIER_OP, @@ -801,8 +805,8 @@ public: { fprintf(fp," [inst @ pc=0x%04x] ", pc ); } - bool is_load() const { return (op == LOAD_OP || memory_op == memory_load); } - bool is_store() const { return (op == STORE_OP || memory_op == memory_store); } + bool is_load() const { return (op == LOAD_OP ||op==TENSOR_CORE_LOAD_OP||op==VP_LOAD_OP || memory_op == memory_load); } + bool is_store() const { return (op == STORE_OP ||op==TENSOR_CORE_STORE_OP||op==VP_STORE_OP || memory_op == memory_store); } unsigned get_num_operands() const {return num_operands;} unsigned get_num_regs() const {return num_regs;} void set_num_regs(unsigned num) {num_regs=num;} diff --git a/src/cuda-sim/cuda-sim.cc b/src/cuda-sim/cuda-sim.cc index bcf64c4..8f684e2 100644 --- a/src/cuda-sim/cuda-sim.cc +++ b/src/cuda-sim/cuda-sim.cc @@ -648,12 +648,12 @@ void ptx_instruction::set_opcode_and_latency() if ( has_memory_write() ) op = STORE_OP; break; case LD_OP: op = LOAD_OP; break; - case MMA_LD_OP: op = LOAD_OP; break; - case VP_LD_OP: op = LOAD_OP; break; + case MMA_LD_OP: op = TENSOR_CORE_LOAD_OP; break; + case VP_LD_OP: op = VP_LOAD_OP; break; case LDU_OP: op = LOAD_OP; break; case ST_OP: op = STORE_OP; break; - case MMA_ST_OP: op = STORE_OP; break; - case VP_ST_OP: op = STORE_OP; break; + case MMA_ST_OP: op = TENSOR_CORE_STORE_OP; break; + case VP_ST_OP: op = VP_STORE_OP; break; case BRA_OP: op = BRANCH_OP; break; case BREAKADDR_OP: op = BRANCH_OP; break; case TEX_OP: op = LOAD_OP; mem_op=TEX; break; @@ -1334,6 +1334,7 @@ void ptx_thread_info::ptx_exec_inst( warp_inst_t &inst, unsigned lane_id) skip = !pred_lookup(pI->get_pred_mod(), pred_value.pred & 0x000F); } } + int inst_opcode=pI->get_opcode(); if( skip ) { inst.set_not_active(lane_id); @@ -1346,17 +1347,21 @@ void ptx_thread_info::ptx_exec_inst( warp_inst_t &inst, unsigned lane_id) pI = pJ; } - int inst_opcode=pI->get_opcode(); + if(((inst_opcode==MMA_OP||inst_opcode==MMA_LD_OP||inst_opcode==MMA_ST_OP||inst_opcode==VP_MMA_OP||inst_opcode==VP_LD_OP||inst_opcode==VP_ST_OP))){ + if(inst.active_count()!=MAX_WARP_SIZE) + while(1); + } if(((inst_opcode!=MMA_OP)&&(inst_opcode!=MMA_LD_OP)&&(inst_opcode!=MMA_ST_OP)&&(inst_opcode!=VP_LD_OP)&&(inst_opcode!=VP_ST_OP)&&(inst_opcode!=VP_MMA_OP))||((inst_opcode==MMA_OP||inst_opcode==MMA_LD_OP||inst_opcode==MMA_ST_OP||inst_opcode==VP_MMA_OP||inst_opcode==VP_LD_OP||inst_opcode==VP_ST_OP)&&(lane_id==0))){ - switch ( inst_opcode ) { -#define OP_DEF(OP,FUNC,STR,DST,CLASSIFICATION) case OP: FUNC(pI,this); op_classification = CLASSIFICATION; break; -#define OP_W_DEF(OP,FUNC,STR,DST,CLASSIFICATION) case OP: FUNC(pI,get_core(),inst); op_classification = CLASSIFICATION; break; -#include "opcodes.def" -#undef OP_DEF -#undef OP_W_DEF - default: printf( "Execution error: Invalid opcode (0x%x)\n", pI->get_opcode() ); break; - }} + switch ( inst_opcode ) { + #define OP_DEF(OP,FUNC,STR,DST,CLASSIFICATION) case OP: FUNC(pI,this); op_classification = CLASSIFICATION; break; + #define OP_W_DEF(OP,FUNC,STR,DST,CLASSIFICATION) case OP: FUNC(pI,get_core(),inst); op_classification = CLASSIFICATION; break; + #include "opcodes.def" + #undef OP_DEF + #undef OP_W_DEF + default: printf( "Execution error: Invalid opcode (0x%x)\n", pI->get_opcode() ); break; + } + } delete pJ; pI = pI_saved; @@ -1398,13 +1403,17 @@ void ptx_thread_info::ptx_exec_inst( warp_inst_t &inst, unsigned lane_id) _memory_op_t insn_memory_op = no_memory_op; unsigned insn_data_size = 0; if ( (pI->has_memory_read() || pI->has_memory_write()) ) { - insn_memaddr = last_eaddr(); - insn_space = last_space(); - unsigned to_type = pI->get_type(); - insn_data_size = datatype2size(to_type); - insn_memory_op = pI->has_memory_read() ? memory_load : memory_store; - } - + //if(!((inst_opcode==MMA_LD_OP||inst_opcode==MMA_ST_OP||inst_opcode==VP_LD_OP||inst_opcode==VP_ST_OP))) + //if(!((inst_opcode==MMA_LD_OP||inst_opcode==VP_LD_OP))) + //{ + insn_memaddr = last_eaddr(); + insn_space = last_space(); + unsigned to_type = pI->get_type(); + insn_data_size = datatype2size(to_type); + insn_memory_op = pI->has_memory_read() ? memory_load : memory_store; + //} + } + if ( pI->get_opcode() == BAR_OP && pI->barrier_op() == RED_OPTION) { inst.add_callback( lane_id, last_callback().function, last_callback().instruction, this,false /*not atomic*/); } @@ -1476,12 +1485,16 @@ void ptx_thread_info::ptx_exec_inst( warp_inst_t &inst, unsigned lane_id) // "Return values" if(!skip) { - inst.space = insn_space; - inst.set_addr(lane_id, insn_memaddr); - inst.data_size = insn_data_size; // simpleAtomicIntrinsics - assert( inst.memory_op == insn_memory_op ); - } - + //if(!((inst_opcode==MMA_LD_OP||inst_opcode==MMA_ST_OP||inst_opcode==VP_LD_OP||inst_opcode==VP_ST_OP))) + //if(!((inst_opcode==MMA_LD_OP||inst_opcode==VP_LD_OP))) + //{ + inst.space = insn_space; + inst.set_addr(lane_id, insn_memaddr); + inst.data_size = insn_data_size; // simpleAtomicIntrinsics + assert( inst.memory_op == insn_memory_op ); + //} + } + } catch ( int x ) { printf("GPGPU-Sim PTX: ERROR (%d) executing intruction (%s:%u)\n", x, pI->source_file(), pI->source_line() ); printf("GPGPU-Sim PTX: '%s'\n", pI->get_source() ); diff --git a/src/cuda-sim/instructions.cc b/src/cuda-sim/instructions.cc index 39b8ba5..77e8e71 100644 --- a/src/cuda-sim/instructions.cc +++ b/src/cuda-sim/instructions.cc @@ -3196,6 +3196,7 @@ void mma_st_impl( const ptx_instruction *pI, core_t *core, warp_inst_t inst ) unsigned wmma_type = pI->get_wmma_type(); unsigned wmma_layout = pI->get_wmma_layout(0); int stride; + _memory_op_t insn_memory_op = pI->has_memory_read() ? memory_load : memory_store; for (thrd=0; thrd < core->get_warp_size(); thrd++) { thread = core->get_thread_info()[tid+thrd]; odd=thrd%2; @@ -3224,6 +3225,7 @@ void mma_st_impl( const ptx_instruction *pI, core_t *core, warp_inst_t inst ) if(g_debug_instruction) printf("mma_st: thrd=%d,addr=%x, fp(size=%d), stride=%d\n",thrd,addr_reg.u32,size,src2_data.u32); addr_t new_addr = addr+thread_group_offset(thrd,wmma_type,wmma_layout,type,stride)*size/8; + addr_t push_addr; ptx_reg_t nw_v[8]; for(k=0;k<8;k++){ @@ -3235,7 +3237,10 @@ void mma_st_impl( const ptx_instruction *pI, core_t *core, warp_inst_t inst ) for(k=0;k<8;k++){ if(type==F32_TYPE){ - mem->write(new_addr+4*acc_float_offset(k,wmma_layout,stride),size/8,&v[k].s64,thread,pI); + //mem->write(new_addr+4*acc_float_offset(k,wmma_layout,stride),size/8,&v[k].s64,thread,pI); + push_addr=new_addr+4*acc_float_offset(k,wmma_layout,stride); + mem->write(push_addr,size/8,&v[k].s64,thread,pI); + if(g_debug_instruction){ printf("wmma:store:thread%d=%x,%x,%x,%x,%x,%x,%x,%x\n",thrd,v[0].s64,v[1].s64,v[2].s64,v[3].s64,v[4].s64,v[5].s64,v[6].s64,v[7].s64); float temp; @@ -3250,10 +3255,16 @@ void mma_st_impl( const ptx_instruction *pI, core_t *core, warp_inst_t inst ) } else if(type==F16_TYPE){ - if(wmma_layout==ROW) - mem->write(new_addr+k*2,size/8,&nw_v[k].s64,thread,pI); - else if(wmma_layout==COL) - mem->write(new_addr+k*2*stride,size/8,&nw_v[k].s64,thread,pI); + if(wmma_layout==ROW){ + //mem->write(new_addr+k*2,size/8,&nw_v[k].s64,thread,pI); + push_addr=new_addr+k*2; + mem->write(push_addr,size/8,&nw_v[k].s64,thread,pI); + } + else if(wmma_layout==COL){ + //mem->write(new_addr+k*2*stride,size/8,&nw_v[k].s64,thread,pI); + push_addr=new_addr+k*2*stride; + mem->write(push_addr,size/8,&nw_v[k].s64,thread,pI); + } if(g_debug_instruction) printf("wmma:store:thread%d=%x,%x,%x,%x,%x,%x,%x,%x\n",thrd,nw_v[0].s64,nw_v[1].s64,nw_v[2].s64,nw_v[3].s64,nw_v[4].s64,nw_v[5].s64,nw_v[6].s64,nw_v[7].s64); } @@ -3427,6 +3438,7 @@ void mma_ld_impl( const ptx_instruction *pI, core_t *core, warp_inst_t inst ) int tid = inst.warp_id_func()*core->get_warp_size(); int thrd,stride; ptx_thread_info *thread; + _memory_op_t insn_memory_op = pI->has_memory_read() ? memory_load : memory_store; for (thrd=0; thrd < core->get_warp_size(); thrd++){ thread = core->get_thread_info()[tid+thrd]; @@ -3452,13 +3464,18 @@ void mma_ld_impl( const ptx_instruction *pI, core_t *core, warp_inst_t inst ) printf("mma_ld: thrd=%d,addr=%x, fpsize=%d, stride=%d\n",thrd,src1_data.u32,size,src2_data.u32); addr_t new_addr = addr+thread_group_offset(thrd,wmma_type,wmma_layout,type,stride)*size/8; - + addr_t fetch_addr; if(wmma_type==LOAD_A){ for(i=0;i<16;i++){ - if(wmma_layout==ROW) - mem->read(new_addr+2*i,size/8,&data[i].s64); + if(wmma_layout==ROW){ + //mem->read(new_addr+2*i,size/8,&data[i].s64); + fetch_addr=new_addr+2*i; + mem->read(fetch_addr,size/8,&data[i].s64); + } else if(wmma_layout==COL){ - mem->read(new_addr+2*(i%4)+2*stride*4*(i/4),size/8,&data[i].s64); + //mem->read(new_addr+2*(i%4)+2*stride*4*(i/4),size/8,&data[i].s64); + fetch_addr=new_addr+2*(i%4)+2*stride*4*(i/4); + mem->read(fetch_addr,size/8,&data[i].s64); } else{ printf("mma_ld:wrong_layout_type\n"); @@ -3468,10 +3485,15 @@ void mma_ld_impl( const ptx_instruction *pI, core_t *core, warp_inst_t inst ) } else if(wmma_type==LOAD_B){ for(i=0;i<16;i++){ - if(wmma_layout==COL) - mem->read(new_addr+2*i,size/8,&data[i].s64); + if(wmma_layout==COL){ + //mem->read(new_addr+2*i,size/8,&data[i].s64); + fetch_addr=new_addr+2*i; + mem->read(fetch_addr,size/8,&data[i].s64); + } else if(wmma_layout==ROW){ - mem->read(new_addr+2*(i%4)+2*stride*4*(i/4),size/8,&data[i].s64); + //mem->read(new_addr+2*(i%4)+2*stride*4*(i/4),size/8,&data[i].s64); + fetch_addr=new_addr+2*(i%4)+2*stride*4*(i/4); + mem->read(fetch_addr,size/8,&data[i].s64); } else{ printf("mma_ld:wrong_layout_type\n"); @@ -3482,17 +3504,25 @@ void mma_ld_impl( const ptx_instruction *pI, core_t *core, warp_inst_t inst ) else if(wmma_type==LOAD_C){ for(i=0;i<8;i++){ if(type==F16_TYPE){ - if(wmma_layout==ROW) - mem->read(new_addr+2*i,size/8,&data[i].s64); - else if(wmma_layout==COL) - mem->read(new_addr+2*stride*i,size/8,&data[i].s64); + if(wmma_layout==ROW){ + //mem->read(new_addr+2*i,size/8,&data[i].s64); + fetch_addr=new_addr+2*i; + mem->read(fetch_addr,size/8,&data[i].s64); + } + else if(wmma_layout==COL){ + //mem->read(new_addr+2*stride*i,size/8,&data[i].s64); + fetch_addr=new_addr+2*stride*i; + mem->read(fetch_addr,size/8,&data[i].s64); + } else{ printf("mma_ld:wrong_type\n"); abort(); } } else if(type==F32_TYPE){ - mem->read(new_addr+4*acc_float_offset(i,wmma_layout,stride),size/8,&data[i].s64); + //mem->read(new_addr+4*acc_float_offset(i,wmma_layout,stride),size/8,&data[i].s64); + fetch_addr=new_addr+4*acc_float_offset(i,wmma_layout,stride); + mem->read(fetch_addr,size/8,&data[i].s64); } else{ printf("wrong type"); diff --git a/src/gpgpu-sim/shader.cc b/src/gpgpu-sim/shader.cc index 6f11ad9..5e80fb1 100644 --- a/src/gpgpu-sim/shader.cc +++ b/src/gpgpu-sim/shader.cc @@ -920,7 +920,7 @@ void scheduler_unit::cycle() ready_inst = true; const active_mask_t &active_mask = m_simt_stack[warp_id]->get_active_mask(); assert( warp(warp_id).inst_in_pipeline() ); - if ( (pI->op == LOAD_OP) || (pI->op == STORE_OP) || (pI->op == MEMORY_BARRIER_OP) ) { + if ( (pI->op == LOAD_OP)||(pI->op ==TENSOR_CORE_LOAD_OP)||(pI->op ==VP_LOAD_OP)|| (pI->op == STORE_OP)|| (pI->op==TENSOR_CORE_STORE_OP) ||(pI->op==VP_STORE_OP) || (pI->op == MEMORY_BARRIER_OP) ) { if( m_mem_out->has_free() ) { m_shader->issue_warp(*m_mem_out,pI,active_mask,warp_id); issued++; diff --git a/src/gpgpu-sim/shader.h b/src/gpgpu-sim/shader.h index d292d56..d9558b0 100644 --- a/src/gpgpu-sim/shader.h +++ b/src/gpgpu-sim/shader.h @@ -1116,7 +1116,11 @@ public: switch(inst.op) { case SFU_OP: return false; case LOAD_OP: return false; + case TENSOR_CORE_LOAD_OP: return false; + case VP_LOAD_OP: return false; case STORE_OP: return false; + case TENSOR_CORE_STORE_OP: return false; + case VP_STORE_OP: return false; case MEMORY_BARRIER_OP: return false; default: break; } @@ -1158,7 +1162,11 @@ public: { switch(inst.op) { case LOAD_OP: break; + case TENSOR_CORE_LOAD_OP: break; + case VP_LOAD_OP: break; case STORE_OP: break; + case TENSOR_CORE_STORE_OP: break; + case VP_STORE_OP: break; case MEMORY_BARRIER_OP: break; default: return false; } -- cgit v1.3 From 3949357047a621a06b2e7fb4fd6099cce1469d27 Mon Sep 17 00:00:00 2001 From: aamir Date: Sun, 16 Sep 2018 20:07:33 -0700 Subject: print for mem transaction --- src/abstract_hardware_model.cc | 1 + src/abstract_hardware_model.h | 13 ++++++++++++- src/cuda-sim/instructions.cc | 15 ++++++++++++++- src/gpgpu-sim/shader.cc | 6 +++++- src/gpgpu-sim/traffic_breakdown.cc | 1 + 5 files changed, 33 insertions(+), 3 deletions(-) (limited to 'src/abstract_hardware_model.h') diff --git a/src/abstract_hardware_model.cc b/src/abstract_hardware_model.cc index 83e76fe..72ece0b 100644 --- a/src/abstract_hardware_model.cc +++ b/src/abstract_hardware_model.cc @@ -352,6 +352,7 @@ void warp_inst_t::generate_mem_accesses() ptx_file_line_stats_add_uncoalesced_gmem( pc, m_accessq.size() - starting_queue_size ); } m_mem_accesses_created=true; + print_m_accessq(); } void warp_inst_t::memory_coalescing_arch_13( bool is_write, mem_access_type access_type ) diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index 9c418fa..d628745 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -933,7 +933,18 @@ public: for(unsigned i=0; i::iterator it; + for (it = m_accessq.begin(); it != m_accessq.end(); ++it){ + printf("MEM_TXN_GEN:%s:%x, Size:%d \n",mem_access_type_str(it->get_type()), it->get_addr(),it->get_size()); + } + } + } struct transaction_info { std::bitset<4> chunks; // bitmask: 32-byte chunks accessed mem_access_byte_mask_t bytes; diff --git a/src/cuda-sim/instructions.cc b/src/cuda-sim/instructions.cc index 42c63ca..52d89f2 100644 --- a/src/cuda-sim/instructions.cc +++ b/src/cuda-sim/instructions.cc @@ -3354,31 +3354,41 @@ void vp_ld_impl(const ptx_instruction *pI, core_t *core, warp_inst_t &inst) printf("vp_ld: thrx=%d,addr=%x, base_addr=%x, size=%d, stride=%d\n",thrd,new_addr,addr,size,src2_data.u32); if(wmma_type==LOAD_A||wmma_type==LOAD_C){ + printf("lda/c:"); for(i=0;i<8;i++){ if(wmma_layout==ROW){ //mem->read(new_addr+4*i,size/8,&data[i].s64); mem->read(new_addr+4*i,size/8,&data[i].s64); + printf("%x ", new_addr+4*i); mem_txn_addr[num_mem_txn++]=new_addr+4*i; } else if(wmma_layout==COL){ //mem->read(new_addr+4*stride*i,size/8,&data[i].s64); + printf("%x ", new_addr+4*stride*i); mem->read(new_addr+4*stride*i,size/8,&data[i].s64); mem_txn_addr[num_mem_txn++]=new_addr+4*stride*i; } } + } + else if(wmma_type==LOAD_B4){ + printf("ldb4:"); if(wmma_layout==ROW){ mem->read(new_addr,size/8,&data[0].s64); + printf("%x ",new_addr); mem_txn_addr[num_mem_txn++]=new_addr; } else if(wmma_layout==COL){ } } else if(wmma_type==LOAD_B8){ + printf("ldb8:"); if(wmma_layout==ROW){ mem->read(new_addr,size/8,&data[0].s64); mem->read(new_addr+4,size/8,&data[1].s64); + printf("%x ",new_addr,new_addr+4); + mem_txn_addr[num_mem_txn++]=new_addr; mem_txn_addr[num_mem_txn++]=new_addr+4; } @@ -3387,12 +3397,13 @@ void vp_ld_impl(const ptx_instruction *pI, core_t *core, warp_inst_t &inst) } } else if(wmma_type==LOAD_B16){ - printf("LOADB16_MODE"); + printf("ldb16:"); if(wmma_layout==ROW){ mem->read(new_addr,size/8,&data[0].s64); mem->read(new_addr+4,size/8,&data[1].s64); mem->read(new_addr+8,size/8,&data[2].s64); mem->read(new_addr+12,size/8,&data[3].s64); + printf("%x ",new_addr,new_addr+4,new_addr+8,new_addr+12); mem_txn_addr[num_mem_txn++]=new_addr; mem_txn_addr[num_mem_txn++]=new_addr+4; mem_txn_addr[num_mem_txn++]=new_addr+8; @@ -3405,6 +3416,8 @@ void vp_ld_impl(const ptx_instruction *pI, core_t *core, warp_inst_t &inst) printf("wrong vp_load type\n");; abort(); } + printf("\n"); + //generate timing memory request inst.space = space; inst.set_addr(thrd, (new_addr_type *)mem_txn_addr , num_mem_txn); diff --git a/src/gpgpu-sim/shader.cc b/src/gpgpu-sim/shader.cc index 5e80fb1..e745f03 100644 --- a/src/gpgpu-sim/shader.cc +++ b/src/gpgpu-sim/shader.cc @@ -741,7 +741,10 @@ void shader_core_ctx::func_exec_inst( warp_inst_t &inst ) { execute_warp_inst_t(inst); if( inst.is_load() || inst.is_store() ) - inst.generate_mem_accesses(); + { + inst.generate_mem_accesses(); + //inst.print_m_accessq(); + } } void shader_core_ctx::issue_warp( register_set& pipe_reg_set, const warp_inst_t* next_inst, const active_mask_t &active_mask, unsigned warp_id ) @@ -1512,6 +1515,7 @@ bool ldst_unit::memory_cycle( warp_inst_t &inst, mem_stage_stall_type &stall_rea // bypass L1 cache unsigned control_size = inst.is_store() ? WRITE_PACKET_SIZE : READ_PACKET_SIZE; unsigned size = access.get_size() + control_size; + //printf("Interconnect:Addr: %x, size=%d\n",access.get_addr(),size); if( m_icnt->full(size, inst.is_store() || inst.isatomic()) ) { stall_cond = ICNT_RC_FAIL; } else { diff --git a/src/gpgpu-sim/traffic_breakdown.cc b/src/gpgpu-sim/traffic_breakdown.cc index 32f0d30..587067f 100644 --- a/src/gpgpu-sim/traffic_breakdown.cc +++ b/src/gpgpu-sim/traffic_breakdown.cc @@ -46,6 +46,7 @@ std::string traffic_breakdown::classify_memfetch(class mem_fetch * mf) break; default: assert(0 && "Unknown traffic type"); } + printf("%s:Icnt:%s:Request: %x,Size%d,DataSize:%d,CntrlSize%d:\n",m_network_name.c_str(),traffic_name.c_str(),mf->get_addr(),mf->size(),mf->get_data_size(),mf->get_ctrl_size()); return traffic_name; } -- cgit v1.3 From 0e46a261dfeba9c19d1637f46277986d7eb1b9d8 Mon Sep 17 00:00:00 2001 From: Mahmoud Date: Tue, 9 Oct 2018 17:12:57 -0400 Subject: adding adaptive volta cache config --- configs/4.x-cfgs/SM7_TITANV/gpgpusim.config | 19 ++++++++++-------- src/abstract_hardware_model.cc | 2 ++ src/abstract_hardware_model.h | 2 ++ src/gpgpu-sim/gpu-cache.cc | 9 ++++----- src/gpgpu-sim/gpu-cache.h | 31 +++++++++++++++++++++++++---- src/gpgpu-sim/gpu-sim.cc | 3 +++ src/gpgpu-sim/shader.cc | 29 +++++++++++++++++++++++++++ src/gpgpu-sim/shader.h | 2 ++ 8 files changed, 80 insertions(+), 17 deletions(-) (limited to 'src/abstract_hardware_model.h') diff --git a/configs/4.x-cfgs/SM7_TITANV/gpgpusim.config b/configs/4.x-cfgs/SM7_TITANV/gpgpusim.config index cc4c931..a7056db 100644 --- a/configs/4.x-cfgs/SM7_TITANV/gpgpusim.config +++ b/configs/4.x-cfgs/SM7_TITANV/gpgpusim.config @@ -65,19 +65,21 @@ # ::,::::,::,:** # ** Optional parameter - Required when mshr_type==Texture Fifo -# Defualt config is 64KB DL1 and 64KB shared memory --gpgpu_cache:dl1 S:4:128:128,L:L:s:N:L,A:256:8,16:0,32 --gpgpu_cache:dl1PrefL1 S:4:128:192,L:L:s:N:L,A:256:8,16:0,32 --gpgpu_cache:dl1PrefShared S:4:128:64,L:L:s:N:L,A:256:8,16:0,32 --gpgpu_shmem_size 65536 --gpgpu_shmem_size_PrefL1 32768 --gpgpu_shmem_size_PrefShared 98304 +# Defualt config is 32KB DL1 and 96KB shared memory +# In Volta, we assign the remaining shared memory to L1 cache +# if the assigned shd mem = 0, then L1 cache = 128KB +# For more info, see https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#shared-memory-7-x +# disable this mode in case of multi kernels/apps execution +-adpative_volta_cache_config 1 +-gpgpu_cache:dl1 S:4:128:64,L:L:s:N:L,A:256:8,16:0,32 +-gpgpu_shmem_size 98304 -gmem_skip_L1D 0 -icnt_flit_size 40 -gpgpu_n_cluster_ejection_buffer_size 32 -l1_latency 28 -smem_latency 19 -gpgpu_flush_l1_cache 1 +-adpative_volta_cache_config 1 # 64 sets, each 128 bytes 24-way for each memory sub partition (192 KB per memory sub partition). This gives 4.5MB L2 cache -gpgpu_cache:dl2 S:64:128:24,L:B:m:L:L,A:384:4,32:0,32 @@ -87,7 +89,8 @@ # 128 KB Inst. -gpgpu_cache:il1 N:64:128:16,L:R:f:N:L,S:2:48,4 -# 48 KB Tex +# 48 KB Tex +# Note, TEX is deprected in Volta, It is used for legacy apps only. Use L1D cache instead with .nc modifier or __ldg mehtod -gpgpu_tex_cache:l1 N:16:128:24,L:R:m:N:L,T:128:4,128:2 # 64 KB Const -gpgpu_const_cache:l1 N:128:64:8,L:R:f:N:L,S:2:64,4 diff --git a/src/abstract_hardware_model.cc b/src/abstract_hardware_model.cc index d2a155c..39ed81c 100644 --- a/src/abstract_hardware_model.cc +++ b/src/abstract_hardware_model.cc @@ -591,6 +591,8 @@ kernel_info_t::kernel_info_t( dim3 gridDim, dim3 blockDim, class function_info * //Jin: launch latency management m_launch_latency = g_kernel_launch_latency; + + volta_cache_config_set=false; } kernel_info_t::~kernel_info_t() diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index e708fa7..6fa2ba0 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -301,6 +301,8 @@ public: unsigned long long start_cycle; unsigned long long end_cycle; unsigned m_launch_latency; + + mutable bool volta_cache_config_set; }; struct core_config { diff --git a/src/gpgpu-sim/gpu-cache.cc b/src/gpgpu-sim/gpu-cache.cc index a11853a..8ae4702 100644 --- a/src/gpgpu-sim/gpu-cache.cc +++ b/src/gpgpu-sim/gpu-cache.cc @@ -29,7 +29,6 @@ #include "stat-tool.h" #include -#define MAX_DEFAULT_CACHE_SIZE_MULTIBLIER 4 // used to allocate memory that is large enough to adapt the changes in cache size across kernels const char * cache_request_status_str(enum cache_request_status status) @@ -165,7 +164,7 @@ unsigned l2_cache_config::set_index(new_addr_type addr) const{ tag_array::~tag_array() { - unsigned cache_lines_num = MAX_DEFAULT_CACHE_SIZE_MULTIBLIER*m_config.get_num_lines(); + unsigned cache_lines_num = m_config.get_max_num_lines(); for(unsigned i=0; iis_modified_line()) { for(unsigned j=0; j < SECTOR_CHUNCK_SIZE; j++) m_lines[i]->set_status(INVALID, mem_access_sector_mask_t().set(j)) ; @@ -396,7 +395,7 @@ void tag_array::flush() void tag_array::invalidate() { - for (unsigned i=0; i < m_config.get_num_lines(); i++) + for (unsigned i=0; i < m_config.get_max_num_lines(); i++) for(unsigned j=0; j < SECTOR_CHUNCK_SIZE; j++) m_lines[i]->set_status(INVALID, mem_access_sector_mask_t().set(j)) ; } diff --git a/src/gpgpu-sim/gpu-cache.h b/src/gpgpu-sim/gpu-cache.h index 4ed382c..9174d7f 100644 --- a/src/gpgpu-sim/gpu-cache.h +++ b/src/gpgpu-sim/gpu-cache.h @@ -38,6 +38,8 @@ #include "addrdec.h" #include +#define MAX_DEFAULT_CACHE_SIZE_MULTIBLIER 4 + enum cache_block_state { INVALID=0, RESERVED, @@ -557,15 +559,15 @@ public: } if(m_alloc_policy == STREAMING) { //For streaming cache, we set the alloc policy to be on-fill to remove all line_alloc_fail stalls - //we set the MSHRs to be equal to the cache line. This is possible by moving TAG to be shared between cache line and MSHR enrty (i.e. for each cache line, there is an MSHR rntey associated with it) - // This is the easiest think we can think about to model (mimics) L1 streaming cache in Pascal and Volta + //we set the MSHRs to be equal to max allocated cache lines. This is possible by moving TAG to be shared between cache line and MSHR enrty (i.e. for each cache line, there is an MSHR rntey associated with it) + //This is the easiest think we can think about to model (mimic) L1 streaming cache in Pascal and Volta //Based on our microbenchmakrs, MSHRs entries have been increasing substantially in Pascal and Volta //For more information about streaming cache, see: // http://on-demand.gputechconf.com/gtc/2017/presentation/s7798-luke-durant-inside-volta.pdf // https://ieeexplore.ieee.org/document/8344474/ m_alloc_policy = ON_FILL; - m_mshr_entries = m_nset*m_assoc; + m_mshr_entries = m_nset*m_assoc*MAX_DEFAULT_CACHE_SIZE_MULTIBLIER; if(m_cache_type == SECTOR) m_mshr_entries *= SECTOR_CHUNCK_SIZE; m_mshr_max_merge = MAX_WARP_PER_SM; @@ -581,6 +583,7 @@ public: m_nset_log2 = LOGB2(m_nset); m_valid = true; m_atom_sz = (m_cache_type == SECTOR)? SECTOR_SIZE : m_line_sz; + original_m_assoc = m_assoc; //For more details about difference between FETCH_ON_WRITE and WRITE VALIDAE policies //Read: Jouppi, Norman P. "Cache write policies and performance". ISCA 93. @@ -646,7 +649,11 @@ public: assert( m_valid ); return m_nset * m_assoc; } - + unsigned get_max_num_lines() const + { + assert( m_valid ); + return MAX_DEFAULT_CACHE_SIZE_MULTIBLIER * m_nset * original_m_assoc; + } void print( FILE *fp ) const { fprintf( fp, "Size = %d B (%d Set x %d-way x %d byte line)\n", @@ -687,6 +694,21 @@ public: { return m_mshr_type; } + void set_assoc(unsigned n) + { + //set new assoc. L1 cache dynamically resized in Volta + m_assoc = n; + } + unsigned get_nset() const + { + assert( m_valid ); + return m_nset; + } + unsigned get_total_size_inKB() const + { + assert( m_valid ); + return (m_assoc*m_nset*m_line_sz)/1024; + } FuncCache get_cache_status() {return cache_status;} char *m_config_string; char *m_config_stringPrefL1; @@ -708,6 +730,7 @@ protected: unsigned m_nset_log2; unsigned m_assoc; unsigned m_atom_sz; + unsigned original_m_assoc; enum replacement_policy_t m_replacement_policy; // 'L' = LRU, 'F' = FIFO enum write_policy_t m_write_policy; // 'T' = write through, 'B' = write back, 'R' = read only diff --git a/src/gpgpu-sim/gpu-sim.cc b/src/gpgpu-sim/gpu-sim.cc index 08d4525..080cbac 100644 --- a/src/gpgpu-sim/gpu-sim.cc +++ b/src/gpgpu-sim/gpu-sim.cc @@ -307,6 +307,9 @@ void shader_core_config::reg_options(class OptionParser * opp) option_parser_register(opp, "-gpgpu_shmem_size", OPT_UINT32, &gpgpu_shmem_size, "Size of shared memory per shader core (default 16kB)", "16384"); + option_parser_register(opp, "-adpative_volta_cache_config", OPT_BOOL, &adpative_volta_cache_config, + "adpative_volta_cache_config", + "0"); option_parser_register(opp, "-gpgpu_shmem_size", OPT_UINT32, &gpgpu_shmem_sizeDefault, "Size of shared memory per shader core (default 16kB)", "16384"); diff --git a/src/gpgpu-sim/shader.cc b/src/gpgpu-sim/shader.cc index 0e2e1c2..2cc8a2e 100644 --- a/src/gpgpu-sim/shader.cc +++ b/src/gpgpu-sim/shader.cc @@ -2744,6 +2744,35 @@ unsigned int shader_core_config::max_cta( const kernel_info_t &k ) const abort(); } + if(adpative_volta_cache_config && !k.volta_cache_config_set) { + //For Volta, we assign the remaining shared memory to L1 cache + //For more info, see https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#shared-memory-7-x + unsigned total_shmed = kernel_info->smem * result; + assert(total_shmed >=0 && total_shmed <= gpgpu_shmem_size); + assert(gpgpu_shmem_size == 98304); //Volta has 96 KB shared + assert(m_L1D_config.get_nset() == 4); //Volta L1 has four sets + if(total_shmed < gpgpu_shmem_size){ + if(total_shmed == 0) + m_L1D_config.set_assoc(256); //L1 is 128KB ans shd=0 + else if(total_shmed > 0 && total_shmed <= 8192) + m_L1D_config.set_assoc(240); //L1 is 120KB ans shd=8KB + else if(total_shmed > 8192 && total_shmed <= 16384) + m_L1D_config.set_assoc(224); //L1 is 112KB ans shd=16KB + else if(total_shmed > 16384 && total_shmed <= 32768) + m_L1D_config.set_assoc(192); //L1 is 96KB ans shd=32KB + else if(total_shmed > 32768 && total_shmed <= 65536) + m_L1D_config.set_assoc(128); //L1 is 64KB ans shd=64KB + else if(total_shmed > 65536 && total_shmed <= gpgpu_shmem_size) + m_L1D_config.set_assoc(64); //L1 is 32KB and shd=96KB + else + assert(0); + + printf ("GPGPU-Sim: Reconfigure L1 cache in Volta Archi to %uKB\n", m_L1D_config.get_total_size_inKB()); + } + + k.volta_cache_config_set = true; + } + return result; } diff --git a/src/gpgpu-sim/shader.h b/src/gpgpu-sim/shader.h index e07096e..92b4159 100644 --- a/src/gpgpu-sim/shader.h +++ b/src/gpgpu-sim/shader.h @@ -1409,6 +1409,8 @@ struct shader_core_config : public core_config //Jin: concurrent kernel on sm bool gpgpu_concurrent_kernel_sm; + + bool adpative_volta_cache_config; }; struct shader_core_stats_pod { -- cgit v1.3 From 8db50a319911b803a386a7d7eca10afbea4d7e75 Mon Sep 17 00:00:00 2001 From: aamir Date: Fri, 2 Nov 2018 21:37:31 -0700 Subject: added incount and outcount, addressed all of the pull request comments --- libcuda/cuda_runtime_api.cc | 8 +++++--- src/abstract_hardware_model.h | 6 ++++++ src/cuda-sim/cuda-sim.cc | 22 ++++++++++++++++++---- src/cuda-sim/instructions.cc | 14 ++++++++++---- src/cuda-sim/ptx_parser.cc | 2 +- src/gpgpu-sim/scoreboard.cc | 44 ++++++++----------------------------------- src/gpgpu-sim/shader.cc | 18 ++++++++++++------ 7 files changed, 60 insertions(+), 54 deletions(-) (limited to 'src/abstract_hardware_model.h') diff --git a/libcuda/cuda_runtime_api.cc b/libcuda/cuda_runtime_api.cc index a79e740..d67fd85 100644 --- a/libcuda/cuda_runtime_api.cc +++ b/libcuda/cuda_runtime_api.cc @@ -986,7 +986,6 @@ __host__ cudaError_t CUDARTAPI cudaLaunchKernel ( const char* hostFun, dim3 grid struct CUstream_st *s = (struct CUstream_st *)stream; g_cuda_launch_stack.push_back( kernel_config(gridDim,blockDim,sharedMem,s) ); - //printf("cudaLaunchKernel:sizeof(Arg[0])=%d)\n ",sizeof(args[0])); kernel_config &config = g_cuda_launch_stack.back(); config.set_arg(args[0],432,0);//standard interface for cutlass library #TODO Implementing a generalized kernel @@ -1006,12 +1005,15 @@ __host__ cudaError_t CUDARTAPI cudaLaunchKernel ( const char* hostFun, dim3 grid dim3 blockDim1 = config1.block_dim(); printf("GPGPU-Sim PTX: pushing kernel \'%s\' to stream %u, gridDim= (%u,%u,%u) blockDim = (%u,%u,%u) \n", kname.c_str(), stream1?stream1->get_uid():0, gridDim1.x,gridDim1.y,gridDim1.z,blockDim1.x,blockDim1.y,blockDim1.z ); + + /*Kernel is hardcoded to enable the cutlass library*/ + std::string cutlass("cutlass"); + assert(kname.find(cutlass) != std::string::npos); + stream_operation op(grid,g_ptx_sim_mode,stream1); g_stream_manager->push(op); g_cuda_launch_stack.pop_back(); return g_last_cudaError = cudaSuccess; - - } /******************************************************************************* diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index f561f34..71d3d89 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -36,6 +36,10 @@ class kernel_info_t; #define MAX_CTA_PER_SHADER 32 #define MAX_BARRIERS_PER_CTA 16 +//After expanding the vector input and output operands +#define MAX_INPUT_VALUES 24 +#define MAX_OUTPUT_VALUES 8 + enum _memory_space_t { undefined_space=0, reg_space, @@ -830,7 +834,9 @@ public: address_type reconvergence_pc; // -1 => not a branch, -2 => use function return address unsigned out[8]; + unsigned outcount; unsigned in[24]; + unsigned incount; unsigned char is_vectorin; unsigned char is_vectorout; int pred; // predicate register number diff --git a/src/cuda-sim/cuda-sim.cc b/src/cuda-sim/cuda-sim.cc index 86a1d45..23c5ad5 100644 --- a/src/cuda-sim/cuda-sim.cc +++ b/src/cuda-sim/cuda-sim.cc @@ -602,7 +602,7 @@ void ptx_instruction::set_opcode_and_latency() * [3] MAD * [4] DIV */ - sscanf(opcode_latency_int, "%u,%u,%u,%u,%u,%u,%u", + sscanf(opcode_latency_int, "%u,%u,%u,%u,%u", &int_latency[0],&int_latency[1],&int_latency[2], &int_latency[3],&int_latency[4]); sscanf(opcode_latency_fp, "%u,%u,%u,%u,%u", @@ -850,12 +850,14 @@ void ptx_instruction::pre_decode() { pc = m_PC; isize = m_inst_size; - for(unsigned i=0; i<8; i++) { + for(unsigned i=0; i0) + outcount++; + + for(int i=0;i0) + incount++; // Get predicate if(has_pred()) { @@ -1316,7 +1327,10 @@ void ptx_thread_info::ptx_exec_inst( warp_inst_t &inst, unsigned lane_id) if(((inst_opcode==MMA_OP||inst_opcode==MMA_LD_OP||inst_opcode==MMA_ST_OP))){ if(inst.active_count()!=MAX_WARP_SIZE) - while(1); + { + printf("Tensor Core operation are warp synchronous operation. All the threads needs to be active."); + assert(0); + } } if(((inst_opcode!=MMA_OP)&&(inst_opcode!=MMA_LD_OP)&&(inst_opcode!=MMA_ST_OP))||((inst_opcode==MMA_OP||inst_opcode==MMA_LD_OP||inst_opcode==MMA_ST_OP)&&(lane_id==0))){ diff --git a/src/cuda-sim/instructions.cc b/src/cuda-sim/instructions.cc index 2677c40..06cad54 100644 --- a/src/cuda-sim/instructions.cc +++ b/src/cuda-sim/instructions.cc @@ -1726,7 +1726,7 @@ void mma_impl( const ptx_instruction *pI, core_t *core, warp_inst_t inst ) unsigned b_layout = pI->get_wmma_layout(1); unsigned type = pI->get_type(); unsigned type2 = pI->get_type2(); - int tid = inst.warp_id_func() * core->get_warp_size(); + int tid = inst.warp_id() * core->get_warp_size(); const operand_info &dst = pI->operand_lookup(0); unsigned thread_group_index; @@ -2962,7 +2962,7 @@ void mma_st_impl( const ptx_instruction *pI, core_t *core, warp_inst_t &inst ) const operand_info &src = pI->operand_lookup(1); const operand_info &src1 = pI->operand_lookup(0); const operand_info &src2 = pI->operand_lookup(2); - int tid = inst.warp_id_func()*core->get_warp_size(); + int tid = inst.warp_id()*core->get_warp_size(); unsigned type = pI->get_type(); unsigned wmma_type = pI->get_wmma_type(); unsigned wmma_layout = pI->get_wmma_layout(0); @@ -3069,7 +3069,7 @@ void mma_ld_impl( const ptx_instruction *pI, core_t *core, warp_inst_t &inst ) unsigned type = pI->get_type(); unsigned wmma_type = pI->get_wmma_type(); unsigned wmma_layout = pI->get_wmma_layout(0); - int tid = inst.warp_id_func()*core->get_warp_size(); + int tid = inst.warp_id()*core->get_warp_size(); int thrd,stride; ptx_thread_info *thread; _memory_op_t insn_memory_op = pI->has_memory_read() ? memory_load : memory_store; @@ -4469,7 +4469,13 @@ 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_func() * core->get_warp_size(); + int tid; + + if(core->get_gpu()->is_functional_sim()) + tid = inst.warp_id_func() * core->get_warp_size(); + else + 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(); diff --git a/src/cuda-sim/ptx_parser.cc b/src/cuda-sim/ptx_parser.cc index d5324d0..9671ab7 100644 --- a/src/cuda-sim/ptx_parser.cc +++ b/src/cuda-sim/ptx_parser.cc @@ -39,7 +39,7 @@ void set_ptx_warp_size(const struct core_config * warp_size) g_shader_core_config=warp_size; } -static bool g_debug_ir_generation=true; +static bool g_debug_ir_generation=false; const char *g_filename; unsigned g_max_regs_per_thread = 0; diff --git a/src/gpgpu-sim/scoreboard.cc b/src/gpgpu-sim/scoreboard.cc index 4d1b43a..ebec891 100644 --- a/src/gpgpu-sim/scoreboard.cc +++ b/src/gpgpu-sim/scoreboard.cc @@ -82,7 +82,7 @@ const bool Scoreboard::islongop (unsigned warp_id,unsigned regnum) { void Scoreboard::reserveRegisters(const class warp_inst_t* inst) { - for( unsigned r=0; r < 8; r++) { + for( unsigned r=0; r < MAX_OUTPUT_VALUES; r++) { if(inst->out[r] > 0) { reserveRegister(inst->warp_id(), inst->out[r]); SHADER_DPRINTF( SCOREBOARD, @@ -100,7 +100,7 @@ void Scoreboard::reserveRegisters(const class warp_inst_t* inst) inst->space.get_type() == param_space_local || inst->space.get_type() == param_space_unclassified || inst->space.get_type() == tex_space)){ - for ( unsigned r=0; r<8; r++) { + for ( unsigned r=0; rout[r] > 0) { SHADER_DPRINTF( SCOREBOARD, "New longopreg marked - warp:%d, reg: %d\n", @@ -115,7 +115,7 @@ void Scoreboard::reserveRegisters(const class warp_inst_t* inst) // Release registers for an instruction void Scoreboard::releaseRegisters(const class warp_inst_t *inst) { - for( unsigned r=0; r < 8; r++) { + for( unsigned r=0; r < MAX_OUTPUT_VALUES; r++) { if(inst->out[r] > 0) { SHADER_DPRINTF( SCOREBOARD, "Register Released - warp:%d, reg: %d\n", @@ -138,39 +138,11 @@ bool Scoreboard::checkCollision( unsigned wid, const class inst_t *inst ) const // Get list of all input and output registers std::set inst_regs; - if(inst->out[0] > 0) inst_regs.insert(inst->out[0]); - if(inst->out[1] > 0) inst_regs.insert(inst->out[1]); - if(inst->out[2] > 0) inst_regs.insert(inst->out[2]); - if(inst->out[3] > 0) inst_regs.insert(inst->out[3]); - if(inst->out[4] > 0) inst_regs.insert(inst->out[4]); - if(inst->out[5] > 0) inst_regs.insert(inst->out[5]); - if(inst->out[6] > 0) inst_regs.insert(inst->out[6]); - if(inst->out[7] > 0) inst_regs.insert(inst->out[7]); - - if(inst->in[0] > 0) inst_regs.insert(inst->in[0]); - if(inst->in[1] > 0) inst_regs.insert(inst->in[1]); - if(inst->in[2] > 0) inst_regs.insert(inst->in[2]); - if(inst->in[3] > 0) inst_regs.insert(inst->in[3]); - if(inst->in[4] > 0) inst_regs.insert(inst->in[4]); - if(inst->in[5] > 0) inst_regs.insert(inst->in[5]); - if(inst->in[6] > 0) inst_regs.insert(inst->in[6]); - if(inst->in[7] > 0) inst_regs.insert(inst->in[7]); - if(inst->in[8] > 0) inst_regs.insert(inst->in[8]); - if(inst->in[9] > 0) inst_regs.insert(inst->in[9]); - if(inst->in[10] > 0) inst_regs.insert(inst->in[10]); - if(inst->in[11] > 0) inst_regs.insert(inst->in[11]); - if(inst->in[12] > 0) inst_regs.insert(inst->in[12]); - if(inst->in[13] > 0) inst_regs.insert(inst->in[13]); - if(inst->in[14] > 0) inst_regs.insert(inst->in[14]); - if(inst->in[15] > 0) inst_regs.insert(inst->in[15]); - if(inst->in[16] > 0) inst_regs.insert(inst->in[16]); - if(inst->in[17] > 0) inst_regs.insert(inst->in[17]); - if(inst->in[18] > 0) inst_regs.insert(inst->in[18]); - if(inst->in[19] > 0) inst_regs.insert(inst->in[19]); - if(inst->in[20] > 0) inst_regs.insert(inst->in[20]); - if(inst->in[21] > 0) inst_regs.insert(inst->in[21]); - if(inst->in[22] > 0) inst_regs.insert(inst->in[22]); - if(inst->in[23] > 0) inst_regs.insert(inst->in[23]); + for(int iii=0;iiioutcount;iii++) + inst_regs.insert(inst->out[iii]); + + for(int jjj=0;jjjincount;jjj++) + inst_regs.insert(inst->in[jjj]); if(inst->pred > 0) inst_regs.insert(inst->pred); if(inst->ar1 > 0) inst_regs.insert(inst->ar1); diff --git a/src/gpgpu-sim/shader.cc b/src/gpgpu-sim/shader.cc index 23f255d..f9cfa58 100644 --- a/src/gpgpu-sim/shader.cc +++ b/src/gpgpu-sim/shader.cc @@ -425,7 +425,7 @@ void shader_core_stats::print( FILE* fout ) const fprintf(fout, "gpgpu_n_load_insn = %d\n", gpgpu_n_load_insn); fprintf(fout, "gpgpu_n_store_insn = %d\n", gpgpu_n_store_insn); fprintf(fout, "gpgpu_n_shmem_insn = %d\n", gpgpu_n_shmem_insn); - fprintf(fout, "gpgpu_n_shmem_insn = %d\n", gpgpu_n_sstarr_insn); + fprintf(fout, "gpgpu_n_sstarr_insn = %d\n", gpgpu_n_sstarr_insn); fprintf(fout, "gpgpu_n_tex_insn = %d\n", gpgpu_n_tex_insn); fprintf(fout, "gpgpu_n_const_mem_insn = %d\n", gpgpu_n_const_insn); fprintf(fout, "gpgpu_n_param_mem_insn = %d\n", gpgpu_n_param_insn); @@ -1290,6 +1290,12 @@ void ldst_unit::get_L1T_sub_stats(struct cache_sub_stats &css) const{ void shader_core_ctx::warp_inst_complete(const warp_inst_t &inst) { + + #if 0 + printf("[warp_inst_complete] uid=%u core=%u warp=%u pc=%#x @ time=%llu issued@%llu\n", + inst.get_uid(), m_sid, inst.warp_id(), inst.pc, gpu_tot_sim_cycle + gpu_sim_cycle, inst.get_issue_cycle()); + #endif + if(inst.op_pipe==SP__OP) m_stats->m_num_sp_committed[m_sid]++; else if(inst.op_pipe==SFU__OP) @@ -1386,7 +1392,7 @@ ldst_unit::process_cache_access( cache_t* cache, assert( !read_sent ); inst.accessq_pop_back(); if ( inst.is_load() ) { - for ( unsigned r=0; r < 8; r++) + for ( unsigned r=0; r < MAX_OUTPUT_VALUES; r++) if (inst.out[r] > 0) m_pending_writes[inst.warp_id()][inst.out[r]]--; } @@ -1488,7 +1494,7 @@ bool ldst_unit::memory_cycle( warp_inst_t &inst, mem_stage_stall_type &stall_rea inst.accessq_pop_back(); //inst.clear_active( access.get_warp_mask() ); if( inst.is_load() ) { - for( unsigned r=0; r < 8; r++) + for( unsigned r=0; r < MAX_OUTPUT_VALUES; r++) if(inst.out[r] > 0) assert( m_pending_writes[inst.warp_id()][inst.out[r]] > 0 ); } else if( inst.is_store() ) @@ -1765,7 +1771,7 @@ void ldst_unit:: issue( register_set ®_set ) if (inst->is_load() and inst->space.get_type() != shared_space) { unsigned warp_id = inst->warp_id(); unsigned n_accesses = inst->accessq_count(); - for (unsigned r = 0; r < 8; r++) { + for (unsigned r = 0; r < MAX_OUTPUT_VALUES; r++) { unsigned reg_id = inst->out[r]; if (reg_id > 0) { m_pending_writes[warp_id][reg_id] += n_accesses; @@ -1787,7 +1793,7 @@ void ldst_unit::writeback() if( !m_next_wb.empty() ) { if( m_operand_collector->writeback(m_next_wb) ) { bool insn_completed = false; - for( unsigned r=0; r < 8; r++ ) { + for( unsigned r=0; r < MAX_OUTPUT_VALUES; r++ ) { if( m_next_wb.out[r] > 0 ) { if( m_next_wb.space.get_type() != shared_space ) { assert( m_pending_writes[m_next_wb.warp_id()][m_next_wb.out[r]] > 0 ); @@ -1989,7 +1995,7 @@ void ldst_unit::cycle() //} bool pending_requests=false; - for( unsigned r=0; r<8; r++ ) { + for( unsigned r=0; r 0 ) { if( m_pending_writes[warp_id].find(reg_id) != m_pending_writes[warp_id].end() ) { -- cgit v1.3 From eae030c9d1d607d1c14e4ade99cb5caea6403efd Mon Sep 17 00:00:00 2001 From: aamir Date: Sat, 3 Nov 2018 17:03:58 -0700 Subject: merged with memory subsytem. Regression is passing but tensorcore kernel is stuck in deadlock --- .gitignore | 1 + .travis.yml | 31 +- CHANGES | 30 + Jenkinsfile | 126 ++++ README | 10 +- aerialvision/organizedata.py | 2 +- configs/GTX480/config_fermi_islip.icnt | 70 -- configs/GTX480/gpgpusim.config | 134 ---- configs/GTX480/gpuwattch_gtx480.xml | 538 -------------- configs/GeForceGTX1080Ti/config_fermi_islip.icnt | 70 -- configs/GeForceGTX1080Ti/gpgpusim.config | 150 ---- configs/GeForceGTX1080Ti/gpuwattch_gtx1080Ti.xml | 538 -------------- configs/GeForceGTX750Ti/config_fermi_islip.icnt | 70 -- configs/GeForceGTX750Ti/gpgpusim.config | 131 ---- configs/GeForceGTX750Ti/gpuwattch_gtx750Ti.xml | 539 -------------- configs/Pascal_TITANX/config_fermi_islip.icnt | 70 -- configs/Pascal_TITANX/gpgpusim.config | 156 ---- configs/QuadroFX5600/gpgpusim.config | 99 --- configs/QuadroFX5600/gpuwattch_quadrofx5600.xml | 538 -------------- configs/QuadroFX5600/icnt_config_islip.icnt | 70 -- configs/QuadroFX5800/config_quadro_islip.icnt | 69 -- configs/QuadroFX5800/gpgpusim.config | 88 --- configs/TeslaC2050/config_fermi_islip.icnt | 70 -- configs/TeslaC2050/gpgpusim.config | 133 ---- .../deprecated-cfgs/GTX480/config_fermi_islip.icnt | 70 ++ configs/deprecated-cfgs/GTX480/gpgpusim.config | 134 ++++ .../deprecated-cfgs/GTX480/gpuwattch_gtx480.xml | 538 ++++++++++++++ .../GeForceGTX750Ti/config_fermi_islip.icnt | 70 ++ .../GeForceGTX750Ti/gpgpusim.config | 131 ++++ .../GeForceGTX750Ti/gpuwattch_gtx750Ti.xml | 539 ++++++++++++++ .../deprecated-cfgs/QuadroFX5600/gpgpusim.config | 99 +++ .../QuadroFX5600/gpuwattch_quadrofx5600.xml | 538 ++++++++++++++ .../QuadroFX5600/icnt_config_islip.icnt | 70 ++ .../QuadroFX5800/config_quadro_islip.icnt | 69 ++ .../deprecated-cfgs/QuadroFX5800/gpgpusim.config | 88 +++ .../SM6_GTX1080/config_fermi_islip.icnt | 70 ++ .../deprecated-cfgs/SM6_GTX1080/gpgpusim.config | 150 ++++ .../SM6_GTX1080/gpuwattch_gtx1080Ti.xml | 538 ++++++++++++++ .../SM6_P100/config_fermi_islip.icnt | 70 ++ configs/deprecated-cfgs/SM6_P100/gpgpusim.config | 156 ++++ .../deprecated-cfgs/SM6_P100/gpuwattch_gtx480.xml | 538 ++++++++++++++ .../SM6_TITANX/config_fermi_islip.icnt | 70 ++ configs/deprecated-cfgs/SM6_TITANX/gpgpusim.config | 157 +++++ .../SM6_TITANX/gpuwattch_gtx480.xml | 538 ++++++++++++++ .../SM7_TITANV/config_fermi_islip.icnt | 70 ++ configs/deprecated-cfgs/SM7_TITANV/gpgpusim.config | 165 +++++ .../TeslaC2050/config_fermi_islip.icnt | 70 ++ configs/deprecated-cfgs/TeslaC2050/gpgpusim.config | 133 ++++ .../tested-cfgs/SM2_GTX480/config_fermi_islip.icnt | 70 ++ configs/tested-cfgs/SM2_GTX480/gpgpusim.config | 153 ++++ .../tested-cfgs/SM2_GTX480/gpuwattch_gtx480.xml | 538 ++++++++++++++ .../tested-cfgs/SM6_TITANX/config_fermi_islip.icnt | 73 ++ configs/tested-cfgs/SM6_TITANX/gpgpusim.config | 185 +++++ .../tested-cfgs/SM7_TITANV/config_fermi_islip.icnt | 74 ++ configs/tested-cfgs/SM7_TITANV/gpgpusim.config | 191 +++++ cuobjdump_to_ptxplus/ptx_parser.h | 4 + libcuda/cuda_runtime_api.cc | 49 +- nightly.jenkinsfile | 75 ++ setup_environment | 2 +- src/abstract_hardware_model.cc | 49 +- src/abstract_hardware_model.h | 33 +- src/cuda-sim/cuda-sim.cc | 47 +- src/cuda-sim/instructions.cc | 1 + src/cuda-sim/ptx.y | 3 +- src/cuda-sim/ptx_ir.cc | 7 +- src/cuda-sim/ptx_ir.h | 7 + src/cuda-sim/ptx_parser.cc | 4 + src/cuda-sim/ptx_parser.h | 1 + src/gpgpu-sim/addrdec.cc | 71 ++ src/gpgpu-sim/addrdec.h | 9 + src/gpgpu-sim/delayqueue.h | 1 + src/gpgpu-sim/dram.cc | 637 +++++++++++++---- src/gpgpu-sim/dram.h | 77 +- src/gpgpu-sim/dram_sched.cc | 121 +++- src/gpgpu-sim/dram_sched.h | 12 + src/gpgpu-sim/gpu-cache.cc | 782 +++++++++++++++++---- src/gpgpu-sim/gpu-cache.h | 644 +++++++++++++++-- src/gpgpu-sim/gpu-sim.cc | 125 +++- src/gpgpu-sim/gpu-sim.h | 57 +- src/gpgpu-sim/l2cache.cc | 166 ++++- src/gpgpu-sim/l2cache.h | 18 + src/gpgpu-sim/l2cache_trace.h | 16 + src/gpgpu-sim/mem_fetch.cc | 7 +- src/gpgpu-sim/mem_fetch.h | 13 +- src/gpgpu-sim/mem_latency_stat.cc | 19 +- src/gpgpu-sim/mem_latency_stat.h | 4 + src/gpgpu-sim/shader.cc | 431 ++++++++++-- src/gpgpu-sim/shader.h | 93 ++- src/gpgpusim_entrypoint.cc | 1 + src/gpuwattch/makefile | 4 +- src/intersim2/Makefile | 2 +- src/intersim2/interconnect_interface.cpp | 9 +- src/trace_streams.tup | 2 + version | 2 +- 94 files changed, 9589 insertions(+), 4104 deletions(-) create mode 100644 Jenkinsfile delete mode 100644 configs/GTX480/config_fermi_islip.icnt delete mode 100644 configs/GTX480/gpgpusim.config delete mode 100755 configs/GTX480/gpuwattch_gtx480.xml delete mode 100644 configs/GeForceGTX1080Ti/config_fermi_islip.icnt delete mode 100644 configs/GeForceGTX1080Ti/gpgpusim.config delete mode 100755 configs/GeForceGTX1080Ti/gpuwattch_gtx1080Ti.xml delete mode 100644 configs/GeForceGTX750Ti/config_fermi_islip.icnt delete mode 100644 configs/GeForceGTX750Ti/gpgpusim.config delete mode 100755 configs/GeForceGTX750Ti/gpuwattch_gtx750Ti.xml delete mode 100644 configs/Pascal_TITANX/config_fermi_islip.icnt delete mode 100644 configs/Pascal_TITANX/gpgpusim.config delete mode 100644 configs/QuadroFX5600/gpgpusim.config delete mode 100644 configs/QuadroFX5600/gpuwattch_quadrofx5600.xml delete mode 100644 configs/QuadroFX5600/icnt_config_islip.icnt delete mode 100644 configs/QuadroFX5800/config_quadro_islip.icnt delete mode 100644 configs/QuadroFX5800/gpgpusim.config delete mode 100644 configs/TeslaC2050/config_fermi_islip.icnt delete mode 100644 configs/TeslaC2050/gpgpusim.config create mode 100644 configs/deprecated-cfgs/GTX480/config_fermi_islip.icnt create mode 100644 configs/deprecated-cfgs/GTX480/gpgpusim.config create mode 100755 configs/deprecated-cfgs/GTX480/gpuwattch_gtx480.xml create mode 100644 configs/deprecated-cfgs/GeForceGTX750Ti/config_fermi_islip.icnt create mode 100644 configs/deprecated-cfgs/GeForceGTX750Ti/gpgpusim.config create mode 100755 configs/deprecated-cfgs/GeForceGTX750Ti/gpuwattch_gtx750Ti.xml create mode 100644 configs/deprecated-cfgs/QuadroFX5600/gpgpusim.config create mode 100644 configs/deprecated-cfgs/QuadroFX5600/gpuwattch_quadrofx5600.xml create mode 100644 configs/deprecated-cfgs/QuadroFX5600/icnt_config_islip.icnt create mode 100644 configs/deprecated-cfgs/QuadroFX5800/config_quadro_islip.icnt create mode 100644 configs/deprecated-cfgs/QuadroFX5800/gpgpusim.config create mode 100644 configs/deprecated-cfgs/SM6_GTX1080/config_fermi_islip.icnt create mode 100644 configs/deprecated-cfgs/SM6_GTX1080/gpgpusim.config create mode 100755 configs/deprecated-cfgs/SM6_GTX1080/gpuwattch_gtx1080Ti.xml create mode 100644 configs/deprecated-cfgs/SM6_P100/config_fermi_islip.icnt create mode 100644 configs/deprecated-cfgs/SM6_P100/gpgpusim.config create mode 100755 configs/deprecated-cfgs/SM6_P100/gpuwattch_gtx480.xml create mode 100644 configs/deprecated-cfgs/SM6_TITANX/config_fermi_islip.icnt create mode 100644 configs/deprecated-cfgs/SM6_TITANX/gpgpusim.config create mode 100755 configs/deprecated-cfgs/SM6_TITANX/gpuwattch_gtx480.xml create mode 100644 configs/deprecated-cfgs/SM7_TITANV/config_fermi_islip.icnt create mode 100644 configs/deprecated-cfgs/SM7_TITANV/gpgpusim.config create mode 100644 configs/deprecated-cfgs/TeslaC2050/config_fermi_islip.icnt create mode 100644 configs/deprecated-cfgs/TeslaC2050/gpgpusim.config create mode 100644 configs/tested-cfgs/SM2_GTX480/config_fermi_islip.icnt create mode 100644 configs/tested-cfgs/SM2_GTX480/gpgpusim.config create mode 100755 configs/tested-cfgs/SM2_GTX480/gpuwattch_gtx480.xml create mode 100644 configs/tested-cfgs/SM6_TITANX/config_fermi_islip.icnt create mode 100644 configs/tested-cfgs/SM6_TITANX/gpgpusim.config create mode 100644 configs/tested-cfgs/SM7_TITANV/config_fermi_islip.icnt create mode 100644 configs/tested-cfgs/SM7_TITANV/gpgpusim.config create mode 100644 nightly.jenkinsfile (limited to 'src/abstract_hardware_model.h') diff --git a/.gitignore b/.gitignore index d21cc8f..6c6ed5f 100644 --- a/.gitignore +++ b/.gitignore @@ -32,4 +32,5 @@ cuobjdump_to_ptxplus/sass_parser.hh cuobjdump_to_ptxplus/sass_parser.output build/* +tags *.swp diff --git a/.travis.yml b/.travis.yml index 7a12a1c..b38f468 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ sudo: required before_install: - - docker pull tgrogers/gpgpu-sim_regress:latest + - docker pull tgrogers/gpgpu-sim_regress:volta_update language: cpp @@ -10,34 +10,13 @@ matrix: include: - services: docker env: - - CONFIG=configs.gtx480.yml + - CONFIG=GTX480 - CUDA_INSTALL_PATH=/usr/local/cuda-4.2/ - PTXAS_CUDA_INSTALL_PATH=/usr/local/cuda-4.2/ -# This config is just taking far too long... -# - services: docker -# env: -# - CONFIG=configs.gtx750ti.yml -# - CUDA_INSTALL_PATH=/usr/local/cuda-4.2/ -# - PTXAS_CUDA_INSTALL_PATH=/usr/local/cuda-4.2/ - services: docker env: - - CONFIG=configs.quadro5600.yml - - CUDA_INSTALL_PATH=/usr/local/cuda-4.2/ - - PTXAS_CUDA_INSTALL_PATH=/usr/local/cuda-4.2/ - - services: docker - env: - - CONFIG=configs.quadro5800.yml - - CUDA_INSTALL_PATH=/usr/local/cuda-4.2/ - - PTXAS_CUDA_INSTALL_PATH=/usr/local/cuda-4.2/ - - services: docker - env: - - CONFIG=configs.teslac2050.yml - - CUDA_INSTALL_PATH=/usr/local/cuda-4.2/ - - PTXAS_CUDA_INSTALL_PATH=/usr/local/cuda-4.2/ - - services: docker - env: - - CONFIG=configs.gtx1080ti.yml - - CUDA_INSTALL_PATH=/usr/local/cuda-4.2/ + - CONFIG=TITANV + - CUDA_INSTALL_PATH=/usr/local/cuda-9.1/ - PTXAS_CUDA_INSTALL_PATH=/usr/local/cuda-9.1/ -script: docker run -v `pwd`:/home/runner/gpgpu-sim_distribution:rw tgrogers/gpgpu-sim_regress:latest /bin/bash -c "./start_torque.sh; chown -R runner /home/runner/gpgpu-sim_distribution; su - runner -c 'export CUDA_INSTALL_PATH=$CUDA_INSTALL_PATH && export PTXAS_CUDA_INSTALL_PATH=$PTXAS_CUDA_INSTALL_PATH && source /home/runner/gpgpu-sim_distribution/setup_environment && make -j -C /home/runner/gpgpu-sim_distribution && cd /home/runner/gpgpu-sim_simulations/ && git pull && /home/runner/gpgpu-sim_simulations/util/job_launching/run_simulations.py -c /home/runner/gpgpu-sim_simulations/util/job_launching/regression_recipies/rodinia_2.0-ft/$CONFIG -N regress && /home/runner/gpgpu-sim_simulations/util/job_launching/monitor_func_test.py -v -N regress'" +script: docker run -v `pwd`:/home/runner/gpgpu-sim_distribution:rw tgrogers/gpgpu-sim_regress:volta_update /bin/bash -c "./start_torque.sh; chown -R runner /home/runner/gpgpu-sim_distribution; su - runner -c 'export CUDA_INSTALL_PATH=$CUDA_INSTALL_PATH && export PTXAS_CUDA_INSTALL_PATH=$PTXAS_CUDA_INSTALL_PATH && source /home/runner/gpgpu-sim_distribution/setup_environment && make -j -C /home/runner/gpgpu-sim_distribution && cd /home/runner/gpgpu-sim_simulations/ && git pull && /home/runner/gpgpu-sim_simulations/util/job_launching/run_simulations.py -C $CONFIG -B rodinia_2.0-ft -N regress && /home/runner/gpgpu-sim_simulations/util/job_launching/monitor_func_test.py -v -N regress'" diff --git a/CHANGES b/CHANGES index dbf5b39..60be885 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,34 @@ LOG: +Version 4.0.0 (development branch) versus 3.2.3 +-Front-End: +1- Support .nc cache modifier and __ldg function to access the read-only L1D cache +2- Partially-support some SASS_60 in the PTXP_PLUS (not completed yet) +-GPU Core: +1- Fermi/Pascal coalescer: coalescing on 32-bytes sectors. +2- Adding separate dp unit pipeline. +3- diff dual issue: allow scheduler to issue diff insts at a time +4- Fair memory issue from multiple schedulers. +-Cache System: +1- Sector L1/L2 cache +2- Fetch-on-write and lazy-fetch-on-read write allocation policy. +3- Improving the L1 cache throughput (streaming L1 cache) +4- Performance model for CUDA memory copy. +5- Support memory partition indexing to reduce partition camping (POLY, XOR and PAE (ISCA’18) Indexing) +6- Adaptive cache configuration +-Memory: +1- Performance Model for HBM (mainly the dual-bus interface) +2- Separate Read/Write buffers. +3- Advanced bank indexing function. +-Statistics: +1- Adding more detailed cache statistics to define and analyze cache bottlenecks. +2- Adding more detailed memory statistics (BLP, RBL, etc) to define and analyze memory bottlenecks. +3- Addig new system stats: gpu occupancy, L2BW, etc +-Configs: +Adding the Pascal and Volta config files that has been correlated against real hardware. +See the correlation website here: +https://engineering.purdue.edu/tgrogers/group/correlator.html + + Version 3.2.3+edits (development branch) versus 3.2.3 - Support for running regression tests using Travis - Support added for CUDA dynamic parallelism (courtesy of Jin Wang from Georgia Tech) diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000..1969aea --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,126 @@ +pipeline { + agent { + label "purdue-cluster" + } + + options { + disableConcurrentBuilds() + } + + stages { + stage('simulator-build') { + steps { + parallel "4.2": { + sh 'source /home/tgrogers-raid/a/common/gpgpu-sim-setup/4.2_env_setup.sh &&\ + source `pwd`/setup_environment &&\ + make -j' + }, "9.1" : { + sh 'source /home/tgrogers-raid/a/common/gpgpu-sim-setup/9.1_env_setup.sh &&\ + source `pwd`/setup_environment &&\ + make -j' + } + } + } + stage('simulations-build'){ + steps{ + sh 'rm -rf gpgpu-sim_simulations' + sh 'git clone git@github.rcac.purdue.edu:TimRogersGroup/gpgpu-sim_simulations.git && \ + cd gpgpu-sim_simulations && \ + git checkout purdue-cluster && \ + git pull && \ + ln -s /home/tgrogers-raid/a/common/data_dirs benchmarks/' + sh 'source /home/tgrogers-raid/a/common/gpgpu-sim-setup/4.2_env_setup.sh &&\ + source `pwd`/setup_environment &&\ + cd gpgpu-sim_simulations && \ + source ./benchmarks/src/setup_environment && \ + make -j -C ./benchmarks/src rodinia_2.0-ft sdk-4.2 && \ + make -C ./benchmarks/src data' + sh 'source /home/tgrogers-raid/a/common/gpgpu-sim-setup/9.1_env_setup.sh &&\ + source `pwd`/setup_environment &&\ + cd gpgpu-sim_simulations && \ + source ./benchmarks/src/setup_environment && \ + make -j -C ./benchmarks/src/ rodinia_2.0-ft sdk-4.2 && \ + make -C ./benchmarks/src data' + } + } + stage('regress'){ + steps { + parallel "4.2-rodinia": { + sh 'source /home/tgrogers-raid/a/common/gpgpu-sim-setup/4.2_env_setup.sh &&\ + source `pwd`/setup_environment &&\ + ./gpgpu-sim_simulations/util/job_launching/run_simulations.py -B rodinia_2.0-ft -C GTX480,GTX480-PTXPLUS -N regress-$$ && \ + PLOTDIR="jenkins/${JOB_NAME}/${BUILD_NUMBER}/4.2-rodinia" && ssh tgrogers@dynamo.ecn.purdue.edu mkdir -p /home/dynamo/a/tgrogers/website/gpgpu-sim-plots/$PLOTDIR && \ + ./gpgpu-sim_simulations/util/job_launching/monitor_func_test.py -v -N regress-$$ -s stats-per-app-4.2.csv && \ + ./gpgpu-sim_simulations/util/plotting/plot-get-stats.py -c stats-per-app-4.2.csv -p tgrogers@dynamo.ecn.purdue.edu:~/website/gpgpu-sim-plots/$PLOTDIR -w https://engineering.purdue.edu/tgrogers/gpgpu-sim-plots/$PLOTDIR -n $PLOTDIR ' + }, "9.1-functest": { + sh 'source /home/tgrogers-raid/a/common/gpgpu-sim-setup/9.1_env_setup.sh &&\ + source `pwd`/setup_environment &&\ + ./gpgpu-sim_simulations/util/job_launching/run_simulations.py -B rodinia_2.0-ft,sdk-4.2 -C TITANX,TITANX-L1ON -N regress-$$ && \ + PLOTDIR="jenkins/${JOB_NAME}/${BUILD_NUMBER}/9.1-rodinia" && ssh tgrogers@dynamo.ecn.purdue.edu mkdir -p /home/dynamo/a/tgrogers/website/gpgpu-sim-plots/$PLOTDIR && \ + ./gpgpu-sim_simulations/util/job_launching/monitor_func_test.py -v -s stats-per-app-9.1.csv -N regress-$$ && \ + ./gpgpu-sim_simulations/util/plotting/plot-get-stats.py -c stats-per-app-9.1.csv -p tgrogers@dynamo.ecn.purdue.edu:~/website/gpgpu-sim-plots/$PLOTDIR -w https://engineering.purdue.edu/tgrogers/gpgpu-sim-plots/$PLOTDIR -n $PLOTDIR' + } + } + } + stage('4.2-correlate'){ + steps { + sh 'source /home/tgrogers-raid/a/common/gpgpu-sim-setup/4.2_env_setup.sh &&\ + source `pwd`/setup_environment &&\ + PLOTDIR="jenkins/${JOB_NAME}" &&\ + ./gpgpu-sim_simulations/util/job_launching/get_stats.py -R -K -k -B rodinia_2.0-ft -C GTX480,GTX480-PTXPLUS > stats-per-kernel-4.2.csv &&\ + ./gpgpu-sim_simulations/util/plotting/correlate_and_publish.sh stats-per-kernel-4.2.csv $PLOTDIR ${BUILD_NUMBER}' + } + } + stage('9.1-correlate'){ + steps { + sh 'source /home/tgrogers-raid/a/common/gpgpu-sim-setup/9.1_env_setup.sh &&\ + source `pwd`/setup_environment &&\ + PLOTDIR="jenkins/${JOB_NAME}" &&\ + ./gpgpu-sim_simulations/util/job_launching/get_stats.py -R -K -k -B rodinia_2.0-ft,sdk-4.2 -C TITANX,TITANX-L1ON > stats-per-kernel-9.1.csv &&\ + ./gpgpu-sim_simulations/util/plotting/correlate_and_publish.sh stats-per-kernel-9.1.csv $PLOTDIR ${BUILD_NUMBER}' + } + } + stage('archive-and-delta') { + steps { + sh 'rm -rf gpgpu-sim-results-repo' + sh 'git clone git@github.com:purdue-aalp/gpgpu-sim-results-repo.git' + sh 'source /home/tgrogers-raid/a/common/gpgpu-sim-setup/4.2_env_setup.sh &&\ + ./gpgpu-sim_simulations/util/job_launching/get_stats.py -R -K -k -B rodinia_2.0-ft -C GTX480-PTXPLUS > stats-per-kernel-4.2-ptxplus.csv &&\ + ./gpgpu-sim_simulations/util/job_launching/get_stats.py -R -K -k -B rodinia_2.0-ft -C GTX480 > stats-per-kernel-4.2-ptx.csv' + sh 'source /home/tgrogers-raid/a/common/gpgpu-sim-setup/9.1_env_setup.sh &&\ + ./gpgpu-sim_simulations/util/job_launching/get_stats.py -R -K -k -B rodinia_2.0-ft,sdk-4.2 -C TITANX > stats-per-kernel-9.1-titanx.csv' + sh './gpgpu-sim_simulations/util/plotting/merge-stats.py -c ./gpgpu-sim-results-repo/jenkins/quick-regress/AALP/gpgpu-sim_distribution/dev-purdue-integration/stats-per-app-4.2.csv,./stats-per-app-4.2.csv -R > per-app-merge-4.2.csv' + sh './gpgpu-sim_simulations/util/plotting/merge-stats.py -c ./gpgpu-sim-results-repo/jenkins/quick-regress/AALP/gpgpu-sim_distribution/dev-purdue-integration/stats-per-app-9.1.csv,./stats-per-app-9.1.csv -R > per-app-merge-9.1.csv' + sh 'PLOTDIR="jenkins/${JOB_NAME}" &&\ + ./gpgpu-sim_simulations/util/plotting/plot-get-stats.py -c per-app-merge-4.2.csv -p tgrogers@dynamo.ecn.purdue.edu:~/website/gpgpu-sim-plots/$PLOTDIR/deltas -w https://engineering.purdue.edu/tgrogers/gpgpu-sim-plots/$PLOTDIR -n $PLOTDIR/deltas &&\ + ./gpgpu-sim_simulations/util/plotting/plot-get-stats.py -c per-app-merge-9.1.csv -p tgrogers@dynamo.ecn.purdue.edu:~/website/gpgpu-sim-plots/$PLOTDIR/deltas -w https://engineering.purdue.edu/tgrogers/gpgpu-sim-plots/$PLOTDIR/deltas -n $PLOTDIR/deltas &&\ + ./gpgpu-sim_simulations/util/plotting/merge-stats.py -c ./gpgpu-sim-results-repo/jenkins/quick-regress/AALP/gpgpu-sim_distribution/dev-purdue-integration/stats-per-kernel-4.2-ptx.csv,./stats-per-kernel-4.2-ptx.csv -R > per-kernel-merge-4.2-ptx.csv &&\ + ./gpgpu-sim_simulations/util/plotting/merge-stats.py -c ./gpgpu-sim-results-repo/jenkins/quick-regress/AALP/gpgpu-sim_distribution/dev-purdue-integration/stats-per-kernel-4.2-ptxplus.csv,./stats-per-kernel-4.2-ptxplus.csv -R > per-kernel-merge-4.2-ptxplus.csv &&\ + ./gpgpu-sim_simulations/util/plotting/merge-stats.py -c ./gpgpu-sim-results-repo/jenkins/quick-regress/AALP/gpgpu-sim_distribution/dev-purdue-integration/stats-per-kernel-9.1-titanx.csv,./stats-per-kernel-9.1-titanx.csv -R > per-kernel-merge-9.1-titanx.csv &&\ + ./gpgpu-sim_simulations/util/plotting/correlate_and_publish.sh per-kernel-merge-4.2-ptx.csv $PLOTDIR ${BUILD_NUMBER} &&\ + ./gpgpu-sim_simulations/util/plotting/correlate_and_publish.sh per-kernel-merge-4.2-ptxplus.csv $PLOTDIR ${BUILD_NUMBER} &&\ + ./gpgpu-sim_simulations/util/plotting/correlate_and_publish.sh per-kernel-merge-9.1-titanx.csv $PLOTDIR ${BUILD_NUMBER} &&\ + mkdir -p ./jenkins/quick-regress/${JOB_NAME}/ && cp stats-per-*.csv ./jenkins/quick-regress/${JOB_NAME}/ &&\ + cd ./gpgpu-sim-results-repo &&\ + git diff --quiet && git diff --staged --quiet || git commit -am "Jenkins automated checkin ${BUILD_NUMBER}" &&\ + git push' + } + } + } + post { + success { + emailext body: "See ${BUILD_URL}", + recipientProviders: [[$class: 'CulpritsRecipientProvider'], + [$class: 'RequesterRecipientProvider']], + subject: "[AALP Jenkins] Build #${BUILD_NUMBER} - Success!", + to: 'tgrogers@purdue.edu' + } + failure { + emailext body: "See ${BUILD_URL}", + recipientProviders: [[$class: 'CulpritsRecipientProvider'], + [$class: 'RequesterRecipientProvider']], + subject: "[AALP Jenkins] Build #${BUILD_NUMBER} - ${currentBuild.result}", + to: 'tgrogers@purdue.edu' + } + } +} diff --git a/README b/README index 6e2d734..7eaae5d 100644 --- a/README +++ b/README @@ -5,8 +5,8 @@ AerialVision and a configurable and extensible energy model called GPUWattch. GPGPU-Sim and GPUWattch have been rigorously validated with performance and power measurements of real hardware GPUs. -This version of GPGPU-Sim has been tested with CUDA version 2.3, 3.1, 4.0, -5.0, 5.5, 6.0 and 7.5. +This version of GPGPU-Sim has been tested with CUDA version 4.2, +5.0, 5.5, 6.0 and 7.5, 8.0, 9.0, 9.1 Please see the copyright notice in the file COPYRIGHT distributed with this release in the same directory as this file. @@ -18,6 +18,12 @@ Analyzing CUDA Workloads Using a Detailed GPU Simulator, in IEEE International Symposium on Performance Analysis of Systems and Software (ISPASS), Boston, MA, April 19-21, 2009. +If you use the memory system in GPGPU-Sim, or the Volta/Pascal models, +please cite: +Mahmoud Khairy, Jain Akshay, Tor Aamodt, Timothy G Rogers, +Exploring Modern GPU Memory System Design Challenges through Accurate Modeling, arXiv:1810.07269, +https://arxiv.org/abs/1810.07269 + If you use the GPUWattch energy model in your research, please cite: Jingwen Leng, Tayler Hetherington, Ahmed ElTantawy, Syed Gilani, Nam Sung Kim, diff --git a/aerialvision/organizedata.py b/aerialvision/organizedata.py index 090b90f..ea947cd 100644 --- a/aerialvision/organizedata.py +++ b/aerialvision/organizedata.py @@ -97,7 +97,7 @@ def organizedata(fileVars): 'sparse':OrganizeSparse, # Vector data with 2D index (used by DRAM access stats) 'custom':0 } - data_type_char = {int:'I', float:'f'} + data_type_char = {int:'L', float:'d'} print "Organizing data into internal format..." diff --git a/configs/GTX480/config_fermi_islip.icnt b/configs/GTX480/config_fermi_islip.icnt deleted file mode 100644 index 7820e4e..0000000 --- a/configs/GTX480/config_fermi_islip.icnt +++ /dev/null @@ -1,70 +0,0 @@ -//21*1 fly with 32 flits per packet under gpgpusim injection mode -use_map = 0; -flit_size = 32; - -// currently we do not use this, see subnets below -network_count = 2; - -// Topology -topology = fly; -k = 27; -n = 1; - -// Routing - -routing_function = dest_tag; - -// Flow control - -num_vcs = 1; -vc_buf_size = 8; - -wait_for_tail_credit = 0; - -// Router architecture - -vc_allocator = islip; //separable_input_first; -sw_allocator = islip; //separable_input_first; -alloc_iters = 1; - -credit_delay = 0; -routing_delay = 0; -vc_alloc_delay = 1; -sw_alloc_delay = 1; - -input_speedup = 2; -output_speedup = 1; -internal_speedup = 1.0; - -// Traffic, GPGPU-Sim does not use this - -traffic = uniform; -packet_size ={{1,2,3,4},{10,20}}; -packet_size_rate={{1,1,1,1},{2,1}}; - -// Simulation - Don't change - -sim_type = gpgpusim; -//sim_type = latency; -injection_rate = 0.1; - -subnets = 2; - -// Always use read and write no matter following line -//use_read_write = 1; - - -read_request_subnet = 0; -read_reply_subnet = 1; -write_request_subnet = 0; -write_reply_subnet = 1; - -read_request_begin_vc = 0; -read_request_end_vc = 0; -write_request_begin_vc = 0; -write_request_end_vc = 0; -read_reply_begin_vc = 0; -read_reply_end_vc = 0; -write_reply_begin_vc = 0; -write_reply_end_vc = 0; - diff --git a/configs/GTX480/gpgpusim.config b/configs/GTX480/gpgpusim.config deleted file mode 100644 index ee90c12..0000000 --- a/configs/GTX480/gpgpusim.config +++ /dev/null @@ -1,134 +0,0 @@ -# functional simulator specification --gpgpu_ptx_instruction_classification 0 --gpgpu_ptx_sim_mode 0 --gpgpu_ptx_force_max_capability 20 - - -# SASS execution (only supported with CUDA >= 4.0) --gpgpu_ptx_convert_to_ptxplus 0 --gpgpu_ptx_save_converted_ptxplus 0 - -# high level architecture configuration --gpgpu_n_clusters 15 --gpgpu_n_cores_per_cluster 1 --gpgpu_n_mem 6 --gpgpu_n_sub_partition_per_mchannel 2 - -# Fermi clock domains -#-gpgpu_clock_domains ::: -# In Fermi, each pipeline has 16 execution units, so the Core clock needs to be divided -# by 2. (GPGPU-Sim simulates a warp (32 threads) in a single cycle). 1400/2 = 700 --gpgpu_clock_domains 700.0:700.0:700.0:924.0 - -# shader core pipeline config --gpgpu_shader_registers 32768 --gpgpu_occupancy_sm_number 20 - -# This implies a maximum of 48 warps/SM --gpgpu_shader_core_pipeline 1536:32 --gpgpu_shader_cta 8 --gpgpu_simd_model 1 - -# Pipeline widths and number of FUs -# ID_OC_SP,ID_OC_SFU,ID_OC_MEM,OC_EX_SP,OC_EX_SFU,OC_EX_MEM,EX_WB --gpgpu_pipeline_widths 2,1,1,2,1,1,2 --gpgpu_num_sp_units 2 --gpgpu_num_sfu_units 1 - -# Instruction latencies and initiation intervals -# "ADD,MAX,MUL,MAD,DIV" --ptx_opcode_latency_int 4,13,4,5,145 --ptx_opcode_initiation_int 1,2,2,1,8 --ptx_opcode_latency_fp 4,13,4,5,39 --ptx_opcode_initiation_fp 1,2,1,1,4 --ptx_opcode_latency_dp 8,19,8,8,330 --ptx_opcode_initiation_dp 8,16,8,8,130 - - -# In Fermi, the cache and shared memory can be configured to 16kb:48kb(default) or 48kb:16kb -# ::,::::,::,:** -# ** Optional parameter - Required when mshr_type==Texture Fifo -# Note: Hashing set index function (H) only applies to a set size of 32 or 64. --gpgpu_cache:dl1 32:128:4,L:L:m:N:H,A:32:8,8 --gpgpu_shmem_size 49152 - -# The alternative configuration for fermi in case cudaFuncCachePreferL1 is selected -#-gpgpu_cache:dl1 64:128:6,L:L:m:N:H,A:32:8,8 -#-gpgpu_shmem_size 16384 - -# 64 sets, each 128 bytes 8-way for each memory sub partition. This gives 786KB L2 cache --gpgpu_cache:dl2 64:128:8,L:B:m:W:L,A:32:4,4:0,32 --gpgpu_cache:dl2_texture_only 0 - --gpgpu_cache:il1 4:128:4,L:R:f:N:L,A:2:32,4 --gpgpu_tex_cache:l1 4:128:24,L:R:m:N:L,F:128:4,128:2 --gpgpu_const_cache:l1 64:64:2,L:R:f:N:L,A:2:32,4 - -# enable operand collector --gpgpu_operand_collector_num_units_sp 6 --gpgpu_operand_collector_num_units_sfu 8 --gpgpu_operand_collector_num_in_ports_sp 2 --gpgpu_operand_collector_num_out_ports_sp 2 --gpgpu_num_reg_banks 16 - -# shared memory bankconflict detection --gpgpu_shmem_num_banks 32 --gpgpu_shmem_limited_broadcast 0 --gpgpu_shmem_warp_parts 1 - --gpgpu_max_insn_issue_per_warp 1 - -# interconnection --network_mode 1 --inter_config_file config_fermi_islip.icnt - -# memory partition latency config --rop_latency 120 --dram_latency 100 - -# dram model config --gpgpu_dram_scheduler 1 -# The DRAM return queue and the scheduler queue together should provide buffer -# to sustain the memory level parallelism to tolerate DRAM latency -# To allow 100% DRAM utility, there should at least be enough buffer to sustain -# the minimum DRAM latency (100 core cycles). I.e. -# Total buffer space required = 100 x 924MHz / 700MHz = 132 --gpgpu_frfcfs_dram_sched_queue_size 16 --gpgpu_dram_return_queue_size 116 - -# for Fermi, bus width is 384bits, this is 8 bytes (4 bytes at each DRAM chip) per memory partition --gpgpu_n_mem_per_ctrlr 2 --gpgpu_dram_buswidth 4 --gpgpu_dram_burst_length 8 --dram_data_command_freq_ratio 4 # GDDR5 is QDR --gpgpu_mem_address_mask 1 --gpgpu_mem_addr_mapping dramid@8;00000000.00000000.00000000.00000000.0000RRRR.RRRRRRRR.BBBCCCCB.CCSSSSSS - -# GDDR5 timing from hynix H5GQ1H24AFR -# to disable bank groups, set nbkgrp to 1 and tCCDL and tRTPL to 0 --gpgpu_dram_timing_opt "nbk=16:CCD=2:RRD=6:RCD=12:RAS=28:RP=12:RC=40: - CL=12:WL=4:CDLR=5:WR=12:nbkgrp=4:CCDL=3:RTPL=2" - -# Fermi has two schedulers per core --gpgpu_num_sched_per_core 2 -# Two Level Scheduler with active and pending pools -#-gpgpu_scheduler two_level_active:6:0:1 -# Loose round robbin scheduler -#-gpgpu_scheduler lrr -# Greedy then oldest scheduler --gpgpu_scheduler gto - -# stat collection --gpgpu_memlatency_stat 14 --gpgpu_runtime_stat 500 --enable_ptx_file_line_stats 1 --visualizer_enabled 0 - -# power model configs --power_simulation_enabled 1 --gpuwattch_xml_file gpuwattch_gtx480.xml - -# tracing functionality -#-trace_enabled 1 -#-trace_components WARP_SCHEDULER,SCOREBOARD -#-trace_sampling_core 0 diff --git a/configs/GTX480/gpuwattch_gtx480.xml b/configs/GTX480/gpuwattch_gtx480.xml deleted file mode 100755 index 304e0fd..0000000 --- a/configs/GTX480/gpuwattch_gtx480.xml +++ /dev/null @@ -1,538 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/configs/GeForceGTX1080Ti/config_fermi_islip.icnt b/configs/GeForceGTX1080Ti/config_fermi_islip.icnt deleted file mode 100644 index 2a69ddd..0000000 --- a/configs/GeForceGTX1080Ti/config_fermi_islip.icnt +++ /dev/null @@ -1,70 +0,0 @@ -//21*1 fly with 32 flits per packet under gpgpusim injection mode -use_map = 0; -flit_size = 32; - -// currently we do not use this, see subnets below -network_count = 2; - -// Topology -topology = fly; -k = 50; -n = 1; - -// Routing - -routing_function = dest_tag; - -// Flow control - -num_vcs = 1; -vc_buf_size = 8; - -wait_for_tail_credit = 0; - -// Router architecture - -vc_allocator = islip; //separable_input_first; -sw_allocator = islip; //separable_input_first; -alloc_iters = 1; - -credit_delay = 0; -routing_delay = 0; -vc_alloc_delay = 1; -sw_alloc_delay = 1; - -input_speedup = 2; -output_speedup = 1; -internal_speedup = 1.0; - -// Traffic, GPGPU-Sim does not use this - -traffic = uniform; -packet_size ={{1,2,3,4},{10,20}}; -packet_size_rate={{1,1,1,1},{2,1}}; - -// Simulation - Don't change - -sim_type = gpgpusim; -//sim_type = latency; -injection_rate = 0.1; - -subnets = 2; - -// Always use read and write no matter following line -//use_read_write = 1; - - -read_request_subnet = 0; -read_reply_subnet = 1; -write_request_subnet = 0; -write_reply_subnet = 1; - -read_request_begin_vc = 0; -read_request_end_vc = 0; -write_request_begin_vc = 0; -write_request_end_vc = 0; -read_reply_begin_vc = 0; -read_reply_end_vc = 0; -write_reply_begin_vc = 0; -write_reply_end_vc = 0; - diff --git a/configs/GeForceGTX1080Ti/gpgpusim.config b/configs/GeForceGTX1080Ti/gpgpusim.config deleted file mode 100644 index fb044c6..0000000 --- a/configs/GeForceGTX1080Ti/gpgpusim.config +++ /dev/null @@ -1,150 +0,0 @@ -# This config models the Pascal GP102 (GeForceGTX 1080Ti) - -# functional simulator specification --gpgpu_ptx_instruction_classification 0 --gpgpu_ptx_sim_mode 0 --gpgpu_ptx_force_max_capability 60 - -# SASS execution (only supported with CUDA >= 4.0) --gpgpu_ptx_convert_to_ptxplus 0 --gpgpu_ptx_save_converted_ptxplus 0 - -# high level architecture configuration --gpgpu_n_clusters 28 --gpgpu_n_cores_per_cluster 1 --gpgpu_n_mem 11 --gpgpu_n_sub_partition_per_mchannel 2 - -# Pascal clock domains -#-gpgpu_clock_domains ::: -# Pascal NVIDIA TITAN X clock domains are adopted from -# https://en.wikipedia.org/wiki/GeForce_10_series --gpgpu_clock_domains 1481.0:2962.0:1481.0:2750.0 - -# shader core pipeline config --gpgpu_shader_registers 65536 --gpgpu_occupancy_sm_number 60 - -# This implies a maximum of 64 warps/SM --gpgpu_shader_core_pipeline 2048:32 --gpgpu_shader_cta 32 --gpgpu_simd_model 1 - -# Pipeline widths and number of FUs -# ID_OC_SP,ID_OC_SFU,ID_OC_MEM,OC_EX_SP,OC_EX_SFU,OC_EX_MEM,EX_WB -## Pascal GP102 has 4 SP SIMD units and 1 SFU unit -## we need to scale the number of pipeline registers to be equal to the number of SP units --gpgpu_pipeline_widths 4,1,1,4,1,1,6 --gpgpu_num_sp_units 4 --gpgpu_num_sfu_units 1 - -# Instruction latencies and initiation intervals -# "ADD,MAX,MUL,MAD,DIV" -# SFU is 32-width in pascal, then dp units initiation is 1 cycle --ptx_opcode_latency_int 4,13,4,5,145 --ptx_opcode_initiation_int 1,2,2,2,8 --ptx_opcode_latency_fp 4,13,4,5,39 --ptx_opcode_initiation_fp 1,2,1,1,4 --ptx_opcode_latency_dp 8,19,8,8,330 --ptx_opcode_initiation_dp 1,2,1,1,130 - -# ::,::::,::,:** -# ** Optional parameter - Required when mshr_type==Texture Fifo -# Note: Hashing set index function (H) only applies to a set size of 32 or 64. -# Pascal GP102 has 96KB Shared memory -# Pascal GP102 has 64KB L1 cache -# The default is to disable the L1 cache, unless cache modifieres is used --gpgpu_cache:dl1 64:128:6,L:L:m:N:H,A:128:8,8 --gpgpu_shmem_size 98304 --gmem_skip_L1D 1 - -# 64 sets, each 128 bytes 16-way for each memory sub partition (128 KB per memory sub partition). This gives 3MB L2 cache --gpgpu_cache:dl2 64:128:16,L:B:m:W:L,A:1024:1024,4:0,32 # used to be 128:4 --gpgpu_cache:dl2_texture_only 0 - -# 4 KB Inst. --gpgpu_cache:il1 8:128:4,L:R:f:N:L,A:2:48,4 -# 48 KB Tex --gpgpu_tex_cache:l1 16:128:24,L:R:m:N:L,F:128:4,128:2 -# 12 KB Const --gpgpu_const_cache:l1 128:64:2,L:R:f:N:L,A:2:64,4 - -# enable operand collector -## larger operand collectors and reg_banks are needed for the 4 warp schedulers and 4 SIMD units --gpgpu_operand_collector_num_units_sp 20 --gpgpu_operand_collector_num_units_sfu 4 --gpgpu_operand_collector_num_units_mem 8 --gpgpu_operand_collector_num_in_ports_sp 4 --gpgpu_operand_collector_num_out_ports_sp 4 --gpgpu_operand_collector_num_in_ports_sfu 1 --gpgpu_operand_collector_num_out_ports_sfu 1 --gpgpu_operand_collector_num_in_ports_mem 1 --gpgpu_operand_collector_num_out_ports_mem 1 -# gpgpu_num_reg_banks should be increased to 32, but it gives an error! --gpgpu_num_reg_banks 32 - -# shared memory bankconflict detection --gpgpu_shmem_num_banks 32 --gpgpu_shmem_limited_broadcast 0 --gpgpu_shmem_warp_parts 1 - -## In Pascal, a warp scheduler can issue 2 insts per cycle --gpgpu_max_insn_issue_per_warp 2 - -# interconnection --network_mode 1 --inter_config_file config_fermi_islip.icnt - -# memory partition latency config --rop_latency 120 --dram_latency 100 - -# dram model config --gpgpu_dram_scheduler 1 -# The DRAM return queue and the scheduler queue together should provide buffer -# to sustain the memory level parallelism to tolerate DRAM latency -# To allow 100% DRAM utility, there should at least be enough buffer to sustain -# the minimum DRAM latency (100 core cycles). I.e. -# Total buffer space required = 100 x 924MHz / 700MHz = 132 --gpgpu_frfcfs_dram_sched_queue_size 64 --gpgpu_dram_return_queue_size 116 - -# for NVIDIA GeForceGTX 1080Ti, bus width is 352bits (11 DRAM chips x 32 bits) -# 11 memory paritions, 4 bytes (1 DRAM chip) per memory partition -# the atom size of GDDR5X (the smallest read request) is 32 bytes --gpgpu_n_mem_per_ctrlr 1 --gpgpu_dram_buswidth 4 --gpgpu_dram_burst_length 8 --dram_data_command_freq_ratio 4 # GDDR5X is QDR --gpgpu_mem_address_mask 1 --gpgpu_mem_addr_mapping dramid@8;00000000.00000000.00000000.00000000.0000RRRR.RRRRRRRR.RBBBCCCC.BCCSSSSS - -# Use the same GDDR5 timing from hynix H5GQ1H24AFR -# disable bank groups for now, set nbkgrp to 1 and tCCDL and tRTPL to 0 --gpgpu_dram_timing_opt "nbk=16:CCD=2:RRD=6:RCD=12:RAS=28:RP=12:RC=40: - CL=12:WL=4:CDLR=5:WR=12:nbkgrp=1:CCDL=0:RTPL=0" - -# Pascal has four schedulers per core --gpgpu_num_sched_per_core 2 -# Two Level Scheduler with active and pending pools -#-gpgpu_scheduler two_level_active:6:0:1 -# Loose round robbin scheduler -#-gpgpu_scheduler lrr -# Greedy then oldest scheduler --gpgpu_scheduler gto - -# stat collection --gpgpu_memlatency_stat 14 --gpgpu_runtime_stat 500 --enable_ptx_file_line_stats 1 --visualizer_enabled 0 - -# power model configs --power_simulation_enabled 1 --gpuwattch_xml_file gpuwattch_gtx1080Ti.xml - -# tracing functionality -#-trace_enabled 1 -#-trace_components WARP_SCHEDULER,SCOREBOARD -#-trace_sampling_core 0 - diff --git a/configs/GeForceGTX1080Ti/gpuwattch_gtx1080Ti.xml b/configs/GeForceGTX1080Ti/gpuwattch_gtx1080Ti.xml deleted file mode 100755 index 02619ff..0000000 --- a/configs/GeForceGTX1080Ti/gpuwattch_gtx1080Ti.xml +++ /dev/null @@ -1,538 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/configs/GeForceGTX750Ti/config_fermi_islip.icnt b/configs/GeForceGTX750Ti/config_fermi_islip.icnt deleted file mode 100644 index 069ca02..0000000 --- a/configs/GeForceGTX750Ti/config_fermi_islip.icnt +++ /dev/null @@ -1,70 +0,0 @@ -//21*1 fly with 32 flits per packet under gpgpusim injection mode -use_map = 0; -flit_size = 32; - -// currently we do not use this, see subnets below -network_count = 2; - -// Topology -topology = fly; -k = 7; -n = 1; - -// Routing - -routing_function = dest_tag; - -// Flow control - -num_vcs = 1; -vc_buf_size = 8; - -wait_for_tail_credit = 0; - -// Router architecture - -vc_allocator = islip; //separable_input_first; -sw_allocator = islip; //separable_input_first; -alloc_iters = 1; - -credit_delay = 0; -routing_delay = 0; -vc_alloc_delay = 1; -sw_alloc_delay = 1; - -input_speedup = 2; -output_speedup = 1; -internal_speedup = 1.0; - -// Traffic, GPGPU-Sim does not use this - -traffic = uniform; -packet_size ={{1,2,3,4},{10,20}}; -packet_size_rate={{1,1,1,1},{2,1}}; - -// Simulation - Don't change - -sim_type = gpgpusim; -//sim_type = latency; -injection_rate = 0.1; - -subnets = 2; - -// Always use read and write no matter following line -//use_read_write = 1; - - -read_request_subnet = 0; -read_reply_subnet = 1; -write_request_subnet = 0; -write_reply_subnet = 1; - -read_request_begin_vc = 0; -read_request_end_vc = 0; -write_request_begin_vc = 0; -write_request_end_vc = 0; -read_reply_begin_vc = 0; -read_reply_end_vc = 0; -write_reply_begin_vc = 0; -write_reply_end_vc = 0; - diff --git a/configs/GeForceGTX750Ti/gpgpusim.config b/configs/GeForceGTX750Ti/gpgpusim.config deleted file mode 100644 index c675aab..0000000 --- a/configs/GeForceGTX750Ti/gpgpusim.config +++ /dev/null @@ -1,131 +0,0 @@ -# functional simulator specification --gpgpu_ptx_instruction_classification 0 --gpgpu_ptx_sim_mode 0 --gpgpu_ptx_force_max_capability 52 - - -# SASS execution (only supported with CUDA >= 4.0) --gpgpu_ptx_convert_to_ptxplus 0 --gpgpu_ptx_save_converted_ptxplus 0 - -# high level architecture configuration --gpgpu_n_clusters 5 --gpgpu_n_cores_per_cluster 1 --gpgpu_n_mem 2 --gpgpu_n_sub_partition_per_mchannel 1 - -# Maxwell clock domains -#-gpgpu_clock_domains ::: -# In Maxwell, each pipeline has 32 execution units, so the Core clock is just the reported number. --gpgpu_clock_domains 1137.0:1137.0:1137.0:2700.0 - -# shader core pipeline config --gpgpu_shader_registers 65536 --gpgpu_occupancy_sm_number 52 - -# This implies a maximum of 64 warps/SM --gpgpu_shader_core_pipeline 2048:32 --gpgpu_shader_cta 8 --gpgpu_simd_model 1 - -# Pipeline widths and number of FUs -# ID_OC_SP,ID_OC_SFU,ID_OC_MEM,OC_EX_SP,OC_EX_SFU,OC_EX_MEM,EX_WB --gpgpu_pipeline_widths 2,1,1,2,1,1,2 --gpgpu_num_sp_units 8 --gpgpu_num_sfu_units 32 - -# Instruction latencies and initiation intervals -# "ADD,MAX,MUL,MAD,DIV" --ptx_opcode_latency_int 6,12,13,13,210 --ptx_opcode_initiation_int 1,1,1,1,4 --ptx_opcode_latency_fp 6,12,6,6,374 --ptx_opcode_initiation_fp 1,1,1,1,4 --ptx_opcode_latency_dp 8,19,8,8,330 --ptx_opcode_initiation_dp 8,16,8,8,130 - --gpgpu_cache:dl1 32:128:4,L:L:m:N:H,A:32:8,8 --gmem_skip_L1D 1 --gpgpu_shmem_size 65536 - -# The alternative configuration for fermi in case cudaFuncCachePreferL1 is selected -#-gpgpu_cache:dl1 64:128:6,L:L:m:N:H,A:32:8,8 -#-gpgpu_shmem_size 16384 - -# 1024 sets, each 128 bytes 8-way for each memory sub partition. This gives 2MB L2 cache --gpgpu_cache:dl2 1024:128:8,L:B:m:W:L,A:32:4,4:0,32 --gpgpu_cache:dl2_texture_only 0 - --gpgpu_cache:il1 4:128:4,L:R:f:N:L,A:2:32,4 --gpgpu_tex_cache:l1 16:128:32,L:R:m:N:L,F:128:4,128:2 --gpgpu_const_cache:l1 64:64:2,L:R:f:N:L,A:2:32,4 - -# enable operand collector --gpgpu_operand_collector_num_units_sp 6 --gpgpu_operand_collector_num_units_sfu 8 --gpgpu_operand_collector_num_in_ports_sp 2 --gpgpu_operand_collector_num_out_ports_sp 2 --gpgpu_num_reg_banks 16 - -# shared memory bankconflict detection --gpgpu_shmem_num_banks 32 --gpgpu_shmem_limited_broadcast 0 --gpgpu_shmem_warp_parts 1 - --gpgpu_max_insn_issue_per_warp 2 - -# interconnection --network_mode 1 --inter_config_file config_fermi_islip.icnt - -# memory partition latency config --rop_latency 150 --dram_latency 130 - -# dram model config --gpgpu_dram_scheduler 1 -# The DRAM return queue and the scheduler queue together should provide buffer -# to sustain the memory level parallelism to tolerate DRAM latency -# To allow 100% DRAM utility, there should at least be enough buffer to sustain -# the minimum DRAM latency (100 core cycles). I.e. -# Total buffer space required = 100 x 924MHz / 700MHz = 132 --gpgpu_frfcfs_dram_sched_queue_size 16 --gpgpu_dram_return_queue_size 300 - -# for Maxwell, bus width is 128bits, this is 64 bytes (32 bytes at each DRAM chip) per memory partition --gpgpu_n_mem_per_ctrlr 2 --gpgpu_dram_buswidth 32 --gpgpu_dram_burst_length 8 --dram_data_command_freq_ratio 4 # GDDR5 is QDR --gpgpu_mem_address_mask 1 --gpgpu_mem_addr_mapping dramid@8;00000000.00000000.00000000.00000000.0000RRRR.RRRRRRRR.BBBCCCCB.CCSSSSSS - -# GDDR5 timing from hynix H5GQ1H24AFR -# to disable bank groups, set nbkgrp to 1 and tCCDL and tRTPL to 0 --gpgpu_dram_timing_opt "nbk=16:CCD=2:RRD=6:RCD=12:RAS=28:RP=12:RC=40: - CL=12:WL=4:CDLR=5:WR=12:nbkgrp=4:CCDL=3:RTPL=2" - -# Maxwell has four schedulers per core --gpgpu_num_sched_per_core 4 -# Two Level Scheduler with active and pending pools -#-gpgpu_scheduler two_level_active:6:0:1 -# Loose round robbin scheduler -#-gpgpu_scheduler lrr -# Greedy then oldest scheduler --gpgpu_scheduler gto - -# stat collection --gpgpu_memlatency_stat 14 --gpgpu_runtime_stat 500 --enable_ptx_file_line_stats 1 --visualizer_enabled 0 - -# power model configs -# power modeling is currently disabled for GTX750Ti. The gpuwattch_gtx750ti.xml file present is only a placeholder and has NOT been tested for accuracy. -# proper modeling of Maxwell power is planned, but should be considered completely unsupported at present. --power_simulation_enabled 0 --gpuwattch_xml_file gpuwattch_gtx750Ti.xml - -# tracing functionality -#-trace_enabled 1 -#-trace_components WARP_SCHEDULER,SCOREBOARD -#-trace_sampling_core 0 diff --git a/configs/GeForceGTX750Ti/gpuwattch_gtx750Ti.xml b/configs/GeForceGTX750Ti/gpuwattch_gtx750Ti.xml deleted file mode 100755 index e2b2324..0000000 --- a/configs/GeForceGTX750Ti/gpuwattch_gtx750Ti.xml +++ /dev/null @@ -1,539 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/configs/Pascal_TITANX/config_fermi_islip.icnt b/configs/Pascal_TITANX/config_fermi_islip.icnt deleted file mode 100644 index 602daee..0000000 --- a/configs/Pascal_TITANX/config_fermi_islip.icnt +++ /dev/null @@ -1,70 +0,0 @@ -//21*1 fly with 32 flits per packet under gpgpusim injection mode -use_map = 0; -flit_size = 32; - -// currently we do not use this, see subnets below -network_count = 2; - -// Topology -topology = fly; -k = 52; -n = 1; - -// Routing - -routing_function = dest_tag; - -// Flow control - -num_vcs = 1; -vc_buf_size = 8; - -wait_for_tail_credit = 0; - -// Router architecture - -vc_allocator = islip; //separable_input_first; -sw_allocator = islip; //separable_input_first; -alloc_iters = 1; - -credit_delay = 0; -routing_delay = 0; -vc_alloc_delay = 1; -sw_alloc_delay = 1; - -input_speedup = 2; -output_speedup = 1; -internal_speedup = 1.0; - -// Traffic, GPGPU-Sim does not use this - -traffic = uniform; -packet_size ={{1,2,3,4},{10,20}}; -packet_size_rate={{1,1,1,1},{2,1}}; - -// Simulation - Don't change - -sim_type = gpgpusim; -//sim_type = latency; -injection_rate = 0.1; - -subnets = 2; - -// Always use read and write no matter following line -//use_read_write = 1; - - -read_request_subnet = 0; -read_reply_subnet = 1; -write_request_subnet = 0; -write_reply_subnet = 1; - -read_request_begin_vc = 0; -read_request_end_vc = 0; -write_request_begin_vc = 0; -write_request_end_vc = 0; -read_reply_begin_vc = 0; -read_reply_end_vc = 0; -write_reply_begin_vc = 0; -write_reply_end_vc = 0; - diff --git a/configs/Pascal_TITANX/gpgpusim.config b/configs/Pascal_TITANX/gpgpusim.config deleted file mode 100644 index f78bd02..0000000 --- a/configs/Pascal_TITANX/gpgpusim.config +++ /dev/null @@ -1,156 +0,0 @@ -# This config models the Pascal GP102 (NVIDIA TITAN X) -# For more info about this card, see Nvidia White paper -# http://international.download.nvidia.com/geforce-com/international/pdfs/GeForce_GTX_1080_Whitepaper_FINAL.pdf - -# functional simulator specification --gpgpu_ptx_instruction_classification 0 --gpgpu_ptx_sim_mode 0 --gpgpu_ptx_force_max_capability 61 - -# SASS execution (only supported with CUDA >= 4.0) --gpgpu_ptx_convert_to_ptxplus 0 --gpgpu_ptx_save_converted_ptxplus 0 - -# high level architecture configuration --gpgpu_n_clusters 28 --gpgpu_n_cores_per_cluster 1 --gpgpu_n_mem 12 --gpgpu_n_sub_partition_per_mchannel 2 - -# Pascal clock domains -#-gpgpu_clock_domains ::: -# Pascal NVIDIA TITAN X clock domains are adopted from -# https://en.wikipedia.org/wiki/GeForce_10_series --gpgpu_clock_domains 1417.0:1417.0:1417.0:2500.0 - -# shader core pipeline config --gpgpu_shader_registers 65536 - -# This implies a maximum of 64 warps/SM --gpgpu_shader_core_pipeline 2048:32 --gpgpu_shader_cta 32 --gpgpu_simd_model 1 - -# Pipeline widths and number of FUs -# ID_OC_SP,ID_OC_DP,ID_OC_SFU,ID_OC_MEM,OC_EX_SP,OC_EX_DP,OC_EX_SFU,OC_EX_MEM,EX_WB -## Pascal GP102 has 4 SP SIMD units and 1 SFU unit -## we need to scale the number of pipeline registers to be equal to the number of SP units --gpgpu_pipeline_widths 4,1,1,4,1,1,6 --gpgpu_num_sp_units 4 --gpgpu_num_sfu_units 1 - -# Instruction latencies and initiation intervals -# "ADD,MAX,MUL,MAD,DIV" -# SFU is 32-width in pascal, then dp units initiation is 1 cycle --ptx_opcode_latency_int 4,13,4,5,145 --ptx_opcode_initiation_int 1,1,1,1,4 --ptx_opcode_latency_fp 4,13,4,5,39 --ptx_opcode_initiation_fp 1,2,1,1,4 --ptx_opcode_latency_dp 8,19,8,8,330 --ptx_opcode_initiation_dp 4,8,4,4,130 - -# ::,::::,::,:** -# ** Optional parameter - Required when mshr_type==Texture Fifo -# Note: Hashing set index function (H) only applies to a set size of 32 or 64. -# Pascal GP102 has 96KB Shared memory -# Pascal GP102 has 64KB L1 cache -# The defulat is to disable the L1 cache, unless cache modifieres is used --gpgpu_cache:dl1 64:128:6,L:L:m:N:H,A:128:8,16 --gpgpu_cache:dl1PrefL1 64:128:6,L:L:m:N:H,A:128:8,16 --gpgpu_cache:dl1PrefShared 64:128:6,L:L:m:N:H,A:128:8,16 --gpgpu_shmem_size 98304 --gpgpu_shmem_size_PrefL1 98304 --gpgpu_shmem_size_PrefShared 98304 --gmem_skip_L1D 1 - -# 64 sets, each 128 bytes 16-way for each memory sub partition (128 KB per memory sub partition). This gives 3MB L2 cache --gpgpu_cache:dl2 64:128:16,L:B:m:W:L,A:128:8,4:0,32 --gpgpu_cache:dl2_texture_only 0 --gpgpu_dram_partition_queues 32:32:32:32 - -# 4 KB Inst. --gpgpu_cache:il1 8:128:4,L:R:f:N:L,A:2:48,4 -# 48 KB Tex --gpgpu_tex_cache:l1 16:128:24,L:R:m:N:L,F:128:4,128:2 -# 12 KB Const --gpgpu_const_cache:l1 128:64:2,L:R:f:N:L,A:2:64,4 - -# enable operand collector -## larger operand collectors and reg_banks are needed for the 4 warp schedulers and 4 SIMD units --gpgpu_operand_collector_num_units_sp 20 --gpgpu_operand_collector_num_units_sfu 4 --gpgpu_operand_collector_num_units_mem 8 --gpgpu_operand_collector_num_in_ports_sp 4 --gpgpu_operand_collector_num_out_ports_sp 4 --gpgpu_operand_collector_num_in_ports_sfu 1 --gpgpu_operand_collector_num_out_ports_sfu 1 --gpgpu_operand_collector_num_in_ports_mem 1 --gpgpu_operand_collector_num_out_ports_mem 1 -# gpgpu_num_reg_banks should be increased to 32 --gpgpu_num_reg_banks 32 - -# shared memory bankconflict detection --gpgpu_shmem_num_banks 32 --gpgpu_shmem_limited_broadcast 0 --gpgpu_shmem_warp_parts 1 - -## In Pascal, a warp scheduler can issue 2 insts per cycle --gpgpu_max_insn_issue_per_warp 2 - -# interconnection --network_mode 1 --inter_config_file config_fermi_islip.icnt - -# memory partition latency config --rop_latency 120 --dram_latency 100 - -# dram model config --gpgpu_dram_scheduler 1 -# The DRAM return queue and the scheduler queue together should provide buffer -# to sustain the memory level parallelism to tolerate DRAM latency -# To allow 100% DRAM utility, there should at least be enough buffer to sustain -# the minimum DRAM latency (100 core cycles). I.e. -# Total buffer space required = 100 x 924MHz / 700MHz = 132 --gpgpu_frfcfs_dram_sched_queue_size 64 --gpgpu_dram_return_queue_size 116 - -# for NVIDIA TITAN X, bus width is 384bits (12 DRAM chips x 32 bits) -# 12 memory paritions, 4 bytes (1 DRAM chip) per memory partition -# the atom size of GDDR5X (the smallest read request) is 32 bytes --gpgpu_n_mem_per_ctrlr 1 --gpgpu_dram_buswidth 4 --gpgpu_dram_burst_length 8 --dram_data_command_freq_ratio 4 # GDDR5X is QDR --gpgpu_mem_address_mask 1 --gpgpu_mem_addr_mapping dramid@8;00000000.00000000.00000000.00000000.0000RRRR.RRRRRRRR.RBBBCCCC.BCCSSSSS - -# Use the same GDDR5 timing from hynix H5GQ1H24AFR -# disable bank groups for now, set nbkgrp to 1 and tCCDL and tRTPL to 0 --gpgpu_dram_timing_opt "nbk=16:CCD=2:RRD=6:RCD=12:RAS=28:RP=12:RC=40: - CL=12:WL=4:CDLR=5:WR=12:nbkgrp=1:CCDL=0:RTPL=0" - -# Fermi has two schedulers per core --gpgpu_num_sched_per_core 4 -# Two Level Scheduler with active and pending pools -#-gpgpu_scheduler two_level_active:6:0:1 -# Loose round robbin scheduler -#-gpgpu_scheduler lrr -# Greedy then oldest scheduler --gpgpu_scheduler gto - -# stat collection --gpgpu_memlatency_stat 14 --gpgpu_runtime_stat 500 --enable_ptx_file_line_stats 1 --visualizer_enabled 0 - -# power model configs --power_simulation_enabled 1 --gpuwattch_xml_file gpuwattch_gtx480.xml - -# tracing functionality -#-trace_enabled 1 -#-trace_components WARP_SCHEDULER,SCOREBOARD -#-trace_sampling_core 0 - diff --git a/configs/QuadroFX5600/gpgpusim.config b/configs/QuadroFX5600/gpgpusim.config deleted file mode 100644 index 6f836ee..0000000 --- a/configs/QuadroFX5600/gpgpusim.config +++ /dev/null @@ -1,99 +0,0 @@ -# functional simulator specification --gpgpu_ptx_instruction_classification 0 --gpgpu_ptx_sim_mode 0 --gpgpu_ptx_force_max_capability 12 - -# high level architecture configuration --gpgpu_n_clusters 8 --gpgpu_n_cores_per_cluster 2 --gpgpu_n_mem 6 --gpgpu_clock_domains 337.5:600.0:600.0:800.0 - -# shader core pipeline config --gpgpu_shader_registers 16384 --gpgpu_occupancy_sm_number 12 - --gpgpu_occupancy_sm_number 12 -#8192 (registers per block as written by device Query and which used in this option in our other configurations but this break some benchmarks execution! it does not affect performance modeling though) --gpgpu_shader_core_pipeline 768:32 --gpgpu_shader_cta 8 --gpgpu_simd_model 1 - -# Pipeline widths and number of FUs -# ID_OC_SP,ID_OC_SFU,ID_OC_MEM,OC_EX_SP,OC_EX_SFU,OC_EX_MEM,EX_WB --gpgpu_pipeline_widths 1,1,1,1,1,1,1 --gpgpu_num_sp_units 1 --gpgpu_num_sfu_units 1 - -# Instruction latencies and initiation intervals -# "ADD,MAX,MUL,MAD,DIV" --ptx_opcode_latency_int 1,1,19,25,145 --ptx_opcode_initiation_int 1,1,4,4,32 --ptx_opcode_latency_fp 1,1,1,1,30 --ptx_opcode_initiation_fp 1,1,1,1,5 --ptx_opcode_latency_dp 8,8,8,8,335 --ptx_opcode_initiation_dp 8,8,8,8,130 - -# memory stage behaviour --gpgpu_cache:il1 4:256:4,L:R:f:N:L,A:2:32,4 --gpgpu_tex_cache:l1 8:128:5,L:R:m:N:L,F:128:4,128:2 --gpgpu_const_cache:l1 64:64:2,L:R:f:N:L,A:2:32,4 --gpgpu_cache:dl2 16:256:8,L:B:m:W:L,A:16:4,4 --gpgpu_cache:dl2_texture_only 1 - -# TLB parameters -#-gpgpu_cache:tlbl1 1:524288:16:1:L:R:m,A:32:8,8 -#-gpgpu_tlbl2_latency 45 - - --gpgpu_shmem_warp_parts 2 - -# interconnection --network_mode 1 --inter_config_file icnt_config_islip.icnt - -# dram scheduler config --gpgpu_dram_scheduler 1 -# The DRAM return queue and the scheduler queue together should provide buffer -# to sustain the memory level parallelism to tolerate DRAM latency -# To allow 100% DRAM utility, there should at least be enough buffer to sustain -# the minimum DRAM latency (30 core cycles). I.e. -# Total buffer space required = 30 x 800MHz / 337.5MHz = 71 --gpgpu_frfcfs_dram_sched_queue_size 16 --gpgpu_dram_return_queue_size 55 - -# dram model config --gpgpu_n_mem_per_ctrlr 2 --gpgpu_dram_buswidth 4 --gpgpu_dram_burst_length 4 --gpgpu_mem_address_mask 1 --gpgpu_mem_addr_mapping dramid@8;00000000.00000000.00000000.00000000.0000RRRR.RRRRRRRR.RRBBBCCC.CCCSSSSS -# GDDR3 timing from Samsung K4J52324QH-HC12 @ 800MHz -# {nbk:tCCD:tRRD:tRCD:tRAS:tRP:tRC:CL:WL:tCDLR:tWR:nbkgrp:tCCDL:tRTPL} --gpgpu_dram_timing_opt nbk=8:CCD=2:RRD=8:RCD=12:RAS=25:RP=10:RC=35:CL=10:WL=7:CDLR=6:WR=11 - -# stat collection --gpgpu_memlatency_stat 14 --gpgpu_runtime_stat 500 --enable_ptx_file_line_stats 1 - - - -# Using cuobjdump to extract ptx/SASS --gpgpu_ptx_use_cuobjdump 1 - -# SASS execution (only supported with CUDA >= 4.0) --gpgpu_ptx_convert_to_ptxplus 0 --gpgpu_ptx_save_converted_ptxplus 0 - -# enable operand collector --gpgpu_operand_collector_num_units_sp 6 --gpgpu_operand_collector_num_units_sfu 8 - --visualizer_enabled 0 --power_trace_enabled 0 --power_simulation_enabled 1 --gpuwattch_xml_file gpuwattch_quadrofx5600.xml - --steady_power_levels_enabled 1 --steady_state_definition 8,4 diff --git a/configs/QuadroFX5600/gpuwattch_quadrofx5600.xml b/configs/QuadroFX5600/gpuwattch_quadrofx5600.xml deleted file mode 100644 index 2c5a6fc..0000000 --- a/configs/QuadroFX5600/gpuwattch_quadrofx5600.xml +++ /dev/null @@ -1,538 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/configs/QuadroFX5600/icnt_config_islip.icnt b/configs/QuadroFX5600/icnt_config_islip.icnt deleted file mode 100644 index de3bcc8..0000000 --- a/configs/QuadroFX5600/icnt_config_islip.icnt +++ /dev/null @@ -1,70 +0,0 @@ -//14*1 fly with 32 flits per packet under gpgpusim injection mode -use_map = 0; -flit_size = 32; - -// currently we donot use this, see subnets below -network_count = 2; - -// Topology -topology = fly; -k = 14; -n = 1; - -// Routing - -routing_function = dest_tag; - -// Flow control - -num_vcs = 1; -vc_buf_size = 8; - -wait_for_tail_credit = 0; - -// Router architecture - -vc_allocator = islip; //separable_input_first; -sw_allocator = islip; //separable_input_first; -alloc_iters = 1; - -credit_delay = 0; -routing_delay = 0; -vc_alloc_delay = 1; -sw_alloc_delay = 1; - -input_speedup = 2; -output_speedup = 1; -internal_speedup = 1.0; - -// Traffic, GPGPU-Sim does not use this - -traffic = uniform; -packet_size ={{1,2,3,4},{10,20}}; -packet_size_rate={{1,1,1,1},{2,1}}; - -// Simulation - Don't change - -sim_type = gpgpusim; -//sim_type = latency; -injection_rate = 0.1; - -subnets = 2; - -// Always use read and write no matter following line -//use_read_write = 1; - - -read_request_subnet = 0; -read_reply_subnet = 1; -write_request_subnet = 0; -write_reply_subnet = 1; - -read_request_begin_vc = 0; -read_request_end_vc = 0; -write_request_begin_vc = 0; -write_request_end_vc = 0; -read_reply_begin_vc = 0; -read_reply_end_vc = 0; -write_reply_begin_vc = 0; -write_reply_end_vc = 0; - diff --git a/configs/QuadroFX5800/config_quadro_islip.icnt b/configs/QuadroFX5800/config_quadro_islip.icnt deleted file mode 100644 index cfe9cac..0000000 --- a/configs/QuadroFX5800/config_quadro_islip.icnt +++ /dev/null @@ -1,69 +0,0 @@ -//18*1 fly with 32 flits per packet under gpgpusim injection mode -use_map = 0; -flit_size = 32; - -// currently we donot use this, see subnets below -network_count = 2; - -// Topology -topology = fly; -k = 18; -n = 1; - -// Routing - -routing_function = dest_tag; - -// Flow control - -num_vcs = 1; -vc_buf_size = 8; - -wait_for_tail_credit = 0; - -// Router architecture - -vc_allocator = islip; //separable_input_first; -sw_allocator = islip; //separable_input_first; -alloc_iters = 1; - -credit_delay = 0; -routing_delay = 0; -vc_alloc_delay = 1; -sw_alloc_delay = 1; - -input_speedup = 2; -output_speedup = 1; -internal_speedup = 1.0; - -// Traffic, GPGPU-Sim does not use this -traffic = uniform; -packet_size ={{1,2,3,4},{10,20}}; -packet_size_rate={{1,1,1,1},{2,1}}; - -// Simulation - Don't change -sim_type = gpgpusim; -//sim_type = latency; -injection_rate = 0.1; - - -subnets = 2; - -// Always use read and write no matter following line -//use_read_write = 1; - - -read_request_subnet = 0; -read_reply_subnet = 1; -write_request_subnet = 0; -write_reply_subnet = 1; - -read_request_begin_vc = 0; -read_request_end_vc = 0; -write_request_begin_vc = 0; -write_request_end_vc = 0; -read_reply_begin_vc = 0; -read_reply_end_vc = 0; -write_reply_begin_vc = 0; -write_reply_end_vc = 0; - diff --git a/configs/QuadroFX5800/gpgpusim.config b/configs/QuadroFX5800/gpgpusim.config deleted file mode 100644 index fef1110..0000000 --- a/configs/QuadroFX5800/gpgpusim.config +++ /dev/null @@ -1,88 +0,0 @@ -# functional simulator specification --gpgpu_ptx_instruction_classification 0 --gpgpu_ptx_sim_mode 0 --gpgpu_ptx_force_max_capability 13 - -# high level architecture configuration --gpgpu_n_clusters 10 --gpgpu_n_cores_per_cluster 3 --gpgpu_n_mem 8 --gpgpu_clock_domains 325.0:650.0:650.0:800.0 - -# shader core pipeline config --gpgpu_shader_registers 16384 --gpgpu_occupancy_sm_number 13 - --gpgpu_shader_core_pipeline 1024:32 --gpgpu_shader_cta 8 --gpgpu_simd_model 1 - -# Pipeline widths and number of FUs -# ID_OC_SP,ID_OC_SFU,ID_OC_MEM,OC_EX_SP,OC_EX_SFU,OC_EX_MEM,EX_WB --gpgpu_pipeline_widths 1,1,1,1,1,1,1 --gpgpu_num_sp_units 1 --gpgpu_num_sfu_units 1 - -# Instruction latencies and initiation intervals -# "ADD,MAX,MUL,MAD,DIV" --ptx_opcode_latency_int 1,1,19,25,145 --ptx_opcode_initiation_int 1,1,4,4,32 --ptx_opcode_latency_fp 1,1,1,1,30 --ptx_opcode_initiation_fp 1,1,1,1,5 --ptx_opcode_latency_dp 8,8,8,8,335 --ptx_opcode_initiation_dp 8,8,8,8,130 - -# memory stage behaviour -# ::,::::,::,:** -# ** Optional parameter - Required when mshr_type==Texture Fifo --gpgpu_cache:il1 4:256:4,L:R:f:N:L,A:2:32,4 --gpgpu_tex_cache:l1 8:128:5,L:R:m:N:L,F:128:4,128:2 --gpgpu_const_cache:l1 64:64:2,L:R:f:N:L,A:2:32,4 --gpgpu_cache:dl2 16:256:8,L:B:m:W:L,A:16:4,4 --gpgpu_cache:dl2_texture_only 1 - --gpgpu_shmem_warp_parts 2 - -# interconnection --network_mode 1 --inter_config_file config_quadro_islip.icnt - -# dram scheduler config --gpgpu_dram_scheduler 1 -# The DRAM return queue and the scheduler queue together should provide buffer -# to sustain the memory level parallelism to tolerate DRAM latency -# To allow 100% DRAM utility, there should at least be enough buffer to sustain -# the minimum DRAM latency (30 core cycles). I.e. -# Total buffer space required = 30 x 800MHz / 325MHz = 74 --gpgpu_frfcfs_dram_sched_queue_size 16 --gpgpu_dram_return_queue_size 58 - -# dram model config --gpgpu_n_mem_per_ctrlr 2 --gpgpu_dram_buswidth 4 --gpgpu_dram_burst_length 4 --dram_data_command_freq_ratio 2 # GDDR3 is DDR --gpgpu_mem_address_mask 1 --gpgpu_mem_addr_mapping dramid@8;00000000.00000000.00000000.00000000.0000RRRR.RRRRRRRR.RRBBBCCC.CCCSSSSS -# GDDR3 timing from Samsung K4J52324QH-HC12 @ 800MHz --gpgpu_dram_timing_opt nbk=8:CCD=2:RRD=8:RCD=12:RAS=25:RP=10:RC=35:CL=10:WL=7:CDLR=6:WR=11 - -# stat collection --gpgpu_memlatency_stat 14 --gpgpu_runtime_stat 500 --enable_ptx_file_line_stats 1 - -# SASS execution (only supported with CUDA >= 4.0) --gpgpu_ptx_convert_to_ptxplus 0 --gpgpu_ptx_save_converted_ptxplus 0 - -# enable operand collector --gpgpu_operand_collector_num_units_sp 6 --gpgpu_operand_collector_num_units_sfu 8 - --visualizer_enabled 0 - -# tracing functionality -#-trace_enabled 1 -#-trace_components WARP_SCHEDULER,SCOREBOARD -#-trace_sampling_core 0 diff --git a/configs/TeslaC2050/config_fermi_islip.icnt b/configs/TeslaC2050/config_fermi_islip.icnt deleted file mode 100644 index a11bd8e..0000000 --- a/configs/TeslaC2050/config_fermi_islip.icnt +++ /dev/null @@ -1,70 +0,0 @@ -//20*1 fly with 32 flits per packet under gpgpusim injection mode -use_map = 0; -flit_size = 32; - -// currently we donot use this, see subnets below -network_count = 2; - -// Topology -topology = fly; -k = 26; -n = 1; - -// Routing - -routing_function = dest_tag; - -// Flow control - -num_vcs = 1; -vc_buf_size = 8; - -wait_for_tail_credit = 0; - -// Router architecture - -vc_allocator = islip; //separable_input_first; -sw_allocator = islip; //separable_input_first; -alloc_iters = 1; - -credit_delay = 0; -routing_delay = 0; -vc_alloc_delay = 1; -sw_alloc_delay = 1; - -input_speedup = 2; -output_speedup = 1; -internal_speedup = 1.0; - -// Traffic, GPGPU-Sim does not use this - -traffic = uniform; -packet_size ={{1,2,3,4},{10,20}}; -packet_size_rate={{1,1,1,1},{2,1}}; - -// Simulation - Don't change - -sim_type = gpgpusim; -//sim_type = latency; -injection_rate = 0.1; - - -subnets = 2; - -// Always use read and write no matter following line -//use_read_write = 1; - - -read_request_subnet = 0; -read_reply_subnet = 1; -write_request_subnet = 0; -write_reply_subnet = 1; - -read_request_begin_vc = 0; -read_request_end_vc = 0; -write_request_begin_vc = 0; -write_request_end_vc = 0; -read_reply_begin_vc = 0; -read_reply_end_vc = 0; -write_reply_begin_vc = 0; -write_reply_end_vc = 0; diff --git a/configs/TeslaC2050/gpgpusim.config b/configs/TeslaC2050/gpgpusim.config deleted file mode 100644 index 6ac2c12..0000000 --- a/configs/TeslaC2050/gpgpusim.config +++ /dev/null @@ -1,133 +0,0 @@ -# functional simulator specification --gpgpu_ptx_instruction_classification 0 --gpgpu_ptx_sim_mode 0 --gpgpu_ptx_force_max_capability 20 - -# Using cuobjdump to extract ptx/SASS -#-gpgpu_ptx_use_cuobjdump 1 # use default - -# SASS execution (only supported with CUDA >= 4.0) --gpgpu_ptx_convert_to_ptxplus 0 --gpgpu_ptx_save_converted_ptxplus 0 - - -# high level architecture configuration --gpgpu_n_clusters 14 --gpgpu_n_cores_per_cluster 1 --gpgpu_n_mem 6 --gpgpu_n_sub_partition_per_mchannel 2 - -# Fermi clock domains -#-gpgpu_clock_domains ::: -# In Fermi, each pipeline has 16 execution units, so the Core clock needs to be divided -# by 2. (GPGPU-Sim simulates a warp (32 threads) in a single cycle). 1400/2 = 700 --gpgpu_clock_domains 575.0:575.0:575.0:750.0 - -# shader core pipeline config --gpgpu_shader_registers 32768 --gpgpu_occupancy_sm_number 20 - -# This implies a maximum of 48 warps/SM --gpgpu_shader_core_pipeline 1536:32 --gpgpu_shader_cta 8 --gpgpu_simd_model 1 - -# Pipeline widths and number of FUs -# ID_OC_SP,ID_OC_SFU,ID_OC_MEM,OC_EX_SP,OC_EX_SFU,OC_EX_MEM,EX_WB --gpgpu_pipeline_widths 2,1,1,2,1,1,2 --gpgpu_num_sp_units 2 --gpgpu_num_sfu_units 1 - -# Instruction latencies and initiation intervals -# "ADD,MAX,MUL,MAD,DIV" --ptx_opcode_latency_int 4,13,4,5,145 --ptx_opcode_initiation_int 1,2,2,1,8 --ptx_opcode_latency_fp 4,13,4,5,39 --ptx_opcode_initiation_fp 1,2,1,1,4 --ptx_opcode_latency_dp 8,19,8,8,330 --ptx_opcode_initiation_dp 8,16,8,8,130 - - -# In Fermi, the cache and shared memory can be configured to 16kb:48kb(default) or 48kb:16kb -# ::,::::,::,:** -# ** Optional parameter - Required when mshr_type==Texture Fifo -# Note: Hashing set index function (H) only applies to a set size of 32 or 64. --gpgpu_cache:dl1 32:128:4,L:L:m:N:H,A:32:8,8 --gpgpu_shmem_size 49152 - -# The alternative configuration for fermi in case cudaFuncCachePreferL1 is selected -#-gpgpu_cache:dl1 64:128:6,L:L:m:N:H,A:32:8,8 -#-gpgpu_shmem_size 16384 - -# 64 sets, each 128 bytes 8-way for each memory sub partition. This gives 786KB L2 cache --gpgpu_cache:dl2 64:128:8,L:B:m:W:L,A:32:4,4:0,32 --gpgpu_cache:dl2_texture_only 0 - --gpgpu_cache:il1 4:128:4,L:R:f:N:L,A:2:32,4 --gpgpu_tex_cache:l1 4:128:24,L:R:m:N:L,F:128:4,128:2 --gpgpu_const_cache:l1 64:64:2,L:R:f:N:L,A:2:32,4 - -# enable operand collector --gpgpu_operand_collector_num_units_sp 6 --gpgpu_operand_collector_num_units_sfu 8 --gpgpu_operand_collector_num_in_ports_sp 2 --gpgpu_operand_collector_num_out_ports_sp 2 --gpgpu_num_reg_banks 16 - -# shared memory bankconflict detection --gpgpu_shmem_num_banks 32 --gpgpu_shmem_limited_broadcast 0 --gpgpu_shmem_warp_parts 1 - --gpgpu_max_insn_issue_per_warp 1 - -# interconnection --network_mode 1 --inter_config_file config_fermi_islip.icnt - -# memory partition latency config --rop_latency 120 --dram_latency 100 - -# dram model config --gpgpu_dram_scheduler 1 -# The DRAM return queue and the scheduler queue together should provide buffer -# to sustain the memory level parallelism to tolerate DRAM latency -# To allow 100% DRAM utility, there should at least be enough buffer to sustain -# the minimum DRAM latency (100 core cycles). I.e. -# Total buffer space required = 100 x 750MHz / 575MHz = 130 --gpgpu_frfcfs_dram_sched_queue_size 16 --gpgpu_dram_return_queue_size 114 - -# for Fermi, bus width is 384bits, this is 8 bytes (4 bytes at each DRAM chip) per memory partition --gpgpu_n_mem_per_ctrlr 2 --gpgpu_dram_buswidth 4 --gpgpu_dram_burst_length 8 --dram_data_command_freq_ratio 4 # GDDR5 is QDR --gpgpu_mem_address_mask 1 --gpgpu_mem_addr_mapping dramid@8;00000000.00000000.00000000.00000000.0000RRRR.RRRRRRRR.BBBCCCCB.CCSSSSSS - -# GDDR5 timing from hynix H5GQ1H24AFR -# to disable bank groups, set nbkgrp to 1 and tCCDL and tRTPL to 0 --gpgpu_dram_timing_opt "nbk=16:CCD=2:RRD=6:RCD=12:RAS=28:RP=12:RC=40: - CL=12:WL=4:CDLR=5:WR=12:nbkgrp=4:CCDL=3:RTPL=2" - -# Fermi has two schedulers per core --gpgpu_num_sched_per_core 2 -# Two Level Scheduler with active and pending pools -#-gpgpu_scheduler two_level_active:6:0:1 -# Loose round robbin scheduler -#-gpgpu_scheduler lrr -# Greedy then oldest scheduler --gpgpu_scheduler gto - -# stat collection --gpgpu_memlatency_stat 14 --gpgpu_runtime_stat 500 --enable_ptx_file_line_stats 1 --visualizer_enabled 0 - -# tracing functionality -#-trace_enabled 1 -#-trace_components WARP_SCHEDULER,SCOREBOARD -#-trace_sampling_core 0 diff --git a/configs/deprecated-cfgs/GTX480/config_fermi_islip.icnt b/configs/deprecated-cfgs/GTX480/config_fermi_islip.icnt new file mode 100644 index 0000000..7820e4e --- /dev/null +++ b/configs/deprecated-cfgs/GTX480/config_fermi_islip.icnt @@ -0,0 +1,70 @@ +//21*1 fly with 32 flits per packet under gpgpusim injection mode +use_map = 0; +flit_size = 32; + +// currently we do not use this, see subnets below +network_count = 2; + +// Topology +topology = fly; +k = 27; +n = 1; + +// Routing + +routing_function = dest_tag; + +// Flow control + +num_vcs = 1; +vc_buf_size = 8; + +wait_for_tail_credit = 0; + +// Router architecture + +vc_allocator = islip; //separable_input_first; +sw_allocator = islip; //separable_input_first; +alloc_iters = 1; + +credit_delay = 0; +routing_delay = 0; +vc_alloc_delay = 1; +sw_alloc_delay = 1; + +input_speedup = 2; +output_speedup = 1; +internal_speedup = 1.0; + +// Traffic, GPGPU-Sim does not use this + +traffic = uniform; +packet_size ={{1,2,3,4},{10,20}}; +packet_size_rate={{1,1,1,1},{2,1}}; + +// Simulation - Don't change + +sim_type = gpgpusim; +//sim_type = latency; +injection_rate = 0.1; + +subnets = 2; + +// Always use read and write no matter following line +//use_read_write = 1; + + +read_request_subnet = 0; +read_reply_subnet = 1; +write_request_subnet = 0; +write_reply_subnet = 1; + +read_request_begin_vc = 0; +read_request_end_vc = 0; +write_request_begin_vc = 0; +write_request_end_vc = 0; +read_reply_begin_vc = 0; +read_reply_end_vc = 0; +write_reply_begin_vc = 0; +write_reply_end_vc = 0; + diff --git a/configs/deprecated-cfgs/GTX480/gpgpusim.config b/configs/deprecated-cfgs/GTX480/gpgpusim.config new file mode 100644 index 0000000..ee90c12 --- /dev/null +++ b/configs/deprecated-cfgs/GTX480/gpgpusim.config @@ -0,0 +1,134 @@ +# functional simulator specification +-gpgpu_ptx_instruction_classification 0 +-gpgpu_ptx_sim_mode 0 +-gpgpu_ptx_force_max_capability 20 + + +# SASS execution (only supported with CUDA >= 4.0) +-gpgpu_ptx_convert_to_ptxplus 0 +-gpgpu_ptx_save_converted_ptxplus 0 + +# high level architecture configuration +-gpgpu_n_clusters 15 +-gpgpu_n_cores_per_cluster 1 +-gpgpu_n_mem 6 +-gpgpu_n_sub_partition_per_mchannel 2 + +# Fermi clock domains +#-gpgpu_clock_domains ::: +# In Fermi, each pipeline has 16 execution units, so the Core clock needs to be divided +# by 2. (GPGPU-Sim simulates a warp (32 threads) in a single cycle). 1400/2 = 700 +-gpgpu_clock_domains 700.0:700.0:700.0:924.0 + +# shader core pipeline config +-gpgpu_shader_registers 32768 +-gpgpu_occupancy_sm_number 20 + +# This implies a maximum of 48 warps/SM +-gpgpu_shader_core_pipeline 1536:32 +-gpgpu_shader_cta 8 +-gpgpu_simd_model 1 + +# Pipeline widths and number of FUs +# ID_OC_SP,ID_OC_SFU,ID_OC_MEM,OC_EX_SP,OC_EX_SFU,OC_EX_MEM,EX_WB +-gpgpu_pipeline_widths 2,1,1,2,1,1,2 +-gpgpu_num_sp_units 2 +-gpgpu_num_sfu_units 1 + +# Instruction latencies and initiation intervals +# "ADD,MAX,MUL,MAD,DIV" +-ptx_opcode_latency_int 4,13,4,5,145 +-ptx_opcode_initiation_int 1,2,2,1,8 +-ptx_opcode_latency_fp 4,13,4,5,39 +-ptx_opcode_initiation_fp 1,2,1,1,4 +-ptx_opcode_latency_dp 8,19,8,8,330 +-ptx_opcode_initiation_dp 8,16,8,8,130 + + +# In Fermi, the cache and shared memory can be configured to 16kb:48kb(default) or 48kb:16kb +# ::,::::,::,:** +# ** Optional parameter - Required when mshr_type==Texture Fifo +# Note: Hashing set index function (H) only applies to a set size of 32 or 64. +-gpgpu_cache:dl1 32:128:4,L:L:m:N:H,A:32:8,8 +-gpgpu_shmem_size 49152 + +# The alternative configuration for fermi in case cudaFuncCachePreferL1 is selected +#-gpgpu_cache:dl1 64:128:6,L:L:m:N:H,A:32:8,8 +#-gpgpu_shmem_size 16384 + +# 64 sets, each 128 bytes 8-way for each memory sub partition. This gives 786KB L2 cache +-gpgpu_cache:dl2 64:128:8,L:B:m:W:L,A:32:4,4:0,32 +-gpgpu_cache:dl2_texture_only 0 + +-gpgpu_cache:il1 4:128:4,L:R:f:N:L,A:2:32,4 +-gpgpu_tex_cache:l1 4:128:24,L:R:m:N:L,F:128:4,128:2 +-gpgpu_const_cache:l1 64:64:2,L:R:f:N:L,A:2:32,4 + +# enable operand collector +-gpgpu_operand_collector_num_units_sp 6 +-gpgpu_operand_collector_num_units_sfu 8 +-gpgpu_operand_collector_num_in_ports_sp 2 +-gpgpu_operand_collector_num_out_ports_sp 2 +-gpgpu_num_reg_banks 16 + +# shared memory bankconflict detection +-gpgpu_shmem_num_banks 32 +-gpgpu_shmem_limited_broadcast 0 +-gpgpu_shmem_warp_parts 1 + +-gpgpu_max_insn_issue_per_warp 1 + +# interconnection +-network_mode 1 +-inter_config_file config_fermi_islip.icnt + +# memory partition latency config +-rop_latency 120 +-dram_latency 100 + +# dram model config +-gpgpu_dram_scheduler 1 +# The DRAM return queue and the scheduler queue together should provide buffer +# to sustain the memory level parallelism to tolerate DRAM latency +# To allow 100% DRAM utility, there should at least be enough buffer to sustain +# the minimum DRAM latency (100 core cycles). I.e. +# Total buffer space required = 100 x 924MHz / 700MHz = 132 +-gpgpu_frfcfs_dram_sched_queue_size 16 +-gpgpu_dram_return_queue_size 116 + +# for Fermi, bus width is 384bits, this is 8 bytes (4 bytes at each DRAM chip) per memory partition +-gpgpu_n_mem_per_ctrlr 2 +-gpgpu_dram_buswidth 4 +-gpgpu_dram_burst_length 8 +-dram_data_command_freq_ratio 4 # GDDR5 is QDR +-gpgpu_mem_address_mask 1 +-gpgpu_mem_addr_mapping dramid@8;00000000.00000000.00000000.00000000.0000RRRR.RRRRRRRR.BBBCCCCB.CCSSSSSS + +# GDDR5 timing from hynix H5GQ1H24AFR +# to disable bank groups, set nbkgrp to 1 and tCCDL and tRTPL to 0 +-gpgpu_dram_timing_opt "nbk=16:CCD=2:RRD=6:RCD=12:RAS=28:RP=12:RC=40: + CL=12:WL=4:CDLR=5:WR=12:nbkgrp=4:CCDL=3:RTPL=2" + +# Fermi has two schedulers per core +-gpgpu_num_sched_per_core 2 +# Two Level Scheduler with active and pending pools +#-gpgpu_scheduler two_level_active:6:0:1 +# Loose round robbin scheduler +#-gpgpu_scheduler lrr +# Greedy then oldest scheduler +-gpgpu_scheduler gto + +# stat collection +-gpgpu_memlatency_stat 14 +-gpgpu_runtime_stat 500 +-enable_ptx_file_line_stats 1 +-visualizer_enabled 0 + +# power model configs +-power_simulation_enabled 1 +-gpuwattch_xml_file gpuwattch_gtx480.xml + +# tracing functionality +#-trace_enabled 1 +#-trace_components WARP_SCHEDULER,SCOREBOARD +#-trace_sampling_core 0 diff --git a/configs/deprecated-cfgs/GTX480/gpuwattch_gtx480.xml b/configs/deprecated-cfgs/GTX480/gpuwattch_gtx480.xml new file mode 100755 index 0000000..304e0fd --- /dev/null +++ b/configs/deprecated-cfgs/GTX480/gpuwattch_gtx480.xml @@ -0,0 +1,538 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/configs/deprecated-cfgs/GeForceGTX750Ti/config_fermi_islip.icnt b/configs/deprecated-cfgs/GeForceGTX750Ti/config_fermi_islip.icnt new file mode 100644 index 0000000..069ca02 --- /dev/null +++ b/configs/deprecated-cfgs/GeForceGTX750Ti/config_fermi_islip.icnt @@ -0,0 +1,70 @@ +//21*1 fly with 32 flits per packet under gpgpusim injection mode +use_map = 0; +flit_size = 32; + +// currently we do not use this, see subnets below +network_count = 2; + +// Topology +topology = fly; +k = 7; +n = 1; + +// Routing + +routing_function = dest_tag; + +// Flow control + +num_vcs = 1; +vc_buf_size = 8; + +wait_for_tail_credit = 0; + +// Router architecture + +vc_allocator = islip; //separable_input_first; +sw_allocator = islip; //separable_input_first; +alloc_iters = 1; + +credit_delay = 0; +routing_delay = 0; +vc_alloc_delay = 1; +sw_alloc_delay = 1; + +input_speedup = 2; +output_speedup = 1; +internal_speedup = 1.0; + +// Traffic, GPGPU-Sim does not use this + +traffic = uniform; +packet_size ={{1,2,3,4},{10,20}}; +packet_size_rate={{1,1,1,1},{2,1}}; + +// Simulation - Don't change + +sim_type = gpgpusim; +//sim_type = latency; +injection_rate = 0.1; + +subnets = 2; + +// Always use read and write no matter following line +//use_read_write = 1; + + +read_request_subnet = 0; +read_reply_subnet = 1; +write_request_subnet = 0; +write_reply_subnet = 1; + +read_request_begin_vc = 0; +read_request_end_vc = 0; +write_request_begin_vc = 0; +write_request_end_vc = 0; +read_reply_begin_vc = 0; +read_reply_end_vc = 0; +write_reply_begin_vc = 0; +write_reply_end_vc = 0; + diff --git a/configs/deprecated-cfgs/GeForceGTX750Ti/gpgpusim.config b/configs/deprecated-cfgs/GeForceGTX750Ti/gpgpusim.config new file mode 100644 index 0000000..c675aab --- /dev/null +++ b/configs/deprecated-cfgs/GeForceGTX750Ti/gpgpusim.config @@ -0,0 +1,131 @@ +# functional simulator specification +-gpgpu_ptx_instruction_classification 0 +-gpgpu_ptx_sim_mode 0 +-gpgpu_ptx_force_max_capability 52 + + +# SASS execution (only supported with CUDA >= 4.0) +-gpgpu_ptx_convert_to_ptxplus 0 +-gpgpu_ptx_save_converted_ptxplus 0 + +# high level architecture configuration +-gpgpu_n_clusters 5 +-gpgpu_n_cores_per_cluster 1 +-gpgpu_n_mem 2 +-gpgpu_n_sub_partition_per_mchannel 1 + +# Maxwell clock domains +#-gpgpu_clock_domains ::: +# In Maxwell, each pipeline has 32 execution units, so the Core clock is just the reported number. +-gpgpu_clock_domains 1137.0:1137.0:1137.0:2700.0 + +# shader core pipeline config +-gpgpu_shader_registers 65536 +-gpgpu_occupancy_sm_number 52 + +# This implies a maximum of 64 warps/SM +-gpgpu_shader_core_pipeline 2048:32 +-gpgpu_shader_cta 8 +-gpgpu_simd_model 1 + +# Pipeline widths and number of FUs +# ID_OC_SP,ID_OC_SFU,ID_OC_MEM,OC_EX_SP,OC_EX_SFU,OC_EX_MEM,EX_WB +-gpgpu_pipeline_widths 2,1,1,2,1,1,2 +-gpgpu_num_sp_units 8 +-gpgpu_num_sfu_units 32 + +# Instruction latencies and initiation intervals +# "ADD,MAX,MUL,MAD,DIV" +-ptx_opcode_latency_int 6,12,13,13,210 +-ptx_opcode_initiation_int 1,1,1,1,4 +-ptx_opcode_latency_fp 6,12,6,6,374 +-ptx_opcode_initiation_fp 1,1,1,1,4 +-ptx_opcode_latency_dp 8,19,8,8,330 +-ptx_opcode_initiation_dp 8,16,8,8,130 + +-gpgpu_cache:dl1 32:128:4,L:L:m:N:H,A:32:8,8 +-gmem_skip_L1D 1 +-gpgpu_shmem_size 65536 + +# The alternative configuration for fermi in case cudaFuncCachePreferL1 is selected +#-gpgpu_cache:dl1 64:128:6,L:L:m:N:H,A:32:8,8 +#-gpgpu_shmem_size 16384 + +# 1024 sets, each 128 bytes 8-way for each memory sub partition. This gives 2MB L2 cache +-gpgpu_cache:dl2 1024:128:8,L:B:m:W:L,A:32:4,4:0,32 +-gpgpu_cache:dl2_texture_only 0 + +-gpgpu_cache:il1 4:128:4,L:R:f:N:L,A:2:32,4 +-gpgpu_tex_cache:l1 16:128:32,L:R:m:N:L,F:128:4,128:2 +-gpgpu_const_cache:l1 64:64:2,L:R:f:N:L,A:2:32,4 + +# enable operand collector +-gpgpu_operand_collector_num_units_sp 6 +-gpgpu_operand_collector_num_units_sfu 8 +-gpgpu_operand_collector_num_in_ports_sp 2 +-gpgpu_operand_collector_num_out_ports_sp 2 +-gpgpu_num_reg_banks 16 + +# shared memory bankconflict detection +-gpgpu_shmem_num_banks 32 +-gpgpu_shmem_limited_broadcast 0 +-gpgpu_shmem_warp_parts 1 + +-gpgpu_max_insn_issue_per_warp 2 + +# interconnection +-network_mode 1 +-inter_config_file config_fermi_islip.icnt + +# memory partition latency config +-rop_latency 150 +-dram_latency 130 + +# dram model config +-gpgpu_dram_scheduler 1 +# The DRAM return queue and the scheduler queue together should provide buffer +# to sustain the memory level parallelism to tolerate DRAM latency +# To allow 100% DRAM utility, there should at least be enough buffer to sustain +# the minimum DRAM latency (100 core cycles). I.e. +# Total buffer space required = 100 x 924MHz / 700MHz = 132 +-gpgpu_frfcfs_dram_sched_queue_size 16 +-gpgpu_dram_return_queue_size 300 + +# for Maxwell, bus width is 128bits, this is 64 bytes (32 bytes at each DRAM chip) per memory partition +-gpgpu_n_mem_per_ctrlr 2 +-gpgpu_dram_buswidth 32 +-gpgpu_dram_burst_length 8 +-dram_data_command_freq_ratio 4 # GDDR5 is QDR +-gpgpu_mem_address_mask 1 +-gpgpu_mem_addr_mapping dramid@8;00000000.00000000.00000000.00000000.0000RRRR.RRRRRRRR.BBBCCCCB.CCSSSSSS + +# GDDR5 timing from hynix H5GQ1H24AFR +# to disable bank groups, set nbkgrp to 1 and tCCDL and tRTPL to 0 +-gpgpu_dram_timing_opt "nbk=16:CCD=2:RRD=6:RCD=12:RAS=28:RP=12:RC=40: + CL=12:WL=4:CDLR=5:WR=12:nbkgrp=4:CCDL=3:RTPL=2" + +# Maxwell has four schedulers per core +-gpgpu_num_sched_per_core 4 +# Two Level Scheduler with active and pending pools +#-gpgpu_scheduler two_level_active:6:0:1 +# Loose round robbin scheduler +#-gpgpu_scheduler lrr +# Greedy then oldest scheduler +-gpgpu_scheduler gto + +# stat collection +-gpgpu_memlatency_stat 14 +-gpgpu_runtime_stat 500 +-enable_ptx_file_line_stats 1 +-visualizer_enabled 0 + +# power model configs +# power modeling is currently disabled for GTX750Ti. The gpuwattch_gtx750ti.xml file present is only a placeholder and has NOT been tested for accuracy. +# proper modeling of Maxwell power is planned, but should be considered completely unsupported at present. +-power_simulation_enabled 0 +-gpuwattch_xml_file gpuwattch_gtx750Ti.xml + +# tracing functionality +#-trace_enabled 1 +#-trace_components WARP_SCHEDULER,SCOREBOARD +#-trace_sampling_core 0 diff --git a/configs/deprecated-cfgs/GeForceGTX750Ti/gpuwattch_gtx750Ti.xml b/configs/deprecated-cfgs/GeForceGTX750Ti/gpuwattch_gtx750Ti.xml new file mode 100755 index 0000000..e2b2324 --- /dev/null +++ b/configs/deprecated-cfgs/GeForceGTX750Ti/gpuwattch_gtx750Ti.xml @@ -0,0 +1,539 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/configs/deprecated-cfgs/QuadroFX5600/gpgpusim.config b/configs/deprecated-cfgs/QuadroFX5600/gpgpusim.config new file mode 100644 index 0000000..6f836ee --- /dev/null +++ b/configs/deprecated-cfgs/QuadroFX5600/gpgpusim.config @@ -0,0 +1,99 @@ +# functional simulator specification +-gpgpu_ptx_instruction_classification 0 +-gpgpu_ptx_sim_mode 0 +-gpgpu_ptx_force_max_capability 12 + +# high level architecture configuration +-gpgpu_n_clusters 8 +-gpgpu_n_cores_per_cluster 2 +-gpgpu_n_mem 6 +-gpgpu_clock_domains 337.5:600.0:600.0:800.0 + +# shader core pipeline config +-gpgpu_shader_registers 16384 +-gpgpu_occupancy_sm_number 12 + +-gpgpu_occupancy_sm_number 12 +#8192 (registers per block as written by device Query and which used in this option in our other configurations but this break some benchmarks execution! it does not affect performance modeling though) +-gpgpu_shader_core_pipeline 768:32 +-gpgpu_shader_cta 8 +-gpgpu_simd_model 1 + +# Pipeline widths and number of FUs +# ID_OC_SP,ID_OC_SFU,ID_OC_MEM,OC_EX_SP,OC_EX_SFU,OC_EX_MEM,EX_WB +-gpgpu_pipeline_widths 1,1,1,1,1,1,1 +-gpgpu_num_sp_units 1 +-gpgpu_num_sfu_units 1 + +# Instruction latencies and initiation intervals +# "ADD,MAX,MUL,MAD,DIV" +-ptx_opcode_latency_int 1,1,19,25,145 +-ptx_opcode_initiation_int 1,1,4,4,32 +-ptx_opcode_latency_fp 1,1,1,1,30 +-ptx_opcode_initiation_fp 1,1,1,1,5 +-ptx_opcode_latency_dp 8,8,8,8,335 +-ptx_opcode_initiation_dp 8,8,8,8,130 + +# memory stage behaviour +-gpgpu_cache:il1 4:256:4,L:R:f:N:L,A:2:32,4 +-gpgpu_tex_cache:l1 8:128:5,L:R:m:N:L,F:128:4,128:2 +-gpgpu_const_cache:l1 64:64:2,L:R:f:N:L,A:2:32,4 +-gpgpu_cache:dl2 16:256:8,L:B:m:W:L,A:16:4,4 +-gpgpu_cache:dl2_texture_only 1 + +# TLB parameters +#-gpgpu_cache:tlbl1 1:524288:16:1:L:R:m,A:32:8,8 +#-gpgpu_tlbl2_latency 45 + + +-gpgpu_shmem_warp_parts 2 + +# interconnection +-network_mode 1 +-inter_config_file icnt_config_islip.icnt + +# dram scheduler config +-gpgpu_dram_scheduler 1 +# The DRAM return queue and the scheduler queue together should provide buffer +# to sustain the memory level parallelism to tolerate DRAM latency +# To allow 100% DRAM utility, there should at least be enough buffer to sustain +# the minimum DRAM latency (30 core cycles). I.e. +# Total buffer space required = 30 x 800MHz / 337.5MHz = 71 +-gpgpu_frfcfs_dram_sched_queue_size 16 +-gpgpu_dram_return_queue_size 55 + +# dram model config +-gpgpu_n_mem_per_ctrlr 2 +-gpgpu_dram_buswidth 4 +-gpgpu_dram_burst_length 4 +-gpgpu_mem_address_mask 1 +-gpgpu_mem_addr_mapping dramid@8;00000000.00000000.00000000.00000000.0000RRRR.RRRRRRRR.RRBBBCCC.CCCSSSSS +# GDDR3 timing from Samsung K4J52324QH-HC12 @ 800MHz +# {nbk:tCCD:tRRD:tRCD:tRAS:tRP:tRC:CL:WL:tCDLR:tWR:nbkgrp:tCCDL:tRTPL} +-gpgpu_dram_timing_opt nbk=8:CCD=2:RRD=8:RCD=12:RAS=25:RP=10:RC=35:CL=10:WL=7:CDLR=6:WR=11 + +# stat collection +-gpgpu_memlatency_stat 14 +-gpgpu_runtime_stat 500 +-enable_ptx_file_line_stats 1 + + + +# Using cuobjdump to extract ptx/SASS +-gpgpu_ptx_use_cuobjdump 1 + +# SASS execution (only supported with CUDA >= 4.0) +-gpgpu_ptx_convert_to_ptxplus 0 +-gpgpu_ptx_save_converted_ptxplus 0 + +# enable operand collector +-gpgpu_operand_collector_num_units_sp 6 +-gpgpu_operand_collector_num_units_sfu 8 + +-visualizer_enabled 0 +-power_trace_enabled 0 +-power_simulation_enabled 1 +-gpuwattch_xml_file gpuwattch_quadrofx5600.xml + +-steady_power_levels_enabled 1 +-steady_state_definition 8,4 diff --git a/configs/deprecated-cfgs/QuadroFX5600/gpuwattch_quadrofx5600.xml b/configs/deprecated-cfgs/QuadroFX5600/gpuwattch_quadrofx5600.xml new file mode 100644 index 0000000..2c5a6fc --- /dev/null +++ b/configs/deprecated-cfgs/QuadroFX5600/gpuwattch_quadrofx5600.xml @@ -0,0 +1,538 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/configs/deprecated-cfgs/QuadroFX5600/icnt_config_islip.icnt b/configs/deprecated-cfgs/QuadroFX5600/icnt_config_islip.icnt new file mode 100644 index 0000000..de3bcc8 --- /dev/null +++ b/configs/deprecated-cfgs/QuadroFX5600/icnt_config_islip.icnt @@ -0,0 +1,70 @@ +//14*1 fly with 32 flits per packet under gpgpusim injection mode +use_map = 0; +flit_size = 32; + +// currently we donot use this, see subnets below +network_count = 2; + +// Topology +topology = fly; +k = 14; +n = 1; + +// Routing + +routing_function = dest_tag; + +// Flow control + +num_vcs = 1; +vc_buf_size = 8; + +wait_for_tail_credit = 0; + +// Router architecture + +vc_allocator = islip; //separable_input_first; +sw_allocator = islip; //separable_input_first; +alloc_iters = 1; + +credit_delay = 0; +routing_delay = 0; +vc_alloc_delay = 1; +sw_alloc_delay = 1; + +input_speedup = 2; +output_speedup = 1; +internal_speedup = 1.0; + +// Traffic, GPGPU-Sim does not use this + +traffic = uniform; +packet_size ={{1,2,3,4},{10,20}}; +packet_size_rate={{1,1,1,1},{2,1}}; + +// Simulation - Don't change + +sim_type = gpgpusim; +//sim_type = latency; +injection_rate = 0.1; + +subnets = 2; + +// Always use read and write no matter following line +//use_read_write = 1; + + +read_request_subnet = 0; +read_reply_subnet = 1; +write_request_subnet = 0; +write_reply_subnet = 1; + +read_request_begin_vc = 0; +read_request_end_vc = 0; +write_request_begin_vc = 0; +write_request_end_vc = 0; +read_reply_begin_vc = 0; +read_reply_end_vc = 0; +write_reply_begin_vc = 0; +write_reply_end_vc = 0; + diff --git a/configs/deprecated-cfgs/QuadroFX5800/config_quadro_islip.icnt b/configs/deprecated-cfgs/QuadroFX5800/config_quadro_islip.icnt new file mode 100644 index 0000000..cfe9cac --- /dev/null +++ b/configs/deprecated-cfgs/QuadroFX5800/config_quadro_islip.icnt @@ -0,0 +1,69 @@ +//18*1 fly with 32 flits per packet under gpgpusim injection mode +use_map = 0; +flit_size = 32; + +// currently we donot use this, see subnets below +network_count = 2; + +// Topology +topology = fly; +k = 18; +n = 1; + +// Routing + +routing_function = dest_tag; + +// Flow control + +num_vcs = 1; +vc_buf_size = 8; + +wait_for_tail_credit = 0; + +// Router architecture + +vc_allocator = islip; //separable_input_first; +sw_allocator = islip; //separable_input_first; +alloc_iters = 1; + +credit_delay = 0; +routing_delay = 0; +vc_alloc_delay = 1; +sw_alloc_delay = 1; + +input_speedup = 2; +output_speedup = 1; +internal_speedup = 1.0; + +// Traffic, GPGPU-Sim does not use this +traffic = uniform; +packet_size ={{1,2,3,4},{10,20}}; +packet_size_rate={{1,1,1,1},{2,1}}; + +// Simulation - Don't change +sim_type = gpgpusim; +//sim_type = latency; +injection_rate = 0.1; + + +subnets = 2; + +// Always use read and write no matter following line +//use_read_write = 1; + + +read_request_subnet = 0; +read_reply_subnet = 1; +write_request_subnet = 0; +write_reply_subnet = 1; + +read_request_begin_vc = 0; +read_request_end_vc = 0; +write_request_begin_vc = 0; +write_request_end_vc = 0; +read_reply_begin_vc = 0; +read_reply_end_vc = 0; +write_reply_begin_vc = 0; +write_reply_end_vc = 0; + diff --git a/configs/deprecated-cfgs/QuadroFX5800/gpgpusim.config b/configs/deprecated-cfgs/QuadroFX5800/gpgpusim.config new file mode 100644 index 0000000..fef1110 --- /dev/null +++ b/configs/deprecated-cfgs/QuadroFX5800/gpgpusim.config @@ -0,0 +1,88 @@ +# functional simulator specification +-gpgpu_ptx_instruction_classification 0 +-gpgpu_ptx_sim_mode 0 +-gpgpu_ptx_force_max_capability 13 + +# high level architecture configuration +-gpgpu_n_clusters 10 +-gpgpu_n_cores_per_cluster 3 +-gpgpu_n_mem 8 +-gpgpu_clock_domains 325.0:650.0:650.0:800.0 + +# shader core pipeline config +-gpgpu_shader_registers 16384 +-gpgpu_occupancy_sm_number 13 + +-gpgpu_shader_core_pipeline 1024:32 +-gpgpu_shader_cta 8 +-gpgpu_simd_model 1 + +# Pipeline widths and number of FUs +# ID_OC_SP,ID_OC_SFU,ID_OC_MEM,OC_EX_SP,OC_EX_SFU,OC_EX_MEM,EX_WB +-gpgpu_pipeline_widths 1,1,1,1,1,1,1 +-gpgpu_num_sp_units 1 +-gpgpu_num_sfu_units 1 + +# Instruction latencies and initiation intervals +# "ADD,MAX,MUL,MAD,DIV" +-ptx_opcode_latency_int 1,1,19,25,145 +-ptx_opcode_initiation_int 1,1,4,4,32 +-ptx_opcode_latency_fp 1,1,1,1,30 +-ptx_opcode_initiation_fp 1,1,1,1,5 +-ptx_opcode_latency_dp 8,8,8,8,335 +-ptx_opcode_initiation_dp 8,8,8,8,130 + +# memory stage behaviour +# ::,::::,::,:** +# ** Optional parameter - Required when mshr_type==Texture Fifo +-gpgpu_cache:il1 4:256:4,L:R:f:N:L,A:2:32,4 +-gpgpu_tex_cache:l1 8:128:5,L:R:m:N:L,F:128:4,128:2 +-gpgpu_const_cache:l1 64:64:2,L:R:f:N:L,A:2:32,4 +-gpgpu_cache:dl2 16:256:8,L:B:m:W:L,A:16:4,4 +-gpgpu_cache:dl2_texture_only 1 + +-gpgpu_shmem_warp_parts 2 + +# interconnection +-network_mode 1 +-inter_config_file config_quadro_islip.icnt + +# dram scheduler config +-gpgpu_dram_scheduler 1 +# The DRAM return queue and the scheduler queue together should provide buffer +# to sustain the memory level parallelism to tolerate DRAM latency +# To allow 100% DRAM utility, there should at least be enough buffer to sustain +# the minimum DRAM latency (30 core cycles). I.e. +# Total buffer space required = 30 x 800MHz / 325MHz = 74 +-gpgpu_frfcfs_dram_sched_queue_size 16 +-gpgpu_dram_return_queue_size 58 + +# dram model config +-gpgpu_n_mem_per_ctrlr 2 +-gpgpu_dram_buswidth 4 +-gpgpu_dram_burst_length 4 +-dram_data_command_freq_ratio 2 # GDDR3 is DDR +-gpgpu_mem_address_mask 1 +-gpgpu_mem_addr_mapping dramid@8;00000000.00000000.00000000.00000000.0000RRRR.RRRRRRRR.RRBBBCCC.CCCSSSSS +# GDDR3 timing from Samsung K4J52324QH-HC12 @ 800MHz +-gpgpu_dram_timing_opt nbk=8:CCD=2:RRD=8:RCD=12:RAS=25:RP=10:RC=35:CL=10:WL=7:CDLR=6:WR=11 + +# stat collection +-gpgpu_memlatency_stat 14 +-gpgpu_runtime_stat 500 +-enable_ptx_file_line_stats 1 + +# SASS execution (only supported with CUDA >= 4.0) +-gpgpu_ptx_convert_to_ptxplus 0 +-gpgpu_ptx_save_converted_ptxplus 0 + +# enable operand collector +-gpgpu_operand_collector_num_units_sp 6 +-gpgpu_operand_collector_num_units_sfu 8 + +-visualizer_enabled 0 + +# tracing functionality +#-trace_enabled 1 +#-trace_components WARP_SCHEDULER,SCOREBOARD +#-trace_sampling_core 0 diff --git a/configs/deprecated-cfgs/SM6_GTX1080/config_fermi_islip.icnt b/configs/deprecated-cfgs/SM6_GTX1080/config_fermi_islip.icnt new file mode 100644 index 0000000..2a69ddd --- /dev/null +++ b/configs/deprecated-cfgs/SM6_GTX1080/config_fermi_islip.icnt @@ -0,0 +1,70 @@ +//21*1 fly with 32 flits per packet under gpgpusim injection mode +use_map = 0; +flit_size = 32; + +// currently we do not use this, see subnets below +network_count = 2; + +// Topology +topology = fly; +k = 50; +n = 1; + +// Routing + +routing_function = dest_tag; + +// Flow control + +num_vcs = 1; +vc_buf_size = 8; + +wait_for_tail_credit = 0; + +// Router architecture + +vc_allocator = islip; //separable_input_first; +sw_allocator = islip; //separable_input_first; +alloc_iters = 1; + +credit_delay = 0; +routing_delay = 0; +vc_alloc_delay = 1; +sw_alloc_delay = 1; + +input_speedup = 2; +output_speedup = 1; +internal_speedup = 1.0; + +// Traffic, GPGPU-Sim does not use this + +traffic = uniform; +packet_size ={{1,2,3,4},{10,20}}; +packet_size_rate={{1,1,1,1},{2,1}}; + +// Simulation - Don't change + +sim_type = gpgpusim; +//sim_type = latency; +injection_rate = 0.1; + +subnets = 2; + +// Always use read and write no matter following line +//use_read_write = 1; + + +read_request_subnet = 0; +read_reply_subnet = 1; +write_request_subnet = 0; +write_reply_subnet = 1; + +read_request_begin_vc = 0; +read_request_end_vc = 0; +write_request_begin_vc = 0; +write_request_end_vc = 0; +read_reply_begin_vc = 0; +read_reply_end_vc = 0; +write_reply_begin_vc = 0; +write_reply_end_vc = 0; + diff --git a/configs/deprecated-cfgs/SM6_GTX1080/gpgpusim.config b/configs/deprecated-cfgs/SM6_GTX1080/gpgpusim.config new file mode 100644 index 0000000..fb044c6 --- /dev/null +++ b/configs/deprecated-cfgs/SM6_GTX1080/gpgpusim.config @@ -0,0 +1,150 @@ +# This config models the Pascal GP102 (GeForceGTX 1080Ti) + +# functional simulator specification +-gpgpu_ptx_instruction_classification 0 +-gpgpu_ptx_sim_mode 0 +-gpgpu_ptx_force_max_capability 60 + +# SASS execution (only supported with CUDA >= 4.0) +-gpgpu_ptx_convert_to_ptxplus 0 +-gpgpu_ptx_save_converted_ptxplus 0 + +# high level architecture configuration +-gpgpu_n_clusters 28 +-gpgpu_n_cores_per_cluster 1 +-gpgpu_n_mem 11 +-gpgpu_n_sub_partition_per_mchannel 2 + +# Pascal clock domains +#-gpgpu_clock_domains ::: +# Pascal NVIDIA TITAN X clock domains are adopted from +# https://en.wikipedia.org/wiki/GeForce_10_series +-gpgpu_clock_domains 1481.0:2962.0:1481.0:2750.0 + +# shader core pipeline config +-gpgpu_shader_registers 65536 +-gpgpu_occupancy_sm_number 60 + +# This implies a maximum of 64 warps/SM +-gpgpu_shader_core_pipeline 2048:32 +-gpgpu_shader_cta 32 +-gpgpu_simd_model 1 + +# Pipeline widths and number of FUs +# ID_OC_SP,ID_OC_SFU,ID_OC_MEM,OC_EX_SP,OC_EX_SFU,OC_EX_MEM,EX_WB +## Pascal GP102 has 4 SP SIMD units and 1 SFU unit +## we need to scale the number of pipeline registers to be equal to the number of SP units +-gpgpu_pipeline_widths 4,1,1,4,1,1,6 +-gpgpu_num_sp_units 4 +-gpgpu_num_sfu_units 1 + +# Instruction latencies and initiation intervals +# "ADD,MAX,MUL,MAD,DIV" +# SFU is 32-width in pascal, then dp units initiation is 1 cycle +-ptx_opcode_latency_int 4,13,4,5,145 +-ptx_opcode_initiation_int 1,2,2,2,8 +-ptx_opcode_latency_fp 4,13,4,5,39 +-ptx_opcode_initiation_fp 1,2,1,1,4 +-ptx_opcode_latency_dp 8,19,8,8,330 +-ptx_opcode_initiation_dp 1,2,1,1,130 + +# ::,::::,::,:** +# ** Optional parameter - Required when mshr_type==Texture Fifo +# Note: Hashing set index function (H) only applies to a set size of 32 or 64. +# Pascal GP102 has 96KB Shared memory +# Pascal GP102 has 64KB L1 cache +# The default is to disable the L1 cache, unless cache modifieres is used +-gpgpu_cache:dl1 64:128:6,L:L:m:N:H,A:128:8,8 +-gpgpu_shmem_size 98304 +-gmem_skip_L1D 1 + +# 64 sets, each 128 bytes 16-way for each memory sub partition (128 KB per memory sub partition). This gives 3MB L2 cache +-gpgpu_cache:dl2 64:128:16,L:B:m:W:L,A:1024:1024,4:0,32 # used to be 128:4 +-gpgpu_cache:dl2_texture_only 0 + +# 4 KB Inst. +-gpgpu_cache:il1 8:128:4,L:R:f:N:L,A:2:48,4 +# 48 KB Tex +-gpgpu_tex_cache:l1 16:128:24,L:R:m:N:L,F:128:4,128:2 +# 12 KB Const +-gpgpu_const_cache:l1 128:64:2,L:R:f:N:L,A:2:64,4 + +# enable operand collector +## larger operand collectors and reg_banks are needed for the 4 warp schedulers and 4 SIMD units +-gpgpu_operand_collector_num_units_sp 20 +-gpgpu_operand_collector_num_units_sfu 4 +-gpgpu_operand_collector_num_units_mem 8 +-gpgpu_operand_collector_num_in_ports_sp 4 +-gpgpu_operand_collector_num_out_ports_sp 4 +-gpgpu_operand_collector_num_in_ports_sfu 1 +-gpgpu_operand_collector_num_out_ports_sfu 1 +-gpgpu_operand_collector_num_in_ports_mem 1 +-gpgpu_operand_collector_num_out_ports_mem 1 +# gpgpu_num_reg_banks should be increased to 32, but it gives an error! +-gpgpu_num_reg_banks 32 + +# shared memory bankconflict detection +-gpgpu_shmem_num_banks 32 +-gpgpu_shmem_limited_broadcast 0 +-gpgpu_shmem_warp_parts 1 + +## In Pascal, a warp scheduler can issue 2 insts per cycle +-gpgpu_max_insn_issue_per_warp 2 + +# interconnection +-network_mode 1 +-inter_config_file config_fermi_islip.icnt + +# memory partition latency config +-rop_latency 120 +-dram_latency 100 + +# dram model config +-gpgpu_dram_scheduler 1 +# The DRAM return queue and the scheduler queue together should provide buffer +# to sustain the memory level parallelism to tolerate DRAM latency +# To allow 100% DRAM utility, there should at least be enough buffer to sustain +# the minimum DRAM latency (100 core cycles). I.e. +# Total buffer space required = 100 x 924MHz / 700MHz = 132 +-gpgpu_frfcfs_dram_sched_queue_size 64 +-gpgpu_dram_return_queue_size 116 + +# for NVIDIA GeForceGTX 1080Ti, bus width is 352bits (11 DRAM chips x 32 bits) +# 11 memory paritions, 4 bytes (1 DRAM chip) per memory partition +# the atom size of GDDR5X (the smallest read request) is 32 bytes +-gpgpu_n_mem_per_ctrlr 1 +-gpgpu_dram_buswidth 4 +-gpgpu_dram_burst_length 8 +-dram_data_command_freq_ratio 4 # GDDR5X is QDR +-gpgpu_mem_address_mask 1 +-gpgpu_mem_addr_mapping dramid@8;00000000.00000000.00000000.00000000.0000RRRR.RRRRRRRR.RBBBCCCC.BCCSSSSS + +# Use the same GDDR5 timing from hynix H5GQ1H24AFR +# disable bank groups for now, set nbkgrp to 1 and tCCDL and tRTPL to 0 +-gpgpu_dram_timing_opt "nbk=16:CCD=2:RRD=6:RCD=12:RAS=28:RP=12:RC=40: + CL=12:WL=4:CDLR=5:WR=12:nbkgrp=1:CCDL=0:RTPL=0" + +# Pascal has four schedulers per core +-gpgpu_num_sched_per_core 2 +# Two Level Scheduler with active and pending pools +#-gpgpu_scheduler two_level_active:6:0:1 +# Loose round robbin scheduler +#-gpgpu_scheduler lrr +# Greedy then oldest scheduler +-gpgpu_scheduler gto + +# stat collection +-gpgpu_memlatency_stat 14 +-gpgpu_runtime_stat 500 +-enable_ptx_file_line_stats 1 +-visualizer_enabled 0 + +# power model configs +-power_simulation_enabled 1 +-gpuwattch_xml_file gpuwattch_gtx1080Ti.xml + +# tracing functionality +#-trace_enabled 1 +#-trace_components WARP_SCHEDULER,SCOREBOARD +#-trace_sampling_core 0 + diff --git a/configs/deprecated-cfgs/SM6_GTX1080/gpuwattch_gtx1080Ti.xml b/configs/deprecated-cfgs/SM6_GTX1080/gpuwattch_gtx1080Ti.xml new file mode 100755 index 0000000..02619ff --- /dev/null +++ b/configs/deprecated-cfgs/SM6_GTX1080/gpuwattch_gtx1080Ti.xml @@ -0,0 +1,538 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/configs/deprecated-cfgs/SM6_P100/config_fermi_islip.icnt b/configs/deprecated-cfgs/SM6_P100/config_fermi_islip.icnt new file mode 100644 index 0000000..d26c8d9 --- /dev/null +++ b/configs/deprecated-cfgs/SM6_P100/config_fermi_islip.icnt @@ -0,0 +1,70 @@ +//21*1 fly with 32 flits per packet under gpgpusim injection mode +use_map = 0; +flit_size = 32; + +// currently we do not use this, see subnets below +network_count = 2; + +// Topology +topology = fly; +k = 60; +n = 1; + +// Routing + +routing_function = dest_tag; + +// Flow control + +num_vcs = 1; +vc_buf_size = 8; + +wait_for_tail_credit = 0; + +// Router architecture + +vc_allocator = islip; //separable_input_first; +sw_allocator = islip; //separable_input_first; +alloc_iters = 1; + +credit_delay = 0; +routing_delay = 0; +vc_alloc_delay = 1; +sw_alloc_delay = 1; + +input_speedup = 2; +output_speedup = 1; +internal_speedup = 1.0; + +// Traffic, GPGPU-Sim does not use this + +traffic = uniform; +packet_size ={{1,2,3,4},{10,20}}; +packet_size_rate={{1,1,1,1},{2,1}}; + +// Simulation - Don't change + +sim_type = gpgpusim; +//sim_type = latency; +injection_rate = 0.1; + +subnets = 2; + +// Always use read and write no matter following line +//use_read_write = 1; + + +read_request_subnet = 0; +read_reply_subnet = 1; +write_request_subnet = 0; +write_reply_subnet = 1; + +read_request_begin_vc = 0; +read_request_end_vc = 0; +write_request_begin_vc = 0; +write_request_end_vc = 0; +read_reply_begin_vc = 0; +read_reply_end_vc = 0; +write_reply_begin_vc = 0; +write_reply_end_vc = 0; + diff --git a/configs/deprecated-cfgs/SM6_P100/gpgpusim.config b/configs/deprecated-cfgs/SM6_P100/gpgpusim.config new file mode 100644 index 0000000..a5e6736 --- /dev/null +++ b/configs/deprecated-cfgs/SM6_P100/gpgpusim.config @@ -0,0 +1,156 @@ +# This config models the Pascal GP100 +# For more info about this card, see Nvidia White paper +# https://images.nvidia.com/content/pdf/tesla/whitepaper/pascal-architecture-whitepaper.pdf + +# functional simulator specification +-gpgpu_ptx_instruction_classification 0 +-gpgpu_ptx_sim_mode 0 +-gpgpu_ptx_force_max_capability 60 + +# SASS execution (only supported with CUDA >= 4.0) +-gpgpu_ptx_convert_to_ptxplus 0 +-gpgpu_ptx_save_converted_ptxplus 0 + +# high level architecture configuration +-gpgpu_n_clusters 28 +-gpgpu_n_cores_per_cluster 2 +-gpgpu_n_mem 32 +-gpgpu_n_sub_partition_per_mchannel 1 + +# Pscal clock domains +#-gpgpu_clock_domains ::: +# Pascal NVIDIA GP100 clock domains are adopted from +# https://en.wikipedia.org/wiki/Nvidia_Tesla +-gpgpu_clock_domains 1480.0:1480.0:1480.0:715.0 + +# shader core pipeline config +-gpgpu_shader_registers 65536 + +# This implies a maximum of 64 warps/SM +-gpgpu_shader_core_pipeline 2048:32 +-gpgpu_shader_cta 32 +-gpgpu_simd_model 1 + +# Pipeline widths and number of FUs +# ID_OC_SP,ID_OC_DP,ID_OC_SFU,ID_OC_MEM,OC_EX_SP,OC_EX_DP,OC_EX_SFU,OC_EX_MEM,EX_WB +## Pascal GP102 has 4 SP SIMD units and 1 SFU unit +## we need to scale the number of pipeline registers to be equal to the number of SP units +-gpgpu_pipeline_widths 2,2,1,2,2,1,4 +-gpgpu_num_sp_units 2 +-gpgpu_num_sfu_units 1 + +# Instruction latencies and initiation intervals +# "ADD,MAX,MUL,MAD,DIV" +# SFU is 32-width in pascal, then dp units initiation is 1 cycle +-ptx_opcode_latency_int 4,13,4,5,145 +-ptx_opcode_initiation_int 1,1,1,1,4 +-ptx_opcode_latency_fp 4,13,4,5,39 +-ptx_opcode_initiation_fp 1,2,1,1,4 +-ptx_opcode_latency_dp 8,19,8,8,330 +-ptx_opcode_initiation_dp 2,2,2,2,130 + +# ::,::::,::,:** +# ** Optional parameter - Required when mshr_type==Texture Fifo +# Note: Hashing set index function (H) only applies to a set size of 32 or 64. +# Pascal GP100 has 64KB Shared memory +# Pascal GP100 has 48KB L1 cache +-gpgpu_cache:dl1 64:128:6,L:L:m:N:H,A:128:8,16 +-gpgpu_cache:dl1PrefL1 64:128:6,L:L:m:N:H,A:128:8,16 +-gpgpu_cache:dl1PrefShared 64:128:6,L:L:m:N:H,A:128:8,16 +-gpgpu_shmem_size 65536 +-gpgpu_shmem_size_PrefL1 65536 +-gpgpu_shmem_size_PrefShared 65536 +-gmem_skip_L1D 0 + +# 64 sets, each 128 bytes 16-way for each memory sub partition (128 KB per memory sub partition). This gives 3MB L2 cache +-gpgpu_cache:dl2 64:128:16,L:B:m:W:L,A:128:8,4:0,32 +-gpgpu_cache:dl2_texture_only 0 +-gpgpu_dram_partition_queues 32:32:32:32 + +# 4 KB Inst. +-gpgpu_cache:il1 8:128:4,L:R:f:N:L,A:2:48,4 +# 48 KB Tex +-gpgpu_tex_cache:l1 16:128:24,L:R:m:N:L,F:128:4,128:2 +# 12 KB Const +-gpgpu_const_cache:l1 128:64:2,L:R:f:N:L,A:2:64,4 + +# enable operand collector +-gpgpu_operand_collector_num_units_sp 14 +-gpgpu_operand_collector_num_units_sfu 8 +-gpgpu_operand_collector_num_units_mem 10 +-gpgpu_operand_collector_num_in_ports_sp 4 +-gpgpu_operand_collector_num_out_ports_sp 4 +-gpgpu_operand_collector_num_in_ports_sfu 1 +-gpgpu_operand_collector_num_out_ports_sfu 1 +-gpgpu_operand_collector_num_in_ports_mem 1 +-gpgpu_operand_collector_num_out_ports_mem 1 +-gpgpu_num_reg_banks 32 + +# shared memory bankconflict detection +-gpgpu_shmem_num_banks 32 +-gpgpu_shmem_limited_broadcast 0 +-gpgpu_shmem_warp_parts 1 + +## In Pascal, a warp scheduler can issue 2 insts per cycle +-gpgpu_max_insn_issue_per_warp 2 + +# interconnection +-network_mode 1 +-inter_config_file config_fermi_islip.icnt + +# memory partition latency config +-rop_latency 120 +-dram_latency 100 + +# dram model config +-gpgpu_dram_scheduler 1 +# The DRAM return queue and the scheduler queue together should provide buffer +# to sustain the memory level parallelism to tolerate DRAM latency +# To allow 100% DRAM utility, there should at least be enough buffer to sustain +# the minimum DRAM latency (100 core cycles). I.e. +# Total buffer space required = 100 x 924MHz / 700MHz = 132 +-gpgpu_frfcfs_dram_sched_queue_size 64 +-gpgpu_dram_return_queue_size 116 + +# for HBM, 32 channles, each (128 bits) 16 bytes width +-gpgpu_n_mem_per_ctrlr 1 +-gpgpu_dram_buswidth 16 +-gpgpu_dram_burst_length 2 +-dram_data_command_freq_ratio 2 # HBM is DDR +-gpgpu_mem_address_mask 1 +-gpgpu_mem_addr_mapping dramid@8;00000000.00000000.00000000.00000000.0000RRRR.RRRRRRRR.RBBBBCCC.CCCSSSSS + +# HBM timing are adopted from hynix JESD235 standered and nVidia HPCA 2017 paper (http://www.cs.utah.edu/~nil/pubs/hpca17.pdf) +# Timing for 1 GHZ +# tRRDl and tWTR are missing, need to be added +#-gpgpu_dram_timing_opt "nbk=16:CCD=1:RRD=4:RCD=14:RAS=33:RP=14:RC=47: +# CL=14:WL=2:CDLR=3:WR=12:nbkgrp=4:CCDL=2:RTPL=4" + +# Timing for 715 MHZ, Tesla Pascal P100 HBM runs at 715 MHZ +-gpgpu_dram_timing_opt "nbk=16:CCD=1:RRD=3:RCD=10:RAS=24:RP=10:RC=34: + CL=10:WL=2:CDLR=3:WR=9:nbkgrp=4:CCDL=2:RTPL=3" + +# Fermi has two schedulers per core +-gpgpu_num_sched_per_core 2 +# Two Level Scheduler with active and pending pools +#-gpgpu_scheduler two_level_active:6:0:1 +# Loose round robbin scheduler +#-gpgpu_scheduler lrr +# Greedy then oldest scheduler +-gpgpu_scheduler gto + +# stat collection +-gpgpu_memlatency_stat 14 +-gpgpu_runtime_stat 500 +-enable_ptx_file_line_stats 1 +-visualizer_enabled 0 + +# power model configs +-power_simulation_enabled 0 +-gpuwattch_xml_file gpuwattch_gtx480.xml + +# tracing functionality +#-trace_enabled 1 +#-trace_components WARP_SCHEDULER,SCOREBOARD +#-trace_sampling_core 0 + diff --git a/configs/deprecated-cfgs/SM6_P100/gpuwattch_gtx480.xml b/configs/deprecated-cfgs/SM6_P100/gpuwattch_gtx480.xml new file mode 100755 index 0000000..304e0fd --- /dev/null +++ b/configs/deprecated-cfgs/SM6_P100/gpuwattch_gtx480.xml @@ -0,0 +1,538 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/configs/deprecated-cfgs/SM6_TITANX/config_fermi_islip.icnt b/configs/deprecated-cfgs/SM6_TITANX/config_fermi_islip.icnt new file mode 100644 index 0000000..602daee --- /dev/null +++ b/configs/deprecated-cfgs/SM6_TITANX/config_fermi_islip.icnt @@ -0,0 +1,70 @@ +//21*1 fly with 32 flits per packet under gpgpusim injection mode +use_map = 0; +flit_size = 32; + +// currently we do not use this, see subnets below +network_count = 2; + +// Topology +topology = fly; +k = 52; +n = 1; + +// Routing + +routing_function = dest_tag; + +// Flow control + +num_vcs = 1; +vc_buf_size = 8; + +wait_for_tail_credit = 0; + +// Router architecture + +vc_allocator = islip; //separable_input_first; +sw_allocator = islip; //separable_input_first; +alloc_iters = 1; + +credit_delay = 0; +routing_delay = 0; +vc_alloc_delay = 1; +sw_alloc_delay = 1; + +input_speedup = 2; +output_speedup = 1; +internal_speedup = 1.0; + +// Traffic, GPGPU-Sim does not use this + +traffic = uniform; +packet_size ={{1,2,3,4},{10,20}}; +packet_size_rate={{1,1,1,1},{2,1}}; + +// Simulation - Don't change + +sim_type = gpgpusim; +//sim_type = latency; +injection_rate = 0.1; + +subnets = 2; + +// Always use read and write no matter following line +//use_read_write = 1; + + +read_request_subnet = 0; +read_reply_subnet = 1; +write_request_subnet = 0; +write_reply_subnet = 1; + +read_request_begin_vc = 0; +read_request_end_vc = 0; +write_request_begin_vc = 0; +write_request_end_vc = 0; +read_reply_begin_vc = 0; +read_reply_end_vc = 0; +write_reply_begin_vc = 0; +write_reply_end_vc = 0; + diff --git a/configs/deprecated-cfgs/SM6_TITANX/gpgpusim.config b/configs/deprecated-cfgs/SM6_TITANX/gpgpusim.config new file mode 100644 index 0000000..28912a3 --- /dev/null +++ b/configs/deprecated-cfgs/SM6_TITANX/gpgpusim.config @@ -0,0 +1,157 @@ +# This config models the Pascal GP102 (NVIDIA TITAN X) +# For more info about this card, see Nvidia White paper +# http://international.download.nvidia.com/geforce-com/international/pdfs/GeForce_GTX_1080_Whitepaper_FINAL.pdf + +# functional simulator specification +-gpgpu_ptx_instruction_classification 0 +-gpgpu_ptx_sim_mode 0 +-gpgpu_ptx_force_max_capability 61 + +# SASS execution (only supported with CUDA >= 4.0) +-gpgpu_ptx_convert_to_ptxplus 0 +-gpgpu_ptx_save_converted_ptxplus 0 + +# high level architecture configuration +-gpgpu_n_clusters 28 +-gpgpu_n_cores_per_cluster 1 +-gpgpu_n_mem 12 +-gpgpu_n_sub_partition_per_mchannel 2 + +# Pascal clock domains +#-gpgpu_clock_domains ::: +# Pascal NVIDIA TITAN X clock domains are adopted from +# https://en.wikipedia.org/wiki/GeForce_10_series +-gpgpu_clock_domains 1417.0:1417.0:1417.0:2500.0 + +# shader core pipeline config +-gpgpu_shader_registers 65536 +-gpgpu_occupancy_sm_number 61 + +# This implies a maximum of 64 warps/SM +-gpgpu_shader_core_pipeline 2048:32 +-gpgpu_shader_cta 32 +-gpgpu_simd_model 1 + +# Pipeline widths and number of FUs +# ID_OC_SP,ID_OC_DP,ID_OC_SFU,ID_OC_MEM,OC_EX_SP,OC_EX_DP,OC_EX_SFU,OC_EX_MEM,EX_WB +## Pascal GP102 has 4 SP SIMD units and 1 SFU unit +## we need to scale the number of pipeline registers to be equal to the number of SP units +-gpgpu_pipeline_widths 4,1,1,4,1,1,6 +-gpgpu_num_sp_units 4 +-gpgpu_num_sfu_units 1 + +# Instruction latencies and initiation intervals +# "ADD,MAX,MUL,MAD,DIV" +# SFU is 32-width in pascal, then dp units initiation is 1 cycle +-ptx_opcode_latency_int 4,13,4,5,145 +-ptx_opcode_initiation_int 1,1,1,1,4 +-ptx_opcode_latency_fp 4,13,4,5,39 +-ptx_opcode_initiation_fp 1,2,1,1,4 +-ptx_opcode_latency_dp 8,19,8,8,330 +-ptx_opcode_initiation_dp 4,8,4,4,130 + +# ::,::::,::,:** +# ** Optional parameter - Required when mshr_type==Texture Fifo +# Note: Hashing set index function (H) only applies to a set size of 32 or 64. +# Pascal GP102 has 96KB Shared memory +# Pascal GP102 has 64KB L1 cache +# The defulat is to disable the L1 cache, unless cache modifieres is used +-gpgpu_cache:dl1 64:128:6,L:L:m:N:H,A:128:8,16 +-gpgpu_cache:dl1PrefL1 64:128:6,L:L:m:N:H,A:128:8,16 +-gpgpu_cache:dl1PrefShared 64:128:6,L:L:m:N:H,A:128:8,16 +-gpgpu_shmem_size 98304 +-gpgpu_shmem_size_PrefL1 98304 +-gpgpu_shmem_size_PrefShared 98304 +-gmem_skip_L1D 1 + +# 64 sets, each 128 bytes 16-way for each memory sub partition (128 KB per memory sub partition). This gives 3MB L2 cache +-gpgpu_cache:dl2 64:128:16,L:B:m:W:L,A:128:8,4:0,32 +-gpgpu_cache:dl2_texture_only 0 +-gpgpu_dram_partition_queues 32:32:32:32 + +# 4 KB Inst. +-gpgpu_cache:il1 8:128:4,L:R:f:N:L,A:2:48,4 +# 48 KB Tex +-gpgpu_tex_cache:l1 16:128:24,L:R:m:N:L,F:128:4,128:2 +# 12 KB Const +-gpgpu_const_cache:l1 128:64:2,L:R:f:N:L,A:2:64,4 + +# enable operand collector +## larger operand collectors and reg_banks are needed for the 4 warp schedulers and 4 SIMD units +-gpgpu_operand_collector_num_units_sp 20 +-gpgpu_operand_collector_num_units_sfu 4 +-gpgpu_operand_collector_num_units_mem 8 +-gpgpu_operand_collector_num_in_ports_sp 4 +-gpgpu_operand_collector_num_out_ports_sp 4 +-gpgpu_operand_collector_num_in_ports_sfu 1 +-gpgpu_operand_collector_num_out_ports_sfu 1 +-gpgpu_operand_collector_num_in_ports_mem 1 +-gpgpu_operand_collector_num_out_ports_mem 1 +# gpgpu_num_reg_banks should be increased to 32 +-gpgpu_num_reg_banks 32 + +# shared memory bankconflict detection +-gpgpu_shmem_num_banks 32 +-gpgpu_shmem_limited_broadcast 0 +-gpgpu_shmem_warp_parts 1 + +## In Pascal, a warp scheduler can issue 2 insts per cycle +-gpgpu_max_insn_issue_per_warp 2 + +# interconnection +-network_mode 1 +-inter_config_file config_fermi_islip.icnt + +# memory partition latency config +-rop_latency 120 +-dram_latency 100 + +# dram model config +-gpgpu_dram_scheduler 1 +# The DRAM return queue and the scheduler queue together should provide buffer +# to sustain the memory level parallelism to tolerate DRAM latency +# To allow 100% DRAM utility, there should at least be enough buffer to sustain +# the minimum DRAM latency (100 core cycles). I.e. +# Total buffer space required = 100 x 924MHz / 700MHz = 132 +-gpgpu_frfcfs_dram_sched_queue_size 64 +-gpgpu_dram_return_queue_size 116 + +# for NVIDIA TITAN X, bus width is 384bits (12 DRAM chips x 32 bits) +# 12 memory paritions, 4 bytes (1 DRAM chip) per memory partition +# the atom size of GDDR5X (the smallest read request) is 32 bytes +-gpgpu_n_mem_per_ctrlr 1 +-gpgpu_dram_buswidth 4 +-gpgpu_dram_burst_length 8 +-dram_data_command_freq_ratio 4 # GDDR5X is QDR +-gpgpu_mem_address_mask 1 +-gpgpu_mem_addr_mapping dramid@8;00000000.00000000.00000000.00000000.0000RRRR.RRRRRRRR.RBBBCCCC.BCCSSSSS + +# Use the same GDDR5 timing from hynix H5GQ1H24AFR +# disable bank groups for now, set nbkgrp to 1 and tCCDL and tRTPL to 0 +-gpgpu_dram_timing_opt "nbk=16:CCD=2:RRD=6:RCD=12:RAS=28:RP=12:RC=40: + CL=12:WL=4:CDLR=5:WR=12:nbkgrp=1:CCDL=0:RTPL=0" + +# Fermi has two schedulers per core +-gpgpu_num_sched_per_core 4 +# Two Level Scheduler with active and pending pools +#-gpgpu_scheduler two_level_active:6:0:1 +# Loose round robbin scheduler +#-gpgpu_scheduler lrr +# Greedy then oldest scheduler +-gpgpu_scheduler gto + +# stat collection +-gpgpu_memlatency_stat 14 +-gpgpu_runtime_stat 500 +-enable_ptx_file_line_stats 1 +-visualizer_enabled 0 + +# power model configs +-power_simulation_enabled 1 +-gpuwattch_xml_file gpuwattch_gtx480.xml + +# tracing functionality +#-trace_enabled 1 +#-trace_components WARP_SCHEDULER,SCOREBOARD +#-trace_sampling_core 0 + diff --git a/configs/deprecated-cfgs/SM6_TITANX/gpuwattch_gtx480.xml b/configs/deprecated-cfgs/SM6_TITANX/gpuwattch_gtx480.xml new file mode 100755 index 0000000..304e0fd --- /dev/null +++ b/configs/deprecated-cfgs/SM6_TITANX/gpuwattch_gtx480.xml @@ -0,0 +1,538 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/configs/deprecated-cfgs/SM7_TITANV/config_fermi_islip.icnt b/configs/deprecated-cfgs/SM7_TITANV/config_fermi_islip.icnt new file mode 100644 index 0000000..fac792a --- /dev/null +++ b/configs/deprecated-cfgs/SM7_TITANV/config_fermi_islip.icnt @@ -0,0 +1,70 @@ +//21*1 fly with 32 flits per packet under gpgpusim injection mode +use_map = 0; +flit_size = 32; + +// currently we do not use this, see subnets below +network_count = 2; + +// Topology +topology = fly; +k = 64; +n = 1; + +// Routing + +routing_function = dest_tag; + +// Flow control + +num_vcs = 1; +vc_buf_size = 8; + +wait_for_tail_credit = 0; + +// Router architecture + +vc_allocator = islip; //separable_input_first; +sw_allocator = islip; //separable_input_first; +alloc_iters = 1; + +credit_delay = 0; +routing_delay = 0; +vc_alloc_delay = 1; +sw_alloc_delay = 1; + +input_speedup = 2; +output_speedup = 1; +internal_speedup = 1.0; + +// Traffic, GPGPU-Sim does not use this + +traffic = uniform; +packet_size ={{1,2,3,4},{10,20}}; +packet_size_rate={{1,1,1,1},{2,1}}; + +// Simulation - Don't change + +sim_type = gpgpusim; +//sim_type = latency; +injection_rate = 0.1; + +subnets = 2; + +// Always use read and write no matter following line +//use_read_write = 1; + + +read_request_subnet = 0; +read_reply_subnet = 1; +write_request_subnet = 0; +write_reply_subnet = 1; + +read_request_begin_vc = 0; +read_request_end_vc = 0; +write_request_begin_vc = 0; +write_request_end_vc = 0; +read_reply_begin_vc = 0; +read_reply_end_vc = 0; +write_reply_begin_vc = 0; +write_reply_end_vc = 0; + diff --git a/configs/deprecated-cfgs/SM7_TITANV/gpgpusim.config b/configs/deprecated-cfgs/SM7_TITANV/gpgpusim.config new file mode 100644 index 0000000..aefb04a --- /dev/null +++ b/configs/deprecated-cfgs/SM7_TITANV/gpgpusim.config @@ -0,0 +1,165 @@ +# This config models the Volta Titan X +# For more info about this card: +# http://images.nvidia.com/content/volta-architecture/pdf/volta-architecture-whitepaper.pdf +# https://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=8344474&tag=1# +# http://on-demand.gputechconf.com/gtc/2018/presentation/s8122-dissecting-the-volta-gpu-architecture-through-microbenchmarking.pdf +# https://en.wikipedia.org/wiki/Volta_(microarchitecture) +# https://www.hotchips.org/wp-content/uploads/hc_archives/hc29/HC29.21-Monday-Pub/HC29.21.10-GPU-Gaming-Pub/HC29.21.132-Volta-Choquette-NVIDIA-Final3.pdf +# https://devblogs.nvidia.com/inside-volta/ +# http://on-demand.gputechconf.com/gtc/2017/presentation/s7798-luke-durant-inside-volta.pdf + +# functional simulator specification +-gpgpu_ptx_instruction_classification 0 +-gpgpu_ptx_sim_mode 0 +-gpgpu_ptx_force_max_capability 70 + +# SASS execution (only supported with CUDA >= 4.0) +-gpgpu_ptx_convert_to_ptxplus 0 +-gpgpu_ptx_save_converted_ptxplus 0 + +# high level architecture configuration +-gpgpu_n_clusters 40 +-gpgpu_n_cores_per_cluster 2 +-gpgpu_n_mem 24 +-gpgpu_n_sub_partition_per_mchannel 1 + +# volta clock domains +#-gpgpu_clock_domains ::: +# Pascal NVIDIA GP100 clock domains are adopted from +# https://en.wikipedia.org/wiki/Volta_(microarchitecture) +-gpgpu_clock_domains 1200.0:1200.0:1200.0:850.0 +# boost mode +# -gpgpu_clock_domains 1455.0:2000.0:1455.0:850.0 + +# shader core pipeline config +-gpgpu_shader_registers 65536 + +# This implies a maximum of 64 warps/SM +-gpgpu_shader_core_pipeline 2048:32 +-gpgpu_shader_cta 32 +-gpgpu_simd_model 1 + +# Pipeline widths and number of FUs +# ID_OC_SP,ID_OC_DP,ID_OC_SFU,ID_OC_MEM,OC_EX_SP,OC_EX_DP,OC_EX_SFU,OC_EX_MEM,EX_WB +## Pascal GP100 has 2 SP SIMD units, 2 SFU units, 2 DP units per core +## we need to scale the number of pipeline registers to be equal to the number of SP units +-gpgpu_pipeline_widths 4,4,1,4,4,1,9 +-gpgpu_num_sp_units 4 +-gpgpu_num_sfu_units 4 + +# Instruction latencies and initiation intervals +# "ADD,MAX,MUL,MAD,DIV" +# All Div operations are executed on SFU unit +# Throughput (initiation latency) are adopted from +# http://on-demand.gputechconf.com/gtc/2018/presentation/s8122-dissecting-the-volta-gpu-architecture-through-microbenchmarking.pdf +-ptx_opcode_latency_int 4,13,4,5,145 +-ptx_opcode_initiation_int 2,2,2,2,8 +-ptx_opcode_latency_fp 4,13,4,5,39 +-ptx_opcode_initiation_fp 2,2,2,2,4 +-ptx_opcode_latency_dp 8,19,8,8,330 +-ptx_opcode_initiation_dp 4,4,4,4,130 + +# ::,::::,::,:** +# ** Optional parameter - Required when mshr_type==Texture Fifo +# Note: Hashing set index function (H) only applies to a set size of 32 or 64. +# Volta GV100 has 64KB Shared memory +-gpgpu_cache:dl1 64:128:8,L:L:m:N:H,A:256:8,16:0 +-gpgpu_cache:dl1PrefL1 64:128:16,L:L:m:N:H,A:256:8,16:0 +-gpgpu_cache:dl1PrefShared 32:128:6,L:L:m:N:H,A:256:8,16:0 +-gpgpu_shmem_size 65536 +-gpgpu_shmem_size_PrefL1 1 +-gpgpu_shmem_size_PrefShared 98304 +-gmem_skip_L1D 0 + +# 64 sets, each 128 bytes 24-way for each memory sub partition (192 KB per memory sub partition). This gives 4.5MB L2 cache +-gpgpu_cache:dl2 64:128:24,L:B:m:W:L,A:256:4,32:0,32 +-gpgpu_cache:dl2_texture_only 0 +-gpgpu_dram_partition_queues 64:64:64:64 + +# 128 KB Inst. +-gpgpu_cache:il1 64:128:16,L:R:f:N:L,A:2:48,4 +# 48 KB Tex +-gpgpu_tex_cache:l1 16:128:24,L:R:m:N:L,F:128:4,128:2 +# 64 KB Const +-gpgpu_const_cache:l1 128:64:8,L:R:f:N:L,A:2:64,4 + +# enable operand collector +-gpgpu_operand_collector_num_units_sp 14 +-gpgpu_operand_collector_num_units_sfu 8 +-gpgpu_operand_collector_num_units_mem 10 +-gpgpu_operand_collector_num_in_ports_sp 4 +-gpgpu_operand_collector_num_out_ports_sp 4 +-gpgpu_operand_collector_num_in_ports_sfu 1 +-gpgpu_operand_collector_num_out_ports_sfu 1 +-gpgpu_operand_collector_num_in_ports_mem 1 +-gpgpu_operand_collector_num_out_ports_mem 1 +-gpgpu_num_reg_banks 32 + +# shared memory bankconflict detection +-gpgpu_shmem_num_banks 32 +-gpgpu_shmem_limited_broadcast 0 +-gpgpu_shmem_warp_parts 1 + +## In Pascal, a warp scheduler can issue 2 insts per cycle +-gpgpu_max_insn_issue_per_warp 1 + +# interconnection +-network_mode 1 +-inter_config_file config_fermi_islip.icnt + +# memory partition latency config +-rop_latency 120 +-dram_latency 100 + +# dram model config +-gpgpu_dram_scheduler 1 +# The DRAM return queue and the scheduler queue together should provide buffer +# to sustain the memory level parallelism to tolerate DRAM latency +# To allow 100% DRAM utility, there should at least be enough buffer to sustain +# the minimum DRAM latency (100 core cycles). I.e. +# Total buffer space required = 100 x 924MHz / 700MHz = 132 +-gpgpu_frfcfs_dram_sched_queue_size 64 +-gpgpu_dram_return_queue_size 116 + +# for HBM, 32 channles, each (128 bits) 16 bytes width +-gpgpu_n_mem_per_ctrlr 1 +-gpgpu_dram_buswidth 16 +-gpgpu_dram_burst_length 2 +-dram_data_command_freq_ratio 2 # HBM is DDR +-gpgpu_mem_address_mask 1 +-gpgpu_mem_addr_mapping dramid@8;00000000.00000000.00000000.00000000.0000RRRR.RRRRRRRR.RBBBBCCC.CCCSSSSS + +# HBM timing are adopted from hynix JESD235 standered and nVidia HPCA 2017 paper (http://www.cs.utah.edu/~nil/pubs/hpca17.pdf) +# Timing for 1 GHZ +# tRRDl and tWTR are missing, need to be added +#-gpgpu_dram_timing_opt "nbk=16:CCD=1:RRD=4:RCD=14:RAS=33:RP=14:RC=47: +# CL=14:WL=2:CDLR=3:WR=12:nbkgrp=4:CCDL=2:RTPL=4" + +# Timing for 715 MHZ, Tesla Pascal P100 HBM runs at 715 MHZ +-gpgpu_dram_timing_opt "nbk=16:CCD=1:RRD=3:RCD=10:RAS=24:RP=10:RC=34: + CL=10:WL=2:CDLR=3:WR=9:nbkgrp=4:CCDL=2:RTPL=3" + +# Fermi has two schedulers per core +-gpgpu_num_sched_per_core 4 +# Two Level Scheduler with active and pending pools +#-gpgpu_scheduler two_level_active:6:0:1 +# Loose round robbin scheduler +#-gpgpu_scheduler lrr +# Greedy then oldest scheduler +-gpgpu_scheduler gto + +# stat collection +-gpgpu_memlatency_stat 14 +-gpgpu_runtime_stat 500 +-enable_ptx_file_line_stats 1 +-visualizer_enabled 0 + +# power model configs +-power_simulation_enabled 0 +-gpuwattch_xml_file gpuwattch_gtx480.xml + +# tracing functionality +#-trace_enabled 1 +#-trace_components WARP_SCHEDULER,SCOREBOARD +#-trace_sampling_core 0 + diff --git a/configs/deprecated-cfgs/TeslaC2050/config_fermi_islip.icnt b/configs/deprecated-cfgs/TeslaC2050/config_fermi_islip.icnt new file mode 100644 index 0000000..a11bd8e --- /dev/null +++ b/configs/deprecated-cfgs/TeslaC2050/config_fermi_islip.icnt @@ -0,0 +1,70 @@ +//20*1 fly with 32 flits per packet under gpgpusim injection mode +use_map = 0; +flit_size = 32; + +// currently we donot use this, see subnets below +network_count = 2; + +// Topology +topology = fly; +k = 26; +n = 1; + +// Routing + +routing_function = dest_tag; + +// Flow control + +num_vcs = 1; +vc_buf_size = 8; + +wait_for_tail_credit = 0; + +// Router architecture + +vc_allocator = islip; //separable_input_first; +sw_allocator = islip; //separable_input_first; +alloc_iters = 1; + +credit_delay = 0; +routing_delay = 0; +vc_alloc_delay = 1; +sw_alloc_delay = 1; + +input_speedup = 2; +output_speedup = 1; +internal_speedup = 1.0; + +// Traffic, GPGPU-Sim does not use this + +traffic = uniform; +packet_size ={{1,2,3,4},{10,20}}; +packet_size_rate={{1,1,1,1},{2,1}}; + +// Simulation - Don't change + +sim_type = gpgpusim; +//sim_type = latency; +injection_rate = 0.1; + + +subnets = 2; + +// Always use read and write no matter following line +//use_read_write = 1; + + +read_request_subnet = 0; +read_reply_subnet = 1; +write_request_subnet = 0; +write_reply_subnet = 1; + +read_request_begin_vc = 0; +read_request_end_vc = 0; +write_request_begin_vc = 0; +write_request_end_vc = 0; +read_reply_begin_vc = 0; +read_reply_end_vc = 0; +write_reply_begin_vc = 0; +write_reply_end_vc = 0; diff --git a/configs/deprecated-cfgs/TeslaC2050/gpgpusim.config b/configs/deprecated-cfgs/TeslaC2050/gpgpusim.config new file mode 100644 index 0000000..6ac2c12 --- /dev/null +++ b/configs/deprecated-cfgs/TeslaC2050/gpgpusim.config @@ -0,0 +1,133 @@ +# functional simulator specification +-gpgpu_ptx_instruction_classification 0 +-gpgpu_ptx_sim_mode 0 +-gpgpu_ptx_force_max_capability 20 + +# Using cuobjdump to extract ptx/SASS +#-gpgpu_ptx_use_cuobjdump 1 # use default + +# SASS execution (only supported with CUDA >= 4.0) +-gpgpu_ptx_convert_to_ptxplus 0 +-gpgpu_ptx_save_converted_ptxplus 0 + + +# high level architecture configuration +-gpgpu_n_clusters 14 +-gpgpu_n_cores_per_cluster 1 +-gpgpu_n_mem 6 +-gpgpu_n_sub_partition_per_mchannel 2 + +# Fermi clock domains +#-gpgpu_clock_domains ::: +# In Fermi, each pipeline has 16 execution units, so the Core clock needs to be divided +# by 2. (GPGPU-Sim simulates a warp (32 threads) in a single cycle). 1400/2 = 700 +-gpgpu_clock_domains 575.0:575.0:575.0:750.0 + +# shader core pipeline config +-gpgpu_shader_registers 32768 +-gpgpu_occupancy_sm_number 20 + +# This implies a maximum of 48 warps/SM +-gpgpu_shader_core_pipeline 1536:32 +-gpgpu_shader_cta 8 +-gpgpu_simd_model 1 + +# Pipeline widths and number of FUs +# ID_OC_SP,ID_OC_SFU,ID_OC_MEM,OC_EX_SP,OC_EX_SFU,OC_EX_MEM,EX_WB +-gpgpu_pipeline_widths 2,1,1,2,1,1,2 +-gpgpu_num_sp_units 2 +-gpgpu_num_sfu_units 1 + +# Instruction latencies and initiation intervals +# "ADD,MAX,MUL,MAD,DIV" +-ptx_opcode_latency_int 4,13,4,5,145 +-ptx_opcode_initiation_int 1,2,2,1,8 +-ptx_opcode_latency_fp 4,13,4,5,39 +-ptx_opcode_initiation_fp 1,2,1,1,4 +-ptx_opcode_latency_dp 8,19,8,8,330 +-ptx_opcode_initiation_dp 8,16,8,8,130 + + +# In Fermi, the cache and shared memory can be configured to 16kb:48kb(default) or 48kb:16kb +# ::,::::,::,:** +# ** Optional parameter - Required when mshr_type==Texture Fifo +# Note: Hashing set index function (H) only applies to a set size of 32 or 64. +-gpgpu_cache:dl1 32:128:4,L:L:m:N:H,A:32:8,8 +-gpgpu_shmem_size 49152 + +# The alternative configuration for fermi in case cudaFuncCachePreferL1 is selected +#-gpgpu_cache:dl1 64:128:6,L:L:m:N:H,A:32:8,8 +#-gpgpu_shmem_size 16384 + +# 64 sets, each 128 bytes 8-way for each memory sub partition. This gives 786KB L2 cache +-gpgpu_cache:dl2 64:128:8,L:B:m:W:L,A:32:4,4:0,32 +-gpgpu_cache:dl2_texture_only 0 + +-gpgpu_cache:il1 4:128:4,L:R:f:N:L,A:2:32,4 +-gpgpu_tex_cache:l1 4:128:24,L:R:m:N:L,F:128:4,128:2 +-gpgpu_const_cache:l1 64:64:2,L:R:f:N:L,A:2:32,4 + +# enable operand collector +-gpgpu_operand_collector_num_units_sp 6 +-gpgpu_operand_collector_num_units_sfu 8 +-gpgpu_operand_collector_num_in_ports_sp 2 +-gpgpu_operand_collector_num_out_ports_sp 2 +-gpgpu_num_reg_banks 16 + +# shared memory bankconflict detection +-gpgpu_shmem_num_banks 32 +-gpgpu_shmem_limited_broadcast 0 +-gpgpu_shmem_warp_parts 1 + +-gpgpu_max_insn_issue_per_warp 1 + +# interconnection +-network_mode 1 +-inter_config_file config_fermi_islip.icnt + +# memory partition latency config +-rop_latency 120 +-dram_latency 100 + +# dram model config +-gpgpu_dram_scheduler 1 +# The DRAM return queue and the scheduler queue together should provide buffer +# to sustain the memory level parallelism to tolerate DRAM latency +# To allow 100% DRAM utility, there should at least be enough buffer to sustain +# the minimum DRAM latency (100 core cycles). I.e. +# Total buffer space required = 100 x 750MHz / 575MHz = 130 +-gpgpu_frfcfs_dram_sched_queue_size 16 +-gpgpu_dram_return_queue_size 114 + +# for Fermi, bus width is 384bits, this is 8 bytes (4 bytes at each DRAM chip) per memory partition +-gpgpu_n_mem_per_ctrlr 2 +-gpgpu_dram_buswidth 4 +-gpgpu_dram_burst_length 8 +-dram_data_command_freq_ratio 4 # GDDR5 is QDR +-gpgpu_mem_address_mask 1 +-gpgpu_mem_addr_mapping dramid@8;00000000.00000000.00000000.00000000.0000RRRR.RRRRRRRR.BBBCCCCB.CCSSSSSS + +# GDDR5 timing from hynix H5GQ1H24AFR +# to disable bank groups, set nbkgrp to 1 and tCCDL and tRTPL to 0 +-gpgpu_dram_timing_opt "nbk=16:CCD=2:RRD=6:RCD=12:RAS=28:RP=12:RC=40: + CL=12:WL=4:CDLR=5:WR=12:nbkgrp=4:CCDL=3:RTPL=2" + +# Fermi has two schedulers per core +-gpgpu_num_sched_per_core 2 +# Two Level Scheduler with active and pending pools +#-gpgpu_scheduler two_level_active:6:0:1 +# Loose round robbin scheduler +#-gpgpu_scheduler lrr +# Greedy then oldest scheduler +-gpgpu_scheduler gto + +# stat collection +-gpgpu_memlatency_stat 14 +-gpgpu_runtime_stat 500 +-enable_ptx_file_line_stats 1 +-visualizer_enabled 0 + +# tracing functionality +#-trace_enabled 1 +#-trace_components WARP_SCHEDULER,SCOREBOARD +#-trace_sampling_core 0 diff --git a/configs/tested-cfgs/SM2_GTX480/config_fermi_islip.icnt b/configs/tested-cfgs/SM2_GTX480/config_fermi_islip.icnt new file mode 100644 index 0000000..c399db9 --- /dev/null +++ b/configs/tested-cfgs/SM2_GTX480/config_fermi_islip.icnt @@ -0,0 +1,70 @@ +//21*1 fly with 32 flits per packet under gpgpusim injection mode +use_map = 0; +flit_size = 40; + +// currently we do not use this, see subnets below +network_count = 2; + +// Topology +topology = fly; +k = 27; +n = 1; + +// Routing + +routing_function = dest_tag; + +// Flow control + +num_vcs = 1; +vc_buf_size = 64; + +wait_for_tail_credit = 0; + +// Router architecture + +vc_allocator = islip; //separable_input_first; +sw_allocator = islip; //separable_input_first; +alloc_iters = 1; + +credit_delay = 0; +routing_delay = 0; +vc_alloc_delay = 1; +sw_alloc_delay = 1; + +input_speedup = 1; +output_speedup = 1; +internal_speedup = 2.0; + +// Traffic, GPGPU-Sim does not use this + +traffic = uniform; +packet_size ={{1,2,3,4},{10,20}}; +packet_size_rate={{1,1,1,1},{2,1}}; + +// Simulation - Don't change + +sim_type = gpgpusim; +//sim_type = latency; +injection_rate = 0.1; + +subnets = 2; + +// Always use read and write no matter following line +//use_read_write = 1; + + +read_request_subnet = 0; +read_reply_subnet = 1; +write_request_subnet = 0; +write_reply_subnet = 1; + +read_request_begin_vc = 0; +read_request_end_vc = 0; +write_request_begin_vc = 0; +write_request_end_vc = 0; +read_reply_begin_vc = 0; +read_reply_end_vc = 0; +write_reply_begin_vc = 0; +write_reply_end_vc = 0; + diff --git a/configs/tested-cfgs/SM2_GTX480/gpgpusim.config b/configs/tested-cfgs/SM2_GTX480/gpgpusim.config new file mode 100644 index 0000000..4096b09 --- /dev/null +++ b/configs/tested-cfgs/SM2_GTX480/gpgpusim.config @@ -0,0 +1,153 @@ +# functional simulator specification +-gpgpu_ptx_instruction_classification 0 +-gpgpu_ptx_sim_mode 0 +-gpgpu_ptx_force_max_capability 20 + + +# SASS execution (only supported with CUDA >= 4.0) +-gpgpu_ptx_convert_to_ptxplus 0 +-gpgpu_ptx_save_converted_ptxplus 0 + +# high level architecture configuration +-gpgpu_n_clusters 15 +-gpgpu_n_cores_per_cluster 1 +-gpgpu_n_mem 6 +-gpgpu_n_sub_partition_per_mchannel 2 + +# Fermi clock domains +#-gpgpu_clock_domains ::: +# In Fermi, each pipeline has 16 execution units, so the Core clock needs to be divided +# by 2. (GPGPU-Sim simulates a warp (32 threads) in a single cycle). 1400/2 = 700 +-gpgpu_clock_domains 700.0:700.0:700.0:924.0 + +# shader core pipeline config +-gpgpu_shader_registers 32768 +-gpgpu_occupancy_sm_number 20 + +# This implies a maximum of 48 warps/SM +-gpgpu_shader_core_pipeline 1536:32 +-gpgpu_shader_cta 8 +-gpgpu_simd_model 1 + +# Pipeline widths and number of FUs +# ID_OC_SP,ID_OC_DP,ID_OC_SFU,ID_OC_MEM,OC_EX_SP,OC_EX_DP,OC_EX_SFU,OC_EX_MEM,EX_WB +#For Fermi, DP unit =0, DP inst is executed on SFU +-gpgpu_pipeline_widths 2,0,1,1,2,0,1,1,2 +-gpgpu_num_sp_units 2 +-gpgpu_num_sfu_units 1 +-gpgpu_num_dp_units 0 + +# Instruction latencies and initiation intervals +# "ADD,MAX,MUL,MAD,DIV" +-ptx_opcode_latency_int 4,13,4,5,145 +-ptx_opcode_initiation_int 1,2,2,1,8 +-ptx_opcode_latency_fp 4,13,4,5,39 +-ptx_opcode_initiation_fp 1,2,1,1,4 +-ptx_opcode_latency_dp 8,19,8,8,330 +-ptx_opcode_initiation_dp 8,16,8,8,130 + + +# In Fermi, the cache and shared memory can be configured to 16kb:48kb(default) or 48kb:16kb +# ::,::::,::,:** +# ** Optional parameter - Required when mshr_type==Texture Fifo +# Note: Hashing set index function (H) only applies to a set size of 32 or 64. +-gpgpu_cache:dl1 N:32:128:4,L:L:m:N:H,S:64:8,8 +-gpgpu_shmem_size 49152 +-icnt_flit_size 40 +-gmem_skip_L1D 0 +-gpgpu_n_cluster_ejection_buffer_size 32 +-l1_latency 35 +-smem_latency 26 +-gpgpu_flush_l1_cache 1 + +# The alternative configuration for fermi in case cudaFuncCachePreferL1 is selected +#-gpgpu_cache:dl1 N:64:128:6,L:L:m:N:H,S:64:8,8 +#-gpgpu_shmem_size 16384 + +# 64 sets, each 128 bytes 8-way for each memory sub partition. This gives 786KB L2 cache +-gpgpu_cache:dl2 S:64:128:8,L:B:m:L:L,A:256:4,4:0,32 +-gpgpu_cache:dl2_texture_only 0 +-gpgpu_dram_partition_queues 64:64:64:64 +-perf_sim_memcpy 1 +-memory_partition_indexing 0 + +-gpgpu_cache:il1 N:4:128:4,L:R:f:N:L,S:2:32,4 +-gpgpu_tex_cache:l1 N:4:128:24,L:R:m:N:L,T:128:4,128:2 +-gpgpu_const_cache:l1 N:64:64:2,L:R:f:N:L,S:2:32,4 + +# enable operand collector +-gpgpu_operand_collector_num_units_sp 6 +-gpgpu_operand_collector_num_units_sfu 8 +-gpgpu_operand_collector_num_in_ports_sp 2 +-gpgpu_operand_collector_num_out_ports_sp 2 +-gpgpu_num_reg_banks 16 + +# shared memory bankconflict detection +-gpgpu_shmem_num_banks 32 +-gpgpu_shmem_limited_broadcast 0 +-gpgpu_shmem_warp_parts 1 +-gpgpu_coalesce_arch 20 + +-gpgpu_max_insn_issue_per_warp 1 + +# interconnection +-network_mode 1 +-inter_config_file config_fermi_islip.icnt + +# memory partition latency config +-rop_latency 120 +-dram_latency 100 + +# dram model config +-gpgpu_dram_scheduler 1 +# The DRAM return queue and the scheduler queue together should provide buffer +# to sustain the memory level parallelism to tolerate DRAM latency +# To allow 100% DRAM utility, there should at least be enough buffer to sustain +# the minimum DRAM latency (100 core cycles). I.e. +# Total buffer space required = 100 x 924MHz / 700MHz = 132 +-gpgpu_frfcfs_dram_sched_queue_size 64 +-gpgpu_dram_return_queue_size 116 + +# for Fermi, bus width is 384bits, this is 8 bytes (4 bytes at each DRAM chip) per memory partition +-gpgpu_n_mem_per_ctrlr 2 +-gpgpu_dram_buswidth 4 +-gpgpu_dram_burst_length 8 +-dram_data_command_freq_ratio 4 # GDDR5 is QDR +-gpgpu_mem_address_mask 1 +-gpgpu_mem_addr_mapping dramid@8;00000000.00000000.00000000.00000000.0000RRRR.RRRRRRRR.BBBCCCCB.CCSSSSSS + +# GDDR5 timing from hynix H5GQ1H24AFR +# to disable bank groups, set nbkgrp to 1 and tCCDL and tRTPL to 0 +-gpgpu_dram_timing_opt "nbk=16:CCD=2:RRD=6:RCD=12:RAS=28:RP=12:RC=40: + CL=12:WL=4:CDLR=5:WR=12:nbkgrp=4:CCDL=3:RTPL=2" + +# select lower bits for bnkgrp to increase bnkgrp parallelism +-dram_bnk_indexing_policy 0 +-dram_bnkgrp_indexing_policy 1 + +#-Seperate_Write_Queue_Enable 1 +#-Write_Queue_Size 64:56:32 + +# Fermi has two schedulers per core +-gpgpu_num_sched_per_core 2 +# Two Level Scheduler with active and pending pools +#-gpgpu_scheduler two_level_active:6:0:1 +# Loose round robbin scheduler +#-gpgpu_scheduler lrr +# Greedy then oldest scheduler +-gpgpu_scheduler gto + +# stat collection +-gpgpu_memlatency_stat 14 +-gpgpu_runtime_stat 500 +-enable_ptx_file_line_stats 1 +-visualizer_enabled 0 + +# power model configs +-power_simulation_enabled 1 +-gpuwattch_xml_file gpuwattch_gtx480.xml + +# tracing functionality +#-trace_enabled 1 +#-trace_components WARP_SCHEDULER,SCOREBOARD +#-trace_sampling_core 0 diff --git a/configs/tested-cfgs/SM2_GTX480/gpuwattch_gtx480.xml b/configs/tested-cfgs/SM2_GTX480/gpuwattch_gtx480.xml new file mode 100755 index 0000000..304e0fd --- /dev/null +++ b/configs/tested-cfgs/SM2_GTX480/gpuwattch_gtx480.xml @@ -0,0 +1,538 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/configs/tested-cfgs/SM6_TITANX/config_fermi_islip.icnt b/configs/tested-cfgs/SM6_TITANX/config_fermi_islip.icnt new file mode 100644 index 0000000..dec4789 --- /dev/null +++ b/configs/tested-cfgs/SM6_TITANX/config_fermi_islip.icnt @@ -0,0 +1,73 @@ +//21*1 fly with 32 flits per packet under gpgpusim injection mode +use_map = 0; +flit_size = 40; + +// currently we do not use this, see subnets below +network_count = 2; + +// Topology +topology = fly; +k = 52; +n = 1; + +// Routing + +routing_function = dest_tag; + +// Flow control + +num_vcs = 1; +vc_buf_size = 64; +input_buffer_size = 256; +ejection_buffer_size = 64; +boundary_buffer_size = 64; + +wait_for_tail_credit = 0; + +// Router architecture + +vc_allocator = islip; //separable_input_first; +sw_allocator = islip; //separable_input_first; +alloc_iters = 1; + +credit_delay = 0; +routing_delay = 0; +vc_alloc_delay = 1; +sw_alloc_delay = 1; + +input_speedup = 1; +output_speedup = 1; +internal_speedup = 2.0; + +// Traffic, GPGPU-Sim does not use this + +traffic = uniform; +packet_size ={{1,2,3,4},{10,20}}; +packet_size_rate={{1,1,1,1},{2,1}}; + +// Simulation - Don't change + +sim_type = gpgpusim; +//sim_type = latency; +injection_rate = 0.1; + +subnets = 2; + +// Always use read and write no matter following line +//use_read_write = 1; + + +read_request_subnet = 0; +read_reply_subnet = 1; +write_request_subnet = 0; +write_reply_subnet = 1; + +read_request_begin_vc = 0; +read_request_end_vc = 0; +write_request_begin_vc = 0; +write_request_end_vc = 0; +read_reply_begin_vc = 0; +read_reply_end_vc = 0; +write_reply_begin_vc = 0; +write_reply_end_vc = 0; + diff --git a/configs/tested-cfgs/SM6_TITANX/gpgpusim.config b/configs/tested-cfgs/SM6_TITANX/gpgpusim.config new file mode 100644 index 0000000..3842508 --- /dev/null +++ b/configs/tested-cfgs/SM6_TITANX/gpgpusim.config @@ -0,0 +1,185 @@ +# This config models the Pascal GP102 (NVIDIA TITAN X) +# For more info about this card, see Nvidia White paper +# http://international.download.nvidia.com/geforce-com/international/pdfs/GeForce_GTX_1080_Whitepaper_FINAL.pdf + +# functional simulator specification +-gpgpu_ptx_instruction_classification 0 +-gpgpu_ptx_sim_mode 0 +-gpgpu_ptx_force_max_capability 61 +-gpgpu_ignore_resources_limitation 1 + +# SASS execution (only supported with CUDA >= 4.0) +-gpgpu_ptx_convert_to_ptxplus 0 +-gpgpu_ptx_save_converted_ptxplus 0 + +# high level architecture configuration +# P102 has two semi-indp scheds per core, and two cores per cluster +-gpgpu_n_clusters 28 +-gpgpu_n_cores_per_cluster 2 +-gpgpu_n_mem 12 +-gpgpu_n_sub_partition_per_mchannel 2 + +# Pascal clock domains +#-gpgpu_clock_domains ::: +# Pascal NVIDIA TITAN X clock domains are adopted from +# https://en.wikipedia.org/wiki/GeForce_10_series +-gpgpu_clock_domains 1417.0:1417.0:1417.0:2500.0 + +# shader core pipeline config +-gpgpu_shader_registers 32768 +-gpgpu_occupancy_sm_number 62 + +# This implies a maximum of 32 warps/SM +-gpgpu_shader_core_pipeline 1024:32 +-gpgpu_shader_cta 16 +-gpgpu_simd_model 1 + +# Pipeline widths and number of FUs +# ID_OC_SP,ID_OC_DP,ID_OC_SFU,ID_OC_MEM,OC_EX_SP,OC_EX_DP,OC_EX_SFU,OC_EX_MEM,EX_WB +## Pascal GP102 has 4 SP SIMD units and 4 SFU units +## we need to scale the number of pipeline registers to be equal to the number of SP units +-gpgpu_pipeline_widths 2,1,2,1,2,1,2,1,5 +-gpgpu_num_sp_units 2 +-gpgpu_num_sfu_units 2 +-gpgpu_num_dp_units 1 + + +# Instruction latencies and initiation intervals +# "ADD,MAX,MUL,MAD,DIV" +# All Div operations are executed on SFU unit +# Throughput (initiation latency) are adopted from CUDA SDK document V8, section 5.4.1, Table 2 +-ptx_opcode_latency_int 4,13,4,5,145 +-ptx_opcode_initiation_int 1,1,1,1,4 +-ptx_opcode_latency_fp 4,13,4,5,39 +-ptx_opcode_initiation_fp 1,2,1,1,4 +-ptx_opcode_latency_dp 8,19,8,8,330 +-ptx_opcode_initiation_dp 8,8,8,8,130 +-ptx_opcode_initiation_sfu 4 +-ptx_opcode_latency_sfu 8 + + +# latencies and cache configs are adopted from: +# https://arxiv.org/pdf/1804.06826.pdf +# ::,::::,::,:** +# ** Optional parameter - Required when mshr_type==Texture Fifo +# Note: Hashing set index function (H) only applies to a set size of 32 or 64. +# Pascal GP102 has 96KB Shared memory divided over 2 cores, each has 48KB +# Pascal GP102 has 2 banks L1 cache, where each is 24KB L1 cache +# The defulat is to disable the L1 cache, unless cache modifieres are used +-gpgpu_cache:dl1 S:4:128:48,L:L:s:N:L,A:256:8,16:0,32 +-gpgpu_cache:dl1PrefL1 S:4:128:48,L:L:s:N:L,A:256:8,16:0,32 +-gpgpu_cache:dl1PrefShared S:4:128:48,L:L:s:N:L,A:256:8,16:0,32 +-gpgpu_shmem_size 49152 +-gpgpu_shmem_size_PrefL1 49152 +-gpgpu_shmem_size_PrefShared 49152 +# By default, L1 cache is disabled in Pascal P102. +# requests with .nc modifier or __ldg mehtod will be cached in L1 cache even with gmem_skip_L1D=1 +-gmem_skip_L1D 1 +-icnt_flit_size 40 +-gpgpu_n_cluster_ejection_buffer_size 32 +-l1_latency 82 +-smem_latency 24 +-gpgpu_flush_l1_cache 1 + +# 64 sets, each 128 bytes 16-way for each memory sub partition (128 KB per memory sub partition). This gives 3MB L2 cache +-gpgpu_cache:dl2 S:64:128:16,L:B:m:L:L,A:256:64,16:0,32 +-gpgpu_cache:dl2_texture_only 0 +-gpgpu_dram_partition_queues 32:32:32:32 +-perf_sim_memcpy 1 + +# 4 KB Inst. +-gpgpu_cache:il1 N:8:128:4,L:R:f:N:L,S:2:48,4 +# 48 KB Tex +# Note, TEX is deprected in Volta, It is used for legacy apps only. Use L1D cache instead with .nc modifier or __ldg mehtod +-gpgpu_tex_cache:l1 N:16:128:24,L:R:m:N:L,T:128:4,128:2 +# 12 KB Const +-gpgpu_const_cache:l1 N:128:64:2,L:R:f:N:L,S:2:64,4 + +# enable operand collector +-gpgpu_operand_collector_num_units_sp 12 +-gpgpu_operand_collector_num_units_sfu 6 +-gpgpu_operand_collector_num_units_mem 8 +-gpgpu_operand_collector_num_units_dp 6 +-gpgpu_operand_collector_num_in_ports_sp 2 +-gpgpu_operand_collector_num_out_ports_sp 2 +-gpgpu_operand_collector_num_in_ports_sfu 2 +-gpgpu_operand_collector_num_out_ports_sfu 2 +-gpgpu_operand_collector_num_in_ports_mem 1 +-gpgpu_operand_collector_num_out_ports_mem 1 +-gpgpu_operand_collector_num_in_ports_dp 1 +-gpgpu_operand_collector_num_out_ports_dp 1 +-gpgpu_num_reg_banks 32 + +# shared memory bankconflict detection +-gpgpu_shmem_num_banks 32 +-gpgpu_shmem_limited_broadcast 0 +-gpgpu_shmem_warp_parts 1 +# Use Pascal Coalsce arhitetecture +-gpgpu_coalesce_arch 61 + +## In Pascal, a warp scheduler can issue 2 insts per cycle using 2 diff execution units +-gpgpu_max_insn_issue_per_warp 2 +-gpgpu_dual_issue_diff_exec_units 1 + +# interconnection +-network_mode 1 +-inter_config_file config_fermi_islip.icnt + +# memory partition latency config +-rop_latency 120 +-dram_latency 100 + +# dram model config +-gpgpu_dram_scheduler 1 +# The DRAM return queue and the scheduler queue together should provide buffer +# to sustain the memory level parallelism to tolerate DRAM latency +# To allow 100% DRAM utility, there should at least be enough buffer to sustain +# the minimum DRAM latency (100 core cycles). I.e. +# Total buffer space required = 100 x 924MHz / 700MHz = 132 +-gpgpu_frfcfs_dram_sched_queue_size 64 +-gpgpu_dram_return_queue_size 240 + +# for NVIDIA TITAN X, bus width is 384bits (12 DRAM chips x 32 bits) +# 12 memory paritions, 4 bytes (1 DRAM chip) per memory partition +# the atom size of GDDR5X (the smallest read request) is 32 bytes +-gpgpu_n_mem_per_ctrlr 1 +-gpgpu_dram_buswidth 4 +-gpgpu_dram_burst_length 8 +-dram_data_command_freq_ratio 4 # GDDR5X is QDR +-gpgpu_mem_address_mask 1 +-gpgpu_mem_addr_mapping dramid@8;00000000.00000000.00000000.00000000.0000RRRR.RRRRRRRR.RBBBCCCC.BCCSSSSS + +# Use the same GDDR5 timing +-gpgpu_dram_timing_opt "nbk=16:CCD=2:RRD=8:RCD=16:RAS=37:RP=16:RC=52: + CL=16:WL=6:CDLR=7:WR=16:nbkgrp=4:CCDL=4:RTPL=3" + +-dram_bnk_indexing_policy 0 +-dram_bnkgrp_indexing_policy 1 + +#-Seperate_Write_Queue_Enable 1 +#-Write_Queue_Size 64:56:32 + +# Pascal 102 has four schedulers per core +-gpgpu_num_sched_per_core 2 +# Two Level Scheduler with active and pending pools +#-gpgpu_scheduler two_level_active:6:0:1 +# Loose round robbin scheduler +#-gpgpu_scheduler lrr +# Greedy then oldest scheduler +-gpgpu_scheduler gto + +# stat collection +-gpgpu_memlatency_stat 14 +-gpgpu_runtime_stat 500 +-enable_ptx_file_line_stats 1 +-visualizer_enabled 0 + +# power model configs, disable it untill we create a real energy model for Pascal 102 +-power_simulation_enabled 0 +-gpuwattch_xml_file gpuwattch_gtx480.xml + +# tracing functionality +#-trace_enabled 1 +#-trace_components WARP_SCHEDULER,SCOREBOARD +#-trace_sampling_core 0 + diff --git a/configs/tested-cfgs/SM7_TITANV/config_fermi_islip.icnt b/configs/tested-cfgs/SM7_TITANV/config_fermi_islip.icnt new file mode 100644 index 0000000..2f25889 --- /dev/null +++ b/configs/tested-cfgs/SM7_TITANV/config_fermi_islip.icnt @@ -0,0 +1,74 @@ +//21*1 fly with 32 flits per packet under gpgpusim injection mode +use_map = 0; +flit_size = 40; + +// currently we do not use this, see subnets below +network_count = 2; + +// Topology +topology = fly; +k = 64; +n = 1; + +// Routing + +routing_function = dest_tag; + + +// Flow control + +num_vcs = 1; +vc_buf_size = 256; +input_buffer_size = 256; +ejection_buffer_size = 256; +boundary_buffer_size = 256; + +wait_for_tail_credit = 0; + +// Router architecture + +vc_allocator = islip; //separable_input_first; +sw_allocator = islip; //separable_input_first; +alloc_iters = 1; + +credit_delay = 0; +routing_delay = 0; +vc_alloc_delay = 1; +sw_alloc_delay = 1; + +input_speedup = 1; +output_speedup = 1; +internal_speedup = 2.0; + +// Traffic, GPGPU-Sim does not use this + +traffic = uniform; +packet_size ={{1,2,3,4},{10,20}}; +packet_size_rate={{1,1,1,1},{2,1}}; + +// Simulation - Don't change + +sim_type = gpgpusim; +//sim_type = latency; +injection_rate = 0.1; + +subnets = 2; + +// Always use read and write no matter following line +//use_read_write = 1; + + +read_request_subnet = 0; +read_reply_subnet = 1; +write_request_subnet = 0; +write_reply_subnet = 1; + +read_request_begin_vc = 0; +read_request_end_vc = 0; +write_request_begin_vc = 0; +write_request_end_vc = 0; +read_reply_begin_vc = 0; +read_reply_end_vc = 0; +write_reply_begin_vc = 0; +write_reply_end_vc = 0; + diff --git a/configs/tested-cfgs/SM7_TITANV/gpgpusim.config b/configs/tested-cfgs/SM7_TITANV/gpgpusim.config new file mode 100644 index 0000000..c8351da --- /dev/null +++ b/configs/tested-cfgs/SM7_TITANV/gpgpusim.config @@ -0,0 +1,191 @@ +# This config models the Volta Titan X +# For more info about this card: +# http://images.nvidia.com/content/volta-architecture/pdf/volta-architecture-whitepaper.pdf +# https://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=8344474&tag=1# +# http://on-demand.gputechconf.com/gtc/2018/presentation/s8122-dissecting-the-volta-gpu-architecture-through-microbenchmarking.pdf +# https://en.wikipedia.org/wiki/Volta_(microarchitecture) +# https://www.hotchips.org/wp-content/uploads/hc_archives/hc29/HC29.21-Monday-Pub/HC29.21.10-GPU-Gaming-Pub/HC29.21.132-Volta-Choquette-NVIDIA-Final3.pdf +# https://devblogs.nvidia.com/inside-volta/ +# http://on-demand.gputechconf.com/gtc/2017/presentation/s7798-luke-durant-inside-volta.pdf + +# functional simulator specification +-gpgpu_ptx_instruction_classification 0 +-gpgpu_ptx_sim_mode 0 +-gpgpu_ptx_force_max_capability 70 + +# SASS execution (only supported with CUDA >= 4.0) +-gpgpu_ptx_convert_to_ptxplus 0 +-gpgpu_ptx_save_converted_ptxplus 0 + +# high level architecture configuration +-gpgpu_n_clusters 40 +-gpgpu_n_cores_per_cluster 2 +-gpgpu_n_mem 24 +-gpgpu_n_sub_partition_per_mchannel 1 + +# volta clock domains +#-gpgpu_clock_domains ::: +# Volta NVIDIA GV100 clock domains are adopted from +# https://en.wikipedia.org/wiki/Volta_(microarchitecture) +-gpgpu_clock_domains 1200.0:2000.0:1200.0:850.0 +# boost mode +# -gpgpu_clock_domains 1455.0:2000.0:1455.0:850.0 + +# shader core pipeline config +-gpgpu_shader_registers 65536 +-gpgpu_occupancy_sm_number 70 + +# This implies a maximum of 64 warps/SM +-gpgpu_shader_core_pipeline 2048:32 +-gpgpu_shader_cta 32 +-gpgpu_simd_model 1 + +# Pipeline widths and number of FUs +# ID_OC_SP,ID_OC_DP,ID_OC_SFU,ID_OC_MEM,OC_EX_SP,OC_EX_DP,OC_EX_SFU,OC_EX_MEM,EX_WB +## Volta GV100 has 2 SP SIMD units, 2 SFU units, 2 DP units per core +## we need to scale the number of pipeline registers to be equal to the number of SP units +-gpgpu_pipeline_widths 4,4,4,1,4,4,4,1,12 +-gpgpu_num_sp_units 4 +-gpgpu_num_sfu_units 4 +-gpgpu_num_dp_units 4 + +# Instruction latencies and initiation intervals +# "ADD,MAX,MUL,MAD,DIV" +# All Div operations are executed on SFU unit +# Throughput (initiation latency) are adopted from +# http://on-demand.gputechconf.com/gtc/2018/presentation/s8122-dissecting-the-volta-gpu-architecture-through-microbenchmarking.pdf +-ptx_opcode_latency_int 4,13,4,5,145 +-ptx_opcode_initiation_int 2,2,2,2,8 +-ptx_opcode_latency_fp 4,13,4,5,39 +-ptx_opcode_initiation_fp 2,2,2,2,4 +-ptx_opcode_latency_dp 8,19,8,8,330 +-ptx_opcode_initiation_dp 4,4,4,4,130 +-ptx_opcode_latency_sfu 100 +-ptx_opcode_initiation_sfu 8 + + +# ::,::::,::,:** +# ** Optional parameter - Required when mshr_type==Texture Fifo +# Defualt config is 32KB DL1 and 96KB shared memory +# In Volta, we assign the remaining shared memory to L1 cache +# if the assigned shd mem = 0, then L1 cache = 128KB +# For more info, see https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#shared-memory-7-x +# disable this mode in case of multi kernels/apps execution +-adpative_volta_cache_config 1 +-gpgpu_cache:dl1 S:4:128:64,L:L:s:N:L,A:256:8,16:0,32 +-gpgpu_shmem_size 98304 +-gmem_skip_L1D 0 +-icnt_flit_size 40 +-gpgpu_n_cluster_ejection_buffer_size 32 +-l1_latency 28 +-smem_latency 19 +-gpgpu_flush_l1_cache 1 + +# 64 sets, each 128 bytes 24-way for each memory sub partition (192 KB per memory sub partition). This gives 4.5MB L2 cache +-gpgpu_cache:dl2 S:64:128:24,L:B:m:L:L,A:384:4,32:0,32 +-gpgpu_cache:dl2_texture_only 0 +-gpgpu_dram_partition_queues 64:64:64:64 +-perf_sim_memcpy 1 + +# 128 KB Inst. +-gpgpu_cache:il1 N:64:128:16,L:R:f:N:L,S:2:48,4 +# 48 KB Tex +# Note, TEX is deprected in Volta, It is used for legacy apps only. Use L1D cache instead with .nc modifier or __ldg mehtod +-gpgpu_tex_cache:l1 N:16:128:24,L:R:m:N:L,T:128:4,128:2 +# 64 KB Const +-gpgpu_const_cache:l1 N:128:64:8,L:R:f:N:L,S:2:64,4 + +# enable operand collector +-gpgpu_operand_collector_num_units_sp 12 +-gpgpu_operand_collector_num_units_sfu 6 +-gpgpu_operand_collector_num_units_mem 8 +-gpgpu_operand_collector_num_units_dp 6 +-gpgpu_operand_collector_num_in_ports_sp 4 +-gpgpu_operand_collector_num_out_ports_sp 4 +-gpgpu_operand_collector_num_in_ports_sfu 1 +-gpgpu_operand_collector_num_out_ports_sfu 1 +-gpgpu_operand_collector_num_in_ports_mem 1 +-gpgpu_operand_collector_num_out_ports_mem 1 +-gpgpu_operand_collector_num_in_ports_dp 1 +-gpgpu_operand_collector_num_out_ports_dp 1 +-gpgpu_num_reg_banks 32 + +# shared memory bankconflict detection +-gpgpu_shmem_num_banks 32 +-gpgpu_shmem_limited_broadcast 0 +-gpgpu_shmem_warp_parts 1 +-gpgpu_coalesce_arch 60 + +## In Pascal, a warp scheduler can issue 2 insts per cycle using 2 diff execution units +-gpgpu_max_insn_issue_per_warp 1 +-gpgpu_dual_issue_diff_exec_units 1 + +# interconnection +-network_mode 1 +-inter_config_file config_fermi_islip.icnt + +# memory partition latency config +-rop_latency 120 +-dram_latency 100 + +# dram model config +-gpgpu_dram_scheduler 1 +# The DRAM return queue and the scheduler queue together should provide buffer +# to sustain the memory level parallelism to tolerate DRAM latency +# To allow 100% DRAM utility, there should at least be enough buffer to sustain +# the minimum DRAM latency (100 core cycles). I.e. +# Total buffer space required = 100 x 924MHz / 700MHz = 132 +-gpgpu_frfcfs_dram_sched_queue_size 64 +-gpgpu_dram_return_queue_size 192 + +# for HBM, 32 channles, each (128 bits) 16 bytes width +-gpgpu_n_mem_per_ctrlr 1 +-gpgpu_dram_buswidth 16 +-gpgpu_dram_burst_length 2 +-dram_data_command_freq_ratio 2 # HBM is DDR +-gpgpu_mem_address_mask 1 +-gpgpu_mem_addr_mapping dramid@8;00000000.00000000.00000000.00000000.0000RRRR.RRRRRRRR.RBBBBCCC.CCCSSSSS + +# HBM timing are adopted from hynix JESD235 standered and nVidia HPCA 2017 paper (http://www.cs.utah.edu/~nil/pubs/hpca17.pdf) +# Timing for 1 GHZ +# tRRDl and tWTR are missing, need to be added +#-gpgpu_dram_timing_opt "nbk=16:CCD=1:RRD=4:RCD=14:RAS=33:RP=14:RC=47: +# CL=14:WL=2:CDLR=3:WR=12:nbkgrp=4:CCDL=2:RTPL=4" + +# Timing for 715 MHZ, Tesla Volta V100 HBM runs at 715 MHZ +-gpgpu_dram_timing_opt "nbk=16:CCD=1:RRD=3:RCD=10:RAS=24:RP=10:RC=34: + CL=10:WL=2:CDLR=3:WR=9:nbkgrp=4:CCDL=2:RTPL=3" + +# HBM has dual bus interface, in which it can issue two col and row commands at a time +-dual_bus_interface 1 +# select lower bits for bnkgrp to increase bnkgrp parallelism +-dram_bnk_indexing_policy 0 +-dram_bnkgrp_indexing_policy 1 + +#-Seperate_Write_Queue_Enable 1 +#-Write_Queue_Size 64:56:32 + +# Pascal has two schedulers per core +-gpgpu_num_sched_per_core 4 +# Two Level Scheduler with active and pending pools +#-gpgpu_scheduler two_level_active:6:0:1 +# Loose round robbin scheduler +#-gpgpu_scheduler lrr +# Greedy then oldest scheduler +-gpgpu_scheduler gto + +# stat collection +-gpgpu_memlatency_stat 14 +-gpgpu_runtime_stat 500 +-enable_ptx_file_line_stats 1 +-visualizer_enabled 0 + +# power model configs, disable it untill we create a real energy model for Pascal 100 +-power_simulation_enabled 0 +-gpuwattch_xml_file gpuwattch_gtx480.xml + +# tracing functionality +#-trace_enabled 1 +#-trace_components WARP_SCHEDULER,SCOREBOARD +#-trace_sampling_core 0 + diff --git a/cuobjdump_to_ptxplus/ptx_parser.h b/cuobjdump_to_ptxplus/ptx_parser.h index a534e92..ee7a942 100644 --- a/cuobjdump_to_ptxplus/ptx_parser.h +++ b/cuobjdump_to_ptxplus/ptx_parser.h @@ -376,4 +376,8 @@ void func_header_info_int(const char* s, int i) g_headerList->getListEnd().addOperand(buff); } } + +void maxnt_id(int x, int y, int z) { + +} #endif //_PTX_PARSER_H_ diff --git a/libcuda/cuda_runtime_api.cc b/libcuda/cuda_runtime_api.cc index d67fd85..61af0ee 100644 --- a/libcuda/cuda_runtime_api.cc +++ b/libcuda/cuda_runtime_api.cc @@ -338,10 +338,19 @@ struct _cuda_device_id *GPGPUSim_Init() prop->minor = 2; prop->totalGlobalMem = 0x80000000 /* 2 GB */; prop->memPitch = 0; - prop->maxThreadsPerBlock = 512; - prop->maxThreadsDim[0] = 512; - prop->maxThreadsDim[1] = 512; - prop->maxThreadsDim[2] = 512; + if(prop->major >= 2) { + prop->maxThreadsPerBlock = 1024; + prop->maxThreadsDim[0] = 1024; + prop->maxThreadsDim[1] = 1024; + } + else + { + prop->maxThreadsPerBlock = 512; + prop->maxThreadsDim[0] = 512; + prop->maxThreadsDim[1] = 512; + } + + prop->maxThreadsDim[2] = 64; prop->maxGridSize[0] = 0x40000000; prop->maxGridSize[1] = 0x40000000; prop->maxGridSize[2] = 0x40000000; @@ -353,6 +362,9 @@ struct _cuda_device_id *GPGPUSim_Init() prop->clockRate = the_gpu->shader_clock(); #if (CUDART_VERSION >= 2010) prop->multiProcessorCount = the_gpu->get_config().num_shader(); +#endif +#if (CUDART_VERSION >= 4000) + prop->maxThreadsPerMultiProcessor = the_gpu->threads_per_core(); #endif the_gpu->set_prop(prop); the_device = new _cuda_device_id(the_gpu); @@ -2167,8 +2179,28 @@ cudaError_t CUDARTAPI cudaSetValidDevices(int *device_arr, int len) cudaError_t CUDARTAPI cudaSetDeviceFlags( int flags ) { - cuda_not_implemented(__my_func__,__LINE__); - return g_last_cudaError = cudaErrorUnknown; + // This flag is implicitly always on (unless you are using the driver API). It is safe for GPGPU-Sim to + // just ignore it. + if ( cudaDeviceMapHost == flags ) { + return g_last_cudaError = cudaSuccess; + } else { + cuda_not_implemented(__my_func__,__LINE__); + return g_last_cudaError = cudaErrorUnknown; + } +} + +size_t getMaxThreadsPerBlock(struct cudaFuncAttributes *attr) { + _cuda_device_id *dev = GPGPUSim_Init(); + struct cudaDeviceProp prop; + + prop = *dev->get_prop(); + + size_t max = prop.maxThreadsPerBlock; + + if ((prop.regsPerBlock / attr->numRegs) < max) + max = prop.regsPerBlock / attr->numRegs; + + return max; } cudaError_t CUDARTAPI cudaFuncGetAttributes(struct cudaFuncAttributes *attr, const char *hostFun ) @@ -2181,7 +2213,10 @@ cudaError_t CUDARTAPI cudaFuncGetAttributes(struct cudaFuncAttributes *attr, con attr->constSizeBytes = kinfo->cmem; attr->localSizeBytes = kinfo->lmem; attr->numRegs = kinfo->regs; - attr->maxThreadsPerBlock = 0; // from pragmas? + if(kinfo->maxthreads > 0) + attr->maxThreadsPerBlock = kinfo->maxthreads; + else + attr->maxThreadsPerBlock = getMaxThreadsPerBlock(attr); #if CUDART_VERSION >= 3000 attr->ptxVersion = kinfo->ptx_version; attr->binaryVersion = kinfo->sm_target; diff --git a/nightly.jenkinsfile b/nightly.jenkinsfile new file mode 100644 index 0000000..5221b3b --- /dev/null +++ b/nightly.jenkinsfile @@ -0,0 +1,75 @@ +pipeline { + agent { + label "purdue-cluster" + } + + options { + disableConcurrentBuilds() + overrideIndexTriggers(true) + } + + triggers { + pollSCM('0 1 * * *') + } + + stages { + stage('nightly-simulator-build') { + steps { + sh 'source /home/tgrogers-raid/a/common/gpgpu-sim-setup/9.1_env_setup.sh &&\ + source `pwd`/setup_environment &&\ + make -j' + } + } + stage('nightly-simulations-build'){ + steps{ + sh 'rm -rf gpgpu-sim_simulations' + sh 'git clone git@github.rcac.purdue.edu:TimRogersGroup/gpgpu-sim_simulations.git && \ + cd gpgpu-sim_simulations && \ + git checkout purdue-cluster && \ + git pull && \ + ln -s /home/tgrogers-raid/a/common/data_dirs benchmarks/' + sh 'source /home/tgrogers-raid/a/common/gpgpu-sim-setup/9.1_env_setup.sh &&\ + source `pwd`/setup_environment &&\ + cd gpgpu-sim_simulations && \ + source ./benchmarks/src/setup_environment && \ + make -i -j -C ./benchmarks/src/ all && \ + make -C ./benchmarks/src data' + } + } + stage('nightly-2B-insn-run'){ + steps { + sh 'source /home/tgrogers-raid/a/common/gpgpu-sim-setup/9.1_env_setup.sh &&\ + source `pwd`/setup_environment &&\ + ./gpgpu-sim_simulations/util/job_launching/run_simulations.py -B `cat ./gpgpu-sim_simulations/util/job_launching/apps/all-apps.list` -C TITANX-2B,TITANX-L1ON-2B,P100-2B,TITANV-2B -N nightly-$$ && \ + PLOTDIR="jenkins/${JOB_NAME}/${BUILD_NUMBER}/getstats" && ssh tgrogers@dynamo.ecn.purdue.edu mkdir -p /home/dynamo/a/tgrogers/website/gpgpu-sim-plots/$PLOTDIR && \ + ./gpgpu-sim_simulations/util/job_launching/monitor_func_test.py -I -S 1800 -v -s stats-$$.csv -N nightly-$$ && \ + ./gpgpu-sim_simulations/util/plotting/plot-get-stats.py -c stats-$$.csv -p tgrogers@dynamo.ecn.purdue.edu:~/website/gpgpu-sim-plots/$PLOTDIR -w https://engineering.purdue.edu/tgrogers/gpgpu-sim-plots/$PLOTDIR -n $PLOTDIR' + } + } + stage('nightly-correlate'){ + steps { + sh 'source /home/tgrogers-raid/a/common/gpgpu-sim-setup/9.1_env_setup.sh &&\ + source `pwd`/setup_environment &&\ + PLOTDIR="jenkins/${JOB_NAME}" &&\ + ./gpgpu-sim_simulations/util/job_launching/get_stats.py -R -K -k -B `cat ./gpgpu-sim_simulations/util/job_launching/apps/all-apps.list` -C TITANX-2B,TITANX-L1ON-2B,P100-2B,TITANV-2B > nightly-stats-per-kernel-9.1.csv &&\ + ./gpgpu-sim_simulations/util/plotting/correlate_and_publish.sh nightly-stats-per-kernel-9.1.csv $PLOTDIR ${BUILD_NUMBER}' + } + } + } + post { + success { + emailext body: "See ${BUILD_URL}", + recipientProviders: [[$class: 'CulpritsRecipientProvider'], + [$class: 'RequesterRecipientProvider']], + subject: "[AALP Jenkins] Build #${BUILD_NUMBER} - Success!", + to: 'tgrogers@purdue.edu' + } + failure { + emailext body: "See ${BUILD_URL}", + recipientProviders: [[$class: 'CulpritsRecipientProvider'], + [$class: 'RequesterRecipientProvider']], + subject: "[AALP Jenkins] Build #${BUILD_NUMBER} - ${currentBuild.result}", + to: 'tgrogers@purdue.edu' + } + } +} diff --git a/setup_environment b/setup_environment index f1af978..9578942 100644 --- a/setup_environment +++ b/setup_environment @@ -1,6 +1,6 @@ # see README before running this -ps -p $$ | awk '/bash/ || / sh/ || /zsh/ {exit 1;}' && echo "ERROR ** source setup_environment must be run in a bash, zsh or sh shell; see README" && exit +ps -p $$ | awk '/bash/ || / sh/ || /zsh/ {exit 1;}' && echo "WARNING ** source setup_environment must be run in a bash, zsh or sh shell; see README" export GPGPUSIM_SETUP_ENVIRONMENT_WAS_RUN= export GPGPUSIM_ROOT="$( cd "$( dirname "$BASH_SOURCE" )" && pwd )" diff --git a/src/abstract_hardware_model.cc b/src/abstract_hardware_model.cc index f7f1016..acb376a 100644 --- a/src/abstract_hardware_model.cc +++ b/src/abstract_hardware_model.cc @@ -316,12 +316,12 @@ void warp_inst_t::generate_mem_accesses() break; case global_space: case local_space: case param_space_local: - if( m_config->gpgpu_coalesce_arch == 13 ) { - if(isatomic()) - memory_coalescing_arch_13_atomic(is_write, access_type); - else - memory_coalescing_arch_13(is_write, access_type); - } else abort(); + if( m_config->gpgpu_coalesce_arch >= 13 && m_config->gpgpu_coalesce_arch <= 62) { + if(isatomic()) + memory_coalescing_arch_atomic(is_write, access_type); + else + memory_coalescing_arch(is_write, access_type); + } else abort(); break; @@ -345,7 +345,7 @@ void warp_inst_t::generate_mem_accesses() byte_mask.set(idx+i); } for( a=accesses.begin(); a != accesses.end(); ++a ) - m_accessq.push_back( mem_access_t(access_type,a->first,cache_block_size,is_write,a->second,byte_mask) ); + m_accessq.push_back( mem_access_t(access_type,a->first,cache_block_size,is_write,a->second, byte_mask, mem_access_sector_mask_t())); } if ( space.get_type() == global_space ) { @@ -354,15 +354,32 @@ void warp_inst_t::generate_mem_accesses() m_mem_accesses_created=true; } -void warp_inst_t::memory_coalescing_arch_13( bool is_write, mem_access_type access_type ) +void warp_inst_t::memory_coalescing_arch( bool is_write, mem_access_type access_type ) { // see the CUDA manual where it discusses coalescing rules before reading this unsigned segment_size = 0; unsigned warp_parts = m_config->mem_warp_parts; + bool sector_segment_size = false; + + if(m_config->gpgpu_coalesce_arch >= 20 && m_config->gpgpu_coalesce_arch < 39) + { + //Fermi and Kepler, L1 is normal and L2 is sector + if(m_config->gmem_skip_L1D || cache_op == CACHE_GLOBAL) + sector_segment_size = true; + else + sector_segment_size = false; + } + else if(m_config->gpgpu_coalesce_arch >= 40) + { + //Maxwell and Pascal, L1 and L2 are sectors + //all requests should be 32 bytes + sector_segment_size = true; + } + switch( data_size ) { case 1: segment_size = 32; break; - case 2: segment_size = 64; break; - case 4: case 8: case 16: segment_size = 128; break; + case 2: segment_size = sector_segment_size? 32 : 64; break; + case 4: case 8: case 16: segment_size = sector_segment_size? 32 : 128; break; } unsigned subwarp_size = m_config->warp_size / warp_parts; @@ -413,13 +430,13 @@ void warp_inst_t::memory_coalescing_arch_13( bool is_write, mem_access_type acce new_addr_type addr = t->first; const transaction_info &info = t->second; - memory_coalescing_arch_13_reduce_and_send(is_write, access_type, info, addr, segment_size); + memory_coalescing_arch_reduce_and_send(is_write, access_type, info, addr, segment_size); } } } -void warp_inst_t::memory_coalescing_arch_13_atomic( bool is_write, mem_access_type access_type ) +void warp_inst_t::memory_coalescing_arch_atomic( bool is_write, mem_access_type access_type ) { assert(space.get_type() == global_space); // Atomics allowed only for global memory @@ -488,13 +505,13 @@ void warp_inst_t::memory_coalescing_arch_13_atomic( bool is_write, mem_access_ty for(t=transaction_list.begin(); t!=transaction_list.end(); t++) { // For each transaction const transaction_info &info = *t; - memory_coalescing_arch_13_reduce_and_send(is_write, access_type, info, addr, segment_size); + memory_coalescing_arch_reduce_and_send(is_write, access_type, info, addr, segment_size); } } } } -void warp_inst_t::memory_coalescing_arch_13_reduce_and_send( bool is_write, mem_access_type access_type, const transaction_info &info, new_addr_type addr, unsigned segment_size ) +void warp_inst_t::memory_coalescing_arch_reduce_and_send( bool is_write, mem_access_type access_type, const transaction_info &info, new_addr_type addr, unsigned segment_size ) { assert( (addr & (segment_size-1)) == 0 ); @@ -543,7 +560,7 @@ void warp_inst_t::memory_coalescing_arch_13_reduce_and_send( bool is_write, mem_ assert(lower_half_used && upper_half_used); } } - m_accessq.push_back( mem_access_t(access_type,addr,size,is_write,info.active,info.bytes) ); + m_accessq.push_back( mem_access_t(access_type,addr,size,is_write,info.active,info.bytes, info.chunks) ); } void warp_inst_t::completed( unsigned long long cycle ) const @@ -577,6 +594,8 @@ kernel_info_t::kernel_info_t( dim3 gridDim, dim3 blockDim, class function_info * //Jin: launch latency management m_launch_latency = g_kernel_launch_latency; + + volta_cache_config_set=false; } kernel_info_t::~kernel_info_t() diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index 71d3d89..a612bac 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -82,6 +82,7 @@ enum uarch_op_t { ALU_OP=1, SFU_OP, TENSOR_CORE_OP, + DP_OP, ALU_SFU_OP, LOAD_OP, TENSOR_CORE_LOAD_OP, @@ -139,6 +140,7 @@ typedef enum special_operations_t special_ops; // Required to identify for the p enum operation_pipeline_t { UNKOWN_OP, SP__OP, + DP__OP, SFU__OP, TENSOR_CORE__OP, MEM__OP @@ -308,6 +310,8 @@ public: unsigned long long start_cycle; unsigned long long end_cycle; unsigned m_launch_latency; + + mutable bool volta_cache_config_set; }; struct core_config { @@ -347,6 +351,7 @@ struct core_config { unsigned gpgpu_cache_constl1_linesize; unsigned gpgpu_max_insn_issue_per_warp; + bool gmem_skip_L1D; // on = global memory access always skip the L1 cache }; // bounded stack that implements simt reconvergence using pdom mechanism from MICRO'07 paper @@ -398,6 +403,7 @@ protected: #define LOCAL_MEM_SIZE_MAX (8*1024) #define MAX_STREAMING_MULTIPROCESSORS 64 #define MAX_THREAD_PER_SM 2048 +#define MAX_WARP_PER_SM 64 #define TOTAL_LOCAL_MEM_PER_SM (MAX_THREAD_PER_SM*LOCAL_MEM_SIZE_MAX) #define TOTAL_SHARED_MEM (MAX_STREAMING_MULTIPROCESSORS*SHARED_MEM_SIZE_MAX) #define TOTAL_LOCAL_MEM (MAX_STREAMING_MULTIPROCESSORS*MAX_THREAD_PER_SM*LOCAL_MEM_SIZE_MAX) @@ -523,7 +529,14 @@ public: const struct textureReference* get_texref(const std::string &texname) const { std::map::const_iterator t=m_NameToTextureRef.find(texname); - assert( t != m_NameToTextureRef.end() ); + if( t == m_NameToTextureRef.end() ) { + // search for :: prefixed names + std::string temp("::" + texname); + t=m_NameToTextureRef.find(temp); + } + + assert(t != m_NameToTextureRef.end()); + return t->second; } const struct cudaArray* get_texarray( const struct textureReference *texref ) const @@ -574,6 +587,7 @@ struct gpgpu_ptx_sim_info int cmem; int gmem; int regs; + unsigned maxthreads; unsigned ptx_version; unsigned sm_target; }; @@ -625,6 +639,9 @@ private: const unsigned MAX_MEMORY_ACCESS_SIZE = 128; typedef std::bitset mem_access_byte_mask_t; +const unsigned SECTOR_CHUNCK_SIZE = 4; //four sectors +const unsigned SECTOR_SIZE = 32 ; //sector is 32 bytes width +typedef std::bitset mem_access_sector_mask_t; #define NO_PARTIAL_WRITE (mem_access_byte_mask_t()) #define MEM_ACCESS_TYPE_TUP_DEF \ @@ -660,6 +677,7 @@ enum cache_operator_type { CACHE_ALL, // .ca CACHE_LAST_USE, // .lu CACHE_VOLATILE, // .cv + CACHE_L1, // .nc // loads and stores CACHE_STREAMING, // .cs @@ -689,8 +707,9 @@ public: unsigned size, bool wr, const active_mask_t &active_mask, - const mem_access_byte_mask_t &byte_mask ) - : m_warp_mask(active_mask), m_byte_mask(byte_mask) + const mem_access_byte_mask_t &byte_mask, + const mem_access_sector_mask_t §or_mask) + : m_warp_mask(active_mask), m_byte_mask(byte_mask), m_sector_mask(sector_mask) { init(); m_type = type; @@ -706,6 +725,7 @@ public: bool is_write() const { return m_write; } enum mem_access_type get_type() const { return m_type; } mem_access_byte_mask_t get_byte_mask() const { return m_byte_mask; } + mem_access_sector_mask_t get_sector_mask() const { return m_sector_mask; } void print(FILE *fp) const { @@ -739,6 +759,7 @@ private: mem_access_type m_type; active_mask_t m_warp_mask; mem_access_byte_mask_t m_byte_mask; + mem_access_sector_mask_t m_sector_mask; static unsigned sm_next_access_uid; }; @@ -961,9 +982,9 @@ public: }; void generate_mem_accesses(); - void memory_coalescing_arch_13( bool is_write, mem_access_type access_type ); - void memory_coalescing_arch_13_atomic( bool is_write, mem_access_type access_type ); - void memory_coalescing_arch_13_reduce_and_send( bool is_write, mem_access_type access_type, const transaction_info &info, new_addr_type addr, unsigned segment_size ); + void memory_coalescing_arch( bool is_write, mem_access_type access_type ); + void memory_coalescing_arch_atomic( bool is_write, mem_access_type access_type ); + void memory_coalescing_arch_reduce_and_send( bool is_write, mem_access_type access_type, const transaction_info &info, new_addr_type addr, unsigned segment_size ); void add_callback( unsigned lane_id, void (*function)(const class inst_t*, class ptx_thread_info*), diff --git a/src/cuda-sim/cuda-sim.cc b/src/cuda-sim/cuda-sim.cc index d5c5c3d..87a0b9c 100644 --- a/src/cuda-sim/cuda-sim.cc +++ b/src/cuda-sim/cuda-sim.cc @@ -62,8 +62,8 @@ addr_t g_debug_pc = 0xBEEF1518; unsigned g_ptx_sim_num_insn = 0; 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 *opcode_latency_int, *opcode_latency_fp, *opcode_latency_dp,*opcode_latency_sfu; +char *opcode_initiation_int, *opcode_initiation_fp, *opcode_initiation_dp,*opcode_initiation_sfu; char *cdp_latency_str; unsigned cdp_latency[5]; @@ -80,6 +80,10 @@ void ptx_opcocde_latency_options (option_parser_t opp) { "Opcode latencies for double precision floating points " "Default 8,8,8,8,335", "8,8,8,8,335"); + option_parser_register(opp, "-ptx_opcode_latency_sfu", OPT_CSTR, &opcode_latency_sfu, + "Opcode latencies for SFU instructions" + "Default 8", + "8"); option_parser_register(opp, "-ptx_opcode_initiation_int", OPT_CSTR, &opcode_initiation_int, "Opcode initiation intervals for integers " "Default 1,1,4,4,32", @@ -92,6 +96,10 @@ void ptx_opcocde_latency_options (option_parser_t opp) { "Opcode initiation intervals for double precision floating points " "Default 8,8,8,8,130", "8,8,8,8,130"); + option_parser_register(opp, "-ptx_opcode_initiation_sfu", OPT_CSTR, &opcode_initiation_sfu, + "Opcode initiation intervals for sfu instructions" + "Default 8", + "8"); option_parser_register(opp, "-cdp_latency", OPT_CSTR, &cdp_latency_str, "CDP API latency write(dst_start_addr+n,1, src_data+n,NULL,NULL); + + // Copy into the performance model. + extern gpgpu_sim* g_the_gpu; + g_the_gpu->perf_memcpy_to_gpu(dst_start_addr, count); if(g_debug_execution >= 3) { printf( " done.\n"); fflush(stdout); @@ -408,6 +420,10 @@ void gpgpu_t::memcpy_from_gpu( void *dst, size_t src_start_addr, size_t count ) unsigned char *dst_data = (unsigned char*)dst; for (unsigned n=0; n < count; n ++ ) m_global_mem->read(src_start_addr+n,1,dst_data+n); + + // Copy into the performance model. + extern gpgpu_sim* g_the_gpu; + g_the_gpu->perf_memcpy_to_gpu(src_start_addr, count); if(g_debug_execution >= 3) { printf( " done.\n"); fflush(stdout); @@ -592,9 +608,11 @@ void ptx_instruction::set_opcode_and_latency() unsigned int_latency[5]; unsigned fp_latency[5]; unsigned dp_latency[5]; + unsigned sfu_latency; unsigned int_init[5]; unsigned fp_init[5]; unsigned dp_init[5]; + unsigned sfu_init; /* * [0] ADD,SUB * [1] MAX,Min @@ -611,7 +629,9 @@ void ptx_instruction::set_opcode_and_latency() sscanf(opcode_latency_dp, "%u,%u,%u,%u,%u", &dp_latency[0],&dp_latency[1],&dp_latency[2], &dp_latency[3],&dp_latency[4]); - sscanf(opcode_initiation_int, "%u,%u,%u,%u,%u,%u, %u", + sscanf(opcode_latency_sfu, "%u", + &sfu_latency); + sscanf(opcode_initiation_int, "%u,%u,%u,%u,%u", &int_init[0],&int_init[1],&int_init[2], &int_init[3],&int_init[4]); sscanf(opcode_initiation_fp, "%u,%u,%u,%u,%u", @@ -620,8 +640,10 @@ 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(opcode_initiation_sfu, "%u", + &sfu_init); sscanf(cdp_latency_str, "%u,%u,%u,%u,%u", - &cdp_latency[0],&cdp_latency[1],&cdp_latency[2], + &cdp_latency[0],&cdp_latency[1],&cdp_latency[2], &cdp_latency[3],&cdp_latency[4]); if(!m_operands.empty()){ @@ -684,6 +706,7 @@ void ptx_instruction::set_opcode_and_latency() case FF64_TYPE: latency = dp_latency[0]; initiation_interval = dp_init[0]; + op = DP_OP; break; case B32_TYPE: case U32_TYPE: @@ -705,6 +728,7 @@ void ptx_instruction::set_opcode_and_latency() case FF64_TYPE: latency = dp_latency[1]; initiation_interval = dp_init[1]; + op = DP_OP; break; case B32_TYPE: case U32_TYPE: @@ -721,13 +745,12 @@ void ptx_instruction::set_opcode_and_latency() case F32_TYPE: latency = fp_latency[2]; initiation_interval = fp_init[2]; - op = ALU_SFU_OP; break; case F64_TYPE: case FF64_TYPE: latency = dp_latency[2]; initiation_interval = dp_init[2]; - op = ALU_SFU_OP; + op = DP_OP; break; case B32_TYPE: case U32_TYPE: @@ -750,6 +773,7 @@ void ptx_instruction::set_opcode_and_latency() case FF64_TYPE: latency = dp_latency[3]; initiation_interval = dp_init[3]; + op = DP_OP; break; case B32_TYPE: case U32_TYPE: @@ -785,8 +809,8 @@ void ptx_instruction::set_opcode_and_latency() break; case SQRT_OP: case SIN_OP: case COS_OP: case EX2_OP: case LG2_OP: case RSQRT_OP: case RCP_OP: //Using double to approximate those - latency = dp_latency[2]; - initiation_interval = dp_init[2]; + latency = sfu_latency; + initiation_interval = sfu_init; op = SFU_OP; break; case MMA_OP: @@ -796,7 +820,7 @@ void ptx_instruction::set_opcode_and_latency() break; case SHFL_OP: latency = 32; - initiation_interval = 15; + initiation_interval = 4; break; default: break; @@ -889,6 +913,7 @@ void ptx_instruction::pre_decode() switch( m_cache_option ) { case CA_OPTION: cache_op = CACHE_ALL; break; + case NC_OPTION: cache_op = CACHE_L1; break; case CG_OPTION: cache_op = CACHE_GLOBAL; break; case CS_OPTION: cache_op = CACHE_STREAMING; break; case LU_OPTION: cache_op = CACHE_LAST_USE; break; @@ -1169,13 +1194,13 @@ void function_info::finalize( memory_space *param_mem ) // 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 + //param_address = (param_address + size - 1) / size * size; //aligned with size TODO: align not correct for (size_t idx = 0; idx < size; idx += word_size) { const char *pdata = reinterpret_cast(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); + //assert(offset == param_address); param->set_address(param_address); param_address += size; } diff --git a/src/cuda-sim/instructions.cc b/src/cuda-sim/instructions.cc index 4614f25..973eeab 100644 --- a/src/cuda-sim/instructions.cc +++ b/src/cuda-sim/instructions.cc @@ -33,6 +33,7 @@ #include "ptx.tab.h" #include #include +#include #include #include "cuda-math.h" #include "../abstract_hardware_model.h" diff --git a/src/cuda-sim/ptx.y b/src/cuda-sim/ptx.y index 8b901a3..45392fb 100644 --- a/src/cuda-sim/ptx.y +++ b/src/cuda-sim/ptx.y @@ -237,7 +237,8 @@ function_defn: function_decl { set_symtab($1); func_header(".skip"); } statement block_spec: MAXNTID_DIRECTIVE INT_OPERAND COMMA INT_OPERAND COMMA INT_OPERAND {func_header_info_int(".maxntid", $2); func_header_info_int(",", $4); - func_header_info_int(",", $6); } + func_header_info_int(",", $6); + maxnt_id($2, $4, $6);} | MINNCTAPERSM_DIRECTIVE INT_OPERAND { func_header_info_int(".minnctapersm", $2); printf("GPGPU-Sim: Warning: .minnctapersm ignored. \n"); } | MAXNCTAPERSM_DIRECTIVE INT_OPERAND { func_header_info_int(".maxnctapersm", $2); printf("GPGPU-Sim: Warning: .maxnctapersm ignored. \n"); } ; diff --git a/src/cuda-sim/ptx_ir.cc b/src/cuda-sim/ptx_ir.cc index d12c741..1813f8c 100644 --- a/src/cuda-sim/ptx_ir.cc +++ b/src/cuda-sim/ptx_ir.cc @@ -222,6 +222,7 @@ bool symbol_table::add_function_decl( const char *name, int entry_point, functio } else { *func_info = new function_info(entry_point); (*func_info)->set_name(name); + (*func_info)->set_maxnt_id(0); m_function_info_lookup[key] = *func_info; } @@ -1234,16 +1235,16 @@ ptx_instruction::ptx_instruction( int opcode, m_inst_size = 4; // bytes break; case EXTP_OPTION: - break; + break; case NC_OPTION: - break; + m_cache_option = last_ptx_inst_option; + break; case UP_OPTION: case DOWN_OPTION: case BFLY_OPTION: case IDX_OPTION: m_shfl_op = last_ptx_inst_option; break; - case PRMT_F4E_MODE: case PRMT_B4E_MODE: case PRMT_RC8_MODE: diff --git a/src/cuda-sim/ptx_ir.h b/src/cuda-sim/ptx_ir.h index 0767379..4c36cfc 100644 --- a/src/cuda-sim/ptx_ir.h +++ b/src/cuda-sim/ptx_ir.h @@ -1333,6 +1333,7 @@ public: const struct gpgpu_ptx_sim_info* get_kernel_info () const { + assert (m_kernel_info.maxthreads == maxnt_id); return &m_kernel_info; } @@ -1340,6 +1341,8 @@ public: m_kernel_info = info; m_kernel_info.ptx_version = 10*get_ptx_version().ver(); m_kernel_info.sm_target = get_ptx_version().target(); + // THIS DEPENDS ON ptxas being called after the PTX is parsed. + m_kernel_info.maxthreads = maxnt_id; } symbol_table *get_symtab() { @@ -1363,7 +1366,11 @@ public: } bool is_entry_point() const { return m_entry_point; } + void set_maxnt_id(unsigned maxthreads) { maxnt_id = maxthreads;} + unsigned get_maxnt_id() { return maxnt_id;} + private: + unsigned maxnt_id; unsigned m_uid; unsigned m_local_mem_framesize; bool m_entry_point; diff --git a/src/cuda-sim/ptx_parser.cc b/src/cuda-sim/ptx_parser.cc index 9671ab7..cf40365 100644 --- a/src/cuda-sim/ptx_parser.cc +++ b/src/cuda-sim/ptx_parser.cc @@ -1012,6 +1012,10 @@ void target_header3(char* a, char* b, char* c) g_global_symbol_table->set_sm_target(a,b,c); } +void maxnt_id(int x, int y, int z) { + g_func_info->set_maxnt_id(x * y * z); +} + void func_header(const char* a) {} //intentional dummy function void func_header_info(const char* a) {} //intentional dummy function void func_header_info_int(const char* a, int b) {} //intentional dummy function diff --git a/src/cuda-sim/ptx_parser.h b/src/cuda-sim/ptx_parser.h index 8094b43..7b6e3a2 100644 --- a/src/cuda-sim/ptx_parser.h +++ b/src/cuda-sim/ptx_parser.h @@ -95,6 +95,7 @@ void change_double_operand_type( int addr_type ); void change_operand_neg( ); void set_immediate_operand_type( ); void version_header(double a); +void maxnt_id(int x, int y, int z); //Jin: handle instructino group for cdp void start_inst_group(); diff --git a/src/gpgpu-sim/addrdec.cc b/src/gpgpu-sim/addrdec.cc index 422576d..8651869 100644 --- a/src/gpgpu-sim/addrdec.cc +++ b/src/gpgpu-sim/addrdec.cc @@ -62,6 +62,9 @@ void linear_to_raw_address_translation::addrdec_setoption(option_parser_t opp) option_parser_register(opp, "-gpgpu_mem_address_mask", OPT_INT32, &gpgpu_mem_address_mask, "0 = old addressing mask, 1 = new addressing mask, 2 = new add. mask + flipped bank sel and chip sel bits", "0"); + option_parser_register(opp, "-memory_partition_indexing", OPT_UINT32, &memory_partition_indexing, + "0 = no indexing, 1 = bitwise xoring, 2 = IPoly, 3 = custom indexing", + "0"); } new_addr_type linear_to_raw_address_translation::partition_address( new_addr_type addr ) const @@ -103,6 +106,74 @@ void linear_to_raw_address_translation::addrdec_tlx(new_addr_type addr, addrdec_ tlx->burst= addrdec_packbits(addrdec_mask[BURST], rest_of_addr, addrdec_mkhigh[BURST], addrdec_mklow[BURST]); } + switch(memory_partition_indexing){ + case CONSECUTIVE: + //Do nothing + break; + case BITWISE_PERMUTATION: + { + assert(!gap); + tlx->chip = (tlx->chip) ^ (tlx->row & (m_n_channel-1)); + assert(tlx->chip < m_n_channel); + break; + } + case IPOLY: + { + /* + * Set Indexing function from "Pseudo-randomly interleaved memory." + * Rau, B. R et al. + * ISCA 1991 + * + * equations are adopted from: + * "Sacat: streaming-aware conflict-avoiding thrashing-resistant gpgpu cache management scheme." + * Khairy et al. + * IEEE TPDS 2017. + */ + if(m_n_channel == 32) { + std::bitset<64> a(tlx->row); + std::bitset<5> chip(tlx->chip); + chip[0] = a[13]^a[12]^a[11]^a[10]^a[9]^a[6]^a[5]^a[3]^a[0]^chip[0]; + chip[1] = a[14]^a[13]^a[12]^a[11]^a[10]^a[7]^a[6]^a[4]^a[1]^chip[1]; + chip[2] = a[14]^a[10]^a[9]^a[8]^a[7]^a[6]^a[3]^a[2]^a[0]^chip[2]; + chip[3] = a[11]^a[10]^a[9]^a[8]^a[7]^a[4]^a[3]^a[1]^chip[3]; + chip[4] = a[12]^a[11]^a[10]^a[9]^a[8]^a[5]^a[4]^a[2]^chip[4]; + tlx->chip = chip.to_ulong(); + + } + else{ /* Else incorrect number of channels for the hashing function */ + assert("\nGPGPU-Sim memory_partition_indexing error: The number of channels should be " + "32 for the hashing IPOLY index function.\n" && 0); + } + assert(tlx->chip < m_n_channel); + break; + } + case PAE: + { + //Page Address Entropy + //random selected bits from the page and bank bits + //similar to + //Liu, Yuxi, et al. "Get Out of the Valley: Power-Efficient Address Mapping for GPUs." ISCA 2018 + std::bitset<64> a(tlx->row); + std::bitset<5> chip(tlx->chip); + std::bitset<4> b(tlx->bk); + chip[0] = a[13]^a[10]^a[9]^a[5]^a[0]^b[3]^b[0]^chip[0]; + chip[1] = a[12]^a[11]^a[6]^a[1]^b[3]^b[2]^b[1]^chip[1]; + chip[2] = a[14]^a[9]^a[8]^a[7]^a[2]^b[1]^chip[2]; + chip[3] = a[11]^a[10]^a[8]^a[3]^b[2]^b[3]^chip[3]; + chip[4] = a[12]^a[9]^a[8]^a[5]^a[4]^b[1]^b[0]^chip[4]; + tlx->chip = chip.to_ulong(); + assert(tlx->chip < m_n_channel); + break; + } + case CUSTOM: + /* No custom set function implemented */ + //Do you custom index here + break; + default: + assert("\nUndefined set index function.\n" && 0); + break; + } + // combine the chip address and the lower bits of DRAM bank address to form the subpartition ID unsigned sub_partition_addr_mask = m_n_sub_partition_in_channel - 1; tlx->sub_partition = tlx->chip * m_n_sub_partition_in_channel diff --git a/src/gpgpu-sim/addrdec.h b/src/gpgpu-sim/addrdec.h index fd9af8d..bdc5fec 100644 --- a/src/gpgpu-sim/addrdec.h +++ b/src/gpgpu-sim/addrdec.h @@ -35,6 +35,14 @@ #include "../abstract_hardware_model.h" +enum partition_index_function{ + CONSECUTIVE = 0, + BITWISE_PERMUTATION, + IPOLY, + PAE, + CUSTOM +}; + struct addrdec_t { void print( FILE *fp ) const; @@ -72,6 +80,7 @@ private: const char *addrdec_option; int gpgpu_mem_address_mask; + partition_index_function memory_partition_indexing; bool run_test; int ADDR_CHIP_S; diff --git a/src/gpgpu-sim/delayqueue.h b/src/gpgpu-sim/delayqueue.h index b25f143..0caa5d4 100644 --- a/src/gpgpu-sim/delayqueue.h +++ b/src/gpgpu-sim/delayqueue.h @@ -161,6 +161,7 @@ public: } bool full() const { return (m_max_len && m_length >= m_max_len); } + bool is_avilable_size(unsigned size) const { return (m_max_len && m_length+size-1 >= m_max_len); } bool empty() const { return m_head == NULL; } unsigned get_n_element() const { return m_n_element; } unsigned get_length() const { return m_length; } diff --git a/src/gpgpu-sim/dram.cc b/src/gpgpu-sim/dram.cc index a0e024b..6c11b43 100644 --- a/src/gpgpu-sim/dram.cc +++ b/src/gpgpu-sim/dram.cc @@ -49,11 +49,45 @@ dram_t::dram_t( unsigned int partition_id, const struct memory_config *config, m m_stats = stats; m_config = config; + //rowblp + access_num=0; + hits_num=0; + read_num=0; + write_num=0; + hits_read_num=0; + hits_write_num=0; + banks_1time=0; + banks_acess_total=0; + banks_acess_total_after=0; + banks_time_ready=0; + banks_access_ready_total=0; + issued_two=0; + issued_total=0; + issued_total_row=0; + issued_total_col=0; + CCDc = 0; RRDc = 0; RTWc = 0; WTRc = 0; + wasted_bw_row=0; + wasted_bw_col=0; + util_bw=0; + idle_bw=0; + RCDc_limit=0; + CCDLc_limit=0; + CCDLc_limit_alone=0; + CCDc_limit=0; + WTRc_limit=0; + WTRc_limit_alone=0; + RCDWRc_limit=0; + RTWc_limit=0; + RTWc_limit_alone=0; + rwq_limit=0; + write_to_read_ratio_blp_rw_average=0; + bkgrp_parallsim_rw=0; + rw = READ; //read mode is default bkgrp = (bankgrp_t**) calloc(sizeof(bankgrp_t*), m_config->nbkgrp); @@ -74,12 +108,13 @@ dram_t::dram_t( unsigned int partition_id, const struct memory_config *config, m bk[i]->state = BANK_IDLE; bk[i]->bkgrpindex = i/(m_config->nbk/m_config->nbkgrp); } - prio = 0; + prio = 0; + rwq = new fifo_pipeline("rwq",m_config->CL,m_config->CL+1); mrqq = new fifo_pipeline("mrqq",0,2); returnq = new fifo_pipeline("dramreturnq",0,m_config->gpgpu_dram_return_queue_size==0?1024:m_config->gpgpu_dram_return_queue_size); m_frfcfs_scheduler = NULL; - if ( m_config->scheduler_type == DRAM_FRFCFS ) + if ( m_config->scheduler_type == DRAM_FRFCFS) m_frfcfs_scheduler = new frfcfs_scheduler(m_config,this,stats); n_cmd = 0; n_activity = 0; @@ -88,6 +123,8 @@ dram_t::dram_t( unsigned int partition_id, const struct memory_config *config, m n_pre = 0; n_rd = 0; n_wr = 0; + n_wr_WB=0; + n_rd_L2_A=0; n_req = 0; max_mrqs_temp = 0; bwutil = 0; @@ -113,13 +150,21 @@ dram_t::dram_t( unsigned int partition_id, const struct memory_config *config, m mrqq_Dist = StatCreate("mrqq_length",1, queue_limit()); else //queue length is unlimited; mrqq_Dist = StatCreate("mrqq_length",1,64); //track up to 64 entries + } -bool dram_t::full() const +bool dram_t::full(bool is_write) const { - if(m_config->scheduler_type == DRAM_FRFCFS ){ + if(m_config->scheduler_type == DRAM_FRFCFS){ if(m_config->gpgpu_frfcfs_dram_sched_queue_size == 0 ) return false; - return m_frfcfs_scheduler->num_pending() >= m_config->gpgpu_frfcfs_dram_sched_queue_size; + if(m_config->seperate_write_queue_enabled){ + if(is_write) + return m_frfcfs_scheduler->num_write_pending() >= m_config->gpgpu_frfcfs_dram_write_queue_size; + else + return m_frfcfs_scheduler->num_pending() >= m_config->gpgpu_frfcfs_dram_sched_queue_size; + } + else + return m_frfcfs_scheduler->num_pending() >= m_config->gpgpu_frfcfs_dram_sched_queue_size; } else return mrqq->full(); } @@ -127,7 +172,7 @@ bool dram_t::full() const unsigned dram_t::que_length() const { unsigned nreqs = 0; - if (m_config->scheduler_type == DRAM_FRFCFS ) { + if (m_config->scheduler_type == DRAM_FRFCFS) { nreqs = m_frfcfs_scheduler->num_pending(); } else { nreqs = mrqq->get_length(); @@ -146,7 +191,7 @@ unsigned int dram_t::queue_limit() const } -dram_req_t::dram_req_t( class mem_fetch *mf ) +dram_req_t::dram_req_t( class mem_fetch *mf, unsigned banks, unsigned dram_bnk_indexing_policy) { txbytes = 0; dqbytes = 0; @@ -154,7 +199,29 @@ dram_req_t::dram_req_t( class mem_fetch *mf ) const addrdec_t &tlx = mf->get_tlx_addr(); - bk = tlx.bk; + switch(dram_bnk_indexing_policy){ + case LINEAR_BK_INDEX: + { + bk = tlx.bk; + break; + } + case BITWISE_XORING_BK_INDEX: + { + //xoring bank bits with lower bits of the page + int lbank = log2(banks); + bk = tlx.bk ^ (tlx.row & ((1<get_data_size(); @@ -169,14 +236,15 @@ void dram_t::push( class mem_fetch *data ) { assert(id == data->get_tlx_addr().chip); // Ensure request is in correct memory partition - dram_req_t *mrq = new dram_req_t(data); + dram_req_t *mrq = new dram_req_t(data,m_config->nbk,m_config->dram_bnk_indexing_policy); + data->set_status(IN_PARTITION_MC_INTERFACE_QUEUE,gpu_sim_cycle+gpu_tot_sim_cycle); - mrqq->push(mrq); + mrqq->push(mrq); // stats... n_req += 1; n_req_partial += 1; - if ( m_config->scheduler_type == DRAM_FRFCFS ) { + if ( m_config->scheduler_type == DRAM_FRFCFS) { unsigned nreqs = m_frfcfs_scheduler->num_pending(); if ( nreqs > max_mrqs_temp) max_mrqs_temp = nreqs; @@ -212,6 +280,7 @@ void dram_t::cycle() printf("\tDQ: BK%d Row:%03x Col:%03x", cmd->bk, cmd->row, cmd->col + cmd->dqbytes); #endif cmd->dqbytes += m_config->dram_atom_size; + if (cmd->dqbytes >= cmd->nbytes) { mem_fetch *data = cmd->data; data->set_status(IN_PARTITION_MC_RETURNQ,gpu_sim_cycle+gpu_tot_sim_cycle); @@ -240,7 +309,7 @@ void dram_t::cycle() printf("Error: Unknown DRAM scheduler type\n"); assert(0); } - if ( m_config->scheduler_type == DRAM_FRFCFS ) { + if ( m_config->scheduler_type == DRAM_FRFCFS) { unsigned nreqs = m_frfcfs_scheduler->num_pending(); if ( nreqs > max_mrqs) { max_mrqs = nreqs; @@ -258,130 +327,123 @@ void dram_t::cycle() unsigned k=m_config->nbk; bool issued = false; - // check if any bank is ready to issue a new read + //collect row buffer locality, BLP and other statistics + ///////////////////////////////////////////////////////////////////////// + unsigned int memory_pending=0; for (unsigned i=0;inbk;i++) { - unsigned j = (i + prio) % m_config->nbk; - unsigned grp = j>>m_config->bk_tag_length; - if (bk[j]->mrq) { //if currently servicing a memory request - bk[j]->mrq->data->set_status(IN_PARTITION_DRAM,gpu_sim_cycle+gpu_tot_sim_cycle); - // correct row activated for a READ - if ( !issued && !CCDc && !bk[j]->RCDc && - !(bkgrp[grp]->CCDLc) && - (bk[j]->curr_row == bk[j]->mrq->row) && - (bk[j]->mrq->rw == READ) && (WTRc == 0 ) && - (bk[j]->state == BANK_ACTIVE) && - !rwq->full() ) { - if (rw==WRITE) { - rw=READ; - rwq->set_min_length(m_config->CL); - } - rwq->push(bk[j]->mrq); - bk[j]->mrq->txbytes += m_config->dram_atom_size; - CCDc = m_config->tCCD; - bkgrp[grp]->CCDLc = m_config->tCCDL; - RTWc = m_config->tRTW; - bk[j]->RTPc = m_config->BL/m_config->data_command_freq_ratio; - bkgrp[grp]->RTPLc = m_config->tRTPL; - issued = true; - n_rd++; - bwutil += m_config->BL/m_config->data_command_freq_ratio; - bwutil_partial += m_config->BL/m_config->data_command_freq_ratio; - bk[j]->n_access++; -#ifdef DRAM_VERIFY - PRINT_CYCLE=1; - printf("\tRD Bk:%d Row:%03x Col:%03x \n", - j, bk[j]->curr_row, - bk[j]->mrq->col + bk[j]->mrq->txbytes - m_config->dram_atom_size); -#endif - // transfer done - if ( !(bk[j]->mrq->txbytes < bk[j]->mrq->nbytes) ) { - bk[j]->mrq = NULL; - } - } else - // correct row activated for a WRITE - if ( !issued && !CCDc && !bk[j]->RCDWRc && - !(bkgrp[grp]->CCDLc) && - (bk[j]->curr_row == bk[j]->mrq->row) && - (bk[j]->mrq->rw == WRITE) && (RTWc == 0 ) && - (bk[j]->state == BANK_ACTIVE) && - !rwq->full() ) { - if (rw==READ) { - rw=WRITE; - rwq->set_min_length(m_config->WL); - } - rwq->push(bk[j]->mrq); - - bk[j]->mrq->txbytes += m_config->dram_atom_size; - CCDc = m_config->tCCD; - bkgrp[grp]->CCDLc = m_config->tCCDL; - WTRc = m_config->tWTR; - bk[j]->WTPc = m_config->tWTP; - issued = true; - n_wr++; - bwutil += m_config->BL/m_config->data_command_freq_ratio; - bwutil_partial += m_config->BL/m_config->data_command_freq_ratio; -#ifdef DRAM_VERIFY - PRINT_CYCLE=1; - printf("\tWR Bk:%d Row:%03x Col:%03x \n", - j, bk[j]->curr_row, - bk[j]->mrq->col + bk[j]->mrq->txbytes - m_config->dram_atom_size); -#endif - // transfer done - if ( !(bk[j]->mrq->txbytes < bk[j]->mrq->nbytes) ) { - bk[j]->mrq = NULL; - } - } - - else - // bank is idle - if ( !issued && !RRDc && - (bk[j]->state == BANK_IDLE) && - !bk[j]->RPc && !bk[j]->RCc ) { -#ifdef DRAM_VERIFY - PRINT_CYCLE=1; - printf("\tACT BK:%d NewRow:%03x From:%03x \n", - j,bk[j]->mrq->row,bk[j]->curr_row); -#endif - // activate the row with current memory request - bk[j]->curr_row = bk[j]->mrq->row; - bk[j]->state = BANK_ACTIVE; - RRDc = m_config->tRRD; - bk[j]->RCDc = m_config->tRCD; - bk[j]->RCDWRc = m_config->tRCDWR; - bk[j]->RASc = m_config->tRAS; - bk[j]->RCc = m_config->tRC; - prio = (j + 1) % m_config->nbk; - issued = true; - n_act_partial++; - n_act++; - } - - else - // different row activated - if ( (!issued) && - (bk[j]->curr_row != bk[j]->mrq->row) && - (bk[j]->state == BANK_ACTIVE) && - (!bk[j]->RASc && !bk[j]->WTPc && - !bk[j]->RTPc && - !bkgrp[grp]->RTPLc) ) { - // make the bank idle again - bk[j]->state = BANK_IDLE; - bk[j]->RPc = m_config->tRP; - prio = (j + 1) % m_config->nbk; - issued = true; - n_pre++; - n_pre_partial++; -#ifdef DRAM_VERIFY - PRINT_CYCLE=1; - printf("\tPRE BK:%d Row:%03x \n", j,bk[j]->curr_row); -#endif - } - } else { - if (!CCDc && !RRDc && !RTWc && !WTRc && !bk[j]->RCDc && !bk[j]->RASc - && !bk[j]->RCc && !bk[j]->RPc && !bk[j]->RCDWRc) k--; - bk[j]->n_idle++; - } + if (bk[i]->mrq) + memory_pending++; } + banks_1time += memory_pending; + if(memory_pending >0) + banks_acess_total++; + + unsigned int memory_pending_rw=0; + unsigned read_blp_rw=0; + unsigned write_blp_rw=0; + std::bitset<8> bnkgrp_rw_found; //assume max we have 8 bank groups + + for (unsigned j=0;jnbk;j++) { + unsigned grp = get_bankgrp_number(j); + if (bk[j]->mrq && (((bk[j]->curr_row == bk[j]->mrq->row) && + (bk[j]->mrq->rw == READ) && + (bk[j]->state == BANK_ACTIVE)))) + { + memory_pending_rw++; + read_blp_rw++; + bnkgrp_rw_found.set(grp); + } + else if + (bk[j]->mrq && (((bk[j]->curr_row == bk[j]->mrq->row) && + (bk[j]->mrq->rw == WRITE) && + (bk[j]->state == BANK_ACTIVE)))) + { + memory_pending_rw++; + write_blp_rw++; + bnkgrp_rw_found.set(grp); + } + } + banks_time_rw += memory_pending_rw; + bkgrp_parallsim_rw += bnkgrp_rw_found.count(); + if(memory_pending_rw >0) + { + write_to_read_ratio_blp_rw_average += (double)write_blp_rw/(write_blp_rw+read_blp_rw); + banks_access_rw_total++; + } + + unsigned int memory_Pending_ready=0; + for (unsigned j=0;jnbk;j++) { + unsigned grp = get_bankgrp_number(j); + if (bk[j]->mrq && ((!CCDc && !bk[j]->RCDc && + !(bkgrp[grp]->CCDLc) && + (bk[j]->curr_row == bk[j]->mrq->row) && + (bk[j]->mrq->rw == READ) && (WTRc == 0 ) && + (bk[j]->state == BANK_ACTIVE) && + !rwq->full()) + || + (!CCDc && !bk[j]->RCDWRc && + !(bkgrp[grp]->CCDLc) && + (bk[j]->curr_row == bk[j]->mrq->row) && + (bk[j]->mrq->rw == WRITE) && (RTWc == 0 ) && + (bk[j]->state == BANK_ACTIVE) && + !rwq->full()))) + { + memory_Pending_ready++; + } + } + banks_time_ready += memory_Pending_ready; + if(memory_Pending_ready >0) + banks_access_ready_total++; + /////////////////////////////////////////////////////////////////////////////////// + + bool issued_col_cmd = false; + bool issued_row_cmd = false; + + if(m_config->dual_bus_interface) + { + //dual bus interface + //issue one row command and one column command + for (unsigned i=0;inbk;i++) { + unsigned j = (i + prio) % m_config->nbk; + issued_col_cmd = issue_col_command(j); + if(issued_col_cmd) break; + } + for (unsigned i=0;inbk;i++) { + unsigned j = (i + prio) % m_config->nbk; + issued_row_cmd = issue_row_command(j); + if(issued_row_cmd) break; + } + for (unsigned i=0;inbk;i++) { + unsigned j = (i + prio) % m_config->nbk; + if(!bk[j]->mrq) { + if (!CCDc && !RRDc && !RTWc && !WTRc && !bk[j]->RCDc && !bk[j]->RASc + && !bk[j]->RCc && !bk[j]->RPc && !bk[j]->RCDWRc) k--; + bk[j]->n_idle++; + } + } + } + else + { + //single bus interface + //issue only one row/column command + for (unsigned i=0;inbk;i++) { + unsigned j = (i + prio) % m_config->nbk; + if(!issued_col_cmd) + issued_col_cmd = issue_col_command(j); + + if(!issued_col_cmd && !issued_row_cmd) + issued_row_cmd = issue_row_command(j); + + if(!bk[j]->mrq) { + if (!CCDc && !RRDc && !RTWc && !WTRc && !bk[j]->RCDc && !bk[j]->RASc + && !bk[j]->RCc && !bk[j]->RPc && !bk[j]->RCDWRc) k--; + bk[j]->n_idle++; + } + + } + } + + issued = issued_row_cmd || issued_col_cmd; if (!issued) { n_nop++; n_nop_partial++; @@ -395,6 +457,85 @@ void dram_t::cycle() } n_cmd++; n_cmd_partial++; + if(issued) + { + issued_total++; + if(issued_col_cmd && issued_row_cmd) + issued_two++; + } + if(issued_col_cmd) issued_total_col++; + if(issued_row_cmd) issued_total_row++; + + + //Collect some statistics + //check the limitation, see where BW is wasted? + ///////////////////////////////////////////////////////// + unsigned int memory_pending_found=0; + for (unsigned i=0;inbk;i++) { + if (bk[i]->mrq) + memory_pending_found++; + } + if(memory_pending_found>0) + banks_acess_total_after++; + + bool memory_pending_rw_found=false; + for (unsigned j=0;jnbk;j++) { + unsigned grp = get_bankgrp_number(j); + if (bk[j]->mrq && (((bk[j]->curr_row == bk[j]->mrq->row) && + (bk[j]->mrq->rw == READ) && + (bk[j]->state == BANK_ACTIVE)) + || + ( + (bk[j]->curr_row == bk[j]->mrq->row) && + (bk[j]->mrq->rw == WRITE) && + (bk[j]->state == BANK_ACTIVE)))) + memory_pending_rw_found=true; + } + + + if(issued_col_cmd || CCDc) + util_bw++; + else if (memory_pending_rw_found) + { + wasted_bw_col++; + for (unsigned j=0;jnbk;j++) { + unsigned grp = get_bankgrp_number(j); + //read + if (bk[j]->mrq && (((bk[j]->curr_row == bk[j]->mrq->row) && + (bk[j]->mrq->rw == READ) && + (bk[j]->state == BANK_ACTIVE)))) + { + if(bk[j]->RCDc) RCDc_limit++; + if(bkgrp[grp]->CCDLc) CCDLc_limit++; + if(WTRc) WTRc_limit++; + if(CCDc) CCDc_limit++; + if(rwq->full()) rwq_limit++; + if(bkgrp[grp]->CCDLc && !WTRc) CCDLc_limit_alone++; + if(!bkgrp[grp]->CCDLc && WTRc) WTRc_limit_alone++; + } + //write + else if (bk[j]->mrq && ((bk[j]->curr_row == bk[j]->mrq->row) && + (bk[j]->mrq->rw == WRITE) && + (bk[j]->state == BANK_ACTIVE))) + { + if(bk[j]->RCDWRc) RCDWRc_limit++; + if(bkgrp[grp]->CCDLc) CCDLc_limit++; + if(RTWc) RTWc_limit++; + if(CCDc) CCDc_limit++; + if(rwq->full()) rwq_limit++; + if(bkgrp[grp]->CCDLc && !RTWc) CCDLc_limit_alone++; + if(!bkgrp[grp]->CCDLc && RTWc) RTWc_limit_alone++; + } + } + } + else if (memory_pending_found) + wasted_bw_row++; + else if (!memory_pending_found) + idle_bw++; + else + assert(1); + + ///////////////////////////////////////////////////////// // decrements counters once for each time dram_issueCMD is called DEC2ZERO(RRDc); @@ -420,39 +561,237 @@ void dram_t::cycle() #endif } +bool dram_t::issue_col_command(int j) +{ + bool issued = false; + unsigned grp = get_bankgrp_number(j); + if (bk[j]->mrq) { //if currently servicing a memory request + bk[j]->mrq->data->set_status(IN_PARTITION_DRAM,gpu_sim_cycle+gpu_tot_sim_cycle); + // correct row activated for a READ + if ( !issued && !CCDc && !bk[j]->RCDc && + !(bkgrp[grp]->CCDLc) && + (bk[j]->curr_row == bk[j]->mrq->row) && + (bk[j]->mrq->rw == READ) && (WTRc == 0 ) && + (bk[j]->state == BANK_ACTIVE) && + !rwq->full() ) { + if (rw==WRITE) { + rw=READ; + rwq->set_min_length(m_config->CL); + } + rwq->push(bk[j]->mrq); + bk[j]->mrq->txbytes += m_config->dram_atom_size; + CCDc = m_config->tCCD; + bkgrp[grp]->CCDLc = m_config->tCCDL; + RTWc = m_config->tRTW; + bk[j]->RTPc = m_config->BL/m_config->data_command_freq_ratio; + bkgrp[grp]->RTPLc = m_config->tRTPL; + issued = true; + if(bk[j]->mrq->data->get_access_type() == L2_WR_ALLOC_R) + n_rd_L2_A++; + else + n_rd++; + + bwutil += m_config->BL/m_config->data_command_freq_ratio; + bwutil_partial += m_config->BL/m_config->data_command_freq_ratio; + bk[j]->n_access++; + +#ifdef DRAM_VERIFY + PRINT_CYCLE=1; + printf("\tRD Bk:%d Row:%03x Col:%03x \n", + j, bk[j]->curr_row, + bk[j]->mrq->col + bk[j]->mrq->txbytes - m_config->dram_atom_size); +#endif + // transfer done + if ( !(bk[j]->mrq->txbytes < bk[j]->mrq->nbytes) ) { + bk[j]->mrq = NULL; + } + } else + // correct row activated for a WRITE + if ( !issued && !CCDc && !bk[j]->RCDWRc && + !(bkgrp[grp]->CCDLc) && + (bk[j]->curr_row == bk[j]->mrq->row) && + (bk[j]->mrq->rw == WRITE) && (RTWc == 0 ) && + (bk[j]->state == BANK_ACTIVE) && + !rwq->full() ) { + if (rw==READ) { + rw=WRITE; + rwq->set_min_length(m_config->WL); + } + rwq->push(bk[j]->mrq); + + bk[j]->mrq->txbytes += m_config->dram_atom_size; + CCDc = m_config->tCCD; + bkgrp[grp]->CCDLc = m_config->tCCDL; + WTRc = m_config->tWTR; + bk[j]->WTPc = m_config->tWTP; + issued = true; + + if(bk[j]->mrq->data->get_access_type() == L2_WRBK_ACC) + n_wr_WB++; + else + n_wr++; + bwutil += m_config->BL/m_config->data_command_freq_ratio; + bwutil_partial += m_config->BL/m_config->data_command_freq_ratio; +#ifdef DRAM_VERIFY + PRINT_CYCLE=1; + printf("\tWR Bk:%d Row:%03x Col:%03x \n", + j, bk[j]->curr_row, + bk[j]->mrq->col + bk[j]->mrq->txbytes - m_config->dram_atom_size); +#endif + // transfer done + if ( !(bk[j]->mrq->txbytes < bk[j]->mrq->nbytes) ) { + bk[j]->mrq = NULL; + } + } + + } + + return issued; +} + +bool dram_t::issue_row_command(int j) +{ + bool issued = false; + unsigned grp = get_bankgrp_number(j); + if (bk[j]->mrq) { //if currently servicing a memory request + bk[j]->mrq->data->set_status(IN_PARTITION_DRAM,gpu_sim_cycle+gpu_tot_sim_cycle); + // bank is idle + //else + if ( !issued && !RRDc && + (bk[j]->state == BANK_IDLE) && + !bk[j]->RPc && !bk[j]->RCc) { // +#ifdef DRAM_VERIFY + PRINT_CYCLE=1; + printf("\tACT BK:%d NewRow:%03x From:%03x \n", + j,bk[j]->mrq->row,bk[j]->curr_row); +#endif + // activate the row with current memory request + bk[j]->curr_row = bk[j]->mrq->row; + bk[j]->state = BANK_ACTIVE; + RRDc = m_config->tRRD; + bk[j]->RCDc = m_config->tRCD; + bk[j]->RCDWRc = m_config->tRCDWR; + bk[j]->RASc = m_config->tRAS; + bk[j]->RCc = m_config->tRC; + prio = (j + 1) % m_config->nbk; + issued = true; + n_act_partial++; + n_act++; + } + + else + // different row activated + if ( (!issued) && + (bk[j]->curr_row != bk[j]->mrq->row) && + (bk[j]->state == BANK_ACTIVE) && + (!bk[j]->RASc && !bk[j]->WTPc && + !bk[j]->RTPc && + !bkgrp[grp]->RTPLc) ) { + // make the bank idle again + bk[j]->state = BANK_IDLE; + bk[j]->RPc = m_config->tRP; + prio = (j + 1) % m_config->nbk; + issued = true; + n_pre++; + n_pre_partial++; +#ifdef DRAM_VERIFY + PRINT_CYCLE=1; + printf("\tPRE BK:%d Row:%03x \n", j,bk[j]->curr_row); +#endif + } + } + return issued; +} + + //if mrq is being serviced by dram, gets popped after CL latency fulfilled -class mem_fetch* dram_t::return_queue_pop() +class mem_fetch* dram_t::return_queue_pop() { return returnq->pop(); } -class mem_fetch* dram_t::return_queue_top() +class mem_fetch* dram_t::return_queue_top() { return returnq->top(); } + void dram_t::print( FILE* simFile) const { unsigned i; fprintf(simFile,"DRAM[%d]: %d bks, busW=%d BL=%d CL=%d, ", id, m_config->nbk, m_config->busW, m_config->BL, m_config->CL ); fprintf(simFile,"tRRD=%d tCCD=%d, tRCD=%d tRAS=%d tRP=%d tRC=%d\n", - m_config->tCCD, m_config->tRRD, m_config->tRCD, m_config->tRAS, m_config->tRP, m_config->tRC ); - fprintf(simFile,"n_cmd=%d n_nop=%d n_act=%d n_pre=%d n_req=%d n_rd=%d n_write=%d bw_util=%.4g\n", - n_cmd, n_nop, n_act, n_pre, n_req, n_rd, n_wr, + m_config->tRRD, m_config->tCCD, m_config->tRCD, m_config->tRAS, m_config->tRP, m_config->tRC ); + fprintf(simFile,"n_cmd=%d n_nop=%d n_act=%d n_pre=%d n_ref_event=%d n_req=%d n_rd=%d n_rd_L2_A=%d n_write=%d n_wr_bk=%d bw_util=%.4g\n", + n_cmd, n_nop, n_act, n_pre, n_ref, n_req, n_rd, n_rd_L2_A, n_wr, n_wr_WB, (float)bwutil/n_cmd); fprintf(simFile,"n_activity=%d dram_eff=%.4g\n", n_activity, (float)bwutil/n_activity); for (i=0;inbk;i++) { fprintf(simFile, "bk%d: %da %di ",i,bk[i]->n_access,bk[i]->n_idle); } + fprintf(simFile, "\n"); + fprintf(simFile, "\n------------------------------------------------------------------------\n"); + + printf("\nRow_Buffer_Locality = %.6f", (float)hits_num / access_num); + printf("\nRow_Buffer_Locality_read = %.6f", (float)hits_read_num / read_num); + printf("\nRow_Buffer_Locality_write = %.6f", (float)hits_write_num / write_num); + printf("\nBank_Level_Parallism = %.6f", (float)banks_1time / banks_acess_total); + printf("\nBank_Level_Parallism_Col = %.6f", (float)banks_time_rw / banks_access_rw_total); + printf("\nBank_Level_Parallism_Ready = %.6f", (float)banks_time_ready /banks_access_ready_total); + printf("\nwrite_to_read_ratio_blp_rw_average = %.6f", write_to_read_ratio_blp_rw_average /banks_access_rw_total); + printf("\nGrpLevelPara = %.6f \n", (float)bkgrp_parallsim_rw /banks_access_rw_total); + + printf("\nBW Util details:\n"); + printf("bwutil = %.6f \n", (float)bwutil/n_cmd); + printf("total_CMD = %d \n", n_cmd); + printf("util_bw = %d \n", util_bw); + printf("Wasted_Col = %d \n", wasted_bw_col); + printf("Wasted_Row = %d \n", wasted_bw_row); + printf("Idle = %d \n", idle_bw); + + printf("\nBW Util Bottlenecks: \n"); + printf("RCDc_limit = %d \n", RCDc_limit); + printf("RCDWRc_limit = %d \n", RCDWRc_limit); + printf("WTRc_limit = %d \n", WTRc_limit); + printf("RTWc_limit = %d \n", RTWc_limit); + printf("CCDLc_limit = %d \n", CCDLc_limit); + printf("rwq = %d \n", rwq_limit); + printf("CCDLc_limit_alone = %d \n", CCDLc_limit_alone); + printf("WTRc_limit_alone = %d \n", WTRc_limit_alone); + printf("RTWc_limit_alone = %d \n", RTWc_limit_alone); + + printf("\nCommands details: \n"); + printf("total_CMD = %d \n", n_cmd); + printf("n_nop = %d \n", n_nop); + printf("Read = %d \n", n_rd); + printf("Write = %d \n",n_wr); + printf("L2_Alloc = %d \n", n_rd_L2_A); + printf("L2_WB = %d \n", n_wr_WB); + printf("n_act = %d \n", n_act); + printf("n_pre = %d \n", n_pre); + printf("n_ref = %d \n", n_ref); + printf("n_req = %d \n", n_req ); + printf("total_req = %d \n", n_rd+n_wr+n_rd_L2_A+n_wr_WB); + + printf("\nDual Bus Interface Util: \n"); + printf("issued_total_row = %lu \n", issued_total_row); + printf("issued_total_col = %lu \n", issued_total_col); + printf("Row_Bus_Util = %.6f \n", (float)issued_total_row / n_cmd); + printf("CoL_Bus_Util = %.6f \n", (float)issued_total_col / n_cmd); + printf("Either_Row_CoL_Bus_Util = %.6f \n", (float)issued_total / n_cmd); + printf("Issued_on_Two_Bus_Simul_Util = %.6f \n", (float)issued_two /n_cmd); + printf("issued_two_Eff = %.6f \n", (float)issued_two /issued_total); + printf("queue_avg = %.6f \n\n", (float)ave_mrqs/n_cmd ); + fprintf(simFile, "\n"); fprintf(simFile, "dram_util_bins:"); for (i=0;i<10;i++) fprintf(simFile, " %d", dram_util_bins[i]); fprintf(simFile, "\ndram_eff_bins:"); for (i=0;i<10;i++) fprintf(simFile, " %d", dram_eff_bins[i]); fprintf(simFile, "\n"); - if(m_config->scheduler_type== DRAM_FRFCFS) + if(m_config->scheduler_type== DRAM_FRFCFS) fprintf(simFile, "mrqq: max=%d avg=%g\n", max_mrqs, (float)ave_mrqs/n_cmd); } @@ -476,8 +815,8 @@ void dram_t::visualize() const void dram_t::print_stat( FILE* simFile ) { - fprintf(simFile,"DRAM (%d): n_cmd=%d n_nop=%d n_act=%d n_pre=%d n_req=%d n_rd=%d n_write=%d bw_util=%.4g ", - id, n_cmd, n_nop, n_act, n_pre, n_req, n_rd, n_wr, + fprintf(simFile,"DRAM (%d): n_cmd=%d n_nop=%d n_act=%d n_pre=%d n_ref=%d n_req=%d n_rd=%d n_write=%d bw_util=%.4g ", + id, n_cmd, n_nop, n_act, n_pre, n_ref, n_req, n_rd, n_wr, (float)bwutil/n_cmd); fprintf(simFile, "mrqq: %d %.4g mrqsmax=%d ", max_mrqs, (float)ave_mrqs/n_cmd, max_mrqs_temp); fprintf(simFile, "\n"); @@ -516,6 +855,7 @@ void dram_t::visualizer_print( gzFile visualizer_file ) n_pre_partial = 0; n_req_partial = 0; + // dram access type classification for (unsigned j = 0; j < m_config->nbk; j++) { gzprintf(visualizer_file,"dramglobal_acc_r: %u %u %u\n", id, j, @@ -553,3 +893,16 @@ void dram_t::set_dram_power_stats( unsigned &cmd, wr = n_wr; req = n_req; } + +unsigned dram_t::get_bankgrp_number(unsigned i) +{ + if(m_config->dram_bnkgrp_indexing_policy == HIGHER_BITS) { //higher bits + return i>>m_config->bk_tag_length; + } + else if (m_config->dram_bnkgrp_indexing_policy == LOWER_BITS) { //lower bits + return i&((m_config->nbkgrp-1)); + } + else { + assert(1); + } +} diff --git a/src/gpgpu-sim/dram.h b/src/gpgpu-sim/dram.h index 15c63e7..bee5b7b 100644 --- a/src/gpgpu-sim/dram.h +++ b/src/gpgpu-sim/dram.h @@ -31,9 +31,15 @@ #include "delayqueue.h" #include +#include +#include +#include +#include +#include #include #include #include +#include #define READ 'R' //define read and write states #define WRITE 'W' @@ -42,7 +48,7 @@ class dram_req_t { public: - dram_req_t( class mem_fetch *data ); + dram_req_t( class mem_fetch *data , unsigned banks, unsigned dram_bnk_indexing_policy); unsigned int row; unsigned int col; @@ -87,6 +93,17 @@ struct bank_t unsigned int bkgrpindex; }; +enum bank_index_function{ + LINEAR_BK_INDEX = 0, + BITWISE_XORING_BK_INDEX, + CUSTOM_BK_INDEX +}; + +enum bank_grp_bits_position{ + HIGHER_BITS = 0, + LOWER_BITS +}; + class mem_fetch; class dram_t @@ -95,7 +112,7 @@ public: dram_t( unsigned int parition_id, const struct memory_config *config, class memory_stats_t *stats, class memory_partition_unit *mp ); - bool full() const; + bool full(bool is_write) const; void print( FILE* simFile ) const; void visualize() const; void print_stat( FILE* simFile ); @@ -106,6 +123,7 @@ public: class mem_fetch* return_queue_pop(); class mem_fetch* return_queue_top(); + void push( class mem_fetch *data ); void cycle(); void dram_log (int task); @@ -123,17 +141,24 @@ public: unsigned &wr, unsigned &req) const; -private: - void scheduler_fifo(); - void scheduler_frfcfs(); + const struct memory_config *m_config; +private: bankgrp_t **bkgrp; bank_t **bk; unsigned int prio; + unsigned get_bankgrp_number(unsigned i); + + void scheduler_fifo(); + void scheduler_frfcfs(); + + bool issue_col_command(int j); + bool issue_row_command(int j); + unsigned int RRDc; unsigned int CCDc; unsigned int RTWc; //read to write penalty applies across banks @@ -146,7 +171,7 @@ private: fifo_pipeline *rwq; fifo_pipeline *mrqq; //buffer to hold packets when DRAM processing is over - //should be filled with dram clock and popped with l2or icnt clock + //should be filled with dram clock and popped with l2or icnt clock fifo_pipeline *returnq; unsigned int dram_util_bins[10]; @@ -158,11 +183,51 @@ private: unsigned int n_nop; unsigned int n_act; unsigned int n_pre; + unsigned int n_ref; unsigned int n_rd; + unsigned int n_rd_L2_A; unsigned int n_wr; + unsigned int n_wr_WB; unsigned int n_req; unsigned int max_mrqs_temp; + //some statistics to collect to see where BW is wasted? + unsigned wasted_bw_row; + unsigned wasted_bw_col; + unsigned util_bw; + unsigned idle_bw; + unsigned RCDc_limit; + unsigned CCDLc_limit; + unsigned CCDLc_limit_alone; + unsigned CCDc_limit; + unsigned WTRc_limit; + unsigned WTRc_limit_alone; + unsigned RCDWRc_limit; + unsigned RTWc_limit; + unsigned RTWc_limit_alone; + unsigned rwq_limit; + + //row locality, BLP and other statistics + unsigned long access_num; + unsigned long read_num; + unsigned long write_num; + unsigned long long hits_num; + unsigned long long hits_read_num; + unsigned long long hits_write_num; + unsigned long long banks_1time; + unsigned long long banks_acess_total; + unsigned long long banks_acess_total_after; + unsigned long long banks_time_rw; + unsigned long long banks_access_rw_total; + unsigned long long banks_time_ready; + unsigned long long banks_access_ready_total; + unsigned long long issued_two; + unsigned long long issued_total; + unsigned long long issued_total_row; + unsigned long long issued_total_col; + double write_to_read_ratio_blp_rw_average; + unsigned long long bkgrp_parallsim_rw; + unsigned int bwutil; unsigned int max_mrqs; unsigned int ave_mrqs; diff --git a/src/gpgpu-sim/dram_sched.cc b/src/gpgpu-sim/dram_sched.cc index 8303e86..ff50050 100644 --- a/src/gpgpu-sim/dram_sched.cc +++ b/src/gpgpu-sim/dram_sched.cc @@ -36,6 +36,7 @@ frfcfs_scheduler::frfcfs_scheduler( const memory_config *config, dram_t *dm, mem m_config = config; m_stats = stats; m_num_pending = 0; + m_num_write_pending = 0; m_dram = dm; m_queue = new std::list[m_config->nbk]; m_bins = new std::map::iterator> >[ m_config->nbk ]; @@ -49,15 +50,36 @@ frfcfs_scheduler::frfcfs_scheduler( const memory_config *config, dram_t *dm, mem curr_row_service_time[i] = 0; row_service_timestamp[i] = 0; } + if(m_config->seperate_write_queue_enabled) { + m_write_queue = new std::list[m_config->nbk]; + m_write_bins = new std::map::iterator> >[ m_config->nbk ]; + m_last_write_row = new std::list::iterator>*[ m_config->nbk ]; + + for ( unsigned i=0; i < m_config->nbk; i++ ) { + m_write_queue[i].clear(); + m_write_bins[i].clear(); + m_last_write_row[i] = NULL; + } + } + m_mode = READ_MODE; } void frfcfs_scheduler::add_req( dram_req_t *req ) { - m_num_pending++; - m_queue[req->bk].push_front(req); - std::list::iterator ptr = m_queue[req->bk].begin(); - m_bins[req->bk][req->row].push_front( ptr ); //newest reqs to the front + if(m_config->seperate_write_queue_enabled && req->data->is_write()) { + assert(m_num_write_pending < m_config->gpgpu_frfcfs_dram_write_queue_size); + m_num_write_pending++; + m_write_queue[req->bk].push_front(req); + std::list::iterator ptr = m_write_queue[req->bk].begin(); + m_write_bins[req->bk][req->row].push_front( ptr ); //newest reqs to the front + } else { + assert(m_num_pending < m_config->gpgpu_frfcfs_dram_sched_queue_size); + m_num_pending++; + m_queue[req->bk].push_front(req); + std::list::iterator ptr = m_queue[req->bk].begin(); + m_bins[req->bk][req->row].push_front( ptr ); //newest reqs to the front + } } void frfcfs_scheduler::data_collection(unsigned int bank) @@ -78,41 +100,92 @@ void frfcfs_scheduler::data_collection(unsigned int bank) dram_req_t *frfcfs_scheduler::schedule( unsigned bank, unsigned curr_row ) { - if ( m_last_row[bank] == NULL ) { - if ( m_queue[bank].empty() ) + //row + bool rowhit = true; + std::list *m_current_queue = m_queue; + std::map::iterator> > *m_current_bins = m_bins ; + std::list::iterator> **m_current_last_row = m_last_row; + + if(m_config->seperate_write_queue_enabled) { + if(m_mode == READ_MODE && + ((m_num_write_pending >= m_config->write_high_watermark ) + // || (m_queue[bank].empty() && !m_write_queue[bank].empty()) + )) { + m_mode = WRITE_MODE; + } + else if(m_mode == WRITE_MODE && + (( m_num_write_pending < m_config->write_low_watermark ) + // || (!m_queue[bank].empty() && m_write_queue[bank].empty()) + )){ + m_mode = READ_MODE; + } + } + + if(m_mode == WRITE_MODE) { + m_current_queue = m_write_queue; + m_current_bins = m_write_bins ; + m_current_last_row = m_last_write_row; + } + + if ( m_current_last_row[bank] == NULL ) { + if ( m_current_queue[bank].empty() ) return NULL; - std::map::iterator> >::iterator bin_ptr = m_bins[bank].find( curr_row ); - if ( bin_ptr == m_bins[bank].end()) { - dram_req_t *req = m_queue[bank].back(); - bin_ptr = m_bins[bank].find( req->row ); - assert( bin_ptr != m_bins[bank].end() ); // where did the request go??? - m_last_row[bank] = &(bin_ptr->second); + std::map::iterator> >::iterator bin_ptr = m_current_bins[bank].find( curr_row ); + if ( bin_ptr == m_current_bins[bank].end()) { + dram_req_t *req = m_current_queue[bank].back(); + bin_ptr = m_current_bins[bank].find( req->row ); + assert( bin_ptr != m_current_bins[bank].end() ); // where did the request go??? + m_current_last_row[bank] = &(bin_ptr->second); data_collection(bank); + rowhit = false; } else { - m_last_row[bank] = &(bin_ptr->second); - + m_current_last_row[bank] = &(bin_ptr->second); + rowhit = true; } } - std::list::iterator next = m_last_row[bank]->back(); + std::list::iterator next = m_current_last_row[bank]->back(); dram_req_t *req = (*next); + //rowblp stats + m_dram->access_num++; + bool is_write = req->data->is_write(); + if(is_write) + m_dram->write_num++; + else + m_dram->read_num++; + + if(rowhit) { + m_dram->hits_num++; + if(is_write) + m_dram->hits_write_num++; + else + m_dram->hits_read_num++; + } + m_stats->concurrent_row_access[m_dram->id][bank]++; m_stats->row_access[m_dram->id][bank]++; - m_last_row[bank]->pop_back(); + m_current_last_row[bank]->pop_back(); - m_queue[bank].erase(next); - if ( m_last_row[bank]->empty() ) { - m_bins[bank].erase( req->row ); - m_last_row[bank] = NULL; + m_current_queue[bank].erase(next); + if ( m_current_last_row[bank]->empty() ) { + m_current_bins[bank].erase( req->row ); + m_current_last_row[bank] = NULL; } #ifdef DEBUG_FAST_IDEAL_SCHED if ( req ) printf("%08u : DRAM(%u) scheduling memory request to bank=%u, row=%u\n", (unsigned)gpu_sim_cycle, m_dram->id, req->bk, req->row ); #endif - assert( req != NULL && m_num_pending != 0 ); - m_num_pending--; + + if(m_config->seperate_write_queue_enabled && req->data->is_write()) { + assert( req != NULL && m_num_write_pending != 0 ); + m_num_write_pending--; + } + else { + assert( req != NULL && m_num_pending != 0 ); + m_num_pending--; + } return req; } @@ -129,7 +202,7 @@ void dram_t::scheduler_frfcfs() { unsigned mrq_latency; frfcfs_scheduler *sched = m_frfcfs_scheduler; - while ( !mrqq->empty() && (!m_config->gpgpu_frfcfs_dram_sched_queue_size || sched->num_pending() < m_config->gpgpu_frfcfs_dram_sched_queue_size)) { + while ( !mrqq->empty() ) { dram_req_t *req = mrqq->pop(); // Power stats @@ -160,6 +233,8 @@ void dram_t::scheduler_frfcfs() bk[b]->mrq = req; if (m_config->gpgpu_memlatency_stat) { mrq_latency = gpu_sim_cycle + gpu_tot_sim_cycle - bk[b]->mrq->timestamp; + m_stats->tot_mrq_latency += mrq_latency; + m_stats->tot_mrq_num++; bk[b]->mrq->timestamp = gpu_tot_sim_cycle + gpu_sim_cycle; m_stats->mrq_lat_table[LOGB2(mrq_latency)]++; if (mrq_latency > m_stats->max_mrq_latency) { diff --git a/src/gpgpu-sim/dram_sched.h b/src/gpgpu-sim/dram_sched.h index 3860f5b..63f5831 100644 --- a/src/gpgpu-sim/dram_sched.h +++ b/src/gpgpu-sim/dram_sched.h @@ -35,6 +35,11 @@ #include #include +enum memory_mode { + READ_MODE = 0, + WRITE_MODE +}; + class frfcfs_scheduler { public: frfcfs_scheduler( const memory_config *config, dram_t *dm, memory_stats_t *stats ); @@ -43,17 +48,24 @@ public: dram_req_t *schedule( unsigned bank, unsigned curr_row ); void print( FILE *fp ); unsigned num_pending() const { return m_num_pending;} + unsigned num_write_pending() const { return m_num_write_pending;} private: const memory_config *m_config; dram_t *m_dram; unsigned m_num_pending; + unsigned m_num_write_pending; std::list *m_queue; std::map::iterator> > *m_bins; std::list::iterator> **m_last_row; unsigned *curr_row_service_time; //one set of variables for each bank. unsigned *row_service_timestamp; //tracks when scheduler began servicing current row + std::list *m_write_queue; + std::map::iterator> > *m_write_bins; + std::list::iterator> **m_last_write_row; + + enum memory_mode m_mode; memory_stats_t *m_stats; }; diff --git a/src/gpgpu-sim/gpu-cache.cc b/src/gpgpu-sim/gpu-cache.cc index 8886398..ba81440 100644 --- a/src/gpgpu-sim/gpu-cache.cc +++ b/src/gpgpu-sim/gpu-cache.cc @@ -29,7 +29,6 @@ #include "stat-tool.h" #include -#define MAX_DEFAULT_CACHE_SIZE_MULTIBLIER 4 // used to allocate memory that is large enough to adapt the changes in cache size across kernels const char * cache_request_status_str(enum cache_request_status status) @@ -38,7 +37,8 @@ const char * cache_request_status_str(enum cache_request_status status) "HIT", "HIT_RESERVED", "MISS", - "RESERVATION_FAIL" + "RESERVATION_FAIL", + "SECTOR_MISS" }; assert(sizeof(static_cache_request_status_str) / sizeof(const char*) == NUM_CACHE_REQUEST_STATUS); @@ -47,6 +47,22 @@ const char * cache_request_status_str(enum cache_request_status status) return static_cache_request_status_str[status]; } +const char * cache_fail_status_str(enum cache_reservation_fail_reason status) +{ + static const char * static_cache_reservation_fail_reason_str[] = { + "LINE_ALLOC_FAIL", + "MISS_QUEUE_FULL", + "MSHR_ENRTY_FAIL", + "MSHR_MERGE_ENRTY_FAIL", + "MSHR_RW_PENDING" + }; + + assert(sizeof(static_cache_reservation_fail_reason_str) / sizeof(const char*) == NUM_CACHE_RESERVATION_FAIL_STATUS); + assert(status < NUM_CACHE_RESERVATION_FAIL_STATUS); + + return static_cache_reservation_fail_reason_str[status]; +} + unsigned l1d_cache_config::set_index(new_addr_type addr) const{ unsigned set_index = m_nset; // Default to linear set index function unsigned lower_xor = 0; @@ -54,10 +70,11 @@ unsigned l1d_cache_config::set_index(new_addr_type addr) const{ switch(m_set_index_function){ case FERMI_HASH_SET_FUNCTION: + case BITWISE_XORING_FUNCTION: /* * Set Indexing function from "A Detailed GPU Cache Model Based on Reuse Distance Theory" * Cedric Nugteren et al. - * ISCA 2014 + * HPCA 2014 */ if(m_nset == 32 || m_nset == 64){ // Lower xor value is bits 7-11 @@ -80,6 +97,36 @@ unsigned l1d_cache_config::set_index(new_addr_type addr) const{ } break; + case HASH_IPOLY_FUNCTION: + /* + * Set Indexing function from "Pseudo-randomly interleaved memory." + * Rau, B. R et al. + * ISCA 1991 + * + * "Sacat: streaming-aware conflict-avoiding thrashing-resistant gpgpu cache management scheme." + * Khairy et al. + * IEEE TPDS 2017. + */ + if(m_nset == 32 || m_nset == 64){ + std::bitset<64> a(addr); + std::bitset<6> index; + index[0] = a[25]^a[24]^a[23]^a[22]^a[21]^a[18]^a[17]^a[15]^a[12]^a[7]; //10 + index[1] = a[26]^a[25]^a[24]^a[23]^a[22]^a[19]^a[18]^a[16]^a[13]^a[8]; //10 + index[2] = a[26]^a[22]^a[21]^a[20]^a[19]^a[18]^a[15]^a[14]^a[12]^a[9]; //10 + index[3] = a[23]^a[22]^a[21]^a[20]^a[19]^a[16]^a[15]^a[13]^a[10]; //9 + index[4] = a[24]^a[23]^a[22]^a[21]^a[20]^a[17]^a[16]^a[14]^a[11]; //9 + + if(m_nset == 64) + index[5] = a[12]; + + set_index = index.to_ulong(); + + }else{ /* Else incorrect number of sets for the hashing function */ + assert("\nGPGPU-Sim cache configuration error: The number of sets should be " + "32 or 64 for the hashing set index function.\n" && 0); + } + break; + case CUSTOM_SET_FUNCTION: /* No custom set function implemented */ break; @@ -87,6 +134,10 @@ unsigned l1d_cache_config::set_index(new_addr_type addr) const{ case LINEAR_SET_FUNCTION: set_index = (addr >> m_line_sz_log2) & (m_nset-1); break; + + default: + assert("\nUndefined set index function.\n" && 0); + break; } // Linear function selected or custom set index function not implemented @@ -113,13 +164,16 @@ unsigned l2_cache_config::set_index(new_addr_type addr) const{ tag_array::~tag_array() { + unsigned cache_lines_num = m_config.get_max_num_lines(); + for(unsigned i=0; iget_addr()); + line_table::const_iterator i = pending_lines.find(addr); + if ( i == pending_lines.end() ) { + pending_lines[addr] = mf->get_inst().get_uid(); + } +} + +void tag_array::remove_pending_line(mem_fetch *mf){ + assert(mf); + new_addr_type addr = m_config.block_addr(mf->get_addr()); + line_table::const_iterator i = pending_lines.find(addr); + if ( i != pending_lines.end() ) { + pending_lines.erase(addr); + } } -enum cache_request_status tag_array::probe( new_addr_type addr, unsigned &idx ) const { +enum cache_request_status tag_array::probe( new_addr_type addr, unsigned &idx, mem_fetch* mf, bool probe_mode) const { + mem_access_sector_mask_t mask = mf->get_access_sector_mask(); + return probe(addr, idx, mask, probe_mode, mf); +} + + +enum cache_request_status tag_array::probe( new_addr_type addr, unsigned &idx, mem_access_sector_mask_t mask, bool probe_mode, mem_fetch* mf) const { //assert( m_config.m_write_policy == READ_ONLY ); unsigned set_index = m_config.set_index(addr); new_addr_type tag = m_config.tag(addr); @@ -169,35 +263,45 @@ enum cache_request_status tag_array::probe( new_addr_type addr, unsigned &idx ) // check for hit or pending hit for (unsigned way=0; waym_tag == tag) { - if ( line->m_status == RESERVED ) { + if ( line->get_status(mask) == RESERVED ) { idx = index; return HIT_RESERVED; - } else if ( line->m_status == VALID ) { + } else if ( line->get_status(mask) == VALID ) { idx = index; return HIT; - } else if ( line->m_status == MODIFIED ) { + } else if ( line->get_status(mask) == MODIFIED) { + if(line->is_readable(mask)) { + idx = index; + return HIT; + } + else { + idx = index; + return SECTOR_MISS; + } + + } else if ( line->is_valid_line() && line->get_status(mask) == INVALID ) { idx = index; - return HIT; - } else { - assert( line->m_status == INVALID ); + return SECTOR_MISS; + }else { + assert( line->get_status(mask) == INVALID ); } } - if (line->m_status != RESERVED) { + if (!line->is_reserved_line()) { all_reserved = false; - if (line->m_status == INVALID) { + if (line->is_invalid_line()) { invalid_line = index; } else { // valid line : keep track of most appropriate replacement candidate if ( m_config.m_replacement_policy == LRU ) { - if ( line->m_last_access_time < valid_timestamp ) { - valid_timestamp = line->m_last_access_time; + if ( line->get_last_access_time() < valid_timestamp ) { + valid_timestamp = line->get_last_access_time(); valid_line = index; } } else if ( m_config.m_replacement_policy == FIFO ) { - if ( line->m_alloc_time < valid_timestamp ) { - valid_timestamp = line->m_alloc_time; + if ( line->get_alloc_time() < valid_timestamp ) { + valid_timestamp = line->get_alloc_time(); valid_line = index; } } @@ -215,40 +319,59 @@ enum cache_request_status tag_array::probe( new_addr_type addr, unsigned &idx ) idx = valid_line; } else abort(); // if an unreserved block exists, it is either invalid or replaceable + + if(probe_mode && m_config.is_streaming()){ + line_table::const_iterator i = pending_lines.find(m_config.block_addr(addr)); + assert(mf); + if ( !mf->is_write() && i != pending_lines.end() ) { + if(i->second != mf->get_inst().get_uid()) + return SECTOR_MISS; + } + } + return MISS; } -enum cache_request_status tag_array::access( new_addr_type addr, unsigned time, unsigned &idx ) +enum cache_request_status tag_array::access( new_addr_type addr, unsigned time, unsigned &idx, mem_fetch* mf) { bool wb=false; - cache_block_t evicted; - enum cache_request_status result = access(addr,time,idx,wb,evicted); + evicted_block_info evicted; + enum cache_request_status result = access(addr,time,idx,wb,evicted,mf); assert(!wb); return result; } -enum cache_request_status tag_array::access( new_addr_type addr, unsigned time, unsigned &idx, bool &wb, cache_block_t &evicted ) +enum cache_request_status tag_array::access( new_addr_type addr, unsigned time, unsigned &idx, bool &wb, evicted_block_info &evicted, mem_fetch* mf ) { m_access++; + is_used = true; shader_cache_access_log(m_core_id, m_type_id, 0); // log accesses to cache - enum cache_request_status status = probe(addr,idx); + enum cache_request_status status = probe(addr,idx,mf); switch (status) { case HIT_RESERVED: m_pending_hit++; case HIT: - m_lines[idx].m_last_access_time=time; + m_lines[idx]->set_last_access_time(time, mf->get_access_sector_mask()); break; case MISS: m_miss++; shader_cache_access_log(m_core_id, m_type_id, 1); // log cache misses if ( m_config.m_alloc_policy == ON_MISS ) { - if( m_lines[idx].m_status == MODIFIED ) { + if( m_lines[idx]->is_modified_line()) { wb = true; - evicted = m_lines[idx]; + evicted.set_info(m_lines[idx]->m_block_addr, m_lines[idx]->get_modified_size()); } - m_lines[idx].allocate( m_config.tag(addr), m_config.block_addr(addr), time ); + m_lines[idx]->allocate( m_config.tag(addr), m_config.block_addr(addr), time, mf->get_access_sector_mask()); } break; + case SECTOR_MISS: + assert(m_config.m_cache_type == SECTOR); + m_sector_miss++; + shader_cache_access_log(m_core_id, m_type_id, 1); // log cache misses + if ( m_config.m_alloc_policy == ON_MISS ) { + ((sector_cache_block*)m_lines[idx])->allocate_sector( time, mf->get_access_sector_mask() ); + } + break; case RESERVATION_FAIL: m_res_fail++; shader_cache_access_log(m_core_id, m_type_id, 1); // log cache misses @@ -261,37 +384,70 @@ enum cache_request_status tag_array::access( new_addr_type addr, unsigned time, return status; } -void tag_array::fill( new_addr_type addr, unsigned time ) +void tag_array::fill( new_addr_type addr, unsigned time, mem_fetch* mf) +{ + fill(addr, time, mf->get_access_sector_mask()); +} + +void tag_array::fill( new_addr_type addr, unsigned time, mem_access_sector_mask_t mask ) { - assert( m_config.m_alloc_policy == ON_FILL ); + //assert( m_config.m_alloc_policy == ON_FILL ); unsigned idx; - enum cache_request_status status = probe(addr,idx); - assert(status==MISS); // MSHR should have prevented redundant memory request - m_lines[idx].allocate( m_config.tag(addr), m_config.block_addr(addr), time ); - m_lines[idx].fill(time); + enum cache_request_status status = probe(addr,idx,mask); + //assert(status==MISS||status==SECTOR_MISS); // MSHR should have prevented redundant memory request + if(status==MISS) + m_lines[idx]->allocate( m_config.tag(addr), m_config.block_addr(addr), time, mask ); + else if (status==SECTOR_MISS) { + assert(m_config.m_cache_type == SECTOR); + ((sector_cache_block*)m_lines[idx])->allocate_sector( time, mask ); + } + + m_lines[idx]->fill(time, mask); } -void tag_array::fill( unsigned index, unsigned time ) +void tag_array::fill( unsigned index, unsigned time, mem_fetch* mf) { assert( m_config.m_alloc_policy == ON_MISS ); - m_lines[index].fill(time); + m_lines[index]->fill(time, mf->get_access_sector_mask()); } + +//TODO: we need write back the flushed data to the upper level void tag_array::flush() { + if(!is_used) + return; + for (unsigned i=0; i < m_config.get_num_lines(); i++) - m_lines[i].m_status = INVALID; + if(m_lines[i]->is_modified_line()) { + for(unsigned j=0; j < SECTOR_CHUNCK_SIZE; j++) + m_lines[i]->set_status(INVALID, mem_access_sector_mask_t().set(j)) ; + } + + is_used = false; +} + +void tag_array::invalidate() +{ + if(!is_used) + return; + + for (unsigned i=0; i < m_config.get_num_lines(); i++) + for(unsigned j=0; j < SECTOR_CHUNCK_SIZE; j++) + m_lines[i]->set_status(INVALID, mem_access_sector_mask_t().set(j)) ; + + is_used = false; } float tag_array::windowed_miss_rate( ) const { unsigned n_access = m_access - m_prev_snapshot_access; - unsigned n_miss = m_miss - m_prev_snapshot_miss; + unsigned n_miss = (m_miss+m_sector_miss) - m_prev_snapshot_miss; // unsigned n_pending_hit = m_pending_hit - m_prev_snapshot_pending_hit; float missrate = 0.0f; if (n_access != 0) - missrate = (float) n_miss / n_access; + missrate = (float) (n_miss+m_sector_miss) / n_access; return missrate; } @@ -299,23 +455,24 @@ void tag_array::new_window() { m_prev_snapshot_access = m_access; m_prev_snapshot_miss = m_miss; + m_prev_snapshot_miss = m_miss + m_sector_miss; m_prev_snapshot_pending_hit = m_pending_hit; } void tag_array::print( FILE *stream, unsigned &total_access, unsigned &total_misses ) const { m_config.print(stream); - fprintf( stream, "\t\tAccess = %d, Miss = %d (%.3g), PendingHit = %d (%.3g)\n", - m_access, m_miss, (float) m_miss / m_access, + fprintf( stream, "\t\tAccess = %d, Miss = %d, Sector_Miss = %d, Total_Miss = %d (%.3g), PendingHit = %d (%.3g)\n", + m_access, m_miss, m_sector_miss, (m_miss+m_sector_miss), (float) (m_miss+m_sector_miss) / m_access, m_pending_hit, (float) m_pending_hit / m_access); - total_misses+=m_miss; + total_misses+=(m_miss+m_sector_miss); total_access+=m_access; } void tag_array::get_stats(unsigned &total_access, unsigned &total_misses, unsigned &total_hit_res, unsigned &total_res_fail) const{ // Update statistics from the tag array total_access = m_access; - total_misses = m_miss; + total_misses = (m_miss+m_sector_miss); total_hit_res = m_pending_hit; total_res_fail = m_res_fail; } @@ -324,16 +481,17 @@ void tag_array::get_stats(unsigned &total_access, unsigned &total_misses, unsign bool was_write_sent( const std::list &events ) { for( std::list::const_iterator e=events.begin(); e!=events.end(); e++ ) { - if( *e == WRITE_REQUEST_SENT ) + if( (*e).m_cache_event_type == WRITE_REQUEST_SENT ) return true; } return false; } -bool was_writeback_sent( const std::list &events ) +bool was_writeback_sent( const std::list &events, cache_event& wb_event) { for( std::list::const_iterator e=events.begin(); e!=events.end(); e++ ) { - if( *e == WRITE_BACK_REQUEST_SENT ) + if( (*e).m_cache_event_type == WRITE_BACK_REQUEST_SENT ) + wb_event = *e; return true; } return false; @@ -342,7 +500,16 @@ bool was_writeback_sent( const std::list &events ) bool was_read_sent( const std::list &events ) { for( std::list::const_iterator e=events.begin(); e!=events.end(); e++ ) { - if( *e == READ_REQUEST_SENT ) + if( (*e).m_cache_event_type == READ_REQUEST_SENT ) + return true; + } + return false; +} + +bool was_writeallocate_sent( const std::list &events ) +{ + for( std::list::const_iterator e=events.begin(); e!=events.end(); e++ ) { + if( (*e).m_cache_event_type == WRITE_ALLOCATE_SENT ) return true; } return false; @@ -375,11 +542,27 @@ void mshr_table::add( new_addr_type block_addr, mem_fetch *mf ){ } } +/// check is_read_after_write_pending +bool mshr_table::is_read_after_write_pending( new_addr_type block_addr){ + std::list my_list = m_data[block_addr].m_list; + bool write_found = false; + for (std::list::iterator it=my_list.begin(); it != my_list.end(); ++it) + { + if((*it)->is_write()) //Pending Write Request + write_found = true; + else if(write_found) //Pending Read Request and we found previous Write + return true; + } + + return false; + +} + /// Accept a new cache fill response: mark entry ready for processing void mshr_table::mark_ready( new_addr_type block_addr, bool &has_atomic ){ assert( !busy() ); table::iterator a = m_data.find(block_addr); - assert( a != m_data.end() ); // don't remove same request twice + assert( a != m_data.end() ); m_current_response.push_back( block_addr ); has_atomic = a->second.m_has_atomic; assert( m_current_response.size() <= m_data.size() ); @@ -417,9 +600,11 @@ void mshr_table::display( FILE *fp ) const{ /***************************************************************** Caches *****************************************************************/ cache_stats::cache_stats(){ m_stats.resize(NUM_MEM_ACCESS_TYPE); + m_fail_stats.resize(NUM_MEM_ACCESS_TYPE); for(unsigned i=0; i 0) - fprintf(fout, "\t%s[%s][%s] = %u\n", - m_cache_name.c_str(), - mem_access_type_str((enum mem_access_type)type), - "TOTAL_ACCESS", - total_access[type]); + if(total_access[type] > 0) + fprintf(fout, "\t%s[%s][%s] = %u\n", + m_cache_name.c_str(), + mem_access_type_str((enum mem_access_type)type), + "TOTAL_ACCESS", + total_access[type]); } } +void cache_stats::print_fail_stats(FILE *fout, const char *cache_name) const{ + std::string m_cache_name = cache_name; + for (unsigned type = 0; type < NUM_MEM_ACCESS_TYPE; ++type) { + for (unsigned fail = 0; fail < NUM_CACHE_RESERVATION_FAIL_STATUS; ++fail) { + if(m_fail_stats[type][fail] > 0){ + fprintf(fout, "\t%s[%s][%s] = %u\n", + m_cache_name.c_str(), + mem_access_type_str((enum mem_access_type)type), + cache_fail_status_str((enum cache_reservation_fail_reason)fail), + m_fail_stats[type][fail]); + } + } + } +} + void cache_sub_stats::print_port_stats(FILE *fout, const char *cache_name) const { float data_port_util = 0.0f; @@ -580,10 +813,10 @@ void cache_stats::get_sub_stats(struct cache_sub_stats &css) const{ for (unsigned type = 0; type < NUM_MEM_ACCESS_TYPE; ++type) { for (unsigned status = 0; status < NUM_CACHE_REQUEST_STATUS; ++status) { - if(status == HIT || status == MISS || status == HIT_RESERVED) + if(status == HIT || status == MISS || status == SECTOR_MISS || status == HIT_RESERVED) t_css.accesses += m_stats[type][status]; - if(status == MISS) + if(status == MISS || status == SECTOR_MISS) t_css.misses += m_stats[type][status]; if(status == HIT_RESERVED) @@ -611,6 +844,16 @@ bool cache_stats::check_valid(int type, int status) const{ return false; } +bool cache_stats::check_fail_valid(int type, int fail) const{ + /// + /// Verify a valid access_type/access_status + /// + if((type >= 0) && (type < NUM_MEM_ACCESS_TYPE) && (fail >= 0) && (fail < NUM_CACHE_RESERVATION_FAIL_STATUS)) + return true; + else + return false; +} + void cache_stats::sample_cache_port_utility(bool data_port_busy, bool fill_port_busy) { m_cache_port_available_cycles += 1; @@ -639,15 +882,18 @@ void baseline_cache::bandwidth_management::use_data_port(mem_fetch *mf, enum cac unsigned data_cycles = data_size / port_width + ((data_size % port_width > 0)? 1 : 0); m_data_port_occupied_cycles += data_cycles; } break; - case HIT_RESERVED: + case HIT_RESERVED: case MISS: { // the data array is accessed to read out the entire line for write-back - if (was_writeback_sent(events)) { - unsigned data_cycles = m_config.m_line_sz / port_width; + // in case of sector cache we need to write bank only the modified sectors + cache_event ev(WRITE_BACK_REQUEST_SENT); + if (was_writeback_sent(events, ev)) { + unsigned data_cycles = ev.m_evicted_block.m_modified_size / port_width; m_data_port_occupied_cycles += data_cycles; } } break; - case RESERVATION_FAIL: + case SECTOR_MISS: + case RESERVATION_FAIL: // Does not consume any port bandwidth break; default: @@ -660,7 +906,7 @@ void baseline_cache::bandwidth_management::use_data_port(mem_fetch *mf, enum cac void baseline_cache::bandwidth_management::use_fill_port(mem_fetch *mf) { // assume filling the entire line with the returned request - unsigned fill_cycles = m_config.m_line_sz / m_config.m_data_port_width; + unsigned fill_cycles = m_config.get_atom_sz() / m_config.m_data_port_width; m_fill_port_occupied_cycles += fill_cycles; } @@ -707,21 +953,43 @@ void baseline_cache::cycle(){ /// Interface for response from lower memory level (model bandwidth restictions in caller) void baseline_cache::fill(mem_fetch *mf, unsigned time){ + + if(m_config.m_mshr_type == SECTOR_ASSOC) { + assert(mf->get_original_mf()); + extra_mf_fields_lookup::iterator e = m_extra_mf_fields.find(mf->get_original_mf()); + assert( e != m_extra_mf_fields.end() ); + e->second.pending_read--; + + if(e->second.pending_read > 0) { + //wait for the other requests to come back + delete mf; + return; + } else { + mem_fetch *temp = mf; + mf = mf->get_original_mf(); + delete temp; + } + } + extra_mf_fields_lookup::iterator e = m_extra_mf_fields.find(mf); assert( e != m_extra_mf_fields.end() ); assert( e->second.m_valid ); mf->set_data_size( e->second.m_data_size ); + mf->set_addr( e->second.m_addr ); if ( m_config.m_alloc_policy == ON_MISS ) - m_tag_array->fill(e->second.m_cache_index,time); - else if ( m_config.m_alloc_policy == ON_FILL ) - m_tag_array->fill(e->second.m_block_addr,time); + m_tag_array->fill(e->second.m_cache_index,time,mf); + else if ( m_config.m_alloc_policy == ON_FILL ) { + m_tag_array->fill(e->second.m_block_addr,time,mf); + if(m_config.is_streaming()) + m_tag_array->remove_pending_line(mf); + } else abort(); bool has_atomic = false; m_mshrs.mark_ready(e->second.m_block_addr, has_atomic); if (has_atomic) { assert(m_config.m_alloc_policy == ON_MISS); - cache_block_t &block = m_tag_array->get_block(e->second.m_cache_index); - block.m_status = MODIFIED; // mark line as dirty for atomic operation + cache_block_t* block = m_tag_array->get_block(e->second.m_cache_index); + block->set_status(MODIFIED, mf->get_access_sector_mask()); // mark line as dirty for atomic operation } m_extra_mf_fields.erase(mf); m_bandwidth_management.use_fill_port(mf); @@ -749,45 +1017,59 @@ void baseline_cache::send_read_request(new_addr_type addr, new_addr_type block_a unsigned time, bool &do_miss, std::list &events, bool read_only, bool wa){ bool wb=false; - cache_block_t e; + evicted_block_info e; send_read_request(addr, block_addr, cache_index, mf, time, do_miss, wb, e, events, read_only, wa); } /// Read miss handler. Check MSHR hit or MSHR available void baseline_cache::send_read_request(new_addr_type addr, new_addr_type block_addr, unsigned cache_index, mem_fetch *mf, - unsigned time, bool &do_miss, bool &wb, cache_block_t &evicted, std::list &events, bool read_only, bool wa){ + unsigned time, bool &do_miss, bool &wb, evicted_block_info &evicted, std::list &events, bool read_only, bool wa){ - bool mshr_hit = m_mshrs.probe(block_addr); - bool mshr_avail = !m_mshrs.full(block_addr); + new_addr_type mshr_addr = m_config.mshr_addr(mf->get_addr()); + bool mshr_hit = m_mshrs.probe(mshr_addr); + bool mshr_avail = !m_mshrs.full(mshr_addr); if ( mshr_hit && mshr_avail ) { if(read_only) - m_tag_array->access(block_addr,time,cache_index); + m_tag_array->access(block_addr,time,cache_index,mf); else - m_tag_array->access(block_addr,time,cache_index,wb,evicted); + m_tag_array->access(block_addr,time,cache_index,wb,evicted,mf); - m_mshrs.add(block_addr,mf); + m_mshrs.add(mshr_addr,mf); do_miss = true; + } else if ( !mshr_hit && mshr_avail && (m_miss_queue.size() < m_config.m_miss_queue_size) ) { if(read_only) - m_tag_array->access(block_addr,time,cache_index); + m_tag_array->access(block_addr,time,cache_index,mf); else - m_tag_array->access(block_addr,time,cache_index,wb,evicted); - - m_mshrs.add(block_addr,mf); - m_extra_mf_fields[mf] = extra_mf_fields(block_addr,cache_index, mf->get_data_size()); - mf->set_data_size( m_config.get_line_sz() ); + m_tag_array->access(block_addr,time,cache_index,wb,evicted,mf); + + m_mshrs.add(mshr_addr,mf); + if(m_config.is_streaming() && m_config.m_cache_type == SECTOR){ + m_tag_array->add_pending_line(mf); + } + m_extra_mf_fields[mf] = extra_mf_fields(mshr_addr,mf->get_addr(),cache_index, mf->get_data_size(), m_config); + mf->set_data_size( m_config.get_atom_sz() ); + mf->set_addr( mshr_addr ); m_miss_queue.push_back(mf); mf->set_status(m_miss_queue_status,time); if(!wa) - events.push_back(READ_REQUEST_SENT); + events.push_back(cache_event(READ_REQUEST_SENT)); + do_miss = true; } + else if(mshr_hit && !mshr_avail) + m_stats.inc_fail_stats(mf->get_access_type(), MSHR_MERGE_ENRTY_FAIL); + else if (!mshr_hit && !mshr_avail) + m_stats.inc_fail_stats(mf->get_access_type(), MSHR_ENRTY_FAIL); + else + assert(0); } /// Sends write request to lower level memory (write or writeback) void data_cache::send_write_request(mem_fetch *mf, cache_event request, unsigned time, std::list &events){ - events.push_back(request); + + events.push_back(request); m_miss_queue.push_back(mf); mf->set_status(m_miss_queue_status,time); } @@ -798,40 +1080,44 @@ void data_cache::send_write_request(mem_fetch *mf, cache_event request, unsigned /// Write-back hit: Mark block as modified cache_request_status data_cache::wr_hit_wb(new_addr_type addr, unsigned cache_index, mem_fetch *mf, unsigned time, std::list &events, enum cache_request_status status ){ new_addr_type block_addr = m_config.block_addr(addr); - m_tag_array->access(block_addr,time,cache_index); // update LRU state - cache_block_t &block = m_tag_array->get_block(cache_index); - block.m_status = MODIFIED; + m_tag_array->access(block_addr,time,cache_index,mf); // update LRU state + cache_block_t* block = m_tag_array->get_block(cache_index); + block->set_status(MODIFIED, mf->get_access_sector_mask()); return HIT; } /// Write-through hit: Directly send request to lower level memory cache_request_status data_cache::wr_hit_wt(new_addr_type addr, unsigned cache_index, mem_fetch *mf, unsigned time, std::list &events, enum cache_request_status status ){ - if(miss_queue_full(0)) + if(miss_queue_full(0)) { + m_stats.inc_fail_stats(mf->get_access_type(), MISS_QUEUE_FULL); return RESERVATION_FAIL; // cannot handle request this cycle + } new_addr_type block_addr = m_config.block_addr(addr); - m_tag_array->access(block_addr,time,cache_index); // update LRU state - cache_block_t &block = m_tag_array->get_block(cache_index); - block.m_status = MODIFIED; + m_tag_array->access(block_addr,time,cache_index,mf); // update LRU state + cache_block_t* block = m_tag_array->get_block(cache_index); + block->set_status(MODIFIED, mf->get_access_sector_mask()); // generate a write-through - send_write_request(mf, WRITE_REQUEST_SENT, time, events); + send_write_request(mf, cache_event(WRITE_REQUEST_SENT), time, events); return HIT; } /// Write-evict hit: Send request to lower level memory and invalidate corresponding block cache_request_status data_cache::wr_hit_we(new_addr_type addr, unsigned cache_index, mem_fetch *mf, unsigned time, std::list &events, enum cache_request_status status ){ - if(miss_queue_full(0)) + if(miss_queue_full(0)) { + m_stats.inc_fail_stats(mf->get_access_type(), MISS_QUEUE_FULL); return RESERVATION_FAIL; // cannot handle request this cycle + } // generate a write-through/evict - cache_block_t &block = m_tag_array->get_block(cache_index); - send_write_request(mf, WRITE_REQUEST_SENT, time, events); + cache_block_t* block = m_tag_array->get_block(cache_index); + send_write_request(mf, cache_event(WRITE_REQUEST_SENT), time, events); // Invalidate block - block.m_status = INVALID; + block->set_status(INVALID, mf->get_access_sector_mask()); return HIT; } @@ -850,34 +1136,46 @@ enum cache_request_status data_cache::wr_hit_global_we_local_wb(new_addr_type ad /// Write-allocate miss: Send write request to lower level memory // and send a read request for the same block enum cache_request_status -data_cache::wr_miss_wa( new_addr_type addr, +data_cache::wr_miss_wa_naive( new_addr_type addr, unsigned cache_index, mem_fetch *mf, unsigned time, std::list &events, enum cache_request_status status ) { new_addr_type block_addr = m_config.block_addr(addr); + new_addr_type mshr_addr = m_config.mshr_addr(mf->get_addr()); // Write allocate, maximum 3 requests (write miss, read request, write back request) // Conservatively ensure the worst-case request can be handled this cycle - bool mshr_hit = m_mshrs.probe(block_addr); - bool mshr_avail = !m_mshrs.full(block_addr); + bool mshr_hit = m_mshrs.probe(mshr_addr); + bool mshr_avail = !m_mshrs.full(mshr_addr); if(miss_queue_full(2) || (!(mshr_hit && mshr_avail) - && !(!mshr_hit && mshr_avail - && (m_miss_queue.size() < m_config.m_miss_queue_size)))) + && !(!mshr_hit && mshr_avail && (m_miss_queue.size() < m_config.m_miss_queue_size)))) { + //check what is the exactly the failure reason + if(miss_queue_full(2) ) + m_stats.inc_fail_stats(mf->get_access_type(), MISS_QUEUE_FULL); + else if(mshr_hit && !mshr_avail) + m_stats.inc_fail_stats(mf->get_access_type(), MSHR_MERGE_ENRTY_FAIL); + else if (!mshr_hit && !mshr_avail) + m_stats.inc_fail_stats(mf->get_access_type(), MSHR_ENRTY_FAIL); + else + assert(0); + return RESERVATION_FAIL; + } - send_write_request(mf, WRITE_REQUEST_SENT, time, events); + send_write_request(mf, cache_event(WRITE_REQUEST_SENT), time, events); // Tries to send write allocate request, returns true on success and false on failure //if(!send_write_allocate(mf, addr, block_addr, cache_index, time, events)) // return RESERVATION_FAIL; const mem_access_t *ma = new mem_access_t( m_wr_alloc_type, mf->get_addr(), - mf->get_data_size(), + m_config.get_atom_sz(), false, // Now performing a read mf->get_access_warp_mask(), - mf->get_access_byte_mask() ); + mf->get_access_byte_mask(), + mf->get_access_sector_mask()); mem_fetch *n_mf = new mem_fetch( *ma, NULL, @@ -889,20 +1187,22 @@ data_cache::wr_miss_wa( new_addr_type addr, bool do_miss = false; bool wb = false; - cache_block_t evicted; + evicted_block_info evicted; // Send read request resulting from write miss send_read_request(addr, block_addr, cache_index, n_mf, time, do_miss, wb, evicted, events, false, true); + events.push_back(cache_event(WRITE_ALLOCATE_SENT)); + if( do_miss ){ // If evicted block is modified and not a write-through // (already modified lower level) if( wb && (m_config.m_write_policy != WRITE_THROUGH) ) { + assert(status == MISS); //SECTOR_MISS and HIT_RESERVED should not send write back mem_fetch *wb = m_memfetch_creator->alloc(evicted.m_block_addr, - m_wrbk_type,m_config.get_line_sz(),true); - m_miss_queue.push_back(wb); - wb->set_status(m_miss_queue_status,time); + m_wrbk_type,evicted.m_modified_size,true); + send_write_request(wb, cache_event(WRITE_BACK_REQUEST_SENT, evicted), time, events); } return MISS; } @@ -910,6 +1210,177 @@ data_cache::wr_miss_wa( new_addr_type addr, return RESERVATION_FAIL; } + +enum cache_request_status +data_cache::wr_miss_wa_fetch_on_write( new_addr_type addr, + unsigned cache_index, mem_fetch *mf, + unsigned time, std::list &events, + enum cache_request_status status ) +{ + new_addr_type block_addr = m_config.block_addr(addr); + new_addr_type mshr_addr = m_config.mshr_addr(mf->get_addr()); + + if(mf->get_access_byte_mask().count() == m_config.get_atom_sz()) + { + //if the request writes to the whole cache line/sector, then, write and set cache line Modified. + //and no need to send read request to memory or reserve mshr + + if(miss_queue_full(0)) { + m_stats.inc_fail_stats(mf->get_access_type(), MISS_QUEUE_FULL); + return RESERVATION_FAIL; // cannot handle request this cycle + } + + bool wb = false; + evicted_block_info evicted; + + cache_request_status status = m_tag_array->access(block_addr,time,cache_index,wb,evicted,mf); + assert(status != HIT); + cache_block_t* block = m_tag_array->get_block(cache_index); + block->set_status(MODIFIED, mf->get_access_sector_mask()); + if(status == HIT_RESERVED) + block->set_ignore_on_fill(true, mf->get_access_sector_mask()); + + if( status != RESERVATION_FAIL ){ + // If evicted block is modified and not a write-through + // (already modified lower level) + if( wb && (m_config.m_write_policy != WRITE_THROUGH) ) { + mem_fetch *wb = m_memfetch_creator->alloc(evicted.m_block_addr, + m_wrbk_type,evicted.m_modified_size,true); + send_write_request(wb, cache_event(WRITE_BACK_REQUEST_SENT, evicted), time, events); + } + return MISS; + } + return RESERVATION_FAIL; + } + else + { + bool mshr_hit = m_mshrs.probe(mshr_addr); + bool mshr_avail = !m_mshrs.full(mshr_addr); + if(miss_queue_full(1) + || (!(mshr_hit && mshr_avail) + && !(!mshr_hit && mshr_avail && (m_miss_queue.size() < m_config.m_miss_queue_size)))) { + //check what is the exactly the failure reason + if(miss_queue_full(1) ) + m_stats.inc_fail_stats(mf->get_access_type(), MISS_QUEUE_FULL); + else if(mshr_hit && !mshr_avail) + m_stats.inc_fail_stats(mf->get_access_type(), MSHR_MERGE_ENRTY_FAIL); + else if (!mshr_hit && !mshr_avail) + m_stats.inc_fail_stats(mf->get_access_type(), MSHR_ENRTY_FAIL); + else + assert(0); + + return RESERVATION_FAIL; + } + + + //prevent Write - Read - Write in pending mshr + //allowing another write will override the value of the first write, and the pending read request will read incorrect result from the second write + if(m_mshrs.probe(mshr_addr) && m_mshrs.is_read_after_write_pending(mshr_addr) && mf->is_write()) + { + //assert(0); + m_stats.inc_fail_stats(mf->get_access_type(), MSHR_RW_PENDING); + return RESERVATION_FAIL; + } + + const mem_access_t *ma = new mem_access_t( m_wr_alloc_type, + mf->get_addr(), + m_config.get_atom_sz(), + false, // Now performing a read + mf->get_access_warp_mask(), + mf->get_access_byte_mask(), + mf->get_access_sector_mask()); + + mem_fetch *n_mf = new mem_fetch( *ma, + NULL, + mf->get_ctrl_size(), + mf->get_wid(), + mf->get_sid(), + mf->get_tpc(), + mf->get_mem_config(), + NULL, + mf); + + + new_addr_type block_addr = m_config.block_addr(addr); + bool do_miss = false; + bool wb = false; + evicted_block_info evicted; + send_read_request( addr, + block_addr, + cache_index, + n_mf, time, do_miss, wb, evicted, events, false, true); + + cache_block_t* block = m_tag_array->get_block(cache_index); + block->set_modified_on_fill(true, mf->get_access_sector_mask()); + + events.push_back(cache_event(WRITE_ALLOCATE_SENT)); + + if( do_miss ){ + // If evicted block is modified and not a write-through + // (already modified lower level) + if(wb && (m_config.m_write_policy != WRITE_THROUGH) ){ + mem_fetch *wb = m_memfetch_creator->alloc(evicted.m_block_addr, + m_wrbk_type,evicted.m_modified_size,true); + send_write_request(wb, cache_event(WRITE_BACK_REQUEST_SENT, evicted), time, events); + } + return MISS; + } + return RESERVATION_FAIL; + } +} + +enum cache_request_status +data_cache::wr_miss_wa_lazy_fetch_on_read( new_addr_type addr, + unsigned cache_index, mem_fetch *mf, + unsigned time, std::list &events, + enum cache_request_status status ) +{ + + new_addr_type block_addr = m_config.block_addr(addr); + new_addr_type mshr_addr = m_config.mshr_addr(mf->get_addr()); + + + //if the request writes to the whole cache line/sector, then, write and set cache line Modified. + //and no need to send read request to memory or reserve mshr + + if(miss_queue_full(0)) { + m_stats.inc_fail_stats(mf->get_access_type(), MISS_QUEUE_FULL); + return RESERVATION_FAIL; // cannot handle request this cycle + } + + bool wb = false; + evicted_block_info evicted; + + cache_request_status m_status = m_tag_array->access(block_addr,time,cache_index,wb,evicted,mf); + assert(m_status != HIT); + cache_block_t* block = m_tag_array->get_block(cache_index); + block->set_status(MODIFIED, mf->get_access_sector_mask()); + if(m_status == HIT_RESERVED) { + block->set_ignore_on_fill(true, mf->get_access_sector_mask()); + block->set_modified_on_fill(true, mf->get_access_sector_mask()); + } + + if(mf->get_access_byte_mask().count() == m_config.get_atom_sz()) + { + block->set_m_readable(true, mf->get_access_sector_mask()); + } else + { + block->set_m_readable(false, mf->get_access_sector_mask()); + } + + if( m_status != RESERVATION_FAIL ){ + // If evicted block is modified and not a write-through + // (already modified lower level) + if( wb && (m_config.m_write_policy != WRITE_THROUGH) ) { + mem_fetch *wb = m_memfetch_creator->alloc(evicted.m_block_addr, + m_wrbk_type,evicted.m_modified_size,true); + send_write_request(wb, cache_event(WRITE_BACK_REQUEST_SENT, evicted), time, events); + } + return MISS; + } + return RESERVATION_FAIL; +} + /// No write-allocate miss: Simply send write request to lower level memory enum cache_request_status data_cache::wr_miss_no_wa( new_addr_type addr, @@ -919,11 +1390,14 @@ data_cache::wr_miss_no_wa( new_addr_type addr, std::list &events, enum cache_request_status status ) { - if(miss_queue_full(0)) - return RESERVATION_FAIL; // cannot handle request this cycle + if(miss_queue_full(0)) { + m_stats.inc_fail_stats(mf->get_access_type(), MISS_QUEUE_FULL); + return RESERVATION_FAIL; // cannot handle request this cycle + } + // on miss, generate write through (no write buffering -- too many threads for that) - send_write_request(mf, WRITE_REQUEST_SENT, time, events); + send_write_request(mf, cache_event(WRITE_REQUEST_SENT), time, events); return MISS; } @@ -941,13 +1415,13 @@ data_cache::rd_hit_base( new_addr_type addr, enum cache_request_status status ) { new_addr_type block_addr = m_config.block_addr(addr); - m_tag_array->access(block_addr,time,cache_index); + m_tag_array->access(block_addr,time,cache_index,mf); // Atomics treated as global read/write requests - Perform read, mark line as // MODIFIED if(mf->isatomic()){ assert(mf->get_access_type() == GLOBAL_ACC_R); - cache_block_t &block = m_tag_array->get_block(cache_index); - block.m_status = MODIFIED; // mark line as dirty + cache_block_t* block = m_tag_array->get_block(cache_index); + block->set_status(MODIFIED, mf->get_access_sector_mask()) ; // mark line as dirty } return HIT; } @@ -963,15 +1437,17 @@ data_cache::rd_miss_base( new_addr_type addr, unsigned time, std::list &events, enum cache_request_status status ){ - if(miss_queue_full(1)) + if(miss_queue_full(1)) { // cannot handle request this cycle // (might need to generate two requests) + m_stats.inc_fail_stats(mf->get_access_type(), MISS_QUEUE_FULL); return RESERVATION_FAIL; + } new_addr_type block_addr = m_config.block_addr(addr); bool do_miss = false; bool wb = false; - cache_block_t evicted; + evicted_block_info evicted; send_read_request( addr, block_addr, cache_index, @@ -982,12 +1458,12 @@ data_cache::rd_miss_base( new_addr_type addr, // (already modified lower level) if(wb && (m_config.m_write_policy != WRITE_THROUGH) ){ mem_fetch *wb = m_memfetch_creator->alloc(evicted.m_block_addr, - m_wrbk_type,m_config.get_line_sz(),true); + m_wrbk_type,evicted.m_modified_size,true); send_write_request(wb, WRITE_BACK_REQUEST_SENT, time, events); } return MISS; } - return RESERVATION_FAIL; + return RESERVATION_FAIL; } /// Access cache for read_only_cache: returns RESERVATION_FAIL if @@ -998,16 +1474,16 @@ read_only_cache::access( new_addr_type addr, unsigned time, std::list &events ) { - assert( mf->get_data_size() <= m_config.get_line_sz()); + assert( mf->get_data_size() <= m_config.get_atom_sz()); assert(m_config.m_write_policy == READ_ONLY); assert(!mf->get_is_write()); new_addr_type block_addr = m_config.block_addr(addr); unsigned cache_index = (unsigned)-1; - enum cache_request_status status = m_tag_array->probe(block_addr,cache_index); + enum cache_request_status status = m_tag_array->probe(block_addr,cache_index,mf); enum cache_request_status cache_status = RESERVATION_FAIL; if ( status == HIT ) { - cache_status = m_tag_array->access(block_addr,time,cache_index); // update LRU state + cache_status = m_tag_array->access(block_addr,time,cache_index,mf); // update LRU state }else if ( status != RESERVATION_FAIL ) { if(!miss_queue_full(0)){ bool do_miss=false; @@ -1018,7 +1494,10 @@ read_only_cache::access( new_addr_type addr, cache_status = RESERVATION_FAIL; }else{ cache_status = RESERVATION_FAIL; + m_stats.inc_fail_stats(mf->get_access_type(), MISS_QUEUE_FULL); } + }else { + m_stats.inc_fail_stats(mf->get_access_type(), LINE_ALLOC_FAIL); } m_stats.inc_stats(mf->get_access_type(), m_stats.select_stats_status(status, cache_status)); @@ -1047,10 +1526,13 @@ data_cache::process_tag_probe( bool wr, access_status = (this->*m_wr_hit)( addr, cache_index, mf, time, events, probe_status ); - }else if ( probe_status != RESERVATION_FAIL ) { + }else if ( (probe_status != RESERVATION_FAIL) || (probe_status == RESERVATION_FAIL && m_config.m_write_alloc_policy == NO_WRITE_ALLOCATE) ) { access_status = (this->*m_wr_miss)( addr, cache_index, mf, time, events, probe_status ); + }else { + //the only reason for reservation fail here is LINE_ALLOC_FAIL (i.e all lines are reserved) + m_stats.inc_fail_stats(mf->get_access_type(), LINE_ALLOC_FAIL); } }else{ // Read if(probe_status == HIT){ @@ -1061,6 +1543,9 @@ data_cache::process_tag_probe( bool wr, access_status = (this->*m_rd_miss)( addr, cache_index, mf, time, events, probe_status ); + }else { + //the only reason for reservation fail here is LINE_ALLOC_FAIL (i.e all lines are reserved) + m_stats.inc_fail_stats(mf->get_access_type(), LINE_ALLOC_FAIL); } } @@ -1080,12 +1565,12 @@ data_cache::access( new_addr_type addr, std::list &events ) { - assert( mf->get_data_size() <= m_config.get_line_sz()); + assert( mf->get_data_size() <= m_config.get_atom_sz()); bool wr = mf->get_is_write(); new_addr_type block_addr = m_config.block_addr(addr); unsigned cache_index = (unsigned)-1; enum cache_request_status probe_status - = m_tag_array->probe( block_addr, cache_index ); + = m_tag_array->probe( block_addr, cache_index, mf, true); enum cache_request_status access_status = process_tag_probe( wr, probe_status, addr, cache_index, mf, time, events ); m_stats.inc_stats(mf->get_access_type(), @@ -1134,7 +1619,7 @@ enum cache_request_status tex_cache::access( new_addr_type addr, mem_fetch *mf, // at this point, we will accept the request : access tags and immediately allocate line new_addr_type block_addr = m_config.block_addr(addr); unsigned cache_index = (unsigned)-1; - enum cache_request_status status = m_tags.access(block_addr,time,cache_index); + enum cache_request_status status = m_tags.access(block_addr,time,cache_index,mf); enum cache_request_status cache_status = RESERVATION_FAIL; assert( status != RESERVATION_FAIL ); assert( status != HIT_RESERVED ); // as far as tags are concerned: HIT or MISS @@ -1142,12 +1627,12 @@ enum cache_request_status tex_cache::access( new_addr_type addr, mem_fetch *mf, if ( status == MISS ) { // we need to send a memory request... unsigned rob_index = m_rob.push( rob_entry(cache_index, mf, block_addr) ); - m_extra_mf_fields[mf] = extra_mf_fields(rob_index); + m_extra_mf_fields[mf] = extra_mf_fields(rob_index, m_config); mf->set_data_size(m_config.get_line_sz()); - m_tags.fill(cache_index,time); // mark block as valid + m_tags.fill(cache_index,time,mf); // mark block as valid m_request_fifo.push(mf); mf->set_status(m_request_queue_status,time); - events.push_back(READ_REQUEST_SENT); + events.push_back(cache_event(READ_REQUEST_SENT)); cache_status = MISS; } else { // the value *will* *be* in the cache already @@ -1174,7 +1659,7 @@ void tex_cache::cycle(){ unsigned rob_index = m_rob.next_pop_index(); const rob_entry &r = m_rob.peek(rob_index); assert( r.m_request == e.m_request ); - assert( r.m_block_addr == m_config.block_addr(e.m_request->get_addr()) ); + //assert( r.m_block_addr == m_config.block_addr(e.m_request->get_addr()) ); if ( r.m_ready ) { assert( r.m_index == e.m_cache_index ); m_cache[r.m_index].m_valid = true; @@ -1197,6 +1682,23 @@ void tex_cache::cycle(){ /// Place returning cache block into reorder buffer void tex_cache::fill( mem_fetch *mf, unsigned time ) { + if(m_config.m_mshr_type == SECTOR_TEX_FIFO) { + assert(mf->get_original_mf()); + extra_mf_fields_lookup::iterator e = m_extra_mf_fields.find(mf->get_original_mf()); + assert( e != m_extra_mf_fields.end() ); + e->second.pending_read--; + + if(e->second.pending_read > 0) { + //wait for the other requests to come back + delete mf; + return; + } else { + mem_fetch *temp = mf; + mf = mf->get_original_mf(); + delete temp; + } + } + extra_mf_fields_lookup::iterator e = m_extra_mf_fields.find(mf); assert( e != m_extra_mf_fields.end() ); assert( e->second.m_valid ); diff --git a/src/gpgpu-sim/gpu-cache.h b/src/gpgpu-sim/gpu-cache.h index 7535a1d..e663cf6 100644 --- a/src/gpgpu-sim/gpu-cache.h +++ b/src/gpgpu-sim/gpu-cache.h @@ -36,9 +36,12 @@ #include "../tr1_hash_map.h" #include "addrdec.h" +#include + +#define MAX_DEFAULT_CACHE_SIZE_MULTIBLIER 4 enum cache_block_state { - INVALID, + INVALID=0, RESERVED, VALID, MODIFIED @@ -49,13 +52,51 @@ enum cache_request_status { HIT_RESERVED, MISS, RESERVATION_FAIL, + SECTOR_MISS, NUM_CACHE_REQUEST_STATUS }; -enum cache_event { +enum cache_reservation_fail_reason { + LINE_ALLOC_FAIL= 0,// all line are reserved + MISS_QUEUE_FULL, // MISS queue (i.e. interconnect or DRAM) is full + MSHR_ENRTY_FAIL, + MSHR_MERGE_ENRTY_FAIL, + MSHR_RW_PENDING, + NUM_CACHE_RESERVATION_FAIL_STATUS +}; + +enum cache_event_type { WRITE_BACK_REQUEST_SENT, READ_REQUEST_SENT, - WRITE_REQUEST_SENT + WRITE_REQUEST_SENT, + WRITE_ALLOCATE_SENT +}; + +struct evicted_block_info { + new_addr_type m_block_addr; + unsigned m_modified_size; + evicted_block_info() { + m_block_addr = 0; + m_modified_size = 0; + } + void set_info(new_addr_type block_addr, unsigned modified_size){ + m_block_addr = block_addr; + m_modified_size = modified_size; + } +}; + +struct cache_event { + enum cache_event_type m_cache_event_type; + evicted_block_info m_evicted_block; //if it was write_back event, fill the the evicted block info + + cache_event(enum cache_event_type m_cache_event){ + m_cache_event_type = m_cache_event; + } + + cache_event(enum cache_event_type cache_event, evicted_block_info evicted_block){ + m_cache_event_type = cache_event; + m_evicted_block = evicted_block; + } }; const char * cache_request_status_str(enum cache_request_status status); @@ -65,33 +106,340 @@ struct cache_block_t { { m_tag=0; m_block_addr=0; - m_alloc_time=0; - m_fill_time=0; - m_last_access_time=0; - m_status=INVALID; } - void allocate( new_addr_type tag, new_addr_type block_addr, unsigned time ) + + virtual void allocate( new_addr_type tag, new_addr_type block_addr, unsigned time, mem_access_sector_mask_t sector_mask) = 0; + virtual void fill( unsigned time, mem_access_sector_mask_t sector_mask) = 0; + + virtual bool is_invalid_line() = 0; + virtual bool is_valid_line() = 0; + virtual bool is_reserved_line() = 0; + virtual bool is_modified_line() = 0; + + virtual enum cache_block_state get_status( mem_access_sector_mask_t sector_mask) = 0; + virtual void set_status(enum cache_block_state m_status, mem_access_sector_mask_t sector_mask) = 0; + + virtual unsigned get_last_access_time() = 0; + virtual void set_last_access_time(unsigned time, mem_access_sector_mask_t sector_mask) = 0; + virtual unsigned get_alloc_time() = 0; + virtual void set_ignore_on_fill(bool m_ignore, mem_access_sector_mask_t sector_mask) = 0; + virtual void set_modified_on_fill(bool m_modified, mem_access_sector_mask_t sector_mask) = 0; + virtual unsigned get_modified_size() = 0; + virtual void set_m_readable(bool readable, mem_access_sector_mask_t sector_mask)=0; + virtual bool is_readable(mem_access_sector_mask_t sector_mask)=0; + virtual void print_status()=0; + virtual ~cache_block_t() {} + + + new_addr_type m_tag; + new_addr_type m_block_addr; + +}; + +struct line_cache_block: public cache_block_t { + line_cache_block() + { + m_alloc_time=0; + m_fill_time=0; + m_last_access_time=0; + m_status=INVALID; + m_ignore_on_fill_status = false; + m_set_modified_on_fill = false; + m_readable = true; + } + void allocate( new_addr_type tag, new_addr_type block_addr, unsigned time, mem_access_sector_mask_t sector_mask) + { + m_tag=tag; + m_block_addr=block_addr; + m_alloc_time=time; + m_last_access_time=time; + m_fill_time=0; + m_status=RESERVED; + m_ignore_on_fill_status = false; + m_set_modified_on_fill = false; + } + void fill( unsigned time, mem_access_sector_mask_t sector_mask ) + { + //if(!m_ignore_on_fill_status) + // assert( m_status == RESERVED ); + + m_status = m_set_modified_on_fill? MODIFIED : VALID; + + m_fill_time=time; + } + virtual bool is_invalid_line() + { + return m_status == INVALID; + } + virtual bool is_valid_line() + { + return m_status == VALID; + } + virtual bool is_reserved_line() + { + return m_status == RESERVED; + } + virtual bool is_modified_line() + { + return m_status == MODIFIED; + } + + virtual enum cache_block_state get_status(mem_access_sector_mask_t sector_mask) + { + return m_status; + } + virtual void set_status(enum cache_block_state status, mem_access_sector_mask_t sector_mask) + { + m_status = status; + } + virtual unsigned get_last_access_time() + { + return m_last_access_time; + } + virtual void set_last_access_time(unsigned time, mem_access_sector_mask_t sector_mask) + { + m_last_access_time = time; + } + virtual unsigned get_alloc_time() + { + return m_alloc_time; + } + virtual void set_ignore_on_fill(bool m_ignore, mem_access_sector_mask_t sector_mask) + { + m_ignore_on_fill_status = m_ignore; + } + virtual void set_modified_on_fill(bool m_modified, mem_access_sector_mask_t sector_mask) + { + m_set_modified_on_fill = m_modified; + } + virtual unsigned get_modified_size() + { + return SECTOR_CHUNCK_SIZE * SECTOR_SIZE; //i.e. cache line size + } + virtual void set_m_readable(bool readable, mem_access_sector_mask_t sector_mask) + { + m_readable = readable; + } + virtual bool is_readable(mem_access_sector_mask_t sector_mask) { + return m_readable; + } + virtual void print_status() { + printf("m_block_addr is %llu, status = %u\n", m_block_addr, m_status); + } + + +private: + unsigned m_alloc_time; + unsigned m_last_access_time; + unsigned m_fill_time; + cache_block_state m_status; + bool m_ignore_on_fill_status; + bool m_set_modified_on_fill; + bool m_readable; +}; + +struct sector_cache_block : public cache_block_t { + sector_cache_block() { - m_tag=tag; - m_block_addr=block_addr; - m_alloc_time=time; - m_last_access_time=time; - m_fill_time=0; - m_status=RESERVED; + init(); } - void fill( unsigned time ) + + void init() { + for(unsigned i =0; i< SECTOR_CHUNCK_SIZE; ++i) { + m_sector_alloc_time[i]= 0; + m_sector_fill_time[i]= 0; + m_last_sector_access_time[i]= 0; + m_status[i]= INVALID; + m_ignore_on_fill_status[i] = false; + m_set_modified_on_fill[i] = false; + m_readable[i] = true; + } + m_line_alloc_time=0; + m_line_last_access_time=0; + m_line_fill_time=0; + } + + virtual void allocate( new_addr_type tag, new_addr_type block_addr, unsigned time, mem_access_sector_mask_t sector_mask ) { - assert( m_status == RESERVED ); - m_status=VALID; - m_fill_time=time; + allocate_line( tag, block_addr, time, sector_mask ); } - new_addr_type m_tag; - new_addr_type m_block_addr; - unsigned m_alloc_time; - unsigned m_last_access_time; - unsigned m_fill_time; - cache_block_state m_status; + void allocate_line( new_addr_type tag, new_addr_type block_addr, unsigned time, mem_access_sector_mask_t sector_mask ) + { + //allocate a new line + //assert(m_block_addr != 0 && m_block_addr != block_addr); + init(); + m_tag=tag; + m_block_addr=block_addr; + + unsigned sidx = get_sector_index(sector_mask); + + //set sector stats + m_sector_alloc_time[sidx]=time; + m_last_sector_access_time[sidx]=time; + m_sector_fill_time[sidx]=0; + m_status[sidx]=RESERVED; + m_ignore_on_fill_status[sidx] = false; + m_set_modified_on_fill[sidx] = false; + + //set line stats + m_line_alloc_time=time; //only set this for the first allocated sector + m_line_last_access_time=time; + m_line_fill_time=0; + } + + void allocate_sector(unsigned time, mem_access_sector_mask_t sector_mask ) + { + //allocate invalid sector of this allocated valid line + assert(is_valid_line()); + unsigned sidx = get_sector_index(sector_mask); + + //set sector stats + m_sector_alloc_time[sidx]=time; + m_last_sector_access_time[sidx]=time; + m_sector_fill_time[sidx]=0; + if(m_status[sidx]==MODIFIED) //this should be the case only for fetch-on-write policy //TO DO + m_set_modified_on_fill[sidx] = true; + else + m_set_modified_on_fill[sidx] = false; + + m_status[sidx]=RESERVED; + m_ignore_on_fill_status[sidx] = false; + //m_set_modified_on_fill[sidx] = false; + m_readable[sidx] = true; + + //set line stats + m_line_last_access_time=time; + m_line_fill_time=0; + } + + virtual void fill( unsigned time, mem_access_sector_mask_t sector_mask) + { + unsigned sidx = get_sector_index(sector_mask); + + // if(!m_ignore_on_fill_status[sidx]) + // assert( m_status[sidx] == RESERVED ); + + m_status[sidx] = m_set_modified_on_fill[sidx]? MODIFIED : VALID; + + m_sector_fill_time[sidx]=time; + m_line_fill_time=time; + } + virtual bool is_invalid_line() { + //all the sectors should be invalid + for(unsigned i =0; i< SECTOR_CHUNCK_SIZE; ++i) { + if (m_status[i] != INVALID) + return false; + } + return true; + } + virtual bool is_valid_line() { return !(is_invalid_line()); } + virtual bool is_reserved_line() { + //if any of the sector is reserved, then the line is reserved + for(unsigned i =0; i< SECTOR_CHUNCK_SIZE; ++i) { + if (m_status[i] == RESERVED) + return true; + } + return false; + } + virtual bool is_modified_line() { + //if any of the sector is modified, then the line is modified + for(unsigned i =0; i< SECTOR_CHUNCK_SIZE; ++i) { + if (m_status[i] == MODIFIED) + return true; + } + return false; + } + + virtual enum cache_block_state get_status(mem_access_sector_mask_t sector_mask) + { + unsigned sidx = get_sector_index(sector_mask); + + return m_status[sidx]; + } + + virtual void set_status(enum cache_block_state status, mem_access_sector_mask_t sector_mask) + { + unsigned sidx = get_sector_index(sector_mask); + m_status[sidx] = status; + } + + virtual unsigned get_last_access_time() + { + return m_line_last_access_time; + } + + virtual void set_last_access_time(unsigned time, mem_access_sector_mask_t sector_mask) + { + unsigned sidx = get_sector_index(sector_mask); + + m_last_sector_access_time[sidx] = time; + m_line_last_access_time = time; + } + + virtual unsigned get_alloc_time() + { + return m_line_alloc_time; + } + + virtual void set_ignore_on_fill(bool m_ignore, mem_access_sector_mask_t sector_mask) + { + unsigned sidx = get_sector_index(sector_mask); + m_ignore_on_fill_status[sidx] = m_ignore; + } + + virtual void set_modified_on_fill(bool m_modified, mem_access_sector_mask_t sector_mask) + { + unsigned sidx = get_sector_index(sector_mask); + m_set_modified_on_fill[sidx] = m_modified; + } + + virtual void set_m_readable(bool readable, mem_access_sector_mask_t sector_mask) + { + unsigned sidx = get_sector_index(sector_mask); + m_readable[sidx] = readable; + } + + virtual bool is_readable(mem_access_sector_mask_t sector_mask) { + unsigned sidx = get_sector_index(sector_mask); + return m_readable[sidx]; + } + + virtual unsigned get_modified_size() + { + unsigned modified=0; + for(unsigned i =0; i< SECTOR_CHUNCK_SIZE; ++i) { + if (m_status[i] == MODIFIED) + modified++; + } + return modified * SECTOR_SIZE; + } + + virtual void print_status() { + printf("m_block_addr is %llu, status = %u %u %u %u\n", m_block_addr, m_status[0], m_status[1], m_status[2], m_status[3]); + } + + +private: + unsigned m_sector_alloc_time[SECTOR_CHUNCK_SIZE]; + unsigned m_last_sector_access_time[SECTOR_CHUNCK_SIZE]; + unsigned m_sector_fill_time[SECTOR_CHUNCK_SIZE]; + unsigned m_line_alloc_time; + unsigned m_line_last_access_time; + unsigned m_line_fill_time; + cache_block_state m_status[SECTOR_CHUNCK_SIZE]; + bool m_ignore_on_fill_status[SECTOR_CHUNCK_SIZE]; + bool m_set_modified_on_fill[SECTOR_CHUNCK_SIZE]; + bool m_readable[SECTOR_CHUNCK_SIZE]; + + unsigned get_sector_index(mem_access_sector_mask_t sector_mask) + { + assert(sector_mask.count() == 1); + for(unsigned i =0; i< SECTOR_CHUNCK_SIZE; ++i) { + if(sector_mask.to_ulong() & (1< line_table; + line_table pending_lines; }; class mshr_table { public: - mshr_table( unsigned num_entries, unsigned max_merged ) + mshr_table( unsigned num_entries, unsigned max_merged) : m_num_entries(num_entries), m_max_merged(max_merged) #if (tr1_hash_map_ismap == 0) @@ -414,6 +879,8 @@ public: /// Returns next ready access mem_fetch *next_access(); void display( FILE *fp ) const; + // Returns true if there is a pending read after write + bool is_read_after_write_pending(new_addr_type block_addr); void check_mshr_parameters( unsigned num_entries, unsigned max_merged ) { @@ -433,7 +900,9 @@ private: mshr_entry() : m_has_atomic(false) { } }; typedef tr1_hash_map table; + typedef tr1_hash_map line_table; table m_data; + line_table pending_lines; // it may take several cycles to process the merged requests bool m_current_response_ready; @@ -510,12 +979,14 @@ public: cache_stats(); void clear(); void inc_stats(int access_type, int access_outcome); + void inc_fail_stats(int access_type, int fail_outcome); enum cache_request_status select_stats_status(enum cache_request_status probe, enum cache_request_status access) const; - unsigned &operator()(int access_type, int access_outcome); - unsigned operator()(int access_type, int access_outcome) const; + unsigned &operator()(int access_type, int access_outcome, bool fail_outcome); + unsigned operator()(int access_type, int access_outcome, bool fail_outcome) const; cache_stats operator+(const cache_stats &cs); cache_stats &operator+=(const cache_stats &cs); void print_stats(FILE *fout, const char *cache_name = "Cache_stats") const; + void print_fail_stats(FILE *fout, const char *cache_name = "Cache_fail_stats") const; unsigned get_stats(enum mem_access_type *access_type, unsigned num_access_type, enum cache_request_status *access_status, unsigned num_access_status) const; void get_sub_stats(struct cache_sub_stats &css) const; @@ -523,8 +994,10 @@ public: void sample_cache_port_utility(bool data_port_busy, bool fill_port_busy); private: bool check_valid(int type, int status) const; + bool check_fail_valid(int type, int fail) const; std::vector< std::vector > m_stats; + std::vector< std::vector > m_fail_stats; unsigned long long m_cache_port_available_cycles; unsigned long long m_cache_data_port_busy_cycles; @@ -543,6 +1016,7 @@ public: bool was_write_sent( const std::list &events ); bool was_read_sent( const std::list &events ); +bool was_writeallocate_sent( const std::list &events ); /// Baseline cache /// Implements common functions for read_only_cache and data_cache @@ -552,7 +1026,7 @@ public: baseline_cache( const char *name, cache_config &config, int core_id, int type_id, mem_fetch_interface *memport, enum mem_fetch_status status ) : m_config(config), m_tag_array(new tag_array(config,core_id,type_id)), - m_mshrs(config.m_mshr_entries,config.m_mshr_max_merge), + m_mshrs(config.m_mshr_entries,config.m_mshr_max_merge), m_bandwidth_management(config) { init( name, config, memport, status ); @@ -564,7 +1038,7 @@ public: enum mem_fetch_status status ) { m_name = name; - assert(config.m_mshr_type == ASSOC); + assert(config.m_mshr_type == ASSOC || config.m_mshr_type == SECTOR_ASSOC); m_memport=memport; m_miss_queue_status = status; } @@ -594,6 +1068,7 @@ public: mem_fetch *next_access(){return m_mshrs.next_access();} // flash invalidate all entries in cache void flush(){m_tag_array->flush();} + void invalidate(){m_tag_array->invalidate();} void print(FILE *fp, unsigned &accesses, unsigned &misses) const; void display_state( FILE *fp ) const; @@ -612,6 +1087,15 @@ public: bool data_port_free() const { return m_bandwidth_management.data_port_free(); } bool fill_port_free() const { return m_bandwidth_management.fill_port_free(); } + // This is a gapping hole we are poking in the system to quickly handle + // filling the cache on cudamemcopies. We don't care about anything other than + // L2 state after the memcopy - so just force the tag array to act as though + // something is read or written without doing anything else. + void force_tag_access( new_addr_type addr, unsigned time, mem_access_sector_mask_t mask ) + { + m_tag_array->fill( addr, time, mask ); + } + protected: // Constructor that can be used by derived classes with custom tag arrays baseline_cache( const char *name, @@ -633,24 +1117,31 @@ protected: std::string m_name; cache_config &m_config; tag_array* m_tag_array; - mshr_table m_mshrs; + mshr_table m_mshrs; std::list m_miss_queue; enum mem_fetch_status m_miss_queue_status; mem_fetch_interface *m_memport; struct extra_mf_fields { extra_mf_fields() { m_valid = false;} - extra_mf_fields( new_addr_type a, unsigned i, unsigned d ) + extra_mf_fields( new_addr_type a, new_addr_type ad, unsigned i, unsigned d, const cache_config& m_config) { m_valid = true; m_block_addr = a; + m_addr = ad; m_cache_index = i; m_data_size = d; + pending_read = m_config.m_mshr_type == SECTOR_ASSOC? m_config.m_line_sz/SECTOR_SIZE : 0; + } bool m_valid; new_addr_type m_block_addr; + new_addr_type m_addr; unsigned m_cache_index; unsigned m_data_size; + //this variable is used when a load request generates multiple load transactions + //For example, a read request from non-sector L1 request sends a request to sector L2 + unsigned pending_read; }; typedef std::map extra_mf_fields_lookup; @@ -668,7 +1159,7 @@ protected: unsigned time, bool &do_miss, std::list &events, bool read_only, bool wa); /// Read miss handler. Check MSHR hit or MSHR available void send_read_request(new_addr_type addr, new_addr_type block_addr, unsigned cache_index, mem_fetch *mf, - unsigned time, bool &do_miss, bool &wb, cache_block_t &evicted, std::list &events, bool read_only, bool wa); + unsigned time, bool &do_miss, bool &wb, evicted_block_info &evicted, std::list &events, bool read_only, bool wa); /// Sub-class containing all metadata for port bandwidth management class bandwidth_management @@ -760,8 +1251,10 @@ public: // Set write miss function switch(m_config.m_write_alloc_policy){ - case WRITE_ALLOCATE: m_wr_miss = &data_cache::wr_miss_wa; break; case NO_WRITE_ALLOCATE: m_wr_miss = &data_cache::wr_miss_no_wa; break; + case WRITE_ALLOCATE: m_wr_miss = &data_cache::wr_miss_wa_naive; break; + case FETCH_ON_WRITE: m_wr_miss = &data_cache::wr_miss_wa_fetch_on_write; break; + case LAZY_FETCH_ON_READ: m_wr_miss = &data_cache::wr_miss_wa_lazy_fetch_on_read; break; default: assert(0 && "Error: Must set valid cache write miss policy\n"); break; // Need to set a write miss function @@ -870,12 +1363,33 @@ protected: /// Sends read request, and possible write-back request, // to lower level memory for a write miss with write-allocate enum cache_request_status - wr_miss_wa( new_addr_type addr, - unsigned cache_index, - mem_fetch *mf, - unsigned time, - std::list &events, - enum cache_request_status status ); // write-allocate + wr_miss_wa_naive( new_addr_type addr, + unsigned cache_index, + mem_fetch *mf, + unsigned time, + std::list &events, + enum cache_request_status status ); // write-allocate-send-write-and-read-request + enum cache_request_status + wr_miss_wa_fetch_on_write( new_addr_type addr, + unsigned cache_index, + mem_fetch *mf, + unsigned time, + std::list &events, + enum cache_request_status status ); // write-allocate with fetch-on-every-write + enum cache_request_status + wr_miss_wa_lazy_fetch_on_read( new_addr_type addr, + unsigned cache_index, + mem_fetch *mf, + unsigned time, + std::list &events, + enum cache_request_status status ); // write-allocate with read-fetch-only + enum cache_request_status + wr_miss_wa_write_validate( new_addr_type addr, + unsigned cache_index, + mem_fetch *mf, + unsigned time, + std::list &events, + enum cache_request_status status ); // write-allocate that writes with no read fetch enum cache_request_status wr_miss_no_wa( new_addr_type addr, unsigned cache_index, @@ -991,7 +1505,7 @@ public: m_result_fifo(config.m_result_fifo_entries) { m_name = name; - assert(config.m_mshr_type == TEX_FIFO); + assert(config.m_mshr_type == TEX_FIFO || config.m_mshr_type == SECTOR_TEX_FIFO ); assert(config.m_write_policy == READ_ONLY); assert(config.m_alloc_policy == ON_MISS); m_memport=memport; @@ -1144,13 +1658,15 @@ private: struct extra_mf_fields { extra_mf_fields() { m_valid = false;} - extra_mf_fields( unsigned i ) + extra_mf_fields( unsigned i, const cache_config &m_config ) { m_valid = true; m_rob_index = i; + pending_read = m_config.m_mshr_type == SECTOR_TEX_FIFO? m_config.m_line_sz/SECTOR_SIZE : 0; } bool m_valid; unsigned m_rob_index; + unsigned pending_read; }; cache_stats m_stats; diff --git a/src/gpgpu-sim/gpu-sim.cc b/src/gpgpu-sim/gpu-sim.cc index 63ba759..a8be4d2 100644 --- a/src/gpgpu-sim/gpu-sim.cc +++ b/src/gpgpu-sim/gpu-sim.cc @@ -150,6 +150,8 @@ void power_config::reg_options(class OptionParser * opp) void memory_config::reg_options(class OptionParser * opp) { + option_parser_register(opp, "-perf_sim_memcpy", OPT_BOOL, &m_perf_sim_memcpy, + "Fill the L2 cache on memcpy", "1"); option_parser_register(opp, "-gpgpu_dram_scheduler", OPT_INT32, &scheduler_type, "0 = fifo, 1 = FR-FCFS (defaul)", "1"); option_parser_register(opp, "-gpgpu_dram_partition_queues", OPT_CSTR, &gpgpu_L2_queue_config, @@ -202,7 +204,27 @@ void memory_config::reg_options(class OptionParser * opp) option_parser_register(opp, "-dram_latency", OPT_UINT32, &dram_latency, "DRAM latency (default 30)", "30"); - + option_parser_register(opp, "-dual_bus_interface", OPT_UINT32, &dual_bus_interface, + "dual_bus_interface (default = 0) ", + "0"); + option_parser_register(opp, "-dram_bnk_indexing_policy", OPT_UINT32, &dram_bnk_indexing_policy, + "dram_bnk_indexing_policy (0 = normal indexing, 1 = Xoring with the higher bits) (Default = 0)", + "0"); + option_parser_register(opp, "-dram_bnkgrp_indexing_policy", OPT_UINT32, &dram_bnkgrp_indexing_policy, + "dram_bnkgrp_indexing_policy (0 = take higher bits, 1 = take lower bits) (Default = 0)", + "0"); + option_parser_register(opp, "-Seperate_Write_Queue_Enable", OPT_BOOL, &seperate_write_queue_enabled, + "Seperate_Write_Queue_Enable", + "0"); + option_parser_register(opp, "-Write_Queue_Size", OPT_CSTR, &write_queue_size_opt, + "Write_Queue_Size", + "32:28:16"); + option_parser_register(opp, "-Elimnate_rw_turnaround", OPT_BOOL, &elimnate_rw_turnaround, + "elimnate_rw_turnaround i.e set tWTR and tRTW = 0", + "0"); + option_parser_register(opp, "-icnt_flit_size", OPT_UINT32, &icnt_flit_size, + "icnt_flit_size", + "32"); m_address_mapping.addrdec_setoption(opp); } @@ -229,6 +251,12 @@ void shader_core_config::reg_options(class OptionParser * opp) "per-shader L1 data cache config " " {::,:::,::, | none}", "none" ); + option_parser_register(opp, "-l1_latency", OPT_UINT32, &m_L1D_config.l1_latency, + "L1 Hit Latency", + "0"); + option_parser_register(opp, "-smem_latency", OPT_UINT32, &smem_latency, + "smem Latency", + "3"); option_parser_register(opp, "-gpgpu_cache:dl1PrefL1", OPT_CSTR, &m_L1D_config.m_config_stringPrefL1, "per-shader L1 data cache config " " {::,:::,::, | none}", @@ -256,6 +284,9 @@ void shader_core_config::reg_options(class OptionParser * opp) option_parser_register(opp, "-gpgpu_shader_registers", OPT_UINT32, &gpgpu_shader_registers, "Number of registers per shader core. Limits number of concurrent CTAs. (default 8192)", "8192"); + option_parser_register(opp, "-gpgpu_ignore_resources_limitation", OPT_BOOL, &gpgpu_ignore_resources_limitation, + "gpgpu_ignore_resources_limitation (default 0)", + "0"); option_parser_register(opp, "-gpgpu_shader_cta", OPT_UINT32, &max_cta_per_core, "Maximum number of concurrent CTAs in shader (default 8)", "8"); @@ -277,6 +308,9 @@ void shader_core_config::reg_options(class OptionParser * opp) option_parser_register(opp, "-gpgpu_shmem_size", OPT_UINT32, &gpgpu_shmem_size, "Size of shared memory per shader core (default 16kB)", "16384"); + option_parser_register(opp, "-adpative_volta_cache_config", OPT_BOOL, &adpative_volta_cache_config, + "adpative_volta_cache_config", + "0"); option_parser_register(opp, "-gpgpu_shmem_size", OPT_UINT32, &gpgpu_shmem_sizeDefault, "Size of shared memory per shader core (default 16kB)", "16384"); @@ -295,6 +329,9 @@ void shader_core_config::reg_options(class OptionParser * opp) option_parser_register(opp, "-gpgpu_shmem_warp_parts", OPT_INT32, &mem_warp_parts, "Number of portions a warp is divided into for shared memory bank conflict check ", "2"); + option_parser_register(opp, "-gpgpu_shmem_warp_parts", OPT_INT32, &mem_warp_parts, + "Number of portions a warp is divided into for shared memory bank conflict check ", + "2"); option_parser_register(opp, "-gpgpu_warpdistro_shader", OPT_INT32, &gpgpu_warpdistro_shader, "Specify which shader core to collect the warp size distribution from", "-1"); @@ -303,7 +340,7 @@ void shader_core_config::reg_options(class OptionParser * opp) "0"); option_parser_register(opp, "-gpgpu_local_mem_map", OPT_BOOL, &gpgpu_local_mem_map, "Mapping from local memory space address to simulated GPU physical address space (default = enabled)", - "1"); + "1"); option_parser_register(opp, "-gpgpu_num_reg_banks", OPT_INT32, &gpgpu_num_reg_banks, "Number of register banks (default = 8)", "8"); @@ -313,6 +350,9 @@ void shader_core_config::reg_options(class OptionParser * opp) option_parser_register(opp, "-gpgpu_operand_collector_num_units_sp", OPT_INT32, &gpgpu_operand_collector_num_units_sp, "number of collector units (default = 4)", "4"); + option_parser_register(opp, "-gpgpu_operand_collector_num_units_dp", OPT_INT32, &gpgpu_operand_collector_num_units_dp, + "number of collector units (default = 0)", + "0"); option_parser_register(opp, "-gpgpu_operand_collector_num_units_sfu", OPT_INT32, &gpgpu_operand_collector_num_units_sfu, "number of collector units (default = 4)", "4"); @@ -328,6 +368,9 @@ void shader_core_config::reg_options(class OptionParser * opp) option_parser_register(opp, "-gpgpu_operand_collector_num_in_ports_sp", OPT_INT32, &gpgpu_operand_collector_num_in_ports_sp, "number of collector unit in ports (default = 1)", "1"); + option_parser_register(opp, "-gpgpu_operand_collector_num_in_ports_dp", OPT_INT32, &gpgpu_operand_collector_num_in_ports_dp, + "number of collector unit in ports (default = 0)", + "0"); option_parser_register(opp, "-gpgpu_operand_collector_num_in_ports_sfu", OPT_INT32, &gpgpu_operand_collector_num_in_ports_sfu, "number of collector unit in ports (default = 1)", "1"); @@ -343,6 +386,9 @@ void shader_core_config::reg_options(class OptionParser * opp) option_parser_register(opp, "-gpgpu_operand_collector_num_out_ports_sp", OPT_INT32, &gpgpu_operand_collector_num_out_ports_sp, "number of collector unit in ports (default = 1)", "1"); + option_parser_register(opp, "-gpgpu_operand_collector_num_out_ports_dp", OPT_INT32, &gpgpu_operand_collector_num_out_ports_dp, + "number of collector unit in ports (default = 0)", + "0"); option_parser_register(opp, "-gpgpu_operand_collector_num_out_ports_sfu", OPT_INT32, &gpgpu_operand_collector_num_out_ports_sfu, "number of collector unit in ports (default = 1)", "1"); @@ -356,27 +402,33 @@ void shader_core_config::reg_options(class OptionParser * opp) "number of collector unit in ports (default = 0)", "0"); option_parser_register(opp, "-gpgpu_coalesce_arch", OPT_INT32, &gpgpu_coalesce_arch, - "Coalescing arch (default = 13, anything else is off for now)", + "Coalescing arch (GT200 = 13, Fermi = 20)", "13"); option_parser_register(opp, "-gpgpu_num_sched_per_core", OPT_INT32, &gpgpu_num_sched_per_core, "Number of warp schedulers per core", "1"); option_parser_register(opp, "-gpgpu_max_insn_issue_per_warp", OPT_INT32, &gpgpu_max_insn_issue_per_warp, - "Max number of instructions that can be issued per warp in one cycle by scheduler", - "2"); + "Max number of instructions that can be issued per warp in one cycle by scheduler (either 1 or 2)", + "2"); + option_parser_register(opp, "-gpgpu_dual_issue_diff_exec_units", OPT_BOOL, &gpgpu_dual_issue_diff_exec_units, + "should dual issue use two different execution unit resources (Default = 1)", + "1"); option_parser_register(opp, "-gpgpu_simt_core_sim_order", OPT_INT32, &simt_core_sim_order, "Select the simulation order of cores in a cluster (0=Fix, 1=Round-Robin)", "1"); option_parser_register(opp, "-gpgpu_pipeline_widths", OPT_CSTR, &pipeline_widths_string, "Pipeline widths " - "ID_OC_SP,ID_OC_SFU,ID_OC_TENSOR_CORE,ID_OC_MEM,OC_EX_SP,OC_EX_SFU,OC_EX_TENSOR_CORE,OC_EX_MEM,EX_WB", - "1,1,1,1,1,1,1,1,1,1" ); + "ID_OC_SP,ID_OC_DP,ID_OC_SFU,ID_OC_MEM,OC_EX_SP,OC_EX_DP,OC_EX_SFU,OC_EX_MEM,EX_WB,ID_OC_TENSOR_CORE,OC_EX_TENSOR_CORE", + "1,1,1,1,1,1,1,1,1,1,1" ); option_parser_register(opp, "-gpgpu_tensor_core_avail", OPT_INT32, &gpgpu_tensor_core_avail, "Tensor Core Available (default=0)", "0"); option_parser_register(opp, "-gpgpu_num_sp_units", OPT_INT32, &gpgpu_num_sp_units, "Number of SP units (default=1)", "1"); + option_parser_register(opp, "-gpgpu_num_dp_units", OPT_INT32, &gpgpu_num_dp_units, + "Number of DP units (default=0)", + "0"); option_parser_register(opp, "-gpgpu_num_sfu_units", OPT_INT32, &gpgpu_num_sfu_units, "Number of SF units (default=1)", "1"); @@ -425,7 +477,6 @@ void gpgpu_sim_config::reg_options(option_parser_t opp) option_parser_register(opp, "-gpgpu_flush_l2_cache", OPT_BOOL, &gpgpu_flush_l2_cache, "Flush L2 cache at the end of each kernel call", "0"); - option_parser_register(opp, "-gpgpu_deadlock_detect", OPT_BOOL, &gpu_deadlock_detect, "Stop the simulation at deadlock (1=on (default), 0=off)", "1"); @@ -669,7 +720,7 @@ gpgpu_sim::gpgpu_sim( const gpgpu_sim_config &config ) m_running_kernels.resize( config.max_concurrent_kernel, NULL ); m_last_issued_kernel = 0; - m_last_cluster_issue = 0; + m_last_cluster_issue = m_shader_config->n_simt_clusters-1; // this causes first launch to use simt cluster 0 *average_pipeline_duty_cycle=0; *active_sms=0; @@ -813,6 +864,7 @@ void gpgpu_sim::update_stats() { partiton_replys_in_parallel_total += partiton_replys_in_parallel; partiton_reqs_in_parallel_util_total += partiton_reqs_in_parallel_util; gpu_tot_sim_cycle_parition_util += gpu_sim_cycle_parition_util ; + gpu_tot_occupancy += gpu_occupancy; gpu_sim_cycle = 0; partiton_reqs_in_parallel = 0; @@ -821,6 +873,7 @@ void gpgpu_sim::update_stats() { gpu_sim_cycle_parition_util = 0; gpu_sim_insn = 0; m_total_cta_launched = 0; + gpu_occupancy = occupancy_stats(); } void gpgpu_sim::print_stats() @@ -994,6 +1047,9 @@ void gpgpu_sim::gpu_print_stat() printf("gpu_tot_sim_insn = %lld\n", gpu_tot_sim_insn+gpu_sim_insn); 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); + printf("gpu_occupancy = %.4f\% \n", gpu_occupancy.get_occ_fraction() * 100); + printf("gpu_tot_occupancy = %.4f\% \n", (gpu_occupancy + gpu_tot_occupancy).get_occ_fraction() * 100); + extern unsigned long long g_max_total_param_size; fprintf(statfout, "max_total_param_size = %llu\n", g_max_total_param_size); @@ -1032,6 +1088,8 @@ void gpgpu_sim::gpu_print_stat() } printf("\nTotal_core_cache_stats:\n"); core_cache_stats.print_stats(stdout, "Total_core_cache_stats_breakdown"); + printf("\nTotal_core_cache_fail_stats:\n"); + core_cache_stats.print_fail_stats(stdout, "Total_core_cache_fail_stats_breakdown"); shader_print_scheduler_stat( stdout, false ); m_shader_stats->print(stdout); @@ -1076,6 +1134,8 @@ void gpgpu_sim::gpu_print_stat() printf("L2_total_cache_reservation_fails = %u\n", total_l2_css.res_fails); printf("L2_total_cache_breakdown:\n"); l2_stats.print_stats(stdout, "L2_cache_stats_breakdown"); + printf("L2_total_cache_reservation_fail_breakdown:\n"); + l2_stats.print_fail_stats(stdout, "L2_cache_stats_fail_breakdown"); total_l2_css.print_port_stats(stdout, "L2_cache"); } } @@ -1429,7 +1489,7 @@ void gpgpu_sim::cycle() if (mf) { unsigned response_size = mf->get_is_write()?mf->get_ctrl_size():mf->size(); if ( ::icnt_has_buffer( m_shader_config->mem2device(i), response_size ) ) { - if (!mf->get_is_write()) + //if (!mf->get_is_write()) mf->set_return_timestamp(gpu_sim_cycle+gpu_tot_sim_cycle); mf->set_status(IN_ICNT_TO_SHADER,gpu_sim_cycle+gpu_tot_sim_cycle); ::icnt_push( m_shader_config->mem2device(i), mf->get_tpc(), mf, response_size ); @@ -1462,12 +1522,14 @@ void gpgpu_sim::cycle() for (unsigned i=0;im_n_mem_sub_partition;i++) { //move memory request from interconnect into memory partition (if not backed up) //Note:This needs to be called in DRAM clock domain if there is no L2 cache in the system - if ( m_memory_sub_partition[i]->full() ) { + //In the worst case, we may need to push SECTOR_CHUNCK_SIZE requests, so ensure you have enough buffer for them + if ( m_memory_sub_partition[i]->full(SECTOR_CHUNCK_SIZE) ) { gpu_stall_dramfull++; } else { mem_fetch* mf = (mem_fetch*) icnt_pop( m_shader_config->mem2device(i) ); m_memory_sub_partition[i]->push( mf, gpu_sim_cycle + gpu_tot_sim_cycle ); - partiton_reqs_in_parallel_per_cycle++; + if(mf) + partiton_reqs_in_parallel_per_cycle++; } m_memory_sub_partition[i]->cache_cycle(gpu_sim_cycle+gpu_tot_sim_cycle); m_memory_sub_partition[i]->accumulate_L2cache_stats(m_power_stats->pwr_mem_stat->l2_cache_stats[CURRENT_STAT_IDX]); @@ -1494,6 +1556,8 @@ void gpgpu_sim::cycle() // Update core icnt/cache stats for GPUWattch m_cluster[i]->get_icnt_stats(m_power_stats->pwr_mem_stat->n_simt_to_mem[CURRENT_STAT_IDX][i], m_power_stats->pwr_mem_stat->n_mem_to_simt[CURRENT_STAT_IDX][i]); m_cluster[i]->get_cache_stats(m_power_stats->pwr_mem_stat->core_cache_stats[CURRENT_STAT_IDX]); + m_cluster[i]->get_current_occupancy(gpu_occupancy.aggregate_warp_slot_filled, gpu_occupancy.aggregate_theoretical_warp_slots); + } float temp=0; for (unsigned i=0;inum_shader();i++){ @@ -1521,12 +1585,12 @@ void gpgpu_sim::cycle() issue_block2core(); - // Depending on configuration, flush the caches once all of threads are completed. + // Depending on configuration, invalidate the caches once all of threads are completed. int all_threads_complete = 1; if (m_config.gpgpu_flush_l1_cache) { for (unsigned i=0;in_simt_clusters;i++) { if (m_cluster[i]->get_not_completed() == 0) - m_cluster[i]->cache_flush(); + m_cluster[i]->cache_invalidate(); else all_threads_complete = 0 ; } @@ -1548,7 +1612,7 @@ void gpgpu_sim::cycle() int dlc = 0; for (unsigned i=0;im_n_mem;i++) { dlc = m_memory_sub_partition[i]->flushL2(); - assert (dlc == 0); // need to model actual writes to DRAM here + assert (dlc == 0); // TODO: need to model actual writes to DRAM here printf("Dirty lines flushed from L2 %d is %d\n", i, dlc ); } } @@ -1560,15 +1624,20 @@ void gpgpu_sim::cycle() time_t curr_time; time(&curr_time); unsigned long long elapsed_time = MAX(curr_time - g_simulation_starttime, 1); - if ( (elapsed_time - last_liveness_message_time) >= m_config.liveness_message_freq ) { + if ( (elapsed_time - last_liveness_message_time) >= m_config.liveness_message_freq && DTRACE(LIVENESS) ) { days = elapsed_time/(3600*24); hrs = elapsed_time/3600 - 24*days; minutes = elapsed_time/60 - 60*(hrs + 24*days); sec = elapsed_time - 60*(minutes + 60*(hrs + 24*days)); - - DPRINTF(LIVENESS, "GPGPU-Sim uArch: cycles simulated: %lld inst.: %lld (ipc=%4.1f) sim_rate=%u (inst/sec) elapsed = %u:%u:%02u:%02u / %s", - gpu_tot_sim_cycle + gpu_sim_cycle, gpu_tot_sim_insn + gpu_sim_insn, + + unsigned long long active = 0, total = 0; + for (unsigned i=0;in_simt_clusters;i++) { + m_cluster[i]->get_current_occupancy(active, total); + } + DPRINTF(LIVENESS, "uArch: inst.: %lld (ipc=%4.1f, occ=%0.4f\% [%llu / %llu]) sim_rate=%u (inst/sec) elapsed = %u:%u:%02u:%02u / %s", + gpu_tot_sim_insn + gpu_sim_insn, (double)gpu_sim_insn/(double)gpu_sim_cycle, + float(active)/float(total) * 100, active, total, (unsigned)((gpu_tot_sim_insn+gpu_sim_insn) / elapsed_time), (unsigned)days,(unsigned)hrs,(unsigned)minutes,(unsigned)sec, ctime(&curr_time)); @@ -1620,6 +1689,24 @@ void shader_core_ctx::dump_warp_state( FILE *fout ) const m_warp[w].print(fout); } + +void gpgpu_sim::perf_memcpy_to_gpu( size_t dst_start_addr, size_t count ) +{ + if (m_memory_config->m_perf_sim_memcpy) { + assert (dst_start_addr % 32 == 0); + + for ( unsigned counter = 0; counter < count; counter += 32 ) { + const unsigned wr_addr = dst_start_addr + counter; + addrdec_t raw_addr; + mem_access_sector_mask_t mask; + mask.set(wr_addr % 128 / 32); + m_memory_config->m_address_mapping.addrdec_tlx( wr_addr, &raw_addr ); + const unsigned partition_id = raw_addr.sub_partition / m_memory_config->m_n_sub_partition_per_memory_channel; + m_memory_partition_unit[ partition_id ]->handle_memcpy_to_gpu( wr_addr, raw_addr.sub_partition, mask ); + } + } +} + void gpgpu_sim::dump_pipeline( int mask, int s, int m ) const { /* diff --git a/src/gpgpu-sim/gpu-sim.h b/src/gpgpu-sim/gpu-sim.h index 7d92c66..1bae1fa 100644 --- a/src/gpgpu-sim/gpu-sim.h +++ b/src/gpgpu-sim/gpu-sim.h @@ -198,8 +198,14 @@ struct memory_config { bk_tag_length = i-1; assert(nbkgrp>0 && "Number of bank groups cannot be zero"); tRCDWR = tRCD-(WL+1); + if(elimnate_rw_turnaround) + { + tRTW = 0; + tWTR = 0; + } else { tRTW = (CL+(BL/data_command_freq_ratio)+2-WL); - tWTR = (WL+(BL/data_command_freq_ratio)+tCDLR); + tWTR = (WL+(BL/data_command_freq_ratio)+tCDLR); + } tWTP = (WL+(BL/data_command_freq_ratio)+tWR); dram_atom_size = BL * busW * gpu_n_mem_per_ctrlr; // burst length x bus width x # chips per partition @@ -213,7 +219,9 @@ struct memory_config { m_L2_config.init(&m_address_mapping); m_valid = true; - icnt_flit_size = 32; // Default 32 + + sscanf(write_queue_size_opt,"%d:%d:%d", + &gpgpu_frfcfs_dram_write_queue_size,&write_high_watermark,&write_low_watermark); } void reg_options(class OptionParser * opp); @@ -264,12 +272,25 @@ struct memory_config { unsigned nbk; + bool elimnate_rw_turnaround; + unsigned data_command_freq_ratio; // frequency ratio between DRAM data bus and command bus (2 for GDDR3, 4 for GDDR5) unsigned dram_atom_size; // number of bytes transferred per read or write command linear_to_raw_address_translation m_address_mapping; unsigned icnt_flit_size; + + unsigned dram_bnk_indexing_policy; + unsigned dram_bnkgrp_indexing_policy; + bool dual_bus_interface; + + bool seperate_write_queue_enabled; + char *write_queue_size_opt; + unsigned gpgpu_frfcfs_dram_write_queue_size; + unsigned write_high_watermark; + unsigned write_low_watermark; + bool m_perf_sim_memcpy; }; // global counters and flags (please try not to add to this list!!!) @@ -362,6 +383,32 @@ private: friend class gpgpu_sim; }; +struct occupancy_stats { + occupancy_stats() : aggregate_warp_slot_filled(0), aggregate_theoretical_warp_slots(0){} + occupancy_stats( unsigned long long wsf, unsigned long long tws ) + : aggregate_warp_slot_filled(wsf), aggregate_theoretical_warp_slots(tws){} + + unsigned long long aggregate_warp_slot_filled; + unsigned long long aggregate_theoretical_warp_slots; + + float get_occ_fraction() const { + return float(aggregate_warp_slot_filled) / float(aggregate_theoretical_warp_slots); + } + + occupancy_stats& operator+=(const occupancy_stats& rhs) { + aggregate_warp_slot_filled += rhs.aggregate_warp_slot_filled; + aggregate_theoretical_warp_slots += rhs.aggregate_theoretical_warp_slots; + return *this; + } + + occupancy_stats operator+(const occupancy_stats& rhs) const{ + return occupancy_stats( aggregate_warp_slot_filled + rhs.aggregate_warp_slot_filled, + aggregate_theoretical_warp_slots + rhs.aggregate_theoretical_warp_slots + ); + } +}; + + class gpgpu_sim : public gpgpu_t { public: gpgpu_sim( const gpgpu_sim_config &config ); @@ -405,6 +452,8 @@ public: void gpu_print_stat(); void dump_pipeline( int mask, int s, int m ) const; + void perf_memcpy_to_gpu( size_t dst_start_addr, size_t count ); + //The next three functions added to be used by the functional simulation function //! Get shader core configuration @@ -498,6 +547,9 @@ public: unsigned long long gpu_tot_sim_insn; unsigned long long gpu_sim_insn_last_update; unsigned gpu_sim_insn_last_update_sid; + occupancy_stats gpu_occupancy; + occupancy_stats gpu_tot_occupancy; + FuncCache get_cache_config(std::string kernel_name); void set_cache_config(std::string kernel_name, FuncCache cacheConfig ); @@ -526,4 +578,5 @@ public: } }; + #endif diff --git a/src/gpgpu-sim/l2cache.cc b/src/gpgpu-sim/l2cache.cc index c5fc44e..25da107 100644 --- a/src/gpgpu-sim/l2cache.cc +++ b/src/gpgpu-sim/l2cache.cc @@ -74,6 +74,15 @@ memory_partition_unit::memory_partition_unit( unsigned partition_id, } } +void memory_partition_unit::handle_memcpy_to_gpu( size_t addr, unsigned global_subpart_id, mem_access_sector_mask_t mask ) +{ + unsigned p = global_sub_partition_id_to_local_id(global_subpart_id); + std::string mystring = + mask.to_string(); + MEMPART_DPRINTF("Copy Engine Request Received For Address=%llx, local_subpart=%u, global_subpart=%u, sector_mask=%s \n", addr, p, global_subpart_id, mystring.c_str()); + m_sub_partition[p]->force_l2_tag_update(addr,gpu_sim_cycle+gpu_tot_sim_cycle, mask); +} + memory_partition_unit::~memory_partition_unit() { delete m_dram; @@ -93,7 +102,9 @@ memory_partition_unit::arbitration_metadata::arbitration_metadata(const struct m m_private_credit_limit = 1; m_shared_credit_limit = config->gpgpu_frfcfs_dram_sched_queue_size + config->gpgpu_dram_return_queue_size - - (config->m_n_sub_partition_per_memory_channel - 1); + - (config->m_n_sub_partition_per_memory_channel - 1); + if(config->seperate_write_queue_enabled ) + m_shared_credit_limit += config->gpgpu_frfcfs_dram_write_queue_size; if (config->gpgpu_frfcfs_dram_sched_queue_size == 0 or config->gpgpu_dram_return_queue_size == 0) { @@ -220,7 +231,8 @@ void memory_partition_unit::dram_cycle() m_dram->cycle(); m_dram->dram_log(SAMPLELOG); - if( !m_dram->full() ) { + // mem_fetch *mf = m_sub_partition[spid]->L2_dram_queue_top(); + //if( !m_dram->full(mf->is_write()) ) { // L2->DRAM queue to DRAM latency queue // Arbitrate among multiple L2 subpartitions int last_issued_partition = m_arbitration_metadata.last_borrower(); @@ -228,6 +240,9 @@ void memory_partition_unit::dram_cycle() int spid = (p + last_issued_partition + 1) % m_config->m_n_sub_partition_per_memory_channel; if (!m_sub_partition[spid]->L2_dram_queue_empty() && can_issue_to_dram(spid)) { mem_fetch *mf = m_sub_partition[spid]->L2_dram_queue_top(); + if(m_dram->full(mf->is_write()) ) + break; + m_sub_partition[spid]->L2_dram_queue_pop(); MEMPART_DPRINTF("Issue mem_fetch request %p from sub partition %d to dram\n", mf, spid); dram_delay_t d; @@ -239,12 +254,13 @@ void memory_partition_unit::dram_cycle() break; // the DRAM should only accept one request per cycle } } - } + //} // DRAM latency queue - if( !m_dram_latency_queue.empty() && ( (gpu_sim_cycle+gpu_tot_sim_cycle) >= m_dram_latency_queue.front().ready_cycle ) && !m_dram->full() ) { - mem_fetch* mf = m_dram_latency_queue.front().req; - m_dram_latency_queue.pop_front(); + + if( !m_dram_latency_queue.empty() && ( (gpu_sim_cycle+gpu_tot_sim_cycle) >= m_dram_latency_queue.front().ready_cycle ) && !m_dram->full(m_dram_latency_queue.front().req->is_write()) ) { + mem_fetch* mf = m_dram_latency_queue.front().req; + m_dram_latency_queue.pop_front(); m_dram->push(mf); } } @@ -299,6 +315,7 @@ memory_sub_partition::memory_sub_partition( unsigned sub_partition_id, m_id = sub_partition_id; m_config=config; m_stats=stats; + m_memcpy_cycle_offset = 0; assert(m_id < m_config->m_n_mem_sub_partition); @@ -343,6 +360,14 @@ void memory_sub_partition::cache_cycle( unsigned cycle ) mf->set_status(IN_PARTITION_L2_TO_ICNT_QUEUE,gpu_sim_cycle+gpu_tot_sim_cycle); m_L2_icnt_queue->push(mf); }else{ + if(m_config->m_L2_config.m_write_alloc_policy == FETCH_ON_WRITE) + { + mem_fetch* original_wr_mf = mf->get_original_wr_mf(); + assert(original_wr_mf); + original_wr_mf->set_reply(); + original_wr_mf->set_status(IN_PARTITION_L2_TO_ICNT_QUEUE,gpu_sim_cycle+gpu_tot_sim_cycle); + m_L2_icnt_queue->push(original_wr_mf); + } m_request_tracker.erase(mf); delete mf; } @@ -355,10 +380,11 @@ void memory_sub_partition::cache_cycle( unsigned cycle ) if ( !m_config->m_L2_config.disabled() && m_L2cache->waiting_for_fill(mf) ) { if (m_L2cache->fill_port_free()) { mf->set_status(IN_PARTITION_L2_FILL_QUEUE,gpu_sim_cycle+gpu_tot_sim_cycle); - m_L2cache->fill(mf,gpu_sim_cycle+gpu_tot_sim_cycle); + m_L2cache->fill(mf,gpu_sim_cycle+gpu_tot_sim_cycle+m_memcpy_cycle_offset); m_dram_L2_queue->pop(); } } else if ( !m_L2_icnt_queue->full() ) { + if(mf->is_write() && mf->get_type() == WRITE_ACK) mf->set_status(IN_PARTITION_L2_TO_ICNT_QUEUE,gpu_sim_cycle+gpu_tot_sim_cycle); m_L2_icnt_queue->push(mf); m_dram_L2_queue->pop(); @@ -380,9 +406,10 @@ void memory_sub_partition::cache_cycle( unsigned cycle ) bool port_free = m_L2cache->data_port_free(); if ( !output_full && port_free ) { std::list events; - enum cache_request_status status = m_L2cache->access(mf->get_addr(),mf,gpu_sim_cycle+gpu_tot_sim_cycle,events); + enum cache_request_status status = m_L2cache->access(mf->get_addr(),mf,gpu_sim_cycle+gpu_tot_sim_cycle+m_memcpy_cycle_offset,events); bool write_sent = was_write_sent(events); bool read_sent = was_read_sent(events); + MEM_SUBPART_DPRINTF("Probing L2 cache Address=%llx, status=%u\n", mf->get_addr(), status); if ( status == HIT ) { if( !write_sent ) { @@ -402,6 +429,11 @@ void memory_sub_partition::cache_cycle( unsigned cycle ) m_icnt_L2_queue->pop(); } } else if ( status != RESERVATION_FAIL ) { + if(mf->is_write() && (m_config->m_L2_config.m_write_alloc_policy == FETCH_ON_WRITE || m_config->m_L2_config.m_write_alloc_policy == LAZY_FETCH_ON_READ) && !was_writeallocate_sent(events)) { + mf->set_reply(); + mf->set_status(IN_PARTITION_L2_TO_ICNT_QUEUE,gpu_sim_cycle+gpu_tot_sim_cycle); + m_L2_icnt_queue->push(mf); + } // L2 cache accepted request m_icnt_L2_queue->pop(); } else { @@ -432,6 +464,11 @@ bool memory_sub_partition::full() const return m_icnt_L2_queue->full(); } +bool memory_sub_partition::full(unsigned size) const +{ + return m_icnt_L2_queue->is_avilable_size(size); +} + bool memory_sub_partition::L2_dram_queue_empty() const { return m_L2_dram_queue->empty(); @@ -532,7 +569,15 @@ unsigned memory_sub_partition::flushL2() if (!m_config->m_L2_config.disabled()) { m_L2cache->flush(); } - return 0; // L2 is read only in this version + return 0; //TODO: write the flushed data to the main memory +} + +unsigned memory_sub_partition::invalidateL2() +{ + if (!m_config->m_L2_config.disabled()) { + m_L2cache->invalidate(); + } + return 0; } bool memory_sub_partition::busy() const @@ -540,21 +585,94 @@ bool memory_sub_partition::busy() const return !m_request_tracker.empty(); } -void memory_sub_partition::push( mem_fetch* req, unsigned long long cycle ) -{ - if (req) { - m_request_tracker.insert(req); - m_stats->memlatstat_icnt2mem_pop(req); - if( req->istexture() ) { - m_icnt_L2_queue->push(req); - req->set_status(IN_PARTITION_ICNT_TO_L2_QUEUE,gpu_sim_cycle+gpu_tot_sim_cycle); - } else { - rop_delay_t r; - r.req = req; - r.ready_cycle = cycle + m_config->rop_latency; - m_rop.push(r); - req->set_status(IN_PARTITION_ROP_DELAY,gpu_sim_cycle+gpu_tot_sim_cycle); - } +std::vector memory_sub_partition::breakdown_request_to_sector_requests(mem_fetch* mf) +{ + std::vector result; + + if(mf->get_data_size() == SECTOR_SIZE && mf->get_access_sector_mask().count() == 1) { + result.push_back(mf); + } else if (mf->get_data_size() == 128 || mf->get_data_size() == 64) { + //We only accept 32, 64 and 128 bytes reqs + unsigned start=0, end=0; + if(mf->get_data_size() == 128) { + start=0; end=3; + } else if (mf->get_data_size() == 64 && mf->get_access_sector_mask().to_string() == "1100") { + start=2; end=3; + } else if (mf->get_data_size() == 64 && mf->get_access_sector_mask().to_string() == "0011") { + start=0; end=1; + } else if (mf->get_data_size() == 64 && (mf->get_access_sector_mask().to_string() == "1111" || mf->get_access_sector_mask().to_string() == "0000")) { + if(mf->get_addr() % 128 == 0) { + start=0; end=1; + } else { + start=2; end=3; + } + } else + { + printf("Invalid sector received, address = 0x%06x, sector mask = %s, data size = %d", + mf->get_addr(), mf->get_access_sector_mask(), mf->get_data_size()); + assert(0 && "Undefined sector mask is received"); + } + + std::bitset byte_sector_mask; + byte_sector_mask.reset(); + for(unsigned k=start*SECTOR_SIZE; k< SECTOR_SIZE; ++k) + byte_sector_mask.set(k); + + for(unsigned j=start, i=0; j<= end ; ++j, ++i){ + + const mem_access_t *ma = new mem_access_t( mf->get_access_type(), + mf->get_addr() + SECTOR_SIZE*i, + SECTOR_SIZE, + mf->is_write(), + mf->get_access_warp_mask(), + mf->get_access_byte_mask() & byte_sector_mask, + std::bitset().set(j)); + + mem_fetch *n_mf = new mem_fetch( *ma, + NULL, + mf->get_ctrl_size(), + mf->get_wid(), + mf->get_sid(), + mf->get_tpc(), + mf->get_mem_config(), + mf); + + result.push_back(n_mf); + byte_sector_mask <<= SECTOR_SIZE; + } + } else { + printf("Invalid sector received, address = 0x%06x, sector mask = %d, byte mask = , data size = %d", + mf->get_addr(), mf->get_access_sector_mask().count(), mf->get_data_size()); + assert(0 && "Undefined data size is received"); + } + + return result; +} + +void memory_sub_partition::push( mem_fetch* m_req, unsigned long long cycle ) +{ + if (m_req) { + m_stats->memlatstat_icnt2mem_pop(m_req); + std::vector reqs; + if(m_config->m_L2_config.m_cache_type == SECTOR) + reqs = breakdown_request_to_sector_requests(m_req); + else + reqs.push_back(m_req); + + for(unsigned i=0; iistexture() ) { + m_icnt_L2_queue->push(req); + req->set_status(IN_PARTITION_ICNT_TO_L2_QUEUE,gpu_sim_cycle+gpu_tot_sim_cycle); + } else { + rop_delay_t r; + r.req = req; + r.ready_cycle = cycle + m_config->rop_latency; + m_rop.push(r); + req->set_status(IN_PARTITION_ROP_DELAY,gpu_sim_cycle+gpu_tot_sim_cycle); + } + } } } diff --git a/src/gpgpu-sim/l2cache.h b/src/gpgpu-sim/l2cache.h index 3df54b1..18c0a8b 100644 --- a/src/gpgpu-sim/l2cache.h +++ b/src/gpgpu-sim/l2cache.h @@ -72,6 +72,7 @@ public: void print_stat( FILE *fp ) { m_dram->print_stat(fp); } void visualize() const { m_dram->visualize(); } void print( FILE *fp ) const; + void handle_memcpy_to_gpu( size_t dst_start_addr, unsigned subpart_id, mem_access_sector_mask_t mask ); class memory_sub_partition * get_sub_partition(int sub_partition_id) { @@ -154,12 +155,14 @@ public: void cache_cycle( unsigned cycle ); bool full() const; + bool full(unsigned size) const; void push( class mem_fetch* mf, unsigned long long clock_cycle ); class mem_fetch* pop(); class mem_fetch* top(); void set_done( mem_fetch *mf ); unsigned flushL2(); + unsigned invalidateL2(); // interface to L2_dram_queue bool L2_dram_queue_empty() const; @@ -177,6 +180,12 @@ public: void accumulate_L2cache_stats(class cache_stats &l2_stats) const; void get_L2cache_sub_stats(struct cache_sub_stats &css) const; + void force_l2_tag_update(new_addr_type addr, unsigned time, mem_access_sector_mask_t mask) + { + m_L2cache->force_tag_access( addr, m_memcpy_cycle_offset + time, mask ); + m_memcpy_cycle_offset += 1; + } + private: // data unsigned m_id; //< the global sub partition ID @@ -207,6 +216,15 @@ private: std::set m_request_tracker; friend class L2interface; + + std::vector breakdown_request_to_sector_requests(mem_fetch* mf); + + // This is a cycle offset that has to be applied to the l2 accesses to account for + // the cudamemcpy read/writes. We want GPGPU-Sim to only count cycles for kernel execution + // but we want cudamemcpy to go through the L2. Everytime an access is made from cudamemcpy + // this counter is incremented, and when the l2 is accessed (in both cudamemcpyies and otherwise) + // this value is added to the gpgpu-sim cycle counters. + unsigned m_memcpy_cycle_offset; }; class L2interface : public mem_fetch_interface { diff --git a/src/gpgpu-sim/l2cache_trace.h b/src/gpgpu-sim/l2cache_trace.h index 3dac87d..2235cdc 100644 --- a/src/gpgpu-sim/l2cache_trace.h +++ b/src/gpgpu-sim/l2cache_trace.h @@ -34,6 +34,9 @@ #define MEMPART_PRINT_STR SIM_PRINT_STR " %d - " #define MEMPART_DTRACE(x) ( DTRACE(x) && (Trace::sampling_memory_partition == -1 || Trace::sampling_memory_partition == (int)get_mpid()) ) +#define MEM_SUBPART_PRINT_STR SIM_PRINT_STR " %d - " +#define MEM_SUBPART_DTRACE(x) ( DTRACE(x) && (Trace::sampling_memory_partition == -1 || Trace::sampling_memory_partition == (int)m_id) ) + // Intended to be called from inside components of a memory partition // Depends on a get_mpid() function #define MEMPART_DPRINTF(...) do {\ @@ -46,10 +49,23 @@ }\ } while (0) +#define MEM_SUBPART_DPRINTF(...) do {\ + if (MEM_SUBPART_DTRACE(MEMORY_PARTITION_UNIT)) {\ + printf( MEM_SUBPART_PRINT_STR,\ + gpu_sim_cycle + gpu_tot_sim_cycle,\ + Trace::trace_streams_str[Trace::MEMORY_SUBPARTITION_UNIT],\ + m_id );\ + printf(__VA_ARGS__);\ + }\ +} while (0) + #else #define MEMPART_DTRACE(x) (false) #define MEMPART_DPRINTF(x, ...) do {} while (0) +#define MEM_SUBPART_DTRACE(x) (false) +#define MEM_SUBPART_DPRINTF(x, ...) do {} while (0) + #endif diff --git a/src/gpgpu-sim/mem_fetch.cc b/src/gpgpu-sim/mem_fetch.cc index 729636d..a260a35 100644 --- a/src/gpgpu-sim/mem_fetch.cc +++ b/src/gpgpu-sim/mem_fetch.cc @@ -39,7 +39,10 @@ mem_fetch::mem_fetch( const mem_access_t &access, unsigned wid, unsigned sid, unsigned tpc, - const struct memory_config *config ) + const struct memory_config *config, + mem_fetch *m_original_mf, + mem_fetch *m_original_wr_mf) + { m_request_uid = sm_next_mf_request_uid++; m_access = access; @@ -61,6 +64,8 @@ mem_fetch::mem_fetch( const mem_access_t &access, m_status_change = gpu_sim_cycle + gpu_tot_sim_cycle; m_mem_config = config; icnt_flit_size = config->icnt_flit_size; + original_mf = m_original_mf; + original_wr_mf = m_original_wr_mf; } mem_fetch::~mem_fetch() diff --git a/src/gpgpu-sim/mem_fetch.h b/src/gpgpu-sim/mem_fetch.h index de98748..e5efffd 100644 --- a/src/gpgpu-sim/mem_fetch.h +++ b/src/gpgpu-sim/mem_fetch.h @@ -55,7 +55,9 @@ public: unsigned wid, unsigned sid, unsigned tpc, - const struct memory_config *config ); + const struct memory_config *config, + mem_fetch *original_mf = NULL, + mem_fetch *original_wr_mf = NULL); ~mem_fetch(); void set_status( enum mem_fetch_status status, unsigned long long cycle ); @@ -104,6 +106,7 @@ public: enum mem_access_type get_access_type() const { return m_access.get_type(); } const active_mask_t& get_access_warp_mask() const { return m_access.get_warp_mask(); } mem_access_byte_mask_t get_access_byte_mask() const { return m_access.get_byte_mask(); } + mem_access_sector_mask_t get_access_sector_mask() const { return m_access.get_sector_mask(); } address_type get_pc() const { return m_inst.empty()?-1:m_inst.pc; } const warp_inst_t &get_inst() { return m_inst; } @@ -112,6 +115,10 @@ public: const memory_config *get_mem_config(){return m_mem_config;} unsigned get_num_flits(bool simt_to_mem); + + mem_fetch* get_original_mf() { return original_mf; } + mem_fetch* get_original_wr_mf() { return original_wr_mf; } + private: // request source information unsigned m_request_uid; @@ -143,6 +150,10 @@ private: const struct memory_config *m_mem_config; unsigned icnt_flit_size; + + mem_fetch* original_mf; //this pointer is set up when a request is divided into sector requests at L2 cache (if the req size > L2 sector size), so the pointer refers to the original request + mem_fetch* original_wr_mf; //this pointer refers to the original write req, when fetch-on-write policy is used + }; #endif diff --git a/src/gpgpu-sim/mem_latency_stat.cc b/src/gpgpu-sim/mem_latency_stat.cc index fde0eff..c5452b9 100644 --- a/src/gpgpu-sim/mem_latency_stat.cc +++ b/src/gpgpu-sim/mem_latency_stat.cc @@ -75,6 +75,10 @@ memory_stats_t::memory_stats_t( unsigned n_shader, const struct shader_core_conf max_mf_latency = 0; max_icnt2mem_latency = 0; max_icnt2sh_latency = 0; + tot_icnt2mem_latency = 0; + tot_icnt2sh_latency = 0; + tot_mrq_num = 0; + tot_mrq_latency = 0; memset(mrq_lat_table, 0, sizeof(unsigned)*32); memset(dq_lat_table, 0, sizeof(unsigned)*32); memset(mf_lat_table, 0, sizeof(unsigned)*32); @@ -158,6 +162,7 @@ void memory_stats_t::memlatstat_read_done(mem_fetch *mf) mf_max_lat_table[mf->get_tlx_addr().chip][mf->get_tlx_addr().bk] = mf_latency; unsigned icnt2sh_latency; icnt2sh_latency = (gpu_tot_sim_cycle+gpu_sim_cycle) - mf->get_return_timestamp(); + tot_icnt2sh_latency += icnt2sh_latency; icnt2sh_lat_table[LOGB2(icnt2sh_latency)]++; if (icnt2sh_latency > max_icnt2sh_latency) max_icnt2sh_latency = icnt2sh_latency; @@ -191,6 +196,7 @@ void memory_stats_t::memlatstat_icnt2mem_pop(mem_fetch *mf) if (m_memory_config->gpgpu_memlatency_stat) { unsigned icnt2mem_latency; icnt2mem_latency = (gpu_tot_sim_cycle+gpu_sim_cycle) - mf->get_timestamp(); + tot_icnt2mem_latency += icnt2mem_latency; icnt2mem_lat_table[LOGB2(icnt2mem_latency)]++; if (icnt2mem_latency > max_icnt2mem_latency) max_icnt2mem_latency = icnt2mem_latency; @@ -216,14 +222,19 @@ void memory_stats_t::memlatstat_print( unsigned n_mem, unsigned gpu_mem_n_bk ) unsigned max_bank_accesses, min_bank_accesses, max_chip_accesses, min_chip_accesses; if (m_memory_config->gpgpu_memlatency_stat) { + printf("maxmflatency = %d \n", max_mf_latency); + printf("max_icnt2mem_latency = %d \n", max_icnt2mem_latency); printf("maxmrqlatency = %d \n", max_mrq_latency); - printf("maxdqlatency = %d \n", max_dq_latency); - printf("maxmflatency = %d \n", max_mf_latency); + //printf("maxdqlatency = %d \n", max_dq_latency); + printf("max_icnt2sh_latency = %d \n", max_icnt2sh_latency); if (num_mfs) { printf("averagemflatency = %lld \n", mf_total_lat/num_mfs); + printf("avg_icnt2mem_latency = %lld \n", tot_icnt2mem_latency/num_mfs); + if(tot_mrq_num) + printf("avg_mrq_latency = %lld \n", tot_mrq_latency/tot_mrq_num); + + printf("avg_icnt2sh_latency = %lld \n", tot_icnt2sh_latency/num_mfs); } - printf("max_icnt2mem_latency = %d \n", max_icnt2mem_latency); - printf("max_icnt2sh_latency = %d \n", max_icnt2sh_latency); printf("mrq_lat_table:"); for (i=0; i< 32; i++) { printf("%d \t", mrq_lat_table[i]); diff --git a/src/gpgpu-sim/mem_latency_stat.h b/src/gpgpu-sim/mem_latency_stat.h index 4968a3b..5b89202 100644 --- a/src/gpgpu-sim/mem_latency_stat.h +++ b/src/gpgpu-sim/mem_latency_stat.h @@ -56,6 +56,10 @@ public: unsigned max_dq_latency; unsigned max_mf_latency; unsigned max_icnt2mem_latency; + unsigned long long int tot_icnt2mem_latency; + unsigned long long int tot_icnt2sh_latency; + unsigned long long int tot_mrq_latency; + unsigned long long int tot_mrq_num; unsigned max_icnt2sh_latency; unsigned mrq_lat_table[32]; unsigned dq_lat_table[32]; diff --git a/src/gpgpu-sim/shader.cc b/src/gpgpu-sim/shader.cc index f9cfa58..82f9181 100644 --- a/src/gpgpu-sim/shader.cc +++ b/src/gpgpu-sim/shader.cc @@ -74,13 +74,14 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, shader_core_stats *stats ) : core_t( gpu, NULL, config->warp_size, config->n_thread_per_shader ), m_barriers( this, config->max_warps_per_shader, config->max_cta_per_core, config->max_barriers_per_cta, config->warp_size ), - m_dynamic_warp_id(0) + m_dynamic_warp_id(0), m_active_warps(0) { m_cluster = cluster; m_config = config; m_memory_config = mem_config; m_stats = stats; unsigned warp_size=config->warp_size; + Issue_Prio = 0; m_sid = shader_id; m_tpc = tpc_id; @@ -131,6 +132,8 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, CONCRETE_SCHEDULER_TWO_LEVEL_ACTIVE : sched_config.find("gto") != std::string::npos ? CONCRETE_SCHEDULER_GTO : + sched_config.find("old") != std::string::npos ? + CONCRETE_SCHEDULER_OLDEST_FIRST : sched_config.find("warp_limiting") != std::string::npos ? CONCRETE_SCHEDULER_WARP_LIMITING: NUM_CONCRETE_SCHEDULERS; @@ -147,6 +150,7 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, m_simt_stack, &m_warp, &m_pipeline_reg[ID_OC_SP], + &m_pipeline_reg[ID_OC_DP], &m_pipeline_reg[ID_OC_SFU], &m_pipeline_reg[ID_OC_TENSOR_CORE], &m_pipeline_reg[ID_OC_MEM], @@ -162,6 +166,7 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, m_simt_stack, &m_warp, &m_pipeline_reg[ID_OC_SP], + &m_pipeline_reg[ID_OC_DP], &m_pipeline_reg[ID_OC_SFU], &m_pipeline_reg[ID_OC_TENSOR_CORE], &m_pipeline_reg[ID_OC_MEM], @@ -178,6 +183,7 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, m_simt_stack, &m_warp, &m_pipeline_reg[ID_OC_SP], + &m_pipeline_reg[ID_OC_DP], &m_pipeline_reg[ID_OC_SFU], &m_pipeline_reg[ID_OC_TENSOR_CORE], &m_pipeline_reg[ID_OC_MEM], @@ -185,6 +191,22 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, ) ); break; + case CONCRETE_SCHEDULER_OLDEST_FIRST: + schedulers.push_back( + new oldest_scheduler( m_stats, + this, + m_scoreboard, + m_simt_stack, + &m_warp, + &m_pipeline_reg[ID_OC_SP], + &m_pipeline_reg[ID_OC_DP], + &m_pipeline_reg[ID_OC_SFU], + &m_pipeline_reg[ID_OC_TENSOR_CORE], + &m_pipeline_reg[ID_OC_MEM], + i + ) + ); + break; case CONCRETE_SCHEDULER_WARP_LIMITING: schedulers.push_back( new swl_scheduler( m_stats, @@ -193,6 +215,7 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, m_simt_stack, &m_warp, &m_pipeline_reg[ID_OC_SP], + &m_pipeline_reg[ID_OC_DP], &m_pipeline_reg[ID_OC_SFU], &m_pipeline_reg[ID_OC_TENSOR_CORE], &m_pipeline_reg[ID_OC_MEM], @@ -215,8 +238,9 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, } //op collector configuration - enum { SP_CUS, SFU_CUS, TENSOR_CORE_CUS, MEM_CUS, GEN_CUS }; + enum { SP_CUS, DP_CUS, SFU_CUS, MEM_CUS, TENSOR_CORE_CUS, GEN_CUS }; m_operand_collector.add_cu_set(SP_CUS, m_config->gpgpu_operand_collector_num_units_sp, m_config->gpgpu_operand_collector_num_out_ports_sp); + m_operand_collector.add_cu_set(DP_CUS, m_config->gpgpu_operand_collector_num_units_dp, m_config->gpgpu_operand_collector_num_out_ports_dp); m_operand_collector.add_cu_set(SFU_CUS, m_config->gpgpu_operand_collector_num_units_sfu, m_config->gpgpu_operand_collector_num_out_ports_sfu); m_operand_collector.add_cu_set(TENSOR_CORE_CUS, config->gpgpu_operand_collector_num_units_tensor_core, config->gpgpu_operand_collector_num_out_ports_tensor_core); m_operand_collector.add_cu_set(MEM_CUS, m_config->gpgpu_operand_collector_num_units_mem, m_config->gpgpu_operand_collector_num_out_ports_mem); @@ -234,6 +258,15 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, in_ports.clear(),out_ports.clear(),cu_sets.clear(); } + for (unsigned i = 0; i < m_config->gpgpu_operand_collector_num_in_ports_dp; i++) { + in_ports.push_back(&m_pipeline_reg[ID_OC_DP]); + out_ports.push_back(&m_pipeline_reg[OC_EX_DP]); + cu_sets.push_back((unsigned)DP_CUS); + cu_sets.push_back((unsigned)GEN_CUS); + m_operand_collector.add_port(in_ports,out_ports,cu_sets); + in_ports.clear(),out_ports.clear(),cu_sets.clear(); + } + for (unsigned i = 0; i < m_config->gpgpu_operand_collector_num_in_ports_sfu; i++) { in_ports.push_back(&m_pipeline_reg[ID_OC_SFU]); out_ports.push_back(&m_pipeline_reg[OC_EX_SFU]); @@ -279,7 +312,7 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, m_operand_collector.init( m_config->gpgpu_num_reg_banks, this ); // execute - m_num_function_units = m_config->gpgpu_num_sp_units + m_config->gpgpu_num_sfu_units + config->gpgpu_num_tensor_core_units + 1; // sp_unit, sfu, ldst_unit + m_num_function_units = m_config->gpgpu_num_sp_units + m_config->gpgpu_num_dp_units + m_config->gpgpu_num_sfu_units + m_config->gpgpu_num_tensor_core_units + 1; // sp_unit, sfu, ldst_unit //m_dispatch_port = new enum pipeline_stage_name_t[ m_num_function_units ]; //m_issue_port = new enum pipeline_stage_name_t[ m_num_function_units ]; @@ -291,6 +324,12 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, m_issue_port.push_back(OC_EX_SP); } + for (int k = 0; k < m_config->gpgpu_num_dp_units; k++) { + m_fu.push_back(new dp_unit( &m_pipeline_reg[EX_WB], m_config, this )); + m_dispatch_port.push_back(ID_OC_DP); + m_issue_port.push_back(OC_EX_DP); + } + for (int k = 0; k < m_config->gpgpu_num_sfu_units; k++) { m_fu.push_back(new sfu( &m_pipeline_reg[EX_WB], m_config, this )); m_dispatch_port.push_back(ID_OC_SFU); @@ -307,7 +346,7 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, m_fu.push_back(m_ldst_unit); m_dispatch_port.push_back(ID_OC_MEM); m_issue_port.push_back(OC_EX_MEM); - + assert(m_num_function_units == m_fu.size() and m_fu.size() == m_dispatch_port.size() and m_fu.size() == m_issue_port.size()); //there are as many result buses as the width of the EX_WB stage @@ -341,6 +380,7 @@ void shader_core_ctx::reinit(unsigned start_thread, unsigned end_thread, bool re m_occupied_ctas = 0; m_occupied_hwtid.reset(); m_occupied_cta_to_hwtid.clear(); + m_active_warps = 0; } for (unsigned i = start_thread; iget_pdom_stack_top_info(pc,rpc); } +float shader_core_ctx::get_current_occupancy( unsigned long long & active, unsigned long long & total ) const +{ + // To match the achieved_occupancy in nvprof, only SMs that are active are counted toward the occupancy. + if ( m_active_warps > 0 ) { + total += m_warp.size(); + active += m_active_warps; + return float(active) / float(total); + } else { + return 0; + } +} + void shader_core_stats::print( FILE* fout ) const { unsigned long long thread_icount_uarch=0; @@ -436,15 +489,15 @@ void shader_core_stats::print( FILE* fout ) const fprintf(fout, "gpgpu_n_intrawarp_mshr_merge = %d\n", gpgpu_n_intrawarp_mshr_merge); fprintf(fout, "gpgpu_n_cmem_portconflict = %d\n", gpgpu_n_cmem_portconflict); - fprintf(fout, "gpgpu_stall_shd_mem[c_mem][bk_conf] = %d\n", gpu_stall_shd_mem_breakdown[C_MEM][BK_CONF]); - fprintf(fout, "gpgpu_stall_shd_mem[c_mem][mshr_rc] = %d\n", gpu_stall_shd_mem_breakdown[C_MEM][MSHR_RC_FAIL]); - fprintf(fout, "gpgpu_stall_shd_mem[c_mem][icnt_rc] = %d\n", gpu_stall_shd_mem_breakdown[C_MEM][ICNT_RC_FAIL]); - fprintf(fout, "gpgpu_stall_shd_mem[c_mem][data_port_stall] = %d\n", gpu_stall_shd_mem_breakdown[C_MEM][DATA_PORT_STALL]); - fprintf(fout, "gpgpu_stall_shd_mem[t_mem][mshr_rc] = %d\n", gpu_stall_shd_mem_breakdown[T_MEM][MSHR_RC_FAIL]); - fprintf(fout, "gpgpu_stall_shd_mem[t_mem][icnt_rc] = %d\n", gpu_stall_shd_mem_breakdown[T_MEM][ICNT_RC_FAIL]); - fprintf(fout, "gpgpu_stall_shd_mem[t_mem][data_port_stall] = %d\n", gpu_stall_shd_mem_breakdown[T_MEM][DATA_PORT_STALL]); + fprintf(fout, "gpgpu_stall_shd_mem[c_mem][resource_stall] = %d\n", gpu_stall_shd_mem_breakdown[C_MEM][BK_CONF]); + //fprintf(fout, "gpgpu_stall_shd_mem[c_mem][mshr_rc] = %d\n", gpu_stall_shd_mem_breakdown[C_MEM][MSHR_RC_FAIL]); + //fprintf(fout, "gpgpu_stall_shd_mem[c_mem][icnt_rc] = %d\n", gpu_stall_shd_mem_breakdown[C_MEM][ICNT_RC_FAIL]); + //fprintf(fout, "gpgpu_stall_shd_mem[c_mem][data_port_stall] = %d\n", gpu_stall_shd_mem_breakdown[C_MEM][DATA_PORT_STALL]); + //fprintf(fout, "gpgpu_stall_shd_mem[t_mem][mshr_rc] = %d\n", gpu_stall_shd_mem_breakdown[T_MEM][MSHR_RC_FAIL]); + //fprintf(fout, "gpgpu_stall_shd_mem[t_mem][icnt_rc] = %d\n", gpu_stall_shd_mem_breakdown[T_MEM][ICNT_RC_FAIL]); + //fprintf(fout, "gpgpu_stall_shd_mem[t_mem][data_port_stall] = %d\n", gpu_stall_shd_mem_breakdown[T_MEM][DATA_PORT_STALL]); fprintf(fout, "gpgpu_stall_shd_mem[s_mem][bk_conf] = %d\n", gpu_stall_shd_mem_breakdown[S_MEM][BK_CONF]); - fprintf(fout, "gpgpu_stall_shd_mem[gl_mem][bk_conf] = %d\n", + fprintf(fout, "gpgpu_stall_shd_mem[gl_mem][resource_stall] = %d\n", gpu_stall_shd_mem_breakdown[G_MEM_LD][BK_CONF] + gpu_stall_shd_mem_breakdown[G_MEM_ST][BK_CONF] + gpu_stall_shd_mem_breakdown[L_MEM_LD][BK_CONF] + @@ -462,22 +515,22 @@ void shader_core_stats::print( FILE* fout ) const gpu_stall_shd_mem_breakdown[L_MEM_LD][DATA_PORT_STALL] + gpu_stall_shd_mem_breakdown[L_MEM_ST][DATA_PORT_STALL] ); // data port stall at data cache - fprintf(fout, "gpgpu_stall_shd_mem[g_mem_ld][mshr_rc] = %d\n", gpu_stall_shd_mem_breakdown[G_MEM_LD][MSHR_RC_FAIL]); - fprintf(fout, "gpgpu_stall_shd_mem[g_mem_ld][icnt_rc] = %d\n", gpu_stall_shd_mem_breakdown[G_MEM_LD][ICNT_RC_FAIL]); - fprintf(fout, "gpgpu_stall_shd_mem[g_mem_ld][wb_icnt_rc] = %d\n", gpu_stall_shd_mem_breakdown[G_MEM_LD][WB_ICNT_RC_FAIL]); - fprintf(fout, "gpgpu_stall_shd_mem[g_mem_ld][wb_rsrv_fail] = %d\n", gpu_stall_shd_mem_breakdown[G_MEM_LD][WB_CACHE_RSRV_FAIL]); - fprintf(fout, "gpgpu_stall_shd_mem[g_mem_st][mshr_rc] = %d\n", gpu_stall_shd_mem_breakdown[G_MEM_ST][MSHR_RC_FAIL]); - fprintf(fout, "gpgpu_stall_shd_mem[g_mem_st][icnt_rc] = %d\n", gpu_stall_shd_mem_breakdown[G_MEM_ST][ICNT_RC_FAIL]); - fprintf(fout, "gpgpu_stall_shd_mem[g_mem_st][wb_icnt_rc] = %d\n", gpu_stall_shd_mem_breakdown[G_MEM_ST][WB_ICNT_RC_FAIL]); - fprintf(fout, "gpgpu_stall_shd_mem[g_mem_st][wb_rsrv_fail] = %d\n", gpu_stall_shd_mem_breakdown[G_MEM_ST][WB_CACHE_RSRV_FAIL]); - fprintf(fout, "gpgpu_stall_shd_mem[l_mem_ld][mshr_rc] = %d\n", gpu_stall_shd_mem_breakdown[L_MEM_LD][MSHR_RC_FAIL]); - fprintf(fout, "gpgpu_stall_shd_mem[l_mem_ld][icnt_rc] = %d\n", gpu_stall_shd_mem_breakdown[L_MEM_LD][ICNT_RC_FAIL]); - fprintf(fout, "gpgpu_stall_shd_mem[l_mem_ld][wb_icnt_rc] = %d\n", gpu_stall_shd_mem_breakdown[L_MEM_LD][WB_ICNT_RC_FAIL]); - fprintf(fout, "gpgpu_stall_shd_mem[l_mem_ld][wb_rsrv_fail] = %d\n", gpu_stall_shd_mem_breakdown[L_MEM_LD][WB_CACHE_RSRV_FAIL]); - fprintf(fout, "gpgpu_stall_shd_mem[l_mem_st][mshr_rc] = %d\n", gpu_stall_shd_mem_breakdown[L_MEM_ST][MSHR_RC_FAIL]); - fprintf(fout, "gpgpu_stall_shd_mem[l_mem_st][icnt_rc] = %d\n", gpu_stall_shd_mem_breakdown[L_MEM_ST][ICNT_RC_FAIL]); - fprintf(fout, "gpgpu_stall_shd_mem[l_mem_ld][wb_icnt_rc] = %d\n", gpu_stall_shd_mem_breakdown[L_MEM_ST][WB_ICNT_RC_FAIL]); - fprintf(fout, "gpgpu_stall_shd_mem[l_mem_ld][wb_rsrv_fail] = %d\n", gpu_stall_shd_mem_breakdown[L_MEM_ST][WB_CACHE_RSRV_FAIL]); + //fprintf(fout, "gpgpu_stall_shd_mem[g_mem_ld][mshr_rc] = %d\n", gpu_stall_shd_mem_breakdown[G_MEM_LD][MSHR_RC_FAIL]); + //fprintf(fout, "gpgpu_stall_shd_mem[g_mem_ld][icnt_rc] = %d\n", gpu_stall_shd_mem_breakdown[G_MEM_LD][ICNT_RC_FAIL]); + //fprintf(fout, "gpgpu_stall_shd_mem[g_mem_ld][wb_icnt_rc] = %d\n", gpu_stall_shd_mem_breakdown[G_MEM_LD][WB_ICNT_RC_FAIL]); + //fprintf(fout, "gpgpu_stall_shd_mem[g_mem_ld][wb_rsrv_fail] = %d\n", gpu_stall_shd_mem_breakdown[G_MEM_LD][WB_CACHE_RSRV_FAIL]); + //fprintf(fout, "gpgpu_stall_shd_mem[g_mem_st][mshr_rc] = %d\n", gpu_stall_shd_mem_breakdown[G_MEM_ST][MSHR_RC_FAIL]); + //fprintf(fout, "gpgpu_stall_shd_mem[g_mem_st][icnt_rc] = %d\n", gpu_stall_shd_mem_breakdown[G_MEM_ST][ICNT_RC_FAIL]); + //fprintf(fout, "gpgpu_stall_shd_mem[g_mem_st][wb_icnt_rc] = %d\n", gpu_stall_shd_mem_breakdown[G_MEM_ST][WB_ICNT_RC_FAIL]); + //fprintf(fout, "gpgpu_stall_shd_mem[g_mem_st][wb_rsrv_fail] = %d\n", gpu_stall_shd_mem_breakdown[G_MEM_ST][WB_CACHE_RSRV_FAIL]); + //fprintf(fout, "gpgpu_stall_shd_mem[l_mem_ld][mshr_rc] = %d\n", gpu_stall_shd_mem_breakdown[L_MEM_LD][MSHR_RC_FAIL]); + //fprintf(fout, "gpgpu_stall_shd_mem[l_mem_ld][icnt_rc] = %d\n", gpu_stall_shd_mem_breakdown[L_MEM_LD][ICNT_RC_FAIL]); + //fprintf(fout, "gpgpu_stall_shd_mem[l_mem_ld][wb_icnt_rc] = %d\n", gpu_stall_shd_mem_breakdown[L_MEM_LD][WB_ICNT_RC_FAIL]); + //fprintf(fout, "gpgpu_stall_shd_mem[l_mem_ld][wb_rsrv_fail] = %d\n", gpu_stall_shd_mem_breakdown[L_MEM_LD][WB_CACHE_RSRV_FAIL]); + //fprintf(fout, "gpgpu_stall_shd_mem[l_mem_st][mshr_rc] = %d\n", gpu_stall_shd_mem_breakdown[L_MEM_ST][MSHR_RC_FAIL]); + //fprintf(fout, "gpgpu_stall_shd_mem[l_mem_st][icnt_rc] = %d\n", gpu_stall_shd_mem_breakdown[L_MEM_ST][ICNT_RC_FAIL]); + //fprintf(fout, "gpgpu_stall_shd_mem[l_mem_ld][wb_icnt_rc] = %d\n", gpu_stall_shd_mem_breakdown[L_MEM_ST][WB_ICNT_RC_FAIL]); + //fprintf(fout, "gpgpu_stall_shd_mem[l_mem_ld][wb_rsrv_fail] = %d\n", gpu_stall_shd_mem_breakdown[L_MEM_ST][WB_CACHE_RSRV_FAIL]); fprintf(fout, "gpu_reg_bank_conflict_stalls = %d\n", gpu_reg_bank_conflict_stalls); @@ -488,6 +541,14 @@ void shader_core_stats::print( FILE* fout ) const for (unsigned i = 3; i < m_config->warp_size + 3; i++) fprintf(fout, "\tW%d:%d", i-2, shader_cycle_distro[i]); fprintf(fout, "\n"); + fprintf(fout, "single_issue_nums: "); + for (unsigned i = 0; i < m_config->gpgpu_num_sched_per_core; i++) + fprintf(fout, "WS%d:%d\t", i, single_issue_nums[i]); + fprintf(fout, "\n"); + fprintf(fout, "dual_issue_nums: "); + for (unsigned i = 0; i < m_config->gpgpu_num_sched_per_core; i++) + fprintf(fout, "WS%d:%d\t", i, dual_issue_nums[i]); + fprintf(fout, "\n"); m_outgoing_traffic_stats->print(fout); m_incoming_traffic_stats->print(fout); @@ -669,13 +730,15 @@ void shader_core_ctx::fetch() } if( did_exit ) m_warp[warp_id].set_done_exit(); + --m_active_warps; + assert(m_active_warps >= 0); } // this code fetches instructions from the i-cache or generates memory requests if( !m_warp[warp_id].functional_done() && !m_warp[warp_id].imiss_pending() && m_warp[warp_id].ibuffer_empty() ) { address_type pc = m_warp[warp_id].get_pc(); address_type ppc = pc + PROGRAM_MEM_START; - unsigned nbytes=16; + unsigned nbytes=16; unsigned offset_in_block = pc & (m_config->m_L1I_config.get_line_sz()-1); if( (offset_in_block+nbytes) > m_config->m_L1I_config.get_line_sz() ) nbytes = (m_config->m_L1I_config.get_line_sz()-offset_in_block); @@ -750,10 +813,19 @@ void shader_core_ctx::issue_warp( register_set& pipe_reg_set, const warp_inst_t* } void shader_core_ctx::issue(){ + + //Ensure fair round robin issu between schedulers + unsigned j; + for (unsigned i = 0; i < schedulers.size(); i++) { + j = (Issue_Prio + i) % schedulers.size(); + schedulers[j]->cycle(); + } + Issue_Prio = (Issue_Prio+1)% schedulers.size(); + //really is issue; - for (unsigned i = 0; i < schedulers.size(); i++) { - schedulers[i]->cycle(); - } + //for (unsigned i = 0; i < schedulers.size(); i++) { + // schedulers[i]->cycle(); + //} } shd_warp_t& scheduler_unit::warp(int i){ @@ -868,7 +940,10 @@ void scheduler_unit::cycle() unsigned warp_id = (*iter)->get_warp_id(); unsigned checked=0; unsigned issued=0; - unsigned max_issue = m_shader->m_config->gpgpu_max_insn_issue_per_warp; + exec_unit_type_t previous_issued_inst_exec_type = exec_unit_type_t::NONE; + unsigned max_issue = m_shader->m_config->gpgpu_max_insn_issue_per_warp; + bool diff_exec_units = m_shader->m_config->gpgpu_dual_issue_diff_exec_units; + 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; @@ -901,18 +976,21 @@ void scheduler_unit::cycle() ready_inst = true; const active_mask_t &active_mask = m_simt_stack[warp_id]->get_active_mask(); assert( warp(warp_id).inst_in_pipeline() ); - if ( (pI->op == LOAD_OP)||(pI->op ==TENSOR_CORE_LOAD_OP)|| (pI->op == STORE_OP)|| (pI->op==TENSOR_CORE_STORE_OP) || (pI->op == MEMORY_BARRIER_OP) ) { - if( m_mem_out->has_free() ) { - m_shader->issue_warp(*m_mem_out,pI,active_mask,warp_id); - issued++; - issued_inst=true; - warp_inst_issued = true; - } + if ( (pI->op == LOAD_OP) || (pI->op == STORE_OP) || (pI->op == MEMORY_BARRIER_OP)||(pI->op==TENSOR_CORE_LOAD_OP)||(pI->op==TENSOR_CORE_STORE_OP) ) { + if( m_mem_out->has_free() && (!diff_exec_units || previous_issued_inst_exec_type != exec_unit_type_t::MEM)) { + m_shader->issue_warp(*m_mem_out,pI,active_mask,warp_id); + issued++; + issued_inst=true; + warp_inst_issued = true; + previous_issued_inst_exec_type = exec_unit_type_t::MEM; + } } else { + bool sp_pipe_avail = m_sp_out->has_free(); bool sfu_pipe_avail = m_sfu_out->has_free(); bool tensor_core_pipe_avail = m_tensor_core_out->has_free(); - if( sp_pipe_avail && (pI->op != SFU_OP) && (pI->op != TENSOR_CORE_OP) ) { + bool dp_pipe_avail = m_dp_out->has_free(); + if( sp_pipe_avail && (pI->op != TENSOR_CORE_OP) && (pI->op != SFU_OP && pI->op != DP_OP) && (!diff_exec_units || previous_issued_inst_exec_type != exec_unit_type_t::SP)) { //Jin: special for CDP api if(pI->m_is_cdp && !warp(warp_id).m_cdp_dummy) { @@ -937,12 +1015,23 @@ void scheduler_unit::cycle() issued++; issued_inst=true; warp_inst_issued = true; - } else if ( (pI->op == SFU_OP) || (pI->op == ALU_SFU_OP) ) { + previous_issued_inst_exec_type = exec_unit_type_t::SP; + } else if ( (m_shader->m_config->gpgpu_num_dp_units != 0) && (pI->op == DP_OP) && (!diff_exec_units || previous_issued_inst_exec_type != exec_unit_type_t::DP)) { + if( dp_pipe_avail ) { + m_shader->issue_warp(*m_dp_out,pI,active_mask,warp_id); + issued++; + issued_inst=true; + warp_inst_issued = true; + previous_issued_inst_exec_type = exec_unit_type_t::DP; + } + } //If the DP units = 0 (like in Fermi archi), then change DP inst to SFU inst + else if ( ((m_shader->m_config->gpgpu_num_dp_units == 0 && pI->op == DP_OP) || (pI->op == SFU_OP) || (pI->op == ALU_SFU_OP)) && (!diff_exec_units || previous_issued_inst_exec_type != exec_unit_type_t::SFU)) { if( sfu_pipe_avail ) { m_shader->issue_warp(*m_sfu_out,pI,active_mask,warp_id); issued++; issued_inst=true; warp_inst_issued = true; + previous_issued_inst_exec_type = exec_unit_type_t::SFU; } } else if ( (pI->op == TENSOR_CORE_OP) ) { @@ -952,12 +1041,12 @@ void scheduler_unit::cycle() issued_inst=true; warp_inst_issued = true; } - } - } - } else { + } + }//end of else + } else { SCHED_DPRINTF( "Warp (warp_id %u, dynamic_warp_id %u) fails scoreboard\n", (*iter)->get_warp_id(), (*iter)->get_dynamic_warp_id() ); - } + } } } else if( valid ) { // this case can happen after a return instruction in diverged warp @@ -988,6 +1077,14 @@ void scheduler_unit::cycle() m_last_supervised_issued = supervised_iter; } } + + if(issued == 1) + m_stats->single_issue_nums[m_id]++; + else if(issued > 1) + m_stats->dual_issue_nums[m_id]++; + else + abort(); //issued should be > 0 + break; } } @@ -1045,6 +1142,16 @@ void gto_scheduler::order_warps() scheduler_unit::sort_warps_by_oldest_dynamic_id ); } +void oldest_scheduler::order_warps() +{ + order_by_priority( m_next_cycle_prioritized_warps, + m_supervised_warps, + m_last_supervised_issued, + m_supervised_warps.size(), + ORDERED_PRIORITY_FUNC_ONLY, + scheduler_unit::sort_warps_by_oldest_dynamic_id ); +} + void two_level_active_scheduler::do_on_warp_issued( unsigned warp_id, unsigned num_issued, @@ -1117,12 +1224,13 @@ swl_scheduler::swl_scheduler ( shader_core_stats* stats, shader_core_ctx* shader Scoreboard* scoreboard, simt_stack** simt, std::vector* warp, register_set* sp_out, + register_set* dp_out, register_set* sfu_out, register_set* tensor_core_out, register_set* mem_out, int id, char* config_string ) - : scheduler_unit ( stats, shader, scoreboard, simt, warp, sp_out, sfu_out, tensor_core_out, mem_out, id ) + : scheduler_unit ( stats, shader, scoreboard, simt, warp, sp_out, dp_out, sfu_out,tensor_core_out, mem_out, id ) { unsigned m_prioritization_readin; int ret = sscanf( config_string, @@ -1386,8 +1494,14 @@ ldst_unit::process_cache_access( cache_t* cache, mem_stage_stall_type result = NO_RC_FAIL; bool write_sent = was_write_sent(events); bool read_sent = was_read_sent(events); - if( write_sent ) - m_core->inc_store_req( inst.warp_id() ); + if( write_sent ) { + unsigned inc_ack = (m_config->m_L1D_config.get_mshr_type() == SECTOR_ASSOC)? + (mf->get_data_size()/SECTOR_SIZE) : 1; + + for(unsigned i=0; i< inc_ack; ++i) + m_core->inc_store_req( inst.warp_id() ); + + } if ( status == HIT ) { assert( !read_sent ); inst.accessq_pop_back(); @@ -1399,7 +1513,7 @@ ldst_unit::process_cache_access( cache_t* cache, if( !write_sent ) delete mf; } else if ( status == RESERVATION_FAIL ) { - result = COAL_STALL; + result = BK_CONF; assert( !read_sent ); assert( !write_sent ); delete mf; @@ -1408,8 +1522,8 @@ ldst_unit::process_cache_access( cache_t* cache, //inst.clear_active( access.get_warp_mask() ); // threads in mf writeback when mf returns inst.accessq_pop_back(); } - if( !inst.accessq_empty() ) - result = BK_CONF; + if( !inst.accessq_empty() && result == NO_RC_FAIL) + result = COAL_STALL; return result; } @@ -1429,6 +1543,111 @@ mem_stage_stall_type ldst_unit::process_memory_access_queue( cache_t *cache, war return process_cache_access( cache, mf->get_addr(), inst, events, mf, status ); } +mem_stage_stall_type ldst_unit::process_memory_access_queue_l1cache( l1_cache *cache, warp_inst_t &inst ) +{ + mem_stage_stall_type result = NO_RC_FAIL; + if( inst.accessq_empty() ) + return result; + + mem_fetch *mf = m_mf_allocator->alloc(inst,inst.accessq_back()); + + if(m_config->m_L1D_config.l1_latency > 0) + { + if((l1_latency_queue[m_config->m_L1D_config.l1_latency-1]) == NULL) + { + l1_latency_queue[m_config->m_L1D_config.l1_latency-1] = mf; + + if( mf->get_inst().is_store() ) { + unsigned inc_ack = (m_config->m_L1D_config.get_mshr_type() == SECTOR_ASSOC)? + (mf->get_data_size()/SECTOR_SIZE) : 1; + + for(unsigned i=0; i< inc_ack; ++i) + m_core->inc_store_req( inst.warp_id() ); + } + + inst.accessq_pop_back(); + } + else + { + result = BK_CONF; + delete mf; + } + if( !inst.accessq_empty() && result !=BK_CONF) + result = COAL_STALL; + return result; + } + else + { + std::list events; + enum cache_request_status status = cache->access(mf->get_addr(),mf,gpu_sim_cycle+gpu_tot_sim_cycle,events); + return process_cache_access( cache, mf->get_addr(), inst, events, mf, status ); + } +} + +void ldst_unit::L1_latency_queue_cycle() +{ + //std::deque< std::pair >::iterator it = m_latency_queue.begin(); + if((l1_latency_queue[0]) != NULL) + { + mem_fetch* mf_next = l1_latency_queue[0]; + std::list events; + enum cache_request_status status = m_L1D->access(mf_next->get_addr(),mf_next,gpu_sim_cycle+gpu_tot_sim_cycle,events); + + bool write_sent = was_write_sent(events); + bool read_sent = was_read_sent(events); + + if ( status == HIT ) { + assert( !read_sent ); + l1_latency_queue[0] = NULL; + if ( mf_next->get_inst().is_load() ) { + for ( unsigned r=0; r < 4; r++) + if (mf_next->get_inst().out[r] > 0) + { + assert(m_pending_writes[mf_next->get_inst().warp_id()][mf_next->get_inst().out[r]]>0); + unsigned still_pending = --m_pending_writes[mf_next->get_inst().warp_id()][mf_next->get_inst().out[r]]; + if(!still_pending) + { + m_pending_writes[mf_next->get_inst().warp_id()].erase(mf_next->get_inst().out[r]); + m_scoreboard->releaseRegister(mf_next->get_inst().warp_id(),mf_next->get_inst().out[r]); + m_core->warp_inst_complete(mf_next->get_inst()); + } + } + } + + //For write hit in WB policy + if(mf_next->get_inst().is_store() && !write_sent) + { + unsigned dec_ack = (m_config->m_L1D_config.get_mshr_type() == SECTOR_ASSOC)? + (mf_next->get_data_size()/SECTOR_SIZE) : 1; + + mf_next->set_reply(); + + for(unsigned i=0; i< dec_ack; ++i) + m_core->store_ack(mf_next); + } + + if( !write_sent ) + delete mf_next; + + } else if ( status == RESERVATION_FAIL ) { + assert( !read_sent ); + assert( !write_sent ); + } else { + assert( status == MISS || status == HIT_RESERVED ); + l1_latency_queue[0] = NULL; + } + } + + for( unsigned stage = 0; stagem_L1D_config.l1_latency-1; ++stage) + if( l1_latency_queue[stage] == NULL) { + l1_latency_queue[stage] = l1_latency_queue[stage+1] ; + l1_latency_queue[stage+1] = NULL; + } + +} + + + bool ldst_unit::constant_cycle( warp_inst_t &inst, mem_stage_stall_type &rc_fail, mem_stage_access_type &fail_type) { if( inst.empty() || ((inst.space.get_type() != const_space) && (inst.space.get_type() != param_space_kernel)) ) @@ -1478,7 +1697,7 @@ bool ldst_unit::memory_cycle( warp_inst_t &inst, mem_stage_stall_type &stall_rea bypassL1D = true; } else if (inst.space.is_global()) { // global memory access // skip L1 cache if the option is enabled - if (m_core->get_config()->gmem_skip_L1D) + if (m_core->get_config()->gmem_skip_L1D && (CACHE_L1 != inst.cache_op)) bypassL1D = true; } if( bypassL1D ) { @@ -1502,9 +1721,9 @@ bool ldst_unit::memory_cycle( warp_inst_t &inst, mem_stage_stall_type &stall_rea } } else { assert( CACHE_UNDEFINED != inst.cache_op ); - stall_cond = process_memory_access_queue(m_L1D,inst); + stall_cond = process_memory_access_queue_l1cache(m_L1D,inst); } - if( !inst.accessq_empty() ) + if( !inst.accessq_empty() && stall_cond == NO_RC_FAIL) stall_cond = COAL_STALL; if (stall_cond != NO_RC_FAIL) { stall_reason = stall_cond; @@ -1534,6 +1753,11 @@ void ldst_unit::flush(){ m_L1D->flush(); } +void ldst_unit::invalidate(){ + // Flush L1D cache + m_L1D->invalidate(); +} + simd_function_unit::simd_function_unit( const shader_core_config *config ) { m_config=config; @@ -1586,6 +1810,13 @@ void sp_unit::active_lanes_in_pipeline(){ m_core->incfuactivelanes_stat(active_count); m_core->incfumemactivelanes_stat(active_count); } +void dp_unit::active_lanes_in_pipeline(){ + unsigned active_count=pipelined_simd_unit::get_active_lanes_in_pipeline(); + assert(active_count<=m_core->get_config()->warp_size); + m_core->incspactivelanes_stat(active_count); + m_core->incfuactivelanes_stat(active_count); + m_core->incfumemactivelanes_stat(active_count); +} void sfu::active_lanes_in_pipeline(){ unsigned active_count=pipelined_simd_unit::get_active_lanes_in_pipeline(); @@ -1610,6 +1841,12 @@ sp_unit::sp_unit( register_set* result_port, const shader_core_config *config,sh m_name = "SP "; } +dp_unit::dp_unit( register_set* result_port, const shader_core_config *config,shader_core_ctx *core) + : pipelined_simd_unit(result_port,config,config->max_sfu_latency,core) +{ + m_name = "DP "; +} + void sp_unit :: issue(register_set& source_reg) { warp_inst_t** ready_reg = source_reg.get_ready(); @@ -1619,6 +1856,14 @@ void sp_unit :: issue(register_set& source_reg) pipelined_simd_unit::issue(source_reg); } +void dp_unit :: issue(register_set& source_reg) +{ + warp_inst_t** ready_reg = source_reg.get_ready(); + //m_core->incexecstat((*ready_reg)); + (*ready_reg)->op_pipe=DP__OP; + m_core->incsp_stat(m_core->get_config()->warp_size,(*ready_reg)->latency); + pipelined_simd_unit::issue(source_reg); +} pipelined_simd_unit::pipelined_simd_unit( register_set* result_port, const shader_core_config *config, unsigned max_latency,shader_core_ctx *core ) : simd_function_unit(config) @@ -1712,8 +1957,9 @@ ldst_unit::ldst_unit( mem_fetch_interface *icnt, const memory_config *mem_config, shader_core_stats *stats, unsigned sid, - unsigned tpc ) : pipelined_simd_unit(NULL,config,3,core), m_next_wb(config) + unsigned tpc ) : pipelined_simd_unit(NULL,config,config->smem_latency,core), m_next_wb(config) { + assert(config->smem_latency > 1); init( icnt, mf_allocator, core, @@ -1734,6 +1980,12 @@ ldst_unit::ldst_unit( mem_fetch_interface *icnt, m_icnt, m_mf_allocator, IN_L1D_MISS_QUEUE ); + + if(m_config->m_L1D_config.l1_latency > 0) + { + for(int i=0; im_L1D_config.l1_latency; i++ ) + l1_latency_queue.push_back((mem_fetch*)NULL); + } } } @@ -1916,12 +2168,12 @@ void ldst_unit::cycle() if( !m_response_fifo.empty() ) { mem_fetch *mf = m_response_fifo.front(); - if (mf->istexture()) { + if (mf->get_access_type() == TEXTURE_ACC_R) { if (m_L1T->fill_port_free()) { m_L1T->fill(mf,gpu_sim_cycle+gpu_tot_sim_cycle); m_response_fifo.pop_front(); } - } else if (mf->isconst()) { + } else if (mf->get_access_type() == CONST_ACC_R) { if (m_L1C->fill_port_free()) { mf->set_status(IN_SHADER_FETCHED,gpu_sim_cycle+gpu_tot_sim_cycle); m_L1C->fill(mf,gpu_sim_cycle+gpu_tot_sim_cycle); @@ -1960,7 +2212,11 @@ void ldst_unit::cycle() m_L1T->cycle(); m_L1C->cycle(); - if( m_L1D ) m_L1D->cycle(); + if( m_L1D ) { + m_L1D->cycle(); + if(m_config->m_L1D_config.l1_latency > 0) + L1_latency_queue_cycle(); + } warp_inst_t &pipe_reg = *m_dispatch_reg; enum mem_stage_stall_type rc_fail = NO_RC_FAIL; @@ -1983,9 +2239,9 @@ void ldst_unit::cycle() unsigned warp_id = pipe_reg.warp_id(); if( pipe_reg.is_load() ) { if( pipe_reg.space.get_type() == shared_space ) { - if( m_pipeline_reg[2]->empty() ) { + if( m_pipeline_reg[m_config->smem_latency-1]->empty() ) { // new shared memory request - move_warp(m_pipeline_reg[2],m_dispatch_reg); + move_warp(m_pipeline_reg[m_config->smem_latency-1],m_dispatch_reg); m_dispatch_reg->clear(); } } else { @@ -2562,9 +2818,42 @@ unsigned int shader_core_config::max_cta( const kernel_info_t &k ) const assert( result <= MAX_CTA_PER_SHADER ); if (result < 1) { printf ("GPGPU-Sim uArch: ERROR ** Kernel requires more resources than shader has.\n"); + if(gpgpu_ignore_resources_limitation) { + printf ("GPGPU-Sim uArch: gpgpu_ignore_resources_limitation is set, ignore the ERROR!\n"); + return 1; + } abort(); } + if(adpative_volta_cache_config && !k.volta_cache_config_set) { + //For Volta, we assign the remaining shared memory to L1 cache + //For more info, see https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#shared-memory-7-x + unsigned total_shmed = kernel_info->smem * result; + assert(total_shmed >=0 && total_shmed <= gpgpu_shmem_size); + assert(gpgpu_shmem_size == 98304); //Volta has 96 KB shared + assert(m_L1D_config.get_nset() == 4); //Volta L1 has four sets + if(total_shmed < gpgpu_shmem_size){ + if(total_shmed == 0) + m_L1D_config.set_assoc(256); //L1 is 128KB ans shd=0 + else if(total_shmed > 0 && total_shmed <= 8192) + m_L1D_config.set_assoc(240); //L1 is 120KB ans shd=8KB + else if(total_shmed > 8192 && total_shmed <= 16384) + m_L1D_config.set_assoc(224); //L1 is 112KB ans shd=16KB + else if(total_shmed > 16384 && total_shmed <= 32768) + m_L1D_config.set_assoc(192); //L1 is 96KB ans shd=32KB + else if(total_shmed > 32768 && total_shmed <= 65536) + m_L1D_config.set_assoc(128); //L1 is 64KB ans shd=64KB + else if(total_shmed > 65536 && total_shmed <= gpgpu_shmem_size) + m_L1D_config.set_assoc(64); //L1 is 32KB and shd=96KB + else + assert(0); + + printf ("GPGPU-Sim: Reconfigure L1 cache in Volta Archi to %uKB\n", m_L1D_config.get_total_size_inKB()); + } + + k.volta_cache_config_set = true; + } + return result; } @@ -2586,6 +2875,11 @@ void shader_core_ctx::cache_flush() m_ldst_unit->flush(); } +void shader_core_ctx::cache_invalidate() +{ + m_ldst_unit->invalidate(); +} + // modifiers std::list opndcoll_rfu_t::arbiter_t::allocate_reads() { @@ -3340,6 +3634,15 @@ void simt_core_cluster::print_not_completed( FILE *fp ) const } } + +float simt_core_cluster::get_current_occupancy( unsigned long long& active, unsigned long long& total ) const { + float aggregate = 0.f; + for( unsigned i=0; i < m_config->n_simt_cores_per_cluster; i++ ) { + aggregate+=m_core[i]->get_current_occupancy( active, total ); + } + return aggregate / m_config->n_simt_cores_per_cluster; +} + unsigned simt_core_cluster::get_n_active_cta() const { unsigned n=0; @@ -3403,6 +3706,12 @@ void simt_core_cluster::cache_flush() m_core[i]->cache_flush(); } +void simt_core_cluster::cache_invalidate() +{ + for( unsigned i=0; i < m_config->n_simt_cores_per_cluster; i++ ) + m_core[i]->cache_invalidate(); +} + bool simt_core_cluster::icnt_injection_buffer_full(unsigned size, bool write) { unsigned request_size = size; diff --git a/src/gpgpu-sim/shader.h b/src/gpgpu-sim/shader.h index 97e438f..437506c 100644 --- a/src/gpgpu-sim/shader.h +++ b/src/gpgpu-sim/shader.h @@ -70,6 +70,14 @@ #define WRITE_MASK_SIZE 8 +enum exec_unit_type_t +{ + NONE = 0, + SP = 1, + SFU = 2, + MEM = 3, + DP = 4 +}; class thread_ctx_t { public: @@ -308,6 +316,7 @@ enum concrete_scheduler CONCRETE_SCHEDULER_GTO, CONCRETE_SCHEDULER_TWO_LEVEL_ACTIVE, CONCRETE_SCHEDULER_WARP_LIMITING, + CONCRETE_SCHEDULER_OLDEST_FIRST, NUM_CONCRETE_SCHEDULERS }; @@ -317,13 +326,14 @@ public: Scoreboard* scoreboard, simt_stack** simt, std::vector* warp, register_set* sp_out, + register_set* dp_out, register_set* sfu_out, register_set* tensor_core_out, register_set* mem_out, int id) : m_supervised_warps(), m_stats(stats), m_shader(shader), m_scoreboard(scoreboard), m_simt_stack(simt), /*m_pipeline_reg(pipe_regs),*/ m_warp(warp), - m_sp_out(sp_out),m_sfu_out(sfu_out),m_tensor_core_out(tensor_core_out),m_mem_out(mem_out), m_id(id){} + m_sp_out(sp_out),m_dp_out(dp_out),m_sfu_out(sfu_out),m_tensor_core_out(tensor_core_out),m_mem_out(mem_out), m_id(id){} virtual ~scheduler_unit(){} virtual void add_supervised_warp_id(int i) { m_supervised_warps.push_back(&warp(i)); @@ -395,6 +405,7 @@ protected: //warp_inst_t** m_pipeline_reg; std::vector* m_warp; register_set* m_sp_out; + register_set* m_dp_out; register_set* m_sfu_out; register_set* m_tensor_core_out; register_set* m_mem_out; @@ -408,11 +419,12 @@ public: Scoreboard* scoreboard, simt_stack** simt, std::vector* warp, register_set* sp_out, + register_set* dp_out, register_set* sfu_out, register_set* tensor_core_out, register_set* mem_out, int id ) - : scheduler_unit ( stats, shader, scoreboard, simt, warp, sp_out, sfu_out, tensor_core_out, mem_out, id ){} + : scheduler_unit ( stats, shader, scoreboard, simt, warp, sp_out, dp_out, sfu_out,tensor_core_out, mem_out, id ){} virtual ~lrr_scheduler () {} virtual void order_warps (); virtual void done_adding_supervised_warps() { @@ -426,11 +438,12 @@ public: Scoreboard* scoreboard, simt_stack** simt, std::vector* warp, register_set* sp_out, + register_set* dp_out, register_set* sfu_out, register_set* tensor_core_out, register_set* mem_out, int id ) - : scheduler_unit ( stats, shader, scoreboard, simt, warp, sp_out, sfu_out, tensor_core_out, mem_out, id ){} + : scheduler_unit ( stats, shader, scoreboard, simt, warp, sp_out, dp_out, sfu_out,tensor_core_out, mem_out, id ){} virtual ~gto_scheduler () {} virtual void order_warps (); virtual void done_adding_supervised_warps() { @@ -439,6 +452,25 @@ public: }; +class oldest_scheduler : public scheduler_unit { +public: + oldest_scheduler ( shader_core_stats* stats, shader_core_ctx* shader, + Scoreboard* scoreboard, simt_stack** simt, + std::vector* warp, + register_set* sp_out, + register_set* dp_out, + register_set* sfu_out, + register_set* tensor_core_out, + register_set* mem_out, + int id ) + : scheduler_unit ( stats, shader, scoreboard, simt, warp, sp_out, dp_out, sfu_out,tensor_core_out, mem_out, id ){} + virtual ~oldest_scheduler () {} + virtual void order_warps (); + virtual void done_adding_supervised_warps() { + m_last_supervised_issued = m_supervised_warps.begin(); + } + +}; class two_level_active_scheduler : public scheduler_unit { public: @@ -446,12 +478,13 @@ public: Scoreboard* scoreboard, simt_stack** simt, std::vector* warp, register_set* sp_out, + register_set* dp_out, register_set* sfu_out, register_set* tensor_core_out, register_set* mem_out, int id, char* config_str ) - : scheduler_unit ( stats, shader, scoreboard, simt, warp, sp_out, sfu_out, tensor_core_out, mem_out, id ), + : scheduler_unit ( stats, shader, scoreboard, simt, warp, sp_out, dp_out, sfu_out,tensor_core_out, mem_out, id ), m_pending_warps() { unsigned inner_level_readin; @@ -497,6 +530,7 @@ public: Scoreboard* scoreboard, simt_stack** simt, std::vector* warp, register_set* sp_out, + register_set* dp_out, register_set* sfu_out, register_set* tensor_core_out, register_set* mem_out, @@ -1060,6 +1094,23 @@ public: switch(inst.op) { case SFU_OP: break; case ALU_SFU_OP: break; + case DP_OP: break; //for compute <= 29 (i..e Fermi and GT200) + default: return false; + } + return pipelined_simd_unit::can_issue(inst); + } + virtual void active_lanes_in_pipeline(); + virtual void issue( register_set& source_reg ); +}; + +class dp_unit : public pipelined_simd_unit +{ +public: + dp_unit( register_set* result_port, const shader_core_config *config, shader_core_ctx *core ); + virtual bool can_issue( const warp_inst_t &inst ) const + { + switch(inst.op) { + case DP_OP: break; default: return false; } return pipelined_simd_unit::can_issue(inst); @@ -1098,6 +1149,7 @@ public: case STORE_OP: return false; case TENSOR_CORE_STORE_OP: return false; case MEMORY_BARRIER_OP: return false; + case DP_OP: return false; default: break; } return pipelined_simd_unit::can_issue(inst); @@ -1129,6 +1181,7 @@ public: void fill( mem_fetch *mf ); void flush(); + void invalidate(); void writeback(); // accessors @@ -1195,6 +1248,7 @@ protected: mem_fetch *mf, enum cache_request_status status ); mem_stage_stall_type process_memory_access_queue( cache_t *cache, warp_inst_t &inst ); + mem_stage_stall_type process_memory_access_queue_l1cache( l1_cache *cache, warp_inst_t &inst ); const memory_config *m_memory_config; class mem_fetch_interface *m_icnt; @@ -1223,13 +1277,18 @@ protected: // for debugging unsigned long long m_last_inst_gpu_sim_cycle; unsigned long long m_last_inst_gpu_tot_sim_cycle; + + std::deque l1_latency_queue; + void L1_latency_queue_cycle(); }; enum pipeline_stage_name_t { ID_OC_SP=0, + ID_OC_DP, ID_OC_SFU, ID_OC_MEM, OC_EX_SP, + OC_EX_DP, OC_EX_SFU, OC_EX_MEM, EX_WB, @@ -1240,9 +1299,11 @@ enum pipeline_stage_name_t { const char* const pipeline_stage_name_decode[] = { "ID_OC_SP", + "ID_OC_DP", "ID_OC_SFU", "ID_OC_MEM", "OC_EX_SP", + "OC_EX_DP", "OC_EX_SFU", "OC_EX_MEM", "EX_WB", @@ -1340,27 +1401,29 @@ struct shader_core_config : public core_config mutable cache_config m_L1C_config; mutable l1d_cache_config m_L1D_config; - bool gmem_skip_L1D; // on = global memory access always skip the L1 cache - bool gpgpu_dwf_reg_bankconflict; int gpgpu_num_sched_per_core; int gpgpu_max_insn_issue_per_warp; + bool gpgpu_dual_issue_diff_exec_units; //op collector int gpgpu_operand_collector_num_units_sp; + int gpgpu_operand_collector_num_units_dp; int gpgpu_operand_collector_num_units_sfu; int gpgpu_operand_collector_num_units_tensor_core; int gpgpu_operand_collector_num_units_mem; int gpgpu_operand_collector_num_units_gen; unsigned int gpgpu_operand_collector_num_in_ports_sp; + unsigned int gpgpu_operand_collector_num_in_ports_dp; unsigned int gpgpu_operand_collector_num_in_ports_sfu; unsigned int gpgpu_operand_collector_num_in_ports_tensor_core; unsigned int gpgpu_operand_collector_num_in_ports_mem; unsigned int gpgpu_operand_collector_num_in_ports_gen; unsigned int gpgpu_operand_collector_num_out_ports_sp; + unsigned int gpgpu_operand_collector_num_out_ports_dp; unsigned int gpgpu_operand_collector_num_out_ports_sfu; unsigned int gpgpu_operand_collector_num_out_ports_tensor_core; unsigned int gpgpu_operand_collector_num_out_ports_mem; @@ -1368,6 +1431,7 @@ struct shader_core_config : public core_config int gpgpu_num_sp_units; int gpgpu_tensor_core_avail; + int gpgpu_num_dp_units; int gpgpu_num_sfu_units; int gpgpu_num_tensor_core_units; int gpgpu_num_mem_units; @@ -1379,6 +1443,7 @@ struct shader_core_config : public core_config unsigned gpgpu_num_reg_banks; bool gpgpu_reg_bank_use_warp_id; bool gpgpu_local_mem_map; + bool gpgpu_ignore_resources_limitation; unsigned max_sp_latency; unsigned max_sfu_latency; @@ -1391,10 +1456,14 @@ struct shader_core_config : public core_config int simt_core_sim_order; + unsigned smem_latency; + unsigned mem2device(unsigned memid) const { return memid + n_simt_clusters; } //Jin: concurrent kernel on sm bool gpgpu_concurrent_kernel_sm; + + bool adpative_volta_cache_config; }; struct shader_core_stats_pod { @@ -1457,6 +1526,8 @@ struct shader_core_stats_pod { unsigned *last_shader_cycle_distro; unsigned *num_warps_issuable; unsigned gpgpu_n_stall_shd_mem; + unsigned* single_issue_nums; + unsigned* dual_issue_nums; //memory access classification int gpgpu_n_mem_read_local; @@ -1528,6 +1599,8 @@ public: m_n_diverge = (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); shader_cycle_distro = (unsigned*) calloc(config->warp_size+3, sizeof(unsigned)); last_shader_cycle_distro = (unsigned*) calloc(m_config->warp_size+3, sizeof(unsigned)); + single_issue_nums = (unsigned*) calloc(config->gpgpu_num_sched_per_core,sizeof(unsigned)); + dual_issue_nums = (unsigned*) calloc(config->gpgpu_num_sched_per_core, sizeof(unsigned)); n_simt_to_mem = (long *)calloc(config->num_shader(), sizeof(long)); n_mem_to_simt = (long *)calloc(config->num_shader(), sizeof(long)); @@ -1651,6 +1724,7 @@ public: void issue_block2core( class kernel_info_t &kernel ); void cache_flush(); + void cache_invalidate(); void accept_fetch_response( mem_fetch *mf ); void accept_ldst_unit_response( class mem_fetch * mf ); void broadcast_barrier_reduction(unsigned cta_id, unsigned bar_id,warp_set_t warps); @@ -1679,6 +1753,7 @@ public: // accessors virtual bool warp_waiting_at_barrier( unsigned warp_id ) const; void get_pdom_stack_top_info( unsigned tid, unsigned *pc, unsigned *rpc ) const; + float get_current_occupancy( unsigned long long & active, unsigned long long & total ) const; // used by pipeline timing model components: // modifiers @@ -1885,10 +1960,14 @@ public: std::vector m_pipeline_reg; Scoreboard *m_scoreboard; opndcoll_rfu_t m_operand_collector; + int m_active_warps; //schedule std::vector schedulers; + //issue + unsigned int Issue_Prio; + // execute unsigned m_num_function_units; std::vector m_dispatch_port; @@ -1940,6 +2019,7 @@ public: void reinit(); unsigned issue_block2core(); void cache_flush(); + void cache_invalidate(); bool icnt_injection_buffer_full(unsigned size, bool write); void icnt_inject_request_packet(class mem_fetch *mf); @@ -1970,6 +2050,7 @@ public: void get_L1T_sub_stats(struct cache_sub_stats &css) const; void get_icnt_stats(long &n_simt_to_mem, long &n_mem_to_simt) const; + float get_current_occupancy( unsigned long long& active, unsigned long long & total ) const; private: unsigned m_cluster_id; diff --git a/src/gpgpusim_entrypoint.cc b/src/gpgpusim_entrypoint.cc index ede9f20..52e2f5e 100644 --- a/src/gpgpusim_entrypoint.cc +++ b/src/gpgpusim_entrypoint.cc @@ -172,6 +172,7 @@ void *gpgpu_sim_thread_concurrent(void*) g_sim_active = false; pthread_mutex_unlock(&g_sim_lock); } while( !g_sim_done ); + printf("GPGPU-Sim: *** simulation thread exiting ***\n"); fflush(stdout); diff --git a/src/gpuwattch/makefile b/src/gpuwattch/makefile index ab718cc..354c9ec 100644 --- a/src/gpuwattch/makefile +++ b/src/gpuwattch/makefile @@ -11,10 +11,10 @@ opt: $(TAR).mk obj_opt @$(MAKE) TAG=opt -C . -f $(TAR).mk obj_dbg: - mkdir $@ + mkdir -p $@ obj_opt: - mkdir $@ + mkdir -p $@ depend: @$(MAKE) TAG=opt -C . -f $(TAR).mk depend diff --git a/src/intersim2/Makefile b/src/intersim2/Makefile index bd42000..7d10b3f 100644 --- a/src/intersim2/Makefile +++ b/src/intersim2/Makefile @@ -36,7 +36,7 @@ DEBUG ?= 0 LEX = flex YACC = bison -y DEFINE = #-DTRACK_STALLS -DTRACK_BUFFERS -DTRACK_FLOWS -DTRACK_CREDITS -INCPATH = -I. -Iarbiters -Iallocators -Irouters -Inetworks -Ipower +INCPATH = -I. -Iarbiters -Iallocators -Irouters -Inetworks -Ipower -I$(GPGPUSIM_ROOT)/src ifeq ($(CREATE_LIBRARY),1) INCPATH += -I$(GPGPUSIM_ROOT)/src/gpgpu-sim/ diff --git a/src/intersim2/interconnect_interface.cpp b/src/intersim2/interconnect_interface.cpp index 4386821..1e1a2d7 100644 --- a/src/intersim2/interconnect_interface.cpp +++ b/src/intersim2/interconnect_interface.cpp @@ -44,6 +44,7 @@ #include "booksim.hpp" #include "intersim_config.hpp" #include "network.hpp" +#include "trace.h" InterconnectInterface* InterconnectInterface::New(const char* const config_file) { @@ -147,6 +148,8 @@ void InterconnectInterface::Push(unsigned input_deviceID, unsigned output_device { // it should have free buffer assert(HasBuffer(input_deviceID, size)); + + DPRINTF(INTERCONNECT, "Sent %d bytes from %d to %d", size, input_deviceID, output_deviceID); int output_icntID = _node_map[output_deviceID]; int input_icntID = _node_map[input_deviceID]; @@ -178,7 +181,11 @@ void InterconnectInterface::Push(unsigned input_deviceID, unsigned output_device case WRITE_REQUEST: packet_type = Flit::WRITE_REQUEST ;break; case READ_REPLY: packet_type = Flit::READ_REPLY ;break; case WRITE_ACK: packet_type = Flit::WRITE_REPLY ;break; - default: assert (0); + default: + { + cout<<"Type "<get_type()<<" is undefined!"< Date: Mon, 5 Nov 2018 20:01:42 -0500 Subject: adding Volta sub_core model and double L1 BW --- configs/tested-cfgs/SM7_TITANV/gpgpusim.config | 29 ++--- src/abstract_hardware_model.h | 20 ++- src/gpgpu-sim/gpu-sim.cc | 11 +- src/gpgpu-sim/shader.cc | 161 +++++++++++++++---------- src/gpgpu-sim/shader.h | 36 ++++-- 5 files changed, 168 insertions(+), 89 deletions(-) (limited to 'src/abstract_hardware_model.h') diff --git a/configs/tested-cfgs/SM7_TITANV/gpgpusim.config b/configs/tested-cfgs/SM7_TITANV/gpgpusim.config index 03ef5b9..2093cc0 100644 --- a/configs/tested-cfgs/SM7_TITANV/gpgpusim.config +++ b/configs/tested-cfgs/SM7_TITANV/gpgpusim.config @@ -42,9 +42,9 @@ # Pipeline widths and number of FUs # ID_OC_SP,ID_OC_DP,ID_OC_SFU,ID_OC_MEM,OC_EX_SP,OC_EX_DP,OC_EX_SFU,OC_EX_MEM,EX_WB -## Volta GV100 has 2 SP SIMD units, 2 SFU units, 2 DP units per core +## Volta GV100 has 4 SP SIMD units, 4SFU units, 4 DP units per core ## we need to scale the number of pipeline registers to be equal to the number of SP units --gpgpu_pipeline_widths 4,4,4,4,4,4,4,4,12 +-gpgpu_pipeline_widths 4,4,4,4,4,4,4,4,8 -gpgpu_num_sp_units 4 -gpgpu_num_sfu_units 4 -gpgpu_num_dp_units 4 @@ -72,6 +72,8 @@ # For more info, see https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#shared-memory-7-x # disable this mode in case of multi kernels/apps execution -adpative_volta_cache_config 1 +# Volta unified cache has four ports +-mem_unit_ports 4 -gpgpu_cache:dl1 S:4:128:64,L:L:s:N:L,A:256:8,16:0,32 -gpgpu_shmem_size 98304 -gmem_skip_L1D 0 @@ -96,20 +98,15 @@ # 64 KB Const -gpgpu_const_cache:l1 N:128:64:8,L:R:f:N:L,S:2:64,4 -# enable operand collector --gpgpu_operand_collector_num_units_sp 12 --gpgpu_operand_collector_num_units_sfu 6 --gpgpu_operand_collector_num_units_mem 8 --gpgpu_operand_collector_num_units_dp 6 --gpgpu_operand_collector_num_in_ports_sp 4 --gpgpu_operand_collector_num_out_ports_sp 4 --gpgpu_operand_collector_num_in_ports_sfu 1 --gpgpu_operand_collector_num_out_ports_sfu 1 --gpgpu_operand_collector_num_in_ports_mem 1 --gpgpu_operand_collector_num_out_ports_mem 1 --gpgpu_operand_collector_num_in_ports_dp 1 --gpgpu_operand_collector_num_out_ports_dp 1 -# two banks per scheduler +# Volta has sub core model, in which each scheduler has its own reisiter file and EUs +# i.e. schedulers are isolated +-sub_core_model 1 +# disable specialized operand collectors and use generic operand collectors instead +-enable_specialized_operand_collector 0 +-gpgpu_operand_collector_num_units_gen 8 +-gpgpu_operand_collector_num_in_ports_gen 8 +-gpgpu_operand_collector_num_out_ports_gen 8 +# volta has 8 banks, 4 schedulers, two banks per scheduler -gpgpu_num_reg_banks 8 # shared memory bankconflict detection diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index 8333247..d0f7066 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -336,6 +336,7 @@ struct core_config { unsigned gpgpu_shmem_sizeDefault; unsigned gpgpu_shmem_sizePrefL1; unsigned gpgpu_shmem_sizePrefShared; + unsigned mem_unit_ports; // texture and constant cache line sizes (used to determine number of memory accesses) unsigned gpgpu_cache_texl1_linesize; @@ -908,7 +909,7 @@ public: { m_empty=true; } - void issue( const active_mask_t &mask, unsigned warp_id, unsigned long long cycle, int dynamic_warp_id ) + void issue( const active_mask_t &mask, unsigned warp_id, unsigned long long cycle, int dynamic_warp_id, int sch_id ) { m_warp_active_mask = mask; m_warp_issued_mask = mask; @@ -919,6 +920,7 @@ public: cycles = initiation_interval; m_cache_hit=false; m_empty=false; + m_scheduler_id=sch_id; } const active_mask_t & get_active_mask() const { @@ -1037,6 +1039,7 @@ public: void print( FILE *fout ) const; unsigned get_uid() const { return m_uid; } + unsigned get_schd_id() const { return m_scheduler_id; } protected: @@ -1069,6 +1072,8 @@ protected: static unsigned sm_next_uid; + unsigned m_scheduler_id; //the scheduler that issues this inst + //Jin: cdp support public: int m_is_cdp; @@ -1161,6 +1166,10 @@ public: } return false; } + bool has_free(unsigned reg_id){ + assert(reg_id < regs.size()); + return regs[reg_id]->empty(); + } bool has_ready(){ for( unsigned i = 0; i < regs.size(); i++ ) { if( not regs[i]->empty() ) { @@ -1216,6 +1225,15 @@ public: return NULL; } + warp_inst_t ** get_free(unsigned reg_id){ + assert(reg_id < regs.size()); + if( regs[reg_id]->empty() ) { + return ®s[reg_id]; + } + assert(0 && "No free register found"); + return NULL; + } + private: std::vector regs; const char* m_name; diff --git a/src/gpgpu-sim/gpu-sim.cc b/src/gpgpu-sim/gpu-sim.cc index 8bbadf5..f318f7d 100644 --- a/src/gpgpu-sim/gpu-sim.cc +++ b/src/gpgpu-sim/gpu-sim.cc @@ -329,6 +329,9 @@ void shader_core_config::reg_options(class OptionParser * opp) option_parser_register(opp, "-gpgpu_shmem_warp_parts", OPT_INT32, &mem_warp_parts, "Number of portions a warp is divided into for shared memory bank conflict check ", "2"); + option_parser_register(opp, "-mem_unit_ports", OPT_INT32, &mem_unit_ports, + "The number of memory transactions allowed per core cycle", + "1"); option_parser_register(opp, "-gpgpu_shmem_warp_parts", OPT_INT32, &mem_warp_parts, "Number of portions a warp is divided into for shared memory bank conflict check ", "2"); @@ -347,8 +350,14 @@ void shader_core_config::reg_options(class OptionParser * opp) option_parser_register(opp, "-gpgpu_reg_bank_use_warp_id", OPT_BOOL, &gpgpu_reg_bank_use_warp_id, "Use warp ID in mapping registers to banks (default = off)", "0"); + option_parser_register(opp, "-sub_core_model", OPT_BOOL, &sub_core_model, + "Sub Core Volta/Pascal model (default = off)", + "0"); + option_parser_register(opp, "-enable_specialized_operand_collector", OPT_BOOL, &enable_specialized_operand_collector, + "enable_specialized_operand_collector", + "1"); option_parser_register(opp, "-gpgpu_operand_collector_num_units_sp", OPT_INT32, &gpgpu_operand_collector_num_units_sp, - "number of collector units (default = 4)", + "number of collector units (default = 4)", "4"); option_parser_register(opp, "-gpgpu_operand_collector_num_units_dp", OPT_INT32, &gpgpu_operand_collector_num_units_dp, "number of collector units (default = 0)", diff --git a/src/gpgpu-sim/shader.cc b/src/gpgpu-sim/shader.cc index 8a84970..300871e 100644 --- a/src/gpgpu-sim/shader.cc +++ b/src/gpgpu-sim/shader.cc @@ -234,52 +234,12 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, //op collector configuration enum { SP_CUS, DP_CUS, SFU_CUS, MEM_CUS, GEN_CUS }; - m_operand_collector.add_cu_set(SP_CUS, m_config->gpgpu_operand_collector_num_units_sp, m_config->gpgpu_operand_collector_num_out_ports_sp); - m_operand_collector.add_cu_set(DP_CUS, m_config->gpgpu_operand_collector_num_units_dp, m_config->gpgpu_operand_collector_num_out_ports_dp); - m_operand_collector.add_cu_set(SFU_CUS, m_config->gpgpu_operand_collector_num_units_sfu, m_config->gpgpu_operand_collector_num_out_ports_sfu); - m_operand_collector.add_cu_set(MEM_CUS, m_config->gpgpu_operand_collector_num_units_mem, m_config->gpgpu_operand_collector_num_out_ports_mem); - m_operand_collector.add_cu_set(GEN_CUS, m_config->gpgpu_operand_collector_num_units_gen, m_config->gpgpu_operand_collector_num_out_ports_gen); - opndcoll_rfu_t::port_vector_t in_ports; opndcoll_rfu_t::port_vector_t out_ports; opndcoll_rfu_t::uint_vector_t cu_sets; - for (unsigned i = 0; i < m_config->gpgpu_operand_collector_num_in_ports_sp; i++) { - in_ports.push_back(&m_pipeline_reg[ID_OC_SP]); - out_ports.push_back(&m_pipeline_reg[OC_EX_SP]); - cu_sets.push_back((unsigned)SP_CUS); - cu_sets.push_back((unsigned)GEN_CUS); - m_operand_collector.add_port(in_ports,out_ports,cu_sets); - in_ports.clear(),out_ports.clear(),cu_sets.clear(); - } - - for (unsigned i = 0; i < m_config->gpgpu_operand_collector_num_in_ports_dp; i++) { - in_ports.push_back(&m_pipeline_reg[ID_OC_DP]); - out_ports.push_back(&m_pipeline_reg[OC_EX_DP]); - cu_sets.push_back((unsigned)DP_CUS); - cu_sets.push_back((unsigned)GEN_CUS); - m_operand_collector.add_port(in_ports,out_ports,cu_sets); - in_ports.clear(),out_ports.clear(),cu_sets.clear(); - } - for (unsigned i = 0; i < m_config->gpgpu_operand_collector_num_in_ports_sfu; i++) { - in_ports.push_back(&m_pipeline_reg[ID_OC_SFU]); - out_ports.push_back(&m_pipeline_reg[OC_EX_SFU]); - cu_sets.push_back((unsigned)SFU_CUS); - cu_sets.push_back((unsigned)GEN_CUS); - m_operand_collector.add_port(in_ports,out_ports,cu_sets); - in_ports.clear(),out_ports.clear(),cu_sets.clear(); - } - - for (unsigned i = 0; i < m_config->gpgpu_operand_collector_num_in_ports_mem; i++) { - in_ports.push_back(&m_pipeline_reg[ID_OC_MEM]); - out_ports.push_back(&m_pipeline_reg[OC_EX_MEM]); - cu_sets.push_back((unsigned)MEM_CUS); - cu_sets.push_back((unsigned)GEN_CUS); - m_operand_collector.add_port(in_ports,out_ports,cu_sets); - in_ports.clear(),out_ports.clear(),cu_sets.clear(); - } - - + //configure generic collectors + m_operand_collector.add_cu_set(GEN_CUS, m_config->gpgpu_operand_collector_num_units_gen, m_config->gpgpu_operand_collector_num_out_ports_gen); for (unsigned i = 0; i < m_config->gpgpu_operand_collector_num_in_ports_gen; i++) { in_ports.push_back(&m_pipeline_reg[ID_OC_SP]); in_ports.push_back(&m_pipeline_reg[ID_OC_SFU]); @@ -287,10 +247,57 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, out_ports.push_back(&m_pipeline_reg[OC_EX_SP]); out_ports.push_back(&m_pipeline_reg[OC_EX_SFU]); out_ports.push_back(&m_pipeline_reg[OC_EX_MEM]); - cu_sets.push_back((unsigned)GEN_CUS); + if(m_config->gpgpu_num_dp_units > 0) { + in_ports.push_back(&m_pipeline_reg[ID_OC_DP]); + out_ports.push_back(&m_pipeline_reg[OC_EX_DP]); + } + cu_sets.push_back((unsigned)GEN_CUS); m_operand_collector.add_port(in_ports,out_ports,cu_sets); in_ports.clear(),out_ports.clear(),cu_sets.clear(); } + + if(m_config->enable_specialized_operand_collector) { + m_operand_collector.add_cu_set(SP_CUS, m_config->gpgpu_operand_collector_num_units_sp, m_config->gpgpu_operand_collector_num_out_ports_sp); + m_operand_collector.add_cu_set(DP_CUS, m_config->gpgpu_operand_collector_num_units_dp, m_config->gpgpu_operand_collector_num_out_ports_dp); + m_operand_collector.add_cu_set(SFU_CUS, m_config->gpgpu_operand_collector_num_units_sfu, m_config->gpgpu_operand_collector_num_out_ports_sfu); + m_operand_collector.add_cu_set(MEM_CUS, m_config->gpgpu_operand_collector_num_units_mem, m_config->gpgpu_operand_collector_num_out_ports_mem); + + for (unsigned i = 0; i < m_config->gpgpu_operand_collector_num_in_ports_sp; i++) { + in_ports.push_back(&m_pipeline_reg[ID_OC_SP]); + out_ports.push_back(&m_pipeline_reg[OC_EX_SP]); + cu_sets.push_back((unsigned)SP_CUS); + cu_sets.push_back((unsigned)GEN_CUS); + m_operand_collector.add_port(in_ports,out_ports,cu_sets); + in_ports.clear(),out_ports.clear(),cu_sets.clear(); + } + + for (unsigned i = 0; i < m_config->gpgpu_operand_collector_num_in_ports_dp; i++) { + in_ports.push_back(&m_pipeline_reg[ID_OC_DP]); + out_ports.push_back(&m_pipeline_reg[OC_EX_DP]); + cu_sets.push_back((unsigned)DP_CUS); + cu_sets.push_back((unsigned)GEN_CUS); + m_operand_collector.add_port(in_ports,out_ports,cu_sets); + in_ports.clear(),out_ports.clear(),cu_sets.clear(); + } + + for (unsigned i = 0; i < m_config->gpgpu_operand_collector_num_in_ports_sfu; i++) { + in_ports.push_back(&m_pipeline_reg[ID_OC_SFU]); + out_ports.push_back(&m_pipeline_reg[OC_EX_SFU]); + cu_sets.push_back((unsigned)SFU_CUS); + cu_sets.push_back((unsigned)GEN_CUS); + m_operand_collector.add_port(in_ports,out_ports,cu_sets); + in_ports.clear(),out_ports.clear(),cu_sets.clear(); + } + + for (unsigned i = 0; i < m_config->gpgpu_operand_collector_num_in_ports_mem; i++) { + in_ports.push_back(&m_pipeline_reg[ID_OC_MEM]); + out_ports.push_back(&m_pipeline_reg[OC_EX_MEM]); + cu_sets.push_back((unsigned)MEM_CUS); + cu_sets.push_back((unsigned)GEN_CUS); + m_operand_collector.add_port(in_ports,out_ports,cu_sets); + in_ports.clear(),out_ports.clear(),cu_sets.clear(); + } + } m_operand_collector.init( m_config->gpgpu_num_reg_banks, this ); @@ -761,15 +768,19 @@ void shader_core_ctx::func_exec_inst( warp_inst_t &inst ) inst.generate_mem_accesses(); } -void shader_core_ctx::issue_warp( register_set& pipe_reg_set, const warp_inst_t* next_inst, const active_mask_t &active_mask, unsigned warp_id ) +void shader_core_ctx::issue_warp( register_set& pipe_reg_set, const warp_inst_t* next_inst, const active_mask_t &active_mask, unsigned warp_id, unsigned sch_id ) { - warp_inst_t** pipe_reg = pipe_reg_set.get_free(); + warp_inst_t** pipe_reg; + if(m_config->sub_core_model) + pipe_reg = pipe_reg_set.get_free(sch_id); + else + pipe_reg = pipe_reg_set.get_free(); assert(pipe_reg); m_warp[warp_id].ibuffer_free(); assert(next_inst->valid()); **pipe_reg = *next_inst; // static instruction information - (*pipe_reg)->issue( active_mask, warp_id, gpu_tot_sim_cycle + gpu_sim_cycle, m_warp[warp_id].get_dynamic_warp_id() ); // dynamic instruction information + (*pipe_reg)->issue( active_mask, warp_id, gpu_tot_sim_cycle + gpu_sim_cycle, m_warp[warp_id].get_dynamic_warp_id(), sch_id ); // dynamic instruction information m_stats->shader_cycle_distro[2+(*pipe_reg)->active_count()]++; func_exec_inst( **pipe_reg ); if( next_inst->op == BARRIER_OP ){ @@ -950,8 +961,8 @@ void scheduler_unit::cycle() const active_mask_t &active_mask = m_simt_stack[warp_id]->get_active_mask(); assert( warp(warp_id).inst_in_pipeline() ); if ( (pI->op == LOAD_OP) || (pI->op == STORE_OP) || (pI->op == MEMORY_BARRIER_OP) ) { - if( m_mem_out->has_free() && (!diff_exec_units || previous_issued_inst_exec_type != exec_unit_type_t::MEM)) { - m_shader->issue_warp(*m_mem_out,pI,active_mask,warp_id); + if( m_mem_out->has_free(m_id) && (!diff_exec_units || previous_issued_inst_exec_type != exec_unit_type_t::MEM)) { + m_shader->issue_warp(*m_mem_out,pI,active_mask,warp_id,m_id); issued++; issued_inst=true; warp_inst_issued = true; @@ -959,9 +970,9 @@ void scheduler_unit::cycle() } } else { - bool sp_pipe_avail = m_sp_out->has_free(); - bool sfu_pipe_avail = m_sfu_out->has_free(); - bool dp_pipe_avail = m_dp_out->has_free(); + bool sp_pipe_avail = m_sp_out->has_free(m_id); + bool sfu_pipe_avail = m_sfu_out->has_free(m_id); + bool dp_pipe_avail = m_dp_out->has_free(m_id); if( sp_pipe_avail && (pI->op != SFU_OP && pI->op != DP_OP) && (!diff_exec_units || previous_issued_inst_exec_type != exec_unit_type_t::SP)) { //Jin: special for CDP api @@ -983,14 +994,14 @@ void scheduler_unit::cycle() } // 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); + m_shader->issue_warp(*m_sp_out,pI,active_mask,warp_id,m_id); issued++; issued_inst=true; warp_inst_issued = true; previous_issued_inst_exec_type = exec_unit_type_t::SP; } else if ( (m_shader->m_config->gpgpu_num_dp_units != 0) && (pI->op == DP_OP) && (!diff_exec_units || previous_issued_inst_exec_type != exec_unit_type_t::DP)) { if( dp_pipe_avail ) { - m_shader->issue_warp(*m_dp_out,pI,active_mask,warp_id); + m_shader->issue_warp(*m_dp_out,pI,active_mask,warp_id,m_id); issued++; issued_inst=true; warp_inst_issued = true; @@ -999,7 +1010,7 @@ void scheduler_unit::cycle() } //If the DP units = 0 (like in Fermi archi), then change DP inst to SFU inst else if ( ((m_shader->m_config->gpgpu_num_dp_units == 0 && pI->op == DP_OP) || (pI->op == SFU_OP) || (pI->op == ALU_SFU_OP)) && (!diff_exec_units || previous_issued_inst_exec_type != exec_unit_type_t::SFU)) { if( sfu_pipe_avail ) { - m_shader->issue_warp(*m_sfu_out,pI,active_mask,warp_id); + m_shader->issue_warp(*m_sfu_out,pI,active_mask,warp_id,m_id); issued++; issued_inst=true; warp_inst_issued = true; @@ -2068,7 +2079,11 @@ void ldst_unit::writeback() unsigned ldst_unit::clock_multiplier() const { - return m_config->mem_warp_parts; + //to model multiple read port, we give multiple cycles for the memory units + if(m_config->mem_unit_ports) + return m_config->mem_unit_ports; + else + return m_config->mem_warp_parts; } /* void ldst_unit::issue( register_set ®_set ) @@ -3305,18 +3320,34 @@ void opndcoll_rfu_t::init( unsigned num_banks, shader_core_ctx *shader ) m_bank_warp_shift = (unsigned)(int) (log(m_warp_size+0.5) / log(2.0)); assert( (m_bank_warp_shift == 5) || (m_warp_size != 32) ); + sub_core_model = shader->get_config()->sub_core_model; + m_num_warp_sceds = shader->get_config()->gpgpu_num_sched_per_core; + if(sub_core_model) + assert(num_banks % shader->get_config()->gpgpu_num_sched_per_core == 0); + m_num_banks_per_sched = num_banks / shader->get_config()->gpgpu_num_sched_per_core; + for( unsigned j=0; jinit(j,num_banks,m_bank_warp_shift,shader->get_config(),this); + m_cu[j]->init(j,num_banks,m_bank_warp_shift,shader->get_config(),this, sub_core_model, m_num_banks_per_sched ); } m_initialized=true; + + + + } -int register_bank(int regnum, int wid, unsigned num_banks, unsigned bank_warp_shift) +int register_bank(int regnum, int wid, unsigned num_banks, unsigned bank_warp_shift, bool sub_core_model, unsigned banks_per_sched, unsigned sched_id) { int bank = regnum; if (bank_warp_shift) bank += wid; - return bank % num_banks; + if(sub_core_model) { + unsigned bank_num = (bank % banks_per_sched) + (sched_id * banks_per_sched); + assert(bank_num < num_banks); + return bank_num; + } + else + return bank % num_banks; } bool opndcoll_rfu_t::writeback( const warp_inst_t &inst ) @@ -3327,9 +3358,9 @@ bool opndcoll_rfu_t::writeback( const warp_inst_t &inst ) unsigned n=0; for( r=regs.begin(); r!=regs.end();r++,n++ ) { unsigned reg = *r; - unsigned bank = register_bank(reg,inst.warp_id(),m_num_banks,m_bank_warp_shift); + unsigned bank = register_bank(reg,inst.warp_id(),m_num_banks,m_bank_warp_shift, sub_core_model, m_num_banks_per_sched, inst.get_schd_id()); if( m_arbiter.bank_idle(bank) ) { - m_arbiter.allocate_bank_for_write(bank,op_t(&inst,reg,m_num_banks,m_bank_warp_shift)); + m_arbiter.allocate_bank_for_write(bank,op_t(&inst,reg,m_num_banks,m_bank_warp_shift, sub_core_model, m_num_banks_per_sched, inst.get_schd_id())); } else { return false; } @@ -3413,7 +3444,7 @@ void opndcoll_rfu_t::allocate_reads() const op_t &rr = *r; unsigned reg = rr.get_reg(); unsigned wid = rr.get_wid(); - unsigned bank = register_bank(reg,wid,m_num_banks,m_bank_warp_shift); + unsigned bank = register_bank(reg,wid,m_num_banks,m_bank_warp_shift,sub_core_model, m_num_banks_per_sched, rr.get_sid()); m_arbiter.allocate_for_read(bank,rr); read_ops[bank] = rr; } @@ -3464,7 +3495,9 @@ void opndcoll_rfu_t::collector_unit_t::init( unsigned n, unsigned num_banks, unsigned log2_warp_size, const core_config *config, - opndcoll_rfu_t *rfu ) + opndcoll_rfu_t *rfu, + bool sub_core_model, + unsigned banks_per_sched) { m_rfu=rfu; m_cuid=n; @@ -3472,6 +3505,8 @@ void opndcoll_rfu_t::collector_unit_t::init( unsigned n, assert(m_warp==NULL); m_warp = new warp_inst_t(config); m_bank_warp_shift=log2_warp_size; + m_sub_core_model = sub_core_model; + m_num_banks_per_sched = banks_per_sched; } bool opndcoll_rfu_t::collector_unit_t::allocate( register_set* pipeline_reg_set, register_set* output_reg_set ) @@ -3486,7 +3521,7 @@ bool opndcoll_rfu_t::collector_unit_t::allocate( register_set* pipeline_reg_set, for( unsigned op=0; op < MAX_REG_OPERANDS; op++ ) { int reg_num = (*pipeline_reg)->arch_reg.src[op]; // this math needs to match that used in function_info::ptx_decode_inst if( reg_num >= 0 ) { // valid register - m_src_op[op] = op_t( this, op, reg_num, m_num_banks, m_bank_warp_shift ); + m_src_op[op] = op_t( this, op, reg_num, m_num_banks, m_bank_warp_shift, m_sub_core_model, m_num_banks_per_sched, (*pipeline_reg)->get_schd_id() ); m_not_ready.set(op); } else m_src_op[op] = op_t(); diff --git a/src/gpgpu-sim/shader.h b/src/gpgpu-sim/shader.h index 4a87126..e6132f5 100644 --- a/src/gpgpu-sim/shader.h +++ b/src/gpgpu-sim/shader.h @@ -291,7 +291,7 @@ inline unsigned wid_from_hw_tid(unsigned tid, unsigned warp_size){return tid/war const unsigned WARP_PER_CTA_MAX = 64; typedef std::bitset warp_set_t; -int register_bank(int regnum, int wid, unsigned num_banks, unsigned bank_warp_shift); +int register_bank(int regnum, int wid, unsigned num_banks, unsigned bank_warp_shift, bool sub_core_model, unsigned banks_per_sched, unsigned sched_id ); class shader_core_ctx; struct shader_core_config; @@ -378,6 +378,8 @@ public: // m_supervised_warps with their scheduling policies virtual void order_warps() = 0; + int get_schd_id() const {return m_id;} + protected: virtual void do_on_warp_issued( unsigned warp_id, unsigned num_issued, @@ -601,23 +603,25 @@ private: public: op_t() { m_valid = false; } - op_t( collector_unit_t *cu, unsigned op, unsigned reg, unsigned num_banks, unsigned bank_warp_shift ) + op_t( collector_unit_t *cu, unsigned op, unsigned reg, unsigned num_banks, unsigned bank_warp_shift, bool sub_core_model, unsigned banks_per_sched, unsigned sched_id ) { m_valid = true; m_warp=NULL; m_cu = cu; m_operand = op; m_register = reg; - m_bank = register_bank(reg,cu->get_warp_id(),num_banks,bank_warp_shift); + m_shced_id = sched_id; + m_bank = register_bank(reg,cu->get_warp_id(),num_banks,bank_warp_shift, sub_core_model, banks_per_sched, sched_id); } - op_t( const warp_inst_t *warp, unsigned reg, unsigned num_banks, unsigned bank_warp_shift ) + op_t( const warp_inst_t *warp, unsigned reg, unsigned num_banks, unsigned bank_warp_shift, bool sub_core_model, unsigned banks_per_sched, unsigned sched_id ) { m_valid=true; m_warp=warp; m_register=reg; m_cu=NULL; m_operand = -1; - m_bank = register_bank(reg,warp->warp_id(),num_banks,bank_warp_shift); + m_shced_id = sched_id; + m_bank = register_bank(reg,warp->warp_id(),num_banks,bank_warp_shift, sub_core_model, banks_per_sched, sched_id); } // accessors @@ -633,6 +637,10 @@ private: else if( m_cu ) return m_cu->get_warp_id(); else abort(); } + unsigned get_sid() const + { + return m_shced_id; + } unsigned get_active_count() const { if( m_warp ) return m_warp->active_count(); @@ -677,6 +685,7 @@ private: unsigned m_operand; // operand offset in instruction. e.g., add r1,r2,r3; r2 is oprd 0, r3 is 1 (r1 is dst) unsigned m_register; unsigned m_bank; + unsigned m_shced_id; //scheduler id that has issued this inst }; enum alloc_t { @@ -697,7 +706,7 @@ private: else if( m_allocation == WRITE_ALLOC ) { fprintf(fp,"wr: "); m_op.dump(fp); } fprintf(fp,"\n"); } - void alloc_read( const op_t &op ) { assert(is_free()); m_allocation=READ_ALLOC; m_op=op; } + void alloc_read( const op_t &op ) { assert(is_free()); m_allocation=READ_ALLOC; m_op=op; } void alloc_write( const op_t &op ) { assert(is_free()); m_allocation=WRITE_ALLOC; m_op=op; } void reset() { m_allocation = NO_ALLOC; } private: @@ -851,7 +860,9 @@ private: unsigned num_banks, unsigned log2_warp_size, const core_config *config, - opndcoll_rfu_t *rfu ); + opndcoll_rfu_t *rfu, + bool m_sub_core_model, + unsigned num_banks_per_sched); bool allocate( register_set* pipeline_reg, register_set* output_reg ); void collect_operand( unsigned op ) @@ -879,6 +890,9 @@ private: unsigned m_bank_warp_shift; opndcoll_rfu_t *m_rfu; + unsigned m_num_banks_per_sched; + bool m_sub_core_model; + }; class dispatch_unit_t { @@ -921,6 +935,10 @@ private: std::vector m_cu; arbiter_t m_arbiter; + unsigned m_num_banks_per_sched; + unsigned m_num_warp_sceds; + bool sub_core_model; + //unsigned m_num_ports; //std::vector m_input; //std::vector m_output; @@ -1361,6 +1379,7 @@ struct shader_core_config : public core_config bool gpgpu_dual_issue_diff_exec_units; //op collector + bool enable_specialized_operand_collector; int gpgpu_operand_collector_num_units_sp; int gpgpu_operand_collector_num_units_dp; int gpgpu_operand_collector_num_units_sfu; @@ -1392,6 +1411,7 @@ struct shader_core_config : public core_config bool gpgpu_reg_bank_use_warp_id; bool gpgpu_local_mem_map; bool gpgpu_ignore_resources_limitation; + bool sub_core_model; unsigned max_sp_latency; unsigned max_sfu_latency; @@ -1848,7 +1868,7 @@ public: friend class scheduler_unit; //this is needed to use private issue warp. friend class TwoLevelScheduler; friend class LooseRoundRobbinScheduler; - void issue_warp( register_set& warp, const warp_inst_t *pI, const active_mask_t &active_mask, unsigned warp_id ); + void issue_warp( register_set& warp, const warp_inst_t *pI, const active_mask_t &active_mask, unsigned warp_id, unsigned sch_id ); void func_exec_inst( warp_inst_t &inst ); // Returns numbers of addresses in translated_addrs -- cgit v1.3 From 2823b21ea0b84555c0f0c9b8a6e02614bf80f941 Mon Sep 17 00:00:00 2001 From: Mahmoud Date: Mon, 5 Nov 2018 20:11:21 -0500 Subject: fixing subcore model bug --- src/abstract_hardware_model.h | 12 ++++++++++-- src/gpgpu-sim/shader.cc | 14 +++++--------- 2 files changed, 15 insertions(+), 11 deletions(-) (limited to 'src/abstract_hardware_model.h') diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index d0f7066..d123131 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -1166,7 +1166,11 @@ public: } return false; } - bool has_free(unsigned reg_id){ + bool has_free(bool sub_core_model, unsigned reg_id){ + //in subcore model, each sched has a one specific reg to use (based on sched id) + if(!sub_core_model) + return has_free(); + assert(reg_id < regs.size()); return regs[reg_id]->empty(); } @@ -1225,7 +1229,11 @@ public: return NULL; } - warp_inst_t ** get_free(unsigned reg_id){ + warp_inst_t ** get_free(bool sub_core_model, unsigned reg_id){ + //in subcore model, each sched has a one specific reg to use (based on sched id) + if(!sub_core_model) + return get_free(); + assert(reg_id < regs.size()); if( regs[reg_id]->empty() ) { return ®s[reg_id]; diff --git a/src/gpgpu-sim/shader.cc b/src/gpgpu-sim/shader.cc index 300871e..c610d49 100644 --- a/src/gpgpu-sim/shader.cc +++ b/src/gpgpu-sim/shader.cc @@ -770,11 +770,7 @@ void shader_core_ctx::func_exec_inst( warp_inst_t &inst ) void shader_core_ctx::issue_warp( register_set& pipe_reg_set, const warp_inst_t* next_inst, const active_mask_t &active_mask, unsigned warp_id, unsigned sch_id ) { - warp_inst_t** pipe_reg; - if(m_config->sub_core_model) - pipe_reg = pipe_reg_set.get_free(sch_id); - else - pipe_reg = pipe_reg_set.get_free(); + warp_inst_t** pipe_reg = pipe_reg = pipe_reg_set.get_free(m_config->sub_core_model, sch_id); assert(pipe_reg); m_warp[warp_id].ibuffer_free(); @@ -961,7 +957,7 @@ void scheduler_unit::cycle() const active_mask_t &active_mask = m_simt_stack[warp_id]->get_active_mask(); assert( warp(warp_id).inst_in_pipeline() ); if ( (pI->op == LOAD_OP) || (pI->op == STORE_OP) || (pI->op == MEMORY_BARRIER_OP) ) { - if( m_mem_out->has_free(m_id) && (!diff_exec_units || previous_issued_inst_exec_type != exec_unit_type_t::MEM)) { + if( m_mem_out->has_free(m_shader->m_config->sub_core_model, m_id) && (!diff_exec_units || previous_issued_inst_exec_type != exec_unit_type_t::MEM)) { m_shader->issue_warp(*m_mem_out,pI,active_mask,warp_id,m_id); issued++; issued_inst=true; @@ -970,9 +966,9 @@ void scheduler_unit::cycle() } } else { - bool sp_pipe_avail = m_sp_out->has_free(m_id); - bool sfu_pipe_avail = m_sfu_out->has_free(m_id); - bool dp_pipe_avail = m_dp_out->has_free(m_id); + bool sp_pipe_avail = m_sp_out->has_free(m_shader->m_config->sub_core_model, m_id); + bool sfu_pipe_avail = m_sfu_out->has_free(m_shader->m_config->sub_core_model, m_id); + bool dp_pipe_avail = m_dp_out->has_free(m_shader->m_config->sub_core_model, m_id); if( sp_pipe_avail && (pI->op != SFU_OP && pI->op != DP_OP) && (!diff_exec_units || previous_issued_inst_exec_type != exec_unit_type_t::SP)) { //Jin: special for CDP api -- cgit v1.3 From 7d42f5849aa1abb4f081803843ea78009d5b20ce Mon Sep 17 00:00:00 2001 From: Mahmoud Date: Tue, 6 Nov 2018 19:48:52 -0500 Subject: adding tensor cores config --- configs/tested-cfgs/SM7_TITANV/gpgpusim.config | 5 +++-- src/abstract_hardware_model.h | 4 ++++ src/gpgpu-sim/shader.cc | 11 ++++++++++- src/gpgpu-sim/shader.h | 4 ---- 4 files changed, 17 insertions(+), 7 deletions(-) (limited to 'src/abstract_hardware_model.h') diff --git a/configs/tested-cfgs/SM7_TITANV/gpgpusim.config b/configs/tested-cfgs/SM7_TITANV/gpgpusim.config index 5ac734d..7b0369a 100644 --- a/configs/tested-cfgs/SM7_TITANV/gpgpusim.config +++ b/configs/tested-cfgs/SM7_TITANV/gpgpusim.config @@ -12,7 +12,6 @@ -gpgpu_ptx_instruction_classification 0 -gpgpu_ptx_sim_mode 0 -gpgpu_ptx_force_max_capability 70 --gpgpu_tensor_core_avail 1 # SASS execution (only supported with CUDA >= 4.0) -gpgpu_ptx_convert_to_ptxplus 0 @@ -45,10 +44,12 @@ # ID_OC_SP,ID_OC_DP,ID_OC_SFU,ID_OC_MEM,OC_EX_SP,OC_EX_DP,OC_EX_SFU,OC_EX_MEM,EX_WB,ID_OC_TENSOR_CORE,OC_EX_TENSOR_CORE ## Volta GV100 has 4 SP SIMD units, 4 SFU units, 4 DP units per core ## we need to scale the number of pipeline registers to be equal to the number of SP units --gpgpu_pipeline_widths 4,4,4,4,4,4,4,4,8,1,1 +-gpgpu_pipeline_widths 4,4,4,4,4,4,4,4,8,4,4 -gpgpu_num_sp_units 4 -gpgpu_num_sfu_units 4 -gpgpu_num_dp_units 4 +-gpgpu_tensor_core_avail 1 +-gpgpu_num_tensor_core_units 4 # Instruction latencies and initiation intervals # "ADD,MAX,MUL,MAD,DIV" diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index 5543a71..edd48a1 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -1269,6 +1269,10 @@ public: return NULL; } + unsigned get_size(){ + return regs.size(); + } + private: std::vector regs; const char* m_name; diff --git a/src/gpgpu-sim/shader.cc b/src/gpgpu-sim/shader.cc index 78facbd..c52ba35 100644 --- a/src/gpgpu-sim/shader.cc +++ b/src/gpgpu-sim/shader.cc @@ -90,6 +90,15 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, for (int j = 0; jpipe_widths[j],pipeline_stage_name_decode[j])); } + if(m_config->sub_core_model) { + //in subcore model, each scheduler should has its own issue register, so num scheduler = reg width + assert(m_config->gpgpu_num_sched_per_core == m_pipeline_reg[ID_OC_SP].get_size() ); + if(m_config->gpgpu_num_dp_units > 0) + assert(m_config->gpgpu_num_sched_per_core == m_pipeline_reg[ID_OC_DP].get_size() ); + assert(m_config->gpgpu_num_sched_per_core == m_pipeline_reg[ID_OC_SFU].get_size() ); + assert(m_config->gpgpu_num_sched_per_core == m_pipeline_reg[ID_OC_MEM].get_size() ); + assert(m_config->gpgpu_num_sched_per_core == m_pipeline_reg[ID_OC_TENSOR_CORE].get_size() ); + } m_threadState = (thread_ctx_t*) calloc(sizeof(thread_ctx_t), config->n_thread_per_shader); @@ -1045,7 +1054,7 @@ void scheduler_unit::cycle() } else if ( (pI->op == TENSOR_CORE_OP) ) { if( tensor_core_pipe_avail ) { - m_shader->issue_warp(*m_tensor_core_out,pI,active_mask,warp_id); + m_shader->issue_warp(*m_tensor_core_out,pI,active_mask,warp_id,m_id); issued++; issued_inst=true; warp_inst_issued = true; diff --git a/src/gpgpu-sim/shader.h b/src/gpgpu-sim/shader.h index fcd134d..7b33c14 100644 --- a/src/gpgpu-sim/shader.h +++ b/src/gpgpu-sim/shader.h @@ -1378,10 +1378,6 @@ struct shader_core_config : public core_config max_sp_latency = 32; max_tensor_core_latency = 64; - gpgpu_num_tensor_core_units=4;//It will be (#TENSORCORE INSIDE SM)/2 (One warp is allocated to 2 Tensor Core) - gpgpu_operand_collector_num_units_tensor_core=24; - gpgpu_operand_collector_num_in_ports_tensor_core=8; - gpgpu_operand_collector_num_out_ports_tensor_core=8; m_L1I_config.init(m_L1I_config.m_config_string,FuncCachePreferNone); m_L1T_config.init(m_L1T_config.m_config_string,FuncCachePreferNone); -- cgit v1.3 From 111cca2a061fe4f247be930cb44fdcdaec2b59f5 Mon Sep 17 00:00:00 2001 From: Mahmoud Date: Wed, 7 Nov 2018 20:30:02 -0500 Subject: Adding INT unit, fixing tensor core latency, updating config files --- configs/tested-cfgs/SM2_GTX480/gpgpusim.config | 7 +- configs/tested-cfgs/SM6_TITANX/gpgpusim.config | 7 +- configs/tested-cfgs/SM7_TITANV/gpgpusim.config | 8 +- src/abstract_hardware_model.h | 3 + src/cuda-sim/cuda-sim.cc | 35 ++++-- src/gpgpu-sim/gpu-sim.cc | 16 ++- src/gpgpu-sim/shader.cc | 165 +++++++++++++++++++------ src/gpgpu-sim/shader.h | 57 +++++++-- 8 files changed, 232 insertions(+), 66 deletions(-) (limited to 'src/abstract_hardware_model.h') diff --git a/configs/tested-cfgs/SM2_GTX480/gpgpusim.config b/configs/tested-cfgs/SM2_GTX480/gpgpusim.config index 4096b09..d71b2fd 100644 --- a/configs/tested-cfgs/SM2_GTX480/gpgpusim.config +++ b/configs/tested-cfgs/SM2_GTX480/gpgpusim.config @@ -30,9 +30,10 @@ -gpgpu_simd_model 1 # Pipeline widths and number of FUs -# ID_OC_SP,ID_OC_DP,ID_OC_SFU,ID_OC_MEM,OC_EX_SP,OC_EX_DP,OC_EX_SFU,OC_EX_MEM,EX_WB -#For Fermi, DP unit =0, DP inst is executed on SFU --gpgpu_pipeline_widths 2,0,1,1,2,0,1,1,2 +# ID_OC_SP,ID_OC_DP,ID_OC_INT,ID_OC_SFU,ID_OC_MEM,OC_EX_SP,OC_EX_DP,OC_EX_INT,OC_EX_SFU,OC_EX_MEM,EX_WB +# For Fermi, DP unit =0, DP inst is executed on SFU +# For Fermi, INT unit =0, INT inst is executed on SP +-gpgpu_pipeline_widths 2,0,0,1,1,2,0,0,1,1,2 -gpgpu_num_sp_units 2 -gpgpu_num_sfu_units 1 -gpgpu_num_dp_units 0 diff --git a/configs/tested-cfgs/SM6_TITANX/gpgpusim.config b/configs/tested-cfgs/SM6_TITANX/gpgpusim.config index ed35531..cb23ab3 100644 --- a/configs/tested-cfgs/SM6_TITANX/gpgpusim.config +++ b/configs/tested-cfgs/SM6_TITANX/gpgpusim.config @@ -35,10 +35,11 @@ -gpgpu_simd_model 1 # Pipeline widths and number of FUs -# ID_OC_SP,ID_OC_DP,ID_OC_SFU,ID_OC_MEM,OC_EX_SP,OC_EX_DP,OC_EX_SFU,OC_EX_MEM,EX_WB -## Pascal GP102 has 4 SP SIMD units and 4 SFU units +# ID_OC_SP,ID_OC_DP,ID_OC_INT,ID_OC_SFU,ID_OC_MEM,OC_EX_SP,OC_EX_DP,OC_EX_INT,OC_EX_SFU,OC_EX_MEM,EX_WB +## Pascal GP102 has 4 SP SIMD units and 4 SFU units per SM. In this config, we split SM into two shader cores, each has 2 SPs and 2 SFUs +# There is no int unit in Pascal ## we need to scale the number of pipeline registers to be equal to the number of SP units --gpgpu_pipeline_widths 2,1,2,1,2,1,2,1,5 +-gpgpu_pipeline_widths 2,1,0,2,1,2,1,0,2,1,5 -gpgpu_num_sp_units 2 -gpgpu_num_sfu_units 2 -gpgpu_num_dp_units 1 diff --git a/configs/tested-cfgs/SM7_TITANV/gpgpusim.config b/configs/tested-cfgs/SM7_TITANV/gpgpusim.config index 7b0369a..e143f31 100644 --- a/configs/tested-cfgs/SM7_TITANV/gpgpusim.config +++ b/configs/tested-cfgs/SM7_TITANV/gpgpusim.config @@ -41,13 +41,14 @@ -gpgpu_simd_model 1 # Pipeline widths and number of FUs -# ID_OC_SP,ID_OC_DP,ID_OC_SFU,ID_OC_MEM,OC_EX_SP,OC_EX_DP,OC_EX_SFU,OC_EX_MEM,EX_WB,ID_OC_TENSOR_CORE,OC_EX_TENSOR_CORE +# ID_OC_SP,ID_OC_DP,ID_OC_INT,ID_OC_SFU,ID_OC_MEM,OC_EX_SP,OC_EX_DP,OC_EX_INT,OC_EX_SFU,OC_EX_MEM,EX_WB,ID_OC_TENSOR_CORE,OC_EX_TENSOR_CORE ## Volta GV100 has 4 SP SIMD units, 4 SFU units, 4 DP units per core ## we need to scale the number of pipeline registers to be equal to the number of SP units --gpgpu_pipeline_widths 4,4,4,4,4,4,4,4,8,4,4 +-gpgpu_pipeline_widths 4,4,4,4,4,4,4,4,4,4,8,4,4 -gpgpu_num_sp_units 4 -gpgpu_num_sfu_units 4 -gpgpu_num_dp_units 4 +-gpgpu_num_int_units 4 -gpgpu_tensor_core_avail 1 -gpgpu_num_tensor_core_units 4 @@ -64,7 +65,8 @@ -ptx_opcode_initiation_dp 4,4,4,4,130 -ptx_opcode_latency_sfu 100 -ptx_opcode_initiation_sfu 8 - +-ptx_opcode_latency_tesnor 64 +-ptx_opcode_initiation_tensor 64 # ::,::::,::,:** # ** Optional parameter - Required when mshr_type==Texture Fifo diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index edd48a1..b65df81 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -83,6 +83,8 @@ enum uarch_op_t { SFU_OP, TENSOR_CORE_OP, DP_OP, + SP_OP, + INTP_OP, ALU_SFU_OP, LOAD_OP, TENSOR_CORE_LOAD_OP, @@ -141,6 +143,7 @@ enum operation_pipeline_t { UNKOWN_OP, SP__OP, DP__OP, + INTP__OP, SFU__OP, TENSOR_CORE__OP, MEM__OP diff --git a/src/cuda-sim/cuda-sim.cc b/src/cuda-sim/cuda-sim.cc index c9ac8cb..7dc20cd 100644 --- a/src/cuda-sim/cuda-sim.cc +++ b/src/cuda-sim/cuda-sim.cc @@ -62,8 +62,8 @@ addr_t g_debug_pc = 0xBEEF1518; unsigned g_ptx_sim_num_insn = 0; unsigned gpgpu_param_num_shaders = 0; -char *opcode_latency_int, *opcode_latency_fp, *opcode_latency_dp,*opcode_latency_sfu; -char *opcode_initiation_int, *opcode_initiation_fp, *opcode_initiation_dp,*opcode_initiation_sfu; +char *opcode_latency_int, *opcode_latency_fp, *opcode_latency_dp,*opcode_latency_sfu,*opcode_latency_tensor; +char *opcode_initiation_int, *opcode_initiation_fp, *opcode_initiation_dp,*opcode_initiation_sfu,*opcode_initiation_tensor; char *cdp_latency_str; unsigned cdp_latency[5]; @@ -84,6 +84,10 @@ void ptx_opcocde_latency_options (option_parser_t opp) { "Opcode latencies for SFU instructions" "Default 8", "8"); + option_parser_register(opp, "-ptx_opcode_latency_tesnor", OPT_CSTR, &opcode_latency_tensor, + "Opcode latencies for Tensor instructions" + "Default 64", + "64"); option_parser_register(opp, "-ptx_opcode_initiation_int", OPT_CSTR, &opcode_initiation_int, "Opcode initiation intervals for integers " "Default 1,1,4,4,32", @@ -100,6 +104,10 @@ void ptx_opcocde_latency_options (option_parser_t opp) { "Opcode initiation intervals for sfu instructions" "Default 8", "8"); + option_parser_register(opp, "-ptx_opcode_initiation_tensor", OPT_CSTR, &opcode_initiation_tensor, + "Opcode initiation intervals for tensor instructions" + "Default 64", + "64"); option_parser_register(opp, "-cdp_latency", OPT_CSTR, &cdp_latency_str, "CDP API latency sub_core_model) { //in subcore model, each scheduler should has its own issue register, so num scheduler = reg width assert(m_config->gpgpu_num_sched_per_core == m_pipeline_reg[ID_OC_SP].get_size() ); - if(m_config->gpgpu_num_dp_units > 0) - assert(m_config->gpgpu_num_sched_per_core == m_pipeline_reg[ID_OC_DP].get_size() ); assert(m_config->gpgpu_num_sched_per_core == m_pipeline_reg[ID_OC_SFU].get_size() ); assert(m_config->gpgpu_num_sched_per_core == m_pipeline_reg[ID_OC_MEM].get_size() ); - assert(m_config->gpgpu_num_sched_per_core == m_pipeline_reg[ID_OC_TENSOR_CORE].get_size() ); + if(m_config->gpgpu_tensor_core_avail) + assert(m_config->gpgpu_num_sched_per_core == m_pipeline_reg[ID_OC_TENSOR_CORE].get_size() ); + if(m_config->gpgpu_num_dp_units > 0) + assert(m_config->gpgpu_num_sched_per_core == m_pipeline_reg[ID_OC_DP].get_size() ); + if(m_config->gpgpu_num_int_units > 0) + assert(m_config->gpgpu_num_sched_per_core == m_pipeline_reg[ID_OC_INT].get_size() ); } m_threadState = (thread_ctx_t*) calloc(sizeof(thread_ctx_t), config->n_thread_per_shader); @@ -161,6 +164,7 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, &m_pipeline_reg[ID_OC_SP], &m_pipeline_reg[ID_OC_DP], &m_pipeline_reg[ID_OC_SFU], + &m_pipeline_reg[ID_OC_INT], &m_pipeline_reg[ID_OC_TENSOR_CORE], &m_pipeline_reg[ID_OC_MEM], i @@ -177,6 +181,7 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, &m_pipeline_reg[ID_OC_SP], &m_pipeline_reg[ID_OC_DP], &m_pipeline_reg[ID_OC_SFU], + &m_pipeline_reg[ID_OC_INT], &m_pipeline_reg[ID_OC_TENSOR_CORE], &m_pipeline_reg[ID_OC_MEM], i, @@ -194,6 +199,7 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, &m_pipeline_reg[ID_OC_SP], &m_pipeline_reg[ID_OC_DP], &m_pipeline_reg[ID_OC_SFU], + &m_pipeline_reg[ID_OC_INT], &m_pipeline_reg[ID_OC_TENSOR_CORE], &m_pipeline_reg[ID_OC_MEM], i @@ -210,7 +216,8 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, &m_pipeline_reg[ID_OC_SP], &m_pipeline_reg[ID_OC_DP], &m_pipeline_reg[ID_OC_SFU], - &m_pipeline_reg[ID_OC_TENSOR_CORE], + &m_pipeline_reg[ID_OC_INT], + &m_pipeline_reg[ID_OC_TENSOR_CORE], &m_pipeline_reg[ID_OC_MEM], i ) @@ -226,6 +233,7 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, &m_pipeline_reg[ID_OC_SP], &m_pipeline_reg[ID_OC_DP], &m_pipeline_reg[ID_OC_SFU], + &m_pipeline_reg[ID_OC_INT], &m_pipeline_reg[ID_OC_TENSOR_CORE], &m_pipeline_reg[ID_OC_MEM], i, @@ -248,7 +256,7 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, //op collector configuration - enum { SP_CUS, DP_CUS, SFU_CUS, TENSOR_CORE_CUS, MEM_CUS, GEN_CUS }; + enum { SP_CUS, DP_CUS, SFU_CUS, TENSOR_CORE_CUS, INT_CUS, MEM_CUS, GEN_CUS }; opndcoll_rfu_t::port_vector_t in_ports; opndcoll_rfu_t::port_vector_t out_ports; @@ -260,16 +268,22 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, for (unsigned i = 0; i < m_config->gpgpu_operand_collector_num_in_ports_gen; i++) { in_ports.push_back(&m_pipeline_reg[ID_OC_SP]); in_ports.push_back(&m_pipeline_reg[ID_OC_SFU]); - in_ports.push_back(&m_pipeline_reg[ID_OC_TENSOR_CORE]); in_ports.push_back(&m_pipeline_reg[ID_OC_MEM]); out_ports.push_back(&m_pipeline_reg[OC_EX_SP]); out_ports.push_back(&m_pipeline_reg[OC_EX_SFU]); - out_ports.push_back(&m_pipeline_reg[OC_EX_TENSOR_CORE]); out_ports.push_back(&m_pipeline_reg[OC_EX_MEM]); + if(m_config->gpgpu_tensor_core_avail) { + in_ports.push_back(&m_pipeline_reg[ID_OC_TENSOR_CORE]); + out_ports.push_back(&m_pipeline_reg[OC_EX_TENSOR_CORE]); + } if(m_config->gpgpu_num_dp_units > 0) { in_ports.push_back(&m_pipeline_reg[ID_OC_DP]); out_ports.push_back(&m_pipeline_reg[OC_EX_DP]); } + if(m_config->gpgpu_num_int_units > 0) { + in_ports.push_back(&m_pipeline_reg[ID_OC_INT]); + out_ports.push_back(&m_pipeline_reg[OC_EX_INT]); + } cu_sets.push_back((unsigned)GEN_CUS); m_operand_collector.add_port(in_ports,out_ports,cu_sets); in_ports.clear(),out_ports.clear(),cu_sets.clear(); @@ -281,6 +295,7 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, m_operand_collector.add_cu_set(TENSOR_CORE_CUS, config->gpgpu_operand_collector_num_units_tensor_core, config->gpgpu_operand_collector_num_out_ports_tensor_core); m_operand_collector.add_cu_set(SFU_CUS, m_config->gpgpu_operand_collector_num_units_sfu, m_config->gpgpu_operand_collector_num_out_ports_sfu); m_operand_collector.add_cu_set(MEM_CUS, m_config->gpgpu_operand_collector_num_units_mem, m_config->gpgpu_operand_collector_num_out_ports_mem); + m_operand_collector.add_cu_set(INT_CUS, m_config->gpgpu_operand_collector_num_units_int, m_config->gpgpu_operand_collector_num_out_ports_int); for (unsigned i = 0; i < m_config->gpgpu_operand_collector_num_in_ports_sp; i++) { in_ports.push_back(&m_pipeline_reg[ID_OC_SP]); @@ -326,11 +341,20 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, m_operand_collector.add_port(in_ports,out_ports,cu_sets); in_ports.clear(),out_ports.clear(),cu_sets.clear(); } + + for (unsigned i = 0; i < m_config->gpgpu_operand_collector_num_in_ports_int; i++) { + in_ports.push_back(&m_pipeline_reg[ID_OC_INT]); + out_ports.push_back(&m_pipeline_reg[OC_EX_INT]); + cu_sets.push_back((unsigned)INT_CUS); + cu_sets.push_back((unsigned)GEN_CUS); + m_operand_collector.add_port(in_ports,out_ports,cu_sets); + in_ports.clear(),out_ports.clear(),cu_sets.clear(); + } } m_operand_collector.init( m_config->gpgpu_num_reg_banks, this ); - m_num_function_units = m_config->gpgpu_num_sp_units + m_config->gpgpu_num_dp_units + m_config->gpgpu_num_sfu_units + m_config->gpgpu_num_tensor_core_units + 1; // sp_unit, sfu, ldst_unit + m_num_function_units = m_config->gpgpu_num_sp_units + m_config->gpgpu_num_dp_units + m_config->gpgpu_num_sfu_units + m_config->gpgpu_num_tensor_core_units + m_config->gpgpu_num_int_units + 1; // sp_unit, sfu, dp, tensor, int, ldst_unit //m_dispatch_port = new enum pipeline_stage_name_t[ m_num_function_units ]; //m_issue_port = new enum pipeline_stage_name_t[ m_num_function_units ]; @@ -347,6 +371,11 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, m_dispatch_port.push_back(ID_OC_DP); m_issue_port.push_back(OC_EX_DP); } + for (int k = 0; k < m_config->gpgpu_num_int_units; k++) { + m_fu.push_back(new int_unit( &m_pipeline_reg[EX_WB], m_config, this )); + m_dispatch_port.push_back(ID_OC_INT); + m_issue_port.push_back(OC_EX_INT); + } for (int k = 0; k < m_config->gpgpu_num_sfu_units; k++) { m_fu.push_back(new sfu( &m_pipeline_reg[EX_WB], m_config, this )); @@ -359,6 +388,7 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, m_dispatch_port.push_back(ID_OC_TENSOR_CORE); m_issue_port.push_back(OC_EX_TENSOR_CORE); } + m_ldst_unit = new ldst_unit( m_icnt, m_mem_fetch_allocator, this, &m_operand_collector, m_scoreboard, config, mem_config, stats, shader_id, tpc_id ); m_fu.push_back(m_ldst_unit); m_dispatch_port.push_back(ID_OC_MEM); @@ -958,8 +988,8 @@ void scheduler_unit::cycle() unsigned checked=0; unsigned issued=0; exec_unit_type_t previous_issued_inst_exec_type = exec_unit_type_t::NONE; - unsigned max_issue = m_shader->m_config->gpgpu_max_insn_issue_per_warp; - bool diff_exec_units = m_shader->m_config->gpgpu_dual_issue_diff_exec_units; + unsigned max_issue = m_shader->m_config->gpgpu_max_insn_issue_per_warp; + bool diff_exec_units = m_shader->m_config->gpgpu_dual_issue_diff_exec_units; //In tis mode, we only allow dual issue to diff execution units (as in Maxwell and Pascal) 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(); @@ -1008,33 +1038,62 @@ void scheduler_unit::cycle() bool sfu_pipe_avail = m_sfu_out->has_free(m_shader->m_config->sub_core_model, m_id); bool tensor_core_pipe_avail = m_tensor_core_out->has_free(m_shader->m_config->sub_core_model, m_id); bool dp_pipe_avail = m_dp_out->has_free(m_shader->m_config->sub_core_model, m_id); - if( sp_pipe_avail && (pI->op != TENSOR_CORE_OP) && (pI->op != SFU_OP && pI->op != DP_OP) && (!diff_exec_units || previous_issued_inst_exec_type != exec_unit_type_t::SP)) { - - //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; - } + bool int_pipe_avail = m_int_out->has_free(m_shader->m_config->sub_core_model, m_id); - // 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,m_id); - issued++; - issued_inst=true; - warp_inst_issued = true; - previous_issued_inst_exec_type = exec_unit_type_t::SP; - } else if ( (m_shader->m_config->gpgpu_num_dp_units != 0) && (pI->op == DP_OP) && (!diff_exec_units || previous_issued_inst_exec_type != exec_unit_type_t::DP)) { + //This code need to be refactored + if(pI->op != TENSOR_CORE_OP && pI->op != SFU_OP && pI->op != DP_OP) { + + bool execute_on_SP = false; + bool execute_on_INT = false; + + //if INT unit pipline exist, then execute ALU and INT operations on INT unit and SP-FPU on SP unit (like in Volta) + //if INT unit pipline does not exist, then execute all ALU, INT and SP operations on SP unit (as in Fermi, Pascal GPUs) + if(m_shader->m_config->gpgpu_num_int_units > 0 && + int_pipe_avail && + pI->op != SP_OP && + !(diff_exec_units && previous_issued_inst_exec_type == exec_unit_type_t::INT)) + execute_on_INT = true; + else if (sp_pipe_avail && + (m_shader->m_config->gpgpu_num_int_units == 0 || + (m_shader->m_config->gpgpu_num_int_units > 0 && pI->op == SP_OP)) && + !(diff_exec_units && previous_issued_inst_exec_type == exec_unit_type_t::SP) ) + execute_on_SP = true; + + + if(execute_on_INT || execute_on_SP) { + //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; + } + } + + if(execute_on_SP) { + m_shader->issue_warp(*m_sp_out,pI,active_mask,warp_id,m_id); + issued++; + issued_inst=true; + warp_inst_issued = true; + previous_issued_inst_exec_type = exec_unit_type_t::SP; + } else if (execute_on_INT) { + m_shader->issue_warp(*m_int_out,pI,active_mask,warp_id,m_id); + issued++; + issued_inst=true; + warp_inst_issued = true; + previous_issued_inst_exec_type = exec_unit_type_t::INT; + } + } else if ( (m_shader->m_config->gpgpu_num_dp_units > 0) && (pI->op == DP_OP) && !(diff_exec_units && previous_issued_inst_exec_type == exec_unit_type_t::DP)) { if( dp_pipe_avail ) { m_shader->issue_warp(*m_dp_out,pI,active_mask,warp_id,m_id); issued++; @@ -1042,8 +1101,8 @@ void scheduler_unit::cycle() warp_inst_issued = true; previous_issued_inst_exec_type = exec_unit_type_t::DP; } - } //If the DP units = 0 (like in Fermi archi), then change DP inst to SFU inst - else if ( ((m_shader->m_config->gpgpu_num_dp_units == 0 && pI->op == DP_OP) || (pI->op == SFU_OP) || (pI->op == ALU_SFU_OP)) && (!diff_exec_units || previous_issued_inst_exec_type != exec_unit_type_t::SFU)) { + } //If the DP units = 0 (like in Fermi archi), then execute DP inst on SFU unit + else if ( ((m_shader->m_config->gpgpu_num_dp_units == 0 && pI->op == DP_OP) || (pI->op == SFU_OP) || (pI->op == ALU_SFU_OP)) && !(diff_exec_units && previous_issued_inst_exec_type == exec_unit_type_t::SFU)) { if( sfu_pipe_avail ) { m_shader->issue_warp(*m_sfu_out,pI,active_mask,warp_id,m_id); issued++; @@ -1052,12 +1111,13 @@ void scheduler_unit::cycle() previous_issued_inst_exec_type = exec_unit_type_t::SFU; } } - else if ( (pI->op == TENSOR_CORE_OP) ) { + else if ( (pI->op == TENSOR_CORE_OP) && !(diff_exec_units && previous_issued_inst_exec_type == exec_unit_type_t::SP) ) { if( tensor_core_pipe_avail ) { m_shader->issue_warp(*m_tensor_core_out,pI,active_mask,warp_id,m_id); issued++; issued_inst=true; warp_inst_issued = true; + previous_issued_inst_exec_type = exec_unit_type_t::TENSOR; } } }//end of else @@ -1245,11 +1305,12 @@ swl_scheduler::swl_scheduler ( shader_core_stats* stats, shader_core_ctx* shader register_set* sp_out, register_set* dp_out, register_set* sfu_out, + register_set* int_out, register_set* tensor_core_out, register_set* mem_out, int id, char* config_string ) - : scheduler_unit ( stats, shader, scoreboard, simt, warp, sp_out, dp_out, sfu_out,tensor_core_out, mem_out, id ) + : scheduler_unit ( stats, shader, scoreboard, simt, warp, sp_out, dp_out, sfu_out, int_out, tensor_core_out, mem_out, id ) { unsigned m_prioritization_readin; int ret = sscanf( config_string, @@ -1822,6 +1883,7 @@ void ldst_unit::active_lanes_in_pipeline(){ assert(active_count<=m_core->get_config()->warp_size); m_core->incfumemactivelanes_stat(active_count); } + void sp_unit::active_lanes_in_pipeline(){ unsigned active_count=pipelined_simd_unit::get_active_lanes_in_pipeline(); assert(active_count<=m_core->get_config()->warp_size); @@ -1837,6 +1899,13 @@ void dp_unit::active_lanes_in_pipeline(){ m_core->incfumemactivelanes_stat(active_count); } +void int_unit::active_lanes_in_pipeline(){ + unsigned active_count=pipelined_simd_unit::get_active_lanes_in_pipeline(); + assert(active_count<=m_core->get_config()->warp_size); + m_core->incspactivelanes_stat(active_count); + m_core->incfuactivelanes_stat(active_count); + m_core->incfumemactivelanes_stat(active_count); +} void sfu::active_lanes_in_pipeline(){ unsigned active_count=pipelined_simd_unit::get_active_lanes_in_pipeline(); assert(active_count<=m_core->get_config()->warp_size); @@ -1866,6 +1935,12 @@ dp_unit::dp_unit( register_set* result_port, const shader_core_config *config,sh m_name = "DP "; } +int_unit::int_unit( register_set* result_port, const shader_core_config *config,shader_core_ctx *core) + : pipelined_simd_unit(result_port,config,config->max_sp_latency,core) +{ + m_name = "INT "; +} + void sp_unit :: issue(register_set& source_reg) { warp_inst_t** ready_reg = source_reg.get_ready(); @@ -1884,6 +1959,15 @@ void dp_unit :: issue(register_set& source_reg) pipelined_simd_unit::issue(source_reg); } +void int_unit :: issue(register_set& source_reg) +{ + warp_inst_t** ready_reg = source_reg.get_ready(); + //m_core->incexecstat((*ready_reg)); + (*ready_reg)->op_pipe=INTP__OP; + m_core->incsp_stat(m_core->get_config()->warp_size,(*ready_reg)->latency); + pipelined_simd_unit::issue(source_reg); +} + pipelined_simd_unit::pipelined_simd_unit( register_set* result_port, const shader_core_config *config, unsigned max_latency,shader_core_ctx *core ) : simd_function_unit(config) { @@ -2006,6 +2090,7 @@ ldst_unit::ldst_unit( mem_fetch_interface *icnt, l1_latency_queue.push_back((mem_fetch*)NULL); } } + m_name = "MEM "; } ldst_unit::ldst_unit( mem_fetch_interface *icnt, diff --git a/src/gpgpu-sim/shader.h b/src/gpgpu-sim/shader.h index 7b33c14..45cf8e4 100644 --- a/src/gpgpu-sim/shader.h +++ b/src/gpgpu-sim/shader.h @@ -76,7 +76,9 @@ enum exec_unit_type_t SP = 1, SFU = 2, MEM = 3, - DP = 4 + DP = 4, + INT = 5, + TENSOR = 6 }; class thread_ctx_t { @@ -328,12 +330,13 @@ public: register_set* sp_out, register_set* dp_out, register_set* sfu_out, + register_set* int_out, register_set* tensor_core_out, register_set* mem_out, int id) : m_supervised_warps(), m_stats(stats), m_shader(shader), m_scoreboard(scoreboard), m_simt_stack(simt), /*m_pipeline_reg(pipe_regs),*/ m_warp(warp), - m_sp_out(sp_out),m_dp_out(dp_out),m_sfu_out(sfu_out),m_tensor_core_out(tensor_core_out),m_mem_out(mem_out), m_id(id){} + m_sp_out(sp_out),m_dp_out(dp_out),m_sfu_out(sfu_out),m_int_out(int_out),m_tensor_core_out(tensor_core_out),m_mem_out(mem_out), m_id(id){} virtual ~scheduler_unit(){} virtual void add_supervised_warp_id(int i) { m_supervised_warps.push_back(&warp(i)); @@ -409,6 +412,7 @@ protected: register_set* m_sp_out; register_set* m_dp_out; register_set* m_sfu_out; + register_set* m_int_out; register_set* m_tensor_core_out; register_set* m_mem_out; @@ -423,10 +427,11 @@ public: register_set* sp_out, register_set* dp_out, register_set* sfu_out, + register_set* int_out, register_set* tensor_core_out, register_set* mem_out, int id ) - : scheduler_unit ( stats, shader, scoreboard, simt, warp, sp_out, dp_out, sfu_out,tensor_core_out, mem_out, id ){} + : scheduler_unit ( stats, shader, scoreboard, simt, warp, sp_out, dp_out, sfu_out, int_out, tensor_core_out, mem_out, id ){} virtual ~lrr_scheduler () {} virtual void order_warps (); virtual void done_adding_supervised_warps() { @@ -442,10 +447,11 @@ public: register_set* sp_out, register_set* dp_out, register_set* sfu_out, + register_set* int_out, register_set* tensor_core_out, register_set* mem_out, int id ) - : scheduler_unit ( stats, shader, scoreboard, simt, warp, sp_out, dp_out, sfu_out,tensor_core_out, mem_out, id ){} + : scheduler_unit ( stats, shader, scoreboard, simt, warp, sp_out, dp_out, sfu_out, int_out, tensor_core_out, mem_out, id ){} virtual ~gto_scheduler () {} virtual void order_warps (); virtual void done_adding_supervised_warps() { @@ -462,10 +468,11 @@ public: register_set* sp_out, register_set* dp_out, register_set* sfu_out, - register_set* tensor_core_out, + register_set* int_out, + register_set* tensor_core_out, register_set* mem_out, int id ) - : scheduler_unit ( stats, shader, scoreboard, simt, warp, sp_out, dp_out, sfu_out,tensor_core_out, mem_out, id ){} + : scheduler_unit ( stats, shader, scoreboard, simt, warp, sp_out, dp_out, sfu_out, int_out, tensor_core_out, mem_out, id ){} virtual ~oldest_scheduler () {} virtual void order_warps (); virtual void done_adding_supervised_warps() { @@ -482,11 +489,12 @@ public: register_set* sp_out, register_set* dp_out, register_set* sfu_out, + register_set* int_out, register_set* tensor_core_out, register_set* mem_out, int id, char* config_str ) - : scheduler_unit ( stats, shader, scoreboard, simt, warp, sp_out, dp_out, sfu_out,tensor_core_out, mem_out, id ), + : scheduler_unit ( stats, shader, scoreboard, simt, warp, sp_out, dp_out, sfu_out, int_out, tensor_core_out, mem_out, id ), m_pending_warps() { unsigned inner_level_readin; @@ -534,6 +542,7 @@ public: register_set* sp_out, register_set* dp_out, register_set* sfu_out, + register_set* int_out, register_set* tensor_core_out, register_set* mem_out, int id, @@ -1046,6 +1055,9 @@ public: fprintf(fp,"%s dispatch= ", m_name.c_str() ); m_dispatch_reg->print(fp); } + const char* get_name() { + return m_name.c_str(); + } protected: std::string m_name; const shader_core_config *m_config; @@ -1154,6 +1166,29 @@ public: }; +class int_unit : public pipelined_simd_unit +{ +public: + int_unit( register_set* result_port, const shader_core_config *config, shader_core_ctx *core ); + virtual bool can_issue( const warp_inst_t &inst ) const + { + switch(inst.op) { + case SFU_OP: return false; + case LOAD_OP: return false; + case TENSOR_CORE_LOAD_OP: return false; + case STORE_OP: return false; + case TENSOR_CORE_STORE_OP: return false; + case MEMORY_BARRIER_OP: return false; + case SP_OP: return false; + case DP_OP: return false; + default: break; + } + return pipelined_simd_unit::can_issue(inst); + } + virtual void active_lanes_in_pipeline(); + virtual void issue( register_set& source_reg ); +}; + class sp_unit : public pipelined_simd_unit { public: @@ -1303,10 +1338,12 @@ protected: enum pipeline_stage_name_t { ID_OC_SP=0, ID_OC_DP, + ID_OC_INT, ID_OC_SFU, ID_OC_MEM, OC_EX_SP, OC_EX_DP, + OC_EX_INT, OC_EX_SFU, OC_EX_MEM, EX_WB, @@ -1318,10 +1355,12 @@ enum pipeline_stage_name_t { const char* const pipeline_stage_name_decode[] = { "ID_OC_SP", "ID_OC_DP", + "ID_OC_INT", "ID_OC_SFU", "ID_OC_MEM", "OC_EX_SP", "OC_EX_DP", + "OC_EX_INT", "OC_EX_SFU", "OC_EX_MEM", "EX_WB", @@ -1429,6 +1468,7 @@ struct shader_core_config : public core_config int gpgpu_operand_collector_num_units_tensor_core; int gpgpu_operand_collector_num_units_mem; int gpgpu_operand_collector_num_units_gen; + int gpgpu_operand_collector_num_units_int; unsigned int gpgpu_operand_collector_num_in_ports_sp; unsigned int gpgpu_operand_collector_num_in_ports_dp; @@ -1436,6 +1476,7 @@ struct shader_core_config : public core_config unsigned int gpgpu_operand_collector_num_in_ports_tensor_core; unsigned int gpgpu_operand_collector_num_in_ports_mem; unsigned int gpgpu_operand_collector_num_in_ports_gen; + unsigned int gpgpu_operand_collector_num_in_ports_int; unsigned int gpgpu_operand_collector_num_out_ports_sp; unsigned int gpgpu_operand_collector_num_out_ports_dp; @@ -1443,6 +1484,7 @@ struct shader_core_config : public core_config unsigned int gpgpu_operand_collector_num_out_ports_tensor_core; unsigned int gpgpu_operand_collector_num_out_ports_mem; unsigned int gpgpu_operand_collector_num_out_ports_gen; + unsigned int gpgpu_operand_collector_num_out_ports_int; int gpgpu_num_sp_units; int gpgpu_tensor_core_avail; @@ -1450,6 +1492,7 @@ struct shader_core_config : public core_config int gpgpu_num_sfu_units; int gpgpu_num_tensor_core_units; int gpgpu_num_mem_units; + int gpgpu_num_int_units; //Shader core resources unsigned gpgpu_shader_registers; -- cgit v1.3 From 7a9c450e6b905af9ca6cdd3c7b79ad5aec535a5a Mon Sep 17 00:00:00 2001 From: Deval Shah Date: Fri, 9 Nov 2018 21:27:34 -0800 Subject: resolving merge conflicts --- libcuda/cuda_runtime_api.cc | 35 +--------------- src/abstract_hardware_model.h | 30 ++------------ src/cuda-sim/cuda-sim.cc | 94 ++++--------------------------------------- src/cuda-sim/instructions.cc | 56 -------------------------- src/gpgpu-sim/gpu-sim.cc | 25 ++---------- 5 files changed, 16 insertions(+), 224 deletions(-) (limited to 'src/abstract_hardware_model.h') diff --git a/libcuda/cuda_runtime_api.cc b/libcuda/cuda_runtime_api.cc index 4b50e34..f00fe52 100644 --- a/libcuda/cuda_runtime_api.cc +++ b/libcuda/cuda_runtime_api.cc @@ -1425,40 +1425,7 @@ __host__ cudaError_t CUDARTAPI cudaLaunch( const char *hostFun ) dim3 gridDim = config.grid_dim(); dim3 blockDim = config.block_dim(); - gpgpu_t *gpu = context->get_device()->get_gpgpu(); - checkpoint *g_checkpoint; - g_checkpoint = new checkpoint(); - class memory_space *global_mem; - global_mem = gpu->get_global_memory(); - - if(gpu->resume_option ==1 && (grid->get_uid()==gpu->resume_kernel)) - { - - char f1name[2048]; - snprintf(f1name,2048,"checkpoint_files/global_mem_%d.txt", grid->get_uid()); - - g_checkpoint->load_global_mem(global_mem, f1name); - for (int i=0;iresume_CTA;i++) - grid->increment_cta_id(); - } - if(gpu->resume_option==1 && (grid->get_uid()resume_kernel)) - { - char f1name[2048]; - snprintf(f1name,2048,"checkpoint_files/global_mem_%d.txt", grid->get_uid()); - - g_checkpoint->load_global_mem(global_mem, f1name); - printf("Skipping kernel %d as resuming from kernel %d\n",grid->get_uid(),gpu->resume_kernel ); - g_cuda_launch_stack.pop_back(); - return g_last_cudaError = cudaSuccess; - - } - if(gpu->checkpoint_option==1 && (grid->get_uid()>gpu->checkpoint_kernel)) - { - printf("Skipping kernel %d as checkpoint from kernel %d\n",grid->get_uid(),gpu->checkpoint_kernel ); - g_cuda_launch_stack.pop_back(); - return g_last_cudaError = cudaSuccess; - - } + printf("GPGPU-Sim PTX: pushing kernel \'%s\' to stream %u, gridDim= (%u,%u,%u) blockDim = (%u,%u,%u) \n", kname.c_str(), stream?stream->get_uid():0, gridDim.x,gridDim.y,gridDim.z,blockDim.x,blockDim.y,blockDim.z ); stream_operation op(grid,g_ptx_sim_mode,stream); diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index 2350db4..45fba76 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -381,8 +381,7 @@ public: void get_pdom_stack_top_info( unsigned *pc, unsigned *rpc ) const; unsigned get_rp() const; void print(FILE *fp) const; - void resume(char * fname) ; - void print_checkpoint (FILE *fout) const; + protected: unsigned m_warp_id; @@ -502,28 +501,14 @@ public: const char* get_ptx_inst_debug_file() const { return g_ptx_inst_debug_file; } int get_ptx_inst_debug_thread_uid() const { return g_ptx_inst_debug_thread_uid; } unsigned get_texcache_linesize() const { return m_texcache_linesize; } - int get_checkpoint_option() const {return checkpoint_option; } - int get_checkpoint_kernel() const {return checkpoint_kernel; } - int get_checkpoint_CTA() const {return checkpoint_CTA; } - int get_resume_option() const {return resume_option; } - int get_resume_kernel() const {return resume_kernel; } - int get_resume_CTA() const {return resume_CTA; } - int get_checkpoint_CTA_t() const {return checkpoint_CTA_t; } - int get_checkpoint_insn_Y() const {return checkpoint_insn_Y; } + private: // PTX options int m_ptx_convert_to_ptxplus; int m_ptx_use_cuobjdump; int m_experimental_lib_support; unsigned m_ptx_force_max_capability; - int checkpoint_option; - int checkpoint_kernel; - int checkpoint_CTA; - int resume_option; - int resume_kernel; - int resume_CTA; - int checkpoint_CTA_t; - int checkpoint_insn_Y; + int g_ptx_inst_debug_to_file; char* g_ptx_inst_debug_file; int g_ptx_inst_debug_thread_uid; @@ -535,14 +520,7 @@ private: class gpgpu_t { public: gpgpu_t( const gpgpu_functional_sim_config &config ); - int checkpoint_option; - int checkpoint_kernel; - int checkpoint_CTA; - int resume_option; - int resume_kernel; - int resume_CTA; - int checkpoint_CTA_t; - int checkpoint_insn_Y; + void* gpu_malloc( size_t size ); void* gpu_mallocarray( size_t count ); void gpu_memset( size_t dst_start_addr, int c, size_t count ); diff --git a/src/cuda-sim/cuda-sim.cc b/src/cuda-sim/cuda-sim.cc index 642e301..6a6b307 100644 --- a/src/cuda-sim/cuda-sim.cc +++ b/src/cuda-sim/cuda-sim.cc @@ -2125,8 +2125,7 @@ void gpgpu_cuda_ptx_sim_main_func( kernel_info_t &kernel, bool openCL ) //before we execute, we should do PDOM analysis for functional simulation scenario. function_info *kernel_func_info = kernel.entry(); const struct gpgpu_ptx_sim_info *kernel_info = ptx_sim_kernel_info(kernel_func_info); - checkpoint *g_checkpoint; - g_checkpoint = new checkpoint(); + if (kernel_func_info->is_pdom_set()) { printf("GPGPU-Sim PTX: PDOM analysis already done for %s \n", kernel.name().c_str() ); @@ -2143,21 +2142,12 @@ void gpgpu_cuda_ptx_sim_main_func( kernel_info_t &kernel, bool openCL ) - int inst_count=50; - int cp_op= g_the_gpu->checkpoint_option; - int cp_CTA = g_the_gpu->checkpoint_CTA; - int cp_kernel= g_the_gpu->checkpoint_kernel; - cp_count= g_the_gpu->checkpoint_insn_Y; - cp_cta_resume= g_the_gpu->checkpoint_CTA_t; - int cta_launched =0; //we excute the kernel one CTA (Block) at the time, as synchronization functions work block wise while(!kernel.no_more_ctas_to_run()){ unsigned temp=kernel.get_next_cta_id_single(); - if(cp_op==0 || (cp_op==1 && cta_launched= 5000) launch_all_device_kernels(); #endif - } - else - { - kernel.increment_cta_id(); - } - cta_launched++; + } - if(cp_op==1) - { - char f1name[2048]; - snprintf(f1name,2048,"checkpoint_files/global_mem_%d.txt", kernel.get_uid() ); - g_checkpoint->store_global_mem(g_the_gpu->get_global_memory(), f1name , "%08x"); - } + @@ -2227,7 +2207,6 @@ void gpgpu_cuda_ptx_sim_main_func( kernel_info_t &kernel, bool openCL ) void functionalCoreSim::initializeCTA(unsigned ctaid_cp) { int ctaLiveThreads=0; - symbol_table * symtab= m_kernel->entry()->get_symtab(); for(int i=0; i< m_warp_count; i++){ m_warpAtBarrier[i]=false; @@ -2240,10 +2219,7 @@ void functionalCoreSim::initializeCTA(unsigned ctaid_cp) for(unsigned i=0; ithreads_per_cta();i++) { ptx_sim_init_thread(*m_kernel,&m_thread[i],0,i,m_kernel->threads_per_cta()-i,m_kernel->threads_per_cta(),this,0,i/m_warp_size,(gpgpu_t*)m_gpu, true); assert(m_thread[i]!=NULL && !m_thread[i]->is_done()); - char fname[2048]; - snprintf(fname,2048,"checkpoint_files/thread_%d_0_reg.txt",i ); - if(cp_cta_resume==1) - m_thread[i]->resume_reg_thread(fname,symtab); + ctaLiveThreads++; } @@ -2266,40 +2242,25 @@ void functionalCoreSim::createWarp(unsigned warpId) char fname[2048]; snprintf(fname,2048,"checkpoint_files/warp_%d_0_simt.txt",warpId ); - if(cp_cta_resume==1) - { - unsigned pc,rpc; - m_simt_stack[warpId]->resume(fname); - m_simt_stack[warpId]->get_pdom_stack_top_info(&pc,&rpc); - for(int i=warpId*m_warp_size; iset_npc(pc); - m_thread[i]->update_pc(); - } - } m_liveThreadCount[warpId]= liveThreadsCount; } void functionalCoreSim::execute(int inst_count, unsigned ctaid_cp) { - cp_count= m_gpu->checkpoint_insn_Y; - cp_cta_resume= m_gpu->checkpoint_CTA_t; + initializeCTA(ctaid_cp); - int count=0; + while(true){ bool someOneLive= false; bool allAtBarrier = true; for(unsigned i=0;i0 && count>inst_count && (m_kernel->get_uid()==m_gpu->checkpoint_kernel) && (ctaid_cp>=m_gpu->checkpoint_CTA) && (ctaid_cpcheckpoint_CTA_t) && m_gpu->checkpoint_option==1) - { - someOneLive=false; - break; - } + if(!someOneLive) break; if(allAtBarrier){ for(unsigned i=0;ientry()->get_symtab(); - - - unsigned ctaid =m_kernel->get_next_cta_id_single(); - if(m_gpu->checkpoint_option==1 && (m_kernel->get_uid()==m_gpu->checkpoint_kernel) && (ctaid_cp>=m_gpu->checkpoint_CTA) && (ctaid_cpcheckpoint_CTA_t)) - { - char fname[2048]; - snprintf(fname,2048,"checkpoint_files/shared_mem_%d.txt",ctaid-1 ); - g_checkpoint->store_global_mem(m_thread[0]->m_shared_mem, fname , "%08x"); - for(int i=0; i<32*m_warp_count;i++) - { - char fname[2048]; - snprintf(fname,2048,"checkpoint_files/thread_%d_%d_reg.txt",i,ctaid-1 ); - m_thread[i]->print_reg_thread(fname); - char f1name[2048]; - snprintf(f1name,2048,"checkpoint_files/local_mem_thread_%d_%d_reg.txt",i,ctaid-1 ); - g_checkpoint->store_global_mem(m_thread[i]->m_local_mem, f1name , "%08x"); - m_thread[i]->set_done(); - m_thread[i]->exitCore(); - m_thread[i]->registerExit(); - } - - for(int i=0;iprint_checkpoint(fp); - fclose(fp); - } - } } diff --git a/src/cuda-sim/instructions.cc b/src/cuda-sim/instructions.cc index 31a33c6..f57a3f7 100644 --- a/src/cuda-sim/instructions.cc +++ b/src/cuda-sim/instructions.cc @@ -183,63 +183,7 @@ void ptx_thread_info::set_reg( const symbol *reg, const ptx_reg_t &value ) m_last_set_operand_value = value; } -void ptx_thread_info::print_reg_thread(char * fname) -{ - - FILE *fp= fopen(fname,"w"); - assert(fp!=NULL); - - int size = m_regs.size(); - - if(size>0) - { - reg_map_t reg = m_regs.back(); - - typename reg_map_t::const_iterator it; - for (it = reg.begin(); it != reg.end(); ++it) - { - const std::string &name = it->first->name(); - const std::string &dec= it->first->decl_location(); - unsigned size = it->first->get_size_in_bytes(); - fprintf(fp,"%s %llu %s %d\n",name.c_str(),it->second, dec.c_str(),size ); - - } - //m_regs.pop_back(); - } - fclose(fp); - - } - -void ptx_thread_info::resume_reg_thread(char * fname, symbol_table * symtab) -{ - - FILE * fp2 = fopen(fname, "r"); - assert(fp2!=NULL); - //m_regs.push_back( reg_map_t() ); - char line [ 200 ]; - while ( fgets ( line, sizeof line, fp2 ) != NULL ) - { - symbol *reg; - char * pch; - unsigned size; - pch = strtok (line," "); - char * name =pch; - reg= symtab->lookup(name); - ptx_reg_t data; - pch = strtok (NULL," "); - data = atoi(pch); - pch = strtok (NULL," "); - char * decl= pch; - pch = strtok (NULL," "); - size = atoi(pch); - - - m_regs.back()[reg] = data; - } - fclose ( fp2 ); -} - ptx_reg_t ptx_thread_info::get_reg( const symbol *reg ) { diff --git a/src/gpgpu-sim/gpu-sim.cc b/src/gpgpu-sim/gpu-sim.cc index 79a6fcd..c706f23 100644 --- a/src/gpgpu-sim/gpu-sim.cc +++ b/src/gpgpu-sim/gpu-sim.cc @@ -1414,38 +1414,19 @@ void shader_core_ctx::issue_block2core( kernel_info_t &kernel ) // bind functional simulation state of threads to hardware resources (simulation) warp_set_t warps; unsigned nthreads_in_block= 0; - function_info *kernel_func_info = kernel.entry(); - symbol_table * symtab= kernel_func_info->get_symtab(); - unsigned ctaid= kernel.get_next_cta_id_single(); - checkpoint *g_checkpoint= new checkpoint(); + for (unsigned i = start_thread; iwarp_size; nthreads_in_block += ptx_sim_init_thread(kernel,&m_thread[i],m_sid,i,cta_size-(i-start_thread),m_config->n_thread_per_shader,this,free_cta_hw_id,warp_id,m_cluster->get_gpu()); m_threadState[i].m_active = true; - // load thread local memory and register file - if(m_gpu->resume_option==1 && kernel.get_uid()==m_gpu->resume_kernel && ctaid>=m_gpu->resume_CTA && ctaidcheckpoint_CTA_t ) - { - char fname[2048]; - snprintf(fname,2048,"checkpoint_files/thread_%d_%d_reg.txt",i%cta_size,ctaid ); - m_thread[i]->resume_reg_thread(fname,symtab); - char f1name[2048]; - snprintf(f1name,2048,"checkpoint_files/local_mem_thread_%d_%d_reg.txt",i%cta_size,ctaid); - g_checkpoint->load_global_mem(m_thread[i]->m_local_mem, f1name); - } - // + warps.set( warp_id ); } assert( nthreads_in_block > 0 && nthreads_in_block <= m_config->n_thread_per_shader); // should be at least one, but less than max m_cta_status[free_cta_hw_id]=nthreads_in_block; - if(m_gpu->resume_option==1 && kernel.get_uid()==m_gpu->resume_kernel && ctaid>=m_gpu->resume_CTA && ctaidcheckpoint_CTA_t ) - { - char f1name[2048]; - snprintf(f1name,2048,"checkpoint_files/shared_mem_%d.txt", ctaid); - - g_checkpoint->load_global_mem(m_thread[start_thread]->m_shared_mem, f1name); - } + // now that we know which warps are used in this CTA, we can allocate // resources for use in CTA-wide barrier operations m_barriers.allocate_barrier(free_cta_hw_id,warps); -- cgit v1.3 From 642818ae5ff61c1544bcce9e7ba2dd0aea47ea6a Mon Sep 17 00:00:00 2001 From: Deval Shah Date: Fri, 9 Nov 2018 21:29:18 -0800 Subject: Adding checkpoint support --- libcuda/cuda_runtime_api.cc | 35 +++++++++++++++- src/abstract_hardware_model.h | 30 ++++++++++++-- src/cuda-sim/cuda-sim.cc | 94 +++++++++++++++++++++++++++++++++++++++---- src/cuda-sim/instructions.cc | 56 ++++++++++++++++++++++++++ src/gpgpu-sim/gpu-sim.cc | 25 ++++++++++-- 5 files changed, 224 insertions(+), 16 deletions(-) (limited to 'src/abstract_hardware_model.h') diff --git a/libcuda/cuda_runtime_api.cc b/libcuda/cuda_runtime_api.cc index f00fe52..4b50e34 100644 --- a/libcuda/cuda_runtime_api.cc +++ b/libcuda/cuda_runtime_api.cc @@ -1425,7 +1425,40 @@ __host__ cudaError_t CUDARTAPI cudaLaunch( const char *hostFun ) dim3 gridDim = config.grid_dim(); dim3 blockDim = config.block_dim(); - + gpgpu_t *gpu = context->get_device()->get_gpgpu(); + checkpoint *g_checkpoint; + g_checkpoint = new checkpoint(); + class memory_space *global_mem; + global_mem = gpu->get_global_memory(); + + if(gpu->resume_option ==1 && (grid->get_uid()==gpu->resume_kernel)) + { + + char f1name[2048]; + snprintf(f1name,2048,"checkpoint_files/global_mem_%d.txt", grid->get_uid()); + + g_checkpoint->load_global_mem(global_mem, f1name); + for (int i=0;iresume_CTA;i++) + grid->increment_cta_id(); + } + if(gpu->resume_option==1 && (grid->get_uid()resume_kernel)) + { + char f1name[2048]; + snprintf(f1name,2048,"checkpoint_files/global_mem_%d.txt", grid->get_uid()); + + g_checkpoint->load_global_mem(global_mem, f1name); + printf("Skipping kernel %d as resuming from kernel %d\n",grid->get_uid(),gpu->resume_kernel ); + g_cuda_launch_stack.pop_back(); + return g_last_cudaError = cudaSuccess; + + } + if(gpu->checkpoint_option==1 && (grid->get_uid()>gpu->checkpoint_kernel)) + { + printf("Skipping kernel %d as checkpoint from kernel %d\n",grid->get_uid(),gpu->checkpoint_kernel ); + g_cuda_launch_stack.pop_back(); + return g_last_cudaError = cudaSuccess; + + } printf("GPGPU-Sim PTX: pushing kernel \'%s\' to stream %u, gridDim= (%u,%u,%u) blockDim = (%u,%u,%u) \n", kname.c_str(), stream?stream->get_uid():0, gridDim.x,gridDim.y,gridDim.z,blockDim.x,blockDim.y,blockDim.z ); stream_operation op(grid,g_ptx_sim_mode,stream); diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index 45fba76..2350db4 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -381,7 +381,8 @@ public: void get_pdom_stack_top_info( unsigned *pc, unsigned *rpc ) const; unsigned get_rp() const; void print(FILE *fp) const; - + void resume(char * fname) ; + void print_checkpoint (FILE *fout) const; protected: unsigned m_warp_id; @@ -501,14 +502,28 @@ public: const char* get_ptx_inst_debug_file() const { return g_ptx_inst_debug_file; } int get_ptx_inst_debug_thread_uid() const { return g_ptx_inst_debug_thread_uid; } unsigned get_texcache_linesize() const { return m_texcache_linesize; } - + int get_checkpoint_option() const {return checkpoint_option; } + int get_checkpoint_kernel() const {return checkpoint_kernel; } + int get_checkpoint_CTA() const {return checkpoint_CTA; } + int get_resume_option() const {return resume_option; } + int get_resume_kernel() const {return resume_kernel; } + int get_resume_CTA() const {return resume_CTA; } + int get_checkpoint_CTA_t() const {return checkpoint_CTA_t; } + int get_checkpoint_insn_Y() const {return checkpoint_insn_Y; } private: // PTX options int m_ptx_convert_to_ptxplus; int m_ptx_use_cuobjdump; int m_experimental_lib_support; unsigned m_ptx_force_max_capability; - + int checkpoint_option; + int checkpoint_kernel; + int checkpoint_CTA; + int resume_option; + int resume_kernel; + int resume_CTA; + int checkpoint_CTA_t; + int checkpoint_insn_Y; int g_ptx_inst_debug_to_file; char* g_ptx_inst_debug_file; int g_ptx_inst_debug_thread_uid; @@ -520,7 +535,14 @@ private: class gpgpu_t { public: gpgpu_t( const gpgpu_functional_sim_config &config ); - + int checkpoint_option; + int checkpoint_kernel; + int checkpoint_CTA; + int resume_option; + int resume_kernel; + int resume_CTA; + int checkpoint_CTA_t; + int checkpoint_insn_Y; void* gpu_malloc( size_t size ); void* gpu_mallocarray( size_t count ); void gpu_memset( size_t dst_start_addr, int c, size_t count ); diff --git a/src/cuda-sim/cuda-sim.cc b/src/cuda-sim/cuda-sim.cc index 6a6b307..642e301 100644 --- a/src/cuda-sim/cuda-sim.cc +++ b/src/cuda-sim/cuda-sim.cc @@ -2125,7 +2125,8 @@ void gpgpu_cuda_ptx_sim_main_func( kernel_info_t &kernel, bool openCL ) //before we execute, we should do PDOM analysis for functional simulation scenario. function_info *kernel_func_info = kernel.entry(); const struct gpgpu_ptx_sim_info *kernel_info = ptx_sim_kernel_info(kernel_func_info); - + checkpoint *g_checkpoint; + g_checkpoint = new checkpoint(); if (kernel_func_info->is_pdom_set()) { printf("GPGPU-Sim PTX: PDOM analysis already done for %s \n", kernel.name().c_str() ); @@ -2142,12 +2143,21 @@ void gpgpu_cuda_ptx_sim_main_func( kernel_info_t &kernel, bool openCL ) + int inst_count=50; + int cp_op= g_the_gpu->checkpoint_option; + int cp_CTA = g_the_gpu->checkpoint_CTA; + int cp_kernel= g_the_gpu->checkpoint_kernel; + cp_count= g_the_gpu->checkpoint_insn_Y; + cp_cta_resume= g_the_gpu->checkpoint_CTA_t; + int cta_launched =0; //we excute the kernel one CTA (Block) at the time, as synchronization functions work block wise while(!kernel.no_more_ctas_to_run()){ unsigned temp=kernel.get_next_cta_id_single(); + if(cp_op==0 || (cp_op==1 && cta_launched= 5000) launch_all_device_kernels(); #endif - + } + else + { + kernel.increment_cta_id(); + } + cta_launched++; } - + if(cp_op==1) + { + char f1name[2048]; + snprintf(f1name,2048,"checkpoint_files/global_mem_%d.txt", kernel.get_uid() ); + g_checkpoint->store_global_mem(g_the_gpu->get_global_memory(), f1name , "%08x"); + } @@ -2207,6 +2227,7 @@ void gpgpu_cuda_ptx_sim_main_func( kernel_info_t &kernel, bool openCL ) void functionalCoreSim::initializeCTA(unsigned ctaid_cp) { int ctaLiveThreads=0; + symbol_table * symtab= m_kernel->entry()->get_symtab(); for(int i=0; i< m_warp_count; i++){ m_warpAtBarrier[i]=false; @@ -2219,7 +2240,10 @@ void functionalCoreSim::initializeCTA(unsigned ctaid_cp) for(unsigned i=0; ithreads_per_cta();i++) { ptx_sim_init_thread(*m_kernel,&m_thread[i],0,i,m_kernel->threads_per_cta()-i,m_kernel->threads_per_cta(),this,0,i/m_warp_size,(gpgpu_t*)m_gpu, true); assert(m_thread[i]!=NULL && !m_thread[i]->is_done()); - + char fname[2048]; + snprintf(fname,2048,"checkpoint_files/thread_%d_0_reg.txt",i ); + if(cp_cta_resume==1) + m_thread[i]->resume_reg_thread(fname,symtab); ctaLiveThreads++; } @@ -2242,25 +2266,40 @@ void functionalCoreSim::createWarp(unsigned warpId) char fname[2048]; snprintf(fname,2048,"checkpoint_files/warp_%d_0_simt.txt",warpId ); + if(cp_cta_resume==1) + { + unsigned pc,rpc; + m_simt_stack[warpId]->resume(fname); + m_simt_stack[warpId]->get_pdom_stack_top_info(&pc,&rpc); + for(int i=warpId*m_warp_size; iset_npc(pc); + m_thread[i]->update_pc(); + } + } m_liveThreadCount[warpId]= liveThreadsCount; } void functionalCoreSim::execute(int inst_count, unsigned ctaid_cp) { - + cp_count= m_gpu->checkpoint_insn_Y; + cp_cta_resume= m_gpu->checkpoint_CTA_t; initializeCTA(ctaid_cp); - + int count=0; while(true){ bool someOneLive= false; bool allAtBarrier = true; for(unsigned i=0;i0 && count>inst_count && (m_kernel->get_uid()==m_gpu->checkpoint_kernel) && (ctaid_cp>=m_gpu->checkpoint_CTA) && (ctaid_cpcheckpoint_CTA_t) && m_gpu->checkpoint_option==1) + { + someOneLive=false; + break; + } if(!someOneLive) break; if(allAtBarrier){ for(unsigned i=0;ientry()->get_symtab(); + + + unsigned ctaid =m_kernel->get_next_cta_id_single(); + if(m_gpu->checkpoint_option==1 && (m_kernel->get_uid()==m_gpu->checkpoint_kernel) && (ctaid_cp>=m_gpu->checkpoint_CTA) && (ctaid_cpcheckpoint_CTA_t)) + { + char fname[2048]; + snprintf(fname,2048,"checkpoint_files/shared_mem_%d.txt",ctaid-1 ); + g_checkpoint->store_global_mem(m_thread[0]->m_shared_mem, fname , "%08x"); + for(int i=0; i<32*m_warp_count;i++) + { + char fname[2048]; + snprintf(fname,2048,"checkpoint_files/thread_%d_%d_reg.txt",i,ctaid-1 ); + m_thread[i]->print_reg_thread(fname); + char f1name[2048]; + snprintf(f1name,2048,"checkpoint_files/local_mem_thread_%d_%d_reg.txt",i,ctaid-1 ); + g_checkpoint->store_global_mem(m_thread[i]->m_local_mem, f1name , "%08x"); + m_thread[i]->set_done(); + m_thread[i]->exitCore(); + m_thread[i]->registerExit(); + } + + for(int i=0;iprint_checkpoint(fp); + fclose(fp); + } + } } diff --git a/src/cuda-sim/instructions.cc b/src/cuda-sim/instructions.cc index f57a3f7..31a33c6 100644 --- a/src/cuda-sim/instructions.cc +++ b/src/cuda-sim/instructions.cc @@ -183,7 +183,63 @@ void ptx_thread_info::set_reg( const symbol *reg, const ptx_reg_t &value ) m_last_set_operand_value = value; } +void ptx_thread_info::print_reg_thread(char * fname) +{ + + FILE *fp= fopen(fname,"w"); + assert(fp!=NULL); + + int size = m_regs.size(); + + if(size>0) + { + reg_map_t reg = m_regs.back(); + + typename reg_map_t::const_iterator it; + for (it = reg.begin(); it != reg.end(); ++it) + { + const std::string &name = it->first->name(); + const std::string &dec= it->first->decl_location(); + unsigned size = it->first->get_size_in_bytes(); + fprintf(fp,"%s %llu %s %d\n",name.c_str(),it->second, dec.c_str(),size ); + + } + //m_regs.pop_back(); + } + fclose(fp); + + } + +void ptx_thread_info::resume_reg_thread(char * fname, symbol_table * symtab) +{ + + FILE * fp2 = fopen(fname, "r"); + assert(fp2!=NULL); + //m_regs.push_back( reg_map_t() ); + char line [ 200 ]; + while ( fgets ( line, sizeof line, fp2 ) != NULL ) + { + symbol *reg; + char * pch; + unsigned size; + pch = strtok (line," "); + char * name =pch; + reg= symtab->lookup(name); + ptx_reg_t data; + pch = strtok (NULL," "); + data = atoi(pch); + pch = strtok (NULL," "); + char * decl= pch; + pch = strtok (NULL," "); + size = atoi(pch); + + + m_regs.back()[reg] = data; + } + fclose ( fp2 ); +} + ptx_reg_t ptx_thread_info::get_reg( const symbol *reg ) { diff --git a/src/gpgpu-sim/gpu-sim.cc b/src/gpgpu-sim/gpu-sim.cc index c706f23..79a6fcd 100644 --- a/src/gpgpu-sim/gpu-sim.cc +++ b/src/gpgpu-sim/gpu-sim.cc @@ -1414,19 +1414,38 @@ void shader_core_ctx::issue_block2core( kernel_info_t &kernel ) // bind functional simulation state of threads to hardware resources (simulation) warp_set_t warps; unsigned nthreads_in_block= 0; - + function_info *kernel_func_info = kernel.entry(); + symbol_table * symtab= kernel_func_info->get_symtab(); + unsigned ctaid= kernel.get_next_cta_id_single(); + checkpoint *g_checkpoint= new checkpoint(); for (unsigned i = start_thread; iwarp_size; nthreads_in_block += ptx_sim_init_thread(kernel,&m_thread[i],m_sid,i,cta_size-(i-start_thread),m_config->n_thread_per_shader,this,free_cta_hw_id,warp_id,m_cluster->get_gpu()); m_threadState[i].m_active = true; - + // load thread local memory and register file + if(m_gpu->resume_option==1 && kernel.get_uid()==m_gpu->resume_kernel && ctaid>=m_gpu->resume_CTA && ctaidcheckpoint_CTA_t ) + { + char fname[2048]; + snprintf(fname,2048,"checkpoint_files/thread_%d_%d_reg.txt",i%cta_size,ctaid ); + m_thread[i]->resume_reg_thread(fname,symtab); + char f1name[2048]; + snprintf(f1name,2048,"checkpoint_files/local_mem_thread_%d_%d_reg.txt",i%cta_size,ctaid); + g_checkpoint->load_global_mem(m_thread[i]->m_local_mem, f1name); + } + // warps.set( warp_id ); } assert( nthreads_in_block > 0 && nthreads_in_block <= m_config->n_thread_per_shader); // should be at least one, but less than max m_cta_status[free_cta_hw_id]=nthreads_in_block; - + if(m_gpu->resume_option==1 && kernel.get_uid()==m_gpu->resume_kernel && ctaid>=m_gpu->resume_CTA && ctaidcheckpoint_CTA_t ) + { + char f1name[2048]; + snprintf(f1name,2048,"checkpoint_files/shared_mem_%d.txt", ctaid); + + g_checkpoint->load_global_mem(m_thread[start_thread]->m_shared_mem, f1name); + } // now that we know which warps are used in this CTA, we can allocate // resources for use in CTA-wide barrier operations m_barriers.allocate_barrier(free_cta_hw_id,warps); -- cgit v1.3 From a98e7db0402054aee7332380f6679be8527fc844 Mon Sep 17 00:00:00 2001 From: Deval Shah Date: Wed, 30 Jan 2019 17:40:17 -0800 Subject: changes for Ubuntu 18.04 support --- libcuda/cuda_runtime_api.cc | 39 +++++++++++++++++++++++++++++++++++++++ src/abstract_hardware_model.h | 1 + 2 files changed, 40 insertions(+) (limited to 'src/abstract_hardware_model.h') diff --git a/libcuda/cuda_runtime_api.cc b/libcuda/cuda_runtime_api.cc index 95a3c24..042bebd 100644 --- a/libcuda/cuda_runtime_api.cc +++ b/libcuda/cuda_runtime_api.cc @@ -1199,6 +1199,35 @@ __host__ cudaError_t CUDARTAPI cudaGetDevice(int *device) *device = g_active_device; return g_last_cudaError = cudaSuccess; } +__host__ cudaError_t CUDARTAPI cudaDeviceGetLimit ( size_t* pValue, cudaLimit limit ) +{ + if(g_debug_execution >= 3){ + announce_call(__my_func__); + } + cuda_not_implemented(__my_func__,__LINE__); + return g_last_cudaError = cudaSuccess; + +} + +__host__ cudaError_t CUDARTAPI cudaCreateTextureObject ( cudaTextureObject_t* pTexObject, const cudaResourceDesc* pResDesc, const cudaTextureDesc* pTexDesc, const cudaResourceViewDesc* pResViewDesc ) +{ + if(g_debug_execution >= 3){ + announce_call(__my_func__); + } + cuda_not_implemented(__my_func__,__LINE__); + return g_last_cudaError = cudaSuccess; + +} + +__host__ cudaError_t CUDARTAPI cudaStreamGetPriority ( cudaStream_t hStream, int* priority ) +{ + if(g_debug_execution >= 3){ + announce_call(__my_func__); + } + cuda_not_implemented(__my_func__,__LINE__); + return g_last_cudaError = cudaSuccess; + +} __host__ cudaError_t CUDARTAPI cudaDeviceGetPCIBusId ( char *pciBusId, @@ -1235,6 +1264,16 @@ __host__ cudaError_t cudaIpcOpenMemHandle( return g_last_cudaError = cudaErrorUnknown; } +__host__ cudaError_t CUDARTAPI cudaDestroyTextureObject(cudaTextureObject_t texObject) +{ + if(g_debug_execution >= 3){ + announce_call(__my_func__); + } + cuda_not_implemented(__my_func__,__LINE__); + return g_last_cudaError = cudaErrorUnknown; +} + + /******************************************************************************* * * * * diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index 08aa88c..28a22e0 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -73,6 +73,7 @@ enum FuncCache #include typedef unsigned long long new_addr_type; +typedef unsigned long long cudaTextureObject_t; typedef unsigned address_type; typedef unsigned addr_t; -- cgit v1.3 From 73050b730b31e9f58f8c2a0bfc4b3a8cd92be7ff Mon Sep 17 00:00:00 2001 From: Suchita Pati Date: Wed, 10 Apr 2019 23:27:42 -0500 Subject: Adding texture Fix --- libcuda/cuda_runtime_api.cc | 28 ++++++++++++++++++++++++---- src/abstract_hardware_model.cc | 4 +++- src/abstract_hardware_model.h | 22 +++++++++++++++++++++- src/cuda-sim/cuda-sim.cc | 5 +++-- src/cuda-sim/cuda_device_runtime.cc | 3 ++- src/cuda-sim/instructions.cc | 5 +++-- 6 files changed, 56 insertions(+), 11 deletions(-) (limited to 'src/abstract_hardware_model.h') diff --git a/libcuda/cuda_runtime_api.cc b/libcuda/cuda_runtime_api.cc index cf16d9b..7569b20 100644 --- a/libcuda/cuda_runtime_api.cc +++ b/libcuda/cuda_runtime_api.cc @@ -1204,8 +1204,24 @@ __host__ cudaError_t CUDARTAPI cudaDeviceGetLimit ( size_t* pValue, cudaLimit li if(g_debug_execution >= 3){ announce_call(__my_func__); } - cuda_not_implemented(__my_func__,__LINE__); - return g_last_cudaError = cudaSuccess; + switch(limit) { + case 0: + *pValue=1024; + break; + case 2: + *pValue=8388608; + break; + case 3: + *pValue=2; + break; + case 4: + *pValue=2048; + break; + default: + printf("ERROR:Limit %s unimplemented \n",limit); + abort(); + } + return g_last_cudaError = cudaSuccess; } @@ -1571,7 +1587,7 @@ __host__ cudaError_t CUDARTAPI cudaStreamDestroy(cudaStream_t stream) #if (CUDART_VERSION >= 3000) //synchronization required for application using external libraries without explicit synchronization in the code to //avoid the stream_manager from spinning forever to destroy non-empty streams without making any forward progress. - synchronize(); + stream->synchronize(); g_stream_manager->destroy_stream(stream); #endif return g_last_cudaError = cudaSuccess; @@ -2702,6 +2718,7 @@ cudaError_t CUDARTAPI cudaDeviceSynchronize(void){ if(g_debug_execution >= 3){ announce_call(__my_func__); } + synchronize(); return g_last_cudaError = cudaSuccess; } @@ -3135,6 +3152,8 @@ __host__ cudaError_t CUDARTAPI cudaDeviceSetLimit(enum cudaLimit limit, size_t v } return g_last_cudaError = cudaSuccess; } + + #endif #endif @@ -3313,7 +3332,8 @@ kernel_info_t *gpgpu_cuda_ptx_sim_init_grid( const char *hostFun, announce_call(__my_func__); } function_info *entry = context->get_kernel(hostFun); - kernel_info_t *result = new kernel_info_t(gridDim,blockDim,entry); + gpgpu_t* gpu= context->get_device()->get_gpgpu(); + kernel_info_t *result = new kernel_info_t(gridDim,blockDim,entry,gpu->getNameArrayMapping(),gpu->getNameInfoMapping()); if( entry == NULL ) { printf("GPGPU-Sim PTX: ERROR launching kernel -- no PTX implementation found for %p\n", hostFun); abort(); diff --git a/src/abstract_hardware_model.cc b/src/abstract_hardware_model.cc index 307df40..3db87c9 100644 --- a/src/abstract_hardware_model.cc +++ b/src/abstract_hardware_model.cc @@ -688,7 +688,7 @@ unsigned g_kernel_launch_latency; unsigned kernel_info_t::m_next_uid = 1; -kernel_info_t::kernel_info_t( dim3 gridDim, dim3 blockDim, class function_info *entry ) +kernel_info_t::kernel_info_t( dim3 gridDim, dim3 blockDim, class function_info *entry, std::map NameToCudaArray, std::map NameToTexureInfo) { m_kernel_entry=entry; m_grid_dim=gridDim; @@ -708,6 +708,8 @@ kernel_info_t::kernel_info_t( dim3 gridDim, dim3 blockDim, class function_info * m_launch_latency = g_kernel_launch_latency; volta_cache_config_set=false; + m_NameToCudaArray = NameToCudaArray; + m_NameToTexureInfo = NameToTexureInfo; } kernel_info_t::~kernel_info_t() diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index 28a22e0..bbc31e5 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -212,7 +212,7 @@ public: // m_num_cores_running=0; // m_param_mem=NULL; // } - kernel_info_t( dim3 gridDim, dim3 blockDim, class function_info *entry ); + kernel_info_t( dim3 gridDim, dim3 blockDim, class function_info *entry, std::map m_NameToCudaArray, std::map m_NameToTexureInfo); ~kernel_info_t(); void inc_running() { m_num_cores_running++; } @@ -275,6 +275,20 @@ public: std::list &active_threads() { return m_active_threads; } class memory_space *get_param_memory() { return m_param_mem; } + const struct cudaArray* get_texarray( const std::string &texname ) const + { + std::map::const_iterator t=m_NameToCudaArray.find(texname); + assert(t != m_NameToCudaArray.end()); + return t->second; + } + + const struct textureInfo* get_texinfo( const std::string &texname ) const + { + std::map::const_iterator t=m_NameToTexureInfo.find(texname); + assert(t != m_NameToTexureInfo.end()); + return t->second; + } + private: kernel_info_t( const kernel_info_t & ); // disable copy constructor void operator=( const kernel_info_t & ); // disable copy operator @@ -284,6 +298,9 @@ private: unsigned m_uid; static unsigned m_next_uid; + std::map m_NameToCudaArray; + std::map m_NameToTexureInfo; + dim3 m_grid_dim; dim3 m_block_dim; dim3 m_next_cta; @@ -595,6 +612,9 @@ public: const gpgpu_functional_sim_config &get_config() const { return m_function_model_config; } FILE* get_ptx_inst_debug_file() { return ptx_inst_debug_file; } + std::map getNameArrayMapping() {return m_NameToCudaArray;} + std::map getNameInfoMapping() {return m_NameToTexureInfo;} + protected: const gpgpu_functional_sim_config &m_function_model_config; FILE* ptx_inst_debug_file; diff --git a/src/cuda-sim/cuda-sim.cc b/src/cuda-sim/cuda-sim.cc index ec68b5b..a51ea3e 100644 --- a/src/cuda-sim/cuda-sim.cc +++ b/src/cuda-sim/cuda-sim.cc @@ -1507,7 +1507,8 @@ static unsigned get_tex_datasize( const ptx_instruction *pI, ptx_thread_info *th std::string texname = src1.name(); gpgpu_t *gpu = thread->get_gpu(); - const struct textureInfo* texInfo = gpu->get_texinfo(texname); + kernel_info_t& k = thread->get_kernel(); + const struct textureInfo* texInfo = k.get_texinfo(texname); unsigned data_size = texInfo->texel_size; return data_size; @@ -1918,7 +1919,7 @@ kernel_info_t *gpgpu_opencl_ptx_sim_init_grid(class function_info *entry, struct dim3 blockDim, gpgpu_t *gpu ) { - kernel_info_t *result = new kernel_info_t(gridDim,blockDim,entry); + kernel_info_t *result = new kernel_info_t(gridDim,blockDim,entry,gpu->getNameArrayMapping(),gpu->getNameInfoMapping()); unsigned argcount=args.size(); unsigned argn=1; for( gpgpu_ptx_sim_arg_list_t::iterator a = args.begin(); a != args.end(); a++ ) { diff --git a/src/cuda-sim/cuda_device_runtime.cc b/src/cuda-sim/cuda_device_runtime.cc index b399133..917e7a8 100644 --- a/src/cuda-sim/cuda_device_runtime.cc +++ b/src/cuda-sim/cuda_device_runtime.cc @@ -198,7 +198,8 @@ void gpgpusim_cuda_launchDeviceV2(const ptx_instruction * pI, ptx_thread_info * 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); + gpgpu_t* gpu=thread->get_gpu(); + device_grid = new kernel_info_t(config.grid_dim, config.block_dim, device_kernel_entry, gpu->getNameArrayMapping(), gpu->getNameInfoMapping()); 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 (" << diff --git a/src/cuda-sim/instructions.cc b/src/cuda-sim/instructions.cc index c85654c..d29fc8b 100644 --- a/src/cuda-sim/instructions.cc +++ b/src/cuda-sim/instructions.cc @@ -5260,9 +5260,10 @@ void tex_impl( const ptx_instruction *pI, ptx_thread_info *thread ) thread->get_vector_operand_values(src2, ptx_tex_regs, nelem); //ptx_reg should be 4 entry vector type...coordinates into texture gpgpu_t *gpu = thread->get_gpu(); + kernel_info_t &k = thread->get_kernel(); const struct textureReference* texref = gpu->get_texref(texname); - const struct cudaArray* cuArray = gpu->get_texarray(texname); - const struct textureInfo* texInfo = gpu->get_texinfo(texname); + const struct cudaArray* cuArray = k.get_texarray(texname); + const struct textureInfo* texInfo = k.get_texinfo(texname); const struct textureReferenceAttr* texAttr = gpu->get_texattr(texname); //assume always 2D f32 input -- cgit v1.3 From 69af057daf1999f17b81d761c7a616f67f56adbb Mon Sep 17 00:00:00 2001 From: Suchita Pati Date: Tue, 16 Apr 2019 23:36:02 -0500 Subject: Adding additional fixes for the texture bugs --- libcuda/cuda_runtime_api.cc | 22 ++++++++++++---------- src/abstract_hardware_model.cc | 13 ++++++++++--- src/abstract_hardware_model.h | 36 +++++++++++++++++++++--------------- src/cuda-sim/cuda-sim.cc | 7 +++++++ src/cuda-sim/instructions.cc | 8 +++++++- 5 files changed, 57 insertions(+), 29 deletions(-) (limited to 'src/abstract_hardware_model.h') diff --git a/libcuda/cuda_runtime_api.cc b/libcuda/cuda_runtime_api.cc index 7569b20..f6e5e6f 100644 --- a/libcuda/cuda_runtime_api.cc +++ b/libcuda/cuda_runtime_api.cc @@ -1121,10 +1121,10 @@ __host__ cudaError_t CUDARTAPI cudaDeviceGetAttribute(int *value, enum cudaDevic *value= 0; break; case 75: - *value= 9 ; + *value= 7 ; break; case 76: - *value= 3 ; + *value= 0 ; break; case 78: *value= 0 ; //TODO: as of now, we dont support stream priorities. @@ -1199,22 +1199,23 @@ __host__ cudaError_t CUDARTAPI cudaGetDevice(int *device) *device = g_active_device; return g_last_cudaError = cudaSuccess; } + __host__ cudaError_t CUDARTAPI cudaDeviceGetLimit ( size_t* pValue, cudaLimit limit ) { if(g_debug_execution >= 3){ announce_call(__my_func__); } switch(limit) { - case 0: + case 0: // cudaLimitStackSize *pValue=1024; break; - case 2: + case 2: // cudaLimitMallocHeapSize *pValue=8388608; break; - case 3: + case 3: // cudaLimitDevRuntimeSyncDepth *pValue=2; break; - case 4: + case 4: // cudaLimitDevRuntimePendingLaunchCount *pValue=2048; break; default: @@ -1225,7 +1226,6 @@ __host__ cudaError_t CUDARTAPI cudaDeviceGetLimit ( size_t* pValue, cudaLimit li } - __host__ cudaError_t CUDARTAPI cudaStreamGetPriority ( cudaStream_t hStream, int* priority ) { if(g_debug_execution >= 3){ @@ -1585,7 +1585,7 @@ __host__ cudaError_t CUDARTAPI cudaStreamDestroy(cudaStream_t stream) announce_call(__my_func__); } #if (CUDART_VERSION >= 3000) - //synchronization required for application using external libraries without explicit synchronization in the code to + //per-stream synchronization required for application using external libraries without explicit synchronization in the code to //avoid the stream_manager from spinning forever to destroy non-empty streams without making any forward progress. stream->synchronize(); g_stream_manager->destroy_stream(stream); @@ -2714,7 +2714,6 @@ cudaError_t cudaDeviceReset ( void ) { return g_last_cudaError = cudaSuccess; } cudaError_t CUDARTAPI cudaDeviceSynchronize(void){ - // I don't know what this should do if(g_debug_execution >= 3){ announce_call(__my_func__); } @@ -2722,7 +2721,6 @@ cudaError_t CUDARTAPI cudaDeviceSynchronize(void){ return g_last_cudaError = cudaSuccess; } - void CUDARTAPI __cudaRegisterFunction( void **fatCubinHandle, const char *hostFun, @@ -3333,6 +3331,10 @@ kernel_info_t *gpgpu_cuda_ptx_sim_init_grid( const char *hostFun, } function_info *entry = context->get_kernel(hostFun); gpgpu_t* gpu= context->get_device()->get_gpgpu(); + /* + Passing a snapshot of the GPU's current texture mapping to the kernel's info + as kernels should use texture bindings present at the time of their launch. + */ kernel_info_t *result = new kernel_info_t(gridDim,blockDim,entry,gpu->getNameArrayMapping(),gpu->getNameInfoMapping()); if( entry == NULL ) { printf("GPGPU-Sim PTX: ERROR launching kernel -- no PTX implementation found for %p\n", hostFun); diff --git a/src/abstract_hardware_model.cc b/src/abstract_hardware_model.cc index 3db87c9..820f5fd 100644 --- a/src/abstract_hardware_model.cc +++ b/src/abstract_hardware_model.cc @@ -192,6 +192,9 @@ gpgpu_t::gpgpu_t( const gpgpu_functional_sim_config &config ) checkpoint_CTA_t = m_function_model_config.get_checkpoint_CTA_t(); checkpoint_insn_Y = m_function_model_config.get_checkpoint_insn_Y(); + // initialize texture mappings to empty + m_NameToTextureInfo.clear(); + m_NameToCudaArray.clear(); if(m_function_model_config.get_ptx_inst_debug_to_file() != 0) ptx_inst_debug_file = fopen(m_function_model_config.get_ptx_inst_debug_file(), "w"); @@ -688,7 +691,11 @@ unsigned g_kernel_launch_latency; unsigned kernel_info_t::m_next_uid = 1; -kernel_info_t::kernel_info_t( dim3 gridDim, dim3 blockDim, class function_info *entry, std::map NameToCudaArray, std::map NameToTexureInfo) +/*A snapshot of the texture mappings needs to be stored in the kernel's info as +kernels should use the texture bindings seen at the time of launch and textures + can be bound/unbound asynchronously with respect to streams. */ + +kernel_info_t::kernel_info_t( dim3 gridDim, dim3 blockDim, class function_info *entry, std::map nameToCudaArray, std::map nameToTexureInfo) { m_kernel_entry=entry; m_grid_dim=gridDim; @@ -708,8 +715,8 @@ kernel_info_t::kernel_info_t( dim3 gridDim, dim3 blockDim, class function_info * m_launch_latency = g_kernel_launch_latency; volta_cache_config_set=false; - m_NameToCudaArray = NameToCudaArray; - m_NameToTexureInfo = NameToTexureInfo; + m_NameToCudaArray = nameToCudaArray; + m_NameToTexureInfo = nameToTexureInfo; } kernel_info_t::~kernel_info_t() diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index bbc31e5..201b21f 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -212,7 +212,7 @@ public: // m_num_cores_running=0; // m_param_mem=NULL; // } - kernel_info_t( dim3 gridDim, dim3 blockDim, class function_info *entry, std::map m_NameToCudaArray, std::map m_NameToTexureInfo); + kernel_info_t( dim3 gridDim, dim3 blockDim, class function_info *entry, std::map nameToCudaArray, std::map nameToTexureInfo); ~kernel_info_t(); void inc_running() { m_num_cores_running++; } @@ -275,19 +275,22 @@ public: std::list &active_threads() { return m_active_threads; } class memory_space *get_param_memory() { return m_param_mem; } + + //The following functions access texture bindings present at the kernel's launch + const struct cudaArray* get_texarray( const std::string &texname ) const - { - std::map::const_iterator t=m_NameToCudaArray.find(texname); - assert(t != m_NameToCudaArray.end()); - return t->second; - } + { + std::map::const_iterator t=m_NameToCudaArray.find(texname); + assert(t != m_NameToCudaArray.end()); + return t->second; + } - const struct textureInfo* get_texinfo( const std::string &texname ) const - { - std::map::const_iterator t=m_NameToTexureInfo.find(texname); - assert(t != m_NameToTexureInfo.end()); - return t->second; - } + const struct textureInfo* get_texinfo( const std::string &texname ) const + { + std::map::const_iterator t=m_NameToTexureInfo.find(texname); + assert(t != m_NameToTexureInfo.end()); + return t->second; + } private: kernel_info_t( const kernel_info_t & ); // disable copy constructor @@ -297,7 +300,8 @@ private: unsigned m_uid; static unsigned m_next_uid; - + + //These maps contain the snapshot of the texture mappings at kernel launch std::map m_NameToCudaArray; std::map m_NameToTexureInfo; @@ -611,7 +615,9 @@ public: const gpgpu_functional_sim_config &get_config() const { return m_function_model_config; } FILE* get_ptx_inst_debug_file() { return ptx_inst_debug_file; } - + + // These maps return the current texture mappings for the GPU at any given time. + std::map getNameArrayMapping() {return m_NameToCudaArray;} std::map getNameInfoMapping() {return m_NameToTexureInfo;} @@ -624,7 +630,7 @@ protected: class memory_space *m_surf_mem; unsigned long long m_dev_malloc; - + // These maps contain the current texture mappings for the GPU at any given time. std::map > m_NameToTextureRef; std::map m_TextureRefToName; std::map m_NameToCudaArray; diff --git a/src/cuda-sim/cuda-sim.cc b/src/cuda-sim/cuda-sim.cc index a51ea3e..9d59411 100644 --- a/src/cuda-sim/cuda-sim.cc +++ b/src/cuda-sim/cuda-sim.cc @@ -1507,6 +1507,13 @@ static unsigned get_tex_datasize( const ptx_instruction *pI, ptx_thread_info *th std::string texname = src1.name(); gpgpu_t *gpu = thread->get_gpu(); + /* + For programs with many streams, textures can be bound and unbound + asynchronously. This means we need to use the kernel's "snapshot" of + the state of the texture mappings when it was launched (so that we + don't try to access the incorrect texture mapping if it's been updated, + or that we don't access a mapping that has been unbound). + */ kernel_info_t& k = thread->get_kernel(); const struct textureInfo* texInfo = k.get_texinfo(texname); diff --git a/src/cuda-sim/instructions.cc b/src/cuda-sim/instructions.cc index d29fc8b..11001d7 100644 --- a/src/cuda-sim/instructions.cc +++ b/src/cuda-sim/instructions.cc @@ -5258,7 +5258,13 @@ void tex_impl( const ptx_instruction *pI, ptx_thread_info *thread ) if (!ptx_tex_regs) ptx_tex_regs = new ptx_reg_t[4]; unsigned nelem = src2.get_vect_nelem(); thread->get_vector_operand_values(src2, ptx_tex_regs, nelem); //ptx_reg should be 4 entry vector type...coordinates into texture - + /* + For programs with many streams, textures can be bound and unbound + asynchronously. This means we need to use the kernel's "snapshot" of + the state of the texture mappings when it was launched (so that we + don't try to access the incorrect texture mapping if it's been updated, + or that we don't access a mapping that has been unbound). + */ gpgpu_t *gpu = thread->get_gpu(); kernel_info_t &k = thread->get_kernel(); const struct textureReference* texref = gpu->get_texref(texname); -- cgit v1.3 From 49c6eeff7752b5816fb08c0d6baf2b47c789bc18 Mon Sep 17 00:00:00 2001 From: Suchita Pati Date: Wed, 17 Apr 2019 22:09:17 -0500 Subject: Adding configs for device limits and fixed other misc bugs --- libcuda/cuda_runtime_api.cc | 11 +++++++---- src/abstract_hardware_model.cc | 9 ++++----- src/abstract_hardware_model.h | 17 ++++++++--------- src/cuda-sim/cuda-sim.cc | 4 ++-- src/gpgpu-sim/gpu-sim.cc | 8 ++++++++ src/gpgpu-sim/gpu-sim.h | 11 ++++++++++- 6 files changed, 39 insertions(+), 21 deletions(-) (limited to 'src/abstract_hardware_model.h') diff --git a/libcuda/cuda_runtime_api.cc b/libcuda/cuda_runtime_api.cc index f6e5e6f..86435b9 100644 --- a/libcuda/cuda_runtime_api.cc +++ b/libcuda/cuda_runtime_api.cc @@ -1205,18 +1205,20 @@ __host__ cudaError_t CUDARTAPI cudaDeviceGetLimit ( size_t* pValue, cudaLimit li if(g_debug_execution >= 3){ announce_call(__my_func__); } + _cuda_device_id *dev = GPGPUSim_Init(); + const gpgpu_sim_config& config=dev->get_gpgpu()->get_config(); switch(limit) { case 0: // cudaLimitStackSize - *pValue=1024; + *pValue=config.stack_limit(); break; case 2: // cudaLimitMallocHeapSize - *pValue=8388608; + *pValue=config.heap_limit(); break; case 3: // cudaLimitDevRuntimeSyncDepth - *pValue=2; + *pValue=config.sync_depth_limit(); break; case 4: // cudaLimitDevRuntimePendingLaunchCount - *pValue=2048; + *pValue=config.pending_launch_count_limit(); break; default: printf("ERROR:Limit %s unimplemented \n",limit); @@ -2717,6 +2719,7 @@ cudaError_t CUDARTAPI cudaDeviceSynchronize(void){ if(g_debug_execution >= 3){ announce_call(__my_func__); } + //Blocks until the device has completed all preceding requested tasks synchronize(); return g_last_cudaError = cudaSuccess; } diff --git a/src/abstract_hardware_model.cc b/src/abstract_hardware_model.cc index 820f5fd..cebdb25 100644 --- a/src/abstract_hardware_model.cc +++ b/src/abstract_hardware_model.cc @@ -88,8 +88,6 @@ void checkpoint::load_global_mem(class memory_space *temp_mem, char * f1name) fclose ( fp2 ); } - - void checkpoint::store_global_mem(class memory_space * mem, char *fname, char * format) { @@ -195,6 +193,8 @@ gpgpu_t::gpgpu_t( const gpgpu_functional_sim_config &config ) // initialize texture mappings to empty m_NameToTextureInfo.clear(); m_NameToCudaArray.clear(); + m_TextureRefToName.clear(); + m_NameToAttribute.clear(); if(m_function_model_config.get_ptx_inst_debug_to_file() != 0) ptx_inst_debug_file = fopen(m_function_model_config.get_ptx_inst_debug_file(), "w"); @@ -694,8 +694,7 @@ unsigned kernel_info_t::m_next_uid = 1; /*A snapshot of the texture mappings needs to be stored in the kernel's info as kernels should use the texture bindings seen at the time of launch and textures can be bound/unbound asynchronously with respect to streams. */ - -kernel_info_t::kernel_info_t( dim3 gridDim, dim3 blockDim, class function_info *entry, std::map nameToCudaArray, std::map nameToTexureInfo) +kernel_info_t::kernel_info_t( dim3 gridDim, dim3 blockDim, class function_info *entry, std::map nameToCudaArray, std::map nameToTextureInfo) { m_kernel_entry=entry; m_grid_dim=gridDim; @@ -716,7 +715,7 @@ kernel_info_t::kernel_info_t( dim3 gridDim, dim3 blockDim, class function_info * volta_cache_config_set=false; m_NameToCudaArray = nameToCudaArray; - m_NameToTexureInfo = nameToTexureInfo; + m_NameToTextureInfo = nameToTextureInfo; } kernel_info_t::~kernel_info_t() diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index 201b21f..e8716ab 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -212,7 +212,7 @@ public: // m_num_cores_running=0; // m_param_mem=NULL; // } - kernel_info_t( dim3 gridDim, dim3 blockDim, class function_info *entry, std::map nameToCudaArray, std::map nameToTexureInfo); + kernel_info_t( dim3 gridDim, dim3 blockDim, class function_info *entry, std::map nameToCudaArray, std::map nameToTextureInfo); ~kernel_info_t(); void inc_running() { m_num_cores_running++; } @@ -287,8 +287,8 @@ public: const struct textureInfo* get_texinfo( const std::string &texname ) const { - std::map::const_iterator t=m_NameToTexureInfo.find(texname); - assert(t != m_NameToTexureInfo.end()); + std::map::const_iterator t=m_NameToTextureInfo.find(texname); + assert(t != m_NameToTextureInfo.end()); return t->second; } @@ -303,7 +303,7 @@ private: //These maps contain the snapshot of the texture mappings at kernel launch std::map m_NameToCudaArray; - std::map m_NameToTexureInfo; + std::map m_NameToTextureInfo; dim3 m_grid_dim; dim3 m_block_dim; @@ -601,8 +601,8 @@ public: const struct textureInfo* get_texinfo( const std::string &texname ) const { - std::map::const_iterator t=m_NameToTexureInfo.find(texname); - assert(t != m_NameToTexureInfo.end()); + std::map::const_iterator t=m_NameToTextureInfo.find(texname); + assert(t != m_NameToTextureInfo.end()); return t->second; } @@ -617,9 +617,8 @@ public: FILE* get_ptx_inst_debug_file() { return ptx_inst_debug_file; } // These maps return the current texture mappings for the GPU at any given time. - std::map getNameArrayMapping() {return m_NameToCudaArray;} - std::map getNameInfoMapping() {return m_NameToTexureInfo;} + std::map getNameInfoMapping() {return m_NameToTextureInfo;} protected: const gpgpu_functional_sim_config &m_function_model_config; @@ -634,7 +633,7 @@ protected: std::map > m_NameToTextureRef; std::map m_TextureRefToName; std::map m_NameToCudaArray; - std::map m_NameToTexureInfo; + std::map m_NameToTextureInfo; std::map m_NameToAttribute; }; diff --git a/src/cuda-sim/cuda-sim.cc b/src/cuda-sim/cuda-sim.cc index 9d59411..f7bb9cc 100644 --- a/src/cuda-sim/cuda-sim.cc +++ b/src/cuda-sim/cuda-sim.cc @@ -218,7 +218,7 @@ void gpgpu_t::gpgpu_ptx_sim_bindTextureToArray(const struct textureReference* te texInfo->Ty_numbits = intLOGB2(Ty); texInfo->texel_size = texel_size; texInfo->texel_size_numbits = intLOGB2(texel_size); - m_NameToTexureInfo[texname] = texInfo; + m_NameToTextureInfo[texname] = texInfo; } void gpgpu_t::gpgpu_ptx_sim_unbindTexture(const struct textureReference* texref) @@ -226,7 +226,7 @@ void gpgpu_t::gpgpu_ptx_sim_unbindTexture(const struct textureReference* texref) //assumes bind-use-unbind-bind-use-unbind pattern std::string texname = gpgpu_ptx_sim_findNamefromTexture(texref); m_NameToCudaArray.erase(texname); - m_NameToTexureInfo.erase(texname); + m_NameToTextureInfo.erase(texname); } unsigned g_assemble_code_next_pc=0; diff --git a/src/gpgpu-sim/gpu-sim.cc b/src/gpgpu-sim/gpu-sim.cc index ec570bf..2a862a4 100644 --- a/src/gpgpu-sim/gpu-sim.cc +++ b/src/gpgpu-sim/gpu-sim.cc @@ -532,6 +532,14 @@ void gpgpu_sim_config::reg_options(option_parser_t opp) option_parser_register(opp, "-visualizer_zlevel", OPT_INT32, &g_visualizer_zlevel, "Compression level of the visualizer output log (0=no comp, 9=highest)", "6"); + option_parser_register(opp, "-gpgpu_stack_size_limit", OPT_INT32, &stack_size_limit, + "GPU thread stack size", "1024" ); + option_parser_register(opp, "-gpgpu_heap_size_limit", OPT_INT32, &heap_size_limit, + "GPU malloc heap size ", "8388608" ); + option_parser_register(opp, "-gpgpu_runtime_sync_depth_limit", OPT_INT32, &runtime_sync_depth_limit, + "GPU device runtime synchronize depth", "2" ); + option_parser_register(opp, "-gpgpu_runtime_pending_launch_count_limit", OPT_INT32, &runtime_pending_launch_count_limit, + "GPU device runtime pending launch count", "2048" ); option_parser_register(opp, "-trace_enabled", OPT_BOOL, &Trace::enabled, "Turn on traces", "0"); diff --git a/src/gpgpu-sim/gpu-sim.h b/src/gpgpu-sim/gpu-sim.h index 6ce5524..11ffe49 100644 --- a/src/gpgpu-sim/gpu-sim.h +++ b/src/gpgpu-sim/gpu-sim.h @@ -337,6 +337,11 @@ public: unsigned get_max_concurrent_kernel() const { return max_concurrent_kernel; } unsigned checkpoint_option; + size_t stack_limit() const {return stack_size_limit; } + size_t heap_limit() const {return heap_size_limit; } + size_t sync_depth_limit() const {return runtime_sync_depth_limit; } + size_t pending_launch_count_limit() const {return runtime_pending_launch_count_limit;} + private: void init_clock_domains(void ); @@ -377,7 +382,11 @@ private: int gpu_stat_sample_freq; int gpu_runtime_stat_flag; - + // Device Limits + size_t stack_size_limit; + size_t heap_size_limit; + size_t runtime_sync_depth_limit; + size_t runtime_pending_launch_count_limit; unsigned long long liveness_message_freq; -- cgit v1.3 From e7186c0f8232cfd857263d460c3bcd93a7a33877 Mon Sep 17 00:00:00 2001 From: Mahmoud Date: Wed, 8 May 2019 11:25:29 -0400 Subject: fixing the building fail --- src/abstract_hardware_model.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/abstract_hardware_model.h') diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index e8716ab..22ef509 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -386,6 +386,8 @@ struct core_config { unsigned gpgpu_max_insn_issue_per_warp; bool gmem_skip_L1D; // on = global memory access always skip the L1 cache + + bool adaptive_volta_cache_config; }; // bounded stack that implements simt reconvergence using pdom mechanism from MICRO'07 paper -- cgit v1.3 From 37a709bb69fcd9f2b0fe53a189e92e548164cc4b Mon Sep 17 00:00:00 2001 From: Mahmoud Date: Wed, 5 Jun 2019 19:18:29 -0400 Subject: adding new cuda 9 APIs to run the deepbench workloads --- Makefile | 2 ++ libcuda/cuda_runtime_api.cc | 70 +++++++++++++++++++++++++++++++++++++++++- linux-so-version.txt | 4 +++ src/abstract_hardware_model.cc | 22 +++++++++++++ src/abstract_hardware_model.h | 1 + src/gpgpu-sim/gpu-sim.cc | 10 ++++++ src/gpgpu-sim/gpu-sim.h | 2 ++ 7 files changed, 110 insertions(+), 1 deletion(-) (limited to 'src/abstract_hardware_model.h') diff --git a/Makefile b/Makefile index 2d0466e..e1e9aaa 100644 --- a/Makefile +++ b/Makefile @@ -159,10 +159,12 @@ $(SIM_LIB_DIR)/libcudart.so: makedirs $(LIBS) cudalib if [ ! -f $(SIM_LIB_DIR)/libcudart.so.5.5 ]; then ln -s libcudart.so $(SIM_LIB_DIR)/libcudart.so.5.5; fi if [ ! -f $(SIM_LIB_DIR)/libcudart.so.6.0 ]; then ln -s libcudart.so $(SIM_LIB_DIR)/libcudart.so.6.0; fi if [ ! -f $(SIM_LIB_DIR)/libcudart.so.6.5 ]; then ln -s libcudart.so $(SIM_LIB_DIR)/libcudart.so.6.5; fi + if [ ! -f $(SIM_LIB_DIR)/libcudart.so.7.0 ]; then ln -s libcudart.so $(SIM_LIB_DIR)/libcudart.so.7.0; fi if [ ! -f $(SIM_LIB_DIR)/libcudart.so.7.5 ]; then ln -s libcudart.so $(SIM_LIB_DIR)/libcudart.so.7.5; fi if [ ! -f $(SIM_LIB_DIR)/libcudart.so.8.0 ]; then ln -s libcudart.so $(SIM_LIB_DIR)/libcudart.so.8.0; fi if [ ! -f $(SIM_LIB_DIR)/libcudart.so.9.0 ]; then ln -s libcudart.so $(SIM_LIB_DIR)/libcudart.so.9.0; fi if [ ! -f $(SIM_LIB_DIR)/libcudart.so.9.1 ]; then ln -s libcudart.so $(SIM_LIB_DIR)/libcudart.so.9.1; fi + if [ ! -f $(SIM_LIB_DIR)/libcudart.so.9.2 ]; then ln -s libcudart.so $(SIM_LIB_DIR)/libcudart.so.9.2; fi $(SIM_LIB_DIR)/libcudart.dylib: makedirs $(LIBS) cudalib g++ -dynamiclib -Wl,-headerpad_max_install_names,-undefined,dynamic_lookup,-compatibility_version,1.1,-current_version,1.1\ diff --git a/libcuda/cuda_runtime_api.cc b/libcuda/cuda_runtime_api.cc index 3a9d613..2cc84aa 100644 --- a/libcuda/cuda_runtime_api.cc +++ b/libcuda/cuda_runtime_api.cc @@ -974,6 +974,30 @@ __host__ cudaError_t CUDARTAPI cudaGetDeviceProperties(struct cudaDeviceProp *pr } } +#if (CUDART_VERSION >= 8000) +cudaError_t CUDARTAPI cudaOccupancyMaxActiveBlocksPerMultiprocessorWithFlags(int* numBlocks, const char *hostFunc, int blockSize, size_t dynamicSMemSize, unsigned int flags) +{ + printf("GPGPU-Sim PTX: cudaOccupancyMaxActiveBlocksPerMultiprocessorWithFlags %p\n", hostFunc); + CUctx_st *context = GPGPUSim_Context(); + function_info *entry = context->get_kernel(hostFunc); + printf("Calculate Maxium Active Block with function ptr=%p, blockSize=%d, SMemSize=%d\n", hostFunc, blockSize, dynamicSMemSize); + if (flags == cudaOccupancyDefault) { + //create kernel_info based on entry + dim3 gridDim(context->get_device()->get_gpgpu()->max_cta_per_core() + * context->get_device()->get_gpgpu()->get_config().num_shader()); + dim3 blockDim(blockSize); + kernel_info_t result(gridDim, blockDim, entry); + *numBlocks = context->get_device()->get_gpgpu()->get_max_cta(result); + printf("Maximum size is %d with gridDim %d and blockDim %d\n", *numBlocks, gridDim.x, blockDim.x); + return g_last_cudaError = cudaSuccess; + } else { + cuda_not_implemented(__my_func__,__LINE__); + return g_last_cudaError = cudaErrorUnknown; + } +} + +#endif + #if (CUDART_VERSION > 5000) __host__ cudaError_t CUDARTAPI cudaDeviceGetAttribute(int *value, enum cudaDeviceAttr attr, int device) { @@ -3169,6 +3193,23 @@ __host__ cudaError_t CUDARTAPI cudaDeviceSetLimit(enum cudaLimit limit, size_t v return g_last_cudaError = cudaSuccess; } +#if CUDART_VERSION >= 9000 +__host__ cudaError_t cudaFuncSetAttribute ( const void* func, enum cudaFuncAttribute attr, int value ) { + + //ignore this Attribute for now, and the default is that carveout = cudaSharedmemCarveoutDefault; // (-1) + return g_last_cudaError = cudaSuccess; +} + +#if CUDART_VERSION >= 9020 +__host__ __device__ unsigned __cudaPushCallConfiguration(dim3 gridDim, dim3 blockDim, + size_t sharedMem = 0, + void *stream = 0) { + + return 1; +} +#endif + +#endif #endif @@ -4071,6 +4112,33 @@ CUresult CUDAAPI cuMemHostRegister(void *p, size_t bytesize, unsigned int Flags) printf("WARNING: this function has not been implemented yet."); return CUDA_SUCCESS; } +__host__ cudaError_t cudaHostRegister(void* ptr, size_t size, unsigned int flags) +{ + if(g_debug_execution >= 3){ + announce_call(__my_func__); + } + printf("WARNING: this function has not been implemented yet."); + return g_last_cudaError = cudaSuccess; +} + +__host__ cudaError_t cudaProfilerStart ( ) +{ + if(g_debug_execution >= 3){ + announce_call(__my_func__); + } + printf("WARNING: this function has not been implemented yet."); + return g_last_cudaError = cudaSuccess; +} + +__host__ cudaError_t cudaProfilerStop ( ) +{ + if(g_debug_execution >= 3){ + announce_call(__my_func__); + } + printf("WARNING: this function has not been implemented yet."); + return g_last_cudaError = cudaSuccess; +} + #endif #if CUDART_VERSION >= 4000 @@ -4952,7 +5020,7 @@ CUresult CUDAAPI cuOccupancyMaxActiveBlocksPerMultiprocessorWithFlags(int *numBl printf("WARNING: this function has not been implemented yet."); return CUDA_SUCCESS; } - + CUresult CUDAAPI cuOccupancyMaxPotentialBlockSize(int *minGridSize, int *blockSize, CUfunction func, CUoccupancyB2DSize blockSizeToDynamicSMemSize, size_t dynamicSMemSize, int blockSizeLimit) { if(g_debug_execution >= 3){ diff --git a/linux-so-version.txt b/linux-so-version.txt index c6e03e9..a7c2d3c 100644 --- a/linux-so-version.txt +++ b/linux-so-version.txt @@ -1,4 +1,8 @@ +libcudart.so.9.0{ +}; libcudart.so.9.1{ }; +libcudart.so.9.2{ +}; libcuda.so.1{ }; diff --git a/src/abstract_hardware_model.cc b/src/abstract_hardware_model.cc index cebdb25..023f51b 100644 --- a/src/abstract_hardware_model.cc +++ b/src/abstract_hardware_model.cc @@ -691,6 +691,28 @@ unsigned g_kernel_launch_latency; unsigned kernel_info_t::m_next_uid = 1; +kernel_info_t::kernel_info_t( dim3 gridDim, dim3 blockDim, class function_info *entry) +{ + m_kernel_entry=entry; + m_grid_dim=gridDim; + m_block_dim=blockDim; + m_next_cta.x=0; + m_next_cta.y=0; + m_next_cta.z=0; + m_next_tid=m_next_cta; + 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; + + volta_cache_config_set=false; +} + /*A snapshot of the texture mappings needs to be stored in the kernel's info as kernels should use the texture bindings seen at the time of launch and textures can be bound/unbound asynchronously with respect to streams. */ diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index 22ef509..64bbaa2 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -212,6 +212,7 @@ public: // m_num_cores_running=0; // m_param_mem=NULL; // } + kernel_info_t( dim3 gridDim, dim3 blockDim, class function_info *entry); kernel_info_t( dim3 gridDim, dim3 blockDim, class function_info *entry, std::map nameToCudaArray, std::map nameToTextureInfo); ~kernel_info_t(); diff --git a/src/gpgpu-sim/gpu-sim.cc b/src/gpgpu-sim/gpu-sim.cc index c1ba934..6de5845 100644 --- a/src/gpgpu-sim/gpu-sim.cc +++ b/src/gpgpu-sim/gpu-sim.cc @@ -806,6 +806,16 @@ int gpgpu_sim::shader_clock() const return m_config.core_freq/1000; } +int gpgpu_sim::max_cta_per_core() const +{ + return m_shader_config->max_cta_per_core; +} + +int gpgpu_sim::get_max_cta( const kernel_info_t &k ) const +{ + return m_shader_config->max_cta(k); +} + void gpgpu_sim::set_prop( cudaDeviceProp *prop ) { m_cuda_properties = prop; diff --git a/src/gpgpu-sim/gpu-sim.h b/src/gpgpu-sim/gpu-sim.h index c8dad89..7336cac 100644 --- a/src/gpgpu-sim/gpu-sim.h +++ b/src/gpgpu-sim/gpu-sim.h @@ -455,6 +455,8 @@ public: int num_registers_per_block() const; int wrp_size() const; int shader_clock() const; + int max_cta_per_core() const; + int get_max_cta( const kernel_info_t &k ) const; const struct cudaDeviceProp *get_prop() const; enum divergence_support_t simd_model() const; -- cgit v1.3 From ba7145d18dd65391e9510664d26c963fcaab20ee Mon Sep 17 00:00:00 2001 From: "Mahmoud Khairy A. Abdallah" Date: Sun, 14 Jul 2019 10:58:39 -0400 Subject: fixing the volta local memory size per thread --- src/abstract_hardware_model.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/abstract_hardware_model.h') diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index 64bbaa2..27a1ba6 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -438,9 +438,9 @@ protected: #define GLOBAL_HEAP_START 0xC0000000 // start allocating from this address (lower values used for allocating globals in .ptx file) -#define SHARED_MEM_SIZE_MAX (64*1024) -#define LOCAL_MEM_SIZE_MAX (8*1024) -#define MAX_STREAMING_MULTIPROCESSORS 64 +#define SHARED_MEM_SIZE_MAX (96*1024) +#define LOCAL_MEM_SIZE_MAX (16*1024) +#define MAX_STREAMING_MULTIPROCESSORS 80 //scale it to Volta #define MAX_THREAD_PER_SM 2048 #define MAX_WARP_PER_SM 64 #define TOTAL_LOCAL_MEM_PER_SM (MAX_THREAD_PER_SM*LOCAL_MEM_SIZE_MAX) -- cgit v1.3