summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTor Aamodt <[email protected]>2010-11-28 20:48:33 -0800
committerTor Aamodt <[email protected]>2010-11-28 20:48:33 -0800
commit6e06c2e1de8c51a88845b7f35cea219dca7456f2 (patch)
tree28b3daed248f3f4dca9ca49f9d939f6edae10238 /src
parent23d096dd1f1d4f0387087ffff0605fbf349556d2 (diff)
enabling L2 data cache... it is write through, write evict like L1.
[git-p4: depot-paths = "//depot/gpgpu_sim_research/fermi/distribution/": change = 8154]
Diffstat (limited to 'src')
-rw-r--r--src/gpgpu-sim/dram.cc2
-rw-r--r--src/gpgpu-sim/gpu-cache.cc18
-rw-r--r--src/gpgpu-sim/gpu-cache.h70
-rw-r--r--src/gpgpu-sim/gpu-sim.cc17
-rw-r--r--src/gpgpu-sim/gpu-sim.h1
-rw-r--r--src/gpgpu-sim/l2cache.cc64
-rw-r--r--src/gpgpu-sim/l2cache.h22
-rw-r--r--src/gpgpu-sim/mem_fetch.cc2
-rw-r--r--src/gpgpu-sim/mem_fetch.h27
-rw-r--r--src/gpgpu-sim/shader.cc127
-rw-r--r--src/gpgpu-sim/shader.h35
-rw-r--r--src/gpgpu-sim/visualizer.cc8
12 files changed, 310 insertions, 83 deletions
diff --git a/src/gpgpu-sim/dram.cc b/src/gpgpu-sim/dram.cc
index 9227310..bd6758b 100644
--- a/src/gpgpu-sim/dram.cc
+++ b/src/gpgpu-sim/dram.cc
@@ -237,7 +237,7 @@ void dram_t::cycle()
if (cmd->dqbytes >= cmd->nbytes) {
mem_fetch *data = cmd->data;
data->set_status(IN_PARTITION_MC_RETURNQ,gpu_sim_cycle+gpu_tot_sim_cycle);
- data->set_type(REPLY_DATA);
+ data->set_reply();
returnq->push(data);
delete cmd;
}
diff --git a/src/gpgpu-sim/gpu-cache.cc b/src/gpgpu-sim/gpu-cache.cc
index 594e683..202511d 100644
--- a/src/gpgpu-sim/gpu-cache.cc
+++ b/src/gpgpu-sim/gpu-cache.cc
@@ -241,3 +241,21 @@ void tag_array::print( FILE *stream, unsigned &total_access, unsigned &total_mis
total_misses+=m_miss;
total_access+=m_access;
}
+
+bool was_write_sent( const std::list<cache_event> &events )
+{
+ for( std::list<cache_event>::const_iterator e=events.begin(); e!=events.end(); e++ ) {
+ if( *e == WRITE_REQUEST_SENT )
+ return true;
+ }
+ return false;
+}
+
+bool was_read_sent( const std::list<cache_event> &events )
+{
+ for( std::list<cache_event>::const_iterator e=events.begin(); e!=events.end(); e++ ) {
+ if( *e == READ_REQUEST_SENT )
+ return true;
+ }
+ return false;
+}
diff --git a/src/gpgpu-sim/gpu-cache.h b/src/gpgpu-sim/gpu-cache.h
index 6b93d85..64ebdfa 100644
--- a/src/gpgpu-sim/gpu-cache.h
+++ b/src/gpgpu-sim/gpu-cache.h
@@ -88,6 +88,12 @@ enum cache_request_status {
RESERVATION_FAIL
};
+enum cache_event {
+ WRITE_BACK_REQUEST_SENT,
+ READ_REQUEST_SENT,
+ WRITE_REQUEST_SENT
+};
+
struct cache_block_t {
cache_block_t()
{
@@ -412,22 +418,29 @@ private:
class cache_t {
public:
virtual ~cache_t() {}
- virtual enum cache_request_status access( new_addr_type addr, mem_fetch *mf, unsigned time ) = 0;
+ virtual enum cache_request_status access( new_addr_type addr, mem_fetch *mf, unsigned time, std::list<cache_event> &events ) = 0;
};
+bool was_write_sent( const std::list<cache_event> &events );
+bool was_read_sent( const std::list<cache_event> &events );
+
class read_only_cache : public cache_t {
public:
- read_only_cache( const char *name, const cache_config &config, int core_id, int type_id, mem_fetch_interface *memport )
+ read_only_cache( const char *name, const cache_config &config, int core_id, int type_id, mem_fetch_interface *memport,
+ enum mem_fetch_status status )
: m_config(config), m_tag_array(config,core_id,type_id), m_mshrs(config.m_mshr_entries,config.m_mshr_max_merge)
{
m_name = name;
assert(config.m_mshr_type == ASSOC);
m_memport=memport;
+ m_miss_queue_status = status;
}
// 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 ) {
+ virtual enum cache_request_status access( new_addr_type addr, mem_fetch *mf, unsigned time, std::list<cache_event> &events )
+ {
assert(m_config.m_write_policy == READ_ONLY);
+ assert(!mf->get_is_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);
@@ -448,6 +461,8 @@ public:
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);
+ mf->set_status(m_miss_queue_status,time);
+ events.push_back(READ_REQUEST_SENT);
return MISS;
}
}
@@ -482,6 +497,12 @@ public:
m_extra_mf_fields.erase(mf);
}
+ bool waiting_for_fill( mem_fetch *mf )
+ {
+ extra_mf_fields_lookup::iterator e = m_extra_mf_fields.find(mf);
+ return e != m_extra_mf_fields.end();
+ }
+
// are any (accepted) accesses that had to wait for memory now ready? (does not include accesses that "HIT")
bool access_ready() const
{
@@ -520,6 +541,7 @@ public:
tag_array m_tag_array;
mshr_table m_mshrs;
std::list<mem_fetch*> m_miss_queue;
+ enum mem_fetch_status m_miss_queue_status;
mem_fetch_interface *m_memport;
struct extra_mf_fields {
@@ -548,12 +570,14 @@ public:
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)
+ data_cache( const char *name, const cache_config &config, int core_id, int type_id, mem_fetch_interface *memport,
+ mem_fetch_allocator *mfcreator, enum mem_fetch_status status )
+ : read_only_cache(name,config,core_id,type_id,memport,status)
{
m_memfetch_creator=mfcreator;
}
- virtual enum cache_request_status access( new_addr_type addr, mem_fetch *mf, unsigned time ) {
+ virtual enum cache_request_status access( new_addr_type addr, mem_fetch *mf, unsigned time, std::list<cache_event> &events )
+ {
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
@@ -566,19 +590,19 @@ public:
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
+ // generate a write through
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);
+ assert( block.m_status != MODIFIED ); // fails if block was allocated by a ld.local and now accessed by st.global
+ m_miss_queue.push_back(mf);
+ mf->set_status(m_miss_queue_status,time);
+ events.push_back(WRITE_REQUEST_SENT);
- // invalidate block
+ // 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 );
+ assert( type == LOCAL_ACC_W || /*l2 only*/ type == L1_WRBK_ACC );
// treated as write back...
cache_block_t &block = m_tag_array.get_block(cache_index);
block.m_status = MODIFIED;
@@ -592,6 +616,8 @@ public:
// on miss, generate write through (no write buffering -- too many threads for that)
m_miss_queue.push_back(mf);
+ mf->set_status(m_miss_queue_status,time);
+ events.push_back(WRITE_REQUEST_SENT);
return MISS;
} else {
if ( (m_miss_queue.size()+1) >= m_config.m_miss_queue_size )
@@ -613,11 +639,16 @@ public:
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);
+ mf->set_status(m_miss_queue_status,time);
+ events.push_back(READ_REQUEST_SENT);
do_miss = true;
}
if( wb ) {
+ assert(do_miss);
mem_fetch *wb = m_memfetch_creator->alloc(evicted.m_block_addr,L1_WRBK_ACC,m_config.get_line_sz(),true);
+ events.push_back(WRITE_BACK_REQUEST_SENT);
m_miss_queue.push_back(wb);
+ wb->set_status(m_miss_queue_status,time);
}
if( do_miss )
return MISS;
@@ -637,7 +668,9 @@ public:
// http://www-graphics.stanford.edu/papers/texture_prefetch/
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 )
+ tex_cache( const char *name, const cache_config &config, int core_id, int type_id, mem_fetch_interface *memport,
+ enum mem_fetch_status request_status,
+ enum mem_fetch_status rob_status )
: m_config(config),
m_tags(config,core_id,type_id),
m_fragment_fifo(config.m_fragment_fifo_entries),
@@ -651,13 +684,15 @@ public:
assert(config.m_alloc_policy == ON_MISS);
m_memport=memport;
m_cache = new data_block[ config.get_num_lines() ];
+ m_request_queue_status = request_status;
+ m_rob_status = rob_status;
}
// return values: RESERVATION_FAIL if request could not be accepted
// 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 ) {
+ enum cache_request_status access( new_addr_type addr, mem_fetch *mf, unsigned time, std::list<cache_event> &events ) {
if ( m_fragment_fifo.full() || m_request_fifo.full() || m_rob.full() )
return RESERVATION_FAIL;
@@ -675,6 +710,8 @@ public:
mf->set_data_size(m_config.get_line_sz());
m_tags.fill(cache_index,time); // mark block as valid
m_request_fifo.push(mf);
+ mf->set_status(m_request_queue_status,time);
+ events.push_back(READ_REQUEST_SENT);
return MISS;
} else {
// the value *will* *be* in the cache already
@@ -726,6 +763,7 @@ public:
assert( e != m_extra_mf_fields.end() );
assert( e->second.m_valid );
assert( !m_rob.empty() );
+ mf->set_status(m_rob_status,time);
unsigned rob_index = e->second.m_rob_index;
rob_entry &r = m_rob.peek(rob_index);
@@ -884,6 +922,8 @@ public:
fifo<mem_fetch*> m_result_fifo; // next completed texture fetch
mem_fetch_interface *m_memport;
+ enum mem_fetch_status m_request_queue_status;
+ enum mem_fetch_status m_rob_status;
struct extra_mf_fields {
extra_mf_fields() { m_valid = false;}
diff --git a/src/gpgpu-sim/gpu-sim.cc b/src/gpgpu-sim/gpu-sim.cc
index 359a54d..9bb6a23 100644
--- a/src/gpgpu-sim/gpu-sim.cc
+++ b/src/gpgpu-sim/gpu-sim.cc
@@ -138,7 +138,10 @@ void memory_config::reg_options(class OptionParser * opp)
option_parser_register(opp, "-gpgpu_cache:dl2", OPT_CSTR, &m_L2_config.m_config_string,
"unified banked L2 data cache config "
" {<nsets>:<bsize>:<assoc>:<rep>:<wr>:<alloc>,<mshr>:<N>:<merge>,<mq>}",
- NULL);
+ NULL);
+ option_parser_register(opp, "-gpgpu_cache:dl2_texture_only", OPT_BOOL, &m_L2_texure_only,
+ "L2 cache used for texture only",
+ "0");
option_parser_register(opp, "-gpgpu_n_mem", OPT_UINT32, &m_n_mem,
"number of memory modules (e.g. memory controllers) in gpu",
"8");
@@ -518,13 +521,14 @@ unsigned int gpgpu_sim::run_gpu_sim()
if( not_completed ) {
if ( !num_cores ) {
printf("GPGPU-Sim uArch: DEADLOCK shader cores no longer committing instructions [core(# threads)]:\n" );
- printf("GPGPU-Sim uArch: DEADLOCK %u(%u)", i, not_completed);
+ printf("GPGPU-Sim uArch: DEADLOCK ");
+ m_cluster[i]->print_not_completed(stdout);
} else if (num_cores < 8 ) {
- printf(" %u(%u)", i, not_completed);
- } else if (num_cores == 8 ) {
+ m_cluster[i]->print_not_completed(stdout);
+ } else if (num_cores >= 8 ) {
printf(" + others ... ");
}
- num_cores++;
+ num_cores+=m_shader_config->n_simt_cores_per_cluster;
}
}
printf("\n");
@@ -868,9 +872,10 @@ void gpgpu_sim::cycle()
}
}
-void shader_core_ctx::dump_istream_state( FILE *fout ) const
+void shader_core_ctx::dump_warp_state( FILE *fout ) const
{
fprintf(fout, "\n");
+ fprintf(fout, "per warp functional simulation status:\n");
for (unsigned w=0; w < m_config->max_warps_per_shader; w++ )
m_warp[w].print(fout);
}
diff --git a/src/gpgpu-sim/gpu-sim.h b/src/gpgpu-sim/gpu-sim.h
index 54b32d0..db0b18f 100644
--- a/src/gpgpu-sim/gpu-sim.h
+++ b/src/gpgpu-sim/gpu-sim.h
@@ -124,6 +124,7 @@ struct memory_config {
bool m_valid;
cache_config m_L2_config;
+ bool m_L2_texure_only;
char *gpgpu_dram_timing_opt;
char *gpgpu_L2_queue_config;
diff --git a/src/gpgpu-sim/l2cache.cc b/src/gpgpu-sim/l2cache.cc
index ff09d18..bb13cbc 100644
--- a/src/gpgpu-sim/l2cache.cc
+++ b/src/gpgpu-sim/l2cache.cc
@@ -83,6 +83,21 @@
#include "shader.h"
#include "mem_latency_stat.h"
+
+mem_fetch * partition_mf_allocator::alloc(new_addr_type addr, mem_access_type type, unsigned size, bool wr ) const
+{
+ assert( wr );
+ mem_access_t access( type, addr, size, wr );
+ mem_fetch *mf = new mem_fetch( access,
+ NULL,
+ WRITE_PACKET_SIZE,
+ -1,
+ -1,
+ -1,
+ m_memory_config );
+ return mf;
+}
+
memory_partition_unit::memory_partition_unit( unsigned partition_id,
const struct memory_config *config,
class memory_stats_t *stats )
@@ -95,7 +110,8 @@ memory_partition_unit::memory_partition_unit( unsigned partition_id,
char L2c_name[32];
snprintf(L2c_name, 32, "L2_bank_%03d", m_id);
m_L2interface = new L2interface(this);
- m_L2cache = new read_only_cache(L2c_name,m_config->m_L2_config,-1,-1,m_L2interface);
+ m_mf_allocator = new partition_mf_allocator(config);
+ m_L2cache = new data_cache(L2c_name,m_config->m_L2_config,-1,-1,m_L2interface,m_mf_allocator,IN_PARTITION_L2_MISS_QUEUE);
unsigned int icnt_L2;
unsigned int L2_dram;
@@ -125,14 +141,14 @@ void memory_partition_unit::cache_cycle( unsigned cycle )
// L2 fill responses
if ( m_L2cache->access_ready() && !m_L2_icnt_queue->full() ) {
mem_fetch *mf = m_L2cache->next_access();
- mf->set_type(REPLY_DATA);
+ mf->set_reply();
mf->set_status(IN_PARTITION_L2_TO_ICNT_QUEUE,gpu_sim_cycle+gpu_tot_sim_cycle);
m_L2_icnt_queue->push(mf);
}
// DRAM to L2 (texture) and icnt (not texture)
if ( !m_dram_L2_queue->empty() ) {
mem_fetch *mf = m_dram_L2_queue->top();
- if ( mf->istexture() ) {
+ if ( m_L2cache->waiting_for_fill(mf) ) {
mf->set_status(IN_PARTITION_L2_FILL_QUEUE,gpu_sim_cycle+gpu_tot_sim_cycle);
m_L2cache->fill(mf,gpu_sim_cycle+gpu_tot_sim_cycle);
m_dram_L2_queue->pop();
@@ -149,19 +165,31 @@ void memory_partition_unit::cache_cycle( unsigned cycle )
// new L2 texture accesses and/or non-texture accesses
if ( !m_L2_dram_queue->full() && !m_icnt_L2_queue->empty() ) {
mem_fetch *mf = m_icnt_L2_queue->top();
- if ( mf->istexture() ) {
- // in this model, L2 is for texture only
+ if ( (m_config->m_L2_texure_only && mf->istexture()) || (!m_config->m_L2_texure_only) ) {
if ( !m_L2_icnt_queue->full() ) {
- enum cache_request_status status = m_L2cache->access(mf->get_partition_addr(),mf,gpu_sim_cycle+gpu_tot_sim_cycle);
+ std::list<cache_event> events;
+ enum cache_request_status status = m_L2cache->access(mf->get_partition_addr(),mf,gpu_sim_cycle+gpu_tot_sim_cycle,events);
+ bool write_sent = was_write_sent(events);
+ bool read_sent = was_read_sent(events);
+
if ( status == HIT ) {
- // L2 cache replies with data
- mf->set_type(REPLY_DATA);
- m_L2_icnt_queue->push(mf);
- m_icnt_L2_queue->pop();
+ if( !write_sent ) {
+ // L2 cache replies
+ assert(!read_sent);
+ mf->set_reply();
+ mf->set_status(IN_PARTITION_L2_TO_ICNT_QUEUE,gpu_sim_cycle+gpu_tot_sim_cycle);
+ m_L2_icnt_queue->push(mf);
+ m_icnt_L2_queue->pop();
+ } else {
+ assert(write_sent);
+ m_icnt_L2_queue->pop();
+ }
} else if ( status != RESERVATION_FAIL ) {
// L2 cache accepted request
m_icnt_L2_queue->pop();
} else {
+ assert(!write_sent);
+ assert(!read_sent);
// L2 cache lock-up: will try again next cycle
}
}
@@ -205,6 +233,7 @@ void memory_partition_unit::print( FILE *fp ) const
fprintf(fp," <NULL mem_fetch?>\n");
}
}
+ m_L2cache->display_state(fp);
m_dram->print(fp);
}
@@ -266,15 +295,26 @@ void memory_partition_unit::push( mem_fetch* req, unsigned long long cycle )
mem_fetch* memory_partition_unit::pop()
{
mem_fetch* mf = m_L2_icnt_queue->pop();
+ m_request_tracker.erase(mf);
if ( mf && mf->isatomic() )
mf->do_atomic();
- m_request_tracker.erase(mf);
+ if( mf && (mf->get_access_type() == L2_WRBK_ACC || mf->get_access_type() == L1_WRBK_ACC) ) {
+ delete mf;
+ mf = NULL;
+ }
return mf;
}
mem_fetch* memory_partition_unit::top()
{
- return m_L2_icnt_queue->top();
+ mem_fetch *mf = m_L2_icnt_queue->top();
+ if( mf && (mf->get_access_type() == L2_WRBK_ACC || mf->get_access_type() == L1_WRBK_ACC) ) {
+ m_L2_icnt_queue->pop();
+ m_request_tracker.erase(mf);
+ delete mf;
+ mf = NULL;
+ }
+ return mf;
}
void memory_partition_unit::dram_cycle()
diff --git a/src/gpgpu-sim/l2cache.h b/src/gpgpu-sim/l2cache.h
index b7ab49e..761a220 100644
--- a/src/gpgpu-sim/l2cache.h
+++ b/src/gpgpu-sim/l2cache.h
@@ -74,6 +74,22 @@
class mem_fetch;
+class partition_mf_allocator : public mem_fetch_allocator {
+public:
+ partition_mf_allocator( const memory_config *config )
+ {
+ m_memory_config = config;
+ }
+ virtual mem_fetch * alloc(const class warp_inst_t &inst, const mem_access_t &access) const
+ {
+ abort();
+ return NULL;
+ }
+ virtual mem_fetch * alloc(new_addr_type addr, mem_access_type type, unsigned size, bool wr) const;
+private:
+ const memory_config *m_memory_config;
+};
+
class memory_partition_unit
{
public:
@@ -103,8 +119,9 @@ private:
unsigned m_id;
const struct memory_config *m_config;
class dram_t *m_dram;
- class read_only_cache *m_L2cache;
+ class data_cache *m_L2cache;
class L2interface *m_L2interface;
+ partition_mf_allocator *m_mf_allocator;
// model delay of ROP units with a fixed latency
struct rop_delay_t
@@ -140,7 +157,8 @@ public:
}
virtual void push(mem_fetch *mf)
{
- m_unit->m_L2_dram_queue->push(mf);
+ mf->set_status(IN_PARTITION_L2_TO_DRAM_QUEUE,0/*FIXME*/);
+ m_unit->m_L2_dram_queue->push(mf);
}
private:
memory_partition_unit *m_unit;
diff --git a/src/gpgpu-sim/mem_fetch.cc b/src/gpgpu-sim/mem_fetch.cc
index f4c3bcc..699ba0a 100644
--- a/src/gpgpu-sim/mem_fetch.cc
+++ b/src/gpgpu-sim/mem_fetch.cc
@@ -92,7 +92,7 @@ mem_fetch::mem_fetch( const mem_access_t &access,
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_type = m_access.is_write()?WRITE_REQUEST:READ_REQUEST;
m_timestamp = gpu_sim_cycle + gpu_tot_sim_cycle;
m_timestamp2 = 0;
m_status = MEM_FETCH_INITIALIZED;
diff --git a/src/gpgpu-sim/mem_fetch.h b/src/gpgpu-sim/mem_fetch.h
index 05e2206..926e51a 100644
--- a/src/gpgpu-sim/mem_fetch.h
+++ b/src/gpgpu-sim/mem_fetch.h
@@ -72,17 +72,23 @@
#include <bitset>
enum mf_type {
- RD_REQ = 0,
- WR_REQ,
- REPLY_DATA // send to shader
+ READ_REQUEST = 0,
+ WRITE_REQUEST,
+ READ_REPLY, // send to shader
+ WRITE_ACK
};
enum mem_fetch_status {
MEM_FETCH_INITIALIZED = 0,
+ IN_L1I_MISS_QUEUE,
+ IN_L1D_MISS_QUEUE,
+ IN_L1T_MISS_QUEUE,
+ IN_L1C_MISS_QUEUE,
IN_ICNT_TO_MEM,
IN_PARTITION_ROP_DELAY,
IN_PARTITION_ICNT_TO_L2_QUEUE,
IN_PARTITION_L2_TO_DRAM_QUEUE,
+ IN_PARTITION_L2_MISS_QUEUE,
IN_PARTITION_MC_INTERFACE_QUEUE,
IN_PARTITION_MC_INPUT_QUEUE,
IN_PARTITION_MC_BANK_ARB_QUEUE,
@@ -95,6 +101,7 @@ enum mem_fetch_status {
IN_CLUSTER_TO_SHADER_QUEUE,
IN_SHADER_LDST_RESPONSE_FIFO,
IN_SHADER_FETCHED,
+ IN_SHADER_L1T_ROB,
MEM_FETCH_DELETED,
NUM_MEM_REQ_STAT
};
@@ -111,7 +118,17 @@ public:
~mem_fetch();
void set_status( enum mem_fetch_status status, unsigned long long cycle );
- void set_type( enum mf_type t ) { m_type=t; }
+ void set_reply()
+ {
+ assert( m_access.get_type() != L1_WRBK_ACC && m_access.get_type() != L2_WRBK_ACC );
+ if( m_type==READ_REQUEST ) {
+ assert( !get_is_write() );
+ m_type = READ_REPLY;
+ } else if( m_type == WRITE_REQUEST ) {
+ assert( get_is_write() );
+ m_type = WRITE_ACK;
+ }
+ }
void do_atomic();
void print( FILE *fp, bool print_inst = true ) const;
@@ -152,7 +169,7 @@ private:
unsigned m_wid;
// where is this request now?
- enum mem_fetch_status m_status;
+ enum mem_fetch_status m_status;
unsigned long long m_status_change;
// request type, address, size, mask
diff --git a/src/gpgpu-sim/shader.cc b/src/gpgpu-sim/shader.cc
index 303d736..e9ec368 100644
--- a/src/gpgpu-sim/shader.cc
+++ b/src/gpgpu-sim/shader.cc
@@ -127,6 +127,7 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu,
m_thread = (thread_ctx_t*) calloc(sizeof(thread_ctx_t), config->n_thread_per_shader);
m_not_completed = 0;
+ m_active_threads.reset();
m_n_active_cta = 0;
for (unsigned i = 0; i<MAX_CTA_PER_SHADER; i++ )
m_cta_status[i]=0;
@@ -145,7 +146,7 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu,
#define STRSIZE 1024
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_L1I = new read_only_cache( name,m_config->m_L1I_config,m_sid,get_shader_instruction_cache_id(),m_icnt,IN_L1I_MISS_QUEUE);
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];
@@ -183,12 +184,17 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu,
m_fu[2] = m_ldst_unit;
m_dispatch_port[2] = ID_OC_MEM;
m_issue_port[2] = OC_EX_MEM;
+
+ m_last_inst_gpu_sim_cycle = 0;
+ m_last_inst_gpu_tot_sim_cycle = 0;
}
void shader_core_ctx::reinit(unsigned start_thread, unsigned end_thread, bool reset_not_completed )
{
- if( reset_not_completed )
+ if( reset_not_completed ) {
m_not_completed = 0;
+ m_active_threads.reset();
+ }
for (unsigned i = start_thread; i<end_thread; i++) {
m_thread[i].n_insn = 0;
m_thread[i].m_cta_id = -1;
@@ -208,14 +214,19 @@ void shader_core_ctx::init_warps( unsigned cta_id, unsigned start_thread, unsign
for (unsigned i = start_warp; i < end_warp; ++i) {
unsigned initial_active_mask = 0;
unsigned n_active=0;
+ std::bitset<MAX_WARP_SIZE> active_threads;
for (unsigned t = 0; t < m_config->warp_size; t++) {
- if ( i * m_config->warp_size + t < end_thread ) {
+ unsigned hwtid = i * m_config->warp_size + t;
+ if ( hwtid < end_thread ) {
initial_active_mask |= (1 << t);
n_active++;
+ assert( !m_active_threads.test(hwtid) );
+ m_active_threads.set( hwtid );
+ active_threads.set(t);
}
}
m_pdom_warp[i]->launch(start_pc,initial_active_mask);
- m_warp[i].init(start_pc,cta_id,i,n_active);
+ m_warp[i].init(start_pc,cta_id,i,active_threads);
m_not_completed += n_active;
}
}
@@ -509,14 +520,16 @@ void shader_core_ctx::fetch()
// and get next 1-2 instructions from i-cache...
for( unsigned i=0; i < m_config->max_warps_per_shader; i++ ) {
unsigned warp_id = (m_last_warp_fetched+1+i) % m_config->max_warps_per_shader;
- if( m_warp[warp_id].done() && !m_scoreboard->pendingWrites(warp_id) && !m_warp[warp_id].done_exit()
- && m_warp[warp_id].stores_done() && !m_warp[warp_id].inst_in_pipeline() ) {
+
+ // this code checks if this warp has finished executing and can be reclaimed
+ if( m_warp[warp_id].hardware_done() && !m_scoreboard->pendingWrites(warp_id) && !m_warp[warp_id].done_exit() ) {
bool did_exit=false;
for( unsigned t=0; t<m_config->warp_size;t++) {
unsigned tid=warp_id*m_config->warp_size+t;
if( m_thread[tid].m_functional_model_thread_state ) {
register_cta_thread_exit(tid);
m_not_completed -= 1;
+ m_active_threads.reset(tid);
m_thread[tid].m_functional_model_thread_state=NULL;
did_exit=true;
}
@@ -524,7 +537,9 @@ void shader_core_ctx::fetch()
if( did_exit )
m_warp[warp_id].set_done_exit();
}
- if( !m_warp[warp_id].done() && !m_warp[warp_id].imiss_pending() && m_warp[warp_id].ibuffer_empty() ) {
+
+ // this code fetches instructions from the i-cache or generates memory requests
+ if( !m_warp[warp_id].functional_done() && !m_warp[warp_id].imiss_pending() && m_warp[warp_id].ibuffer_empty() ) {
address_type pc = m_warp[warp_id].get_pc();
address_type ppc = pc + PROGRAM_MEM_START;
unsigned nbytes=16;
@@ -542,7 +557,8 @@ void shader_core_ctx::fetch()
m_sid,
m_tpc,
m_memory_config );
- enum cache_request_status status = m_L1I->access( (new_addr_type)ppc, mf, gpu_sim_cycle+gpu_tot_sim_cycle );
+ std::list<cache_event> events;
+ enum cache_request_status status = m_L1I->access( (new_addr_type)ppc, mf, gpu_sim_cycle+gpu_tot_sim_cycle,events);
if( status == MISS ) {
m_last_warp_fetched=warp_id;
m_warp[warp_id].set_imiss_pending();
@@ -551,6 +567,7 @@ void shader_core_ctx::fetch()
m_last_warp_fetched=warp_id;
m_inst_fetch_buffer = ifetch_buffer_t(pc,nbytes,warp_id);
m_warp[warp_id].set_last_fetch(gpu_sim_cycle);
+ delete mf;
} else {
assert( status == RESERVATION_FAIL );
delete mf;
@@ -581,7 +598,7 @@ void shader_core_ctx::func_exec_inst( warp_inst_t &inst )
inst.set_addr(t, translate_local_memaddr(inst.get_addr(t), tid,
m_config->n_simt_clusters*m_config->n_simt_cores_per_cluster) );
if ( ptx_thread_done(tid) ) {
- m_warp[inst.warp_id()].inc_n_completed();
+ m_warp[inst.warp_id()].set_completed(t);
m_warp[inst.warp_id()].ibuffer_flush();
}
}
@@ -748,6 +765,8 @@ void shader_core_ctx::writeback()
m_stats->m_num_sim_insn[m_sid]++;
m_gpu->gpu_sim_insn_last_update_sid = m_sid;
m_gpu->gpu_sim_insn_last_update = gpu_sim_cycle;
+ m_last_inst_gpu_sim_cycle = gpu_sim_cycle;
+ m_last_inst_gpu_tot_sim_cycle = gpu_tot_sim_cycle;
m_gpu->gpu_sim_insn += pipe_reg->active_count();
pipe_reg->clear();
}
@@ -775,24 +794,32 @@ mem_stage_stall_type ldst_unit::process_memory_access_queue( cache_t *cache, war
const mem_access_t &access = 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);
+ std::list<cache_event> events;
+ enum cache_request_status status = cache->access(mf->get_addr(),mf,gpu_sim_cycle+gpu_tot_sim_cycle,events);
+ bool write_sent = was_write_sent(events);
+ bool read_sent = was_read_sent(events);
+ if( write_sent )
+ m_core->inc_store_req( inst.warp_id() );
if ( status == HIT ) {
+ assert( !read_sent );
inst.accessq_pop_back();
- delete mf;
+ if( !write_sent )
+ delete mf;
} else if ( status == RESERVATION_FAIL ) {
result = COAL_STALL;
+ assert( !read_sent );
+ assert( !write_sent );
delete mf;
} else {
- inst.clear_active( access.get_warp_mask() ); // threads in mf writeback when mf returns
assert( status == MISS || status == HIT_RESERVED );
+ inst.clear_active( access.get_warp_mask() ); // threads in mf writeback when mf returns
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() );
+ }
}
if( !inst.accessq_empty() )
result = BK_CONF;
@@ -951,15 +978,17 @@ ldst_unit::ldst_unit( shader_memory_interface *icnt,
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_L1T = new tex_cache(L1T_name,m_config->m_L1T_config,m_sid,get_shader_texture_cache_id(),icnt,IN_L1T_MISS_QUEUE,IN_SHADER_L1T_ROB);
+ m_L1C = new read_only_cache(L1C_name,m_config->m_L1C_config,m_sid,get_shader_constant_cache_id(),icnt,IN_L1C_MISS_QUEUE);
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_L1D = new data_cache(L1D_name,m_config->m_L1D_config,m_sid,get_shader_normal_cache_id(),m_icnt,m_mf_allocator,IN_L1D_MISS_QUEUE);
m_mem_rc = NO_RC_FAIL;
m_num_writeback_clients=5; // = shared memory, global/local (uncached), L1D, L1T, L1C
m_writeback_arb = 0;
m_next_global=NULL;
+ m_last_inst_gpu_sim_cycle=0;
+ m_last_inst_gpu_tot_sim_cycle=0;
}
void ldst_unit::writeback()
@@ -984,6 +1013,8 @@ void ldst_unit::writeback()
}
}
m_next_wb.clear();
+ m_last_inst_gpu_sim_cycle = gpu_sim_cycle;
+ m_last_inst_gpu_tot_sim_cycle = gpu_tot_sim_cycle;
}
}
@@ -1046,7 +1077,6 @@ void ldst_unit::cycle()
if( !m_response_fifo.empty() ) {
mem_fetch *mf = m_response_fifo.front();
if (mf->istexture()) {
- mf->set_status(IN_SHADER_FETCHED,gpu_sim_cycle+gpu_tot_sim_cycle);
m_L1T->fill(mf,gpu_sim_cycle+gpu_tot_sim_cycle);
m_response_fifo.pop_front();
} else if (mf->isconst()) {
@@ -1054,11 +1084,12 @@ void ldst_unit::cycle()
m_L1C->fill(mf,gpu_sim_cycle+gpu_tot_sim_cycle);
m_response_fifo.pop_front();
} else {
- if( mf->get_is_write() ) {
+ if( mf->get_type() == WRITE_ACK ) {
m_core->store_ack(mf);
m_response_fifo.pop_front();
delete mf;
} else {
+ assert( !mf->get_is_write() ); // L1 cache is write evict, allocate line on load miss only
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();
@@ -1247,10 +1278,10 @@ void shader_core_ctx::print_stage(unsigned int stage, FILE *fout ) const
m_pipeline_reg[stage]->print(fout);
}
-void shader_core_ctx::display_pdom_state(FILE *fout, int mask ) const
+void shader_core_ctx::display_simt_state(FILE *fout, int mask ) const
{
if ( (mask & 4) && m_config->model == POST_DOMINATOR ) {
- fprintf(fout,"warp status:\n");
+ fprintf(fout,"per warp SIMT control-flow state:\n");
unsigned n = m_config->n_thread_per_shader / m_config->warp_size;
for (unsigned i=0; i < n; i++) {
unsigned nactive = 0;
@@ -1294,6 +1325,8 @@ void ldst_unit::print(FILE *fout) const
}
fprintf(fout,"LD/ST wb = ");
m_next_wb.print(fout);
+ fprintf(fout, "Last LD/ST writeback @ %llu + %llu (gpu_sim_cycle+gpu_tot_sim_cycle)\n",
+ m_last_inst_gpu_sim_cycle, m_last_inst_gpu_tot_sim_cycle );
fprintf(fout,"Pending register writes:\n");
std::map<unsigned/*warp_id*/, std::map<unsigned/*regnum*/,unsigned/*count*/> >::const_iterator w;
for( w=m_pending_writes.begin(); w!=m_pending_writes.end(); w++ ) {
@@ -1325,7 +1358,7 @@ void shader_core_ctx::display_pipeline(FILE *fout, int print_mem, int mask ) con
gpu_tot_sim_cycle, gpu_sim_cycle, m_not_completed);
fprintf(fout, "=================================================\n");
- dump_istream_state(fout);
+ dump_warp_state(fout);
fprintf(fout,"\n");
m_L1I->display_state(fout);
@@ -1345,7 +1378,7 @@ void shader_core_ctx::display_pipeline(FILE *fout, int print_mem, int mask ) con
m_warp[i].print_ibuffer(fout);
}
fprintf(fout,"\n");
- display_pdom_state(fout,mask);
+ display_simt_state(fout,mask);
m_scoreboard->printContents();
@@ -1371,6 +1404,24 @@ void shader_core_ctx::display_pipeline(FILE *fout, int print_mem, int mask ) con
fprintf(fout, "EX/WB = ");
print_stage(EX_WB, fout);
fprintf(fout, "\n");
+ fprintf(fout, "Last EX/WB writeback @ %llu + %llu (gpu_sim_cycle+gpu_tot_sim_cycle)\n",
+ m_last_inst_gpu_sim_cycle, m_last_inst_gpu_tot_sim_cycle );
+
+ if( m_active_threads.count() <= 2*m_config->warp_size ) {
+ fprintf(fout,"Active Threads : ");
+ unsigned last_warp_id = -1;
+ for(unsigned tid=0; tid < m_active_threads.size(); tid++ ) {
+ unsigned warp_id = tid/m_config->warp_size;
+ if( m_active_threads.test(tid) ) {
+ if( warp_id != last_warp_id ) {
+ fprintf(fout,"\n warp %u : ", warp_id );
+ last_warp_id=warp_id;
+ }
+ fprintf(fout,"%u ", tid );
+ }
+ }
+ }
+
}
unsigned int shader_core_config::max_cta( const kernel_info_t &k ) const
@@ -1679,18 +1730,24 @@ void shader_core_ctx::accept_ldst_unit_response(mem_fetch * mf)
void shader_core_ctx::store_ack( class mem_fetch *mf )
{
+ assert( mf->get_type() == WRITE_ACK );
unsigned warp_id = mf->get_wid();
m_warp[warp_id].dec_store_req();
}
-bool shd_warp_t::done()
+bool shd_warp_t::functional_done() const
{
return get_n_completed() == m_warp_size;
}
+bool shd_warp_t::hardware_done() const
+{
+ return functional_done() && stores_done() && !inst_in_pipeline();
+}
+
bool shd_warp_t::waiting()
{
- if ( done() ) {
+ if ( functional_done() ) {
// waiting to be initialized with a kernel
return true;
} else if ( m_shader->warp_waiting_at_barrier(m_warp_id) ) {
@@ -1712,10 +1769,14 @@ bool shd_warp_t::waiting()
void shd_warp_t::print( FILE *fout ) const
{
- if ( n_completed < m_warp_size ) {
- fprintf( fout, "w%02u npc: 0x%04x, done:%2u i:%u s:%u a:%u (done: ",
+ if( !done_exit() ) {
+ fprintf( fout, "w%02u npc: 0x%04x, done:%c%c%c%c:%2u i:%u s:%u a:%u (done: ",
m_warp_id,
m_next_pc,
+ (functional_done()?'f':' '),
+ (stores_done()?'s':' '),
+ (inst_in_pipeline()?' ':'i'),
+ (done_exit()?'e':' '),
n_completed,
m_inst_in_pipeline,
m_stores_outstanding,
@@ -1727,6 +1788,7 @@ void shd_warp_t::print( FILE *fout ) const
fprintf(fout,",");
}
fprintf(fout,") ");
+ fprintf(fout," active=%s", m_active_threads.to_string().c_str() );
fprintf(fout," last fetched @ %5llu", m_last_fetch);
if( m_imiss_pending )
fprintf(fout," i-miss pending");
@@ -2023,6 +2085,15 @@ unsigned simt_core_cluster::get_not_completed() const
return not_completed;
}
+void simt_core_cluster::print_not_completed( FILE *fp ) const
+{
+ for( unsigned i=0; i < m_config->n_simt_cores_per_cluster; i++ ) {
+ unsigned not_completed=m_core[i]->get_not_completed();
+ unsigned sid=m_config->cid_to_sid(i,m_cluster_id);
+ fprintf(fp,"%u(%u) ", sid, not_completed );
+ }
+}
+
unsigned simt_core_cluster::get_n_active_cta() const
{
unsigned n=0;
@@ -2109,7 +2180,7 @@ void simt_core_cluster::icnt_cycle()
if (!mf)
return;
assert(mf->get_tpc() == m_cluster_id);
- assert(mf->get_type() == REPLY_DATA);
+ assert(mf->get_type() == READ_REPLY || mf->get_type() == WRITE_ACK );
mf->set_status(IN_CLUSTER_TO_SHADER_QUEUE,gpu_sim_cycle+gpu_tot_sim_cycle);
//m_memory_stats->memlatstat_read_done(mf,m_shader_config->max_warps_per_shader);
m_response_fifo.push_back(mf);
diff --git a/src/gpgpu-sim/shader.h b/src/gpgpu-sim/shader.h
index bfe0cc2..17dbd9e 100644
--- a/src/gpgpu-sim/shader.h
+++ b/src/gpgpu-sim/shader.h
@@ -140,22 +140,25 @@ public:
n_completed = m_warp_size;
m_n_atomic=0;
m_membar=false;
- m_done_exit=false;
+ m_done_exit=true;
m_last_fetch=0;
m_next=0;
}
- void init( address_type start_pc, unsigned cta_id, unsigned wid, unsigned active )
+ void init( address_type start_pc, unsigned cta_id, unsigned wid, const std::bitset<MAX_WARP_SIZE> &active )
{
m_cta_id=cta_id;
m_warp_id=wid;
m_next_pc=start_pc;
- assert( n_completed >= active );
+ assert( n_completed >= active.count() );
assert( n_completed <= m_warp_size);
- n_completed -= active; // active threads are not yet completed
+ n_completed -= active.count(); // active threads are not yet completed
+ m_active_threads = active;
+ m_done_exit=false;
}
- bool done();
- bool waiting();
+ bool functional_done() const;
+ bool waiting(); // not const due to membar
+ bool hardware_done() const;
bool done_exit() const { return m_done_exit; }
void set_done_exit() { m_done_exit=true; }
@@ -164,7 +167,12 @@ public:
void print_ibuffer( FILE *fout ) const;
unsigned get_n_completed() const { return n_completed; }
- void inc_n_completed() { n_completed++; }
+ void set_completed( unsigned lane )
+ {
+ assert( m_active_threads.test(lane) );
+ m_active_threads.reset(lane);
+ n_completed++;
+ }
void set_last_fetch( unsigned long long sim_cycle ) { m_last_fetch=sim_cycle; }
@@ -241,6 +249,7 @@ private:
address_type m_next_pc;
unsigned n_completed; // number of threads in warp completed
+ std::bitset<MAX_WARP_SIZE> m_active_threads;
bool m_imiss_pending;
@@ -901,6 +910,10 @@ private:
enum mem_stage_stall_type m_mem_rc;
shader_core_stats *m_stats;
+
+ // for debugging
+ unsigned long long m_last_inst_gpu_sim_cycle;
+ unsigned long long m_last_inst_gpu_tot_sim_cycle;
};
enum pipeline_stage_name_t {
@@ -1136,7 +1149,7 @@ public:
const shader_core_config *get_config() const { return m_config; }
// debug:
- void display_pdom_state(FILE *fout, int mask ) const;
+ void display_simt_state(FILE *fout, int mask ) const;
void display_pipeline( FILE *fout, int print_mem, int mask3bit ) const;
private:
@@ -1157,8 +1170,10 @@ private:
void writeback();
// used in display_pipeline():
- void dump_istream_state( FILE *fout ) const;
+ void dump_warp_state( FILE *fout ) const;
void print_stage(unsigned int stage, FILE *fout) const;
+ unsigned long long m_last_inst_gpu_sim_cycle;
+ unsigned long long m_last_inst_gpu_tot_sim_cycle;
// general information
unsigned m_sid; // shader id
@@ -1175,6 +1190,7 @@ private:
unsigned m_n_active_cta; // number of Cooperative Thread Arrays (blocks) currently running on this shader.
unsigned m_cta_status[MAX_CTA_PER_SHADER]; // CTAs status
unsigned m_not_completed; // number of threads to be completed (==0 when all thread on this core completed)
+ std::bitset<MAX_THREAD_PER_SM> m_active_threads;
// thread contexts
thread_ctx_t *m_thread; // functional state, per thread fetch state
@@ -1228,6 +1244,7 @@ public:
void get_pdom_stack_top_info( unsigned sid, unsigned tid, unsigned *pc, unsigned *rpc ) const;
unsigned max_cta( const kernel_info_t &kernel );
unsigned get_not_completed() const;
+ void print_not_completed( FILE *fp ) const;
unsigned get_n_active_cta() const;
gpgpu_sim *get_gpu() { return m_gpu; }
diff --git a/src/gpgpu-sim/visualizer.cc b/src/gpgpu-sim/visualizer.cc
index c2b1d16..1c32692 100644
--- a/src/gpgpu-sim/visualizer.cc
+++ b/src/gpgpu-sim/visualizer.cc
@@ -394,9 +394,9 @@ void time_vector_print_interval2gzfile(gzFile outfile) {
#include "../gpgpu-sim/mem_fetch.h"
void time_vector_update(unsigned int uid,int slot ,long int cycle,int type) {
- if ( (type == RD_REQ) || (type == REPLY_DATA) ) {
+ if ( (type == READ_REQUEST) || (type == READ_REPLY) ) {
g_my_time_vector->update_ld( uid, slot,cycle);
- } else if ( type == WR_REQ ) {
+ } else if ( (type == WRITE_REQUEST) || (type == WRITE_ACK) ) {
g_my_time_vector->update_st( uid, slot,cycle);
} else {
abort();
@@ -405,9 +405,9 @@ void time_vector_update(unsigned int uid,int slot ,long int cycle,int type) {
void check_time_vector_update(unsigned int uid,int slot ,long int latency,int type)
{
- if ( (type == RD_REQ) || (type == REPLY_DATA) ) {
+ if ( (type == READ_REQUEST) || (type == READ_REPLY) ) {
g_my_time_vector->check_ld_update( uid, slot, latency );
- } else if ( type == WR_REQ ) {
+ } else if ( (type == WRITE_REQUEST) || (type == WRITE_ACK) ) {
g_my_time_vector->check_st_update( uid, slot, latency );
} else {
abort();