aboutsummaryrefslogtreecommitdiff
path: root/src/gpgpu-sim
diff options
context:
space:
mode:
Diffstat (limited to 'src/gpgpu-sim')
-rw-r--r--src/gpgpu-sim/gpu-sim.cc91
-rw-r--r--src/gpgpu-sim/gpu-sim.h3
-rw-r--r--src/gpgpu-sim/scoreboard.cc22
-rw-r--r--src/gpgpu-sim/shader.cc461
-rw-r--r--src/gpgpu-sim/shader.h164
5 files changed, 576 insertions, 165 deletions
diff --git a/src/gpgpu-sim/gpu-sim.cc b/src/gpgpu-sim/gpu-sim.cc
index 8bbadf5..ec570bf 100644
--- a/src/gpgpu-sim/gpu-sim.cc
+++ b/src/gpgpu-sim/gpu-sim.cc
@@ -58,6 +58,7 @@
#include "../debug.h"
#include "../gpgpusim_entrypoint.h"
#include "../cuda-sim/cuda-sim.h"
+#include "../cuda-sim/ptx_ir.h"
#include "../trace.h"
#include "mem_latency_stat.h"
#include "power_stat.h"
@@ -284,6 +285,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_registers_per_block", OPT_UINT32, &gpgpu_registers_per_block,
+ "Maximum number of registers per CTA. (default 8192)",
+ "8192");
option_parser_register(opp, "-gpgpu_ignore_resources_limitation", OPT_BOOL, &gpgpu_ignore_resources_limitation,
"gpgpu_ignore_resources_limitation (default 0)",
"0");
@@ -305,6 +309,9 @@ void shader_core_config::reg_options(class OptionParser * opp)
option_parser_register(opp, "-gpgpu_n_ldst_response_buffer_size", OPT_UINT32, &ldst_unit_response_queue_size,
"number of response packets in ld/st unit ejection buffer",
"2");
+ option_parser_register(opp, "-gpgpu_shmem_per_block", OPT_UINT32, &gpgpu_shmem_per_block,
+ "Size of shared memory per thread block or CTA (default 48kB)",
+ "49152");
option_parser_register(opp, "-gpgpu_shmem_size", OPT_UINT32, &gpgpu_shmem_size,
"Size of shared memory per shader core (default 16kB)",
"16384");
@@ -329,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");
@@ -347,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)",
@@ -356,6 +372,12 @@ 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");
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");
@@ -371,6 +393,12 @@ 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");
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");
@@ -386,6 +414,12 @@ 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");
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");
@@ -409,17 +443,26 @@ 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",
- "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");
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_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");
+ 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");
@@ -721,11 +764,21 @@ int gpgpu_sim::shared_mem_size() const
return m_shader_config->gpgpu_shmem_size;
}
+int gpgpu_sim::shared_mem_per_block() const
+{
+ return m_shader_config->gpgpu_shmem_per_block;
+}
+
int gpgpu_sim::num_registers_per_core() const
{
return m_shader_config->gpgpu_shader_registers;
}
+int gpgpu_sim::num_registers_per_block() const
+{
+ return m_shader_config->gpgpu_registers_per_block;
+}
+
int gpgpu_sim::wrp_size() const
{
return m_shader_config->warp_size;
@@ -1178,6 +1231,9 @@ void shader_core_ctx::mem_instruction_stats(const warp_inst_t &inst)
case shared_space:
m_stats->gpgpu_n_shmem_insn += active_count;
break;
+ case sstarr_space:
+ m_stats->gpgpu_n_sstarr_insn += active_count;
+ break;
case const_space:
m_stats->gpgpu_n_const_insn += active_count;
break;
@@ -1379,22 +1435,44 @@ 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; i<end_thread; i++) {
m_threadState[i].m_cta_id = free_cta_hw_id;
unsigned warp_id = i/m_config->warp_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 && ctaid<m_gpu->checkpoint_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 && ctaid<m_gpu->checkpoint_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);
// initialize the SIMT stacks and fetch hardware
- init_warps( free_cta_hw_id, start_thread, end_thread);
+ init_warps( free_cta_hw_id, start_thread, end_thread, ctaid, cta_size, kernel.get_uid());
m_n_active_cta++;
shader_CTA_count_log(m_sid, 1);
@@ -1553,7 +1631,8 @@ void gpgpu_sim::cycle()
if( g_single_step && ((gpu_sim_cycle+gpu_tot_sim_cycle) >= g_single_step) ) {
raise(SIGTRAP); // Debug breakpoint
}
- gpu_sim_cycle++;
+ gpu_sim_cycle++;
+
if( g_interactive_debugger_enabled )
gpgpu_debug();
@@ -1643,7 +1722,7 @@ void gpgpu_sim::cycle()
}
}
- if (!(gpu_sim_cycle % 20000)) {
+ if (!(gpu_sim_cycle % 50000)) {
// deadlock detection
if (m_config.gpu_deadlock_detect && gpu_sim_insn == last_gpu_sim_insn) {
gpu_deadlock = true;
diff --git a/src/gpgpu-sim/gpu-sim.h b/src/gpgpu-sim/gpu-sim.h
index 1bae1fa..6ce5524 100644
--- a/src/gpgpu-sim/gpu-sim.h
+++ b/src/gpgpu-sim/gpu-sim.h
@@ -335,6 +335,7 @@ public:
unsigned num_shader() const { return m_shader_config.num_shader(); }
unsigned num_cluster() const { return m_shader_config.n_simt_clusters; }
unsigned get_max_concurrent_kernel() const { return max_concurrent_kernel; }
+ unsigned checkpoint_option;
private:
void init_clock_domains(void );
@@ -436,7 +437,9 @@ public:
void get_pdom_stack_top_info( unsigned sid, unsigned tid, unsigned *pc, unsigned *rpc );
int shared_mem_size() const;
+ int shared_mem_per_block() const;
int num_registers_per_core() const;
+ int num_registers_per_block() const;
int wrp_size() const;
int shader_clock() const;
const struct cudaDeviceProp *get_prop() const;
diff --git a/src/gpgpu-sim/scoreboard.cc b/src/gpgpu-sim/scoreboard.cc
index f412054..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 < 4; 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<4; r++) {
+ for ( unsigned r=0; r<MAX_OUTPUT_VALUES; 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 < MAX_OUTPUT_VALUES; r++) {
if(inst->out[r] > 0) {
SHADER_DPRINTF( SCOREBOARD,
"Register Released - warp:%d, reg: %d\n",
@@ -138,15 +138,13 @@ bool Scoreboard::checkCollision( unsigned wid, const class inst_t *inst ) const
// Get list of all input and output registers
std::set<int> 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->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->pred > 0) inst_regs.insert(inst->pred);
+ for(int iii=0;iii<inst->outcount;iii++)
+ inst_regs.insert(inst->out[iii]);
+
+ for(int jjj=0;jjj<inst->incount;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);
if(inst->ar2 > 0) inst_regs.insert(inst->ar2);
diff --git a/src/gpgpu-sim/shader.cc b/src/gpgpu-sim/shader.cc
index 8a84970..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,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_INT],
+ &m_pipeline_reg[ID_OC_TENSOR_CORE],
&m_pipeline_reg[ID_OC_MEM],
i
)
@@ -167,6 +181,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_INT],
+ &m_pipeline_reg[ID_OC_TENSOR_CORE],
&m_pipeline_reg[ID_OC_MEM],
i,
config->gpgpu_scheduler_string
@@ -183,6 +199,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_INT],
+ &m_pipeline_reg[ID_OC_TENSOR_CORE],
&m_pipeline_reg[ID_OC_MEM],
i
)
@@ -198,6 +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_INT],
+ &m_pipeline_reg[ID_OC_TENSOR_CORE],
&m_pipeline_reg[ID_OC_MEM],
i
)
@@ -213,6 +233,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_INT],
+ &m_pipeline_reg[ID_OC_TENSOR_CORE],
&m_pipeline_reg[ID_OC_MEM],
i,
config->gpgpu_scheduler_string
@@ -233,53 +255,16 @@ 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);
-
+
+ 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();
- }
-
- 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,15 +272,89 @@ 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_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 );
- // execute
- m_num_function_units = m_config->gpgpu_num_sp_units + m_config->gpgpu_num_dp_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_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 ];
@@ -312,18 +371,29 @@ 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 ));
m_dispatch_port.push_back(ID_OC_SFU);
m_issue_port.push_back(OC_EX_SFU);
}
+
+ for (int k = 0; k < 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);
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
@@ -370,11 +440,12 @@ void shader_core_ctx::reinit(unsigned start_thread, unsigned end_thread, bool re
}
}
-void shader_core_ctx::init_warps( unsigned cta_id, unsigned start_thread, unsigned end_thread )
+void shader_core_ctx::init_warps( unsigned cta_id, unsigned start_thread, unsigned end_thread, unsigned ctaid, int cta_size, unsigned kernel_id )
{
address_type start_pc = next_pc(start_thread);
if (m_config->model == POST_DOMINATOR) {
unsigned start_warp = start_thread / m_config->warp_size;
+ unsigned warp_per_cta = cta_size / m_config->warp_size;
unsigned end_warp = end_thread / m_config->warp_size + ((end_thread % m_config->warp_size)? 1 : 0);
for (unsigned i = start_warp; i < end_warp; ++i) {
unsigned n_active=0;
@@ -389,6 +460,21 @@ void shader_core_ctx::init_warps( unsigned cta_id, unsigned start_thread, unsign
}
}
m_simt_stack[i]->launch(start_pc,active_threads);
+
+ if(m_gpu->resume_option==1 && kernel_id==m_gpu->resume_kernel && ctaid>=m_gpu->resume_CTA && ctaid<m_gpu->checkpoint_CTA_t )
+ {
+ char fname[2048];
+ snprintf(fname,2048,"checkpoint_files/warp_%d_%d_simt.txt",i%warp_per_cta,ctaid );
+ unsigned pc,rpc;
+ m_simt_stack[i]->resume(fname);
+ m_simt_stack[i]->get_pdom_stack_top_info(&pc,&rpc);
+ for (unsigned t = 0; t < m_config->warp_size; t++) {
+ m_thread[i * m_config->warp_size + t]->set_npc(pc);
+ m_thread[i * m_config->warp_size + t]->update_pc();
+ }
+ start_pc=pc;
+ }
+
m_warp[i].init(start_pc,cta_id,i,active_threads, m_dynamic_warp_id);
++m_dynamic_warp_id;
m_not_completed += n_active;
@@ -455,6 +541,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_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);
@@ -758,18 +845,21 @@ 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 )
+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 ){
@@ -914,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();
@@ -949,9 +1039,10 @@ 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( 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 ( (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(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;
@@ -959,58 +1050,98 @@ 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();
- 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)) {
+ 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 {
+ }
+ 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
+ } 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
@@ -1144,7 +1275,7 @@ void two_level_active_scheduler::order_warps()
for ( std::vector< shd_warp_t* >::iterator iter = m_next_cycle_prioritized_warps.begin();
iter != m_next_cycle_prioritized_warps.end(); ) {
bool waiting = (*iter)->waiting();
- for (int i=0; i<4; i++){
+ for (int i=0; i<MAX_INPUT_VALUES; i++){
const warp_inst_t* inst = (*iter)->ibuffer_next_inst();
//Is the instruction waiting on a long operation?
if ( inst && inst->in[i] > 0 && this->m_scoreboard->islongop((*iter)->get_warp_id(), inst->in[i])){
@@ -1190,10 +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, 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,
@@ -1361,10 +1494,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 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)
@@ -1467,7 +1602,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 < 4; r++)
+ for ( unsigned r=0; r < MAX_OUTPUT_VALUES; r++)
if (inst.out[r] > 0)
m_pending_writes[inst.warp_id()][inst.out[r]]--;
}
@@ -1561,7 +1696,7 @@ void ldst_unit::L1_latency_queue_cycle()
assert( !read_sent );
l1_latency_queue[0] = NULL;
if ( mf_next->get_inst().is_load() ) {
- for ( unsigned r=0; r < 4; r++)
+ for ( unsigned r=0; r < MAX_OUTPUT_VALUES; 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);
@@ -1661,11 +1796,11 @@ bool ldst_unit::memory_cycle( warp_inst_t &inst, mem_stage_stall_type &stall_rea
if (m_core->get_config()->gmem_skip_L1D && (CACHE_L1 != inst.cache_op))
bypassL1D = true;
}
-
if( bypassL1D ) {
// 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 {
@@ -1674,7 +1809,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 < 4; 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() )
@@ -1732,6 +1867,12 @@ 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();
@@ -1742,11 +1883,23 @@ 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);
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);
@@ -1762,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);
@@ -1770,6 +1930,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)
{
@@ -1782,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();
@@ -1800,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)
{
@@ -1922,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,
@@ -1958,7 +2143,7 @@ void ldst_unit:: issue( register_set &reg_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 < 4; 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;
@@ -1980,7 +2165,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 < 4; 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 );
@@ -2068,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 )
@@ -2082,7 +2271,7 @@ void ldst_unit::issue( register_set &reg_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 < 4; 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;
@@ -2186,7 +2375,7 @@ void ldst_unit::cycle()
//}
bool pending_requests=false;
- for( unsigned r=0; r<4; r++ ) {
+ for( unsigned r=0; r<MAX_OUTPUT_VALUES; r++ ) {
unsigned reg_id = pipe_reg.out[r];
if( reg_id > 0 ) {
if( m_pending_writes[warp_id].find(reg_id) != m_pending_writes[warp_id].end() ) {
@@ -2494,7 +2683,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);
@@ -3305,33 +3494,50 @@ 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( const warp_inst_t &inst )
+bool opndcoll_rfu_t::writeback( warp_inst_t &inst )
{
assert( !inst.empty() );
std::list<unsigned> regs = m_shader->get_regs_written(inst);
- std::list<unsigned>::iterator r;
- 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);
- if( m_arbiter.bank_idle(bank) ) {
- m_arbiter.allocate_bank_for_write(bank,op_t(&inst,reg,m_num_banks,m_bank_warp_shift));
- } else {
- return false;
+ 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, 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, sub_core_model, m_num_banks_per_sched, inst.get_schd_id()));
+ inst.arch_reg.dst[op] = -1;
+ } else {
+ return false;
+ }
}
}
for(unsigned i=0;i<(unsigned)regs.size();i++){
@@ -3413,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;
}
@@ -3464,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;
@@ -3472,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 )
@@ -3486,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();
@@ -3664,6 +3874,7 @@ void simt_core_cluster::icnt_inject_request_packet(class mem_fetch *mf)
case CONST_ACC_R: m_stats->gpgpu_n_mem_const++; break;
case TEXTURE_ACC_R: m_stats->gpgpu_n_mem_texture++; break;
case GLOBAL_ACC_R: m_stats->gpgpu_n_mem_read_global++; break;
+ //case GLOBAL_ACC_R: m_stats->gpgpu_n_mem_read_global++; printf("read_global%d\n",m_stats->gpgpu_n_mem_read_global); break;
case GLOBAL_ACC_W: m_stats->gpgpu_n_mem_write_global++; break;
case LOCAL_ACC_R: m_stats->gpgpu_n_mem_read_local++; break;
case LOCAL_ACC_W: m_stats->gpgpu_n_mem_write_local++; break;
diff --git a/src/gpgpu-sim/shader.h b/src/gpgpu-sim/shader.h
index 4a87126..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,11 +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_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));
@@ -378,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,
@@ -406,6 +412,8 @@ 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;
int m_id;
@@ -419,9 +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, 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() {
@@ -437,9 +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, 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() {
@@ -456,9 +468,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, 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() {
@@ -475,10 +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, 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;
@@ -526,6 +542,8 @@ 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_string );
@@ -558,7 +576,7 @@ public:
void init( unsigned num_banks, shader_core_ctx *shader );
// modifiers
- bool writeback( const warp_inst_t &warp ); // might cause stall
+ bool writeback( warp_inst_t &warp );
void step()
{
@@ -601,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
@@ -633,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();
@@ -677,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 {
@@ -697,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:
@@ -851,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 )
@@ -879,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 {
@@ -921,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;
@@ -1021,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;
@@ -1112,6 +1149,46 @@ 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 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:
@@ -1121,7 +1198,9 @@ public:
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 DP_OP: return false;
default: break;
@@ -1165,7 +1244,9 @@ public:
{
switch(inst.op) {
case LOAD_OP: break;
+ case TENSOR_CORE_LOAD_OP: break;
case STORE_OP: break;
+ case TENSOR_CORE_STORE_OP: break;
case MEMORY_BARRIER_OP: break;
default: return false;
}
@@ -1257,26 +1338,34 @@ 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,
+ ID_OC_TENSOR_CORE,
+ OC_EX_TENSOR_CORE,
N_PIPELINE_STAGES
-};
+ };
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",
+ "ID_OC_TENSOR_CORE",
+ "OC_EX_TENSOR_CORE",
"N_PIPELINE_STAGES"
};
@@ -1299,16 +1388,24 @@ struct shader_core_config : public core_config
char* toks = new char[100];
char* tokd = toks;
strcpy(toks,pipeline_widths_string);
-
+
toks = strtok(toks,",");
- for (unsigned i = 0; i < N_PIPELINE_STAGES; i++) {
+
+ /* Removing the tensorcore pipeline while reading the config files if the tensor core is not available.
+ If we won't remove it, old regression will be broken.
+ So to support the legacy config files it's best to handle in this way.
+ */
+ int num_config_to_read=N_PIPELINE_STAGES-2*(!gpgpu_tensor_core_avail);
+
+ for (unsigned i = 0; i <num_config_to_read; i++) {
assert(toks);
ntok = sscanf(toks,"%d", &pipe_widths[i]);
assert(ntok == 1);
toks = strtok(NULL,",");
}
- delete[] tokd;
+ delete[] tokd;
+
if (n_thread_per_shader > MAX_THREAD_PER_SM) {
printf("GPGPU-Sim uArch: Error ** increase MAX_THREAD_PER_SM in abstract_hardware_model.h from %u to %u\n",
MAX_THREAD_PER_SM, n_thread_per_shader);
@@ -1318,7 +1415,10 @@ struct shader_core_config : public core_config
assert( !(n_thread_per_shader % warp_size) );
max_sfu_latency = 512;
max_sp_latency = 32;
- m_L1I_config.init(m_L1I_config.m_config_string,FuncCachePreferNone);
+
+ max_tensor_core_latency = 64;
+
+ 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);
@@ -1345,7 +1445,8 @@ struct shader_core_config : public core_config
unsigned max_cta_per_core; //Limit on number of concurrent CTAs in shader core
unsigned max_barriers_per_cta;
char * gpgpu_scheduler_string;
-
+ unsigned gpgpu_shmem_per_block;
+ unsigned gpgpu_registers_per_block;
char* pipeline_widths_string;
int pipe_widths[N_PIPELINE_STAGES];
@@ -1361,28 +1462,38 @@ 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;
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_in_ports_int;
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;
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;
int gpgpu_num_dp_units;
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;
@@ -1392,9 +1503,11 @@ 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;
+ unsigned max_tensor_core_latency;
unsigned n_simt_cores_per_cluster;
unsigned n_simt_clusters;
@@ -1436,12 +1549,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;
@@ -1450,12 +1565,14 @@ 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
unsigned gpgpu_n_load_insn;
unsigned gpgpu_n_store_insn;
unsigned gpgpu_n_shmem_insn;
+ unsigned gpgpu_n_sstarr_insn;
unsigned gpgpu_n_tex_insn;
unsigned gpgpu_n_const_insn;
unsigned gpgpu_n_param_insn;
@@ -1522,6 +1639,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));
@@ -1529,9 +1647,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));
@@ -1836,7 +1956,7 @@ public:
}
int test_res_bus(int latency);
- void init_warps(unsigned cta_id, unsigned start_thread, unsigned end_thread);
+ void init_warps(unsigned cta_id, unsigned start_thread, unsigned end_thread,unsigned ctaid, int cta_size, unsigned kernel_id);
virtual void checkExecutionStatusAndUpdate(warp_inst_t &inst, unsigned t, unsigned tid);
address_type next_pc( int tid ) const;
void fetch();
@@ -1848,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