summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configs/QuadroFX5800/gpgpusim.config2
-rw-r--r--src/abstract_hardware_model.cc368
-rw-r--r--src/abstract_hardware_model.h177
-rw-r--r--src/gpgpu-sim/gpu-sim.cc6
-rw-r--r--src/gpgpu-sim/mem_fetch.cc42
-rw-r--r--src/gpgpu-sim/mem_fetch.h59
-rw-r--r--src/gpgpu-sim/mem_latency_stat.cc2
-rw-r--r--src/gpgpu-sim/shader.cc213
-rw-r--r--src/gpgpu-sim/shader.h5
-rw-r--r--src/gpgpu-sim/visualizer.cc4
10 files changed, 439 insertions, 439 deletions
diff --git a/configs/QuadroFX5800/gpgpusim.config b/configs/QuadroFX5800/gpgpusim.config
index 6f1c936..3d7d218 100644
--- a/configs/QuadroFX5800/gpgpusim.config
+++ b/configs/QuadroFX5800/gpgpusim.config
@@ -22,7 +22,7 @@
-gpgpu_const_cache:l1 64:64:2:L:R:f,A:2:32,4
-gpgpu_cache:dl2 64:32:8:L:R:m,A:16:4,4
--gpgpu_shmem_pipe_speedup 2
+-gpgpu_shmem_warp_parts 2
-gpgpu_shmem_port_per_bank 2
# interconnection
diff --git a/src/abstract_hardware_model.cc b/src/abstract_hardware_model.cc
index 507e02f..ad5c983 100644
--- a/src/abstract_hardware_model.cc
+++ b/src/abstract_hardware_model.cc
@@ -2,7 +2,7 @@
#include "cuda-sim/memory.h"
#include <algorithm>
-unsigned mem_access_t::next_access_uid = 0;
+unsigned mem_access_t::sm_next_access_uid = 0;
unsigned warp_inst_t::sm_next_uid = 0;
void move_warp( warp_inst_t *&dst, warp_inst_t *&src )
@@ -24,173 +24,241 @@ gpgpu_t::gpgpu_t()
m_dev_malloc=GLOBAL_HEAP_START;
}
-unsigned core_config::shmem_bank_func(address_type addr, unsigned) const
-{
- return ((addr/WORD_SIZE) % gpgpu_n_shmem_bank);
-}
-
-address_type null_tag_func(address_type address, unsigned line_size)
-{
- return address; //no modification: each address is its own tag.
-}
-
-address_type line_size_based_tag_func(address_type address, unsigned line_size)
+address_type line_size_based_tag_func(new_addr_type address, new_addr_type line_size)
{
//gives the tag for an address based on a given line size
- return ((address) & (~((address_type)line_size - 1)));
+ return address & ~(line_size-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".
+struct transaction_info {
+ std::bitset<4> chunks; // bitmask: 32-byte chunks accessed
+ mem_access_byte_mask_t bytes;
+ active_mask_t active; // threads in this transaction
+};
- // 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.
+void warp_inst_t::generate_mem_accesses()
+{
+ if( empty() || op == MEMORY_BARRIER_OP || m_mem_accesses_created )
+ return;
+ if ( !( (op == LOAD_OP) || (op == STORE_OP) || (op == MEMORY_BARRIER_OP) ) )
+ return;
- // 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.
+ assert( is_load() || is_store() );
+ assert( m_per_scalar_thread_valid ); // need address information per thread
- typedef unsigned (core_config::*bank_func_t)(address_type add, unsigned line_size) const;
- typedef address_type (*tag_func_t)(address_type add, unsigned line_size);
- 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;
+ bool is_write = is_store();
- switch( space.get_type() ) {
- case shared_space:
- bank_func = &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.
+ mem_access_type access_type;
+ switch (space.get_type()) {
+ case const_space:
+ case param_space_kernel:
+ access_type = CONST_ACC_R;
break;
case tex_space:
- bank_func = &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;
+ access_type = TEXTURE_ACC_R;
break;
- case const_space: case param_space_kernel:
- bank_func = &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;
+ case global_space:
+ access_type = is_write? GLOBAL_ACC_W: GLOBAL_ACC_R;
break;
- case global_space: case local_space: case param_space_local:
- global_mem_access=true;
- warp_parts = 1;
- line_size = 0;
- if( m_config->gpgpu_coalesce_arch == 13 ){
- warp_parts = 2;
- // 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);
- }
- } else abort();
- bank_func = &core_config::null_bank_func;
- tag_func = line_size_based_tag_func;
- limit_broadcast = false;
+ case local_space:
+ case param_space_local:
+ access_type = is_write? LOCAL_ACC_W: LOCAL_ACC_R;
break;
- default:
- abort();
+ case shared_space: break;
+ default: assert(0); break;
}
- // 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;
+ // Calculate memory accesses generated by this warp
+ new_addr_type cache_block_size = 32; // in bytes
+
+ switch( space.get_type() ) {
+ case shared_space: {
+ unsigned subwarp_size = m_config->warp_size / m_config->shmem_warp_parts;
+ unsigned total_accesses=0;
+ for( unsigned subwarp=0; subwarp < m_config->shmem_warp_parts; subwarp++ ) {
+
+ // data structures used per part warp
+ std::map<unsigned,std::map<new_addr_type,unsigned> > bank_accs; // bank -> word address -> access count
- // 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;
- }
+ // step 1: compute accesses to words in banks
+ for( unsigned thread=subwarp*subwarp_size; thread < (subwarp+1)*subwarp_size; thread++ ) {
+ if( !active(thread) )
+ continue;
+ new_addr_type addr = m_per_scalar_thread[thread].memreqaddr;
+ unsigned bank = m_config->shmem_bank_func(addr);
+ new_addr_type word = line_size_based_tag_func(addr,m_config->WORD_SIZE);
+ bank_accs[bank][word]++;
}
- }
- 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) {
- // 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];
+ // step 2: look for and select a broadcast bank/word if one occurs
+ bool broadcast_detected = false;
+ new_addr_type broadcast_word=(new_addr_type)-1;
+ unsigned broadcast_bank=(unsigned)-1;
+ std::map<unsigned,std::map<new_addr_type,unsigned> >::iterator b;
+ for( b=bank_accs.begin(); b != bank_accs.end(); b++ ) {
+ unsigned bank = b->first;
+ std::map<new_addr_type,unsigned> &access_set = b->second;
+ std::map<new_addr_type,unsigned>::iterator w;
+ for( w=access_set.begin(); w != access_set.end(); ++w ) {
+ if( w->second > 1 ) {
+ // found a broadcast
+ broadcast_detected=true;
+ broadcast_bank=bank;
+ broadcast_word=w->first;
+ break;
+ }
}
- }
- if (accessq(i).req_size == 64) {
- if (low xor high) { //can reduce size
- accessq(i).req_size = 32;
- if (high) accessq(i).addr += 32;
+ if( broadcast_detected )
+ break;
+ }
+
+ // step 3: figure out max bank accesses performed, taking account of broadcast case
+ unsigned max_bank_accesses=0;
+ for( b=bank_accs.begin(); b != bank_accs.end(); b++ ) {
+ unsigned bank_accesses=0;
+ std::map<new_addr_type,unsigned> &access_set = b->second;
+ std::map<new_addr_type,unsigned>::iterator w;
+ for( w=access_set.begin(); w != access_set.end(); ++w )
+ bank_accesses += w->second;
+ if( broadcast_detected && broadcast_bank == b->first ) {
+ for( w=access_set.begin(); w != access_set.end(); ++w ) {
+ if( w->first == broadcast_word ) {
+ unsigned n = w->second;
+ assert(n > 1); // or this wasn't a broadcast
+ assert(bank_accesses >= (n-1));
+ bank_accesses -= (n-1);
+ break;
+ }
+ }
}
- }
- }
- }
- }
-}
+ if( bank_accesses > max_bank_accesses )
+ max_bank_accesses = bank_accesses;
+ }
+
+ // step 4: accumulate
+ total_accesses+= max_bank_accesses;
+ }
+ assert( total_accesses > 0 && total_accesses <= m_config->warp_size );
+ cycles = total_accesses; // shared memory conflicts modeled as larger initiation interval
+ break;
+ }
+ case tex_space:
+ cache_block_size = m_config->gpgpu_cache_texl1_linesize;
+
+ case const_space: case param_space_kernel:
+ cache_block_size = m_config->gpgpu_cache_constl1_linesize; {
+ mem_access_byte_mask_t byte_mask;
+ std::map<new_addr_type,active_mask_t> accesses; // block address -> set of thread offsets in warp
+ std::map<new_addr_type,active_mask_t>::iterator a;
+ for( unsigned thread=0; thread < m_config->warp_size; thread++ ) {
+ if( !active(thread) )
+ continue;
+ new_addr_type addr = m_per_scalar_thread[thread].memreqaddr;
+ unsigned block_address = line_size_based_tag_func(addr,m_config->gpgpu_cache_texl1_linesize);
+ accesses[block_address].set(thread);
+ unsigned idx = addr-block_address;
+ for( unsigned i=0; i < data_size; i++ )
+ byte_mask.set(idx+i);
+ }
+ for( a=accesses.begin(); a != accesses.end(); ++a )
+ m_accessq.push_back( mem_access_t(access_type,a->first,cache_block_size,is_write,a->second,byte_mask) );
+ }
+ break;
+
+ case global_space: case local_space: case param_space_local:
+
+ if( m_config->gpgpu_coalesce_arch == 13 ) {
+ // see the CUDA manual where it discusses coalescing rules before reading this
+ unsigned segment_size = 0;
+ unsigned warp_parts = 2;
+ switch( data_size ) {
+ case 1: segment_size = 32; break;
+ case 2: segment_size = 64; break;
+ case 4: case 8: case 16: segment_size = 128; break;
+ }
+ unsigned subwarp_size = m_config->warp_size / warp_parts;
+
+ for( unsigned subwarp=0; subwarp < warp_parts; subwarp++ ) {
+ std::map<new_addr_type,transaction_info> subwarp_transactions;
+
+ // step 1: find all transactions generated by this subwarp
+ for( unsigned thread=subwarp*subwarp_size; thread<subwarp_size*(subwarp+1); thread++ ) {
+ if( !active(thread) )
+ continue;
+ new_addr_type addr = m_per_scalar_thread[thread].memreqaddr;
+ unsigned block_address = line_size_based_tag_func(addr,segment_size);
+ unsigned chunk = (addr&127)/32; // which 32-byte chunk within in a 128-byte chunk does this thread access?
+ transaction_info &info = subwarp_transactions[block_address];
+ info.chunks.set(chunk);
+ info.active.set(thread);
+ unsigned idx = (addr&127);
+ for( unsigned i=0; i < data_size; i++ )
+ info.bytes.set(idx+i);
+ }
+
+ // step 2: reduce each transaction size, if possible
+ std::map< new_addr_type, transaction_info >::iterator t;
+ for( t=subwarp_transactions.begin(); t !=subwarp_transactions.end(); t++ ) {
+ new_addr_type addr = t->first;
+ assert( (addr & (segment_size-1)) == 0 );
+ const transaction_info &info = t->second;
+ const std::bitset<4> &q = info.chunks;
+ assert( q.count() >= 1 );
+ std::bitset<2> h; // halves (used to check if 64 byte segment can be compressed into a single 32 byte segment)
+
+ unsigned size=segment_size;
+ if( segment_size == 128 ) {
+ bool lower_half_used = q[0] || q[1];
+ bool upper_half_used = q[2] || q[3];
+ if( lower_half_used && !upper_half_used ) {
+ // only lower 64 bytes used
+ size = 64;
+ if(q[0]) h.set(0);
+ if(q[1]) h.set(1);
+ } else if ( (!lower_half_used) && upper_half_used ) {
+ // only upper 64 bytes used
+ addr = addr+64;
+ size = 64;
+ if(q[2]) h.set(0);
+ if(q[3]) h.set(1);
+ } else {
+ assert(lower_half_used && upper_half_used);
+ }
+ } else if( segment_size == 64 ) {
+ // need to set halves
+ if( (addr % 128) == 0 ) {
+ if(q[0]) h.set(0);
+ if(q[1]) h.set(1);
+ } else {
+ assert( (addr % 128) == 64 );
+ if(q[2]) h.set(0);
+ if(q[3]) h.set(1);
+ }
+ }
+ if( size == 64 ) {
+ bool lower_half_used = h[0];
+ bool upper_half_used = h[1];
+ if( lower_half_used && !upper_half_used ) {
+ size = 32;
+ } else if ( (!lower_half_used) && upper_half_used ) {
+ addr = addr+32;
+ size = 32;
+ } else {
+ assert(lower_half_used && upper_half_used);
+ }
+ }
+ m_accessq.push_back( mem_access_t(access_type,addr,size,is_write,info.active,info.bytes) );
+ }
+ }
+
+ } else abort();
+
+ break;
+
+ default:
+ abort();
+ }
+
+ m_mem_accesses_created=true;
+}
diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h
index fc2f0d4..804cf23 100644
--- a/src/abstract_hardware_model.h
+++ b/src/abstract_hardware_model.h
@@ -160,16 +160,21 @@ struct core_config {
bool m_valid;
unsigned warp_size;
- // memory request architecture parameters
+ // off-chip memory request architecture parameters
int gpgpu_coalesce_arch;
- int gpgpu_shmem_pipe_speedup;
- unsigned gpgpu_cache_texl1_linesize;
- unsigned gpgpu_cache_constl1_linesize;
+ // shared memory bank conflict checking parameters
static const address_type WORD_SIZE=4;
- unsigned null_bank_func(address_type, unsigned) const { return 1; }
- int gpgpu_n_shmem_bank;
- unsigned shmem_bank_func(address_type addr, unsigned) const;
+ int num_shmem_bank;
+ unsigned shmem_bank_func(address_type addr) const
+ {
+ return ((addr/WORD_SIZE) % num_shmem_bank);
+ }
+ unsigned shmem_warp_parts;
+
+ // texture and constant cache line sizes (used to determine number of memory accesses)
+ unsigned gpgpu_cache_texl1_linesize;
+ unsigned gpgpu_cache_constl1_linesize;
};
class core_t {
@@ -352,57 +357,94 @@ private:
unsigned m_bank; // n in ".const[n]"; note .const == .const[0] (see PTX 2.1 manual, sec. 5.1.3)
};
+const unsigned MAX_MEMORY_ACCESS_SIZE = 128;
+typedef std::bitset<MAX_MEMORY_ACCESS_SIZE> mem_access_byte_mask_t;
+#define NO_PARTIAL_WRITE (mem_access_byte_mask_t())
+
+const unsigned MAX_WARP_SIZE = 32;
+typedef std::bitset<MAX_WARP_SIZE> active_mask_t;
+
+enum mem_access_type {
+ GLOBAL_ACC_R,
+ LOCAL_ACC_R,
+ CONST_ACC_R,
+ TEXTURE_ACC_R,
+ GLOBAL_ACC_W,
+ LOCAL_ACC_W,
+ L2_WRBK_ACC,
+ INST_ACC_R,
+ NUM_MEM_ACCESS_TYPE
+};
+
class mem_access_t {
public:
- mem_access_t()
- {
- init();
+ mem_access_t() { init(); }
+ mem_access_t( mem_access_type type,
+ address_type address,
+ unsigned size,
+ bool wr )
+ {
+ init();
+ m_type = type;
+ m_addr = address;
+ m_req_size = size;
+ m_write = wr;
}
- mem_access_t(address_type address, unsigned size, unsigned quarter, unsigned idx )
+ mem_access_t( mem_access_type type,
+ address_type address,
+ unsigned size,
+ bool wr,
+ const active_mask_t &active_mask,
+ const mem_access_byte_mask_t &byte_mask )
+ : m_warp_mask(active_mask), m_byte_mask(byte_mask)
{
init();
- addr = address;
- req_size = size;
- quarter_count[quarter]++;
- warp_indices.push_back(idx);
+ m_type = type;
+ m_addr = address;
+ m_req_size = size;
+ m_write = wr;
}
- bool operator<(const mem_access_t &other) const {return (order > other.order);}//this is reverse
+ new_addr_type get_addr() const { return m_addr; }
+ unsigned get_size() const { return m_req_size; }
+ const active_mask_t &get_warp_mask() const { return m_warp_mask; }
+ bool is_write() const { return m_write; }
+ enum mem_access_type get_type() const { return m_type; }
+ mem_access_byte_mask_t get_byte_mask() const { return m_byte_mask; }
+
+ void print(FILE *fp) const
+ {
+ fprintf(fp,"addr=0x%llx, %s, size=%u, ", m_addr, m_write?"store":"load ", m_req_size );
+ switch(m_type) {
+ case GLOBAL_ACC_R: fprintf(fp,"GLOBAL_R"); break;
+ case LOCAL_ACC_R: fprintf(fp,"LOCAL_R "); break;
+ case CONST_ACC_R: fprintf(fp,"CONST "); break;
+ case TEXTURE_ACC_R: fprintf(fp,"TEXTURE "); break;
+ case GLOBAL_ACC_W: fprintf(fp,"GLOBAL_W"); break;
+ case LOCAL_ACC_W: fprintf(fp,"LOCAL_W "); break;
+ case L2_WRBK_ACC: fprintf(fp,"L2_WRBK "); break;
+ case INST_ACC_R: fprintf(fp,"INST "); break;
+ default: fprintf(fp,"unknown "); break;
+ }
+ }
private:
void init()
{
- uid=++next_access_uid;
- addr=0;
- req_size=0;
- order=0;
- _quarter_count_all=0;
- cache_hit = false;
- cache_checked = false;
- recheck_cache = false;
- need_wb = false;
- wb_addr = 0;
+ m_uid=++sm_next_access_uid;
+ m_addr=0;
+ m_req_size=0;
}
-public:
-
- unsigned uid;
- address_type addr; //address of the segment to load.
- unsigned req_size; //bytes
- unsigned order; // order of accesses, based on banks.
- union{
- unsigned _quarter_count_all;
- char quarter_count[4]; //access counts to each quarter of segment, for compaction;
- };
- std::vector<unsigned> warp_indices; // warp indicies for this request.
- bool cache_hit;
- bool cache_checked;
- bool recheck_cache;
- bool need_wb;
- address_type wb_addr; // writeback address (if necessary).
+ unsigned m_uid;
+ new_addr_type m_addr; // request address
+ bool m_write;
+ unsigned m_req_size; // bytes
+ mem_access_type m_type;
+ active_mask_t m_warp_mask;
+ mem_access_byte_mask_t m_byte_mask;
-private:
- static unsigned next_access_uid;
+ static unsigned sm_next_access_uid;
};
class mem_fetch;
@@ -471,8 +513,6 @@ protected:
virtual void pre_decode() {}
};
-#define MAX_WARP_SIZE 32
-
enum divergence_support_t {
POST_DOMINATOR = 1,
NUM_SIMD_MODEL
@@ -518,7 +558,7 @@ public:
{
for (int i=(int)m_config->warp_size-1; i>=0; i--) {
if( mask & (1<<i) )
- warp_active_mask.set(i);
+ m_warp_active_mask.set(i);
}
m_uid = ++sm_next_uid;
m_warp_id = warp_id;
@@ -535,6 +575,7 @@ public:
}
m_per_scalar_thread[n].memreqaddr = addr;
}
+ void generate_mem_accesses();
void add_callback( unsigned lane_id,
void (*function)(const class inst_t*, class ptx_thread_info*),
const inst_t *inst,
@@ -549,17 +590,12 @@ public:
m_per_scalar_thread[lane_id].callback.instruction = inst;
m_per_scalar_thread[lane_id].callback.thread = thread;
}
- void set_active( std::vector<unsigned> &active )
+ void set_active( const active_mask_t &active )
{
- warp_active_mask.reset();
- for( std::vector<unsigned>::iterator i=active.begin(); i!=active.end(); ++i ) {
- unsigned t = *i;
- assert( t < m_config->warp_size );
- warp_active_mask.set(t);
- }
+ m_warp_active_mask = active;
if( m_isatomic ) {
for( unsigned i=0; i < m_config->warp_size; i++ ) {
- if( !warp_active_mask.test(i) ) {
+ if( !m_warp_active_mask.test(i) ) {
m_per_scalar_thread[i].callback.function = NULL;
m_per_scalar_thread[i].callback.instruction = NULL;
m_per_scalar_thread[i].callback.thread = NULL;
@@ -567,29 +603,27 @@ public:
}
}
}
- void clear_active( std::vector<unsigned> &inactive )
+ void clear_active( const active_mask_t &inactive )
{
- std::vector<unsigned>::iterator i;
- for(i=inactive.begin(); i!=inactive.end();i++) {
- unsigned t=*i;
- warp_active_mask.reset(t);
- }
+ active_mask_t test = m_warp_active_mask;
+ test &= inactive;
+ assert( test == inactive ); // verify threads being disabled were active
+ m_warp_active_mask &= ~inactive;
}
void set_not_active( unsigned lane_id )
{
- warp_active_mask.reset(lane_id);
+ m_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_config->warp_size-1; i>=0; i--)
- fprintf(fp, "%c", ((warp_active_mask[i])?'1':'0') );
+ fprintf(fp, "%c", ((m_warp_active_mask[i])?'1':'0') );
}
- bool active( unsigned thread ) const { return warp_active_mask.test(thread); }
- unsigned active_count() const { return warp_active_mask.count(); }
+ bool active( unsigned thread ) const { return m_warp_active_mask.test(thread); }
+ unsigned active_count() const { return m_warp_active_mask.count(); }
bool empty() const { return m_empty; }
unsigned warp_id() const
{
@@ -598,7 +632,7 @@ public:
}
bool has_callback( unsigned n ) const
{
- return warp_active_mask[n] && m_per_scalar_thread_valid &&
+ return m_warp_active_mask[n] && m_per_scalar_thread_valid &&
(m_per_scalar_thread[n].callback.function!=NULL);
}
new_addr_type get_addr( unsigned n ) const
@@ -611,12 +645,8 @@ public:
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(); }
+ const mem_access_t &accessq_back() { return m_accessq.back(); }
void accessq_pop_back() { m_accessq.pop_back(); }
bool dispatch_delay()
@@ -629,6 +659,7 @@ public:
void print( FILE *fout ) const;
protected:
+
unsigned m_uid;
bool m_empty;
bool m_cache_hit;
@@ -637,7 +668,7 @@ protected:
bool m_isatomic;
unsigned m_warp_id;
const core_config *m_config;
- std::bitset<MAX_WARP_SIZE> warp_active_mask;
+ active_mask_t m_warp_active_mask;
struct per_thread_info {
per_thread_info() {
diff --git a/src/gpgpu-sim/gpu-sim.cc b/src/gpgpu-sim/gpu-sim.cc
index e3e54dc..a7b2ecf 100644
--- a/src/gpgpu-sim/gpu-sim.cc
+++ b/src/gpgpu-sim/gpu-sim.cc
@@ -259,8 +259,8 @@ void gpgpu_sim::reg_options(option_parser_t opp)
"Size of shared memory per shader core (default 16kB)",
"16384");
- option_parser_register(opp, "-gpgpu_shmem_pipe_speedup", OPT_INT32, &m_shader_config->gpgpu_shmem_pipe_speedup,
- "Number of groups each warp is divided for shared memory bank conflict check",
+ option_parser_register(opp, "-gpgpu_shmem_warp_parts", OPT_INT32, &m_shader_config->shmem_warp_parts,
+ "Number of portions a warp is divided into for shared memory bank conflict check ",
"2");
option_parser_register(opp, "-gpgpu_deadlock_detect", OPT_BOOL, &gpu_deadlock_detect,
@@ -431,7 +431,7 @@ void gpgpu_sim::init_gpu()
sscanf(gpgpu_runtime_stat, "%d:%x", &gpu_stat_sample_freq, &gpu_runtime_stat_flag);
m_shader_config->pdom_sched_type = m_pdom_sched_type;
- m_shader_config->gpgpu_n_shmem_bank=16;
+ m_shader_config->num_shmem_bank=16;
m_cluster = new simt_core_cluster*[m_shader_config->n_simt_clusters];
for (unsigned i=0;i<m_shader_config->n_simt_clusters;i++)
diff --git a/src/gpgpu-sim/mem_fetch.cc b/src/gpgpu-sim/mem_fetch.cc
index 74a1ac1..aa0006c 100644
--- a/src/gpgpu-sim/mem_fetch.cc
+++ b/src/gpgpu-sim/mem_fetch.cc
@@ -71,36 +71,30 @@
unsigned mem_fetch::sm_next_mf_request_uid=1;
-mem_fetch::mem_fetch( new_addr_type addr,
- unsigned data_size,
- unsigned ctrl_size,
- unsigned sid,
- unsigned tpc,
+mem_fetch::mem_fetch( const mem_access_t &access,
+ const warp_inst_t *inst,
+ unsigned ctrl_size,
unsigned wid,
- warp_inst_t *inst,
- bool write,
- partial_write_mask_t partial_write_mask,
- enum mem_access_type mem_acc,
- enum mf_type type,
- const memory_config *config ) : m_inst()
+ unsigned sid,
+ unsigned tpc,
+ const class memory_config *config )
{
m_request_uid = sm_next_mf_request_uid++;
-
- m_addr = addr;
- m_data_size = data_size;
+ m_access = access;
+ if( inst ) {
+ m_inst = *inst;
+ assert( wid == m_inst.warp_id() );
+ }
+ m_data_size = access.get_size();
m_ctrl_size = ctrl_size;
m_sid = sid;
- m_wid = wid;
m_tpc = tpc;
- if( inst ) m_inst = *inst;
- m_write = write;
- config->m_address_mapping.addrdec_tlx(addr,&m_raw_addr);
- m_partition_addr = config->m_address_mapping.partition_address(addr);
- m_mem_acc = mem_acc;
- m_type = type;
+ m_wid = wid;
+ config->m_address_mapping.addrdec_tlx(access.get_addr(),&m_raw_addr);
+ m_partition_addr = config->m_address_mapping.partition_address(access.get_addr());
+ m_type = m_access.is_write()?WR_REQ:RD_REQ;
m_timestamp = gpu_sim_cycle + gpu_tot_sim_cycle;
m_timestamp2 = 0;
-
m_status = MEM_FETCH_INITIALIZED;
m_status_change = gpu_sim_cycle + gpu_tot_sim_cycle;
}
@@ -137,8 +131,8 @@ void mem_fetch::print( FILE *fp, bool print_inst ) const
fprintf(fp," <NULL mem_fetch pointer>\n");
return;
}
- fprintf(fp," mf: uid=%6u, addr=0x%08llx, sid=%2u, wid=%2u, %s, partition=%u, ",
- m_request_uid, m_addr, m_sid, m_wid, (m_write?"write":"read "), m_raw_addr.chip);
+ fprintf(fp," mf: uid=%6u, sid=%2u, partition=%u, ", m_request_uid, m_sid, m_raw_addr.chip );
+ m_access.print(fp);
if( (unsigned)m_status < NUM_MEM_REQ_STAT )
fprintf(fp," status = %s (%llu), ", Status_str[m_status], m_status_change );
else
diff --git a/src/gpgpu-sim/mem_fetch.h b/src/gpgpu-sim/mem_fetch.h
index 8fe09e0..05e2206 100644
--- a/src/gpgpu-sim/mem_fetch.h
+++ b/src/gpgpu-sim/mem_fetch.h
@@ -73,22 +73,8 @@
enum mf_type {
RD_REQ = 0,
- WT_REQ,
- REPLY_DATA, // send to shader
- L2_WTBK_DATA,
- N_MF_TYPE
-};
-
-enum mem_access_type {
- GLOBAL_ACC_R = 0,
- LOCAL_ACC_R = 1,
- CONST_ACC_R = 2,
- TEXTURE_ACC_R = 3,
- GLOBAL_ACC_W = 4,
- LOCAL_ACC_W = 5,
- L2_WRBK_ACC = 6,
- INST_ACC_R = 7,
- NUM_MEM_ACCESS_TYPE = 8
+ WR_REQ,
+ REPLY_DATA // send to shader
};
enum mem_fetch_status {
@@ -113,23 +99,15 @@ enum mem_fetch_status {
NUM_MEM_REQ_STAT
};
-const unsigned partial_write_mask_bits = 128; //must be at least size of largest memory access.
-typedef std::bitset<partial_write_mask_bits> partial_write_mask_t;
-
class mem_fetch {
public:
- mem_fetch( new_addr_type addr,
- unsigned data_size,
- unsigned ctrl_size,
- unsigned sid,
- unsigned tpc,
- unsigned wid,
- warp_inst_t *inst,
- bool write,
- partial_write_mask_t partial_write_mask,
- enum mem_access_type mem_acc,
- enum mf_type type,
- const class memory_config *config );
+ mem_fetch( const mem_access_t &access,
+ const warp_inst_t *inst,
+ unsigned ctrl_size,
+ unsigned wid,
+ unsigned sid,
+ unsigned tpc,
+ const class memory_config *config );
~mem_fetch();
void set_status( enum mem_fetch_status status, unsigned long long cycle );
@@ -143,9 +121,9 @@ public:
void set_data_size( unsigned size ) { m_data_size=size; }
unsigned get_ctrl_size() const { return m_ctrl_size; }
unsigned size() const { return m_data_size+m_ctrl_size; }
- new_addr_type get_addr() const { return m_addr; }
+ new_addr_type get_addr() const { return m_access.get_addr(); }
new_addr_type get_partition_addr() const { return m_partition_addr; }
- bool get_is_write() const { return m_write; }
+ bool get_is_write() const { return m_access.is_write(); }
unsigned get_request_uid() const { return m_request_uid; }
unsigned get_sid() const { return m_sid; }
unsigned get_tpc() const { return m_tpc; }
@@ -154,12 +132,14 @@ public:
bool isconst() const;
enum mf_type get_type() const { return m_type; }
bool isatomic() const;
+
void set_return_timestamp( unsigned t ) { m_timestamp2=t; }
void set_icnt_receive_time( unsigned t ) { m_icnt_receive_time=t; }
unsigned get_timestamp() const { return m_timestamp; }
unsigned get_return_timestamp() const { return m_timestamp2; }
unsigned get_icnt_receive_time() const { return m_icnt_receive_time; }
- enum mem_access_type get_mem_acc() const { return m_mem_acc; }
+
+ enum mem_access_type get_access_type() const { return m_access.get_type(); }
address_type get_pc() const { return m_inst.empty()?-1:m_inst.pc; }
const warp_inst_t &get_inst() { return m_inst; }
enum mem_fetch_status get_status() const { return m_status; }
@@ -176,15 +156,12 @@ private:
unsigned long long m_status_change;
// request type, address, size, mask
- bool m_write;
- enum mem_access_type m_mem_acc;
- enum mf_type m_type;
- new_addr_type m_addr; // linear (physical) address
- new_addr_type m_partition_addr; // linear physical address *within* dram partition (partition bank select bits squeezed out)
- addrdec_t m_raw_addr; // raw physical address (i.e., decoded DRAM chip-row-bank-column address)
- partial_write_mask_t m_write_mask;
+ mem_access_t m_access;
unsigned m_data_size; // how much data is being written
unsigned m_ctrl_size; // how big would all this meta data be in hardware (does not necessarily match actual size of mem_fetch)
+ new_addr_type m_partition_addr; // linear physical address *within* dram partition (partition bank select bits squeezed out)
+ addrdec_t m_raw_addr; // raw physical address (i.e., decoded DRAM chip-row-bank-column address)
+ enum mf_type m_type;
// statistics
unsigned m_timestamp; // set to gpu_sim_cycle+gpu_tot_sim_cycle at struct creation
diff --git a/src/gpgpu-sim/mem_latency_stat.cc b/src/gpgpu-sim/mem_latency_stat.cc
index f78717e..5b4d3ac 100644
--- a/src/gpgpu-sim/mem_latency_stat.cc
+++ b/src/gpgpu-sim/mem_latency_stat.cc
@@ -229,7 +229,7 @@ void memory_stats_t::memlatstat_dram_access(mem_fetch *mf)
}
if (mf->get_pc() != (unsigned)-1)
ptx_file_line_stats_add_dram_traffic(mf->get_pc(),1);
- mem_access_type_stats[mf->get_mem_acc()][dram_id][bank]++;
+ mem_access_type_stats[mf->get_access_type()][dram_id][bank]++;
}
}
diff --git a/src/gpgpu-sim/shader.cc b/src/gpgpu-sim/shader.cc
index 0604bb8..5c73126 100644
--- a/src/gpgpu-sim/shader.cc
+++ b/src/gpgpu-sim/shader.cc
@@ -425,17 +425,13 @@ void shader_core_ctx::fetch()
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);
- mem_fetch *mf = new mem_fetch(ppc,
- nbytes,
+ mem_access_t acc(INST_ACC_R,ppc,nbytes,false);
+ mem_fetch *mf = new mem_fetch(acc,
+ NULL/*we don't have an instruction yet*/,
READ_PACKET_SIZE,
+ warp_id,
m_sid,
m_tpc,
- warp_id,
- NULL/*we don't have an instruction yet*/,
- false,
- NO_PARTIAL_WRITE,
- INST_ACC_R,
- RD_REQ,
m_memory_config );
enum cache_request_status status = m_L1I->access( (new_addr_type)ppc, mf, gpu_sim_cycle+gpu_tot_sim_cycle );
if( status == MISS ) {
@@ -481,6 +477,8 @@ void shader_core_ctx::func_exec_inst( warp_inst_t &inst )
}
}
}
+ if( inst.is_load() || inst.is_store() )
+ inst.generate_mem_accesses();
}
void shader_core_ctx::issue_warp( warp_inst_t *&pipe_reg, const warp_inst_t *next_inst, unsigned active_mask, unsigned warp_id )
@@ -609,51 +607,16 @@ void shader_core_ctx::execute()
}
}
-mem_fetch *ldst_unit::create_data_mem_fetch(warp_inst_t &inst, mem_access_t &access)
+mem_fetch *ldst_unit::create_data_mem_fetch(const warp_inst_t &inst, const mem_access_t &access)
{
- bool is_write = inst.is_store();
- mem_access_type access_type;
- switch (inst.space.get_type()) {
- case const_space:
- case param_space_kernel:
- access_type = CONST_ACC_R;
- break;
- case tex_space:
- access_type = TEXTURE_ACC_R;
- break;
- case global_space:
- access_type = is_write? GLOBAL_ACC_W: GLOBAL_ACC_R;
- break;
- case local_space:
- case param_space_local:
- access_type = is_write? LOCAL_ACC_W: LOCAL_ACC_R;
- break;
- default: assert(0); break;
- }
- unsigned request_size = access.req_size;
- partial_write_mask_t write_mask = NO_PARTIAL_WRITE;
- if (is_write) {
- 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);
- for (unsigned b = data_offset; b < data_offset + inst.data_size; b++)
- write_mask.set(b);
- }
- }
warp_inst_t inst_copy = inst;
- inst_copy.set_active(access.warp_indices);
- unsigned warp_id = inst.warp_id();
- mem_fetch *mf = new mem_fetch(access.addr,
- request_size,
- is_write?WRITE_PACKET_SIZE:READ_PACKET_SIZE,
- m_sid,
- m_tpc,
- warp_id,
- &inst_copy,
- is_write,
- write_mask,
- access_type,
- is_write?WT_REQ:RD_REQ,
+ inst_copy.set_active(access.get_warp_mask());
+ mem_fetch *mf = new mem_fetch(access,
+ &inst_copy,
+ access.is_write()?WRITE_PACKET_SIZE:READ_PACKET_SIZE,
+ inst.warp_id(),
+ m_sid,
+ m_tpc,
m_memory_config);
return mf;
}
@@ -675,59 +638,51 @@ void shader_core_ctx::writeback()
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 )
return true;
-
- //consume port number orders from the top of the queue;
- for( int i = 0; i < m_config->gpgpu_shmem_port_per_bank; i++ ) {
- if (inst.accessq_empty())
- break;
- unsigned current_order = inst.accessq_back().order;
- //consume all requests of the same order (concurrent bank requests)
- while ((!inst.accessq_empty()) && inst.accessq_back().order == current_order)
- inst.accessq_pop_back();
- }
- if( !inst.accessq_empty() ) {
- rc_fail = BK_CONF;
- fail_type = S_MEM;
- m_stats->gpgpu_n_shmem_bkconflict++;
- }
- return inst.accessq_empty(); //done if empty.
+ bool stall = inst.dispatch_delay();
+ if( stall ) {
+ fail_type = S_MEM;
+ rc_fail = BK_CONF;
+ } else
+ rc_fail = NO_RC_FAIL;
+ return !stall;
}
mem_stage_stall_type ldst_unit::process_memory_access_queue( cache_t *cache, warp_inst_t &inst )
{
mem_stage_stall_type result = NO_RC_FAIL;
- unsigned current_order = inst.accessq_back().order;
- while ((!inst.accessq_empty()) && inst.accessq_back().order == current_order) {
- mem_fetch *mf = create_data_mem_fetch(inst,inst.accessq_back());
- enum cache_request_status status = cache->access(mf->get_addr(),mf,gpu_sim_cycle+gpu_tot_sim_cycle);
- if( status == HIT ) {
- inst.accessq_pop_back();
- delete mf;
- } else if( status == RESERVATION_FAIL ) {
- result = COAL_STALL; // todo: unify enums
- delete mf;
- break;
- } else {
- assert( status == MISS || status == HIT_RESERVED );
- inst.accessq_pop_back();
- if( inst.is_load() ) {
- for( unsigned r=0; r < 4; r++)
- if(inst.out[r] > 0)
- m_pending_writes[inst.warp_id()][inst.out[r]]++;
- }
- }
+ if( inst.accessq_empty() )
+ return result;
+
+ const mem_access_t &access = inst.accessq_back();
+ mem_fetch *mf = create_data_mem_fetch(inst,inst.accessq_back());
+ enum cache_request_status status = cache->access(mf->get_addr(),mf,gpu_sim_cycle+gpu_tot_sim_cycle);
+
+ if ( status == HIT ) {
+ inst.accessq_pop_back();
+ delete mf;
+ } else if ( status == RESERVATION_FAIL ) {
+ result = COAL_STALL;
+ delete mf;
+ } else {
+ inst.clear_active( access.get_warp_mask() ); // threads in mf writeback when mf returns
+ assert( status == MISS || status == HIT_RESERVED );
+ inst.accessq_pop_back();
+ if ( inst.is_load() ) {
+ for ( unsigned r=0; r < 4; r++)
+ if (inst.out[r] > 0)
+ m_pending_writes[inst.warp_id()][inst.out[r]]++;
+ }
}
- if( !inst.accessq_empty() && (inst.accessq_back().order != current_order) )
- result = BK_CONF;
+ if( !inst.accessq_empty() )
+ result = BK_CONF;
return result;
}
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) )
+ if( inst.empty() || ((inst.space.get_type() != const_space) && (inst.space.get_type() != param_space_kernel)) )
return true;
mem_stage_stall_type fail = process_memory_access_queue(m_L1C,inst);
if (fail != NO_RC_FAIL){
@@ -742,7 +697,7 @@ bool ldst_unit::constant_cycle( warp_inst_t &inst, mem_stage_stall_type &rc_fail
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 )
+ if( inst.empty() || inst.space.get_type() != tex_space )
return true;
mem_stage_stall_type fail = process_memory_access_queue(m_L1T,inst);
if (fail != NO_RC_FAIL){
@@ -754,27 +709,28 @@ bool ldst_unit::texture_cycle( warp_inst_t &inst, mem_stage_stall_type &rc_fail,
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) &&
- (inst.space.get_type() != param_space_local) )
+ if( inst.empty() ||
+ ((inst.space.get_type() != global_space) &&
+ (inst.space.get_type() != local_space) &&
+ (inst.space.get_type() != param_space_local)) )
return true;
+ assert( !inst.accessq_empty() );
mem_stage_stall_type stall_cond = NO_RC_FAIL;
- unsigned current_order = inst.accessq_back().order;
- while ((!inst.accessq_empty()) && inst.accessq_back().order == current_order) {
- if( m_icnt->full(inst.accessq_back().req_size, inst.is_store()) ) {
- stall_cond = ICNT_RC_FAIL;
- break;
- } else {
- mem_fetch *mf = create_data_mem_fetch(inst,inst.accessq_back());
- m_icnt->push(mf);
- inst.accessq_pop_back();
- if( inst.is_load() ) {
- for( unsigned r=0; r < 4; r++)
- if(inst.out[r] > 0)
- m_pending_writes[inst.warp_id()][inst.out[r]]++;
- } else if( inst.is_store() )
- m_core->inc_store_req( inst.warp_id() );
- }
+ const mem_access_t &access = inst.accessq_back();
+ unsigned size = access.get_size();
+ if( m_icnt->full(size, inst.is_store()) ) {
+ stall_cond = ICNT_RC_FAIL;
+ } else {
+ mem_fetch *mf = create_data_mem_fetch(inst,access);
+ m_icnt->push(mf);
+ inst.accessq_pop_back();
+ inst.clear_active( access.get_warp_mask() );
+ if( inst.is_load() ) {
+ for( unsigned r=0; r < 4; r++)
+ if(inst.out[r] > 0)
+ m_pending_writes[inst.warp_id()][inst.out[r]]++;
+ } else if( inst.is_store() )
+ m_core->inc_store_req( inst.warp_id() );
}
if( !inst.accessq_empty() )
stall_cond = COAL_STALL;
@@ -785,12 +741,11 @@ bool ldst_unit::memory_cycle( warp_inst_t &inst, mem_stage_stall_type &stall_rea
access_type = (iswrite)?L_MEM_ST:L_MEM_LD;
else
access_type = (iswrite)?G_MEM_ST:G_MEM_LD;
- if (stall_cond == BK_CONF || stall_cond == COAL_STALL)
- m_stats->gpgpu_n_cache_bkconflict++;
}
- return inst.accessq_empty(); //done if empty.
+ return inst.accessq_empty();
}
+
bool ldst_unit::response_buffer_full() const
{
return m_response_fifo.size() >= m_config->ldst_unit_response_queue_size;
@@ -807,20 +762,6 @@ void ldst_unit::flush()
// no L1D
}
-void ldst_unit::generate_mem_accesses(warp_inst_t &inst)
-{
- // 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( inst.op == MEMORY_BARRIER_OP )
- return;
- if( inst.mem_accesses_created() )
- return;
- inst.get_memory_access_list();
- inst.set_mem_accesses_created();
-}
-
simd_function_unit::simd_function_unit( const shader_core_config *config )
{
m_config=config;
@@ -975,10 +916,7 @@ void ldst_unit::cycle()
m_L1T->cycle();
m_L1C->cycle();
- // process new memory requests
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;
bool done = true;
@@ -1975,7 +1913,7 @@ void simt_core_cluster::icnt_inject_request_packet(class mem_fetch *mf)
// stats
if (mf->get_is_write()) m_stats->made_write_mfs++;
else m_stats->made_read_mfs++;
- switch (mf->get_mem_acc()) {
+ switch (mf->get_access_type()) {
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;
@@ -1985,17 +1923,12 @@ void simt_core_cluster::icnt_inject_request_packet(class mem_fetch *mf)
case INST_ACC_R: m_stats->gpgpu_n_mem_read_inst++; break;
default: assert(0);
}
-
unsigned destination = mf->get_tlx_addr().chip;
mf->set_status(IN_ICNT_TO_MEM,gpu_sim_cycle+gpu_tot_sim_cycle);
- if (!mf->get_is_write()) {
- mf->set_type(RD_REQ);
+ if (!mf->get_is_write())
::icnt_push(m_cluster_id, m_config->mem2device(destination), (void*)mf, mf->get_ctrl_size() );
- } else {
- mf->set_type(WT_REQ);
+ else
::icnt_push(m_cluster_id, m_config->mem2device(destination), (void*)mf, mf->size());
- //gpgpu_n_sent_writes++;
- }
}
void simt_core_cluster::icnt_cycle()
@@ -2003,7 +1936,7 @@ void simt_core_cluster::icnt_cycle()
if( !m_response_fifo.empty() ) {
mem_fetch *mf = m_response_fifo.front();
unsigned cid = sid_to_cid(mf->get_sid());
- if( mf->get_mem_acc() == INST_ACC_R ) {
+ if( mf->get_access_type() == INST_ACC_R ) {
// instruction fetch response
if( !m_core[cid]->fetch_unit_response_buffer_full() ) {
m_response_fifo.pop_front();
diff --git a/src/gpgpu-sim/shader.h b/src/gpgpu-sim/shader.h
index b9e0bda..278fafc 100644
--- a/src/gpgpu-sim/shader.h
+++ b/src/gpgpu-sim/shader.h
@@ -105,7 +105,6 @@
#define WRITE_PACKET_SIZE 8
#define WRITE_MASK_SIZE 8
-#define NO_PARTIAL_WRITE (partial_write_mask_t())
//Set a hard limit of 32 CTAs per shader [cuda only has 8]
#define MAX_CTA_PER_SHADER 32
@@ -863,15 +862,13 @@ public:
void print(FILE *fout) const;
private:
- void generate_mem_accesses(warp_inst_t &pipe_reg);
-
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 process_memory_access_queue( cache_t *cache, warp_inst_t &inst );
- mem_fetch *create_data_mem_fetch(warp_inst_t &inst, mem_access_t &access);
+ mem_fetch *create_data_mem_fetch(const warp_inst_t &inst, const mem_access_t &access);
const memory_config *m_memory_config;
class shader_memory_interface *m_icnt;
diff --git a/src/gpgpu-sim/visualizer.cc b/src/gpgpu-sim/visualizer.cc
index 51348d5..730e0c9 100644
--- a/src/gpgpu-sim/visualizer.cc
+++ b/src/gpgpu-sim/visualizer.cc
@@ -483,7 +483,7 @@ void time_vector_print_interval2gzfile(gzFile outfile) {
void time_vector_update(unsigned int uid,int slot ,long int cycle,int type) {
if ( (type == RD_REQ) || (type == REPLY_DATA) ) {
g_my_time_vector->update_ld( uid, slot,cycle);
- } else if ( type == WT_REQ ) {
+ } else if ( type == WR_REQ ) {
g_my_time_vector->update_st( uid, slot,cycle);
} else {
abort();
@@ -494,7 +494,7 @@ void check_time_vector_update(unsigned int uid,int slot ,long int latency,int ty
{
if ( (type == RD_REQ) || (type == REPLY_DATA) ) {
g_my_time_vector->check_ld_update( uid, slot, latency );
- } else if ( type == WT_REQ ) {
+ } else if ( type == WR_REQ ) {
g_my_time_vector->check_st_update( uid, slot, latency );
} else {
abort();