diff options
| author | Tor Aamodt <[email protected]> | 2010-10-02 14:54:02 -0800 |
|---|---|---|
| committer | Tor Aamodt <[email protected]> | 2010-10-02 14:54:02 -0800 |
| commit | d3b9d526ecbf5e0bdaa91d21526cb56a2e98b534 (patch) | |
| tree | d419ff51749e24fb2f30314d42496f25a692561a | |
| parent | 11b308e7363e937966b035b4891db32b4eece3bf (diff) | |
refactoring: make shd_cache_t into a class (cache_t), plus some other cleaning up
[git-p4: depot-paths = "//depot/gpgpu_sim_research/fermi/distribution/": change = 7806]
| -rw-r--r-- | src/gpgpu-sim/delayqueue.h | 2 | ||||
| -rw-r--r-- | src/gpgpu-sim/dram.cc | 31 | ||||
| -rw-r--r-- | src/gpgpu-sim/dram.h | 1 | ||||
| -rw-r--r-- | src/gpgpu-sim/gpu-cache.cc | 271 | ||||
| -rw-r--r-- | src/gpgpu-sim/gpu-cache.h | 94 | ||||
| -rw-r--r-- | src/gpgpu-sim/gpu-misc.cc | 14 | ||||
| -rw-r--r-- | src/gpgpu-sim/gpu-misc.h | 18 | ||||
| -rw-r--r-- | src/gpgpu-sim/gpu-sim.cc | 56 | ||||
| -rw-r--r-- | src/gpgpu-sim/l2cache.cc | 243 | ||||
| -rw-r--r-- | src/gpgpu-sim/l2cache.h | 30 | ||||
| -rw-r--r-- | src/gpgpu-sim/mem_fetch.cc | 6 | ||||
| -rw-r--r-- | src/gpgpu-sim/mem_fetch.h | 3 | ||||
| -rw-r--r-- | src/gpgpu-sim/shader.cc | 110 | ||||
| -rw-r--r-- | src/gpgpu-sim/shader.h | 14 |
14 files changed, 318 insertions, 575 deletions
diff --git a/src/gpgpu-sim/delayqueue.h b/src/gpgpu-sim/delayqueue.h index 8392460..050a916 100644 --- a/src/gpgpu-sim/delayqueue.h +++ b/src/gpgpu-sim/delayqueue.h @@ -156,7 +156,7 @@ public: return data; } - T* top() + T* top() const { if (m_head) { return m_head->m_data; diff --git a/src/gpgpu-sim/dram.cc b/src/gpgpu-sim/dram.cc index 3182b38..fe1b470 100644 --- a/src/gpgpu-sim/dram.cc +++ b/src/gpgpu-sim/dram.cc @@ -411,12 +411,8 @@ void dram_t::issueCMD() //if mrq is being serviced by dram, gets popped after CL latency fulfilled class mem_fetch* dram_t::pop() { - dram_req_t *mrq; - class mem_fetch *data; - unsigned dq_latency; - - data = NULL; - mrq = rwq->pop(gpu_sim_cycle); + class mem_fetch *data = NULL; + dram_req_t *mrq = rwq->pop(gpu_sim_cycle); if (mrq) { #ifdef DRAM_VIEWCMD printf("\tDQ: BK%d Row:%03x Col:%03x", @@ -425,7 +421,7 @@ class mem_fetch* dram_t::pop() mrq->dqbytes += BL * busW * gpu_n_mem_per_ctrlr; /*16 bytes*/ if (mrq->dqbytes >= mrq->nbytes) { if (m_config->gpgpu_memlatency_stat) { - dq_latency = gpu_sim_cycle + gpu_tot_sim_cycle - mrq->timestamp; + unsigned dq_latency = gpu_sim_cycle + gpu_tot_sim_cycle - mrq->timestamp; m_stats->dq_lat_table[LOGB2(dq_latency)]++; if (dq_latency > m_stats->max_dq_latency) m_stats->max_dq_latency = dq_latency; @@ -437,7 +433,6 @@ class mem_fetch* dram_t::pop() #ifdef DRAM_VIEWCMD printf("\n"); #endif - return data; } @@ -456,26 +451,6 @@ class mem_fetch* dram_t::returnq_top() return returnq->top(); } - -// a hack to allow peeking into what memory request will be serviced. -class mem_fetch* dram_t::top() -{ - dram_req_t *mrq; - class mem_fetch *data; - - data = NULL; - mrq = rwq->top(); - if (mrq) { - // number of bytes returned from dram if this is ever popped - unsigned tobe_dqbytes = mrq->dqbytes + BL * busW * gpu_n_mem_per_ctrlr; - if (tobe_dqbytes >= mrq->nbytes) { - data = mrq->data; - } - } - - return data; -} - void dram_t::print( FILE* simFile) const { unsigned i; diff --git a/src/gpgpu-sim/dram.h b/src/gpgpu-sim/dram.h index 68b2474..ee7f7a7 100644 --- a/src/gpgpu-sim/dram.h +++ b/src/gpgpu-sim/dram.h @@ -128,7 +128,6 @@ public: void set_stats( class memory_stats_t *stats ) {m_stats=stats;} int full(); - class mem_fetch* top(); void print( FILE* simFile ) const; void visualize() const; void print_stat( FILE* simFile ); diff --git a/src/gpgpu-sim/gpu-cache.cc b/src/gpgpu-sim/gpu-cache.cc index bfd8772..164c3fd 100644 --- a/src/gpgpu-sim/gpu-cache.cc +++ b/src/gpgpu-sim/gpu-cache.cc @@ -72,20 +72,17 @@ #include <assert.h> #include <string.h> -// both shd_cache_access and shd_cache_probe functions use -// shd_cache_access_internal to access/probe cache -shd_cache_line_t* shd_cache_access_internal( shd_cache_t *cp, - unsigned long long int addr, - unsigned int nbytes, - unsigned char write, - unsigned int sim_cycle, - unsigned int real_access); +cache_t::~cache_t() +{ + delete m_lines; +} -shd_cache_t * shd_cache_create( const char *name, - const char *opt, - unsigned int hit_latency, - unsigned long long int bank_mask, - enum cache_write_policy wp) +cache_t::cache_t( const char *name, + const char *opt, + unsigned long long int bank_mask, + enum cache_write_policy wp, + int core_id, + int type_id) { unsigned int nset; unsigned int line_sz; @@ -96,36 +93,29 @@ shd_cache_t * shd_cache_create( const char *name, printf("GPGPU-Sim uArch: cache configuration string parsing error for cache %s\n", name); abort(); } + assert(nset && assoc); - shd_cache_t *cp; + cache_t *cp = this; unsigned int nlines; - unsigned int i; - if (!nset || !assoc) { - printf("Creating non-existing cache!\n"); - return 0; - } nlines = nset * assoc; - cp = (shd_cache_t*) calloc(1, sizeof(shd_cache_t)); - cp->bank_mask = bank_mask; - cp->name = (char*) malloc(sizeof(char) * (strlen(name) + 1)); - strcpy(cp->name, name); - cp->nset = nset; - cp->nset_log2 = LOGB2(nset); - cp->assoc = assoc; - cp->line_sz = line_sz; + cp->m_name = (char*) malloc(sizeof(char) * (strlen(name) + 1)); + strcpy(cp->m_name, name); + cp->m_nset = nset; + cp->m_nset_log2 = LOGB2(nset); + cp->m_assoc = assoc; + cp->m_line_sz = line_sz; cp->line_sz_log2 = LOGB2(line_sz); cp->policy = policy; - cp->hit_latency = hit_latency; - cp->lines = (shd_cache_line_t*) calloc(nlines, sizeof(shd_cache_line_t)); + cp->m_lines = (cache_block_t*) calloc(nlines, sizeof(cache_block_t)); cp->write_policy = wp; for (i=0; i<nlines; i++) { - cp->lines[i].line_sz = line_sz; - cp->lines[i].status = 0; + cp->m_lines[i].line_sz = line_sz; + cp->m_lines[i].status = 0; } // don't hook up with any logger @@ -136,104 +126,35 @@ shd_cache_t * shd_cache_create( const char *name, cp->prev_snapshot_access = 0; cp->prev_snapshot_miss = 0; cp->prev_snapshot_merge_hit = 0; - - return cp; -} - -void shd_cache_destroy( shd_cache_t* cp ) { - - free(cp->lines); - free(cp); -} - -// hook up with shader core logger -void shd_cache_bind_logger(shd_cache_t* cp, int core_id, int type_id) { cp->core_id = core_id; cp->type_id = type_id; } -shd_cache_line_t* shd_cache_access_internal( shd_cache_t *cp, - unsigned long long int addr, - unsigned int nbytes, - unsigned char write, - unsigned int sim_cycle, - unsigned int real_access) { - //if real_access==0 then its only a cache probe stats and LRU tags should not be updated - unsigned int i; - unsigned int set; - unsigned long long int tag; - unsigned long long int packed_addr; - shd_cache_line_t *pline; - - if (cp->bank_mask) - packed_addr = addrdec_packbits(cp->bank_mask, addr, 64, 0); - else - packed_addr = addr; - - set = (packed_addr >> cp->line_sz_log2) & ( (1<<cp->nset_log2) - 1 ); - tag = packed_addr >> (cp->line_sz_log2 + cp->nset_log2); - - if (real_access) { - cp->access++; - shader_cache_access_log(cp->core_id, cp->type_id, 0); - } - - for (i=0; i<cp->assoc; i++) { - pline = &(cp->lines[set*cp->assoc+i] ); - if (pline->status & VALID) { - if (pline->tag == tag) { - //printf("Cache Hit! Addr=%08x Set=%x Way=%x Tag=%x\n", packed_addr, set, i, tag); - if (real_access) { - pline->last_used = sim_cycle; - if (write) { - pline->status |= DIRTY; - } - } - return pline; - } - } - } - if (real_access) { - cp->miss++; - shader_cache_access_log(cp->core_id, cp->type_id, 1); - } - return 0; -} - -shd_cache_line_t* shd_cache_access( shd_cache_t *cp, - unsigned long long int addr, - unsigned int nbytes, - unsigned char write, - unsigned int sim_cycle ) -{ - assert( cp->write_policy != write_back ); - return shd_cache_access_internal(cp,addr,nbytes,write,sim_cycle,1/*this is a real access*/); -} - -enum cache_request_status shd_cache_access_new( shd_cache_t *cp, - unsigned long long int addr, - unsigned int nbytes, - unsigned char write, - unsigned int sim_cycle, address_type *wb_address) +enum cache_request_status cache_t::access( unsigned long long int addr, + unsigned int nbytes, + unsigned char write, + unsigned int sim_cycle, + address_type *wb_address ) { + cache_t *cp = this; unsigned long long int bank_addr; // offset within bank bool all_reserved = true; - shd_cache_line_t *pending_line = NULL; - shd_cache_line_t *clean_line = NULL; + cache_block_t *pending_line = NULL; + cache_block_t *clean_line = NULL; if (cp->bank_mask) bank_addr = addrdec_packbits(cp->bank_mask, addr, 64, 0); else bank_addr = addr; - unsigned set = (bank_addr >> cp->line_sz_log2) & ( (1<<cp->nset_log2) - 1 ); - unsigned long long tag = bank_addr >> (cp->line_sz_log2 + cp->nset_log2); + unsigned set = (bank_addr >> cp->line_sz_log2) & ( (1<<cp->m_nset_log2) - 1 ); + unsigned long long tag = bank_addr >> (cp->line_sz_log2 + cp->m_nset_log2); - cp->access++; + cp->m_access++; shader_cache_access_log(cp->core_id, cp->type_id, 0); - for (unsigned way=0; way<cp->assoc; way++) { - shd_cache_line_t *line = &(cp->lines[set*cp->assoc+way] ); + for (unsigned way=0; way<cp->m_assoc; way++) { + cache_block_t *line = &(cp->m_lines[set*cp->m_assoc+way] ); if (line->tag == tag) { if (line->status & RESERVED) { pending_line = line; @@ -283,10 +204,10 @@ enum cache_request_status shd_cache_access_new( shd_cache_t *cp, } // no clean lines, need to kick a line out to reserve a spot - shd_cache_line_t *wb_line = NULL; + cache_block_t *wb_line = NULL; - for (unsigned way=0; way<cp->assoc; way++) { - shd_cache_line_t *line = &(cp->lines[set*cp->assoc+way] ); + for (unsigned way=0; way<cp->m_assoc; way++) { + cache_block_t *line = &(cp->m_lines[set*cp->m_assoc+way] ); if (line->status & VALID && !(line->status & RESERVED)) { if (!wb_line) { wb_line = line; @@ -317,91 +238,56 @@ enum cache_request_status shd_cache_access_new( shd_cache_t *cp, return MISS_W_WB; } -shd_cache_line_t* shd_cache_probe( shd_cache_t *cp, - unsigned long long int addr) -{ - return shd_cache_access_internal(cp,addr, - 1,0,0, /*do not matter*/ - 0/*this is just a probe*/); -} - -void shd_cache_undo_stats( shd_cache_t *cp, int miss ) -{ - if (miss) { - cp->miss--; - shader_cache_access_unlog(cp->core_id, cp->type_id, 1); - } - cp->access--; - shader_cache_access_unlog(cp->core_id, cp->type_id, 0); -} - // Obtain the windowed cache miss rate for visualizer -float shd_cache_windowed_cache_miss_rate( shd_cache_t *cp, int minus_merge_hit ) +float cache_t::shd_cache_windowed_cache_miss_rate( int minus_merge_hit ) { - unsigned int n_access = cp->access - cp->prev_snapshot_access; + cache_t *cp = this; + unsigned int n_access = cp->m_access - cp->prev_snapshot_access; unsigned int n_miss = cp->miss - cp->prev_snapshot_miss; unsigned int n_merge_hit = cp->merge_hit - cp->prev_snapshot_merge_hit; - if (minus_merge_hit) { + if (minus_merge_hit) n_miss -= n_merge_hit; - } float missrate = 0.0f; - if (n_access != 0) { + if (n_access != 0) missrate = (float) n_miss / n_access; - } return missrate; } // start a new sampling window -void shd_cache_new_window( shd_cache_t *cp ) +void cache_t::shd_cache_new_window() { - cp->prev_snapshot_access = cp->access; + cache_t *cp = this; + cp->prev_snapshot_access = cp->m_access; cp->prev_snapshot_miss = cp->miss; cp->prev_snapshot_merge_hit = cp->merge_hit; } -unsigned long long int L2_shd_cache_fill( shd_cache_t *cp, - unsigned long long int addr, - unsigned int sim_cycle ) { - unsigned long long int result = shd_cache_fill(cp, addr, sim_cycle); - return result; -} - static unsigned int _n_line_existed = 0; // debug counter // Fetch requested data into cache line. // Returning address on the replaced line if it is dirty, or -1 if it is clean // Assume the line is filled all at once. -unsigned long long int shd_cache_fill( shd_cache_t *cp, - unsigned long long int addr, - unsigned int sim_cycle ) { - - unsigned int i; - unsigned int set; - unsigned long long int tag; - unsigned long long int packed_addr; - unsigned long long int repl_addr; - - unsigned char nofreeslot; - unsigned char line_exists; +new_addr_type cache_t::shd_cache_fill( new_addr_type addr, unsigned int sim_cycle ) +{ + cache_t *cp = this; unsigned int base = 0 ; - unsigned int maxway = cp->assoc ; - - shd_cache_line_t *pline, *cline; - + unsigned int maxway = cp->m_assoc ; + cache_block_t *pline, *cline; + unsigned long long int packed_addr; if (cp->bank_mask) packed_addr = addrdec_packbits(cp->bank_mask, addr, 64, 0); else packed_addr = addr; - set = (packed_addr >> cp->line_sz_log2) & ( (1<<cp->nset_log2) - 1 ); - tag = packed_addr >> (cp->line_sz_log2 + cp->nset_log2); + unsigned set = (packed_addr >> cp->line_sz_log2) & ( (1<<cp->m_nset_log2) - 1 ); + unsigned long long tag = packed_addr >> (cp->line_sz_log2 + cp->m_nset_log2); if (cp->write_policy == write_back) { //this request must have a reserved spot cline = NULL; - for (i=base; i<maxway; i++) { - pline = &(cp->lines[set*cp->assoc+i] ); + for (unsigned i=base; i<maxway; i++) { + pline = &(cp->m_lines[set*cp->m_assoc+i] ); if ((pline->tag == tag) && (pline->status & RESERVED)) { cline = pline; break; @@ -435,17 +321,17 @@ unsigned long long int shd_cache_fill( shd_cache_t *cp, //behavior unchanged for write through cache... probably not all necessary. // Look for any free slots and the possibility that the line is in the cache already - nofreeslot = 1; - line_exists = 0; - for (i=base; i<maxway; i++) { - pline = &(cp->lines[set*cp->assoc+i] ); + bool nofreeslot = true; + bool line_exists = false; + for (unsigned i=base; i<maxway; i++) { + pline = &(cp->m_lines[set*cp->m_assoc+i] ); if (!(pline->status & VALID)) { cline = pline; - nofreeslot = 0; + nofreeslot = false; break; } else if (pline->tag == tag) { cline = pline; - line_exists = 1; + line_exists = true; break; } } @@ -456,9 +342,9 @@ unsigned long long int shd_cache_fill( shd_cache_t *cp, } if (nofreeslot) { - cline = &(cp->lines[set*cp->assoc+base] ); - for (i=1+base; i<maxway; i++) { - pline = &(cp->lines[set*cp->assoc+i] ); + cline = &(cp->m_lines[set*cp->m_assoc+base] ); + for (unsigned i=1+base; i<maxway; i++) { + pline = &(cp->m_lines[set*cp->m_assoc+i] ); if (pline->status & VALID) { switch (cp->policy) { case LRU: @@ -477,6 +363,7 @@ unsigned long long int shd_cache_fill( shd_cache_t *cp, } /* Set the replaced cache line address */ + unsigned long long int repl_addr; if ((cline->status & (DIRTY|VALID)) == (DIRTY|VALID)) { repl_addr = cline->addr; } else { @@ -494,20 +381,30 @@ unsigned long long int shd_cache_fill( shd_cache_t *cp, return repl_addr; } -void shd_cache_mergehit( shd_cache_t *cp, unsigned long long int addr ) +unsigned int cache_t::flush() { - cp->merge_hit += 1; + cache_t *cp = this; + int dirty_lines_flushed = 0 ; + for (unsigned i = 0; i < cp->m_nset * cp->m_assoc ; i++) { + if ( (cp->m_lines[i].status & (DIRTY|VALID)) == (DIRTY|VALID) ) { + dirty_lines_flushed++; + } + cp->m_lines[i].status &= ~VALID; + cp->m_lines[i].status &= ~DIRTY; + } + return dirty_lines_flushed; } -void shd_cache_print( const shd_cache_t *cp, FILE *stream, unsigned &total_access, unsigned &total_misses ) +void cache_t::shd_cache_print( FILE *stream, unsigned &total_access, unsigned &total_misses ) { - fprintf( stream, "Cache %s:\t", cp->name); + cache_t *cp = this; + fprintf( stream, "Cache %s:\t", cp->m_name); fprintf( stream, "Size = %d B (%d Set x %d-way x %d byte line)\n", - cp->line_sz * cp->nset * cp->assoc, - cp->nset, cp->assoc, cp->line_sz ); + cp->m_line_sz * cp->m_nset * cp->m_assoc, + cp->m_nset, cp->m_assoc, cp->m_line_sz ); fprintf( stream, "\t\tAccess = %d, Miss = %d (%.3g), -MgHts = %d (%.3g)\n", - cp->access, cp->miss, (float) cp->miss / cp->access, - cp->miss - cp->merge_hit, (float) (cp->miss - cp->merge_hit) / cp->access); + cp->m_access, cp->miss, (float) cp->miss / cp->m_access, + cp->miss - cp->merge_hit, (float) (cp->miss - cp->merge_hit) / cp->m_access); total_misses+=cp->miss; - total_access+=cp->access; + total_access+=cp->m_access; } diff --git a/src/gpgpu-sim/gpu-cache.h b/src/gpgpu-sim/gpu-cache.h index 3b4bf73..6efb42d 100644 --- a/src/gpgpu-sim/gpu-cache.h +++ b/src/gpgpu-sim/gpu-cache.h @@ -85,8 +85,7 @@ enum cache_request_status { NUM_CACHE_REQUEST_STATUS }; - -struct shd_cache_line_t { +struct cache_block_t { unsigned long long int tag; unsigned long long int addr; unsigned int set; @@ -96,7 +95,6 @@ struct shd_cache_line_t { unsigned char status; /* valid, dirty... etc */ }; - #define LRU 'L' #define FIFO 'F' #define RANDOM 'R' @@ -107,21 +105,44 @@ enum cache_write_policy{ write_through //reservation based, use much handle reservation full error. }; -struct shd_cache_t { +class cache_t { +public: + cache_t( const char *name, + const char *opt, + unsigned long long int bank_mask, + enum cache_write_policy wp, + int core_id, + int type_id); + ~cache_t(); + + enum cache_request_status access( new_addr_type addr, + unsigned int nbytes, + unsigned char write, + unsigned int sim_cycle, + address_type *wb_address); - char *name; + new_addr_type shd_cache_fill( new_addr_type addr, unsigned int sim_cycle ); + + unsigned flush(); + + void shd_cache_print( FILE *stream, unsigned &total_access, unsigned &total_misses ); + float shd_cache_windowed_cache_miss_rate(int); + void shd_cache_new_window(); + unsigned get_line_sz() const { return m_line_sz; } - shd_cache_line_t *lines; /* nset x assoc lines in total */ - unsigned int nset; - unsigned int nset_log2; - unsigned int assoc; - unsigned int line_sz; // bytes +private: + char *m_name; + + cache_block_t *m_lines; /* nset x assoc lines in total */ + unsigned int m_nset; + unsigned int m_nset_log2; + unsigned int m_assoc; + unsigned int m_line_sz; // bytes unsigned int line_sz_log2; enum cache_write_policy write_policy; unsigned char policy; - unsigned int hit_latency; - unsigned int access; + unsigned int m_access; unsigned int miss; unsigned int merge_hit; // number of cache miss that hit the same line (and merged as a result) @@ -135,54 +156,7 @@ struct shd_cache_t { unsigned long long int bank_mask; + class linear_histogram_logger *m_logger; }; -shd_cache_t * shd_cache_create( const char *name, - const char *opt, - unsigned int hit_latency, - unsigned long long int bank_mask, - enum cache_write_policy wp); - -void shd_cache_destroy( shd_cache_t* cp ); - -// hook up with shader core logger -void shd_cache_bind_logger(shd_cache_t* cp, int core_id, int type_id); - -// depricated use shd_cache_access_new -shd_cache_line_t* shd_cache_access( shd_cache_t *cp, - unsigned long long int addr, - unsigned int nbytes, - unsigned char write, - unsigned int sim_cycle ); - -enum cache_request_status shd_cache_access_new( shd_cache_t *cp, - unsigned long long int addr, - unsigned int nbytes, - unsigned char write, - unsigned int sim_cycle, - address_type *wb_address); - - -//just probe the tag array to see if addr is in the cache or not -//does not update LRU or stats... -shd_cache_line_t* shd_cache_probe( shd_cache_t *cp, - unsigned long long int addr); - -// undo the statistic record when the memory access is stalled/squashed and will try again next cycle -void shd_cache_undo_stats( shd_cache_t *cp, int miss ); - -void shd_cache_mergehit( shd_cache_t *cp, unsigned long long int addr ); - -unsigned long long int shd_cache_fill( shd_cache_t *cp, - unsigned long long int addr, - unsigned int sim_cycle ); - -unsigned long long int L2_shd_cache_fill( shd_cache_t *cp, - unsigned long long int addr, - unsigned int sim_cycle ); - -void shd_cache_print( const shd_cache_t *cp, FILE *stream, unsigned &total_access, unsigned &total_misses ); -float shd_cache_windowed_cache_miss_rate(shd_cache_t*, int); -void shd_cache_new_window(shd_cache_t*); - #endif diff --git a/src/gpgpu-sim/gpu-misc.cc b/src/gpgpu-sim/gpu-misc.cc index 06a0f68..c5ad288 100644 --- a/src/gpgpu-sim/gpu-misc.cc +++ b/src/gpgpu-sim/gpu-misc.cc @@ -80,17 +80,3 @@ unsigned int LOGB2( unsigned int v ) { return r; } - -unsigned int MAX2NUM( unsigned int a, unsigned int b ) { - if (a > b) { - return a; - } else - return b; -} - -unsigned int MIN2NUM( unsigned int a, unsigned int b ) { - if (a < b) { - return a; - } else - return b; -} diff --git a/src/gpgpu-sim/gpu-misc.h b/src/gpgpu-sim/gpu-misc.h index ffe316b..57f991a 100644 --- a/src/gpgpu-sim/gpu-misc.h +++ b/src/gpgpu-sim/gpu-misc.h @@ -67,30 +67,12 @@ #ifndef GPU_MISC_H #define GPU_MISC_H -#define CONSTC 100 -#define DCACHE 200 -#define TEXTC 300 -#define SHD_CACHE_TAG(x,shdr) ((x) & (~((unsigned long long int)shdr->m_L1D->line_sz - 1))) -#define SHD_TEXCACHE_TAG(x,shdr) ((x) & (~((unsigned long long int)shdr->m_L1T->line_sz - 1))) -#define SHD_CONSTCACHE_TAG(x,shdr) ((x) & (~((unsigned long long int)shdr->m_L1C->line_sz - 1))) -#define CACHE_TAG_OF(x,cache) ((x) & (~((unsigned long long int)cache->line_sz - 1))) -#define CACHE_TAG_OF_64(x) ((x) & (~((unsigned long long int)64 - 1))) - -#define ispowerof2(x) ((((x) - 1) & (x)) == 0) -#define powerof2(x) (1 << (x)) - //enables a verbose printout of all L1 cache misses and all MSHR status changes //good for a single shader configuration #define DEBUGL1MISS 0 unsigned int LOGB2( unsigned int v ); -unsigned int MAX2NUM( unsigned int a, unsigned int b ); - -unsigned int MIN2NUM( unsigned int a, unsigned int b ); - - -#define gs_max2(a,b) (((a)>(b))?(a):(b)) #define gs_min2(a,b) (((a)<(b))?(a):(b)) #define min3(x,y,z) (((x)<(y) && (x)<(z))?(x):(gs_min2((y),(z)))) diff --git a/src/gpgpu-sim/gpu-sim.cc b/src/gpgpu-sim/gpu-sim.cc index 8114b9e..dc76f53 100644 --- a/src/gpgpu-sim/gpu-sim.cc +++ b/src/gpgpu-sim/gpu-sim.cc @@ -1074,18 +1074,18 @@ void shader_core_ctx::fill_shd_L1_with_new_line(mem_fetch * mf) // When the data arrives, it flags all the appropriate MSHR // entries accordingly (by checking the address in each entry ) if (mf->mshr->isinst()) { - shd_cache_fill(m_L1I,mf->addr,gpu_sim_cycle+gpu_tot_sim_cycle); + m_L1I->shd_cache_fill(mf->addr,gpu_sim_cycle+gpu_tot_sim_cycle); m_warp[mf->mshr->get_warp_id()].clear_imiss_pending(); delete mf->mshr; mf->mshr=NULL; } else { m_mshr_unit->mshr_return_from_mem(mf->mshr); if (mf->mshr->istexture()) - shd_cache_fill(m_L1T,mf->addr,gpu_sim_cycle+gpu_tot_sim_cycle); + m_L1T->shd_cache_fill(mf->addr,gpu_sim_cycle+gpu_tot_sim_cycle); else if (mf->mshr->isconst()) - shd_cache_fill(m_L1C,mf->addr,gpu_sim_cycle+gpu_tot_sim_cycle); + m_L1C->shd_cache_fill(mf->addr,gpu_sim_cycle+gpu_tot_sim_cycle); else if (!m_config->gpgpu_no_dl1) - shd_cache_fill(m_L1D,mf->addr,gpu_sim_cycle+gpu_tot_sim_cycle); + m_L1D->shd_cache_fill(mf->addr,gpu_sim_cycle+gpu_tot_sim_cycle); } freed_read_mfs++; delete mf; @@ -1189,10 +1189,10 @@ void shader_core_ctx::issue_block2core( kernel_info_t &kernel ) /////////////////////////////////////////////////////////////////////////////////////////// // wrapper code to to create an illusion of a memory controller with L2 cache. -//#define DEBUG_PARTIAL_WRITES void memory_partition_unit::push( mem_fetch* req, unsigned long long cycle ) { if (req) { + m_request_tracker.insert(req); rop_delay_t r; r.req = req; r.ready_cycle = cycle + 115; // Add 115*4=460 delay cycles @@ -1209,12 +1209,11 @@ void memory_partition_unit::push( mem_fetch* req, unsigned long long cycle ) time_vector_update(mf->request_uid ,MR_DRAMQ,gpu_sim_cycle+gpu_tot_sim_cycle,mf->type ) ; } m_stats->memlatstat_icnt2mem_pop(mf); - request_tracker_insert(mf); if (m_config->gpgpu_cache_dl2_opt) { if (m_config->gpgpu_l2_readoverwrite && mf->m_write) - cbtoL2writequeue->push(mf,gpu_sim_cycle); + m_icnt2cache_write_queue->push(mf,gpu_sim_cycle); else - cbtoL2queue->push(mf,gpu_sim_cycle); + m_icnt2cache_queue->push(mf,gpu_sim_cycle); m_accessLocality->access(mf); if (mf->mshr) mf->mshr->set_status(IN_CBTOL2QUEUE); } else { @@ -1228,7 +1227,7 @@ mem_fetch* memory_partition_unit::pop() { mem_fetch* mf; if (m_config->gpgpu_cache_dl2_opt) { - mf = L2c_pop(m_dram); + mf = L2tocbqueue->pop(gpu_sim_cycle); if (mf && mf->mshr && mf->mshr->isatomic() ) { dram_callback_t &cb = mf->mshr->get_atomic_callback(); cb.function(cb.instruction, cb.thread); @@ -1241,7 +1240,7 @@ mem_fetch* memory_partition_unit::pop() cb.function(cb.instruction, cb.thread); } } - request_tracker_erase(mf); + m_request_tracker.erase(mf); return mf; } @@ -1258,25 +1257,27 @@ mem_fetch* memory_partition_unit::top() void memory_partition_unit::issueCMD() { - mem_fetch* mf_top = m_dram->top(); - if (mf_top) { - if (mf_top->type == DUMMY_READ) { - m_dram->pop(); - free(mf_top); - freed_dummy_read_mfs++; - return; - } - } if (m_config->gpgpu_cache_dl2_opt) { - L2c_get_dram_output(); + // pop completed memory request from dram and push it to dram-to-L2 queue + if ( !(dramtoL2queue->full() || dramtoL2writequeue->full()) ) { + mem_fetch* mf = m_dram->pop(); + if (mf) { + if (m_config->gpgpu_l2_readoverwrite && mf->m_write) + dramtoL2writequeue->push(mf,gpu_sim_cycle); + else + dramtoL2queue->push(mf,gpu_sim_cycle); + if (mf->mshr) + mf->mshr->set_status(IN_DRAMTOL2QUEUE); + } + } } else { if ( m_dram->returnq_full() ) return; mem_fetch* mf = m_dram->pop(); - assert (mf_top==mf ); if (mf) { m_dram->returnq_push(mf,gpu_sim_cycle); - if (mf->mshr) mf->mshr->set_status(IN_DRAMRETURN_Q); + if (mf->mshr) + mf->mshr->set_status(IN_DRAMRETURN_Q); } } m_dram->issueCMD(); @@ -1413,18 +1414,18 @@ void gpgpu_sim::gpu_sim_loop() if (gpgpu_flush_cache) { int all_threads_complete = 1 ; for (unsigned i=0;i<m_n_shader;i++) { - if (m_sc[i]->get_not_completed() == 0) { + if (m_sc[i]->get_not_completed() == 0) m_sc[i]->cache_flush(); - } else { + else all_threads_complete = 0 ; - } } if (all_threads_complete) { - printf("Flushed L1 caches...\n"); + printf("Flushed L2 caches...\n"); if (m_memory_config->gpgpu_cache_dl2_opt) { int dlc = 0; for (unsigned i=0;i<m_n_mem;i++) { - dlc = m_memory_partition_unit[i]->L2c_cache_flush(); + dlc = m_memory_partition_unit[i]->flushL2(); + assert (dlc == 0); // need to model actual writes to DRAM here printf("Dirty lines flushed from L2 %d is %d\n", i, dlc ); } } @@ -1547,6 +1548,7 @@ void gpgpu_sim::dump_pipeline( int mask, int s, int m ) const printf("DRAM / memory controller %u:\n", i); if(mask&0x100000) m_memory_partition_unit[i]->print_stat(stdout); if(mask&0x1000000) m_memory_partition_unit[i]->visualize(); + if(mask&0x10000000) m_memory_partition_unit[i]->print(stdout); if(m != -1) { break; } diff --git a/src/gpgpu-sim/l2cache.cc b/src/gpgpu-sim/l2cache.cc index cbed2e9..0bf8af6 100644 --- a/src/gpgpu-sim/l2cache.cc +++ b/src/gpgpu-sim/l2cache.cc @@ -296,7 +296,7 @@ void memory_partition_unit::set_stats( class memory_stats_t *stats ) void memory_partition_unit::cache_cycle() { - L2c_process_dram_output(); // pop from dram + process_dram_output(); // pop from dram L2c_push_miss_to_dram(); // push to dram L2c_service_mem_req(); // pop(push) from(to) icnt2l2(l2toicnt) queues; service l2 requests if (m_config->gpgpu_cache_dl2_opt) { // L2 cache enabled @@ -307,13 +307,13 @@ void memory_partition_unit::cache_cycle() unsigned memory_partition_unit::L2c_get_linesize() { - return L2cache->line_sz; + return m_L2cache->get_line_sz(); } bool memory_partition_unit::full() const { if (m_config->gpgpu_cache_dl2_opt) { - return cbtoL2queue->full() || cbtoL2writequeue->full(); + return m_icnt2cache_queue->full() || m_icnt2cache_write_queue->full(); } else { return( m_config->gpgpu_dram_sched_queue_size && m_dram->full() ); } @@ -330,16 +330,15 @@ memory_partition_unit::memory_partition_unit( unsigned partition_id, struct memo m_stats=NULL; m_dram = new dram_t(m_id, m_config); - char L2c_name[32]; - snprintf(L2c_name, 32, "L2_%03d", m_id); - if( m_config->gpgpu_cache_dl2_opt ) { - L2cache = shd_cache_create(L2c_name,m_config->gpgpu_cache_dl2_opt, 16, ~addrdec_mask[CHIP], write_through); - m_mshr = new L2c_mshr(L2cache->line_sz); - m_missTracker = new L2c_miss_tracker(L2cache->line_sz); - m_accessLocality = new L2c_access_locality(L2cache->line_sz); + char L2c_name[32]; + snprintf(L2c_name, 32, "L2_%03d", m_id); + m_L2cache = new cache_t(L2c_name,m_config->gpgpu_cache_dl2_opt, ~addrdec_mask[CHIP], write_through, -1, -1 ); + m_mshr = new L2c_mshr(m_L2cache->get_line_sz()); + m_missTracker = new L2c_miss_tracker(m_L2cache->get_line_sz()); + m_accessLocality = new L2c_access_locality(m_L2cache->get_line_sz()); } else { - L2cache=NULL; + m_L2cache=NULL; m_mshr=NULL; m_missTracker=NULL; m_accessLocality=NULL; @@ -359,19 +358,18 @@ memory_partition_unit::memory_partition_unit( unsigned partition_id, struct memo &L2c_dm_L2_length, &L2c_dm_L2w_length, &L2c_L2_cb_length, &L2c_L2_cb_minlength, &L2c_L2_dm_minlength ); //(<name>,<latency>,<min_length>,<max_length>) - cbtoL2queue = new fifo_pipeline<mem_fetch>("cbtoL2queue", 0,L2c_cb_L2_length, gpu_sim_cycle); - cbtoL2writequeue = new fifo_pipeline<mem_fetch>("cbtoL2writequeue", 0,L2c_cb_L2w_length, gpu_sim_cycle); + m_icnt2cache_queue = new fifo_pipeline<mem_fetch>("cbtoL2queue", 0,L2c_cb_L2_length, gpu_sim_cycle); + m_icnt2cache_write_queue = new fifo_pipeline<mem_fetch>("cbtoL2writequeue", 0,L2c_cb_L2w_length, gpu_sim_cycle); L2todramqueue = new fifo_pipeline<mem_fetch>("L2todramqueue", L2c_L2_dm_minlength, L2c_L2_dm_length, gpu_sim_cycle); dramtoL2queue = new fifo_pipeline<mem_fetch>("dramtoL2queue", 0,L2c_dm_L2_length, gpu_sim_cycle); dramtoL2writequeue = new fifo_pipeline<mem_fetch>("dramtoL2writequeue",0,L2c_dm_L2w_length, gpu_sim_cycle); L2tocbqueue = new fifo_pipeline<mem_fetch>("L2tocbqueue", L2c_L2_cb_minlength, L2c_L2_cb_length, gpu_sim_cycle); L2todram_wbqueue = new fifo_pipeline<mem_fetch>("L2todram_wbqueue", L2c_L2_dm_minlength, L2c_L2_dm_minlength + m_config->gpgpu_dram_sched_queue_size + L2c_dm_L2_length, gpu_sim_cycle); - L2request = NULL; L2dramout = NULL; wb_addr=-1; if (m_config->gpgpu_cache_dl2_opt && 1) { - cbtol2_Dist = StatCreate("cbtoL2",1, cbtoL2queue->get_max_len()); - cbtoL2wr_Dist = StatCreate("cbtoL2write",1, cbtoL2writequeue->get_max_len()); + cbtol2_Dist = StatCreate("cbtoL2",1, m_icnt2cache_queue->get_max_len()); + cbtoL2wr_Dist = StatCreate("cbtoL2write",1, m_icnt2cache_write_queue->get_max_len()); L2tocb_Dist = StatCreate("L2tocb",1, L2tocbqueue->get_max_len()); dramtoL2_Dist = StatCreate("dramtoL2",1, dramtoL2queue->get_max_len()); dramtoL2wr_Dist = StatCreate("dramtoL2write",1, dramtoL2writequeue->get_max_len()); @@ -388,83 +386,49 @@ memory_partition_unit::memory_partition_unit( unsigned partition_id, struct memo } } -mem_fetch* memory_partition_unit::L2c_pop( dram_t *dram_p ) -{ - assert(dram_p->m_memory_partition_unit != NULL); - memory_partition_unit *p_L2c = reinterpret_cast<memory_partition_unit*>(dram_p->m_memory_partition_unit); - - mem_fetch *mf; - mf = p_L2c->L2tocbqueue->pop(gpu_sim_cycle); - - return mf; -} - -// service memory request in icnt-to-L2 queue, writing to L2 as necessary -// (if L2 writeback miss, writeback to memory) void memory_partition_unit::L2c_service_mem_req() { - if (!L2request) { - //if not servicing L2 cache request.. - L2request = cbtoL2queue->pop(gpu_sim_cycle); //..then get one - if (!L2request) - L2request = cbtoL2writequeue->pop(gpu_sim_cycle); - } - - mem_fetch* mf = L2request; - - if (!mf) return; - + // service memory request in icnt-to-L2 queue, writing to L2 as necessary + if( L2tocbqueue->full() || L2todramqueue->full() ) + return; + mem_fetch* mf = m_icnt2cache_queue->pop(gpu_sim_cycle); + if( !mf ) + mf = m_icnt2cache_write_queue->pop(gpu_sim_cycle); + if( !mf ) + return; switch (mf->type) { case RD_REQ: case WT_REQ: { - shd_cache_line_t *hit_cacheline = shd_cache_access(L2cache, - mf->addr, - 4, mf->m_write, - gpu_sim_cycle); - - if (hit_cacheline || m_config->l2_ideal) { //L2 Cache Hit; reads are sent as a single command and need to be stored - if (!mf->m_write) { //L2 Cache Read - if ( L2tocbqueue->full() ) { - L2cache->access--; - } else { - mf->type = REPLY_DATA; - L2tocbqueue->push(mf,gpu_sim_cycle); - // at this point, should first check if earlier L2 miss is ready to be serviced - // if so, service earlier L2 miss first - L2request = NULL; //finished servicing - m_stats->L2_read_hit++; - m_stats->memlatstat_icnt2sh_push(mf); - if (mf->mshr) mf->mshr->set_status(IN_L2TOCBQUEUE_HIT); - } - } else { //L2 Cache Write aka servicing L1 Writeback - L2request = NULL; + address_type rep_block; + enum cache_request_status status = m_L2cache->access( mf->addr, 4, mf->m_write, gpu_sim_cycle, &rep_block); + if( (status==HIT) || m_config->l2_ideal ) { + mf->type = REPLY_DATA; + L2tocbqueue->push(mf,gpu_sim_cycle); + if (!mf->m_write) { + m_stats->L2_read_hit++; + m_stats->memlatstat_icnt2sh_push(mf); + if (mf->mshr) + mf->mshr->set_status(IN_L2TOCBQUEUE_HIT); + } else { m_stats->L2_write_hit++; freed_L1write_mfs++; - free(mf); //writeback from L1 successful gpgpu_n_processed_writes++; } } else { - // L2 Cache Miss; issue commands accordingly - if ( L2todramqueue->full() ) { - L2cache->miss--; - L2cache->access--; - } else { - // if a miss hit the mshr, that means there is another inflight request for the same data - // this miss just need to access the cache later when this request is serviced - bool mshr_hit = m_mshr->new_miss(mf); - if (not mshr_hit) { - if (!mf->m_write) { - L2todramqueue->push(mf,gpu_sim_cycle); - } else { - // if request is writeback from L1 and misses, - // then redirect mf writes to dram (no write allocate) - mf->nbytes_L2 = mf->nbytes_L1 - READ_PACKET_SIZE; - L2todramqueue->push(mf,gpu_sim_cycle); - } + // L2 Cache Miss + // if a miss hits in the mshr, that means there is another inflight request for the same data + // this miss just need to access the cache later when this request is serviced + bool mshr_hit = m_mshr->new_miss(mf); + if (not mshr_hit) { + if (mf->m_write) { + // if request is writeback from L1 and misses, + // then redirect mf writes to dram (no write allocate) + mf->nbytes_L2 = mf->nbytes_L1 - READ_PACKET_SIZE; } - if (mf->mshr) mf->mshr->set_status(IN_L2TODRAMQUEUE); - L2request = NULL; + L2todramqueue->push(mf,gpu_sim_cycle); } + if (mf->mshr) + mf->mshr->set_status(IN_L2TODRAMQUEUE); } } break; @@ -477,7 +441,6 @@ void memory_partition_unit::L2c_push_miss_to_dram() { if ( m_config->gpgpu_dram_sched_queue_size && m_dram->full() ) return; - mem_fetch* mf = L2todram_wbqueue->pop(gpu_sim_cycle); //prioritize writeback if (!mf) mf = L2todramqueue->pop(gpu_sim_cycle); if (mf) { @@ -492,27 +455,9 @@ void memory_partition_unit::L2c_push_miss_to_dram() } } -// pop completed memory request from dram and push it to dram-to-L2 queue -void memory_partition_unit::L2c_get_dram_output () -{ - mem_fetch* mf; - mem_fetch* mf_top; - if ( dramtoL2queue->full() || dramtoL2writequeue->full() ) return; - mf_top = m_dram->top(); - mf = m_dram->pop(); - assert (mf_top==mf ); - if (mf) { - if (m_config->gpgpu_l2_readoverwrite && mf->m_write) - dramtoL2writequeue->push(mf,gpu_sim_cycle); - else - dramtoL2queue->push(mf,gpu_sim_cycle); - if (mf->mshr) mf->mshr->set_status(IN_DRAMTOL2QUEUE); - } -} - // service memory request in dramtoL2queue, writing to L2 as necessary // (may cause cache eviction and subsequent writeback) -void memory_partition_unit::L2c_process_dram_output() +void memory_partition_unit::process_dram_output() { if (L2dramout == NULL) { // pop from mshr chain if it is not empty, otherwise, pop a new cacheline from dram output queue @@ -521,11 +466,10 @@ void memory_partition_unit::L2c_process_dram_output() m_mshr->mshr_chain_pop(); } else { L2dramout = dramtoL2queue->pop(gpu_sim_cycle); - if (!L2dramout) L2dramout = dramtoL2writequeue->pop(gpu_sim_cycle); - + if (!L2dramout) + L2dramout = dramtoL2writequeue->pop(gpu_sim_cycle); if (L2dramout != NULL) { m_mshr->miss_serviced(L2dramout); - if (m_mshr->mshr_chain_empty() == false) { // possible if this is a L2 writeback L2dramout = m_mshr->mshr_chain_top(); m_mshr->mshr_chain_pop(); @@ -533,47 +477,45 @@ void memory_partition_unit::L2c_process_dram_output() } } } - mem_fetch* mf = L2dramout; if (mf) { if (!mf->m_write) { //service L2 read miss - // it is a pre-fill dramout mf if (wb_addr == (unsigned long long int)-1) { - if ( L2tocbqueue->full() ) goto RETURN; - - if (mf->mshr) mf->mshr->set_status(IN_L2TOCBQUEUE_MISS); - + if ( L2tocbqueue->full() ) { + assert (L2dramout || wb_addr == (unsigned long long int)-1); + return; + } + if (mf->mshr) + mf->mshr->set_status(IN_L2TOCBQUEUE_MISS); //only transfer across icnt once the whole line has been received by L2 cache mf->type = REPLY_DATA; L2tocbqueue->push(mf,gpu_sim_cycle); - - shd_cache_line_t *fetch_line_exist = shd_cache_probe(L2cache, mf->addr); - if (fetch_line_exist == NULL) { - wb_addr = L2_shd_cache_fill(L2cache, mf->addr, gpu_sim_cycle ); - } + wb_addr = m_L2cache->shd_cache_fill(mf->addr, gpu_sim_cycle); } // only perform a write on cache eviction (write-back policy) // it is the 1st or nth time trial to writeback if (wb_addr != (unsigned long long int)-1) { // performing L2 writeback (no false sharing for memory-side cache) - int wb_succeed = L2c_write_back(wb_addr, L2cache->line_sz); - if (!wb_succeed) goto RETURN; //try again next cycle + int wb_succeed = L2c_write_back(wb_addr, m_L2cache->get_line_sz()); + if (!wb_succeed) { + assert (L2dramout || wb_addr == (unsigned long long int)-1); + return; + } } - m_missTracker->miss_serviced(mf); L2dramout = NULL; wb_addr = -1; } else { //service L2 write miss m_missTracker->miss_serviced(mf); freed_L2write_mfs++; - free(mf); + m_request_tracker.erase(mf); + delete mf; gpgpu_n_processed_writes++; L2dramout = NULL; wb_addr = -1; } } - RETURN: assert (L2dramout || wb_addr == (unsigned long long int)-1); } @@ -599,36 +541,37 @@ bool memory_partition_unit::L2c_write_back( unsigned long long int addr, int bsi return true; } -unsigned int memory_partition_unit::L2c_cache_flush() -{ - shd_cache_t *cp = L2cache; - int dirty_lines_flushed = 0 ; - for (unsigned i = 0; i < cp->nset * cp->assoc ; i++) { - if ( (cp->lines[i].status & (DIRTY|VALID)) == (DIRTY|VALID) ) { - dirty_lines_flushed++; - } - cp->lines[i].status &= ~VALID; - cp->lines[i].status &= ~DIRTY; - } - return dirty_lines_flushed; -} - void memory_partition_unit::L2c_print_cache_stat(unsigned &accesses, unsigned &misses) const { FILE *fp = stdout; - shd_cache_print(L2cache,fp,accesses,misses); + m_L2cache->shd_cache_print(fp,accesses,misses); m_mshr->print_stat(fp); m_missTracker->print_stat(fp); m_accessLocality->print_stat(fp, false); } +void memory_partition_unit::print( FILE *fp ) const +{ + if( !m_request_tracker.empty() ) { + fprintf(fp,"Memory Parition %u: pending memory requests:\n", m_id); + for( std::set<mem_fetch*>::const_iterator r=m_request_tracker.begin(); r != m_request_tracker.end(); ++r ) { + mem_fetch *mf = *r; + if( mf ) + mf->print(fp); + else + fprintf(fp," <NULL mem_fetch?>\n"); + } + } + m_dram->print(fp); +} + void memory_partition_unit::L2c_update_stat() { unsigned i=m_id; - if (cbtoL2queue->get_length() > m_stats->L2_cbtoL2length[i]) - m_stats->L2_cbtoL2length[i] = cbtoL2queue->get_length(); - if (cbtoL2writequeue->get_length() > m_stats->L2_cbtoL2writelength[i]) - m_stats->L2_cbtoL2writelength[i] = cbtoL2writequeue->get_length(); + if (m_icnt2cache_queue->get_length() > m_stats->L2_cbtoL2length[i]) + m_stats->L2_cbtoL2length[i] = m_icnt2cache_queue->get_length(); + if (m_icnt2cache_write_queue->get_length() > m_stats->L2_cbtoL2writelength[i]) + m_stats->L2_cbtoL2writelength[i] = m_icnt2cache_write_queue->get_length(); if (L2tocbqueue->get_length() > m_stats->L2_L2tocblength[i]) m_stats->L2_L2tocblength[i] = L2tocbqueue->get_length(); if (dramtoL2queue->get_length() > m_stats->L2_dramtoL2length[i]) @@ -759,8 +702,8 @@ void gpgpu_sim::L2c_print_debug() void memory_partition_unit::L2c_log(int task) { if (task == SAMPLELOG) { - StatAddSample(cbtol2_Dist, cbtoL2queue->get_length()); - StatAddSample(cbtoL2wr_Dist, cbtoL2writequeue->get_length()); + StatAddSample(cbtol2_Dist, m_icnt2cache_queue->get_length()); + StatAddSample(cbtoL2wr_Dist, m_icnt2cache_write_queue->get_length()); StatAddSample(L2tocb_Dist, L2tocbqueue->get_length()); StatAddSample(dramtoL2_Dist, dramtoL2queue->get_length()); StatAddSample(dramtoL2wr_Dist, dramtoL2writequeue->get_length()); @@ -777,6 +720,11 @@ void memory_partition_unit::L2c_log(int task) } } +unsigned memory_partition_unit::flushL2() +{ + return m_L2cache->flush(); +} + void gpgpu_sim::L2c_latency_log_dump() { for (unsigned i=0;i<m_n_mem;i++) @@ -785,8 +733,8 @@ void gpgpu_sim::L2c_latency_log_dump() void memory_partition_unit::L2c_latency_log_dump() { - printf ("(LOGB2)Latency DRAM[%u] ",m_id); StatDisp(cbtoL2queue->get_lat_stat()); - printf ("(LOGB2)Latency DRAM[%u] ",m_id); StatDisp(cbtoL2writequeue->get_lat_stat()); + printf ("(LOGB2)Latency DRAM[%u] ",m_id); StatDisp(m_icnt2cache_queue->get_lat_stat()); + printf ("(LOGB2)Latency DRAM[%u] ",m_id); StatDisp(m_icnt2cache_write_queue->get_lat_stat()); printf ("(LOGB2)Latency DRAM[%u] ",m_id); StatDisp(L2tocbqueue->get_lat_stat()); printf ("(LOGB2)Latency DRAM[%u] ",m_id); StatDisp(dramtoL2queue->get_lat_stat()); printf ("(LOGB2)Latency DRAM[%u] ",m_id); StatDisp(dramtoL2writequeue->get_lat_stat()); @@ -799,12 +747,3 @@ bool memory_partition_unit::busy() const return !m_request_tracker.empty(); } -void memory_partition_unit::request_tracker_insert(class mem_fetch *mf) -{ - m_request_tracker.insert(mf); -} - -void memory_partition_unit::request_tracker_erase(class mem_fetch *mf) -{ - m_request_tracker.erase(mf); -} diff --git a/src/gpgpu-sim/l2cache.h b/src/gpgpu-sim/l2cache.h index 55202ee..b2bafb2 100644 --- a/src/gpgpu-sim/l2cache.h +++ b/src/gpgpu-sim/l2cache.h @@ -174,7 +174,7 @@ public: void cache_cycle(); - bool has_cache() { return L2cache != NULL; } + bool has_cache() { return m_L2cache != NULL; } unsigned L2c_get_linesize(); bool full() const; bool busy() const; @@ -186,11 +186,11 @@ public: void visualizer_print( gzFile visualizer_file ); void L2c_latency_log_dump(); void L2c_log(int task); - unsigned L2c_cache_flush(); + unsigned flushL2(); void L2c_print_cache_stat(unsigned &accesses, unsigned &misses) const; - unsigned get_cbtoL2queue_length() const { return cbtoL2queue->get_length(); } - unsigned get_cbtoL2writequeue_length() const { return cbtoL2writequeue->get_length(); } + unsigned get_cbtoL2queue_length() const { return m_icnt2cache_queue->get_length(); } + unsigned get_cbtoL2writequeue_length() const { return m_icnt2cache_write_queue->get_length(); } unsigned get_dramtoL2queue_length() const { return dramtoL2queue->get_length(); } unsigned get_dramtoL2writequeue_length() const { return dramtoL2writequeue->get_length(); } unsigned get_L2todramqueue_length() const { return L2todramqueue->get_length(); } @@ -201,14 +201,9 @@ public: void visualize() const { m_dram->visualize(); } unsigned dram_que_length() const { return m_dram->que_length(); } void queue_latency_log_dump( FILE *fp ) { m_dram->queue_latency_log_dump(fp); } - void print( FILE *fp ) { m_dram->print(fp); } + void print( FILE *fp ) const; private: - void request_tracker_insert(class mem_fetch *mf); - void request_tracker_erase(class mem_fetch *mf); - - // pop completed memory request from dram and push it to dram-to-L2 queue - void L2c_get_dram_output(); // service memory request in icnt-to-L2 queue, writing to L2 as necessary // (if L2 writeback miss, writeback to memory) @@ -219,13 +214,10 @@ private: // service memory request in dramtoL2queue, writing to L2 as necessary // (may cause cache eviction and subsequent writeback) - void L2c_process_dram_output(); + void process_dram_output(); bool L2c_write_back( unsigned long long int addr, int bsize ); - // probe L2 cache for fullness - struct mem_fetch* L2c_pop( dram_t *dram_p ); - void L2c_init_stat(unsigned n_mem); void L2c_update_stat(); void L2c_print_debug(); @@ -234,7 +226,7 @@ private: unsigned m_id; struct memory_config *m_config; class dram_t *m_dram; - struct shd_cache_t *L2cache; + class cache_t *m_L2cache; // model delay of ROP units with a fixed latency struct rop_delay_t @@ -245,15 +237,13 @@ private: std::queue<rop_delay_t> m_rop; // these are various FIFOs between units within a memory partition - fifo_pipeline<mem_fetch> *cbtoL2queue; - fifo_pipeline<mem_fetch> *cbtoL2writequeue; + fifo_pipeline<mem_fetch> *m_icnt2cache_queue; + fifo_pipeline<mem_fetch> *m_icnt2cache_write_queue; fifo_pipeline<mem_fetch> *dramtoL2queue; fifo_pipeline<mem_fetch> *dramtoL2writequeue; fifo_pipeline<mem_fetch> *L2todramqueue; fifo_pipeline<mem_fetch> *L2todram_wbqueue; - fifo_pipeline<mem_fetch> *L2tocbqueue; - - mem_fetch *L2request; //request currently being serviced by the L2 Cache + fifo_pipeline<mem_fetch> *L2tocbqueue; // L2 cache hit response queue L2c_mshr *m_mshr; // mshr model L2c_miss_tracker *m_missTracker; // tracker observing for redundant misses diff --git a/src/gpgpu-sim/mem_fetch.cc b/src/gpgpu-sim/mem_fetch.cc index 99a1e58..58ed2cd 100644 --- a/src/gpgpu-sim/mem_fetch.cc +++ b/src/gpgpu-sim/mem_fetch.cc @@ -104,3 +104,9 @@ mem_fetch::mem_fetch( unsigned long long int addr, mf->type = type; mf->pc = pc; } + +void mem_fetch::print( FILE *fp ) const +{ + fprintf(fp," mf: uid=%6u, addr=0x%08llx, sid=%u, wid=%u, pc=0x%04x, %s, bank=%u\n", + request_uid, addr, sid, wid, pc, (m_write?"write":"read "), bank); +} diff --git a/src/gpgpu-sim/mem_fetch.h b/src/gpgpu-sim/mem_fetch.h index 7196690..9e9ff9a 100644 --- a/src/gpgpu-sim/mem_fetch.h +++ b/src/gpgpu-sim/mem_fetch.h @@ -76,7 +76,6 @@ enum mf_type { WT_REQ, REPLY_DATA, // send to shader L2_WTBK_DATA, - DUMMY_READ, //used in write mask N_MF_TYPE }; @@ -111,6 +110,8 @@ public: enum mf_type type, address_type pc ); + void print( FILE *fp ) const; + public: unsigned request_uid; unsigned long long int addr; diff --git a/src/gpgpu-sim/shader.cc b/src/gpgpu-sim/shader.cc index 1f2be5a..75aec7b 100644 --- a/src/gpgpu-sim/shader.cc +++ b/src/gpgpu-sim/shader.cc @@ -348,17 +348,17 @@ bool shader_core_ctx::pipeline_regster_empty( inst_t *reg ) void shader_core_ctx::L1cache_print( FILE *fp, unsigned &total_accesses, unsigned &total_misses) const { - shd_cache_print(m_L1D,fp,total_accesses,total_misses); + m_L1D->shd_cache_print(fp,total_accesses,total_misses); } void shader_core_ctx::L1texcache_print( FILE *fp, unsigned &total_accesses, unsigned &total_misses) const { - shd_cache_print(m_L1T,fp,total_accesses,total_misses); + m_L1T->shd_cache_print(fp,total_accesses,total_misses); } void shader_core_ctx::L1constcache_print( FILE *fp, unsigned &total_accesses, unsigned &total_misses) const { - shd_cache_print(m_L1C,fp,total_accesses,total_misses); + m_L1C->shd_cache_print(fp,total_accesses,total_misses); } std::list<unsigned> shader_core_ctx::get_regs_written( const inst_t &fvt ) const @@ -438,21 +438,15 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, char L1I_name[STRSIZE]; snprintf(L1D_name, STRSIZE, "L1D_%03d", m_sid); - m_L1D = shd_cache_create(L1D_name,m_config->gpgpu_cache_dl1_opt,1,0,m_config->gpgpu_cache_wt_through?write_through:write_back); - shd_cache_bind_logger(m_L1D, m_sid, get_shader_normal_cache_id()); - snprintf(L1T_name, STRSIZE, "L1T_%03d", m_sid); - m_L1T = shd_cache_create(L1T_name,m_config->gpgpu_cache_texl1_opt,1,0, no_writes ); - shd_cache_bind_logger(m_L1T, m_sid, get_shader_texture_cache_id()); - ptx_set_tex_cache_linesize(m_L1T->line_sz); - snprintf(L1C_name, STRSIZE, "L1C_%03d", m_sid); - m_L1C = shd_cache_create(L1C_name,m_config->gpgpu_cache_constl1_opt,1,0, no_writes ); - shd_cache_bind_logger(m_L1C, m_sid, get_shader_constant_cache_id()); - snprintf(L1I_name, STRSIZE, "L1I_%03d", m_sid); - m_L1I = shd_cache_create(L1I_name,m_config->gpgpu_cache_il1_opt,1,0, no_writes ); - shd_cache_bind_logger(m_L1D, m_sid, get_shader_instruction_cache_id()); + enum cache_write_policy L1D_policy = m_config->gpgpu_cache_wt_through?write_through:write_back; + m_L1D = new cache_t(L1D_name,m_config->gpgpu_cache_dl1_opt, 0,L1D_policy,m_sid,get_shader_normal_cache_id()); + m_L1T = new cache_t(L1T_name,m_config->gpgpu_cache_texl1_opt, 0,no_writes, m_sid,get_shader_texture_cache_id()); + m_L1C = new cache_t(L1C_name,m_config->gpgpu_cache_constl1_opt,0,no_writes, m_sid,get_shader_constant_cache_id()); + m_L1I = new cache_t(L1I_name,m_config->gpgpu_cache_il1_opt, 0,no_writes, m_sid,get_shader_instruction_cache_id()); + ptx_set_tex_cache_linesize(m_L1T->get_line_sz()); m_mshr_unit = new mshr_shader_unit(m_config); m_pdom_warp = new pdom_warp_ctx_t*[config->max_warps_per_shader]; @@ -896,9 +890,9 @@ void pdom_warp_ctx_t::print (FILE *fout) const void shader_core_ctx::new_cache_window() { - shd_cache_new_window(m_L1D); - shd_cache_new_window(m_L1T); - shd_cache_new_window(m_L1C); + m_L1D->shd_cache_new_window(); + m_L1T->shd_cache_new_window(); + m_L1C->shd_cache_new_window(); } void shader_core_ctx::fetch_mimd() @@ -1166,10 +1160,10 @@ void shader_core_ctx::fetch_new() address_type ppc = pc + PROGRAM_MEM_START; address_type wb=0; unsigned nbytes=16; - unsigned offset_in_block = pc & (m_L1I->line_sz-1); - if( (offset_in_block+nbytes) > m_L1I->line_sz ) - nbytes = (m_L1I->line_sz-offset_in_block); - enum cache_request_status status = shd_cache_access_new( m_L1I, (unsigned long long)pc, nbytes, 0, gpu_sim_cycle, &wb ); + unsigned offset_in_block = pc & (m_L1I->get_line_sz()-1); + if( (offset_in_block+nbytes) > m_L1I->get_line_sz() ) + nbytes = (m_L1I->get_line_sz()-offset_in_block); + enum cache_request_status status = m_L1I->access( (unsigned long long)pc, nbytes, 0, gpu_sim_cycle, &wb ); if( status != HIT ) { unsigned req_size = READ_PACKET_SIZE; if( m_gpu->fq_has_buffer(ppc, req_size, false, m_sid) ) { @@ -1852,19 +1846,18 @@ void shader_core_ctx::memory_const_process_warp() line_size_based_tag_func, CONSTANT_MEM_PATH, 1, //warp parts - m_L1C->line_sz, false, //no broadcast limit. + m_L1C->get_line_sz(), false, //no broadcast limit. accessq); //do cache checks here for each request (non-physical), could be done later for more accurate timing of cache accesses, but probably uneccesary; for (unsigned i = qbegin; i < accessq.size(); i++) { if ( accessq[i].space == param_space_kernel ) { accessq[i].cache_hit = true; } else { - cache_request_status status = shd_cache_access_new(m_L1C, - accessq[i].addr, - WORD_SIZE, //this field is ingored. - 0, //should always be a read - gpu_sim_cycle+gpu_tot_sim_cycle, - NULL/*should never writeback*/); + cache_request_status status = m_L1C->access( accessq[i].addr, + WORD_SIZE, //this field is ingored. + 0, //should always be a read + gpu_sim_cycle+gpu_tot_sim_cycle, + NULL/*should never writeback*/); accessq[i].cache_hit = (status == HIT); if (m_config->gpgpu_perfect_mem) accessq[i].cache_hit = true; if (accessq[i].cache_hit) m_stats->L1_const_miss++; @@ -1882,17 +1875,16 @@ void shader_core_ctx::memory_texture_process_warp() &line_size_based_tag_func, TEXTURE_MEM_PATH, 1, //warp parts - m_L1T->line_sz, + m_L1T->get_line_sz(), false, //no broadcast limit. accessq); //do cache checks here for each request (non-hardware), could be done later for more accurate timing of cache accesses, but probably uneccesary; for (unsigned i = qbegin; i < accessq.size(); i++) { - cache_request_status status = shd_cache_access_new(m_L1T, - accessq[i].addr, - WORD_SIZE, //this field is ignored. - 0, //should always be a read - gpu_sim_cycle+gpu_tot_sim_cycle, - NULL /*should never writeback*/); + cache_request_status status = m_L1T->access( accessq[i].addr, + WORD_SIZE, //this field is ignored. + 0, //should always be a read + gpu_sim_cycle+gpu_tot_sim_cycle, + NULL /*should never writeback*/); accessq[i].cache_hit = (status == HIT); if (m_config->gpgpu_perfect_mem) accessq[i].cache_hit = true; if (accessq[i].cache_hit) m_stats->L1_texture_miss++; @@ -1905,7 +1897,7 @@ void shader_core_ctx::memory_global_process_warp() std::vector<mem_access_t> &accessq = m_memory_queue.local_global; unsigned qbegin = accessq.size(); unsigned warp_parts = 1; - unsigned line_size = m_L1D->line_sz; + unsigned line_size = m_L1D->get_line_sz(); if (m_config->gpgpu_coalesce_arch == 13) { warp_parts = 2; if(m_config->gpgpu_no_dl1) { @@ -1966,7 +1958,7 @@ mem_stage_stall_type shader_core_ctx::send_mem_request(mem_access_t &access) // If the cache told us it needed to write back a dirty line, do this now // It is possible to do this writeback in the same cycle as the access request, this may not be realistic. if (access.need_wb) { - unsigned req_size = m_L1D->line_sz + WRITE_PACKET_SIZE; + unsigned req_size = m_L1D->get_line_sz() + WRITE_PACKET_SIZE; if ( ! m_gpu->fq_has_buffer(access.wb_addr, req_size, true, m_sid) ) { m_stats->gpu_stall_sh2icnt++; return WB_ICNT_RC_FAIL; @@ -1978,15 +1970,14 @@ mem_stage_stall_type shader_core_ctx::send_mem_request(mem_access_t &access) access.need_wb = false; } - unsigned code; mem_access_type access_type; switch(access.space.get_type()) { case const_space: - case param_space_kernel: code = CONSTC; access_type = CONST_ACC_R; break; - case tex_space: code = TEXTC; access_type = TEXTURE_ACC_R; break; - case global_space: code = DCACHE; access_type = (access.iswrite)? GLOBAL_ACC_W: GLOBAL_ACC_R; break; + case param_space_kernel: access_type = CONST_ACC_R; break; + case tex_space: access_type = TEXTURE_ACC_R; break; + case global_space: access_type = (access.iswrite)? GLOBAL_ACC_W: GLOBAL_ACC_R; break; case local_space: - case param_space_local: code = DCACHE; access_type = (access.iswrite)? LOCAL_ACC_W: LOCAL_ACC_R; break; + case param_space_local: access_type = (access.iswrite)? LOCAL_ACC_W: LOCAL_ACC_R; break; default: assert(0); break; } //reserve mshr @@ -2162,12 +2153,11 @@ mem_stage_stall_type shader_core_ctx::dcache_check(mem_access_t& access) return NO_RC_FAIL; if (!m_config->gpgpu_no_dl1 && !m_config->gpgpu_perfect_mem) { //check cache - cache_request_status status = shd_cache_access_new(m_L1D, - access.addr, - WORD_SIZE, //this field is ignored. - access.iswrite, - gpu_sim_cycle+gpu_tot_sim_cycle, - &access.wb_addr); + cache_request_status status = m_L1D->access( access.addr, + WORD_SIZE, //this field is ignored. + access.iswrite, + gpu_sim_cycle+gpu_tot_sim_cycle, + &access.wb_addr ); if (status == RESERVATION_FAIL) { access.cache_checked = false; return WB_CACHE_RSRV_FAIL; @@ -2951,27 +2941,28 @@ void shader_core_ctx::cycle() void shader_core_ctx::cache_flush() { + m_L1D->flush(); + // TODO: add flush 'interface' object to provide functionality commented out below +/* + unsigned int i; unsigned int set; unsigned long long int flush_addr; - - shd_cache_t *cp = m_L1D; - shd_cache_line_t *pline; - - for (i=0; i<cp->nset*cp->assoc; i++) { - pline = &(cp->lines[i]); - set = i / cp->assoc; + cache_t *cp = m_L1D; + cache_block_t *pline; + for (i=0; i<cp->m_nset*cp->m_assoc; i++) { + pline = &(cp->m_lines[i]); + set = i / cp->m_assoc; if ((pline->status & (DIRTY|VALID)) == (DIRTY|VALID)) { flush_addr = pline->addr; - - fq_push(flush_addr, m_L1D->line_sz, 1, NO_PARTIAL_WRITE, 0, NULL, 0, GLOBAL_ACC_W, -1); - + fq_push(flush_addr, m_L1D->get_line_sz(), 1, NO_PARTIAL_WRITE, 0, NULL, 0, GLOBAL_ACC_W, -1); pline->status &= ~VALID; pline->status &= ~DIRTY; } else if (pline->status & VALID) { pline->status &= ~VALID; } } +*/ } static int *_inmatch; @@ -3356,6 +3347,7 @@ void mshr_entry::set_status( enum mshr_status status ) req = req->m_merged_requests; } #if DEBUGL1MISS +#define CACHE_TAG_OF_64(x) ((x) & (~((unsigned long long int)64 - 1))) printf("cycle %d Addr %x %d \n",gpu_sim_cycle,CACHE_TAG_OF_64(m_addr),status); #endif } diff --git a/src/gpgpu-sim/shader.h b/src/gpgpu-sim/shader.h index 44206af..fe6192a 100644 --- a/src/gpgpu-sim/shader.h +++ b/src/gpgpu-sim/shader.h @@ -1099,9 +1099,9 @@ public: void L1texcache_print( FILE *fp, unsigned &total_accesses, unsigned &total_misses) const; void L1constcache_print( FILE *fp, unsigned &total_accesses, unsigned &total_misses) const; unsigned get_n_active_cta() const { return m_n_active_cta; } - float L1_windowed_cache_miss_rate( int x ) const { return shd_cache_windowed_cache_miss_rate(m_L1D,x); } - float L1tex_windowed_cache_miss_rate( int x ) const { return shd_cache_windowed_cache_miss_rate(m_L1T,x); } - float L1const_windowed_cache_miss_rate( int x ) const { return shd_cache_windowed_cache_miss_rate(m_L1C,x); } + float L1_windowed_cache_miss_rate( int x ) const { return m_L1D->shd_cache_windowed_cache_miss_rate(x); } + float L1tex_windowed_cache_miss_rate( int x ) const { return m_L1T->shd_cache_windowed_cache_miss_rate(x); } + float L1const_windowed_cache_miss_rate( int x ) const { return m_L1C->shd_cache_windowed_cache_miss_rate(x); } private: @@ -1252,10 +1252,10 @@ private: int m_dwf_RR_k; // counter for register read pipeline int *m_dwf_rrstage_bank_access_counter; - shd_cache_t *m_L1I; // instruction cache - shd_cache_t *m_L1D; // data cache (global/local memory accesses) - shd_cache_t *m_L1T; // texture cache - shd_cache_t *m_L1C; // constant cache + cache_t *m_L1I; // instruction cache + cache_t *m_L1D; // data cache (global/local memory accesses) + cache_t *m_L1T; // texture cache + cache_t *m_L1C; // constant cache bool m_shader_memory_new_instruction_processed; int m_pending_mem_access; // number of memory access to be serviced (use for W0 classification) |
