summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/abstract_hardware_model.cc4
-rw-r--r--src/abstract_hardware_model.h107
-rw-r--r--src/cuda-sim/cuda-sim.cc102
-rw-r--r--src/cuda-sim/ptx_ir.cc3
-rw-r--r--src/cuda-sim/ptx_ir.h11
-rw-r--r--src/cuda-sim/ptx_parser.cc10
-rw-r--r--src/gpgpu-sim/gpu-sim.cc52
-rw-r--r--src/gpgpu-sim/gpu-sim.h47
-rw-r--r--src/gpgpu-sim/mem_fetch.cc2
-rw-r--r--src/gpgpu-sim/shader.cc893
-rw-r--r--src/gpgpu-sim/shader.h345
-rw-r--r--src/gpgpu-sim/stats.h3
-rw-r--r--src/gpgpu-sim/visualizer.cc3
13 files changed, 893 insertions, 689 deletions
diff --git a/src/abstract_hardware_model.cc b/src/abstract_hardware_model.cc
index b943a76..619b9b7 100644
--- a/src/abstract_hardware_model.cc
+++ b/src/abstract_hardware_model.cc
@@ -23,7 +23,3 @@ gpgpu_t::gpgpu_t()
m_dev_malloc=GLOBAL_HEAP_START;
}
-void warp_inst_t::sort_accessq( unsigned qbegin )
-{
- std::stable_sort( m_accessq.begin()+qbegin,m_accessq.end());
-}
diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h
index 5ccdaf3..41fe025 100644
--- a/src/abstract_hardware_model.h
+++ b/src/abstract_hardware_model.h
@@ -386,7 +386,8 @@ public:
is_vectorin=0;
is_vectorout=0;
space = memory_space_t();
- cycles = 0;
+ latency = 1;
+ initiation_interval = 1;
for( unsigned i=0; i < MAX_REG_OPERANDS; i++ )
arch_reg[i]=-1;
isize=0;
@@ -411,7 +412,8 @@ public:
int pred; // predicate register number
int ar1, ar2;
int arch_reg[MAX_REG_OPERANDS]; // register number for bank conflict evaluation
- unsigned cycles; // 1/throughput for instruction
+ unsigned latency; // operation latency
+ unsigned initiation_interval;
unsigned data_size; // what is the size of the word being operated on?
memory_space_t space;
@@ -423,16 +425,77 @@ protected:
#define MAX_WARP_SIZE 32
+enum divergence_support_t {
+ POST_DOMINATOR = 1,
+ NUM_SIMD_MODEL
+};
+
+struct shader_core_config
+{
+ unsigned warp_size;
+ bool gpgpu_perfect_mem;
+ enum divergence_support_t model;
+ unsigned n_thread_per_shader;
+ unsigned max_warps_per_shader;
+ unsigned max_cta_per_core; //Limit on number of concurrent CTAs in shader core
+ unsigned pdom_sched_type;
+ bool gpgpu_no_dl1;
+ char *gpgpu_cache_texl1_opt;
+ char *gpgpu_cache_constl1_opt;
+ char *gpgpu_cache_dl1_opt;
+ char *gpgpu_cache_il1_opt;
+ unsigned n_mshr_per_shader;
+ bool gpgpu_dwf_reg_bankconflict;
+ int gpgpu_operand_collector_num_units_sp;
+ int gpgpu_operand_collector_num_units_sfu;
+ int gpgpu_operand_collector_num_units_mem;
+ bool gpgpu_stall_on_use;
+ bool gpgpu_cache_wt_through;
+ //Shader core resources
+ unsigned gpgpu_shmem_size;
+ unsigned gpgpu_shader_registers;
+ int gpgpu_warpdistro_shader;
+ int gpgpu_interwarp_mshr_merge;
+ int gpgpu_n_shmem_bank;
+ int gpgpu_n_cache_bank;
+ int gpgpu_shmem_port_per_bank;
+ int gpgpu_cache_port_per_bank;
+ int gpgpu_const_port_per_bank;
+ int gpgpu_shmem_pipe_speedup;
+ unsigned gpgpu_num_reg_banks;
+ unsigned gpu_max_cta_per_shader; // TODO: modify this for fermi... computed based upon kernel
+ // resource usage; used in shader_core_ctx::translate_local_memaddr
+ bool gpgpu_reg_bank_use_warp_id;
+ int gpgpu_coalesce_arch;
+ bool gpgpu_local_mem_map;
+ int gpu_padded_cta_size;
+
+ unsigned max_sp_latency;
+ unsigned max_sfu_latency;
+ unsigned gpgpu_cache_texl1_linesize;
+ unsigned gpgpu_cache_constl1_linesize;
+ unsigned gpgpu_cache_dl1_linesize;
+
+ static const address_type WORD_SIZE=4;
+ unsigned null_bank_func(address_type, unsigned) const { return 1; }
+ unsigned shmem_bank_func(address_type addr, unsigned) const;
+ unsigned dcache_bank_func(address_type add, unsigned line_size) const;
+};
+
+typedef unsigned (shader_core_config::*bank_func_t)(address_type add, unsigned line_size) const;
+typedef address_type (*tag_func_t)(address_type add, unsigned line_size);
+
class warp_inst_t: public inst_t {
public:
// constructors
- warp_inst_t( unsigned warp_size )
+ warp_inst_t( const struct shader_core_config *config )
{
- assert(warp_size<=MAX_WARP_SIZE);
- m_warp_size=warp_size;
+ assert(config->warp_size<=MAX_WARP_SIZE);
+ m_config=config;
m_empty=true;
m_isatomic=false;
m_per_scalar_thread_valid=false;
+ m_mem_accesses_created=false;
}
// modifiers
@@ -452,18 +515,19 @@ public:
}
void issue( unsigned mask, unsigned warp_id, unsigned long long cycle )
{
- for (int i=(int)m_warp_size-1; i>=0; i--) {
+ for (int i=(int)m_config->warp_size-1; i>=0; i--) {
if( mask & (1<<i) )
warp_active_mask.set(i);
}
m_warp_id = warp_id;
issue_cycle = cycle;
+ cycles = initiation_interval;
m_empty=false;
}
void set_addr( unsigned n, new_addr_type addr )
{
if( !m_per_scalar_thread_valid ) {
- m_per_scalar_thread.resize(m_warp_size);
+ m_per_scalar_thread.resize(m_config->warp_size);
m_per_scalar_thread_valid=true;
}
m_per_scalar_thread[n].memreqaddr = addr;
@@ -474,7 +538,7 @@ public:
class ptx_thread_info *thread )
{
if( !m_per_scalar_thread_valid ) {
- m_per_scalar_thread.resize(m_warp_size);
+ m_per_scalar_thread.resize(m_config->warp_size);
m_per_scalar_thread_valid=true;
m_isatomic=true;
}
@@ -487,11 +551,11 @@ public:
warp_active_mask.reset();
for( std::vector<unsigned>::iterator i=active.begin(); i!=active.end(); ++i ) {
unsigned t = *i;
- assert( t < m_warp_size );
+ assert( t < m_config->warp_size );
warp_active_mask.set(t);
}
if( m_isatomic ) {
- for( unsigned i=0; i < m_warp_size; i++ ) {
+ for( unsigned i=0; i < m_config->warp_size; i++ ) {
if( !warp_active_mask.test(i) ) {
m_per_scalar_thread[i].callback.function = NULL;
m_per_scalar_thread[i].callback.instruction = NULL;
@@ -504,12 +568,13 @@ public:
{
warp_active_mask.reset(lane_id);
}
+ void get_memory_access_list();
// accessors
virtual void print_insn(FILE *fp) const
{
fprintf(fp," [inst @ pc=0x%04x] ", pc );
- for (int i=(int)m_warp_size-1; i>=0; i--)
+ for (int i=(int)m_config->warp_size-1; i>=0; i--)
fprintf(fp, "%c", ((warp_active_mask[i])?'1':'0') );
}
bool active( unsigned thread ) const { return warp_active_mask.test(thread); }
@@ -533,22 +598,32 @@ public:
bool isatomic() const { return m_isatomic; }
- bool mem_accesses_computed() const { return m_mem_accesses_created; }
- void set_mem_accesses_computed() { m_mem_accesses_created=true; }
+ unsigned warp_size() const { return m_config->warp_size; }
+
+ bool mem_accesses_created() const { return m_mem_accesses_created; }
+ void set_mem_accesses_created() { m_mem_accesses_created=true; }
bool accessq_empty() const { return m_accessq.empty(); }
unsigned get_accessq_size() const { return m_accessq.size(); }
mem_access_t &accessq( unsigned n ) { return m_accessq[n]; }
mem_access_t &accessq_back() { return m_accessq.back(); }
- void accessq_push_back( const mem_access_t &req ) { m_accessq.push_back(req); }
void accessq_pop_back() { m_accessq.pop_back(); }
- void sort_accessq( unsigned qbegin );
+
+ bool dispatch_delay()
+ {
+ if( cycles > 0 )
+ cycles--;
+ return cycles > 0;
+ }
+
+ void print( FILE *fout ) const;
protected:
bool m_empty;
unsigned long long issue_cycle;
+ unsigned cycles; // used for implementing initiation interval delay
bool m_isatomic;
unsigned m_warp_id;
- unsigned m_warp_size;
+ const struct shader_core_config *m_config;
std::bitset<MAX_WARP_SIZE> warp_active_mask;
struct per_thread_info {
diff --git a/src/cuda-sim/cuda-sim.cc b/src/cuda-sim/cuda-sim.cc
index 89e89e8..e61659c 100644
--- a/src/cuda-sim/cuda-sim.cc
+++ b/src/cuda-sim/cuda-sim.cc
@@ -438,61 +438,64 @@ void ptx_print_insn( address_type pc, FILE *fp )
finfo->print_insn(pc,fp);
}
-static void get_opcode_info( const ptx_instruction *pI, unsigned opcode, unsigned *cycles, op_type *op )
+void ptx_instruction::get_opcode_info()
{
- *op = ALU_OP;
- *cycles = 1;
- if ( opcode == LD_OP ) {
- *op = LOAD_OP;
- } else if ( opcode == ST_OP ) {
- *op = STORE_OP;
- } else if ( opcode == BRA_OP ) {
- *op = BRANCH_OP;
- } else if ( opcode == BREAKADDR_OP ) {
- *op = BRANCH_OP;
- } else if ( opcode == TEX_OP ) {
- *op = LOAD_OP;
- } else if ( opcode == ATOM_OP ) {
- *op = LOAD_OP; // timing model treats this like load for now
- } else if ( opcode == BAR_OP ) {
- *op = BARRIER_OP;
- } else if ( opcode == MEMBAR_OP )
- *op = MEMORY_BARRIER_OP;
-
- // Floating point instructions
- if( opcode == RCP_OP ) {
- *cycles = 2;
- *op = SFU_OP;
- } else if ( opcode == LG2_OP || opcode == RSQRT_OP ) {
- *cycles = 4;
- *op = SFU_OP;
- } else if( opcode == SQRT_OP || opcode == SIN_OP || opcode == COS_OP || opcode == EX2_OP ) {
- *cycles = 4;
- *op = SFU_OP;
- } else if( opcode == DIV_OP ) {
+ op = ALU_OP;
+ initiation_interval = latency = 1;
+ switch( m_opcode ) {
+ case LD_OP: op = LOAD_OP; break;
+ case ST_OP: op = STORE_OP; break;
+ case BRA_OP: op = BRANCH_OP; break;
+ case BREAKADDR_OP: op = BRANCH_OP; break;
+ case TEX_OP: op = LOAD_OP; break;
+ case ATOM_OP: op = LOAD_OP; break;
+ case BAR_OP: op = BARRIER_OP; break;
+ case MEMBAR_OP: op = MEMORY_BARRIER_OP; break;
+ case RCP_OP:
+ latency = 2;
+ initiation_interval = 2;
+ op = SFU_OP;
+ break;
+ case LG2_OP: case RSQRT_OP:
+ latency = 4;
+ initiation_interval = 4;
+ op = SFU_OP;
+ break;
+ case SQRT_OP: case SIN_OP: case COS_OP: case EX2_OP:
+ latency = 10;
+ initiation_interval = 4;
+ op = SFU_OP;
+ break;
+ case DIV_OP:
// Floating point only
- if( pI->get_type() == F32_TYPE || pI->get_type() == F64_TYPE ) {
- *cycles = 4;
- *op = SFU_OP;
+ if( get_type() == F32_TYPE || get_type() == F64_TYPE ) {
+ latency = 10;
+ initiation_interval = 4;
+ op = SFU_OP;
}
- }
- // Integer instructions
- if( opcode == MUL_OP ) {
- if( pI->get_type() == B32_TYPE || pI->get_type() == U32_TYPE || pI->get_type() == S32_TYPE ) {
+ break;
+ case MUL_OP:
+ if( get_type() == B32_TYPE || get_type() == U32_TYPE || get_type() == S32_TYPE ) {
// 32-bit integer instruction
- *cycles = 5;
- *op = SFU_OP;
+ latency = 24;
+ initiation_interval = 5;
+ op = SFU_OP;
}
- if( pI->get_type() == F32_TYPE || pI->get_type() == F64_TYPE )
- *op = ALU_SFU_OP;
- }
- if( opcode == MAD_OP ) {
- if( pI->get_type() == B32_TYPE || pI->get_type() == U32_TYPE || pI->get_type() == S32_TYPE ) {
+ if( get_type() == F32_TYPE || get_type() == F64_TYPE ) {
+ op = ALU_SFU_OP;
+ }
+ break;
+ case MAD_OP:
+ if( get_type() == B32_TYPE || get_type() == U32_TYPE || get_type() == S32_TYPE ) {
// 32-bit integer instruction
- *cycles = 6;
- *op = SFU_OP;
+ latency = 30;
+ initiation_interval = 6;
+ op = SFU_OP;
}
- }
+ break;
+ default:
+ break;
+ }
}
void ptx_thread_info::ptx_fetch_inst( inst_t &inst ) const
@@ -519,7 +522,6 @@ void ptx_instruction::pre_decode()
ar2 = 0;
bool has_dst = false ;
- int opcode = get_opcode(); //determine the opcode
switch ( get_opcode() ) {
#define OP_DEF(OP,FUNC,STR,DST,CLASSIFICATION) case OP: has_dst = (DST!=0); break;
@@ -530,7 +532,7 @@ void ptx_instruction::pre_decode()
break;
}
- get_opcode_info(this,opcode,&cycles,&op);
+ get_opcode_info();
// Get register operands
int n=0,m=0;
diff --git a/src/cuda-sim/ptx_ir.cc b/src/cuda-sim/ptx_ir.cc
index 8172f80..8d7fa11 100644
--- a/src/cuda-sim/ptx_ir.cc
+++ b/src/cuda-sim/ptx_ir.cc
@@ -983,7 +983,7 @@ ptx_instruction::ptx_instruction( int opcode,
const char *file,
unsigned line,
const char *source,
- unsigned warp_size ) : warp_inst_t(warp_size)
+ const shader_core_config *config ) : warp_inst_t(config)
{
m_uid = ++g_num_ptx_inst_uid;
m_PC = 0;
@@ -1011,7 +1011,6 @@ ptx_instruction::ptx_instruction( int opcode,
m_geom_spec = 0;
m_vector_spec = 0;
m_atomic_spec = 0;
- m_warp_size = warp_size;
m_membar_level = 0;
m_inst_size = 8; // bytes
diff --git a/src/cuda-sim/ptx_ir.h b/src/cuda-sim/ptx_ir.h
index 07f2e36..84ded76 100644
--- a/src/cuda-sim/ptx_ir.h
+++ b/src/cuda-sim/ptx_ir.h
@@ -801,7 +801,7 @@ public:
const char *file,
unsigned line,
const char *source,
- unsigned warp_size );
+ const shader_core_config *config );
void print_insn() const;
virtual void print_insn( FILE *fp ) const;
@@ -940,7 +940,6 @@ public:
enum vote_mode_t { vote_any, vote_all, vote_uni };
enum vote_mode_t vote_mode() const { return m_vote_mode; }
- unsigned warp_size() const { return m_warp_size; }
int membar_level() const { return m_membar_level; }
bool has_memory_read() const {
@@ -966,6 +965,7 @@ public:
}
private:
+ void get_opcode_info();
basic_block_t *m_basic_block;
unsigned m_uid;
@@ -973,7 +973,6 @@ private:
std::string m_source_file;
unsigned m_source_line;
std::string m_source;
- unsigned m_warp_size;
const symbol *m_pred;
bool m_neg_pred;
@@ -1176,8 +1175,10 @@ public:
static const ptx_instruction* pc_to_instruction(unsigned pc)
{
- assert(pc <= s_g_pc_to_insn.size());
- return s_g_pc_to_insn[pc];
+ if( pc < s_g_pc_to_insn.size() )
+ return s_g_pc_to_insn[pc];
+ else
+ return NULL;
}
unsigned local_mem_framesize() const
{
diff --git a/src/cuda-sim/ptx_parser.cc b/src/cuda-sim/ptx_parser.cc
index 5a65481..c4486a2 100644
--- a/src/cuda-sim/ptx_parser.cc
+++ b/src/cuda-sim/ptx_parser.cc
@@ -68,10 +68,10 @@
extern "C" int ptx_error( const char *s );
extern int ptx_lineno;
-static unsigned g_warp_size;
-void set_ptx_warp_size(unsigned warp_size)
+static const struct shader_core_config *g_shader_core_config;
+void set_ptx_warp_size(const struct shader_core_config * warp_size)
{
- g_warp_size=warp_size;
+ g_shader_core_config=warp_size;
}
static bool g_debug_ir_generation=false;
@@ -292,7 +292,7 @@ const ptx_instruction *ptx_instruction_lookup( const char *filename, unsigned li
void add_instruction()
{
DPRINTF("add_instruction: %s", ((g_opcode>0)?g_opcode_string[g_opcode]:"<label>") );
- assert( g_warp_size != 0 );
+ assert( g_shader_core_config != 0 );
ptx_instruction *i = new ptx_instruction( g_opcode,
g_pred,
g_neg_pred,
@@ -306,7 +306,7 @@ void add_instruction()
g_filename,
ptx_lineno,
linebuf,
- g_warp_size );
+ g_shader_core_config );
g_instructions.push_back(i);
g_inst_lookup[g_filename][ptx_lineno] = i;
init_instruction_state();
diff --git a/src/gpgpu-sim/gpu-sim.cc b/src/gpgpu-sim/gpu-sim.cc
index 7646ee7..9b71aec 100644
--- a/src/gpgpu-sim/gpu-sim.cc
+++ b/src/gpgpu-sim/gpu-sim.cc
@@ -374,12 +374,15 @@ void gpgpu_sim::reg_options(option_parser_t opp)
&m_ptx_force_max_capability,
"Force maximum compute capability",
"0");
- option_parser_register(opp, "-gpgpu_operand_collector_num_units", OPT_INT32, &m_shader_config->gpgpu_operand_collector_num_units,
- "number of collecture units (default = 4)",
+ option_parser_register(opp, "-gpgpu_operand_collector_num_units_sp", OPT_INT32, &m_shader_config->gpgpu_operand_collector_num_units_sp,
+ "number of collector units (default = 4)",
"4");
option_parser_register(opp, "-gpgpu_operand_collector_num_units_sfu", OPT_INT32, &m_shader_config->gpgpu_operand_collector_num_units_sfu,
- "number of collecture units (default = 4)",
+ "number of collector units (default = 4)",
"4");
+ option_parser_register(opp, "-gpgpu_operand_collector_num_units_mem", OPT_INT32, &m_shader_config->gpgpu_operand_collector_num_units_mem,
+ "number of collector units (default = 2)",
+ "2");
option_parser_register(opp, "-gpgpu_coalesce_arch", OPT_INT32, &m_shader_config->gpgpu_coalesce_arch,
"Coalescing arch (default = 13, anything else is off for now)",
"13");
@@ -453,7 +456,7 @@ gpgpu_sim::gpgpu_sim()
gpu_deadlock = false;
}
-void set_ptx_warp_size(unsigned warp_size);
+void set_ptx_warp_size(const struct shader_core_config * warp_size);
void gpgpu_sim::init_gpu()
{
@@ -465,7 +468,7 @@ void gpgpu_sim::init_gpu()
int ntok = sscanf(gpgpu_shader_core_pipeline_opt,"%d:%d",
&m_shader_config->n_thread_per_shader,
&m_shader_config->warp_size);
- set_ptx_warp_size(m_shader_config->warp_size);
+ set_ptx_warp_size(m_shader_config);
m_shader_config->max_warps_per_shader = m_shader_config->n_thread_per_shader/m_shader_config->warp_size;
assert( !(m_shader_config->n_thread_per_shader % m_shader_config->warp_size) );
@@ -743,8 +746,6 @@ unsigned int gpgpu_sim::run_gpu_sim()
void gpgpu_sim::gpu_print_stat() const
{
- unsigned i;
-
printf("gpu_sim_cycle = %lld\n", gpu_sim_cycle);
printf("gpu_sim_insn = %lld\n", gpu_sim_insn);
printf("gpu_sim_no_ld_const_insn = %lld\n", m_shader_stats->gpu_sim_insn_no_ld_const);
@@ -796,16 +797,16 @@ void gpgpu_sim::gpu_print_stat() const
printf("gpgpu_n_mem_texture = %d\n", m_shader_stats->gpgpu_n_mem_texture);
printf("gpgpu_n_mem_const = %d\n", m_shader_stats->gpgpu_n_mem_const);
- printf("max_n_mshr_used = ");
- for (unsigned i=0; i< m_n_shader; i++) printf("%d ", m_sc[i]->get_max_mshr_used() );
- printf("\n");
+ //printf("max_n_mshr_used = ");
+ //for (unsigned i=0; i< m_n_shader; i++) printf("%d ", m_sc[i]->get_max_mshr_used() );
+ //printf("\n");
if (m_memory_config->gpgpu_cache_dl2_opt) {
m_memory_stats->L2c_print_stat( m_n_mem );
}
for (unsigned i=0;i<m_n_mem;i++)
m_memory_partition_unit[i]->print(stdout);
-
+/*
unsigned a,m;
for (unsigned i=0, a=0, m=0;i<m_n_shader;i++)
m_sc[i]->L1cache_print(stdout,a,m);
@@ -816,7 +817,7 @@ void gpgpu_sim::gpu_print_stat() const
for (i=0,a=0,m=0;i<m_n_shader;i++)
m_sc[i]->L1constcache_print(stdout,a,m);
printf("L1 Const Cache Total Miss Rate = %0.3f\n", (float)m/a);
-
+*/
if (m_memory_config->gpgpu_cache_dl2_opt)
L2c_print_cache_stat();
@@ -963,6 +964,20 @@ unsigned char gpgpu_sim::check_icnt_has_buffer(unsigned long long int addr, int
int gpgpu_sim::issue_mf_from_fq(mem_fetch *mf)
{
+ // stats
+ if (mf->get_is_write()) m_shader_stats->made_write_mfs++;
+ else m_shader_stats->made_read_mfs++;
+ switch (mf->get_mem_acc()) {
+ case CONST_ACC_R: m_shader_stats->gpgpu_n_mem_const++; break;
+ case TEXTURE_ACC_R: m_shader_stats->gpgpu_n_mem_texture++; break;
+ case GLOBAL_ACC_R: m_shader_stats->gpgpu_n_mem_read_global++; break;
+ case GLOBAL_ACC_W: m_shader_stats->gpgpu_n_mem_write_global++; break;
+ case LOCAL_ACC_R: m_shader_stats->gpgpu_n_mem_read_local++; break;
+ case LOCAL_ACC_W: m_shader_stats->gpgpu_n_mem_write_local++; break;
+ case INST_ACC_R: m_shader_stats->gpgpu_n_mem_read_inst++; break;
+ default: assert(0);
+ }
+
unsigned destination = mf->get_tlx_addr().chip;
unsigned tpc_id = mf->get_tpc();
mf->set_status(IN_ICNT2MEM,MR_ICNT_PUSHED,gpu_sim_cycle+gpu_tot_sim_cycle);
@@ -985,17 +1000,11 @@ void shader_core_ctx::fill_shd_L1_with_new_line(mem_fetch * mf)
m_L1I->shd_cache_fill(mf->get_addr(),gpu_sim_cycle+gpu_tot_sim_cycle);
m_warp[mf->get_wid()].clear_imiss_pending();
delete mf->get_mshr();
+ delete mf;
} else {
- m_mshr_unit->mshr_return_from_mem(mf->get_mshr());
- if (mf->istexture())
- m_L1T->shd_cache_fill(mf->get_addr(),gpu_sim_cycle+gpu_tot_sim_cycle);
- else if (mf->isconst())
- m_L1C->shd_cache_fill(mf->get_addr(),gpu_sim_cycle+gpu_tot_sim_cycle);
- else if (!m_config->gpgpu_no_dl1)
- m_L1D->shd_cache_fill(mf->get_addr(),gpu_sim_cycle+gpu_tot_sim_cycle);
+ m_ldst_unit->fill(mf);
}
freed_read_mfs++;
- delete mf;
}
void shader_core_ctx::store_ack( class mem_fetch *mf )
@@ -1279,7 +1288,7 @@ void gpgpu_sim::cycle()
// L1 cache + shader core pipeline stages
for (unsigned i=0;i<m_n_shader;i++) {
if (m_sc[i]->get_not_completed() || more_thread) {
- m_sc[i]->cycle_gt200();
+ m_sc[i]->cycle();
}
}
if( g_single_step && ((gpu_sim_cycle+gpu_tot_sim_cycle) >= g_single_step) ) {
@@ -1413,7 +1422,6 @@ void gpgpu_sim::dump_pipeline( int mask, int s, int m ) const
i = s;
}
if(mask&1) m_sc[i]->display_pipeline(stdout, 1, mask & 0x2E );
- if(mask&0x100) m_sc[i]->mshr_print(stdout, mask);
if(s != -1) {
break;
}
diff --git a/src/gpgpu-sim/gpu-sim.h b/src/gpgpu-sim/gpu-sim.h
index 37c87f4..5dbdf51 100644
--- a/src/gpgpu-sim/gpu-sim.h
+++ b/src/gpgpu-sim/gpu-sim.h
@@ -96,51 +96,6 @@
#define SAMPLELOG 222
#define DUMPLOG 333
-enum divergence_support_t {
- POST_DOMINATOR = 1,
- NUM_SIMD_MODEL
-};
-
-struct shader_core_config
-{
- unsigned warp_size;
- bool gpgpu_perfect_mem;
- enum divergence_support_t model;
- unsigned n_thread_per_shader;
- unsigned max_warps_per_shader;
- unsigned max_cta_per_core; //Limit on number of concurrent CTAs in shader core
- unsigned pdom_sched_type;
- bool gpgpu_no_dl1;
- char *gpgpu_cache_texl1_opt;
- char *gpgpu_cache_constl1_opt;
- char *gpgpu_cache_dl1_opt;
- char *gpgpu_cache_il1_opt;
- unsigned n_mshr_per_shader;
- bool gpgpu_dwf_reg_bankconflict;
- int gpgpu_operand_collector_num_units;
- int gpgpu_operand_collector_num_units_sfu;
- bool gpgpu_stall_on_use;
- bool gpgpu_cache_wt_through;
- //Shader core resources
- unsigned gpgpu_shmem_size;
- unsigned gpgpu_shader_registers;
- int gpgpu_warpdistro_shader;
- int gpgpu_interwarp_mshr_merge;
- int gpgpu_n_shmem_bank;
- int gpgpu_n_cache_bank;
- int gpgpu_shmem_port_per_bank;
- int gpgpu_cache_port_per_bank;
- int gpgpu_const_port_per_bank;
- int gpgpu_shmem_pipe_speedup;
- unsigned gpgpu_num_reg_banks;
- unsigned gpu_max_cta_per_shader; // TODO: modify this for fermi... computed based upon kernel
- // resource usage; used in shader_core_ctx::translate_local_memaddr
- bool gpgpu_reg_bank_use_warp_id;
- int gpgpu_coalesce_arch;
- bool gpgpu_local_mem_map;
- int gpu_padded_cta_size;
-};
-
enum dram_ctrl_t {
DRAM_FIFO=0,
DRAM_IDEAL_FAST=1
@@ -309,7 +264,5 @@ extern unsigned int **concurrent_row_access; //concurrent_row_access[dram chip i
extern unsigned int gpgpu_n_sent_writes;
extern unsigned int gpgpu_n_processed_writes;
-extern unsigned made_write_mfs;
-extern unsigned made_read_mfs;
#endif
diff --git a/src/gpgpu-sim/mem_fetch.cc b/src/gpgpu-sim/mem_fetch.cc
index e2bc3e3..1a4af1e 100644
--- a/src/gpgpu-sim/mem_fetch.cc
+++ b/src/gpgpu-sim/mem_fetch.cc
@@ -107,7 +107,7 @@ void mem_fetch::print( FILE *fp ) const
{
fprintf(fp," mf: uid=%6u, addr=0x%08llx, sid=%u, wid=%u, pc=0x%04x, %s, bank=%u, ",
request_uid, addr, sid, wid, pc, (m_write?"write":"read "), tlx.bk);
- if( mshr ) mshr->print(fp,0x100);
+ if( mshr ) mshr->print(fp);
else fprintf(fp,"\n");
}
diff --git a/src/gpgpu-sim/shader.cc b/src/gpgpu-sim/shader.cc
index 28ec00d..f298a67 100644
--- a/src/gpgpu-sim/shader.cc
+++ b/src/gpgpu-sim/shader.cc
@@ -226,7 +226,7 @@ unsigned mshr_shader_unit::mshr_used() const
return m_shader_config->n_mshr_per_shader - m_free_list.size();
}
-std::deque<mshr_entry*> &mshr_shader_unit::choose_return_queue()
+std::list<mshr_entry*> &mshr_shader_unit::choose_return_queue()
{
// prioritize a ready texture over a global/const...
if ((not m_texture_mshr_pipeline.empty()) and m_texture_mshr_pipeline.front()->fetched())
@@ -244,12 +244,7 @@ void mshr_shader_unit::mshr_return_from_mem(mshr_entry *mshr)
}
}
-void shader_core_ctx::mshr_print(FILE* fp, unsigned mask)
-{
- m_mshr_unit->print(fp, this, mask);
-}
-
-void mshr_shader_unit::print(FILE* fp, shader_core_ctx* shader, unsigned mask)
+void mshr_shader_unit::print(FILE* fp)
{
unsigned n=0;
unsigned num_outstanding = 0;
@@ -257,68 +252,23 @@ void mshr_shader_unit::print(FILE* fp, shader_core_ctx* shader, unsigned mask)
mshr_entry *mshr = &(*it);
if (find(m_free_list.begin(),m_free_list.end(), mshr) == m_free_list.end()) {
num_outstanding++;
- mshr->print(fp,mask);
+ mshr->print(fp);
}
}
+ fprintf(fp,"ready texture mshrs:\n");
+ std::list<mshr_entry*>::iterator m;
+ for( m=m_texture_mshr_pipeline.begin(); m!=m_texture_mshr_pipeline.end(); m++ ) {
+ mshr_entry *mshr = *m;
+ mshr->print(fp);
+ }
+ fprintf(fp,"ready non-texture mshrs:\n");
+ for( m=m_mshr_return_queue.begin(); m!=m_mshr_return_queue.end(); m++ ) {
+ mshr_entry *mshr = *m;
+ mshr->print(fp);
+ }
fprintf(fp,"\nTotal outstanding memory requests = %u\n", num_outstanding );
}
-unsigned char shader_core_ctx::fq_push(unsigned long long int addr,
- int bsize,
- unsigned char write,
- partial_write_mask_t partial_write_mask,
- int wid,
- mshr_entry* mshr,
- enum mem_access_type mem_acc,
- address_type pc)
-{
- assert(write || (partial_write_mask == NO_PARTIAL_WRITE));
- mem_fetch *mf = new mem_fetch(addr,
- bsize,
- (write?WRITE_PACKET_SIZE:READ_PACKET_SIZE),
- m_sid,
- m_tpc,
- wid,
- mshr,
- write,
- partial_write_mask,
- mem_acc,
- (write?WT_REQ:RD_REQ),
- pc);
- if (mshr) mshr->set_mf(mf);
-
- // stats
- if (write) made_write_mfs++;
- else made_read_mfs++;
- switch (mem_acc) {
- 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_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;
- case INST_ACC_R: m_stats->gpgpu_n_mem_read_inst++; break;
- default: assert(0);
- }
-
- return(m_gpu->issue_mf_from_fq(mf));
-}
-
-void shader_core_ctx::L1cache_print( FILE *fp, unsigned &total_accesses, unsigned &total_misses) const
-{
- m_L1D->shd_cache_print(fp,total_accesses,total_misses);
-}
-
-void shader_core_ctx::L1texcache_print( FILE *fp, unsigned &total_accesses, unsigned &total_misses) const
-{
- m_L1T->shd_cache_print(fp,total_accesses,total_misses);
-}
-
-void shader_core_ctx::L1constcache_print( FILE *fp, unsigned &total_accesses, unsigned &total_misses) const
-{
- m_L1C->shd_cache_print(fp,total_accesses,total_misses);
-}
-
std::list<unsigned> shader_core_ctx::get_regs_written( const inst_t &fvt ) const
{
std::list<unsigned> result;
@@ -343,7 +293,7 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu,
const char *name,
unsigned shader_id,
unsigned tpc_id,
- const struct shader_core_config *config,
+ struct shader_core_config *config,
struct shader_core_stats *stats )
: m_barriers( config->max_warps_per_shader, config->max_cta_per_core )
{
@@ -351,19 +301,20 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu,
m_config = config;
m_stats = stats;
unsigned warp_size=config->warp_size;
+ config->max_sfu_latency = 32;
+ config->max_sp_latency = 32;
m_name = name;
m_sid = shader_id;
m_tpc = tpc_id;
+
m_pipeline_reg = new warp_inst_t*[N_PIPELINE_STAGES];
for (int j = 0; j<N_PIPELINE_STAGES; j++)
- m_pipeline_reg[j] = new warp_inst_t(warp_size);
+ m_pipeline_reg[j] = new warp_inst_t(config);
m_thread = (thread_ctx_t*) calloc(sizeof(thread_ctx_t), config->n_thread_per_shader);
- m_not_completed = 0;
-
- m_warp.resize(m_config->max_warps_per_shader, shd_warp_t(this, warp_size));
+ m_not_completed = 0;
m_n_active_cta = 0;
for (unsigned i = 0; i<MAX_CTA_PER_SHADER; i++ )
m_cta_status[i]=0;
@@ -372,41 +323,51 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu,
m_thread[i].m_cta_id = -1;
}
+ // fetch
+ m_last_warp_fetched = 0;
+ m_last_warp_issued = 0;
+
#define STRSIZE 1024
- char L1D_name[STRSIZE];
- char L1T_name[STRSIZE];
- char L1C_name[STRSIZE];
char L1I_name[STRSIZE];
-
- snprintf(L1D_name, STRSIZE, "L1D_%03d", m_sid);
- snprintf(L1T_name, STRSIZE, "L1T_%03d", m_sid);
- snprintf(L1C_name, STRSIZE, "L1C_%03d", m_sid);
snprintf(L1I_name, STRSIZE, "L1I_%03d", m_sid);
- enum cache_write_policy L1D_policy = m_config->gpgpu_cache_wt_through?write_through:write_back;
- m_L1D = new cache_t(L1D_name,m_config->gpgpu_cache_dl1_opt, 0,L1D_policy,m_sid,get_shader_normal_cache_id());
- m_L1T = new cache_t(L1T_name,m_config->gpgpu_cache_texl1_opt, 0,no_writes, m_sid,get_shader_texture_cache_id());
- m_L1C = new cache_t(L1C_name,m_config->gpgpu_cache_constl1_opt,0,no_writes, m_sid,get_shader_constant_cache_id());
m_L1I = new cache_t(L1I_name,m_config->gpgpu_cache_il1_opt, 0,no_writes, m_sid,get_shader_instruction_cache_id());
- m_gpu->ptx_set_tex_cache_linesize(m_L1T->get_line_sz());
- m_mshr_unit = new mshr_shader_unit(m_config);
+ m_warp.resize(m_config->max_warps_per_shader, shd_warp_t(this, warp_size));
m_pdom_warp = new pdom_warp_ctx_t*[config->max_warps_per_shader];
for (unsigned i = 0; i < config->max_warps_per_shader; ++i)
m_pdom_warp[i] = new pdom_warp_ctx_t(i,this);
- m_mem_rc = NO_RC_FAIL,
-
- // Initialize scoreboard
m_scoreboard = new Scoreboard(m_sid, m_config->max_warps_per_shader);
- m_operand_collector.init( m_config->gpgpu_operand_collector_num_units,
- m_config->gpgpu_operand_collector_num_units_sfu,
- m_config->gpgpu_num_reg_banks, this,
- &m_pipeline_reg[OC_EX_SP],
- &m_pipeline_reg[OC_EX_SFU] );
+ m_operand_collector.add_port( m_config->gpgpu_operand_collector_num_units_sp,
+ &m_pipeline_reg[ID_OC_SP],
+ &m_pipeline_reg[OC_EX_SP] );
+ m_operand_collector.add_port( m_config->gpgpu_operand_collector_num_units_sfu,
+ &m_pipeline_reg[ID_OC_SFU],
+ &m_pipeline_reg[OC_EX_SFU] );
+ m_operand_collector.add_port( m_config->gpgpu_operand_collector_num_units_mem,
+ &m_pipeline_reg[ID_OC_MEM],
+ &m_pipeline_reg[OC_EX_MEM] );
+ m_operand_collector.init( m_config->gpgpu_num_reg_banks, this );
- // fetch
- m_last_warp_fetched = 0;
- m_last_warp_issued = 0;
+ // execute
+ m_num_function_units = 3; // sp_unit, sfu, ldst_unit
+ m_dispatch_port = new enum pipeline_stage_name_t[ m_num_function_units ];
+ m_issue_port = new enum pipeline_stage_name_t[ m_num_function_units ];
+
+ m_fu = new simd_function_unit*[m_num_function_units];
+
+ m_fu[0] = new sp_unit( &m_pipeline_reg[EX_WB], m_config );
+ m_dispatch_port[0] = ID_OC_SP;
+ m_issue_port[0] = OC_EX_SP;
+
+ m_fu[1] = new sfu( &m_pipeline_reg[EX_WB], m_config );
+ m_dispatch_port[1] = ID_OC_SFU;
+ m_issue_port[1] = OC_EX_SFU;
+
+ m_ldst_unit = new ldst_unit( m_gpu, this, &m_pipeline_reg[EX_WB], config, m_stats, m_sid, m_tpc );
+ m_fu[2] = m_ldst_unit;
+ m_dispatch_port[2] = ID_OC_MEM;
+ m_issue_port[2] = OC_EX_MEM;
}
void shader_core_ctx::reinit(unsigned start_thread, unsigned end_thread, bool reset_not_completed )
@@ -589,14 +550,6 @@ void pdom_warp_ctx_t::print (FILE *fout) const
}
}
-
-void shader_core_ctx::new_cache_window()
-{
- m_L1D->shd_cache_new_window();
- m_L1T->shd_cache_new_window();
- m_L1C->shd_cache_new_window();
-}
-
void gpgpu_sim::print_shader_cycle_distro( FILE *fout ) const
{
fprintf(fout, "Warp Occupancy Distribution:\n");
@@ -613,7 +566,7 @@ void gpgpu_sim::print_shader_cycle_distro( FILE *fout ) const
#define PROGRAM_MEM_START 0xF0000000 /* should be distinct from other memory spaces...
check ptx_ir.h to verify this does not overlap
other memory spaces */
-void shader_core_ctx::fetch_new()
+void shader_core_ctx::fetch()
{
if( m_inst_fetch_buffer.m_valid ) {
// decode 1 or 2 instructions and place them into ibuffer
@@ -666,11 +619,22 @@ void shader_core_ctx::fetch_new()
m_last_warp_fetched=warp_id;
mshr_entry *mshr = new mshr_entry();
mshr->init(ppc,false,instruction_space,warp_id);
- fq_push( pc, req_size, false,
- NO_PARTIAL_WRITE,
- warp_id,
- mshr,
- INST_ACC_R, pc );
+
+ mem_fetch *mf = new mem_fetch(pc,
+ req_size,
+ READ_PACKET_SIZE,
+ m_sid,
+ m_tpc,
+ warp_id,
+ mshr,
+ false,
+ NO_PARTIAL_WRITE,
+ INST_ACC_R,
+ RD_REQ,
+ pc);
+ mshr->set_mf(mf);
+ m_gpu->issue_mf_from_fq(mf);
+
m_warp[warp_id].set_imiss_pending(mshr);
m_warp[warp_id].set_last_fetch(gpu_sim_cycle);
}
@@ -719,7 +683,7 @@ void shader_core_ctx::issue_warp( warp_inst_t *&pipe_reg, const warp_inst_t *nex
m_warp[warp_id].set_next_pc(next_inst->pc + next_inst->isize);
}
-void shader_core_ctx::decode_new()
+void shader_core_ctx::decode()
{
for ( unsigned i=0; i < m_config->max_warps_per_shader; i++ ) {
unsigned warp_id = (m_last_warp_issued+1+i) % m_config->max_warps_per_shader;
@@ -739,13 +703,25 @@ void shader_core_ctx::decode_new()
} else if ( !m_scoreboard->checkCollision(warp_id, pI) ) {
unsigned active_mask = m_pdom_warp[warp_id]->get_active_mask();
assert( m_warp[warp_id].inst_in_pipeline() );
- if ( (pI->op != SFU_OP) && m_pipeline_reg[ID_OC_SP]->empty() ) {
- issue_warp(m_pipeline_reg[ID_OC_SP],pI,active_mask,warp_id);
- issued++;
- } else if ( (pI->op == SFU_OP || pI->op == ALU_SFU_OP) && m_pipeline_reg[ID_OC_SFU]->empty() ) {
- issue_warp(m_pipeline_reg[ID_OC_SFU],pI,active_mask,warp_id);
- issued++;
- }
+ if ( (pI->op == LOAD_OP) || (pI->op == STORE_OP) || (pI->op == MEMORY_BARRIER_OP) ) {
+ if( m_pipeline_reg[ID_OC_MEM]->empty() ) {
+ issue_warp(m_pipeline_reg[ID_OC_MEM],pI,active_mask,warp_id);
+ issued++;
+ }
+ } else {
+ bool sp_pipe_avail = m_pipeline_reg[ID_OC_SP]->empty();
+ bool sfu_pipe_avail = m_pipeline_reg[ID_OC_SFU]->empty();
+ if( sp_pipe_avail && (pI->op != SFU_OP) ) {
+ // always prefer SP pipe for operations that can use both SP and SFU pipelines
+ issue_warp(m_pipeline_reg[ID_OC_SP],pI,active_mask,warp_id);
+ issued++;
+ } else if ( (pI->op == SFU_OP) || (pI->op == ALU_SFU_OP) ) {
+ if( sfu_pipe_avail ) {
+ issue_warp(m_pipeline_reg[ID_OC_SFU],pI,active_mask,warp_id);
+ issued++;
+ }
+ }
+ }
}
} else if( valid ) {
// this case can happen after a return instruction in diverged warp
@@ -767,7 +743,7 @@ address_type coalesced_segment(address_type addr, unsigned segment_size_lg2bytes
return (addr >> segment_size_lg2bytes);
}
-address_type shader_core_ctx::translate_local_memaddr(address_type localaddr, int tid, unsigned num_shader )
+address_type shader_core_ctx::translate_local_memaddr( address_type localaddr, unsigned tid, unsigned num_shader )
{
// During functional execution, each thread sees its own memory space for local memory, but these
// need to be mapped to a shared address space for timing simulation. We do that mapping here.
@@ -795,22 +771,26 @@ address_type shader_core_ctx::translate_local_memaddr(address_type localaddr, in
/////////////////////////////////////////////////////////////////////////////////////////
-void shader_core_ctx::execute_pipe( unsigned current_stage, unsigned next_stage )
+void shader_core_ctx::execute()
{
- if( !m_pipeline_reg[current_stage]->empty() ) {
- if( m_pipeline_reg[current_stage]->cycles > 1 ) {
- m_pipeline_reg[current_stage]->cycles--;
- return;
+ m_result_bus >>= 1;
+ for( unsigned n=0; n < m_num_function_units; n++ ) {
+ m_fu[n]->cycle();
+ enum pipeline_stage_name_t issue_port = m_issue_port[n];
+ warp_inst_t *& issue_inst = m_pipeline_reg[ issue_port ];
+ if( !issue_inst->empty() && m_fu[n]->can_issue( *issue_inst ) ) {
+ bool schedule_wb_now = !m_fu[n]->stallable();
+ if( schedule_wb_now && !m_result_bus.test( issue_inst->latency ) ) {
+ assert( issue_inst->latency < MAX_ALU_LATENCY );
+ m_result_bus.set( issue_inst->latency );
+ m_fu[n]->issue( issue_inst );
+ } else if( !schedule_wb_now ) {
+ m_fu[n]->issue( issue_inst );
+ } else {
+ // stall issue (cannot reserve result bus)
+ }
}
}
- if( m_pipeline_reg[next_stage]->empty() )
- move_warp(m_pipeline_reg[next_stage],m_pipeline_reg[current_stage]);
-}
-
-void shader_core_ctx::execute()
-{
- execute_pipe(OC_EX_SFU,EX_MM);
- execute_pipe(OC_EX_SP,EX_MM);
}
mshr_entry* mshr_shader_unit::add_mshr(mem_access_t &access, warp_inst_t* pinst)
@@ -844,35 +824,18 @@ address_type null_tag_func(address_type address, unsigned line_size)
return address; //no modification: each address is its own tag.
}
-// only 1 bank
-int shader_core_ctx::null_bank_func(address_type add, unsigned line_size)
-{
- return 1;
-}
-
-int shader_core_ctx::shmem_bank_func(address_type addr, unsigned line_size)
+unsigned shader_core_config::shmem_bank_func(address_type addr, unsigned) const
{
- //returns the integer number of the physical bank addr would go in.
- return ((int)(addr/((address_type)WORD_SIZE)) % m_config->gpgpu_n_shmem_bank);
+ return ((addr/WORD_SIZE) % gpgpu_n_shmem_bank);
}
-int shader_core_ctx::dcache_bank_func(address_type add, unsigned line_size)
+unsigned shader_core_config::dcache_bank_func(address_type add, unsigned line_size) const
{
- //returns the integer number of the physical bank addr would go in.
- if (m_config->gpgpu_no_dl1) return 1; //no banks
- else return (add / line_size) & (m_config->gpgpu_n_cache_bank - 1);
+ if (gpgpu_no_dl1) return 1; //no banks
+ else return (add / line_size) & (gpgpu_n_cache_bank - 1);
}
-typedef int (shader_core_ctx::*bank_func_t)(address_type add, unsigned line_size);
-typedef address_type (*tag_func_t)(address_type add, unsigned line_size);
-
-void shader_core_ctx::get_memory_access_list(
- shader_core_ctx::bank_func_t bank_func,
- tag_func_t tag_func,
- unsigned warp_parts,
- unsigned line_size,
- bool limit_broadcast,
- warp_inst_t &inst )
+void warp_inst_t::get_memory_access_list()
{
// Calculates memory accesses generated by this warp
// Returns acesses which are "coalesced"
@@ -882,6 +845,9 @@ void shader_core_ctx::get_memory_access_list(
// It produces the set of distinct memory accesses that need to be peformed.
// These accessess are then performed over multiple cycles (stalling the pipeline)
// if the accessses cannot be performed all at once.
+
+ // In hardware, these accesses would be created at the specific unit handling the type
+ // of memory access. We centralize the logic simply to reduce code duplication.
// Below, accesses are assigned an "order" based on when that access may be issued.
// Accesses with the same order number may occur at the same time: they are to different banks.
@@ -890,6 +856,59 @@ void shader_core_ctx::get_memory_access_list(
//
// Accesses are placed in accessq sorted so that accesses of the same order are adjacent.
+ bank_func_t bank_func = NULL;
+ tag_func_t tag_func = NULL;
+ unsigned warp_parts = 0;
+ unsigned line_size = 0;
+ bool limit_broadcast = 0;
+ bool global_mem_access = false;
+
+ switch( space.get_type() ) {
+ case shared_space:
+ bank_func = &shader_core_config::shmem_bank_func;
+ tag_func = null_tag_func;
+ warp_parts = m_config->gpgpu_shmem_pipe_speedup;
+ line_size = 1; //shared memory doesn't care about line_size, needs to be at least 1;
+ limit_broadcast = true; // limit broadcasts to single cycle.
+ break;
+ case tex_space:
+ bank_func = &shader_core_config::null_bank_func;
+ tag_func = line_size_based_tag_func;
+ warp_parts = 1;
+ line_size = m_config->gpgpu_cache_texl1_linesize;
+ limit_broadcast = false;
+ break;
+ case const_space: case param_space_kernel:
+ bank_func = &shader_core_config::null_bank_func;
+ tag_func = line_size_based_tag_func;
+ warp_parts = 1;
+ line_size = m_config->gpgpu_cache_constl1_linesize;
+ limit_broadcast = false;
+ break;
+ case global_space: case local_space: case param_space_local:
+ global_mem_access=true;
+ warp_parts = 1;
+ line_size = m_config->gpgpu_cache_dl1_linesize;
+ if( m_config->gpgpu_coalesce_arch == 13 ){
+ warp_parts = 2;
+ if( m_config->gpgpu_no_dl1 ) {
+ // line size is dependant on instruction;
+ switch (data_size) {
+ case 1: line_size = 32; break;
+ case 2: line_size = 64; break;
+ case 4: case 8: case 16: line_size = 128; break;
+ default: assert(0);
+ }
+ }
+ }
+ bank_func = &shader_core_config::dcache_bank_func;
+ tag_func = line_size_based_tag_func;
+ limit_broadcast = false;
+ break;
+ default:
+ abort();
+ }
+
// bank_accs tracks bank accesses for sorting into generations;
// each entry is (bank #, number of accesses)
// the idea is that you can only access a bank a number of times each cycle equal to
@@ -898,76 +917,83 @@ void shader_core_ctx::get_memory_access_list(
// keep track of broadcasts with unique orders if limit_broadcast
// the normally calculated orders will never be greater than warp_size
- unsigned broadcast_order = m_config->warp_size;
- unsigned qbegin = inst.get_accessq_size();
+ unsigned broadcast_order = warp_size();
+ unsigned qbegin = get_accessq_size();
unsigned qpartbegin = qbegin;
- unsigned mem_pipe_size = m_config->warp_size / warp_parts;
- for (unsigned part = 0; part < m_config->warp_size; part += mem_pipe_size) {
+ unsigned mem_pipe_size = warp_size() / warp_parts;
+ for (unsigned part = 0; part < warp_size(); part += mem_pipe_size) {
for (unsigned i = part; i < part + mem_pipe_size; i++) {
- if ( !inst.active(i) )
+ if ( !active(i) )
continue;
- assert( inst.space != undefined_space );
- new_addr_type addr = inst.get_addr(i);
+ new_addr_type addr = get_addr(i);
address_type lane_segment_address = tag_func(addr, line_size);
unsigned quarter = 0;
if( line_size>=4 )
quarter = (addr / (line_size/4)) & 3;
bool match = false;
- if( !inst.isatomic() ) { //atomics must have own request
- for( unsigned j = qpartbegin; j <inst.get_accessq_size(); j++ ) {
- if (lane_segment_address == inst.accessq(j).addr) {
- inst.accessq(j).quarter_count[quarter]++;
- inst.accessq(j).warp_indices.push_back(i);
+ if( !isatomic() ) { //atomics must have own request
+ for( unsigned j = qpartbegin; j <get_accessq_size(); j++ ) {
+ if (lane_segment_address == accessq(j).addr) {
+ accessq(j).quarter_count[quarter]++;
+ accessq(j).warp_indices.push_back(i);
if (limit_broadcast) // two threads access this address, so its a broadcast.
- inst.accessq(j).order = ++broadcast_order; //do broadcast in its own cycle.
+ accessq(j).order = ++broadcast_order; //do broadcast in its own cycle.
match = true;
break;
}
}
}
if (!match) { // does not match a previous request by another thread, so need a new request
- assert( inst.space != undefined_space );
- inst.accessq_push_back( mem_access_t( lane_segment_address, line_size, quarter, i) );
+ assert( space != undefined_space );
+ m_accessq.push_back( mem_access_t( lane_segment_address, line_size, quarter, i) );
// Determine Bank Conflicts:
- unsigned bank = (this->*bank_func)(inst.get_addr(i), line_size);
+ unsigned bank = (m_config->*bank_func)(get_addr(i), line_size);
// ensure no concurrent bank access accross warp parts.
// ie. order will be less than part for all previous loads in previous parts, so:
if (bank_accs[bank] < part)
bank_accs[bank]=part;
- inst.accessq_back().order = bank_accs[bank];
+ accessq_back().order = bank_accs[bank];
bank_accs[bank]++;
}
}
- qpartbegin = inst.get_accessq_size(); //don't coalesce accross warp parts
+ qpartbegin = get_accessq_size(); //don't coalesce accross warp parts
}
//sort requests by order they will be processed in
- inst.sort_accessq(qbegin);
-}
+ std::stable_sort( m_accessq.begin()+qbegin,m_accessq.end());
-void shader_core_ctx::memory_shared_process_warp(warp_inst_t &inst)
-{
- // initial processing of shared memory warps
- get_memory_access_list(&shader_core_ctx::shmem_bank_func,
- null_tag_func,
- m_config->gpgpu_shmem_pipe_speedup,
- 1, //shared memory doesn't care about line_size, needs to be at least 1;
- true,
- inst); // limit broadcasts to single cycle.
-}
+ if( global_mem_access ) {
+ // Now that we have the accesses, if we don't have a cache we can adjust request sizes to
+ // include only the data referenced by the threads
+ for (unsigned i = 0; i < get_accessq_size(); i++) {
+ if (m_config->gpgpu_coalesce_arch == 13 && m_config->gpgpu_no_dl1) {
+ // do coalescing here.
+ char* quarter_counts = accessq(i).quarter_count;
+ bool low = quarter_counts[0] or quarter_counts[1];
+ bool high = quarter_counts[2] or quarter_counts[3];
+ if (accessq(i).req_size == 128) {
+ if (low xor high) { //can reduce size
+ accessq(i).req_size = 64;
+ if (high) accessq(i).addr += 64;
+ low = quarter_counts[0] or quarter_counts[2]; //set low and high for next pass
+ high = quarter_counts[1] or quarter_counts[3];
+ }
+ }
+ if (accessq(i).req_size == 64) {
+ if (low xor high) { //can reduce size
+ accessq(i).req_size = 32;
+ if (high) accessq(i).addr += 32;
+ }
+ }
+ }
+ }
+ }
+}
-void shader_core_ctx::memory_const_process_warp(warp_inst_t &inst)
+void ldst_unit::const_cache_access(warp_inst_t &inst)
{
- // initial processing of const memory warps
- unsigned qbegin = inst.get_accessq_size();
- get_memory_access_list( &shader_core_ctx::null_bank_func,
- line_size_based_tag_func,
- 1, //warp parts
- m_L1C->get_line_sz(),
- false, //no broadcast limit.
- inst);
// do cache checks here for each request (non-physical), could be
// done later for more accurate timing of cache accesses, but probably uneccesary;
- for (unsigned i = qbegin; i < inst.get_accessq_size(); i++) {
+ for (unsigned i = 0; i < inst.get_accessq_size(); i++) {
mem_access_t &req = inst.accessq(i);
if ( inst.space == param_space_kernel ) {
req.cache_hit = true;
@@ -984,19 +1010,11 @@ void shader_core_ctx::memory_const_process_warp(warp_inst_t &inst)
}
}
-void shader_core_ctx::memory_texture_process_warp(warp_inst_t &inst)
+void ldst_unit::tex_cache_access(warp_inst_t &inst)
{
- // initial processing of shared texture warps
- unsigned qbegin = inst.get_accessq_size();
- get_memory_access_list(&shader_core_ctx::null_bank_func,
- &line_size_based_tag_func,
- 1, //warp parts
- m_L1T->get_line_sz(),
- false, //no broadcast limit.
- inst);
// do cache checks here for each request (non-hardware), could be done later
// for more accurate timing of cache accesses, but probably uneccesary;
- for (unsigned i = qbegin; i < inst.get_accessq_size(); i++) {
+ for (unsigned i = 0; i < inst.get_accessq_size(); i++) {
mem_access_t &req = inst.accessq(i);
cache_request_status status = m_L1T->access( req.addr,
0, //should always be a read
@@ -1009,78 +1027,35 @@ void shader_core_ctx::memory_texture_process_warp(warp_inst_t &inst)
}
}
-void shader_core_ctx::memory_global_process_warp( warp_inst_t &inst )
-{
- unsigned qbegin = inst.get_accessq_size();
- unsigned warp_parts = 1;
- unsigned line_size = m_L1D->get_line_sz();
- if (m_config->gpgpu_coalesce_arch == 13) {
- warp_parts = 2;
- if(m_config->gpgpu_no_dl1) {
- unsigned data_size = inst.data_size;
- // line size is dependant on instruction;
- switch (data_size) {
- case 1: line_size = 32; break;
- case 2: line_size = 64; break;
- case 4: case 8: case 16: line_size = 128; break;
- default: assert(0);
- }
- }
- }
- get_memory_access_list( &shader_core_ctx::dcache_bank_func,
- &line_size_based_tag_func,
- warp_parts,
- line_size,
- false,
- inst );
-
- // Now that we have the accesses, if we don't have a cache we can adjust request sizes to
- // include only the data referenced by the threads
- for (unsigned i = qbegin; i < inst.get_accessq_size(); i++) {
- if (m_config->gpgpu_coalesce_arch == 13 and m_config->gpgpu_no_dl1) {
- //if there is no l1 cache it makes sense to do coalescing here.
- //reduce memory request sizes.
- char* quarter_counts = inst.accessq(i).quarter_count;
- bool low = quarter_counts[0] or quarter_counts[1];
- bool high = quarter_counts[2] or quarter_counts[3];
- if (inst.accessq(i).req_size == 128) {
- if (low xor high) { //can reduce size
- inst.accessq(i).req_size = 64;
- if (high) inst.accessq(i).addr += 64;
- low = quarter_counts[0] or quarter_counts[2]; //set low and high for next pass
- high = quarter_counts[1] or quarter_counts[3];
- }
- }
- if (inst.accessq(i).req_size == 64) {
- if (low xor high) { //can reduce size
- inst.accessq(i).req_size = 32;
- if (high) inst.accessq(i).addr += 32;
- }
- }
- }
- }
-}
-
-mem_stage_stall_type shader_core_ctx::send_mem_request(warp_inst_t &inst, mem_access_t &access)
+mem_stage_stall_type ldst_unit::send_mem_request(warp_inst_t &inst, mem_access_t &access)
{
// Attempt to send an request/write to memory based on information in access.
// If the cache told us it needed to write back a dirty line, do this now
// It is possible to do this writeback in the same cycle as the access request, this may not be realistic.
if (access.need_wb) {
- unsigned req_size = m_L1D->get_line_sz() + WRITE_PACKET_SIZE;
- if ( ! m_gpu->fq_has_buffer(access.wb_addr, req_size, true, m_sid) ) {
+ unsigned req_size = m_config->gpgpu_cache_dl1_linesize + WRITE_PACKET_SIZE;
+ if ( !m_gpu->fq_has_buffer(access.wb_addr, req_size, true, m_sid) ) {
m_stats->gpu_stall_sh2icnt++;
return WB_ICNT_RC_FAIL;
}
- fq_push( access.wb_addr, req_size, true, NO_PARTIAL_WRITE, -1, NULL,
- inst.space.is_local()?LOCAL_ACC_W:GLOBAL_ACC_W, //space of cache line is same as new request
- -1);
+ mem_fetch *mf = new mem_fetch(access.wb_addr,
+ req_size,
+ READ_PACKET_SIZE,
+ m_sid,
+ m_tpc,
+ -1,
+ NULL,
+ true,
+ NO_PARTIAL_WRITE,
+ inst.space.is_local()?LOCAL_ACC_W:GLOBAL_ACC_W, //space of cache line is same as new request
+ WT_REQ,
+ -1);
+ m_gpu->issue_mf_from_fq(mf);
m_stats->L1_writeback++;
access.need_wb = false;
}
-
bool is_write = inst.is_store();
mem_access_type access_type;
switch(inst.space.get_type()) {
@@ -1098,7 +1073,8 @@ mem_stage_stall_type shader_core_ctx::send_mem_request(warp_inst_t &inst, mem_ac
if (not m_mshr_unit->has_mshr(1))
return MSHR_RC_FAIL;
access.reserved_mshr = m_mshr_unit->add_mshr(access, &inst);
- access.recheck_cache = false; //we have an mshr now, so have checked cache in same cycle as checking mshrs, so have merged if necessary.
+ access.recheck_cache = false;
+ //we have an mshr now, so have checked cache in same cycle as checking mshrs, so have merged if necessary.
}
//require inct if access is this far without reserved mshr, or has and mshr but not merged with another request
bool requires_icnt = (!access.reserved_mshr) || (!access.reserved_mshr->ismerged());
@@ -1120,7 +1096,7 @@ mem_stage_stall_type shader_core_ctx::send_mem_request(warp_inst_t &inst, mem_ac
partial_write_mask_t write_mask = NO_PARTIAL_WRITE;
unsigned warp_id = inst.warp_id();
if (is_write) {
- m_warp[warp_id].inc_store_req();
+ m_core->inc_store_req(warp_id);
for (unsigned i=0;i < access.warp_indices.size();i++) {
unsigned w = access.warp_indices[i];
int data_offset = inst.get_addr(w) & ((unsigned long long int)access.req_size - 1);
@@ -1129,29 +1105,40 @@ mem_stage_stall_type shader_core_ctx::send_mem_request(warp_inst_t &inst, mem_ac
if (write_mask.count() != access.req_size)
m_stats->gpgpu_n_partial_writes++;
}
- fq_push( access.addr, request_size,
- is_write, write_mask, warp_id , access.reserved_mshr,
- access_type, inst.pc );
+ mem_fetch *mf = new mem_fetch(access.addr,
+ request_size,
+ is_write?WRITE_PACKET_SIZE:READ_PACKET_SIZE,
+ m_sid,
+ m_tpc,
+ warp_id,
+ access.reserved_mshr,
+ is_write,
+ write_mask,
+ access_type,
+ is_write?WT_REQ:RD_REQ,
+ inst.pc);
+ if( access.reserved_mshr )
+ access.reserved_mshr->set_mf(mf);
+ m_gpu->issue_mf_from_fq(mf);
}
return NO_RC_FAIL;
}
void shader_core_ctx::writeback()
{
- mshr_entry *m = m_mshr_unit->return_head();
- if( m )
- m_mshr_unit->pop_return_head();
- if( !m_pipeline_reg[MM_WB]->empty() ) {
- m_scoreboard->releaseRegisters( m_pipeline_reg[MM_WB] );
- m_warp[m_pipeline_reg[MM_WB]->warp_id()].dec_inst_in_pipeline();
+ warp_inst_t *&pipe_reg = m_pipeline_reg[EX_WB];
+ if( !pipe_reg->empty() ) {
+ unsigned warp_id = pipe_reg->warp_id();
+ m_scoreboard->releaseRegisters( pipe_reg );
+ m_warp[warp_id].dec_inst_in_pipeline();
m_gpu->gpu_sim_insn_last_update_sid = m_sid;
m_gpu->gpu_sim_insn_last_update = gpu_sim_cycle;
- m_gpu->gpu_sim_insn += m_pipeline_reg[MM_WB]->active_count();
+ m_gpu->gpu_sim_insn += pipe_reg->active_count();
+ pipe_reg->clear();
}
- move_warp(m_pipeline_reg[WB_RT],m_pipeline_reg[MM_WB]);
}
-bool shader_core_ctx::memory_shared_cycle( warp_inst_t &inst, mem_stage_stall_type &rc_fail, mem_stage_access_type &fail_type)
+bool ldst_unit::shared_cycle( warp_inst_t &inst, mem_stage_stall_type &rc_fail, mem_stage_access_type &fail_type)
{
// Process a single cycle of activity from the shared memory queue.
if( inst.space.get_type() != shared_space )
@@ -1174,10 +1161,10 @@ bool shader_core_ctx::memory_shared_cycle( warp_inst_t &inst, mem_stage_stall_ty
return inst.accessq_empty(); //done if empty.
}
-mem_stage_stall_type shader_core_ctx::process_memory_access_queue( shader_core_ctx::cache_check_t cache_check,
- unsigned ports_per_bank,
- unsigned memory_send_max,
- warp_inst_t &inst )
+mem_stage_stall_type ldst_unit::process_memory_access_queue( ldst_unit::cache_check_t cache_check,
+ unsigned ports_per_bank,
+ unsigned memory_send_max,
+ warp_inst_t &inst )
{
// Generic algorithm for processing a single cycle of accesses for the memory space types that go to L2 or DRAM.
@@ -1211,13 +1198,13 @@ mem_stage_stall_type shader_core_ctx::process_memory_access_queue( shader_core_c
return hazard_cond;
}
-bool shader_core_ctx::memory_constant_cycle( warp_inst_t &inst, mem_stage_stall_type &rc_fail, mem_stage_access_type &fail_type)
+bool ldst_unit::constant_cycle( warp_inst_t &inst, mem_stage_stall_type &rc_fail, mem_stage_access_type &fail_type)
{
if( (inst.space.get_type() != const_space) && (inst.space.get_type() != param_space_kernel) )
return true;
// Process a single cycle of activity from the the constant memory queue.
- mem_stage_stall_type fail = process_memory_access_queue(&shader_core_ctx::ccache_check,
+ mem_stage_stall_type fail = process_memory_access_queue(&ldst_unit::ccache_check,
m_config->gpgpu_const_port_per_bank,
1, //memory send max per cycle
inst );
@@ -1231,14 +1218,14 @@ bool shader_core_ctx::memory_constant_cycle( warp_inst_t &inst, mem_stage_stall_
return inst.accessq_empty(); //done if empty.
}
-bool shader_core_ctx::memory_texture_cycle( warp_inst_t &inst, mem_stage_stall_type &rc_fail, mem_stage_access_type &fail_type)
+bool ldst_unit::texture_cycle( warp_inst_t &inst, mem_stage_stall_type &rc_fail, mem_stage_access_type &fail_type)
{
if( inst.space.get_type() != tex_space )
return true;
// Process a single cycle of activity from the the texture memory queue.
- mem_stage_stall_type fail = process_memory_access_queue(&shader_core_ctx::tcache_check,
+ mem_stage_stall_type fail = process_memory_access_queue(&ldst_unit::tcache_check,
1, //how is tex memory banked?
1, //memory send max per cycle
inst );
@@ -1250,7 +1237,7 @@ bool shader_core_ctx::memory_texture_cycle( warp_inst_t &inst, mem_stage_stall_t
}
-mem_stage_stall_type shader_core_ctx::dcache_check(warp_inst_t &inst, mem_access_t& access)
+mem_stage_stall_type ldst_unit::dcache_check(warp_inst_t &inst, mem_access_t& access)
{
// Global memory (data cache) checks the cache for each access at the time it is processed.
// This is more accurate to hardware, and necessary for proper action of the writeback cache.
@@ -1311,7 +1298,7 @@ mem_stage_stall_type shader_core_ctx::dcache_check(warp_inst_t &inst, mem_access
return NO_RC_FAIL;
}
-bool shader_core_ctx::memory_cycle( warp_inst_t &inst, mem_stage_stall_type &stall_reason, mem_stage_access_type &access_type )
+bool ldst_unit::memory_cycle( warp_inst_t &inst, mem_stage_stall_type &stall_reason, mem_stage_access_type &access_type )
{
if( (inst.space.get_type() != global_space) &&
(inst.space.get_type() != local_space) &&
@@ -1319,7 +1306,7 @@ bool shader_core_ctx::memory_cycle( warp_inst_t &inst, mem_stage_stall_type &sta
return true;
// Process a single cycle of activity from the the global/local memory queue.
- mem_stage_stall_type stall_cond = process_memory_access_queue(&shader_core_ctx::dcache_check,m_config->gpgpu_cache_port_per_bank,1,inst);
+ mem_stage_stall_type stall_cond = process_memory_access_queue(&ldst_unit::dcache_check,m_config->gpgpu_cache_port_per_bank,1,inst);
if (stall_cond != NO_RC_FAIL) {
stall_reason = stall_cond;
bool iswrite = inst.is_store();
@@ -1333,36 +1320,114 @@ bool shader_core_ctx::memory_cycle( warp_inst_t &inst, mem_stage_stall_type &sta
return inst.accessq_empty(); //done if empty.
}
-void shader_core_ctx::memory_queue( warp_inst_t &pipe_reg )
+void ldst_unit::fill( mem_fetch *mf )
+{
+ m_mshr_unit->mshr_return_from_mem(mf->get_mshr());
+ if (mf->istexture())
+ m_L1T->shd_cache_fill(mf->get_addr(),gpu_sim_cycle+gpu_tot_sim_cycle);
+ else if (mf->isconst())
+ m_L1C->shd_cache_fill(mf->get_addr(),gpu_sim_cycle+gpu_tot_sim_cycle);
+ else if (!m_config->gpgpu_no_dl1)
+ m_L1D->shd_cache_fill(mf->get_addr(),gpu_sim_cycle+gpu_tot_sim_cycle);
+}
+
+void ldst_unit::flush()
+{
+ m_L1D->flush();
+ // TODO: add flush 'interface' object to provide functionality commented out below
+ /*
+
+ unsigned int i;
+ unsigned int set;
+ unsigned long long int flush_addr;
+ cache_t *cp = m_L1D;
+ cache_block_t *pline;
+ for (i=0; i<cp->m_nset*cp->m_assoc; i++) {
+ pline = &(cp->m_lines[i]);
+ set = i / cp->m_assoc;
+ if ((pline->status & (DIRTY|VALID)) == (DIRTY|VALID)) {
+ flush_addr = pline->addr;
+ fq_push(flush_addr, m_L1D->get_line_sz(), 1, NO_PARTIAL_WRITE, 0, NULL, 0, GLOBAL_ACC_W, -1);
+ pline->status &= ~VALID;
+ pline->status &= ~DIRTY;
+ } else if (pline->status & VALID) {
+ pline->status &= ~VALID;
+ }
+ }
+ */
+}
+
+void ldst_unit::generate_mem_accesses(warp_inst_t &inst)
{
- // Called once per warp when warp enters memory stage.
- // Generates a list of memory accesses, but does not perform the memory access.
- if( pipe_reg.empty() )
+ // Called once per warp when warp enters ld/st unit.
+ // Generates a list of memory accesses, but does not perform the memory access.
+ if( inst.empty() )
return;
- if( pipe_reg.mem_accesses_computed() )
+ if( inst.op == MEMORY_BARRIER_OP )
return;
- m_gpu->mem_instruction_stats(pipe_reg);
- switch( pipe_reg.space.get_type() ) {
- case shared_space: memory_shared_process_warp(pipe_reg); break;
- case tex_space: memory_texture_process_warp(pipe_reg); break;
- case const_space: case param_space_kernel: memory_const_process_warp(pipe_reg); break;
- case global_space: case local_space: case param_space_local: memory_global_process_warp(pipe_reg); break;
+ if( inst.mem_accesses_created() )
+ return;
+ inst.get_memory_access_list();
+ switch( inst.space.get_type() ) {
+ case shared_space: break;
+ case tex_space: tex_cache_access(inst); break;
+ case const_space: case param_space_kernel: const_cache_access(inst); break;
+ case global_space: case local_space: case param_space_local: break;
case param_space_unclassified: abort(); break;
default: break; // non-memory operations
}
- pipe_reg.set_mem_accesses_computed();
+ m_gpu->mem_instruction_stats(inst);
+ inst.set_mem_accesses_created();
}
-void shader_core_ctx::memory()
+ldst_unit::ldst_unit( gpgpu_sim *gpu,
+ shader_core_ctx *core,
+ warp_inst_t **result_port,
+ shader_core_config *config,
+ shader_core_stats *stats,
+ unsigned sid,
+ unsigned tpc ) : simd_function_unit(result_port,config)
{
- warp_inst_t &pipe_reg = *m_pipeline_reg[EX_MM];
- memory_queue(pipe_reg);
- bool done = true;
+ m_gpu = gpu;
+ m_core = core;
+ m_stats = stats;
+ m_sid = sid;
+ m_tpc = tpc;
+ #define STRSIZE 1024
+ char L1D_name[STRSIZE];
+ char L1T_name[STRSIZE];
+ char L1C_name[STRSIZE];
+ snprintf(L1D_name, STRSIZE, "L1D_%03d", m_sid);
+ snprintf(L1T_name, STRSIZE, "L1T_%03d", m_sid);
+ snprintf(L1C_name, STRSIZE, "L1C_%03d", m_sid);
+ enum cache_write_policy L1D_policy = m_config->gpgpu_cache_wt_through?write_through:write_back;
+ m_L1D = new cache_t(L1D_name,m_config->gpgpu_cache_dl1_opt,0,L1D_policy,m_sid,get_shader_normal_cache_id());
+ m_L1T = new cache_t(L1T_name,m_config->gpgpu_cache_texl1_opt,0,no_writes, m_sid,get_shader_texture_cache_id());
+ m_L1C = new cache_t(L1C_name,m_config->gpgpu_cache_constl1_opt,0,no_writes, m_sid,get_shader_constant_cache_id());
+ config->gpgpu_cache_dl1_linesize = m_L1D->get_line_sz();
+ config->gpgpu_cache_texl1_linesize = m_L1T->get_line_sz();
+ config->gpgpu_cache_constl1_linesize = m_L1C->get_line_sz();
+ m_gpu->ptx_set_tex_cache_linesize(m_L1T->get_line_sz());
+ m_mshr_unit = new mshr_shader_unit(m_config);
+ m_mem_rc = NO_RC_FAIL;
+}
+
+void ldst_unit::cycle()
+{
+ mshr_entry *m = m_mshr_unit->return_head();
+ if( m ) {
+ delete m->get_mf();
+ m_mshr_unit->pop_return_head();
+ }
+
+ warp_inst_t &pipe_reg = *m_dispatch_reg;
+ generate_mem_accesses(pipe_reg);
enum mem_stage_stall_type rc_fail = NO_RC_FAIL;
mem_stage_access_type type;
- done &= memory_shared_cycle(pipe_reg, rc_fail, type);
- done &= memory_constant_cycle(pipe_reg, rc_fail, type);
- done &= memory_texture_cycle(pipe_reg, rc_fail, type);
+ bool done = true;
+ done &= shared_cycle(pipe_reg, rc_fail, type);
+ done &= constant_cycle(pipe_reg, rc_fail, type);
+ done &= texture_cycle(pipe_reg, rc_fail, type);
done &= memory_cycle(pipe_reg, rc_fail, type);
m_mem_rc = rc_fail;
if (!done) { // log stall types and return
@@ -1371,9 +1436,9 @@ void shader_core_ctx::memory()
m_stats->gpu_stall_shd_mem_breakdown[type][rc_fail]++;
return;
}
- if( !m_pipeline_reg[MM_WB]->empty() )
+ if( !(*m_result_port)->empty() )
return; // writeback stalled
- move_warp(m_pipeline_reg[MM_WB],m_pipeline_reg[EX_MM]);
+ move_warp(*m_result_port,m_dispatch_reg);
}
void shader_core_ctx::register_cta_thread_exit(int tid )
@@ -1467,33 +1532,24 @@ void gpgpu_sim::shader_print_l1_miss_stat( FILE *fout )
fprintf(fout, "\n");
}
-void shader_core_ctx::print_warp( warp_inst_t *warp, FILE *fout, int print_mem, int mask ) const
+void warp_inst_t::print( FILE *fout ) const
{
- if ( warp->empty() ) {
+ if (empty() ) {
fprintf(fout,"bubble\n" );
return;
} else
- fprintf(fout,"0x%04x ", warp->pc );
- unsigned warp_id = warp->warp_id();
- fprintf(fout, "w%02d[", warp_id);
+ fprintf(fout,"0x%04x ", pc );
+ fprintf(fout, "w%02d[", m_warp_id);
for (unsigned j=0; j<m_config->warp_size; j++)
- fprintf(fout, "%c", (warp->active(j)?'1':'0') );
+ fprintf(fout, "%c", (active(j)?'1':'0') );
fprintf(fout, "]: ");
- if ( m_config->model == POST_DOMINATOR ) {
- unsigned rp = m_pdom_warp[warp_id]->get_rp();
- if ( rp == (unsigned)-1 ) {
- fprintf(fout," rp:--- ");
- } else {
- fprintf(fout," rp:0x%03x ", rp );
- }
- }
- ptx_print_insn( warp->pc, fout );
+ ptx_print_insn( pc, fout );
fprintf(fout, "\n");
}
-void shader_core_ctx::print_stage(unsigned int stage, FILE *fout, int print_mem, int mask )
+void shader_core_ctx::print_stage(unsigned int stage, FILE *fout ) const
{
- print_warp(m_pipeline_reg[stage],fout,print_mem,mask);
+ m_pipeline_reg[stage]->print(fout);
}
void shader_core_ctx::display_pdom_state(FILE *fout, int mask )
@@ -1523,6 +1579,27 @@ void shader_core_ctx::display_pdom_state(FILE *fout, int mask )
}
}
+void ldst_unit::print(FILE *fout) const
+{
+ fprintf(fout,"LD/ST unit = ");
+ m_dispatch_reg->print(fout);
+ if ( m_mem_rc != NO_RC_FAIL ) {
+ fprintf(fout," LD/ST stall condition: ");
+ switch ( m_mem_rc ) {
+ case BK_CONF: fprintf(fout,"BK_CONF"); break;
+ case MSHR_RC_FAIL: fprintf(fout,"MSHR_RC_FAIL"); break;
+ case ICNT_RC_FAIL: fprintf(fout,"ICNT_RC_FAIL"); break;
+ case COAL_STALL: fprintf(fout,"COAL_STALL"); break;
+ case WB_ICNT_RC_FAIL: fprintf(fout,"WB_ICNT_RC_FAIL"); break;
+ case WB_CACHE_RSRV_FAIL: fprintf(fout,"WB_CACHE_RSRV_FAIL"); break;
+ case N_MEM_STAGE_STALL_TYPE: fprintf(fout,"N_MEM_STAGE_STALL_TYPE"); break;
+ default: abort();
+ }
+ fprintf(fout,"\n");
+ }
+ m_mshr_unit->print(fout);
+}
+
void shader_core_ctx::display_pipeline(FILE *fout, int print_mem, int mask )
{
fprintf(fout, "=================================================\n");
@@ -1553,34 +1630,27 @@ void shader_core_ctx::display_pipeline(FILE *fout, int print_mem, int mask )
m_scoreboard->printContents();
fprintf(fout,"ID/OC (SP) = ");
- print_stage(ID_OC_SP, fout, print_mem, mask);
+ print_stage(ID_OC_SP, fout);
fprintf(fout,"ID/OC (SFU) = ");
- print_stage(ID_OC_SFU, fout, print_mem, mask);
+ print_stage(ID_OC_SFU, fout);
+ fprintf(fout,"ID/OC (MEM) = ");
+ print_stage(ID_OC_MEM, fout);
+
m_operand_collector.dump(fout);
- fprintf(fout, "ID/EX (SP) = ");
- print_stage(OC_EX_SP, fout, print_mem, mask);
- fprintf(fout, "ID/EX (SFU) = ");
- print_stage(OC_EX_SFU, fout, print_mem, mask);
- fprintf(fout, "EX/MEM = ");
- print_stage(EX_MM, fout, print_mem, mask);
- if( m_mem_rc != NO_RC_FAIL ) {
- fprintf(fout, "EX/MEM (stall condition: ");
- switch ( m_mem_rc ) {
- case BK_CONF: fprintf(fout,"BK_CONF"); break;
- case MSHR_RC_FAIL: fprintf(fout,"MSHR_RC_FAIL"); break;
- case ICNT_RC_FAIL: fprintf(fout,"ICNT_RC_FAIL"); break;
- case COAL_STALL: fprintf(fout,"COAL_STALL"); break;
- case WB_ICNT_RC_FAIL: fprintf(fout,"WB_ICNT_RC_FAIL"); break;
- case WB_CACHE_RSRV_FAIL: fprintf(fout,"WB_CACHE_RSRV_FAIL"); break;
- case N_MEM_STAGE_STALL_TYPE: fprintf(fout,"N_MEM_STAGE_STALL_TYPE"); break;
- default: abort();
- }
- fprintf(fout,")\n");
- }
- fprintf(fout, "MEM/WB = ");
- print_stage(MM_WB, fout, print_mem, mask);
+
+ fprintf(fout, "OC/EX (SP) = ");
+ print_stage(OC_EX_SP, fout);
+ fprintf(fout, "OC/EX (SFU) = ");
+ print_stage(OC_EX_SFU, fout);
+ fprintf(fout, "OC/EX (MEM) = ");
+ print_stage(OC_EX_MEM, fout);
+ for( unsigned n=0; n < m_num_function_units; n++ )
+ m_fu[n]->print(fout);
+ std::string bits = m_result_bus.to_string();
+ fprintf(fout, "EX/WB sched= %s\n", bits.c_str() );
+ fprintf(fout, "EX/WB = ");
+ print_stage(EX_WB, fout);
fprintf(fout, "\n");
- mshr_print(fout,0);
}
unsigned int shader_core_ctx::max_cta( class function_info *kernel )
@@ -1632,43 +1702,20 @@ unsigned int shader_core_ctx::max_cta( class function_info *kernel )
return result;
}
-void shader_core_ctx::cycle_gt200()
+void shader_core_ctx::cycle()
{
- m_pipeline_reg[WB_RT]->clear();
writeback();
- memory();
execute();
- m_operand_collector.step(m_pipeline_reg[ID_OC_SP],m_pipeline_reg[ID_OC_SFU]);
- decode_new();
- fetch_new();
+ m_operand_collector.step();
+ decode();
+ fetch();
}
// Flushes all content of the cache to memory
void shader_core_ctx::cache_flush()
{
- m_L1D->flush();
- // TODO: add flush 'interface' object to provide functionality commented out below
-/*
-
- unsigned int i;
- unsigned int set;
- unsigned long long int flush_addr;
- cache_t *cp = m_L1D;
- cache_block_t *pline;
- for (i=0; i<cp->m_nset*cp->m_assoc; i++) {
- pline = &(cp->m_lines[i]);
- set = i / cp->m_assoc;
- if ((pline->status & (DIRTY|VALID)) == (DIRTY|VALID)) {
- flush_addr = pline->addr;
- fq_push(flush_addr, m_L1D->get_line_sz(), 1, NO_PARTIAL_WRITE, 0, NULL, 0, GLOBAL_ACC_W, -1);
- pline->status &= ~VALID;
- pline->status &= ~DIRTY;
- } else if (pline->status & VALID) {
- pline->status &= ~VALID;
- }
- }
-*/
+ m_ldst_unit->flush();
}
static int *_inmatch;
@@ -2057,43 +2104,42 @@ void mshr_entry::set_status( enum mshr_status status )
#endif
}
-void mshr_entry::print(FILE *fp, unsigned mask) const
+void mshr_entry::print(FILE *fp) const
{
- if ( mask & 0x100 ) {
- fprintf(fp, "MSHR(%u): w%2u req uid=%5u, %s (0x%llx) merged:%d status:%s ",
- m_id,
- m_warp_id,
- m_request_uid,
- (m_iswrite)? "store" : "load ",
- m_addr,
- (m_merged_requests != NULL || m_merged_on_other_reqest),
- MSHR_Status_str[m_status]);
- if ( m_mf )
- ptx_print_insn( m_mf->get_pc(), fp );
- fprintf(fp,"\n");
- }
+ fprintf(fp, "MSHR(%u): w%2u req uid=%5u, %s (0x%llx) merged:%d status:%s ",
+ m_id,
+ m_warp_id,
+ m_request_uid,
+ (m_iswrite)? "store" : "load ",
+ m_addr,
+ (m_merged_requests != NULL || m_merged_on_other_reqest),
+ MSHR_Status_str[m_status]);
+ if ( m_mf )
+ ptx_print_insn( m_mf->get_pc(), fp );
+ fprintf(fp,"\n");
}
-void opndcoll_rfu_t::init( unsigned num_collectors_alu,
- unsigned num_collectors_sfu,
- unsigned num_banks,
- shader_core_ctx *shader,
- warp_inst_t **alu_port,
- warp_inst_t **sfu_port )
+void opndcoll_rfu_t::add_port( unsigned num_collector_units,
+ warp_inst_t **input_port,
+ warp_inst_t **output_port )
+{
+ m_num_ports++;
+ m_num_collectors += num_collector_units;
+ m_input.resize(m_num_ports);
+ m_output.resize(m_num_ports);
+ m_num_collector_units.resize(m_num_ports);
+ m_input[m_num_ports-1]=input_port;
+ m_output[m_num_ports-1]=output_port;
+ m_num_collector_units[m_num_ports-1]=num_collector_units;
+}
+
+void opndcoll_rfu_t::init( unsigned num_banks, shader_core_ctx *shader )
{
- m_num_collectors = num_collectors_alu+num_collectors_sfu;
-
m_shader=shader;
m_arbiter.init(m_num_collectors,num_banks);
-
- m_alu_port = alu_port;
- m_sfu_port = sfu_port;
-
- m_dispatch_units[ m_alu_port ].init( num_collectors_alu );
- m_dispatch_units[ m_sfu_port ].init( num_collectors_sfu );
-
+ for( unsigned n=0; n<m_num_ports;n++ )
+ m_dispatch_units[m_output[n]].init( m_num_collector_units[n] );
m_num_banks = num_banks;
-
m_bank_warp_shift = 0;
m_warp_size = shader->get_config()->warp_size;
m_bank_warp_shift = (unsigned)(int) (log(m_warp_size+0.5) / log(2.0));
@@ -2102,15 +2148,12 @@ void opndcoll_rfu_t::init( unsigned num_collectors_alu,
m_cu = new collector_unit_t[m_num_collectors];
unsigned c=0;
- for(; c<num_collectors_alu; c++) {
- m_cu[c].init(c,m_alu_port,num_banks,m_bank_warp_shift,m_warp_size,this);
- m_free_cu[m_alu_port].push_back(&m_cu[c]);
- m_dispatch_units[m_alu_port].add_cu(&m_cu[c]);
- }
- for(; c<m_num_collectors; c++) {
- m_cu[c].init(c,m_sfu_port,num_banks,m_bank_warp_shift,m_warp_size,this);
- m_free_cu[m_sfu_port].push_back(&m_cu[c]);
- m_dispatch_units[m_sfu_port].add_cu(&m_cu[c]);
+ for( unsigned n=0; n<m_num_ports;n++ ) {
+ for( unsigned j=0; j<m_num_collector_units[n]; j++, c++) {
+ m_cu[c].init(c,m_output[n],num_banks,m_bank_warp_shift,shader->get_config(),this);
+ m_free_cu[m_output[n]].push_back(&m_cu[c]);
+ m_dispatch_units[m_output[n]].add_cu(&m_cu[c]);
+ }
}
}
@@ -2158,18 +2201,14 @@ void opndcoll_rfu_t::dispatch_ready_cu()
}
}
-void opndcoll_rfu_t::allocate_cu( warp_inst_t *&id_oc_reg )
+void opndcoll_rfu_t::allocate_cu( unsigned port_num )
{
- if( !id_oc_reg->empty() ) {
- warp_inst_t **port = NULL;
- if( id_oc_reg->op == SFU_OP )
- port = m_sfu_port;
- else
- port = m_alu_port;
+ if( !(*m_input[port_num])->empty() ) {
+ warp_inst_t **port = m_output[port_num];
if( !m_free_cu[port].empty() ) {
collector_unit_t *cu = m_free_cu[port].back();
m_free_cu[port].pop_back();
- cu->allocate(id_oc_reg);
+ cu->allocate(*m_input[port_num]);
m_arbiter.add_read_requests(cu);
}
}
@@ -2215,7 +2254,7 @@ void opndcoll_rfu_t::collector_unit_t::dump(FILE *fp, const shader_core_ctx *sha
if( m_free ) {
fprintf(fp," <free>\n");
} else {
- shader->print_warp(m_warp,fp,0,0);
+ m_warp->print(fp);
for( unsigned i=0; i < MAX_REG_OPERANDS; i++ ) {
if( m_not_ready.test(i) ) {
std::string r = m_src_op[i].get_reg_string();
@@ -2229,7 +2268,7 @@ void opndcoll_rfu_t::collector_unit_t::init( unsigned n,
warp_inst_t **port,
unsigned num_banks,
unsigned log2_warp_size,
- unsigned warp_size,
+ const shader_core_config *config,
opndcoll_rfu_t *rfu )
{
m_rfu=rfu;
@@ -2237,7 +2276,7 @@ void opndcoll_rfu_t::collector_unit_t::init( unsigned n,
m_port=port;
m_num_banks=num_banks;
assert(m_warp==NULL);
- m_warp = new warp_inst_t(warp_size);
+ m_warp = new warp_inst_t(config);
m_bank_warp_shift=log2_warp_size;
}
diff --git a/src/gpgpu-sim/shader.h b/src/gpgpu-sim/shader.h
index 8e98749..d6ef552 100644
--- a/src/gpgpu-sim/shader.h
+++ b/src/gpgpu-sim/shader.h
@@ -107,8 +107,6 @@
#define WRITE_MASK_SIZE 8
#define NO_PARTIAL_WRITE (partial_write_mask_t())
-#define WORD_SIZE 4
-
//Set a hard limit of 32 CTAs per shader [cuda only has 8]
#define MAX_CTA_PER_SHADER 32
@@ -319,6 +317,7 @@ public:
void init( new_addr_type address, bool wr, memory_space_t space, unsigned warp_id );
void clear() { m_insts.clear(); }
void set_mf( class mem_fetch *mf ) { m_mf=mf; }
+ class mem_fetch *get_mf() { return m_mf; }
void add_inst( warp_inst_t inst ) { m_insts.push_back(inst); }
void set_status( enum mshr_status status );
void merge( mshr_entry *mshr )
@@ -346,7 +345,7 @@ public:
{
done_insts.insert(done_insts.end(),m_insts.begin(),m_insts.end());
}
- void add_to_queue( std::deque<mshr_entry*> &q )
+ void add_to_queue( std::list<mshr_entry*> &q )
{
// place all merged requests in return queue
mshr_entry *req = this;
@@ -380,7 +379,7 @@ public:
return m_insts[0].isatomic();
}
new_addr_type get_addr() const { return m_addr; }
- void print(FILE *fp, unsigned mask) const;
+ void print(FILE *fp) const;
private:
unsigned m_id;
@@ -416,25 +415,22 @@ public:
m_num_banks=0;
m_cu = NULL;
m_shader=NULL;
- m_sfu_port=NULL;
- m_alu_port=NULL;
+ m_num_ports=0;
}
- void init( unsigned num_collectors_alu,
- unsigned num_collectors_sfu,
- unsigned num_banks,
- shader_core_ctx *shader,
- warp_inst_t **alu_port,
- warp_inst_t **sfu_port );
+ void add_port( unsigned num_collector_units,
+ warp_inst_t **input_port,
+ warp_inst_t **output_port );
+ void init( unsigned num_banks, shader_core_ctx *shader );
// modifiers
bool writeback( const warp_inst_t &warp ); // might cause stall
- void step( warp_inst_t *&alu_issue_port, warp_inst_t *&sfu_issue_port )
+ void step()
{
dispatch_ready_cu();
allocate_reads();
- allocate_cu(alu_issue_port);
- allocate_cu(sfu_issue_port);
+ for( unsigned p=0; p < m_num_ports; p++ )
+ allocate_cu( p );
process_banks();
}
@@ -459,7 +455,7 @@ private:
}
void dispatch_ready_cu();
- void allocate_cu( warp_inst_t *&id_oc_reg );
+ void allocate_cu( unsigned port );
void allocate_reads();
// types
@@ -671,7 +667,7 @@ private:
warp_inst_t **port,
unsigned num_banks,
unsigned log2_warp_size,
- unsigned warp_size,
+ const shader_core_config *config,
opndcoll_rfu_t *rfu );
void allocate( warp_inst_t *&pipeline_reg );
@@ -747,8 +743,11 @@ private:
collector_unit_t *m_cu;
arbiter_t m_arbiter;
+ unsigned m_num_ports;
+ std::vector<warp_inst_t**> m_input;
+ std::vector<warp_inst_t**> m_output;
+ std::vector<unsigned> m_num_collector_units;
warp_inst_t **m_alu_port;
- warp_inst_t **m_sfu_port;
typedef std::map<warp_inst_t**/*port*/,dispatch_unit_t> port_to_du_t;
port_to_du_t m_dispatch_units;
@@ -825,7 +824,7 @@ public:
mshr_entry* add_mshr(mem_access_t &access, warp_inst_t* inst);
void mshr_return_from_mem(mshr_entry *mshr);
unsigned get_max_mshr_used() const {return m_max_mshr_used;}
- void print(FILE* fp, class shader_core_ctx* shader,unsigned mask);
+ void print(FILE* fp);
private:
mshr_entry *alloc_free_mshr(bool istexture);
@@ -836,15 +835,15 @@ private:
return (not m_mshr_return_queue.empty()) or
((not m_texture_mshr_pipeline.empty()) and m_texture_mshr_pipeline.front()->fetched());
}
- std::deque<mshr_entry*> &choose_return_queue();
+ std::list<mshr_entry*> &choose_return_queue();
const struct shader_core_config *m_shader_config;
typedef std::vector<mshr_entry> mshr_storage_type;
mshr_storage_type m_mshrs;
- std::deque<mshr_entry*> m_free_list;
- std::deque<mshr_entry*> m_mshr_return_queue;
- std::deque<mshr_entry*> m_texture_mshr_pipeline;
+ std::list<mshr_entry*> m_free_list;
+ std::list<mshr_entry*> m_mshr_return_queue;
+ std::list<mshr_entry*> m_texture_mshr_pipeline;
unsigned m_max_mshr_used;
mshr_lookup m_mshr_lookup;
};
@@ -871,7 +870,196 @@ struct ifetch_buffer_t {
unsigned m_warp_id;
};
-typedef address_type (*tag_func_t)(address_type add, unsigned line_size);
+class simd_function_unit {
+public:
+ simd_function_unit( warp_inst_t **result_port, const shader_core_config *config )
+ {
+ m_result_port = result_port;
+ m_config=config;
+ m_dispatch_reg = new warp_inst_t(config);
+ }
+ ~simd_function_unit() { delete m_dispatch_reg; }
+
+ // modifiers
+ virtual void issue( warp_inst_t *&inst ) { move_warp(m_dispatch_reg,inst); }
+ virtual void cycle() = 0;
+
+ // accessors
+ virtual bool can_issue( const warp_inst_t & ) const { return m_dispatch_reg->empty(); }
+ virtual bool stallable() const = 0;
+ virtual void print( FILE *fp ) const
+ {
+ fprintf(fp,"%s dispatch= ", m_name.c_str() );
+ m_dispatch_reg->print(fp);
+ }
+protected:
+ std::string m_name;
+ const shader_core_config *m_config;
+ warp_inst_t **m_result_port;
+ warp_inst_t *m_dispatch_reg;
+};
+
+class alu : public simd_function_unit {
+public:
+ alu( warp_inst_t **result_port, const shader_core_config *config, unsigned max_latency )
+ : simd_function_unit(result_port,config)
+ {
+ m_result_port = result_port;
+ m_pipeline_depth = max_latency;
+ m_pipeline_reg = new warp_inst_t*[m_pipeline_depth];
+ for( unsigned i=0; i < m_pipeline_depth; i++ )
+ m_pipeline_reg[i] = new warp_inst_t( config );
+ }
+
+ //modifiers
+ virtual void cycle()
+ {
+ if( !m_pipeline_reg[0]->empty() )
+ move_warp(*m_result_port,m_pipeline_reg[0]); // non-stallable pipeline
+ for( unsigned stage=0; (stage+1)<m_pipeline_depth; stage++ )
+ move_warp(m_pipeline_reg[stage], m_pipeline_reg[stage+1]);
+ if( !m_dispatch_reg->empty() ) {
+ if( !m_dispatch_reg->dispatch_delay() ) {
+ int start_stage = m_dispatch_reg->latency - m_dispatch_reg->initiation_interval;
+ move_warp(m_pipeline_reg[start_stage],m_dispatch_reg);
+ }
+ }
+ }
+ virtual void issue( warp_inst_t *&inst )
+ {
+ move_warp(m_dispatch_reg,inst);
+ }
+
+ // accessors
+ virtual bool stallable() const { return false; }
+ virtual bool can_issue( const warp_inst_t &inst ) const
+ {
+ return simd_function_unit::can_issue(inst);
+ }
+ virtual void print(FILE *fp) const
+ {
+ simd_function_unit::print(fp);
+ for( int s=m_pipeline_depth-1; s>=0; s-- ) {
+ if( !m_pipeline_reg[s]->empty() ) {
+ fprintf(fp," %s[%2d] ", m_name.c_str(), s );
+ m_pipeline_reg[s]->print(fp);
+ }
+ }
+ }
+private:
+ unsigned m_pipeline_depth;
+ warp_inst_t **m_pipeline_reg;
+};
+
+class sfu : public alu
+{
+public:
+ sfu( warp_inst_t **result_port, const shader_core_config *config )
+ : alu(result_port,config,config->max_sfu_latency) { m_name = "SFU"; }
+ virtual bool can_issue( const warp_inst_t &inst ) const
+ {
+ switch(inst.op) {
+ case SFU_OP: break;
+ case ALU_SFU_OP: break;
+ default: return false;
+ }
+ return alu::can_issue(inst);
+ }
+};
+
+class sp_unit : public alu
+{
+public:
+ sp_unit( warp_inst_t **result_port, const shader_core_config *config )
+ : alu(result_port,config,config->max_sp_latency) { m_name = "SP "; }
+ virtual bool can_issue( const warp_inst_t &inst ) const
+ {
+ switch(inst.op) {
+ case SFU_OP: return false;
+ case LOAD_OP: return false;
+ case STORE_OP: return false;
+ case MEMORY_BARRIER_OP: return false;
+ default: break;
+ }
+ return alu::can_issue(inst);
+ }
+};
+
+class ldst_unit : public simd_function_unit {
+public:
+ ldst_unit( gpgpu_sim *gpu,
+ shader_core_ctx *core,
+ warp_inst_t **result_port,
+ shader_core_config *config,
+ shader_core_stats *stats,
+ unsigned sid, unsigned tpc );
+
+ // modifiers
+ virtual void cycle();
+ void fill( mem_fetch *mf );
+ void flush();
+
+ // accessors
+ virtual bool can_issue( const warp_inst_t &inst ) const
+ {
+ switch(inst.op) {
+ case LOAD_OP: break;
+ case STORE_OP: break;
+ case MEMORY_BARRIER_OP: break;
+ default: return false;
+ }
+ return simd_function_unit::can_issue(inst);
+ }
+ virtual bool stallable() const { return true; }
+ void print(FILE *fout) const;
+
+private:
+ void generate_mem_accesses(warp_inst_t &pipe_reg);
+ void tex_cache_access(warp_inst_t &inst);
+ void const_cache_access(warp_inst_t &inst);
+
+ bool shared_cycle( warp_inst_t &inst, mem_stage_stall_type &rc_fail, mem_stage_access_type &fail_type);
+ bool constant_cycle( warp_inst_t &inst, mem_stage_stall_type &rc_fail, mem_stage_access_type &fail_type);
+ bool texture_cycle( warp_inst_t &inst, mem_stage_stall_type &rc_fail, mem_stage_access_type &fail_type);
+ bool memory_cycle( warp_inst_t &inst, mem_stage_stall_type &rc_fail, mem_stage_access_type &fail_type);
+
+ mem_stage_stall_type ccache_check(warp_inst_t &inst, mem_access_t& access){ return NO_RC_FAIL;}
+ mem_stage_stall_type tcache_check(warp_inst_t &inst, mem_access_t& access){ return NO_RC_FAIL;}
+ mem_stage_stall_type dcache_check(warp_inst_t &inst, mem_access_t& access);
+
+ typedef mem_stage_stall_type (ldst_unit::*cache_check_t)(warp_inst_t &,mem_access_t&);
+
+ mem_stage_stall_type process_memory_access_queue( ldst_unit::cache_check_t cache_check,
+ unsigned ports_per_bank,
+ unsigned memory_send_max,
+ warp_inst_t &inst );
+ mem_stage_stall_type send_mem_request(warp_inst_t &inst, mem_access_t &access);
+
+ gpgpu_sim *m_gpu;
+ shader_core_ctx *m_core;
+ unsigned m_sid;
+ unsigned m_tpc;
+
+ cache_t *m_L1D; // data cache (global/local memory accesses)
+ cache_t *m_L1T; // texture cache
+ cache_t *m_L1C; // constant cache
+ mshr_shader_unit *m_mshr_unit;
+
+ enum mem_stage_stall_type m_mem_rc;
+
+ shader_core_stats *m_stats;
+};
+
+enum pipeline_stage_name_t {
+ ID_OC_SP=0,
+ ID_OC_SFU,
+ ID_OC_MEM,
+ OC_EX_SP,
+ OC_EX_SFU,
+ OC_EX_MEM,
+ EX_WB,
+ N_PIPELINE_STAGES
+};
class shader_core_ctx : public core_t
{
@@ -880,12 +1068,11 @@ public:
const char *name,
unsigned shader_id,
unsigned tpc_id,
- const struct shader_core_config *config,
+ struct shader_core_config *config,
struct shader_core_stats *stats );
void issue_block2core( class kernel_info_t &kernel );
void get_pdom_stack_top_info( unsigned tid, unsigned *pc, unsigned *rpc );
- void new_cache_window();
bool ptx_thread_done( unsigned hw_thread_id ) const;
class ptx_thread_info *get_thread_state( unsigned hw_thread_id );
@@ -900,7 +1087,7 @@ public:
void deallocate_barrier( unsigned cta_id );
void decrement_atomic_count( unsigned wid );
- void cycle_gt200();
+ void cycle();
void reinit(unsigned start_thread, unsigned end_thread, bool reset_not_completed );
void init_warps(unsigned cta_id, unsigned start_thread, unsigned end_thread);
@@ -913,10 +1100,8 @@ public:
void fill_shd_L1_with_new_line( class mem_fetch * mf );
void store_ack( class mem_fetch *mf );
void dump_istream_state( FILE *fout );
- void mshr_print(FILE* fp, unsigned mask);
unsigned first_valid_thread( unsigned stage );
class ptx_thread_info* get_functional_thread( unsigned tid ) { return m_thread[tid].m_functional_model_thread_state; }
- void print_warp( warp_inst_t *warp, FILE *fout, int print_mem, int mask ) const;
std::list<unsigned> get_regs_written( const inst_t &fvt ) const;
const shader_core_config *get_config() const { return m_config; }
unsigned get_num_sim_insn() const { return m_num_sim_insn; }
@@ -927,14 +1112,8 @@ public:
unsigned get_thread_n_l1_mis_ac( unsigned tid ) const { return m_thread[tid].n_l1_mis_ac; }
unsigned get_thread_n_l1_mrghit_ac( unsigned tid ) const { return m_thread[tid].n_l1_mrghit_ac; }
unsigned get_thread_n_l1_access_ac( unsigned tid ) const { return m_thread[tid].n_l1_access_ac; }
- unsigned get_max_mshr_used() const { return m_mshr_unit->get_max_mshr_used(); }
- void L1cache_print( FILE *fp, unsigned &total_accesses, unsigned &total_misses) const;
- void L1texcache_print( FILE *fp, unsigned &total_accesses, unsigned &total_misses) const;
- void L1constcache_print( FILE *fp, unsigned &total_accesses, unsigned &total_misses) const;
unsigned get_n_active_cta() const { return m_n_active_cta; }
- float L1_windowed_cache_miss_rate( int x ) const { return m_L1D->shd_cache_windowed_cache_miss_rate(x); }
- float L1tex_windowed_cache_miss_rate( int x ) const { return m_L1T->shd_cache_windowed_cache_miss_rate(x); }
- float L1const_windowed_cache_miss_rate( int x ) const { return m_L1C->shd_cache_windowed_cache_miss_rate(x); }
+ void inc_store_req( unsigned warp_id) { m_warp[warp_id].inc_store_req(); }
private:
@@ -942,64 +1121,20 @@ private:
address_type next_pc( int tid ) const;
- void func_exec_inst( warp_inst_t &inst );
- void fetch_new();
+ void fetch();
+
+ void decode();
void issue_warp( warp_inst_t *&warp, const warp_inst_t *pI, unsigned active_mask, unsigned warp_id );
- void decode_new();
+ void func_exec_inst( warp_inst_t &inst );
+ address_type translate_local_memaddr(address_type localaddr, unsigned tid, unsigned num_shader );
void execute();
- void execute_pipe( unsigned pipeline, unsigned next_stage );
-
- void memory(); // advance memory pipeline stage
- void memory_queue(warp_inst_t &pipe_reg);
- void memory_shared_process_warp(warp_inst_t &inst);
- void memory_const_process_warp(warp_inst_t &inst);
- void memory_texture_process_warp(warp_inst_t &inst);
- void memory_global_process_warp(warp_inst_t &inst);
- bool memory_shared_cycle( warp_inst_t &inst, mem_stage_stall_type &rc_fail, mem_stage_access_type &fail_type);
- bool memory_constant_cycle( warp_inst_t &inst, mem_stage_stall_type &rc_fail, mem_stage_access_type &fail_type);
- bool memory_texture_cycle( warp_inst_t &inst, mem_stage_stall_type &rc_fail, mem_stage_access_type &fail_type);
- bool memory_cycle( warp_inst_t &inst, mem_stage_stall_type &rc_fail, mem_stage_access_type &fail_type);
- address_type translate_local_memaddr(address_type localaddr, int tid, unsigned num_shader );
-
- mem_stage_stall_type ccache_check(warp_inst_t &inst, mem_access_t& access){ return NO_RC_FAIL;}
- mem_stage_stall_type tcache_check(warp_inst_t &inst, mem_access_t& access){ return NO_RC_FAIL;}
- mem_stage_stall_type dcache_check(warp_inst_t &inst, mem_access_t& access);
-
- typedef mem_stage_stall_type (shader_core_ctx::*cache_check_t)(warp_inst_t &,mem_access_t&);
-
- mem_stage_stall_type process_memory_access_queue( shader_core_ctx::cache_check_t cache_check,
- unsigned ports_per_bank,
- unsigned memory_send_max,
- warp_inst_t &inst );
-
- typedef int (shader_core_ctx::*bank_func_t)(address_type add, unsigned line_size);
-
- int null_bank_func(address_type add, unsigned line_size);
- int shmem_bank_func(address_type add, unsigned line_size);
- int dcache_bank_func(address_type add, unsigned line_size);
-
- void get_memory_access_list( bank_func_t bank_func,
- tag_func_t tag_func,
- unsigned warp_parts,
- unsigned line_size,
- bool limit_broadcast,
- warp_inst_t &inst );
- mem_stage_stall_type send_mem_request(warp_inst_t &inst, mem_access_t &access);
void writeback();
- unsigned char fq_push( unsigned long long int addr,
- int bsize,
- unsigned char write,
- partial_write_mask_t partial_write_mask,
- int wid, mshr_entry* mshr,
- enum mem_access_type mem_acc,
- address_type pc );
-
void call_thread_done(inst_t &done_inst );
- void print_stage(unsigned int stage, FILE *fout, int print_mem, int mask );
+ void print_stage(unsigned int stage, FILE *fout) const;
// general information
unsigned m_sid; // shader id
@@ -1020,37 +1155,29 @@ private:
// thread contexts
thread_ctx_t *m_thread; // functional state, per thread fetch state
+
+ // fetch
+ cache_t *m_L1I; // instruction cache
+ int m_last_warp_fetched;
+
+ // decode/dispatch
+ int m_last_warp_issued;
std::vector<shd_warp_t> m_warp; // per warp information array
barrier_set_t m_barriers;
ifetch_buffer_t m_inst_fetch_buffer;
pdom_warp_ctx_t **m_pdom_warp; // pdom reconvergence context for each warp
-
warp_inst_t** m_pipeline_reg;
Scoreboard *m_scoreboard;
opndcoll_rfu_t m_operand_collector;
- mshr_shader_unit *m_mshr_unit;
- // fetch
- int m_last_warp_fetched;
- int m_last_warp_issued;
-
- cache_t *m_L1I; // instruction cache
- cache_t *m_L1D; // data cache (global/local memory accesses)
- cache_t *m_L1T; // texture cache
- cache_t *m_L1C; // constant cache
-
- enum mem_stage_stall_type m_mem_rc;
-};
-
-enum pipeline_stage_name_t {
- ID_OC_SP=0,
- ID_OC_SFU,
- OC_EX_SP,
- OC_EX_SFU,
- EX_MM,
- MM_WB,
- WB_RT,
- N_PIPELINE_STAGES
+ // execute
+ unsigned m_num_function_units;
+ enum pipeline_stage_name_t *m_dispatch_port;
+ enum pipeline_stage_name_t *m_issue_port;
+ simd_function_unit **m_fu; // stallable pipelines should be last in this array
+ ldst_unit *m_ldst_unit;
+ static const unsigned MAX_ALU_LATENCY = 64;
+ std::bitset<MAX_ALU_LATENCY> m_result_bus;
};
#endif /* SHADER_H */
diff --git a/src/gpgpu-sim/stats.h b/src/gpgpu-sim/stats.h
index 76e6699..2c494eb 100644
--- a/src/gpgpu-sim/stats.h
+++ b/src/gpgpu-sim/stats.h
@@ -133,6 +133,9 @@ struct shader_core_stats
int n_pdom_sc_orig_stat;
int n_pdom_sc_single_stat;
+
+ unsigned made_write_mfs;
+ unsigned made_read_mfs;
};
#endif
diff --git a/src/gpgpu-sim/visualizer.cc b/src/gpgpu-sim/visualizer.cc
index fd0a422..4474dcd 100644
--- a/src/gpgpu-sim/visualizer.cc
+++ b/src/gpgpu-sim/visualizer.cc
@@ -142,6 +142,7 @@ void gpgpu_sim::visualizer_printstat()
shader_CTA_count_visualizer_gzprint(visualizer_file);
// per shader core cache miss rate
+/*
gzprintf(visualizer_file, "CacheMissRate_GlobalLocalL1_All: ");
for (unsigned i=0;i<m_n_shader;i++)
gzprintf(visualizer_file, "%0.4f ", m_sc[i]->L1_windowed_cache_miss_rate(0));
@@ -166,10 +167,10 @@ void gpgpu_sim::visualizer_printstat()
for (unsigned i=0;i<m_n_shader;i++)
gzprintf(visualizer_file, "%0.4f ", m_sc[i]->L1const_windowed_cache_miss_rate(1));
gzprintf(visualizer_file, "\n");
-
// reset for next interval
for (unsigned i=0;i<m_n_shader;i++)
m_sc[i]->new_cache_window();
+*/
for (unsigned i=0;i<m_n_mem;i++)
m_memory_partition_unit[i]->visualizer_print(visualizer_file);