summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTor Aamodt <[email protected]>2010-11-28 09:35:25 -0800
committerTor Aamodt <[email protected]>2010-11-28 09:35:25 -0800
commit23d096dd1f1d4f0387087ffff0605fbf349556d2 (patch)
tree18e39a86e83bc445ec37eb9485c2a5ace7c82074 /src
parenta937a4b354b60999a011970d054cd6c478be130d (diff)
adding 1st level data cache
[git-p4: depot-paths = "//depot/gpgpu_sim_research/fermi/distribution/": change = 8153]
Diffstat (limited to 'src')
-rw-r--r--src/abstract_hardware_model.h29
-rw-r--r--src/cuda-sim/cuda-sim.cc18
-rw-r--r--src/cuda-sim/ptx.l3
-rw-r--r--src/cuda-sim/ptx.y9
-rw-r--r--src/gpgpu-sim/gpu-cache.cc175
-rw-r--r--src/gpgpu-sim/gpu-cache.h172
-rw-r--r--src/gpgpu-sim/gpu-sim.cc23
-rw-r--r--src/gpgpu-sim/icnt_wrapper.h3
-rw-r--r--src/gpgpu-sim/l2cache.cc9
-rw-r--r--src/gpgpu-sim/shader.cc110
-rw-r--r--src/gpgpu-sim/shader.h51
-rw-r--r--src/intersim/interconnect_interface.cpp22
12 files changed, 459 insertions, 165 deletions
diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h
index cdecc14..21f9689 100644
--- a/src/abstract_hardware_model.h
+++ b/src/abstract_hardware_model.h
@@ -408,11 +408,29 @@ enum mem_access_type {
TEXTURE_ACC_R,
GLOBAL_ACC_W,
LOCAL_ACC_W,
+ L1_WRBK_ACC,
L2_WRBK_ACC,
- INST_ACC_R,
+ INST_ACC_R,
NUM_MEM_ACCESS_TYPE
};
+enum cache_operator_type {
+ CACHE_UNDEFINED,
+
+ // loads
+ CACHE_ALL, // .ca
+ CACHE_LAST_USE, // .lu
+ CACHE_VOLATILE, // .cv
+
+ // loads and stores
+ CACHE_STREAMING, // .cs
+ CACHE_GLOBAL, // .cg
+
+ // stores
+ CACHE_WRITE_BACK, // .wb
+ CACHE_WRITE_THROUGH // .wt
+};
+
class mem_access_t {
public:
mem_access_t() { init(); }
@@ -461,6 +479,7 @@ public:
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;
+ case L1_WRBK_ACC: fprintf(fp,"L1_WRBK "); break;
default: fprintf(fp,"unknown "); break;
}
}
@@ -492,6 +511,12 @@ public:
virtual void push( mem_fetch *mf ) = 0;
};
+class mem_fetch_allocator {
+public:
+ virtual mem_fetch *alloc( new_addr_type addr, mem_access_type type, unsigned size, bool wr ) const = 0;
+ virtual mem_fetch *alloc( const class warp_inst_t &inst, const mem_access_t &access ) const = 0;
+};
+
#define MAX_REG_OPERANDS 8
struct dram_callback_t {
@@ -513,6 +538,7 @@ public:
is_vectorin=0;
is_vectorout=0;
space = memory_space_t();
+ cache_op = CACHE_UNDEFINED;
latency = 1;
initiation_interval = 1;
for( unsigned i=0; i < MAX_REG_OPERANDS; i++ )
@@ -544,6 +570,7 @@ public:
unsigned data_size; // what is the size of the word being operated on?
memory_space_t space;
+ cache_operator_type cache_op;
protected:
bool m_decoded;
diff --git a/src/cuda-sim/cuda-sim.cc b/src/cuda-sim/cuda-sim.cc
index b1893a0..34bfe82 100644
--- a/src/cuda-sim/cuda-sim.cc
+++ b/src/cuda-sim/cuda-sim.cc
@@ -566,6 +566,24 @@ void ptx_instruction::pre_decode()
break;
}
+ switch( m_cache_option ) {
+ case CA_OPTION: cache_op = CACHE_ALL; break;
+ case CG_OPTION: cache_op = CACHE_GLOBAL; break;
+ case CS_OPTION: cache_op = CACHE_STREAMING; break;
+ case LU_OPTION: cache_op = CACHE_LAST_USE; break;
+ case CV_OPTION: cache_op = CACHE_VOLATILE; break;
+ case WB_OPTION: cache_op = CACHE_WRITE_BACK; break;
+ case WT_OPTION: cache_op = CACHE_WRITE_THROUGH; break;
+ default:
+ if( m_opcode == LD_OP )
+ cache_op = CACHE_ALL;
+ else if( m_opcode == ST_OP )
+ cache_op = CACHE_WRITE_BACK;
+ else if( m_opcode == ATOM_OP )
+ cache_op = CACHE_GLOBAL;
+ break;
+ }
+
set_opcode_and_latency();
// Get register operands
diff --git a/src/cuda-sim/ptx.l b/src/cuda-sim/ptx.l
index 1b87c7d..d54530d 100644
--- a/src/cuda-sim/ptx.l
+++ b/src/cuda-sim/ptx.l
@@ -340,6 +340,9 @@ breakaddr TC; ptx_lval.int_value = BREAKADDR_OP; return OPCODE;
\.lu TC; return LU_OPTION;
\.cv TC; return CV_OPTION;
+\.wb TC; return WB_OPTION;
+\.wt TC; return WT_OPTION;
+
\.and TC; return ATOMIC_AND;
\.or TC; return ATOMIC_OR;
\.xor TC; return ATOMIC_XOR;
diff --git a/src/cuda-sim/ptx.y b/src/cuda-sim/ptx.y
index 833e082..5142f4d 100644
--- a/src/cuda-sim/ptx.y
+++ b/src/cuda-sim/ptx.y
@@ -215,6 +215,8 @@
%token CS_OPTION;
%token LU_OPTION;
%token CV_OPTION;
+%token WB_OPTION;
+%token WT_OPTION;
%type <int_value> function_decl_header
%type <ptr_value> function_decl
@@ -435,6 +437,13 @@ option: type_spec
| atomic_operation_spec ;
| TO_OPTION { add_option(TO_OPTION); }
| HALF_OPTION { add_option(HALF_OPTION); }
+ | CA_OPTION { add_option(CA_OPTION); }
+ | CG_OPTION { add_option(CG_OPTION); }
+ | CS_OPTION { add_option(CS_OPTION); }
+ | LU_OPTION { add_option(LU_OPTION); }
+ | CV_OPTION { add_option(CV_OPTION); }
+ | WB_OPTION { add_option(WB_OPTION); }
+ | WT_OPTION { add_option(WT_OPTION); }
;
atomic_operation_spec: ATOMIC_AND { add_option(ATOMIC_AND); }
diff --git a/src/gpgpu-sim/gpu-cache.cc b/src/gpgpu-sim/gpu-cache.cc
index c746da7..594e683 100644
--- a/src/gpgpu-sim/gpu-cache.cc
+++ b/src/gpgpu-sim/gpu-cache.cc
@@ -70,25 +70,24 @@
tag_array::~tag_array()
{
- delete m_lines;
+ delete m_lines;
}
tag_array::tag_array( const cache_config &config, int core_id, int type_id )
- : m_config(config)
+: m_config(config)
{
- assert( m_config.m_write_policy == READ_ONLY );
- m_lines = new cache_block_t[ config.get_num_lines()];
+ assert( m_config.m_write_policy == READ_ONLY );
+ m_lines = new cache_block_t[ config.get_num_lines()];
- // initialize snapshot counters for visualizer
- m_prev_snapshot_access = 0;
- m_prev_snapshot_miss = 0;
- m_prev_snapshot_pending_hit = 0;
- m_core_id = core_id;
- m_type_id = type_id;
+ // initialize snapshot counters for visualizer
+ m_prev_snapshot_access = 0;
+ m_prev_snapshot_miss = 0;
+ m_prev_snapshot_pending_hit = 0;
+ m_core_id = core_id;
+ m_type_id = type_id;
}
-enum cache_request_status tag_array::probe( new_addr_type addr, unsigned &idx ) const
-{
+enum cache_request_status tag_array::probe( new_addr_type addr, unsigned &idx ) const {
assert( m_config.m_write_policy == READ_ONLY );
unsigned set_index = m_config.set_index(addr);
new_addr_type tag = m_config.tag(addr);
@@ -98,57 +97,70 @@ enum cache_request_status tag_array::probe( new_addr_type addr, unsigned &idx )
unsigned valid_timestamp = (unsigned)-1;
bool all_reserved = true;
-
+
// check for hit or pending hit
for (unsigned way=0; way<m_config.m_assoc; way++) {
- unsigned index = set_index*m_config.m_assoc+way;
- cache_block_t *line = &m_lines[index];
- if (line->m_tag == tag) {
- if( line->m_status == RESERVED ) {
- idx = index;
- return HIT_RESERVED;
- } else if( line->m_status == VALID ) {
- idx = index;
- return HIT;
- } else {
- assert( line->m_status == INVALID );
- }
- }
- if(line->m_status != RESERVED) {
- all_reserved = false;
- if(line->m_status == INVALID) {
- invalid_line = index;
- } else {
- // valid line : keep track of most appropriate replacement candidate
- if( m_config.m_replacement_policy == LRU ) {
- if( line->m_last_access_time < valid_timestamp ) {
- valid_timestamp = line->m_last_access_time;
- valid_line = index;
- }
- } else if( m_config.m_replacement_policy == FIFO ) {
- if( line->m_alloc_time < valid_timestamp ) {
- valid_timestamp = line->m_alloc_time;
- valid_line = index;
- }
- }
- }
- }
- }
- if( all_reserved ) {
- assert( m_config.m_alloc_policy == ON_MISS );
- return RESERVATION_FAIL; // miss and not enough space in cache to allocate on miss
- }
+ unsigned index = set_index*m_config.m_assoc+way;
+ cache_block_t *line = &m_lines[index];
+ if (line->m_tag == tag) {
+ if ( line->m_status == RESERVED ) {
+ idx = index;
+ return HIT_RESERVED;
+ } else if ( line->m_status == VALID ) {
+ idx = index;
+ return HIT;
+ } else if ( line->m_status == MODIFIED ) {
+ idx = index;
+ return HIT;
+ } else {
+ assert( line->m_status == INVALID );
+ }
+ }
+ if (line->m_status != RESERVED) {
+ all_reserved = false;
+ if (line->m_status == INVALID) {
+ invalid_line = index;
+ } else {
+ // valid line : keep track of most appropriate replacement candidate
+ if ( m_config.m_replacement_policy == LRU ) {
+ if ( line->m_last_access_time < valid_timestamp ) {
+ valid_timestamp = line->m_last_access_time;
+ valid_line = index;
+ }
+ } else if ( m_config.m_replacement_policy == FIFO ) {
+ if ( line->m_alloc_time < valid_timestamp ) {
+ valid_timestamp = line->m_alloc_time;
+ valid_line = index;
+ }
+ }
+ }
+ }
+ }
+ if ( all_reserved ) {
+ assert( m_config.m_alloc_policy == ON_MISS );
+ return RESERVATION_FAIL; // miss and not enough space in cache to allocate on miss
+ }
- if( invalid_line != (unsigned)-1 ) {
- idx = invalid_line;
- } else if( valid_line != (unsigned)-1) {
- idx = valid_line;
- } else abort(); // if an unreserved block exists, it is either invalid or replaceable
+ if ( invalid_line != (unsigned)-1 ) {
+ idx = invalid_line;
+ } else if ( valid_line != (unsigned)-1) {
+ idx = valid_line;
+ } else abort(); // if an unreserved block exists, it is either invalid or replaceable
- return MISS;
+ return MISS;
}
-enum cache_request_status tag_array::access( new_addr_type addr, unsigned time, unsigned &idx ) {
+enum cache_request_status tag_array::access( new_addr_type addr, unsigned time, unsigned &idx )
+{
+ bool wb=false;
+ cache_block_t evicted;
+ enum cache_request_status result = access(addr,time,idx,wb,evicted);
+ assert(!wb);
+ return result;
+}
+
+enum cache_request_status tag_array::access( new_addr_type addr, unsigned time, unsigned &idx, bool &wb, cache_block_t &evicted )
+{
m_access++;
shader_cache_access_log(m_core_id, m_type_id, 0); // log accesses to cache
enum cache_request_status status = probe(addr,idx);
@@ -161,8 +173,13 @@ enum cache_request_status tag_array::access( new_addr_type addr, unsigned time,
case MISS:
m_miss++;
shader_cache_access_log(m_core_id, m_type_id, 1); // log cache misses
- if ( m_config.m_alloc_policy == ON_MISS )
+ if ( m_config.m_alloc_policy == ON_MISS ) {
+ if( m_lines[idx].m_status == MODIFIED ) {
+ wb = true;
+ evicted = m_lines[idx];
+ }
m_lines[idx].allocate( m_config.tag(addr), m_config.block_addr(addr), time );
+ }
break;
case RESERVATION_FAIL:
m_miss++;
@@ -190,37 +207,37 @@ void tag_array::fill( unsigned index, unsigned time )
void tag_array::flush()
{
- for (unsigned i=0; i < m_config.get_num_lines(); i++)
- m_lines[i].m_status = INVALID;
+ for (unsigned i=0; i < m_config.get_num_lines(); i++)
+ m_lines[i].m_status = INVALID;
}
float tag_array::windowed_miss_rate( bool minus_pending_hit ) const
{
- unsigned n_access = m_access - m_prev_snapshot_access;
- unsigned n_miss = m_miss - m_prev_snapshot_miss;
- unsigned n_pending_hit = m_pending_hit - m_prev_snapshot_pending_hit;
-
- if (minus_pending_hit)
- n_miss -= n_pending_hit;
- float missrate = 0.0f;
- if (n_access != 0)
- missrate = (float) n_miss / n_access;
- return missrate;
+ unsigned n_access = m_access - m_prev_snapshot_access;
+ unsigned n_miss = m_miss - m_prev_snapshot_miss;
+ unsigned n_pending_hit = m_pending_hit - m_prev_snapshot_pending_hit;
+
+ if (minus_pending_hit)
+ n_miss -= n_pending_hit;
+ float missrate = 0.0f;
+ if (n_access != 0)
+ missrate = (float) n_miss / n_access;
+ return missrate;
}
void tag_array::new_window()
{
- m_prev_snapshot_access = m_access;
- m_prev_snapshot_miss = m_miss;
- m_prev_snapshot_pending_hit = m_pending_hit;
+ m_prev_snapshot_access = m_access;
+ m_prev_snapshot_miss = m_miss;
+ m_prev_snapshot_pending_hit = m_pending_hit;
}
void tag_array::print( FILE *stream, unsigned &total_access, unsigned &total_misses ) const
{
- m_config.print(stream);
- fprintf( stream, "\t\tAccess = %d, Miss = %d (%.3g), -MgHts = %d (%.3g)\n",
- m_access, m_miss, (float) m_miss / m_access,
- m_miss - m_pending_hit, (float) (m_miss - m_pending_hit) / m_access);
- total_misses+=m_miss;
- total_access+=m_access;
+ m_config.print(stream);
+ fprintf( stream, "\t\tAccess = %d, Miss = %d (%.3g), -MgHts = %d (%.3g)\n",
+ m_access, m_miss, (float) m_miss / m_access,
+ m_miss - m_pending_hit, (float) (m_miss - m_pending_hit) / m_access);
+ total_misses+=m_miss;
+ total_access+=m_access;
}
diff --git a/src/gpgpu-sim/gpu-cache.h b/src/gpgpu-sim/gpu-cache.h
index de85b8f..6b93d85 100644
--- a/src/gpgpu-sim/gpu-cache.h
+++ b/src/gpgpu-sim/gpu-cache.h
@@ -77,7 +77,8 @@
enum cache_block_state {
INVALID,
RESERVED,
- VALID
+ VALID,
+ MODIFIED
};
enum cache_request_status {
@@ -147,6 +148,7 @@ public:
cache_config()
{
m_valid = false;
+ m_disabled = false;
m_config_string = NULL; // set by option parser
}
void init()
@@ -156,8 +158,13 @@ public:
int ntok = sscanf(m_config_string,"%u:%u:%u:%c:%c:%c,%c:%u:%u,%u:%u",
&m_nset, &m_line_sz, &m_assoc, &rp, &wp, &ap,
&mshr_type,&m_mshr_entries,&m_mshr_max_merge,&m_miss_queue_size,&m_result_fifo_entries);
- if ( ntok < 10 )
+ if ( ntok < 10 ) {
+ if ( !strcmp(m_config_string,"none") ) {
+ m_disabled = true;
+ return;
+ }
exit_parse_error();
+ }
switch (rp) {
case 'L': m_replacement_policy = LRU; break;
case 'F': m_replacement_policy = FIFO; break;
@@ -183,6 +190,7 @@ public:
m_nset_log2 = LOGB2(m_nset);
m_valid = true;
}
+ bool disabled() const { return m_disabled;}
unsigned get_line_sz() const
{
assert( m_valid );
@@ -224,6 +232,7 @@ private:
}
bool m_valid;
+ bool m_disabled;
unsigned m_line_sz;
unsigned m_line_sz_log2;
unsigned m_nset;
@@ -252,6 +261,7 @@ private:
friend class tag_array;
friend class read_only_cache;
friend class tex_cache;
+ friend class data_cache;
};
class tag_array {
@@ -261,10 +271,14 @@ public:
enum cache_request_status probe( new_addr_type addr, unsigned &idx ) const;
enum cache_request_status access( new_addr_type addr, unsigned time, unsigned &idx );
+ enum cache_request_status access( new_addr_type addr, unsigned time, unsigned &idx, bool &wb, cache_block_t &evicted );
void fill( new_addr_type addr, unsigned time );
void fill( unsigned idx, unsigned time );
+ unsigned size() const { return m_config.get_num_lines();}
+ cache_block_t &get_block(unsigned idx) { return m_lines[idx];}
+
void flush(); // flash invalidate all entries
void new_window();
@@ -408,12 +422,12 @@ public:
{
m_name = name;
assert(config.m_mshr_type == ASSOC);
- assert(config.m_write_policy == READ_ONLY);
m_memport=memport;
}
// access cache: returns RESERVATION_FAIL if request could not be accepted (for any reason)
virtual enum cache_request_status access( new_addr_type addr, mem_fetch *mf, unsigned time ) {
+ assert(m_config.m_write_policy == READ_ONLY);
new_addr_type block_addr = m_config.block_addr(addr);
unsigned cache_index = (unsigned)-1;
enum cache_request_status status = m_tag_array.probe(block_addr,cache_index);
@@ -499,7 +513,8 @@ public:
fprintf(fp,"\n");
}
-private:
+
+ protected:
std::string m_name;
const cache_config &m_config;
tag_array m_tag_array;
@@ -521,13 +536,100 @@ private:
unsigned m_cache_index;
unsigned m_data_size;
};
-
+
typedef std::map<mem_fetch*,extra_mf_fields> extra_mf_fields_lookup;
extra_mf_fields_lookup m_extra_mf_fields;
};
-
+// This is meant to model the first level data cache in Fermi.
+// It is write-evict (global) or write-back (local) at the granularity
+// of individual blocks (the policy used in fermi according to the CUDA manual)
+
+class data_cache : public read_only_cache {
+public:
+ data_cache( const char *name, const cache_config &config, int core_id, int type_id, mem_fetch_interface *memport, mem_fetch_allocator *mfcreator )
+ : read_only_cache(name,config,core_id,type_id,memport)
+ {
+ m_memfetch_creator=mfcreator;
+ }
+ virtual enum cache_request_status access( new_addr_type addr, mem_fetch *mf, unsigned time ) {
+ bool wr = mf->get_is_write();
+ enum mem_access_type type = mf->get_access_type();
+ bool evict = (type == GLOBAL_ACC_W); // evict a line that hits on global memory write
+
+ new_addr_type block_addr = m_config.block_addr(addr);
+ unsigned cache_index = (unsigned)-1;
+ enum cache_request_status status = m_tag_array.probe(block_addr,cache_index);
+ if ( status == HIT ) {
+ if ( evict ) {
+ if ( m_miss_queue.size() >= m_config.m_miss_queue_size )
+ return RESERVATION_FAIL; // cannot handle request this cycle
+
+ // generate writeback request (this assumes we merge global write with this request)
+ // this does not ensure coherence since multiple writes to block could occcur at same
+ // time on different shader cores
+ cache_block_t &block = m_tag_array.get_block(cache_index);
+ mem_fetch *wb = m_memfetch_creator->alloc(block_addr,L1_WRBK_ACC,m_config.get_line_sz(),true);
+ m_miss_queue.push_back(wb);
+
+ // invalidate block
+ block.m_status = INVALID;
+ } else {
+ m_tag_array.access(block_addr,time,cache_index); // update LRU state
+ if ( wr ) {
+ assert( type == LOCAL_ACC_W );
+ // treated as write back...
+ cache_block_t &block = m_tag_array.get_block(cache_index);
+ block.m_status = MODIFIED;
+ }
+ }
+ return HIT;
+ } else if ( status != RESERVATION_FAIL ) {
+ if ( wr ) {
+ if ( m_miss_queue.size() >= m_config.m_miss_queue_size )
+ return RESERVATION_FAIL; // cannot handle request this cycle
+
+ // on miss, generate write through (no write buffering -- too many threads for that)
+ m_miss_queue.push_back(mf);
+ return MISS;
+ } else {
+ if ( (m_miss_queue.size()+1) >= m_config.m_miss_queue_size )
+ return RESERVATION_FAIL; // cannot handle request this cycle (might need to generate two requests)
+
+ bool do_miss = false;
+ bool wb = false;
+ cache_block_t evicted;
+
+ bool mshr_hit = m_mshrs.probe(block_addr);
+ bool mshr_avail = !m_mshrs.full(block_addr);
+ if ( mshr_hit && mshr_avail ) {
+ m_tag_array.access(addr,time,cache_index,wb,evicted);
+ m_mshrs.add(block_addr,mf);
+ do_miss = true;
+ } else if ( !mshr_hit && mshr_avail && (m_miss_queue.size() < m_config.m_miss_queue_size) ) {
+ m_tag_array.access(addr,time,cache_index,wb,evicted);
+ m_mshrs.add(block_addr,mf);
+ m_extra_mf_fields[mf] = extra_mf_fields(block_addr,cache_index, mf->get_data_size());
+ mf->set_data_size( m_config.get_line_sz() );
+ m_miss_queue.push_back(mf);
+ do_miss = true;
+ }
+ if( wb ) {
+ mem_fetch *wb = m_memfetch_creator->alloc(evicted.m_block_addr,L1_WRBK_ACC,m_config.get_line_sz(),true);
+ m_miss_queue.push_back(wb);
+ }
+ if( do_miss )
+ return MISS;
+ }
+ }
+
+ return RESERVATION_FAIL;
+ }
+ private:
+ mem_fetch_allocator *m_memfetch_creator;
+};
+
// See the following paper to understand this cache model:
//
// Igehy, et al., Prefetching in a Texture Cache Architecture,
@@ -537,11 +639,11 @@ class tex_cache : public cache_t {
public:
tex_cache( const char *name, const cache_config &config, int core_id, int type_id, mem_fetch_interface *memport )
: m_config(config),
- m_tags(config,core_id,type_id),
- m_fragment_fifo(config.m_fragment_fifo_entries),
- m_request_fifo(config.m_request_fifo_entries),
- m_rob(config.m_rob_entries),
- m_result_fifo(config.m_result_fifo_entries)
+ m_tags(config,core_id,type_id),
+ m_fragment_fifo(config.m_fragment_fifo_entries),
+ m_request_fifo(config.m_request_fifo_entries),
+ m_rob(config.m_rob_entries),
+ m_result_fifo(config.m_result_fifo_entries)
{
m_name = name;
assert(config.m_mshr_type == TEX_FIFO);
@@ -555,11 +657,10 @@ public:
// otherwise returns HIT_RESERVED or MISS; NOTE: *never* returns HIT
// since unlike a normal CPU cache, a "HIT" in texture cache does not
// mean the data is ready (still need to get through fragment fifo)
- enum cache_request_status access( new_addr_type addr, mem_fetch *mf, unsigned time )
- {
- if( m_fragment_fifo.full() || m_request_fifo.full() || m_rob.full() )
+ enum cache_request_status access( new_addr_type addr, mem_fetch *mf, unsigned time ) {
+ if ( m_fragment_fifo.full() || m_request_fifo.full() || m_rob.full() )
return RESERVATION_FAIL;
-
+
// at this point, we will accept the request : access tags and immediately allocate line
new_addr_type block_addr = m_config.block_addr(addr);
unsigned cache_index = (unsigned)-1;
@@ -567,7 +668,7 @@ public:
assert( status != RESERVATION_FAIL );
assert( status != HIT_RESERVED ); // as far as tags are concerned: HIT or MISS
m_fragment_fifo.push( fragment_entry(mf,cache_index,status==MISS,mf->get_data_size()) );
- if( status == MISS ) {
+ if ( status == MISS ) {
// we need to send a memory request...
unsigned rob_index = m_rob.push( rob_entry(cache_index, mf, block_addr) );
m_extra_mf_fields[mf] = extra_mf_fields(rob_index);
@@ -592,15 +693,15 @@ public:
}
}
// read ready lines from cache
- if( !m_fragment_fifo.empty() && !m_result_fifo.full() ) {
+ if ( !m_fragment_fifo.empty() && !m_result_fifo.full() ) {
const fragment_entry &e = m_fragment_fifo.peek();
- if( e.m_miss ) {
+ if ( e.m_miss ) {
// check head of reorder buffer to see if data is back from memory
unsigned rob_index = m_rob.next_pop_index();
const rob_entry &r = m_rob.peek(rob_index);
assert( r.m_request == e.m_request );
assert( r.m_block_addr == m_config.block_addr(e.m_request->get_addr()) );
- if( r.m_ready ) {
+ if ( r.m_ready ) {
assert( r.m_index == e.m_cache_index );
m_cache[r.m_index].m_valid = true;
m_cache[r.m_index].m_block_addr = r.m_block_addr;
@@ -608,7 +709,7 @@ public:
m_rob.pop();
m_fragment_fifo.pop();
}
- } else {
+ } else {
// hit:
assert( m_cache[e.m_cache_index].m_valid );
assert( m_cache[e.m_cache_index].m_block_addr = m_config.block_addr(e.m_request->get_addr()) );
@@ -652,20 +753,20 @@ public:
fprintf(fp,"fragment fifo entries = %u / %u\n", m_fragment_fifo.size(), m_fragment_fifo.capacity() );
fprintf(fp,"reorder buffer entries = %u / %u\n", m_rob.size(), m_rob.capacity() );
fprintf(fp,"request fifo entries = %u / %u\n", m_request_fifo.size(), m_request_fifo.capacity() );
- if( !m_rob.empty() )
+ if ( !m_rob.empty() )
fprintf(fp,"reorder buffer contents:\n");
- for( int n=m_rob.size()-1; n>=0; n-- ) {
+ for ( int n=m_rob.size()-1; n>=0; n-- ) {
unsigned index = (m_rob.next_pop_index() + n)%m_rob.capacity();
const rob_entry &r = m_rob.peek(index);
fprintf(fp, "tex rob[%3d] : %s ", index, (r.m_ready?"ready ":"pending") );
- if( r.m_ready )
+ if ( r.m_ready )
fprintf(fp,"@%6u", r.m_time );
- else
+ else
fprintf(fp," ");
fprintf(fp,"[idx=%4u]",r.m_index);
r.m_request->print(fp,false);
}
- if( !m_fragment_fifo.empty() ) {
+ if ( !m_fragment_fifo.empty() ) {
fprintf(fp,"fragment fifo (oldest) :");
fragment_entry &f = m_fragment_fifo.peek();
fprintf(fp,"%s: ", f.m_miss?"miss":"hit ");
@@ -673,7 +774,8 @@ public:
}
}
-private:
+
+ private:
std::string m_name;
const cache_config &m_config;
@@ -693,7 +795,7 @@ private:
};
struct rob_entry {
- rob_entry() { m_ready = false; m_time=0; m_request=NULL; }
+ rob_entry() { m_ready = false; m_time=0; m_request=NULL;}
rob_entry( unsigned i, mem_fetch *mf, new_addr_type a )
{
m_ready=false;
@@ -710,7 +812,7 @@ private:
};
struct data_block {
- data_block() { m_valid = false; }
+ data_block() { m_valid = false;}
bool m_valid;
new_addr_type m_block_addr;
};
@@ -726,10 +828,10 @@ private:
m_tail=0;
m_data = new T[size];
}
- bool full() const { return m_num == m_size; }
- bool empty() const { return m_num == 0; }
- unsigned size() const { return m_num; }
- unsigned capacity() const { return m_size; }
+ bool full() const { return m_num == m_size;}
+ bool empty() const { return m_num == 0;}
+ unsigned size() const { return m_num;}
+ unsigned capacity() const { return m_size;}
unsigned push( const T &e )
{
assert(!full());
@@ -764,8 +866,8 @@ private:
return m_tail;
}
private:
- void inc_head() { m_head = (m_head+1)%m_size; m_num++; }
- void inc_tail() { assert(m_num>0); m_tail = (m_tail+1)%m_size; m_num--; }
+ void inc_head() { m_head = (m_head+1)%m_size; m_num++;}
+ void inc_tail() { assert(m_num>0); m_tail = (m_tail+1)%m_size; m_num--;}
unsigned m_head; // next entry goes here
unsigned m_tail; // oldest entry found here
@@ -793,7 +895,7 @@ private:
bool m_valid;
unsigned m_rob_index;
};
-
+
typedef std::map<mem_fetch*,extra_mf_fields> extra_mf_fields_lookup;
extra_mf_fields_lookup m_extra_mf_fields;
diff --git a/src/gpgpu-sim/gpu-sim.cc b/src/gpgpu-sim/gpu-sim.cc
index fc93339..359a54d 100644
--- a/src/gpgpu-sim/gpu-sim.cc
+++ b/src/gpgpu-sim/gpu-sim.cc
@@ -136,7 +136,8 @@ void memory_config::reg_options(class OptionParser * opp)
"Use a ideal L2 cache that always hit",
"0");
option_parser_register(opp, "-gpgpu_cache:dl2", OPT_CSTR, &m_L2_config.m_config_string,
- "unified banked L2 data cache config, i.e., {<nsets>:<bsize>:<assoc>:<repl>|none}; disabled by default",
+ "unified banked L2 data cache config "
+ " {<nsets>:<bsize>:<assoc>:<rep>:<wr>:<alloc>,<mshr>:<N>:<merge>,<mq>}",
NULL);
option_parser_register(opp, "-gpgpu_n_mem", OPT_UINT32, &m_n_mem,
"number of memory modules (e.g. memory controllers) in gpu",
@@ -174,11 +175,17 @@ void shader_core_config::reg_options(class OptionParser * opp)
"per-shader L1 texture cache (READ-ONLY) config, i.e., {<nsets>:<linesize>:<assoc>:<repl>|none}",
"512:64:2:L:R:m");
option_parser_register(opp, "-gpgpu_const_cache:l1", OPT_CSTR, &m_L1C_config.m_config_string,
- "per-shader L1 constant memory cache (READ-ONLY) config, i.e., {<nsets>:<linesize>:<assoc>:<repl>|none}",
- "64:64:2:L:R:f");
+ "per-shader L1 constant memory cache (READ-ONLY) config "
+ " {<nsets>:<bsize>:<assoc>:<rep>:<wr>:<alloc>,<mshr>:<N>:<merge>,<mq>}",
+ "64:64:2:L:R:f,A:2:32,4" );
option_parser_register(opp, "-gpgpu_cache:il1", OPT_CSTR, &m_L1I_config.m_config_string,
- "shader L1 instruction cache config, i.e., {<nsets>:<bsize>:<assoc>:<repl>|none}",
- "4:256:4:L:R:f");
+ "shader L1 instruction cache config "
+ " {<nsets>:<bsize>:<assoc>:<rep>:<wr>:<alloc>,<mshr>:<N>:<merge>,<mq>}",
+ "4:256:4:L:R:f,A:2:32,4" );
+ option_parser_register(opp, "-gpgpu_cache:dl1", OPT_CSTR, &m_L1D_config.m_config_string,
+ "per-shader L1 data cache config "
+ " {<nsets>:<bsize>:<assoc>:<rep>:<wr>:<alloc>,<mshr>:<N>:<merge>,<mq>|none}",
+ "none" );
option_parser_register(opp, "-gpgpu_perfect_mem", OPT_BOOL, &gpgpu_perfect_mem,
"enable perfect memory mode (no cache miss)",
"0");
@@ -501,7 +508,7 @@ unsigned int gpgpu_sim::run_gpu_sim()
if (m_config.gpu_deadlock_detect && gpu_deadlock) {
fflush(stdout);
- printf("GPGPU-Sim uArch: ERROR ** deadlock detected: last writeback core %u @ gpu_sim_cycle %u (+ gpu_tot_sim_cycle %u) (%u cycles ago)\n",
+ printf("\n\nGPGPU-Sim uArch: ERROR ** deadlock detected: last writeback core %u @ gpu_sim_cycle %u (+ gpu_tot_sim_cycle %u) (%u cycles ago)\n",
gpu_sim_insn_last_update_sid,
(unsigned) gpu_sim_insn_last_update, (unsigned) (gpu_tot_sim_cycle-gpu_sim_cycle),
(unsigned) (gpu_sim_cycle - gpu_sim_insn_last_update ));
@@ -526,8 +533,10 @@ unsigned int gpgpu_sim::run_gpu_sim()
if( busy )
printf("GPGPU-Sim uArch DEADLOCK: memory partition %u busy\n", i );
}
- if( icnt_busy() )
+ if( icnt_busy() ) {
printf("GPGPU-Sim uArch DEADLOCK: iterconnect contains traffic\n");
+ display_icnt_state( stdout );
+ }
printf("\nRe-run the simulator in gdb and use debug routines in .gdbinit to debug this\n");
fflush(stdout);
abort();
diff --git a/src/gpgpu-sim/icnt_wrapper.h b/src/gpgpu-sim/icnt_wrapper.h
index d37755a..b1ba991 100644
--- a/src/gpgpu-sim/icnt_wrapper.h
+++ b/src/gpgpu-sim/icnt_wrapper.h
@@ -67,6 +67,8 @@
#ifndef ICNT_WRAPPER_H
#define ICNT_WRAPPER_H
+#include <stdio.h>
+
// functional interface to the interconnect
typedef bool (*icnt_has_buffer_p)(unsigned input, unsigned int size);
typedef void (*icnt_push_p)(unsigned input, unsigned output, void* data, unsigned int size);
@@ -90,5 +92,6 @@ enum network_mode {
void icnt_init( unsigned int n_shader, unsigned int n_mem );
void icnt_reg_options( class OptionParser * opp );
+void display_icnt_state( FILE *fp );
#endif
diff --git a/src/gpgpu-sim/l2cache.cc b/src/gpgpu-sim/l2cache.cc
index 45b8eef..ff09d18 100644
--- a/src/gpgpu-sim/l2cache.cc
+++ b/src/gpgpu-sim/l2cache.cc
@@ -283,8 +283,13 @@ void memory_partition_unit::dram_cycle()
if ( !m_dram_L2_queue->full() ) {
mem_fetch* mf = m_dram->pop();
if (mf) {
- m_dram_L2_queue->push(mf);
- mf->set_status(IN_PARTITION_DRAM_TO_L2_QUEUE,gpu_sim_cycle+gpu_tot_sim_cycle);
+ if( mf->get_access_type() == L1_WRBK_ACC ) {
+ m_request_tracker.erase(mf);
+ delete mf;
+ } else {
+ m_dram_L2_queue->push(mf);
+ mf->set_status(IN_PARTITION_DRAM_TO_L2_QUEUE,gpu_sim_cycle+gpu_tot_sim_cycle);
+ }
}
}
m_dram->cycle();
diff --git a/src/gpgpu-sim/shader.cc b/src/gpgpu-sim/shader.cc
index 8adcf1b..303d736 100644
--- a/src/gpgpu-sim/shader.cc
+++ b/src/gpgpu-sim/shader.cc
@@ -136,15 +136,16 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu,
}
m_icnt = new shader_memory_interface(this,cluster);
+ m_mem_fetch_allocator = new shader_core_mem_fetch_allocator(shader_id,tpc_id,mem_config);
// fetch
m_last_warp_fetched = 0;
m_last_warp_issued = 0;
#define STRSIZE 1024
- char L1I_name[STRSIZE];
- snprintf(L1I_name, STRSIZE, "L1I_%03d", m_sid);
- m_L1I = new read_only_cache(L1I_name,m_config->m_L1I_config,m_sid,get_shader_instruction_cache_id(),m_icnt);
+ char name[STRSIZE];
+ snprintf(name, STRSIZE, "L1I_%03d", m_sid);
+ m_L1I = new read_only_cache( name,m_config->m_L1I_config,m_sid,get_shader_instruction_cache_id(),m_icnt);
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];
@@ -178,7 +179,7 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu,
m_dispatch_port[1] = ID_OC_SFU;
m_issue_port[1] = OC_EX_SFU;
- m_ldst_unit = new ldst_unit( m_icnt, this, &m_operand_collector, m_scoreboard, config, mem_config, stats, shader_id, tpc_id );
+ m_ldst_unit = new ldst_unit( m_icnt, m_mem_fetch_allocator, this, &m_operand_collector, m_scoreboard, config, mem_config, stats, shader_id, tpc_id );
m_fu[2] = m_ldst_unit;
m_dispatch_port[2] = ID_OC_MEM;
m_issue_port[2] = OC_EX_MEM;
@@ -530,6 +531,9 @@ 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);
+
+ // TODO: replace with use of allocator
+ // mem_fetch *mf = m_mem_fetch_allocator->alloc()
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*/,
@@ -734,20 +738,6 @@ void shader_core_ctx::execute()
}
}
-mem_fetch *ldst_unit::create_data_mem_fetch(const warp_inst_t &inst, const mem_access_t &access)
-{
- warp_inst_t inst_copy = inst;
- 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;
-}
-
void shader_core_ctx::writeback()
{
warp_inst_t *&pipe_reg = m_pipeline_reg[EX_WB];
@@ -784,7 +774,7 @@ mem_stage_stall_type ldst_unit::process_memory_access_queue( cache_t *cache, war
return result;
const mem_access_t &access = inst.accessq_back();
- mem_fetch *mf = create_data_mem_fetch(inst,inst.accessq_back());
+ mem_fetch *mf = m_mf_allocator->alloc(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 ) {
@@ -801,7 +791,8 @@ mem_stage_stall_type ldst_unit::process_memory_access_queue( cache_t *cache, war
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() )
result = BK_CONF;
@@ -852,19 +843,27 @@ bool ldst_unit::memory_cycle( warp_inst_t &inst, mem_stage_stall_type &stall_rea
mem_stage_stall_type stall_cond = NO_RC_FAIL;
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;
+
+ assert( CACHE_UNDEFINED != inst.cache_op );
+
+ if( CACHE_GLOBAL == inst.cache_op || (m_L1D == NULL) ) {
+ // bypass L1 cache
+ if( m_icnt->full(size, inst.is_store()) ) {
+ stall_cond = ICNT_RC_FAIL;
+ } else {
+ mem_fetch *mf = m_mf_allocator->alloc(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() );
+ }
} 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() );
+ stall_cond = process_memory_access_queue(m_L1D,inst);
}
if( !inst.accessq_empty() )
stall_cond = COAL_STALL;
@@ -926,6 +925,7 @@ pipelined_simd_unit::pipelined_simd_unit( warp_inst_t **result_port, const shade
}
ldst_unit::ldst_unit( shader_memory_interface *icnt,
+ shader_core_mem_fetch_allocator *mf_allocator,
shader_core_ctx *core,
opndcoll_rfu_t *operand_collector,
Scoreboard *scoreboard,
@@ -935,8 +935,9 @@ ldst_unit::ldst_unit( shader_memory_interface *icnt,
unsigned sid,
unsigned tpc ) : pipelined_simd_unit(NULL,config,3), m_next_wb(config)
{
- m_memory_config = mem_config;
+ m_memory_config = mem_config;
m_icnt = icnt;
+ m_mf_allocator=mf_allocator;
m_core = core;
m_operand_collector = operand_collector;
m_scoreboard = scoreboard;
@@ -946,12 +947,17 @@ ldst_unit::ldst_unit( shader_memory_interface *icnt,
#define STRSIZE 1024
char L1T_name[STRSIZE];
char L1C_name[STRSIZE];
+ char L1D_name[STRSIZE];
snprintf(L1T_name, STRSIZE, "L1T_%03d", m_sid);
snprintf(L1C_name, STRSIZE, "L1C_%03d", m_sid);
+ snprintf(L1D_name, STRSIZE, "L1D_%03d", m_sid);
m_L1T = new tex_cache(L1T_name,m_config->m_L1T_config,m_sid,get_shader_texture_cache_id(),icnt);
m_L1C = new read_only_cache(L1C_name,m_config->m_L1C_config,m_sid,get_shader_constant_cache_id(),icnt);
+ m_L1D = NULL;
+ if( !m_config->m_L1D_config.disabled() )
+ m_L1D = new data_cache(L1D_name,m_config->m_L1D_config,m_sid,get_shader_normal_cache_id(),m_icnt,m_mf_allocator);
m_mem_rc = NO_RC_FAIL;
- m_num_writeback_clients=4; // = shared memory, global/local, L1T, L1C
+ m_num_writeback_clients=5; // = shared memory, global/local (uncached), L1D, L1T, L1C
m_writeback_arb = 0;
m_next_global=NULL;
}
@@ -1014,6 +1020,13 @@ void ldst_unit::writeback()
m_next_global = NULL;
}
break;
+ case 4:
+ if( m_L1D && m_L1D->access_ready() ) {
+ mem_fetch *mf = m_L1D->next_access();
+ m_next_wb = mf->get_inst();
+ delete mf;
+ }
+ break;
default: abort();
}
}
@@ -1046,7 +1059,10 @@ void ldst_unit::cycle()
m_response_fifo.pop_front();
delete mf;
} else {
- if( m_next_global == NULL ) {
+ if( mf->get_inst().cache_op != CACHE_GLOBAL && m_L1D ) {
+ m_L1D->fill(mf,gpu_sim_cycle+gpu_tot_sim_cycle);
+ m_response_fifo.pop_front();
+ } else if( m_next_global == NULL ) {
mf->set_status(IN_SHADER_FETCHED,gpu_sim_cycle+gpu_tot_sim_cycle);
m_response_fifo.pop_front();
m_next_global = mf;
@@ -1057,6 +1073,7 @@ void ldst_unit::cycle()
m_L1T->cycle();
m_L1C->cycle();
+ if( m_L1D ) m_L1D->cycle();
warp_inst_t &pipe_reg = *m_dispatch_reg;
enum mem_stage_stall_type rc_fail = NO_RC_FAIL;
@@ -1084,10 +1101,10 @@ void ldst_unit::cycle()
m_dispatch_reg->clear();
}
} else {
- if( pipe_reg.active_count() > 0 ) {
- if( !m_operand_collector->writeback(pipe_reg) )
- return;
- }
+ //if( pipe_reg.active_count() > 0 ) {
+ // if( !m_operand_collector->writeback(pipe_reg) )
+ // return;
+ //}
bool pending_requests=false;
for( unsigned r=0; r<4; r++ ) {
@@ -1293,6 +1310,12 @@ void ldst_unit::print(FILE *fout) const
}
m_L1C->display_state(fout);
m_L1T->display_state(fout);
+ m_L1D->display_state(fout);
+ fprintf(fout,"LD/ST response FIFO (occupancy = %zu):\n", m_response_fifo.size() );
+ for( std::list<mem_fetch*>::const_iterator i=m_response_fifo.begin(); i != m_response_fifo.end(); i++ ) {
+ const mem_fetch *mf = *i;
+ mf->print(fout);
+ }
}
void shader_core_ctx::display_pipeline(FILE *fout, int print_mem, int mask ) const
@@ -2050,6 +2073,7 @@ void simt_core_cluster::icnt_inject_request_packet(class mem_fetch *mf)
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;
+ case L1_WRBK_ACC: m_stats->gpgpu_n_mem_write_global++; break;
default: assert(0);
}
unsigned destination = mf->get_tlx_addr().chip;
@@ -2101,4 +2125,12 @@ void simt_core_cluster::get_pdom_stack_top_info( unsigned sid, unsigned tid, uns
void simt_core_cluster::display_pipeline( unsigned sid, FILE *fout, int print_mem, int mask )
{
m_core[m_config->sid_to_cid(sid)]->display_pipeline(fout,print_mem,mask);
+
+ fprintf(fout,"\n");
+ fprintf(fout,"Cluster %u pipeline state\n", m_cluster_id );
+ fprintf(fout,"Response FIFO (occupancy = %zu):\n", m_response_fifo.size() );
+ for( std::list<mem_fetch*>::const_iterator i=m_response_fifo.begin(); i != m_response_fifo.end(); i++ ) {
+ const mem_fetch *mf = *i;
+ mf->print(fout);
+ }
}
diff --git a/src/gpgpu-sim/shader.h b/src/gpgpu-sim/shader.h
index e85c210..bfe0cc2 100644
--- a/src/gpgpu-sim/shader.h
+++ b/src/gpgpu-sim/shader.h
@@ -831,11 +831,13 @@ public:
class simt_core_cluster;
class shader_memory_interface;
+class shader_core_mem_fetch_allocator;
class cache_t;
class ldst_unit: public pipelined_simd_unit {
public:
ldst_unit( shader_memory_interface *icnt,
+ shader_core_mem_fetch_allocator *mf_allocator,
shader_core_ctx *core,
opndcoll_rfu_t *operand_collector,
Scoreboard *scoreboard,
@@ -875,16 +877,17 @@ private:
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(const warp_inst_t &inst, const mem_access_t &access);
const memory_config *m_memory_config;
- class shader_memory_interface *m_icnt;
+ shader_memory_interface *m_icnt;
+ shader_core_mem_fetch_allocator *m_mf_allocator;
class shader_core_ctx *m_core;
unsigned m_sid;
unsigned m_tpc;
tex_cache *m_L1T; // texture cache
read_only_cache *m_L1C; // constant cache
+ data_cache *m_L1D; // data cache
std::map<unsigned/*warp_id*/, std::map<unsigned/*regnum*/,unsigned/*count*/> > m_pending_writes;
std::list<mem_fetch*> m_response_fifo;
opndcoll_rfu_t *m_operand_collector;
@@ -929,6 +932,7 @@ struct shader_core_config : public core_config
m_L1I_config.init();
m_L1T_config.init();
m_L1C_config.init();
+ m_L1D_config.init();
gpgpu_cache_texl1_linesize = m_L1T_config.get_line_sz();
gpgpu_cache_constl1_linesize = m_L1C_config.get_line_sz();
m_valid = true;
@@ -951,6 +955,7 @@ struct shader_core_config : public core_config
cache_config m_L1I_config;
cache_config m_L1T_config;
cache_config m_L1C_config;
+ cache_config m_L1D_config;
bool gpgpu_dwf_reg_bankconflict;
int gpgpu_operand_collector_num_units_sp;
@@ -1039,6 +1044,47 @@ private:
friend class simt_core_cluster;
};
+class shader_core_mem_fetch_allocator : public mem_fetch_allocator {
+public:
+ shader_core_mem_fetch_allocator( unsigned core_id, unsigned cluster_id, const memory_config *config )
+ {
+ m_core_id = core_id;
+ m_cluster_id = cluster_id;
+ m_memory_config = config;
+ }
+ mem_fetch *alloc( new_addr_type addr, mem_access_type type, unsigned size, bool wr ) const
+ {
+ mem_access_t access( type, addr, size, wr );
+ mem_fetch *mf = new mem_fetch( access,
+ NULL,
+ wr?WRITE_PACKET_SIZE:READ_PACKET_SIZE,
+ -1,
+ m_core_id,
+ m_cluster_id,
+ m_memory_config );
+ return mf;
+ }
+
+ mem_fetch *alloc( const warp_inst_t &inst, const mem_access_t &access ) const
+ {
+ warp_inst_t inst_copy = inst;
+ 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_core_id,
+ m_cluster_id,
+ m_memory_config);
+ return mf;
+ }
+
+private:
+ unsigned m_core_id;
+ unsigned m_cluster_id;
+ const memory_config *m_memory_config;
+};
+
class shader_core_ctx : public core_t {
public:
// creator:
@@ -1135,6 +1181,7 @@ private:
// interconnect interface
shader_memory_interface *m_icnt;
+ shader_core_mem_fetch_allocator *m_mem_fetch_allocator;
// fetch
read_only_cache *m_L1I; // instruction cache
diff --git a/src/intersim/interconnect_interface.cpp b/src/intersim/interconnect_interface.cpp
index 3059b44..0c155f1 100644
--- a/src/intersim/interconnect_interface.cpp
+++ b/src/intersim/interconnect_interface.cpp
@@ -512,6 +512,28 @@ unsigned interconnect_busy()
return 0;
}
+void display_icnt_state( FILE *fp )
+{
+ fprintf(fp,"GPGPU-Sim uArch: interconnect busy state\n");
+ for (unsigned i=0; i<net_c;i++) {
+ if (traffic[i]->_measured_in_flight)
+ fprintf(fp," Network %u has %u _measured_in_flight\n", i, traffic[i]->_measured_in_flight );
+ }
+
+ for (unsigned i=0 ;i<(_n_shader+_n_mem);i++ ) {
+ if( !traffic[0]->_partial_packets[i] [0].empty() )
+ fprintf(fp," Network 0 has nonempty _partial_packets[%u][0]\n", i);
+ if ( doub_net && !traffic[1]->_partial_packets[i] [0].empty() )
+ fprintf(fp," Network 1 has nonempty _partial_packets[%u][0]\n", i);
+ for (unsigned j=0;j<g_num_vcs;j++ ) {
+ if( !ejection_buf[i][j].empty() )
+ fprintf(fp," ejection_buf[%u][%u] is non-empty\n", i, j);
+ if( clock_boundary_buf[i][j].has_packet() )
+ fprintf(fp," clock_boundary_buf[%u][%u] has packet\n", i, j );
+ }
+ }
+}
+
//create buffers for src_n nodes
void create_buf(int src_n,int warp_n,int vc_n)
{