summaryrefslogtreecommitdiff
path: root/src/gpgpu-sim/shader.cc
diff options
context:
space:
mode:
authorTor Aamodt <[email protected]>2010-10-16 17:30:52 -0800
committerTor Aamodt <[email protected]>2010-10-16 17:30:52 -0800
commitb577cbcdf229a2c02d1bf8584c6e82be7a14cb33 (patch)
tree373ea8ec8ea8d7d9a7a1df0eaa17f15652df1306 /src/gpgpu-sim/shader.cc
parent2072e7ff2037c19a0c346e60469949c9437569bf (diff)
1. creating cache_config object to encapsulate cache configuration information
(and parse it before creating the simulator objects). 2. creating core_config to hold only features of a shader_core that are high level enough either (a) the functional simulator needs to know about them, or (b) they affect memory *access* generation. 3. in config files only (so far) separate out notion of write-{through,back}, from notion of when a line is allocated... will use this to distinguish different types of caches. passing CUDA 3.1 regression [git-p4: depot-paths = "//depot/gpgpu_sim_research/fermi/distribution/": change = 7870]
Diffstat (limited to 'src/gpgpu-sim/shader.cc')
-rw-r--r--src/gpgpu-sim/shader.cc236
1 files changed, 42 insertions, 194 deletions
diff --git a/src/gpgpu-sim/shader.cc b/src/gpgpu-sim/shader.cc
index a316fbb..2c5de09 100644
--- a/src/gpgpu-sim/shader.cc
+++ b/src/gpgpu-sim/shader.cc
@@ -293,7 +293,7 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu,
class simt_core_cluster *cluster,
unsigned shader_id,
unsigned tpc_id,
- struct shader_core_config *config,
+ const struct shader_core_config *config,
const struct memory_config *mem_config,
struct shader_core_stats *stats )
: m_barriers( config->max_warps_per_shader, config->max_cta_per_core )
@@ -304,8 +304,6 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu,
m_memory_config = mem_config;
m_stats = stats;
unsigned warp_size=config->warp_size;
- config->max_sfu_latency = 32;
- config->max_sp_latency = 32;
m_sid = shader_id;
m_tpc = tpc_id;
@@ -332,7 +330,7 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu,
#define STRSIZE 1024
char L1I_name[STRSIZE];
snprintf(L1I_name, STRSIZE, "L1I_%03d", m_sid);
- m_L1I = new cache_t(L1I_name,m_config->gpgpu_cache_il1_opt,no_writes,m_sid,get_shader_instruction_cache_id());
+ m_L1I = new cache_t(L1I_name,m_config->m_L1I_config,m_sid,get_shader_instruction_cache_id());
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];
@@ -611,9 +609,9 @@ void shader_core_ctx::fetch()
address_type ppc = pc + PROGRAM_MEM_START;
address_type wb=0;
unsigned nbytes=16;
- unsigned offset_in_block = pc & (m_L1I->get_line_sz()-1);
- if( (offset_in_block+nbytes) > m_L1I->get_line_sz() )
- nbytes = (m_L1I->get_line_sz()-offset_in_block);
+ unsigned offset_in_block = pc & (m_config->m_L1I_config.get_line_sz()-1);
+ if( (offset_in_block+nbytes) > m_config->m_L1I_config.get_line_sz() )
+ nbytes = (m_config->m_L1I_config.get_line_sz()-offset_in_block);
enum cache_request_status status = m_L1I->access( (unsigned long long)pc, 0, gpu_sim_cycle, &wb );
if( status != HIT ) {
unsigned req_size = READ_PACKET_SIZE;
@@ -813,182 +811,6 @@ mshr_entry* mshr_shader_unit::add_mshr(mem_access_t &access, warp_inst_t* pinst)
return mshr;
}
-address_type line_size_based_tag_func(address_type address, unsigned line_size)
-{
- //gives the tag for an address based on a given line size
- return ((address) & (~((address_type)line_size - 1)));
-}
-
-address_type null_tag_func(address_type address, unsigned line_size)
-{
- return address; //no modification: each address is its own tag.
-}
-
-unsigned shader_core_config::shmem_bank_func(address_type addr, unsigned) const
-{
- return ((addr/WORD_SIZE) % gpgpu_n_shmem_bank);
-}
-
-unsigned shader_core_config::dcache_bank_func(address_type add, unsigned line_size) const
-{
- if (gpgpu_no_dl1) return 1; //no banks
- else return (add / line_size) & (gpgpu_n_cache_bank - 1);
-}
-
-void warp_inst_t::get_memory_access_list()
-{
- // Calculates memory accesses generated by this warp
- // Returns acesses which are "coalesced"
- // Does not coalesce nor overlap bank accesses across warp "parts".
-
- // This is called once per warp_inst_t when the warp_inst_t enters the memory stage.
- // 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.
- // Later, when the queue is processed it will evaluate accesses of as many orders as
- // ports on that cache/shmem.
- //
- // 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
- // its number of ports in one cycle.
- std::map<unsigned,unsigned> bank_accs;
-
- // keep track of broadcasts with unique orders if limit_broadcast
- // the normally calculated orders will never be greater than warp_size
- unsigned broadcast_order = warp_size();
- unsigned qbegin = get_accessq_size();
- unsigned qpartbegin = qbegin;
- 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 ( !active(i) )
- continue;
- 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( !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.
- 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( space != undefined_space );
- m_accessq.push_back( mem_access_t( lane_segment_address, line_size, quarter, i) );
- // Determine Bank Conflicts:
- 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;
- accessq_back().order = bank_accs[bank];
- bank_accs[bank]++;
- }
- }
- qpartbegin = get_accessq_size(); //don't coalesce accross warp parts
- }
- //sort requests by order they will be processed in
- std::stable_sort( m_accessq.begin()+qbegin,m_accessq.end());
-
- 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 ldst_unit::const_cache_access(warp_inst_t &inst)
{
// do cache checks here for each request (non-physical), could be
@@ -1400,11 +1222,41 @@ void ldst_unit::generate_mem_accesses(warp_inst_t &inst)
inst.set_mem_accesses_created();
}
+
+simd_function_unit::simd_function_unit( const shader_core_config *config )
+{
+ m_config=config;
+ m_dispatch_reg = new warp_inst_t(config);
+}
+
+sfu::sfu( warp_inst_t **result_port, const shader_core_config *config )
+ : pipelined_simd_unit(result_port,config,config->max_sfu_latency)
+{
+ m_name = "SFU";
+}
+
+sp_unit::sp_unit( warp_inst_t **result_port, const shader_core_config *config )
+ : pipelined_simd_unit(result_port,config,config->max_sp_latency)
+{
+ m_name = "SP ";
+}
+
+
+pipelined_simd_unit::pipelined_simd_unit( warp_inst_t **result_port, const shader_core_config *config, unsigned max_latency )
+ : simd_function_unit(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 );
+}
+
ldst_unit::ldst_unit( simt_core_cluster *cluster,
shader_core_ctx *core,
opndcoll_rfu_t *operand_collector,
Scoreboard *scoreboard,
- shader_core_config *config,
+ const shader_core_config *config,
const memory_config *mem_config,
shader_core_stats *stats,
unsigned sid,
@@ -1425,14 +1277,10 @@ ldst_unit::ldst_unit( simt_core_cluster *cluster,
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,L1D_policy,m_sid,get_shader_normal_cache_id());
- m_L1T = new cache_t(L1T_name,m_config->gpgpu_cache_texl1_opt,no_writes, m_sid,get_shader_texture_cache_id());
- m_L1C = new cache_t(L1C_name,m_config->gpgpu_cache_constl1_opt,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_cluster->get_gpu()->ptx_set_tex_cache_linesize(m_L1T->get_line_sz());
+ m_L1D = new cache_t(L1D_name,m_config->m_L1D_config,m_sid,get_shader_normal_cache_id());
+ m_L1T = new cache_t(L1T_name,m_config->m_L1T_config,m_sid,get_shader_texture_cache_id());
+ m_L1C = new cache_t(L1C_name,m_config->m_L1C_config,m_sid,get_shader_constant_cache_id());
+ m_cluster->get_gpu()->ptx_set_tex_cache_linesize(m_config->m_L1T_config.get_line_sz());
m_mshr_unit = new mshr_shader_unit(m_config);
m_mem_rc = NO_RC_FAIL;
}
@@ -2401,7 +2249,7 @@ void opndcoll_rfu_t::collector_unit_t::init( unsigned n,
warp_inst_t **port,
unsigned num_banks,
unsigned log2_warp_size,
- const shader_core_config *config,
+ const core_config *config,
opndcoll_rfu_t *rfu )
{
m_rfu=rfu;
@@ -2456,7 +2304,7 @@ class ptx_thread_info *shader_core_ctx::get_thread_state( unsigned hw_thread_id
simt_core_cluster::simt_core_cluster( class gpgpu_sim *gpu,
unsigned cluster_id,
- struct shader_core_config *config,
+ const struct shader_core_config *config,
const struct memory_config *mem_config,
struct shader_core_stats *stats )
{