summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/abstract_hardware_model.cc27
-rw-r--r--src/abstract_hardware_model.h35
-rw-r--r--src/cuda-sim/cuda-sim.cc35
-rw-r--r--src/gpgpu-sim/gpu-sim.cc43
-rw-r--r--src/gpgpu-sim/shader.cc357
-rw-r--r--src/gpgpu-sim/shader.h97
6 files changed, 436 insertions, 158 deletions
diff --git a/src/abstract_hardware_model.cc b/src/abstract_hardware_model.cc
index dc1dc5c..307df40 100644
--- a/src/abstract_hardware_model.cc
+++ b/src/abstract_hardware_model.cc
@@ -411,7 +411,7 @@ 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 && m_config->gpgpu_coalesce_arch <= 62) {
+ if( m_config->gpgpu_coalesce_arch >= 13) {
if(isatomic())
memory_coalescing_arch_atomic(is_write, access_type);
else
@@ -466,7 +466,7 @@ void warp_inst_t::memory_coalescing_arch( bool is_write, mem_access_type access_
}
else if(m_config->gpgpu_coalesce_arch >= 40)
{
- //Maxwell and Pascal, L1 and L2 are sectors
+ //Maxwell, Pascal and Volta, L1 and L2 are sectors
//all requests should be 32 bytes
sector_segment_size = true;
}
@@ -538,11 +538,28 @@ void warp_inst_t::memory_coalescing_arch_atomic( bool is_write, mem_access_type
// see the CUDA manual where it discusses coalescing rules before reading this
unsigned segment_size = 0;
- unsigned warp_parts = 2;
+ 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, Pascal and Volta, 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;
diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h
index 2350db4..08aa88c 100644
--- a/src/abstract_hardware_model.h
+++ b/src/abstract_hardware_model.h
@@ -84,6 +84,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,
@@ -142,6 +144,7 @@ enum operation_pipeline_t {
UNKOWN_OP,
SP__OP,
DP__OP,
+ INTP__OP,
SFU__OP,
TENSOR_CORE__OP,
MEM__OP
@@ -353,6 +356,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;
@@ -949,7 +953,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;
@@ -960,6 +964,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
{
@@ -1093,6 +1098,7 @@ public:
void print( FILE *fout ) const;
unsigned get_uid() const { return m_uid; }
+ unsigned get_schd_id() const { return m_scheduler_id; }
protected:
@@ -1125,6 +1131,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;
@@ -1231,6 +1239,14 @@ public:
}
return false;
}
+ 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();
+ }
bool has_ready(){
for( unsigned i = 0; i < regs.size(); i++ ) {
if( not regs[i]->empty() ) {
@@ -1286,6 +1302,23 @@ public:
return NULL;
}
+ 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 &regs[reg_id];
+ }
+ assert(0 && "No free register found");
+ return NULL;
+ }
+
+ unsigned get_size(){
+ return regs.size();
+ }
+
private:
std::vector<warp_inst_t*> regs;
const char* m_name;
diff --git a/src/cuda-sim/cuda-sim.cc b/src/cuda-sim/cuda-sim.cc
index 642e301..3773f6f 100644
--- a/src/cuda-sim/cuda-sim.cc
+++ b/src/cuda-sim/cuda-sim.cc
@@ -64,8 +64,8 @@ int cp_cta_resume;
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];
@@ -86,6 +86,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 <ADD,MAX,MUL,MAD,DIV>"
"Default 1,1,4,4,32",
@@ -102,6 +106,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 <cudaStreamCreateWithFlags, \
cudaGetParameterBufferV2_init_perWarp, cudaGetParameterBufferV2_perKernel, \
@@ -644,10 +652,12 @@ void ptx_instruction::set_opcode_and_latency()
unsigned fp_latency[5];
unsigned dp_latency[5];
unsigned sfu_latency;
+ unsigned tensor_latency;
unsigned int_init[5];
unsigned fp_init[5];
unsigned dp_init[5];
unsigned sfu_init;
+ unsigned tensor_init;
/*
* [0] ADD,SUB
* [1] MAX,Min
@@ -666,6 +676,8 @@ void ptx_instruction::set_opcode_and_latency()
&dp_latency[3],&dp_latency[4]);
sscanf(opcode_latency_sfu, "%u",
&sfu_latency);
+ sscanf(opcode_latency_tensor, "%u",
+ &tensor_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]);
@@ -677,6 +689,8 @@ void ptx_instruction::set_opcode_and_latency()
&dp_init[3],&dp_init[4]);
sscanf(opcode_initiation_sfu, "%u",
&sfu_init);
+ sscanf(opcode_initiation_tensor, "%u",
+ &tensor_init);
sscanf(cdp_latency_str, "%u,%u,%u,%u,%u",
&cdp_latency[0],&cdp_latency[1],&cdp_latency[2],
&cdp_latency[3],&cdp_latency[4]);
@@ -736,6 +750,7 @@ void ptx_instruction::set_opcode_and_latency()
case F32_TYPE:
latency = fp_latency[0];
initiation_interval = fp_init[0];
+ op = SP_OP;
break;
case F64_TYPE:
case FF64_TYPE:
@@ -749,6 +764,7 @@ void ptx_instruction::set_opcode_and_latency()
default: //Use int settings for default
latency = int_latency[0];
initiation_interval = int_init[0];
+ op = INTP_OP;
break;
}
break;
@@ -758,6 +774,7 @@ void ptx_instruction::set_opcode_and_latency()
case F32_TYPE:
latency = fp_latency[1];
initiation_interval = fp_init[1];
+ op = SP_OP;
break;
case F64_TYPE:
case FF64_TYPE:
@@ -771,6 +788,7 @@ void ptx_instruction::set_opcode_and_latency()
default: //Use int settings for default
latency = int_latency[1];
initiation_interval = int_init[1];
+ op = INTP_OP;
break;
}
break;
@@ -780,6 +798,7 @@ void ptx_instruction::set_opcode_and_latency()
case F32_TYPE:
latency = fp_latency[2];
initiation_interval = fp_init[2];
+ op = SP_OP;
break;
case F64_TYPE:
case FF64_TYPE:
@@ -793,7 +812,7 @@ void ptx_instruction::set_opcode_and_latency()
default: //Use int settings for default
latency = int_latency[2];
initiation_interval = int_init[2];
- op = SFU_OP;
+ op = INTP_OP;
break;
}
break;
@@ -803,6 +822,7 @@ void ptx_instruction::set_opcode_and_latency()
case F32_TYPE:
latency = fp_latency[3];
initiation_interval = fp_init[3];
+ op = SP_OP;
break;
case F64_TYPE:
case FF64_TYPE:
@@ -816,7 +836,7 @@ void ptx_instruction::set_opcode_and_latency()
default: //Use int settings for default
latency = int_latency[3];
initiation_interval = int_init[3];
- op = SFU_OP;
+ op = INTP_OP;
break;
}
break;
@@ -843,15 +863,14 @@ 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 = sfu_latency;
initiation_interval = sfu_init;
op = SFU_OP;
break;
case MMA_OP:
- latency = 64;
- initiation_interval = 64;
- op=TENSOR_CORE_OP;
+ latency = tensor_latency;
+ initiation_interval = tensor_init;
+ 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 79a6fcd..ec570bf 100644
--- a/src/gpgpu-sim/gpu-sim.cc
+++ b/src/gpgpu-sim/gpu-sim.cc
@@ -336,6 +336,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");
@@ -354,8 +357,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)",
@@ -363,6 +372,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_int", OPT_INT32, &gpgpu_operand_collector_num_units_int,
+ "number of collector units (default = 0)",
+ "0");
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");
@@ -381,6 +393,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_int", OPT_INT32, &gpgpu_operand_collector_num_in_ports_int,
+ "number of collector unit in ports (default = 0)",
+ "0");
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");
@@ -399,6 +414,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_int", OPT_INT32, &gpgpu_operand_collector_num_out_ports_int,
+ "number of collector unit in ports (default = 0)",
+ "0");
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");
@@ -425,8 +443,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_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" );
+ "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",
+ "1,1,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");
@@ -436,6 +454,9 @@ void shader_core_config::reg_options(class OptionParser * opp)
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_int_units", OPT_INT32, &gpgpu_num_int_units,
+ "Number of INT 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");
@@ -1075,18 +1096,18 @@ void gpgpu_sim::gpu_print_stat()
printf("gpu_stall_dramfull = %d\n", gpu_stall_dramfull);
printf("gpu_stall_icnt2sh = %d\n", gpu_stall_icnt2sh );
- printf("partiton_reqs_in_parallel = %lld\n", partiton_reqs_in_parallel);
- printf("partiton_reqs_in_parallel_total = %lld\n", partiton_reqs_in_parallel_total );
+ //printf("partiton_reqs_in_parallel = %lld\n", partiton_reqs_in_parallel);
+ //printf("partiton_reqs_in_parallel_total = %lld\n", partiton_reqs_in_parallel_total );
printf("partiton_level_parallism = %12.4f\n", (float)partiton_reqs_in_parallel / gpu_sim_cycle);
printf("partiton_level_parallism_total = %12.4f\n", (float)(partiton_reqs_in_parallel+partiton_reqs_in_parallel_total) / (gpu_tot_sim_cycle+gpu_sim_cycle) );
- printf("partiton_reqs_in_parallel_util = %lld\n", partiton_reqs_in_parallel_util);
- printf("partiton_reqs_in_parallel_util_total = %lld\n", partiton_reqs_in_parallel_util_total );
- printf("gpu_sim_cycle_parition_util = %lld\n", gpu_sim_cycle_parition_util);
- printf("gpu_tot_sim_cycle_parition_util = %lld\n", gpu_tot_sim_cycle_parition_util );
+ //printf("partiton_reqs_in_parallel_util = %lld\n", partiton_reqs_in_parallel_util);
+ //printf("partiton_reqs_in_parallel_util_total = %lld\n", partiton_reqs_in_parallel_util_total );
+ //printf("gpu_sim_cycle_parition_util = %lld\n", gpu_sim_cycle_parition_util);
+ // printf("gpu_tot_sim_cycle_parition_util = %lld\n", gpu_tot_sim_cycle_parition_util );
printf("partiton_level_parallism_util = %12.4f\n", (float)partiton_reqs_in_parallel_util / gpu_sim_cycle_parition_util);
printf("partiton_level_parallism_util_total = %12.4f\n", (float)(partiton_reqs_in_parallel_util+partiton_reqs_in_parallel_util_total) / (gpu_sim_cycle_parition_util+gpu_tot_sim_cycle_parition_util) );
- printf("partiton_replys_in_parallel = %lld\n", partiton_replys_in_parallel);
- printf("partiton_replys_in_parallel_total = %lld\n", partiton_replys_in_parallel_total );
+ //printf("partiton_replys_in_parallel = %lld\n", partiton_replys_in_parallel);
+ //printf("partiton_replys_in_parallel_total = %lld\n", partiton_replys_in_parallel_total );
printf("L2_BW = %12.4f GB/Sec\n", ((float)(partiton_replys_in_parallel * 32) / (gpu_sim_cycle * m_config.icnt_period)) / 1000000000);
printf("L2_BW_total = %12.4f GB/Sec\n", ((float)((partiton_replys_in_parallel+partiton_replys_in_parallel_total) * 32) / ((gpu_tot_sim_cycle+gpu_sim_cycle) * m_config.icnt_period)) / 1000000000 );
diff --git a/src/gpgpu-sim/shader.cc b/src/gpgpu-sim/shader.cc
index faccf18..3db988b 100644
--- a/src/gpgpu-sim/shader.cc
+++ b/src/gpgpu-sim/shader.cc
@@ -90,6 +90,18 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu,
for (int j = 0; j<N_PIPELINE_STAGES; j++) {
m_pipeline_reg.push_back(register_set(m_config->pipe_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() );
+ 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() );
+ 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);
@@ -152,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
@@ -168,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,
@@ -185,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
@@ -201,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
)
@@ -217,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,
@@ -238,80 +255,106 @@ 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 };
- 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);
- 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);
-
+
+ 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;
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();
- }
+ //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 < 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]);
- 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();
- }
-
-
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);
+ 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();
}
+
+ 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(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]);
+ 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 < 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]);
+ 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();
+ }
+
+ 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 ];
@@ -328,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 ));
@@ -340,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);
@@ -802,15 +851,15 @@ 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 )
+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 = pipe_reg = pipe_reg_set.get_free(m_config->sub_core_model, sch_id);
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 ){
@@ -955,8 +1004,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();
@@ -990,70 +1039,101 @@ 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)||(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;
- }
+ 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;
+ 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();
- 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)) {
+ 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 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);
+ bool int_pipe_avail = m_int_out->has_free(m_shader->m_config->sub_core_model, m_id);
+
+ //This code need to be refactored
+ if(pI->op != TENSOR_CORE_OP && pI->op != SFU_OP && pI->op != DP_OP) {
- //Jin: special for CDP api
- if(pI->m_is_cdp && !warp(warp_id).m_cdp_dummy) {
- assert(warp(warp_id).m_cdp_latency == 0);
-
- extern unsigned cdp_latency[5];
- if(pI->m_is_cdp == 1)
- warp(warp_id).m_cdp_latency = cdp_latency[pI->m_is_cdp - 1];
- else //cudaLaunchDeviceV2 and cudaGetParameterBufferV2
- warp(warp_id).m_cdp_latency = cdp_latency[pI->m_is_cdp - 1]
- + cdp_latency[pI->m_is_cdp] * active_mask.count();
- warp(warp_id).m_cdp_dummy = true;
- break;
- }
- else if(pI->m_is_cdp && warp(warp_id).m_cdp_dummy) {
- assert(warp(warp_id).m_cdp_latency == 0);
- warp(warp_id).m_cdp_dummy = false;
- }
+ bool execute_on_SP = false;
+ bool execute_on_INT = false;
- // always prefer SP pipe for operations that can use both SP and SFU pipelines
- m_shader->issue_warp(*m_sp_out,pI,active_mask,warp_id);
- issued++;
- 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 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_shader->issue_warp(*m_dp_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::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_shader->issue_warp(*m_sfu_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::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_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
@@ -1241,11 +1321,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,
@@ -1818,6 +1899,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);
@@ -1833,6 +1915,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);
@@ -1862,6 +1951,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();
@@ -1880,6 +1975,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)
{
@@ -2002,6 +2106,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,
@@ -2148,7 +2253,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 &reg_set )
@@ -3385,18 +3494,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; j<m_cu.size(); j++) {
- m_cu[j]->init(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( warp_inst_t &inst )
@@ -3406,9 +3531,9 @@ bool opndcoll_rfu_t::writeback( warp_inst_t &inst )
for( unsigned op=0; op < MAX_REG_OPERANDS; op++ ) {
int reg_num = inst.arch_reg.dst[op]; // this math needs to match that used in function_info::ptx_decode_inst
if( reg_num >= 0 ){ // valid register
- unsigned bank = register_bank(reg_num,inst.warp_id(),m_num_banks,m_bank_warp_shift);
+ unsigned bank = register_bank(reg_num,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_num,m_num_banks,m_bank_warp_shift));
+ m_arbiter.allocate_bank_for_write(bank,op_t(&inst,reg_num,m_num_banks,m_bank_warp_shift, sub_core_model, m_num_banks_per_sched, inst.get_schd_id()));
inst.arch_reg.dst[op] = -1;
} else {
return false;
@@ -3494,7 +3619,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;
}
@@ -3545,7 +3670,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;
@@ -3553,6 +3680,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 )
@@ -3567,7 +3696,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 46106f8..9abd223 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 {
@@ -291,7 +293,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_PER_CTA_MAX> 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;
@@ -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));
@@ -379,6 +382,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,
@@ -407,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;
@@ -421,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() {
@@ -440,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() {
@@ -460,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() {
@@ -480,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;
@@ -532,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,
@@ -608,23 +619,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
@@ -640,6 +653,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();
@@ -684,6 +701,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 {
@@ -704,7 +722,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:
@@ -858,7 +876,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 )
@@ -886,6 +906,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 {
@@ -928,6 +951,10 @@ private:
std::vector<collector_unit_t *> 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<warp_inst_t**> m_input;
//std::vector<warp_inst_t**> m_output;
@@ -1028,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;
@@ -1136,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:
@@ -1285,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,
@@ -1300,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",
@@ -1360,10 +1417,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);
@@ -1409,12 +1462,14 @@ 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;
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;
@@ -1422,6 +1477,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;
@@ -1429,6 +1485,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;
@@ -1436,6 +1493,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;
@@ -1445,6 +1503,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;
@@ -1909,7 +1968,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