From 9233f6f9eeea537187deb64add77a320442aa621 Mon Sep 17 00:00:00 2001 From: tgrogers Date: Sat, 18 Nov 2017 15:48:26 -0500 Subject: vectoradd is successfully filling the l2 --- src/gpgpu-sim/gpu-cache.h | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'src/gpgpu-sim/gpu-cache.h') diff --git a/src/gpgpu-sim/gpu-cache.h b/src/gpgpu-sim/gpu-cache.h index 3e1691a..3713126 100644 --- a/src/gpgpu-sim/gpu-cache.h +++ b/src/gpgpu-sim/gpu-cache.h @@ -690,11 +690,13 @@ public: ~tag_array(); enum cache_request_status probe( new_addr_type addr, unsigned &idx, mem_fetch* mf ) const; + enum cache_request_status probe( new_addr_type addr, unsigned &idx, mem_access_sector_mask_t mask ) const; enum cache_request_status access( new_addr_type addr, unsigned time, unsigned &idx, mem_fetch* mf ); enum cache_request_status access( new_addr_type addr, unsigned time, unsigned &idx, bool &wb, evicted_block_info &evicted, mem_fetch* mf ); void fill( new_addr_type addr, unsigned time, mem_fetch* mf ); void fill( unsigned idx, unsigned time, mem_fetch* mf ); + void fill( new_addr_type addr, unsigned time, mem_access_sector_mask_t mask ); unsigned size() const { return m_config.get_num_lines();} cache_block_t* get_block(unsigned idx) { return m_lines[idx];} @@ -969,6 +971,15 @@ public: bool data_port_free() const { return m_bandwidth_management.data_port_free(); } bool fill_port_free() const { return m_bandwidth_management.fill_port_free(); } + // This is a gapping hole we are poking in the system to quickly handle + // filling the cache on cudamemcopies. We don't care about anything other than + // L2 state after the memcopy - so just force the tag array to act as though + // something is read or written without doing anything else. + void force_tag_access( new_addr_type addr, unsigned time, mem_access_sector_mask_t mask ) + { + m_tag_array->fill( addr, time, mask ); + } + protected: // Constructor that can be used by derived classes with custom tag arrays baseline_cache( const char *name, -- cgit v1.3 From b2c4c3e23530799e6e24eb83b2a6b82cf7891cf4 Mon Sep 17 00:00:00 2001 From: tgrogers Date: Sat, 18 Nov 2017 21:50:10 -0500 Subject: Getting rid of another assert that crops up cause of our memcpy and L2 interaction --- src/gpgpu-sim/gpu-cache.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/gpgpu-sim/gpu-cache.h') diff --git a/src/gpgpu-sim/gpu-cache.h b/src/gpgpu-sim/gpu-cache.h index 3713126..b649135 100644 --- a/src/gpgpu-sim/gpu-cache.h +++ b/src/gpgpu-sim/gpu-cache.h @@ -292,8 +292,8 @@ struct sector_cache_block : public cache_block_t { { unsigned sidx = get_sector_index(sector_mask); - if(!m_ignore_on_fill_status[sidx]) - assert( m_status[sidx] == RESERVED ); + // if(!m_ignore_on_fill_status[sidx]) + // assert( m_status[sidx] == RESERVED ); m_status[sidx] = m_set_modified_on_fill[sidx]? MODIFIED : VALID; -- cgit v1.3 From 8386d194b8a239ed0c36852c8a6efff142712801 Mon Sep 17 00:00:00 2001 From: tgrogers Date: Sat, 18 Nov 2017 22:25:13 -0500 Subject: removing another assert --- src/gpgpu-sim/gpu-cache.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/gpgpu-sim/gpu-cache.h') diff --git a/src/gpgpu-sim/gpu-cache.h b/src/gpgpu-sim/gpu-cache.h index b649135..6a84a3a 100644 --- a/src/gpgpu-sim/gpu-cache.h +++ b/src/gpgpu-sim/gpu-cache.h @@ -153,8 +153,8 @@ struct line_cache_block: public cache_block_t { } void fill( unsigned time, mem_access_sector_mask_t sector_mask ) { - if(!m_ignore_on_fill_status) - assert( m_status == RESERVED ); + //if(!m_ignore_on_fill_status) + // assert( m_status == RESERVED ); m_status = m_set_modified_on_fill? MODIFIED : VALID; -- cgit v1.3 From 6a2f9978b9325fb78e8af1be5d5aaf90814e08d7 Mon Sep 17 00:00:00 2001 From: Mahmoud Date: Sun, 19 Nov 2017 20:05:53 -0500 Subject: Doing lazy fetch-on-read policy --- src/gpgpu-sim/gpu-cache.cc | 59 ++++++++++++++++++++++++++++++++++++++++++---- src/gpgpu-sim/gpu-cache.h | 31 +++++++++++++++++++++++- 2 files changed, 85 insertions(+), 5 deletions(-) (limited to 'src/gpgpu-sim/gpu-cache.h') diff --git a/src/gpgpu-sim/gpu-cache.cc b/src/gpgpu-sim/gpu-cache.cc index e1e41a5..0602e20 100644 --- a/src/gpgpu-sim/gpu-cache.cc +++ b/src/gpgpu-sim/gpu-cache.cc @@ -219,9 +219,16 @@ enum cache_request_status tag_array::probe( new_addr_type addr, unsigned &idx, m } else if ( line->get_status(mask) == VALID ) { idx = index; return HIT; - } else if ( line->get_status(mask) == MODIFIED ) { - idx = index; - return HIT; + } else if ( line->get_status(mask) == MODIFIED) { + if(line->is_readable(mask)) { + idx = index; + return HIT; + } + else { + idx = index; + return SECTOR_MISS; + } + } else if ( line->is_valid_line() && line->get_status(mask) == INVALID ) { idx = index; return SECTOR_MISS; @@ -1125,6 +1132,50 @@ data_cache::wr_miss_wa_fetch_on_write( new_addr_type addr, { new_addr_type block_addr = m_config.block_addr(addr); + new_addr_type mshr_addr = m_config.mshr_addr(mf->get_addr()); + + + //if the request writes to the whole cache line/sector, then, write and set cache line Modified. + //and no need to send read request to memory or reserve mshr + + if(miss_queue_full(0)) { + m_stats.inc_fail_stats(mf->get_access_type(), MISS_QUEUE_FULL); + return RESERVATION_FAIL; // cannot handle request this cycle + } + + bool wb = false; + evicted_block_info evicted; + + cache_request_status m_status = m_tag_array->access(block_addr,time,cache_index,wb,evicted,mf); + assert(m_status != HIT); + cache_block_t* block = m_tag_array->get_block(cache_index); + block->set_status(MODIFIED, mf->get_access_sector_mask()); + if(m_status == HIT_RESERVED) { + block->set_ignore_on_fill(true, mf->get_access_sector_mask()); + block->set_modified_on_fill(true, mf->get_access_sector_mask()); + } + + if(mf->get_access_byte_mask().count() == m_config.get_atom_sz()) + { + block->set_m_readable(true, mf->get_access_sector_mask()); + } else + { + block->set_m_readable(false, mf->get_access_sector_mask()); + } + + if( m_status != RESERVATION_FAIL ){ + // If evicted block is modified and not a write-through + // (already modified lower level) + if( wb && (m_config.m_write_policy != WRITE_THROUGH) ) { + mem_fetch *wb = m_memfetch_creator->alloc(evicted.m_block_addr, + m_wrbk_type,evicted.m_modified_size,true); + send_write_request(wb, cache_event(WRITE_BACK_REQUEST_SENT, evicted), time, events); + } + return MISS; + } + return RESERVATION_FAIL; + + /*new_addr_type block_addr = m_config.block_addr(addr); new_addr_type mshr_addr = m_config.mshr_addr(mf->get_addr()); if(mf->get_access_byte_mask().count() == m_config.get_atom_sz()) @@ -1233,7 +1284,7 @@ data_cache::wr_miss_wa_fetch_on_write( new_addr_type addr, return MISS; } return RESERVATION_FAIL; - } + }*/ } /// No write-allocate miss: Simply send write request to lower level memory diff --git a/src/gpgpu-sim/gpu-cache.h b/src/gpgpu-sim/gpu-cache.h index 6a84a3a..0d07878 100644 --- a/src/gpgpu-sim/gpu-cache.h +++ b/src/gpgpu-sim/gpu-cache.h @@ -123,8 +123,11 @@ struct cache_block_t { virtual void set_ignore_on_fill(bool m_ignore, mem_access_sector_mask_t sector_mask) = 0; virtual void set_modified_on_fill(bool m_modified, mem_access_sector_mask_t sector_mask) = 0; virtual unsigned get_modified_size() = 0; + virtual void set_m_readable(bool readable, mem_access_sector_mask_t sector_mask)=0; + virtual bool is_readable(mem_access_sector_mask_t sector_mask)=0; virtual ~cache_block_t() {} + new_addr_type m_tag; new_addr_type m_block_addr; @@ -139,6 +142,7 @@ struct line_cache_block: public cache_block_t { m_status=INVALID; m_ignore_on_fill_status = false; m_set_modified_on_fill = false; + m_readable = true; } void allocate( new_addr_type tag, new_addr_type block_addr, unsigned time, mem_access_sector_mask_t sector_mask ) { @@ -209,6 +213,13 @@ struct line_cache_block: public cache_block_t { { return SECTOR_CHUNCK_SIZE * SECTOR_SIZE; //i.e. cache line size } + virtual void set_m_readable(bool readable, mem_access_sector_mask_t sector_mask) + { + m_readable = readable; + } + virtual bool is_readable(mem_access_sector_mask_t sector_mask) { + return m_readable; + } private: @@ -218,6 +229,7 @@ private: cache_block_state m_status; bool m_ignore_on_fill_status; bool m_set_modified_on_fill; + bool m_readable; }; struct sector_cache_block : public cache_block_t { @@ -234,6 +246,7 @@ struct sector_cache_block : public cache_block_t { m_status[i]= INVALID; m_ignore_on_fill_status[i] = false; m_set_modified_on_fill[i] = false; + m_readable[i] = true; } m_line_alloc_time=0; m_line_last_access_time=0; @@ -279,9 +292,15 @@ struct sector_cache_block : public cache_block_t { m_sector_alloc_time[sidx]=time; m_last_sector_access_time[sidx]=time; m_sector_fill_time[sidx]=0; + if(m_status[sidx]==MODIFIED) //this should be the case only for fetch-on-write policy //TO DO + m_set_modified_on_fill[sidx] = true; + else + m_set_modified_on_fill[sidx] = false; + m_status[sidx]=RESERVED; m_ignore_on_fill_status[sidx] = false; - m_set_modified_on_fill[sidx] = false; + //m_set_modified_on_fill[sidx] = false; + m_readable[sidx] = true; //set line stats m_line_last_access_time=time; @@ -362,6 +381,15 @@ struct sector_cache_block : public cache_block_t { unsigned sidx = get_sector_index(sector_mask); m_set_modified_on_fill[sidx] = m_modified; } + virtual void set_m_readable(bool readable, mem_access_sector_mask_t sector_mask) + { + unsigned sidx = get_sector_index(sector_mask); + m_readable[sidx] = readable; + } + virtual bool is_readable(mem_access_sector_mask_t sector_mask) { + unsigned sidx = get_sector_index(sector_mask); + return m_readable[sidx]; + } virtual unsigned get_modified_size() { @@ -383,6 +411,7 @@ private: cache_block_state m_status[SECTOR_CHUNCK_SIZE]; bool m_ignore_on_fill_status[SECTOR_CHUNCK_SIZE]; bool m_set_modified_on_fill[SECTOR_CHUNCK_SIZE]; + bool m_readable[SECTOR_CHUNCK_SIZE]; unsigned get_sector_index(mem_access_sector_mask_t sector_mask) { -- cgit v1.3 From baba81bd9bd5ec5fd07e70b307ccbfeac2d90e0e Mon Sep 17 00:00:00 2001 From: Mahmoud Date: Mon, 12 Mar 2018 16:52:26 -0400 Subject: fixibg sectir l1 deadlock bug --- src/gpgpu-sim/gpu-cache.cc | 4 ++-- src/gpgpu-sim/gpu-cache.h | 15 ++++++++++++--- 2 files changed, 14 insertions(+), 5 deletions(-) (limited to 'src/gpgpu-sim/gpu-cache.h') diff --git a/src/gpgpu-sim/gpu-cache.cc b/src/gpgpu-sim/gpu-cache.cc index 0602e20..8191f62 100644 --- a/src/gpgpu-sim/gpu-cache.cc +++ b/src/gpgpu-sim/gpu-cache.cc @@ -962,7 +962,7 @@ void baseline_cache::send_read_request(new_addr_type addr, new_addr_type block_a m_mshrs.add(mshr_addr,mf); m_extra_mf_fields[mf] = extra_mf_fields(mshr_addr,mf->get_addr(),cache_index, mf->get_data_size(), m_config); mf->set_data_size( m_config.get_atom_sz() ); - mf->set_addr( block_addr ); + mf->set_addr( mshr_addr ); m_miss_queue.push_back(mf); mf->set_status(m_miss_queue_status,time); if(!wa) @@ -1432,7 +1432,7 @@ data_cache::process_tag_probe( bool wr, access_status = (this->*m_wr_hit)( addr, cache_index, mf, time, events, probe_status ); - }else if ( probe_status != RESERVATION_FAIL ) { + }else if ( (probe_status != RESERVATION_FAIL) || (probe_status == RESERVATION_FAIL && m_config.m_write_alloc_policy == NO_WRITE_ALLOCATE) ) { access_status = (this->*m_wr_miss)( addr, cache_index, mf, time, events, probe_status ); diff --git a/src/gpgpu-sim/gpu-cache.h b/src/gpgpu-sim/gpu-cache.h index 0d07878..76b07a2 100644 --- a/src/gpgpu-sim/gpu-cache.h +++ b/src/gpgpu-sim/gpu-cache.h @@ -39,7 +39,7 @@ #include enum cache_block_state { - INVALID, + INVALID=0, RESERVED, VALID, MODIFIED @@ -125,6 +125,7 @@ struct cache_block_t { virtual unsigned get_modified_size() = 0; virtual void set_m_readable(bool readable, mem_access_sector_mask_t sector_mask)=0; virtual bool is_readable(mem_access_sector_mask_t sector_mask)=0; + virtual void print_status()=0; virtual ~cache_block_t() {} @@ -144,7 +145,7 @@ struct line_cache_block: public cache_block_t { m_set_modified_on_fill = false; m_readable = true; } - void allocate( new_addr_type tag, new_addr_type block_addr, unsigned time, mem_access_sector_mask_t sector_mask ) + void allocate( new_addr_type tag, new_addr_type block_addr, unsigned time, mem_access_sector_mask_t sector_mask) { m_tag=tag; m_block_addr=block_addr; @@ -220,6 +221,9 @@ struct line_cache_block: public cache_block_t { virtual bool is_readable(mem_access_sector_mask_t sector_mask) { return m_readable; } + virtual void print_status() { + printf("m_block_addr is %u, status = %u\n", m_block_addr, m_status); + } private: @@ -401,6 +405,11 @@ struct sector_cache_block : public cache_block_t { return modified * SECTOR_SIZE; } + virtual void print_status() { + printf("m_block_addr is %u, status = %u %u %u %u\n", m_block_addr, m_status[0], m_status[1], m_status[2], m_status[3]); + } + + private: unsigned m_sector_alloc_time[SECTOR_CHUNCK_SIZE]; unsigned m_last_sector_access_time[SECTOR_CHUNCK_SIZE]; @@ -1030,7 +1039,7 @@ protected: std::string m_name; cache_config &m_config; tag_array* m_tag_array; - mshr_table m_mshrs; + mshr_table m_mshrs; std::list m_miss_queue; enum mem_fetch_status m_miss_queue_status; mem_fetch_interface *m_memport; -- cgit v1.3 From 1e1c08286a505418d0e3ad1ee819e15881e9cb43 Mon Sep 17 00:00:00 2001 From: Mahmoud Date: Fri, 15 Jun 2018 16:46:14 -0400 Subject: memory partition indexing --- configs/4.x-cfgs/SM6_P100/gpgpusim.config | 1 + src/gpgpu-sim/addrdec.cc | 48 +++++++++++++++++++++++++++++++ src/gpgpu-sim/addrdec.h | 8 ++++++ src/gpgpu-sim/dram.cc | 2 +- src/gpgpu-sim/gpu-cache.cc | 36 ++++++++++++++++++++++- src/gpgpu-sim/gpu-cache.h | 7 +++-- 6 files changed, 98 insertions(+), 4 deletions(-) (limited to 'src/gpgpu-sim/gpu-cache.h') diff --git a/configs/4.x-cfgs/SM6_P100/gpgpusim.config b/configs/4.x-cfgs/SM6_P100/gpgpusim.config index 9a7259e..a43c0bb 100644 --- a/configs/4.x-cfgs/SM6_P100/gpgpusim.config +++ b/configs/4.x-cfgs/SM6_P100/gpgpusim.config @@ -69,6 +69,7 @@ -gpgpu_cache:dl2_texture_only 0 -gpgpu_dram_partition_queues 64:64:64:64 -perf_sim_memcpy 0 +-memory_partition_indexing 2 # 4 KB Inst. -gpgpu_cache:il1 N:8:128:4,L:R:f:N:L,S:2:48,4 diff --git a/src/gpgpu-sim/addrdec.cc b/src/gpgpu-sim/addrdec.cc index 422576d..cfd90ec 100644 --- a/src/gpgpu-sim/addrdec.cc +++ b/src/gpgpu-sim/addrdec.cc @@ -62,6 +62,9 @@ void linear_to_raw_address_translation::addrdec_setoption(option_parser_t opp) option_parser_register(opp, "-gpgpu_mem_address_mask", OPT_INT32, &gpgpu_mem_address_mask, "0 = old addressing mask, 1 = new addressing mask, 2 = new add. mask + flipped bank sel and chip sel bits", "0"); + option_parser_register(opp, "-memory_partition_indexing", OPT_UINT32, &memory_partition_indexing, + "0 = no indexing, 1 = bitwise xoring, 2 = IPoly, 3 = custom indexing", + "0"); } new_addr_type linear_to_raw_address_translation::partition_address( new_addr_type addr ) const @@ -103,6 +106,51 @@ void linear_to_raw_address_translation::addrdec_tlx(new_addr_type addr, addrdec_ tlx->burst= addrdec_packbits(addrdec_mask[BURST], rest_of_addr, addrdec_mkhigh[BURST], addrdec_mklow[BURST]); } + switch(memory_partition_indexing){ + case CONSECUTIVE: + //Do nothing + break; + case BITWISE_PERMUTATION: + assert(!gap); + tlx->chip = (tlx->chip) ^ (tlx->row & (m_n_channel-1)); + assert(tlx->chip < m_n_channel); + break; + case IPOLY: + /* + * Set Indexing function from "Pseudo-randomly interleaved memory." + * Rau, B. R et al. + * ISCA 1991 + * + * equations are adopted from: + * "Sacat: streaming-aware conflict-avoiding thrashing-resistant gpgpu cache management scheme." + * Khairy et al. + * IEEE TPDS 2017. + */ + if(m_n_channel == 32) { + std::bitset<64> a(tlx->row); + std::bitset<5> chip(tlx->chip); + chip[0] = a[13]^a[12]^a[11]^a[10]^a[9]^a[6]^a[5]^a[3]^a[0]^chip[0]; + chip[1] = a[14]^a[13]^a[12]^a[11]^a[10]^a[7]^a[6]^a[4]^a[1]^chip[1]; + chip[2] = a[14]^a[10]^a[9]^a[8]^a[7]^a[6]^a[3]^a[2]^a[0]^chip[2]; + chip[3] = a[11]^a[10]^a[9]^a[8]^a[7]^a[4]^a[3]^a[1]^chip[3]; + chip[4] = a[12]^a[11]^a[10]^a[9]^a[8]^a[5]^a[4]^a[2]^chip[4]; + tlx->chip = chip.to_ulong(); + + } + else{ /* Else incorrect number of channels for the hashing function */ + assert("\nGPGPU-Sim memory_partition_indexing error: The number of channels should be " + "32 for the hashing IPOLY index function.\n" && 0); + } + assert(tlx->chip < m_n_channel); + break; + case CUSTOM: + /* No custom set function implemented */ + break; + default: + assert("\nUndefined set index function.\n" && 0); + break; + } + // combine the chip address and the lower bits of DRAM bank address to form the subpartition ID unsigned sub_partition_addr_mask = m_n_sub_partition_in_channel - 1; tlx->sub_partition = tlx->chip * m_n_sub_partition_in_channel diff --git a/src/gpgpu-sim/addrdec.h b/src/gpgpu-sim/addrdec.h index fd9af8d..a18ff63 100644 --- a/src/gpgpu-sim/addrdec.h +++ b/src/gpgpu-sim/addrdec.h @@ -35,6 +35,13 @@ #include "../abstract_hardware_model.h" +enum partition_index_function{ + CONSECUTIVE = 0, + BITWISE_PERMUTATION, + IPOLY, + CUSTOM +}; + struct addrdec_t { void print( FILE *fp ) const; @@ -72,6 +79,7 @@ private: const char *addrdec_option; int gpgpu_mem_address_mask; + partition_index_function memory_partition_indexing; bool run_test; int ADDR_CHIP_S; diff --git a/src/gpgpu-sim/dram.cc b/src/gpgpu-sim/dram.cc index a57508c..92aa819 100644 --- a/src/gpgpu-sim/dram.cc +++ b/src/gpgpu-sim/dram.cc @@ -204,7 +204,7 @@ dram_req_t::dram_req_t( class mem_fetch *mf, unsigned banks, unsigned dram_bnk_i } else if(dram_bnk_indexing_policy == 1) { int lbank = log2(banks); - bk = tlx.bk ^ (((1< a(addr); + std::bitset<6> index; + index[0] = a[25]^a[24]^a[23]^a[22]^a[21]^a[18]^a[17]^a[15]^a[12]^a[7]; //10 + index[1] = a[26]^a[25]^a[24]^a[23]^a[22]^a[19]^a[18]^a[16]^a[13]^a[8]; //10 + index[2] = a[26]^a[22]^a[21]^a[20]^a[19]^a[18]^a[15]^a[14]^a[12]^a[9]; //10 + index[3] = a[23]^a[22]^a[21]^a[20]^a[19]^a[16]^a[15]^a[13]^a[10]; //9 + index[4] = a[24]^a[23]^a[22]^a[21]^a[20]^a[17]^a[16]^a[14]^a[11]; //9 + + if(m_nset == 64) + index[5] = a[12]; + + set_index = index.to_ulong(); + + }else{ /* Else incorrect number of sets for the hashing function */ + assert("\nGPGPU-Sim cache configuration error: The number of sets should be " + "32 or 64 for the hashing set index function.\n" && 0); + } + break; + case CUSTOM_SET_FUNCTION: /* No custom set function implemented */ break; @@ -104,6 +134,10 @@ unsigned l1d_cache_config::set_index(new_addr_type addr) const{ case LINEAR_SET_FUNCTION: set_index = (addr >> m_line_sz_log2) & (m_nset-1); break; + + default: + assert("\nUndefined set index function.\n" && 0); + break; } // Linear function selected or custom set index function not implemented diff --git a/src/gpgpu-sim/gpu-cache.h b/src/gpgpu-sim/gpu-cache.h index 76b07a2..d2b7757 100644 --- a/src/gpgpu-sim/gpu-cache.h +++ b/src/gpgpu-sim/gpu-cache.h @@ -464,8 +464,10 @@ enum mshr_config_t { }; enum set_index_function{ - FERMI_HASH_SET_FUNCTION = 0, - LINEAR_SET_FUNCTION, + LINEAR_SET_FUNCTION = 0, + BITWISE_XORING_FUNCTION, + HASH_IPOLY_FUNCTION, + FERMI_HASH_SET_FUNCTION, CUSTOM_SET_FUNCTION }; @@ -587,6 +589,7 @@ public: switch(sif){ case 'H': m_set_index_function = FERMI_HASH_SET_FUNCTION; break; + case 'P': m_set_index_function = HASH_IPOLY_FUNCTION; break; case 'C': m_set_index_function = CUSTOM_SET_FUNCTION; break; case 'L': m_set_index_function = LINEAR_SET_FUNCTION; break; default: exit_parse_error(); -- cgit v1.3 From 8c81c1d04e8d20b08f122a12ce090b4f926adb4c Mon Sep 17 00:00:00 2001 From: Mahmoud Date: Wed, 22 Aug 2018 10:19:52 -0400 Subject: adding lazy-fetch-on-read and invalidate operation to cache --- configs/4.x-cfgs/SM6_TITANX/gpgpusim.config | 2 +- configs/4.x-cfgs/SM7_TITANV/gpgpusim.config | 2 +- src/gpgpu-sim/gpu-cache.cc | 110 ++++++++++++++++------------ src/gpgpu-sim/gpu-cache.h | 22 ++++-- src/gpgpu-sim/gpu-sim.cc | 6 +- src/gpgpu-sim/l2cache.cc | 12 ++- src/gpgpu-sim/l2cache.h | 1 + src/gpgpu-sim/shader.cc | 16 ++++ src/gpgpu-sim/shader.h | 3 + 9 files changed, 115 insertions(+), 59 deletions(-) (limited to 'src/gpgpu-sim/gpu-cache.h') diff --git a/configs/4.x-cfgs/SM6_TITANX/gpgpusim.config b/configs/4.x-cfgs/SM6_TITANX/gpgpusim.config index 3097d19..7368882 100644 --- a/configs/4.x-cfgs/SM6_TITANX/gpgpusim.config +++ b/configs/4.x-cfgs/SM6_TITANX/gpgpusim.config @@ -73,7 +73,7 @@ -gpgpu_n_cluster_ejection_buffer_size 32 # 64 sets, each 128 bytes 16-way for each memory sub partition (128 KB per memory sub partition). This gives 3MB L2 cache --gpgpu_cache:dl2 S:64:128:16,L:B:m:F:L,A:128:4,16:0,32 +-gpgpu_cache:dl2 S:64:128:16,L:B:m:L:L,A:128:4,16:0,32 -gpgpu_cache:dl2_texture_only 0 -gpgpu_dram_partition_queues 32:32:32:32 -perf_sim_memcpy 0 diff --git a/configs/4.x-cfgs/SM7_TITANV/gpgpusim.config b/configs/4.x-cfgs/SM7_TITANV/gpgpusim.config index 8969168..da98547 100644 --- a/configs/4.x-cfgs/SM7_TITANV/gpgpusim.config +++ b/configs/4.x-cfgs/SM7_TITANV/gpgpusim.config @@ -78,7 +78,7 @@ -gpgpu_n_cluster_ejection_buffer_size 32 # 64 sets, each 128 bytes 24-way for each memory sub partition (192 KB per memory sub partition). This gives 4.5MB L2 cache --gpgpu_cache:dl2 S:64:128:24,L:B:m:F:L,A:256:4,32:0,32 +-gpgpu_cache:dl2 S:64:128:24,L:B:m:L:L,A:256:4,32:0,32 -gpgpu_cache:dl2_texture_only 0 -gpgpu_dram_partition_queues 64:64:64:64 -perf_sim_memcpy 0 diff --git a/src/gpgpu-sim/gpu-cache.cc b/src/gpgpu-sim/gpu-cache.cc index 75ec00a..9d81de9 100644 --- a/src/gpgpu-sim/gpu-cache.cc +++ b/src/gpgpu-sim/gpu-cache.cc @@ -382,6 +382,8 @@ void tag_array::fill( unsigned index, unsigned time, mem_fetch* mf) m_lines[index]->fill(time, mf->get_access_sector_mask()); } + +//TODO: we need write back the flushed data to the upper level void tag_array::flush() { for (unsigned i=0; i < m_config.get_num_lines(); i++) @@ -391,6 +393,13 @@ void tag_array::flush() } } +void tag_array::invalidate() +{ + for (unsigned i=0; i < m_config.get_num_lines(); i++) + for(unsigned j=0; j < SECTOR_CHUNCK_SIZE; j++) + m_lines[i]->set_status(INVALID, mem_access_sector_mask_t().set(j)) ; +} + float tag_array::windowed_miss_rate( ) const { unsigned n_access = m_access - m_prev_snapshot_access; @@ -1162,52 +1171,7 @@ data_cache::wr_miss_wa_fetch_on_write( new_addr_type addr, unsigned time, std::list &events, enum cache_request_status status ) { - - new_addr_type block_addr = m_config.block_addr(addr); - new_addr_type mshr_addr = m_config.mshr_addr(mf->get_addr()); - - - //if the request writes to the whole cache line/sector, then, write and set cache line Modified. - //and no need to send read request to memory or reserve mshr - - if(miss_queue_full(0)) { - m_stats.inc_fail_stats(mf->get_access_type(), MISS_QUEUE_FULL); - return RESERVATION_FAIL; // cannot handle request this cycle - } - - bool wb = false; - evicted_block_info evicted; - - cache_request_status m_status = m_tag_array->access(block_addr,time,cache_index,wb,evicted,mf); - assert(m_status != HIT); - cache_block_t* block = m_tag_array->get_block(cache_index); - block->set_status(MODIFIED, mf->get_access_sector_mask()); - if(m_status == HIT_RESERVED) { - block->set_ignore_on_fill(true, mf->get_access_sector_mask()); - block->set_modified_on_fill(true, mf->get_access_sector_mask()); - } - - if(mf->get_access_byte_mask().count() == m_config.get_atom_sz()) - { - block->set_m_readable(true, mf->get_access_sector_mask()); - } else - { - block->set_m_readable(false, mf->get_access_sector_mask()); - } - - if( m_status != RESERVATION_FAIL ){ - // If evicted block is modified and not a write-through - // (already modified lower level) - if( wb && (m_config.m_write_policy != WRITE_THROUGH) ) { - mem_fetch *wb = m_memfetch_creator->alloc(evicted.m_block_addr, - m_wrbk_type,evicted.m_modified_size,true); - send_write_request(wb, cache_event(WRITE_BACK_REQUEST_SENT, evicted), time, events); - } - return MISS; - } - return RESERVATION_FAIL; - - /*new_addr_type block_addr = m_config.block_addr(addr); + new_addr_type block_addr = m_config.block_addr(addr); new_addr_type mshr_addr = m_config.mshr_addr(mf->get_addr()); if(mf->get_access_byte_mask().count() == m_config.get_atom_sz()) @@ -1316,7 +1280,59 @@ data_cache::wr_miss_wa_fetch_on_write( new_addr_type addr, return MISS; } return RESERVATION_FAIL; - }*/ + } +} + +enum cache_request_status +data_cache::wr_miss_wa_lazy_fetch_on_read( new_addr_type addr, + unsigned cache_index, mem_fetch *mf, + unsigned time, std::list &events, + enum cache_request_status status ) +{ + + new_addr_type block_addr = m_config.block_addr(addr); + new_addr_type mshr_addr = m_config.mshr_addr(mf->get_addr()); + + + //if the request writes to the whole cache line/sector, then, write and set cache line Modified. + //and no need to send read request to memory or reserve mshr + + if(miss_queue_full(0)) { + m_stats.inc_fail_stats(mf->get_access_type(), MISS_QUEUE_FULL); + return RESERVATION_FAIL; // cannot handle request this cycle + } + + bool wb = false; + evicted_block_info evicted; + + cache_request_status m_status = m_tag_array->access(block_addr,time,cache_index,wb,evicted,mf); + assert(m_status != HIT); + cache_block_t* block = m_tag_array->get_block(cache_index); + block->set_status(MODIFIED, mf->get_access_sector_mask()); + if(m_status == HIT_RESERVED) { + block->set_ignore_on_fill(true, mf->get_access_sector_mask()); + block->set_modified_on_fill(true, mf->get_access_sector_mask()); + } + + if(mf->get_access_byte_mask().count() == m_config.get_atom_sz()) + { + block->set_m_readable(true, mf->get_access_sector_mask()); + } else + { + block->set_m_readable(false, mf->get_access_sector_mask()); + } + + if( m_status != RESERVATION_FAIL ){ + // If evicted block is modified and not a write-through + // (already modified lower level) + if( wb && (m_config.m_write_policy != WRITE_THROUGH) ) { + mem_fetch *wb = m_memfetch_creator->alloc(evicted.m_block_addr, + m_wrbk_type,evicted.m_modified_size,true); + send_write_request(wb, cache_event(WRITE_BACK_REQUEST_SENT, evicted), time, events); + } + return MISS; + } + return RESERVATION_FAIL; } /// No write-allocate miss: Simply send write request to lower level memory diff --git a/src/gpgpu-sim/gpu-cache.h b/src/gpgpu-sim/gpu-cache.h index d2b7757..96b9a6d 100644 --- a/src/gpgpu-sim/gpu-cache.h +++ b/src/gpgpu-sim/gpu-cache.h @@ -454,7 +454,8 @@ enum allocation_policy_t { enum write_allocate_policy_t { NO_WRITE_ALLOCATE, WRITE_ALLOCATE, - FETCH_ON_WRITE + FETCH_ON_WRITE, + LAZY_FETCH_ON_READ }; enum mshr_config_t { @@ -555,6 +556,7 @@ public: case 'N': m_write_alloc_policy = NO_WRITE_ALLOCATE; break; case 'W': m_write_alloc_policy = WRITE_ALLOCATE; break; case 'F': m_write_alloc_policy = FETCH_ON_WRITE; break; + case 'L': m_write_alloc_policy = LAZY_FETCH_ON_READ; break; default: exit_parse_error(); } @@ -572,9 +574,9 @@ public: assert(0 && "Invalid cache configuration: Writeback cache cannot allocate new line on fill. "); } - if(m_write_alloc_policy == FETCH_ON_WRITE && m_alloc_policy == ON_FILL) + if((m_write_alloc_policy == FETCH_ON_WRITE || m_write_alloc_policy == LAZY_FETCH_ON_READ )&& m_alloc_policy == ON_FILL) { - assert(0 && "Invalid cache configuration: FETCH_ON_WRITE cannot work properly with ON_FILL policy. Cache must be ON_MISS. "); + assert(0 && "Invalid cache configuration: FETCH_ON_WRITE and LAZY_FETCH_ON_READ cannot work properly with ON_FILL policy. Cache must be ON_MISS. "); } if(m_cache_type == SECTOR) { @@ -742,7 +744,8 @@ public: unsigned size() const { return m_config.get_num_lines();} cache_block_t* get_block(unsigned idx) { return m_lines[idx];} - void flush(); // flash invalidate all entries + void flush(); // flush all written entries + void invalidate(); // invalidate all entries void new_window(); void print( FILE *stream, unsigned &total_access, unsigned &total_misses ) const; @@ -994,6 +997,7 @@ public: mem_fetch *next_access(){return m_mshrs.next_access();} // flash invalidate all entries in cache void flush(){m_tag_array->flush();} + void invalidate(){m_tag_array->invalidate();} void print(FILE *fp, unsigned &accesses, unsigned &misses) const; void display_state( FILE *fp ) const; @@ -1179,6 +1183,7 @@ public: case NO_WRITE_ALLOCATE: m_wr_miss = &data_cache::wr_miss_no_wa; break; case WRITE_ALLOCATE: m_wr_miss = &data_cache::wr_miss_wa_naive; break; case FETCH_ON_WRITE: m_wr_miss = &data_cache::wr_miss_wa_fetch_on_write; break; + case LAZY_FETCH_ON_READ: m_wr_miss = &data_cache::wr_miss_wa_lazy_fetch_on_read; break; default: assert(0 && "Error: Must set valid cache write miss policy\n"); break; // Need to set a write miss function @@ -1299,7 +1304,14 @@ protected: mem_fetch *mf, unsigned time, std::list &events, - enum cache_request_status status ); // write-allocate with read-fetch-only + enum cache_request_status status ); // write-allocate with fetch-on-every-write + enum cache_request_status + wr_miss_wa_lazy_fetch_on_read( new_addr_type addr, + unsigned cache_index, + mem_fetch *mf, + unsigned time, + std::list &events, + enum cache_request_status status ); // write-allocate with read-fetch-only enum cache_request_status wr_miss_wa_write_validate( new_addr_type addr, unsigned cache_index, diff --git a/src/gpgpu-sim/gpu-sim.cc b/src/gpgpu-sim/gpu-sim.cc index c5d4464..d48de25 100644 --- a/src/gpgpu-sim/gpu-sim.cc +++ b/src/gpgpu-sim/gpu-sim.cc @@ -1548,12 +1548,12 @@ void gpgpu_sim::cycle() issue_block2core(); - // Depending on configuration, flush the caches once all of threads are completed. + // Depending on configuration, invalidate the caches once all of threads are completed. int all_threads_complete = 1; if (m_config.gpgpu_flush_l1_cache) { for (unsigned i=0;in_simt_clusters;i++) { if (m_cluster[i]->get_not_completed() == 0) - m_cluster[i]->cache_flush(); + m_cluster[i]->cache_invalidate(); else all_threads_complete = 0 ; } @@ -1575,7 +1575,7 @@ void gpgpu_sim::cycle() int dlc = 0; for (unsigned i=0;im_n_mem;i++) { dlc = m_memory_sub_partition[i]->flushL2(); - assert (dlc == 0); // need to model actual writes to DRAM here + assert (dlc == 0); // TODO: need to model actual writes to DRAM here printf("Dirty lines flushed from L2 %d is %d\n", i, dlc ); } } diff --git a/src/gpgpu-sim/l2cache.cc b/src/gpgpu-sim/l2cache.cc index b1465a8..359d3c8 100644 --- a/src/gpgpu-sim/l2cache.cc +++ b/src/gpgpu-sim/l2cache.cc @@ -428,7 +428,7 @@ void memory_sub_partition::cache_cycle( unsigned cycle ) m_icnt_L2_queue->pop(); } } else if ( status != RESERVATION_FAIL ) { - if(mf->is_write() && m_config->m_L2_config.m_write_alloc_policy == FETCH_ON_WRITE && !was_writeallocate_sent(events)) { + if(mf->is_write() && (m_config->m_L2_config.m_write_alloc_policy == FETCH_ON_WRITE || m_config->m_L2_config.m_write_alloc_policy == LAZY_FETCH_ON_READ) && !was_writeallocate_sent(events)) { 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); @@ -568,7 +568,15 @@ unsigned memory_sub_partition::flushL2() if (!m_config->m_L2_config.disabled()) { m_L2cache->flush(); } - return 0; // L2 is read only in this version + return 0; //TODO: write the flushed data to the main memory +} + +unsigned memory_sub_partition::invalidateL2() +{ + if (!m_config->m_L2_config.disabled()) { + m_L2cache->invalidate(); + } + return 0; } bool memory_sub_partition::busy() const diff --git a/src/gpgpu-sim/l2cache.h b/src/gpgpu-sim/l2cache.h index 2d13918..18c0a8b 100644 --- a/src/gpgpu-sim/l2cache.h +++ b/src/gpgpu-sim/l2cache.h @@ -162,6 +162,7 @@ public: void set_done( mem_fetch *mf ); unsigned flushL2(); + unsigned invalidateL2(); // interface to L2_dram_queue bool L2_dram_queue_empty() const; diff --git a/src/gpgpu-sim/shader.cc b/src/gpgpu-sim/shader.cc index d2f40a1..b660b8c 100644 --- a/src/gpgpu-sim/shader.cc +++ b/src/gpgpu-sim/shader.cc @@ -1593,6 +1593,11 @@ void ldst_unit::flush(){ m_L1D->flush(); } +void ldst_unit::invalidate(){ + // Flush L1D cache + m_L1D->invalidate(); +} + simd_function_unit::simd_function_unit( const shader_core_config *config ) { m_config=config; @@ -2644,6 +2649,11 @@ void shader_core_ctx::cache_flush() m_ldst_unit->flush(); } +void shader_core_ctx::cache_invalidate() +{ + m_ldst_unit->invalidate(); +} + // modifiers std::list opndcoll_rfu_t::arbiter_t::allocate_reads() { @@ -3461,6 +3471,12 @@ void simt_core_cluster::cache_flush() m_core[i]->cache_flush(); } +void simt_core_cluster::cache_invalidate() +{ + for( unsigned i=0; i < m_config->n_simt_cores_per_cluster; i++ ) + m_core[i]->cache_invalidate(); +} + bool simt_core_cluster::icnt_injection_buffer_full(unsigned size, bool write) { unsigned request_size = size; diff --git a/src/gpgpu-sim/shader.h b/src/gpgpu-sim/shader.h index ae22eaa..cc441b3 100644 --- a/src/gpgpu-sim/shader.h +++ b/src/gpgpu-sim/shader.h @@ -1155,6 +1155,7 @@ public: void fill( mem_fetch *mf ); void flush(); + void invalidate(); void writeback(); // accessors @@ -1655,6 +1656,7 @@ public: void issue_block2core( class kernel_info_t &kernel ); void cache_flush(); + void cache_invalidate(); void accept_fetch_response( mem_fetch *mf ); void accept_ldst_unit_response( class mem_fetch * mf ); void broadcast_barrier_reduction(unsigned cta_id, unsigned bar_id,warp_set_t warps); @@ -1947,6 +1949,7 @@ public: void reinit(); unsigned issue_block2core(); void cache_flush(); + void cache_invalidate(); bool icnt_injection_buffer_full(unsigned size, bool write); void icnt_inject_request_packet(class mem_fetch *mf); -- cgit v1.3 From 5e7bd910c07c066d5d1cc4b12f8aa7abefcdb411 Mon Sep 17 00:00:00 2001 From: Mahmoud Date: Mon, 27 Aug 2018 16:13:13 -0400 Subject: improving code quality --- src/gpgpu-sim/gpu-cache.cc | 72 +++++++++++++++++++++++----------------------- src/gpgpu-sim/gpu-cache.h | 8 ++++++ src/gpgpu-sim/l2cache.cc | 9 +++--- src/gpgpu-sim/mem_fetch.h | 10 +++++-- 4 files changed, 57 insertions(+), 42 deletions(-) (limited to 'src/gpgpu-sim/gpu-cache.h') diff --git a/src/gpgpu-sim/gpu-cache.cc b/src/gpgpu-sim/gpu-cache.cc index 9d81de9..f181f20 100644 --- a/src/gpgpu-sim/gpu-cache.cc +++ b/src/gpgpu-sim/gpu-cache.cc @@ -916,8 +916,8 @@ void baseline_cache::cycle(){ void baseline_cache::fill(mem_fetch *mf, unsigned time){ if(m_config.m_mshr_type == SECTOR_ASSOC) { - assert(mf->original_mf); - extra_mf_fields_lookup::iterator e = m_extra_mf_fields.find(mf->original_mf); + assert(mf->get_original_mf()); + extra_mf_fields_lookup::iterator e = m_extra_mf_fields.find(mf->get_original_mf()); assert( e != m_extra_mf_fields.end() ); e->second.pending_read--; @@ -927,7 +927,7 @@ void baseline_cache::fill(mem_fetch *mf, unsigned time){ return; } else { mem_fetch *temp = mf; - mf = mf->original_mf; + mf = mf->get_original_mf(); delete temp; } } @@ -1294,45 +1294,45 @@ data_cache::wr_miss_wa_lazy_fetch_on_read( new_addr_type addr, new_addr_type mshr_addr = m_config.mshr_addr(mf->get_addr()); - //if the request writes to the whole cache line/sector, then, write and set cache line Modified. - //and no need to send read request to memory or reserve mshr + //if the request writes to the whole cache line/sector, then, write and set cache line Modified. + //and no need to send read request to memory or reserve mshr - if(miss_queue_full(0)) { - m_stats.inc_fail_stats(mf->get_access_type(), MISS_QUEUE_FULL); - return RESERVATION_FAIL; // cannot handle request this cycle - } + if(miss_queue_full(0)) { + m_stats.inc_fail_stats(mf->get_access_type(), MISS_QUEUE_FULL); + return RESERVATION_FAIL; // cannot handle request this cycle + } - bool wb = false; - evicted_block_info evicted; + bool wb = false; + evicted_block_info evicted; - cache_request_status m_status = m_tag_array->access(block_addr,time,cache_index,wb,evicted,mf); - assert(m_status != HIT); - cache_block_t* block = m_tag_array->get_block(cache_index); - block->set_status(MODIFIED, mf->get_access_sector_mask()); - if(m_status == HIT_RESERVED) { - block->set_ignore_on_fill(true, mf->get_access_sector_mask()); - block->set_modified_on_fill(true, mf->get_access_sector_mask()); - } + cache_request_status m_status = m_tag_array->access(block_addr,time,cache_index,wb,evicted,mf); + assert(m_status != HIT); + cache_block_t* block = m_tag_array->get_block(cache_index); + block->set_status(MODIFIED, mf->get_access_sector_mask()); + if(m_status == HIT_RESERVED) { + block->set_ignore_on_fill(true, mf->get_access_sector_mask()); + block->set_modified_on_fill(true, mf->get_access_sector_mask()); + } - if(mf->get_access_byte_mask().count() == m_config.get_atom_sz()) - { - block->set_m_readable(true, mf->get_access_sector_mask()); - } else - { - block->set_m_readable(false, mf->get_access_sector_mask()); - } + if(mf->get_access_byte_mask().count() == m_config.get_atom_sz()) + { + block->set_m_readable(true, mf->get_access_sector_mask()); + } else + { + block->set_m_readable(false, mf->get_access_sector_mask()); + } - if( m_status != RESERVATION_FAIL ){ - // If evicted block is modified and not a write-through - // (already modified lower level) - if( wb && (m_config.m_write_policy != WRITE_THROUGH) ) { - mem_fetch *wb = m_memfetch_creator->alloc(evicted.m_block_addr, - m_wrbk_type,evicted.m_modified_size,true); - send_write_request(wb, cache_event(WRITE_BACK_REQUEST_SENT, evicted), time, events); - } - return MISS; + if( m_status != RESERVATION_FAIL ){ + // If evicted block is modified and not a write-through + // (already modified lower level) + if( wb && (m_config.m_write_policy != WRITE_THROUGH) ) { + mem_fetch *wb = m_memfetch_creator->alloc(evicted.m_block_addr, + m_wrbk_type,evicted.m_modified_size,true); + send_write_request(wb, cache_event(WRITE_BACK_REQUEST_SENT, evicted), time, events); } - return RESERVATION_FAIL; + return MISS; + } + return RESERVATION_FAIL; } /// No write-allocate miss: Simply send write request to lower level memory diff --git a/src/gpgpu-sim/gpu-cache.h b/src/gpgpu-sim/gpu-cache.h index 96b9a6d..dee43f2 100644 --- a/src/gpgpu-sim/gpu-cache.h +++ b/src/gpgpu-sim/gpu-cache.h @@ -355,15 +355,18 @@ struct sector_cache_block : public cache_block_t { return m_status[sidx]; } + virtual void set_status(enum cache_block_state status, mem_access_sector_mask_t sector_mask) { unsigned sidx = get_sector_index(sector_mask); m_status[sidx] = status; } + virtual unsigned get_last_access_time() { return m_line_last_access_time; } + virtual void set_last_access_time(unsigned time, mem_access_sector_mask_t sector_mask) { unsigned sidx = get_sector_index(sector_mask); @@ -371,25 +374,30 @@ struct sector_cache_block : public cache_block_t { m_last_sector_access_time[sidx] = time; m_line_last_access_time = time; } + virtual unsigned get_alloc_time() { return m_line_alloc_time; } + virtual void set_ignore_on_fill(bool m_ignore, mem_access_sector_mask_t sector_mask) { unsigned sidx = get_sector_index(sector_mask); m_ignore_on_fill_status[sidx] = m_ignore; } + virtual void set_modified_on_fill(bool m_modified, mem_access_sector_mask_t sector_mask) { unsigned sidx = get_sector_index(sector_mask); m_set_modified_on_fill[sidx] = m_modified; } + virtual void set_m_readable(bool readable, mem_access_sector_mask_t sector_mask) { unsigned sidx = get_sector_index(sector_mask); m_readable[sidx] = readable; } + virtual bool is_readable(mem_access_sector_mask_t sector_mask) { unsigned sidx = get_sector_index(sector_mask); return m_readable[sidx]; diff --git a/src/gpgpu-sim/l2cache.cc b/src/gpgpu-sim/l2cache.cc index 359d3c8..f42610f 100644 --- a/src/gpgpu-sim/l2cache.cc +++ b/src/gpgpu-sim/l2cache.cc @@ -362,10 +362,11 @@ void memory_sub_partition::cache_cycle( unsigned cycle ) }else{ if(m_config->m_L2_config.m_write_alloc_policy == FETCH_ON_WRITE) { - assert(mf->original_wr_mf); - mf->original_wr_mf->set_reply(); - mf->original_wr_mf->set_status(IN_PARTITION_L2_TO_ICNT_QUEUE,gpu_sim_cycle+gpu_tot_sim_cycle); - m_L2_icnt_queue->push(mf->original_wr_mf); + mem_fetch* original_wr_mf = mf->get_original_wr_mf(); + assert(original_wr_mf); + original_wr_mf->set_reply(); + original_wr_mf->set_status(IN_PARTITION_L2_TO_ICNT_QUEUE,gpu_sim_cycle+gpu_tot_sim_cycle); + m_L2_icnt_queue->push(original_wr_mf); } m_request_tracker.erase(mf); delete mf; diff --git a/src/gpgpu-sim/mem_fetch.h b/src/gpgpu-sim/mem_fetch.h index 278cf32..da67d49 100644 --- a/src/gpgpu-sim/mem_fetch.h +++ b/src/gpgpu-sim/mem_fetch.h @@ -115,8 +115,10 @@ public: const memory_config *get_mem_config(){return m_mem_config;} unsigned get_num_flits(bool simt_to_mem); - mem_fetch* original_mf; - mem_fetch* original_wr_mf; + + mem_fetch* get_original_mf() { return original_mf; } + mem_fetch* get_original_wr_mf() { return original_wr_mf; } + private: // request source information unsigned m_request_uid; @@ -148,6 +150,10 @@ private: const class memory_config *m_mem_config; unsigned icnt_flit_size; + + mem_fetch* original_mf; //this pointer is set up when a request is divided into sector requests at L2 cache (if the req size > L2 sector size), so the pointer refers to the original request + mem_fetch* original_wr_mf; //this pointer refers to the original write req, when fetch-on-write policy is used + }; #endif -- cgit v1.3 From f852a7108e691045dd3910065836a817babcde8c Mon Sep 17 00:00:00 2001 From: Mahmoud Date: Fri, 7 Sep 2018 22:01:31 -0400 Subject: adding streamin cache + fixing TEX cache + adding l1 latency and smem latency --- configs/4.x-cfgs/SM2_GTX480/gpgpusim.config | 2 +- configs/4.x-cfgs/SM6_P100/config_fermi_islip.icnt | 73 --------- configs/4.x-cfgs/SM6_P100/gpgpusim.config | 174 --------------------- .../SM6_P100_64SMs/config_fermi_islip.icnt | 73 --------- configs/4.x-cfgs/SM6_P100_64SMs/gpgpusim.config | 174 --------------------- configs/4.x-cfgs/SM6_TITANX/gpgpusim.config | 27 ++-- src/abstract_hardware_model.h | 1 + src/gpgpu-sim/gpu-cache.cc | 20 ++- src/gpgpu-sim/gpu-cache.h | 36 ++++- src/gpgpu-sim/gpu-sim.cc | 6 + src/gpgpu-sim/l2cache.cc | 8 +- src/gpgpu-sim/shader.cc | 126 ++++++++++++++- src/gpgpu-sim/shader.h | 6 + 13 files changed, 207 insertions(+), 519 deletions(-) delete mode 100644 configs/4.x-cfgs/SM6_P100/config_fermi_islip.icnt delete mode 100644 configs/4.x-cfgs/SM6_P100/gpgpusim.config delete mode 100644 configs/4.x-cfgs/SM6_P100_64SMs/config_fermi_islip.icnt delete mode 100644 configs/4.x-cfgs/SM6_P100_64SMs/gpgpusim.config (limited to 'src/gpgpu-sim/gpu-cache.h') diff --git a/configs/4.x-cfgs/SM2_GTX480/gpgpusim.config b/configs/4.x-cfgs/SM2_GTX480/gpgpusim.config index 7f8da49..35341f7 100644 --- a/configs/4.x-cfgs/SM2_GTX480/gpgpusim.config +++ b/configs/4.x-cfgs/SM2_GTX480/gpgpusim.config @@ -67,7 +67,7 @@ -memory_partition_indexing 0 -gpgpu_cache:il1 N:4:128:4,L:R:f:N:L,S:2:32,4 --gpgpu_tex_cache:l1 N:4:128:24,L:R:m:N:L,F:128:4,128:2 +-gpgpu_tex_cache:l1 N:4:128:24,L:R:m:N:L,T:128:4,128:2 -gpgpu_const_cache:l1 N:64:64:2,L:R:f:N:L,S:2:32,4 # enable operand collector diff --git a/configs/4.x-cfgs/SM6_P100/config_fermi_islip.icnt b/configs/4.x-cfgs/SM6_P100/config_fermi_islip.icnt deleted file mode 100644 index e7c2c3b..0000000 --- a/configs/4.x-cfgs/SM6_P100/config_fermi_islip.icnt +++ /dev/null @@ -1,73 +0,0 @@ -//21*1 fly with 32 flits per packet under gpgpusim injection mode -use_map = 0; -flit_size = 40; - -// currently we do not use this, see subnets below -network_count = 2; - -// Topology -topology = fly; -k = 60; -n = 1; - -// Routing - -routing_function = dest_tag; - -// Flow control - -num_vcs = 1; -vc_buf_size = 128; -input_buffer_size = 256; -ejection_buffer_size = 128; -boundary_buffer_size = 128; - -wait_for_tail_credit = 0; - -// Router architecture - -vc_allocator = islip; //separable_input_first; -sw_allocator = islip; //separable_input_first; -alloc_iters = 1; - -credit_delay = 0; -routing_delay = 0; -vc_alloc_delay = 1; -sw_alloc_delay = 1; - -input_speedup = 2; -output_speedup = 1; -internal_speedup = 1.0; - -// Traffic, GPGPU-Sim does not use this - -traffic = uniform; -packet_size ={{1,2,3,4},{10,20}}; -packet_size_rate={{1,1,1,1},{2,1}}; - -// Simulation - Don't change - -sim_type = gpgpusim; -//sim_type = latency; -injection_rate = 0.1; - -subnets = 2; - -// Always use read and write no matter following line -//use_read_write = 1; - - -read_request_subnet = 0; -read_reply_subnet = 1; -write_request_subnet = 0; -write_reply_subnet = 1; - -read_request_begin_vc = 0; -read_request_end_vc = 0; -write_request_begin_vc = 0; -write_request_end_vc = 0; -read_reply_begin_vc = 0; -read_reply_end_vc = 0; -write_reply_begin_vc = 0; -write_reply_end_vc = 0; - diff --git a/configs/4.x-cfgs/SM6_P100/gpgpusim.config b/configs/4.x-cfgs/SM6_P100/gpgpusim.config deleted file mode 100644 index a4e745d..0000000 --- a/configs/4.x-cfgs/SM6_P100/gpgpusim.config +++ /dev/null @@ -1,174 +0,0 @@ -# functional simulator specification --gpgpu_ptx_instruction_classification 0 --gpgpu_ptx_sim_mode 0 --gpgpu_ptx_force_max_capability 60 - -# SASS execution (only supported with CUDA >= 4.0) --gpgpu_ptx_convert_to_ptxplus 0 --gpgpu_ptx_save_converted_ptxplus 0 - -# high level architecture configuration --gpgpu_n_clusters 28 --gpgpu_n_cores_per_cluster 2 --gpgpu_n_mem 32 --gpgpu_n_sub_partition_per_mchannel 1 - -# Pscal clock domains -#-gpgpu_clock_domains ::: -# Pascal NVIDIA GP100 clock domains are adopted from -# https://en.wikipedia.org/wiki/Nvidia_Tesla --gpgpu_clock_domains 1480.0:1480.0:1480.0:715.0 - -# shader core pipeline config --gpgpu_shader_registers 65536 - -# This implies a maximum of 64 warps/SM --gpgpu_shader_core_pipeline 2048:32 --gpgpu_shader_cta 32 --gpgpu_simd_model 1 - -# Pipeline widths and number of FUs -# ID_OC_SP,ID_OC_DP,ID_OC_SFU,ID_OC_MEM,OC_EX_SP,OC_EX_DP,OC_EX_SFU,OC_EX_MEM,EX_WB -## Pascal GP100 has 2 SP SIMD units, 2 SFU units, 2 DP units per core -## we need to scale the number of pipeline registers to be equal to the number of SP units --gpgpu_pipeline_widths 2,2,2,1,2,2,2,1,6 --gpgpu_num_sp_units 2 --gpgpu_num_sfu_units 2 --gpgpu_num_dp_units 2 - -# Instruction latencies and initiation intervals -# "ADD,MAX,MUL,MAD,DIV" -# All Div operations are executed on SFU unit -# Throughput (initiation latency) are adopted from CUDA SDK document V8, section 5.4.1, Table 2 --ptx_opcode_latency_int 4,13,4,5,145 --ptx_opcode_initiation_int 1,1,1,1,4 --ptx_opcode_latency_fp 4,13,4,5,39 --ptx_opcode_initiation_fp 1,2,1,1,4 --ptx_opcode_latency_dp 8,19,8,8,330 --ptx_opcode_initiation_dp 2,2,2,2,130 --ptx_opcode_latency_sfu 8 --ptx_opcode_initiation_sfu 4 - - -# ::,::::,::,:** -# ** Optional parameter - Required when mshr_type==Texture Fifo -# Note: Hashing set index function (H) only applies to a set size of 32 or 64. -# Pascal GP100 has 64KB Shared memory --gpgpu_cache:dl1 S:64:128:6,L:L:f:N:H,A:256:8,16:0,32 --gpgpu_cache:dl1PrefL1 S:64:128:6,L:L:f:N:H,A:256:8,16:0,32 --gpgpu_cache:dl1PrefShared S:64:128:6,L:L:f:N:H,A:256:8,16:0,32 --gpgpu_shmem_size 65536 --gpgpu_shmem_size_PrefL1 65536 --gpgpu_shmem_size_PrefShared 65536 --gmem_skip_L1D 0 --icnt_flit_size 40 --gpgpu_n_cluster_ejection_buffer_size 32 - -# 32 sets, each 128 bytes 16-way for each memory sub partition (128 KB per memory sub partition). This gives 4MB L2 cache --gpgpu_cache:dl2 S:64:128:16,L:B:m:L:L,A:256:4,32:0,32 --gpgpu_cache:dl2_texture_only 0 --gpgpu_dram_partition_queues 64:64:64:64 --perf_sim_memcpy 0 --memory_partition_indexing 2 - -# 4 KB Inst. --gpgpu_cache:il1 N:8:128:4,L:R:f:N:L,S:2:48,4 -# 48 KB Tex --gpgpu_tex_cache:l1 N:16:128:24,L:R:m:N:L,F:128:4,128:2 -# 12 KB Const --gpgpu_const_cache:l1 N:128:64:2,L:R:f:N:L,S:2:64,4 - -# enable operand collector --gpgpu_operand_collector_num_units_sp 12 --gpgpu_operand_collector_num_units_sfu 6 --gpgpu_operand_collector_num_units_mem 8 --gpgpu_operand_collector_num_units_dp 6 --gpgpu_operand_collector_num_in_ports_sp 4 --gpgpu_operand_collector_num_out_ports_sp 4 --gpgpu_operand_collector_num_in_ports_sfu 1 --gpgpu_operand_collector_num_out_ports_sfu 1 --gpgpu_operand_collector_num_in_ports_mem 1 --gpgpu_operand_collector_num_out_ports_mem 1 --gpgpu_operand_collector_num_in_ports_dp 1 --gpgpu_operand_collector_num_out_ports_dp 1 --gpgpu_num_reg_banks 32 - -# shared memory bankconflict detection --gpgpu_shmem_num_banks 32 --gpgpu_shmem_limited_broadcast 0 --gpgpu_shmem_warp_parts 1 --gpgpu_coalesce_arch 60 - -## In Pascal, a warp scheduler can issue 2 insts per cycle using 2 diff execution units --gpgpu_max_insn_issue_per_warp 2 --gpgpu_dual_issue_diff_exec_units 1 - -# interconnection --network_mode 1 --inter_config_file config_fermi_islip.icnt - -# memory partition latency config --rop_latency 120 --dram_latency 100 - -# dram model config --gpgpu_dram_scheduler 1 -# The DRAM return queue and the scheduler queue together should provide buffer -# to sustain the memory level parallelism to tolerate DRAM latency -# To allow 100% DRAM utility, there should at least be enough buffer to sustain -# the minimum DRAM latency (100 core cycles). I.e. -# Total buffer space required = 100 x 924MHz / 700MHz = 132 --gpgpu_frfcfs_dram_sched_queue_size 64 --gpgpu_dram_return_queue_size 192 - -# for HBM, 32 channles, each (128 bits) 16 bytes width --gpgpu_n_mem_per_ctrlr 1 --gpgpu_dram_buswidth 16 --gpgpu_dram_burst_length 2 --dram_data_command_freq_ratio 2 # HBM is DDR --gpgpu_mem_address_mask 1 --gpgpu_mem_addr_mapping dramid@8;00000000.00000000.00000000.00000000.0000RRRR.RRRRRRRR.RBBBBCCC.CCCSSSSS - -# HBM timing are adopted from hynix JESD235 standered and nVidia HPCA 2017 paper (http://www.cs.utah.edu/~nil/pubs/hpca17.pdf) -# Timing for 1 GHZ -# tRRDl and tWTR are missing, need to be added -#-gpgpu_dram_timing_opt "nbk=16:CCD=1:RRD=4:RCD=14:RAS=33:RP=14:RC=47: -# CL=14:WL=2:CDLR=3:WR=12:nbkgrp=4:CCDL=2:RTPL=4" - -# Timing for 715 MHZ, Tesla Pascal P100 HBM runs at 715 MHZ --gpgpu_dram_timing_opt "nbk=16:CCD=1:RRD=3:RCD=10:RAS=24:RP=10:RC=34: - CL=10:WL=2:CDLR=3:WR=9:nbkgrp=4:CCDL=2:RTPL=3" - -# HBM has dual bus interface, in which it can issue two col and row commands at a time --dual_bus_interface 1 -# select lower bits for bnkgrp to increase bnkgrp parallelism --dram_bnk_indexing_policy 0 --dram_bnkgrp_indexing_policy 1 - -#-Seperate_Write_Queue_Enable 1 -#-Write_Queue_Size 64:56:32 - -# Pascal has two schedulers per core --gpgpu_num_sched_per_core 2 -# Two Level Scheduler with active and pending pools -#-gpgpu_scheduler two_level_active:6:0:1 -# Loose round robbin scheduler -#-gpgpu_scheduler lrr -# Greedy then oldest scheduler --gpgpu_scheduler gto - -# stat collection --gpgpu_memlatency_stat 14 --gpgpu_runtime_stat 500 --enable_ptx_file_line_stats 1 --visualizer_enabled 0 - -# power model configs, disable it untill we create a real energy model for Pascal 100 --power_simulation_enabled 0 --gpuwattch_xml_file gpuwattch_gtx480.xml - -# tracing functionality -#-trace_enabled 1 -#-trace_components WARP_SCHEDULER,SCOREBOARD -#-trace_sampling_core 0 - diff --git a/configs/4.x-cfgs/SM6_P100_64SMs/config_fermi_islip.icnt b/configs/4.x-cfgs/SM6_P100_64SMs/config_fermi_islip.icnt deleted file mode 100644 index 81153b0..0000000 --- a/configs/4.x-cfgs/SM6_P100_64SMs/config_fermi_islip.icnt +++ /dev/null @@ -1,73 +0,0 @@ -//21*1 fly with 32 flits per packet under gpgpusim injection mode -use_map = 0; -flit_size = 40; - -// currently we do not use this, see subnets below -network_count = 2; - -// Topology -topology = fly; -k = 64; -n = 1; - -// Routing - -routing_function = dest_tag; - -// Flow control - -num_vcs = 1; -vc_buf_size = 128; -input_buffer_size = 256; -ejection_buffer_size = 128; -boundary_buffer_size = 128; - -wait_for_tail_credit = 0; - -// Router architecture - -vc_allocator = islip; //separable_input_first; -sw_allocator = islip; //separable_input_first; -alloc_iters = 1; - -credit_delay = 0; -routing_delay = 0; -vc_alloc_delay = 1; -sw_alloc_delay = 1; - -input_speedup = 2; -output_speedup = 1; -internal_speedup = 1.0; - -// Traffic, GPGPU-Sim does not use this - -traffic = uniform; -packet_size ={{1,2,3,4},{10,20}}; -packet_size_rate={{1,1,1,1},{2,1}}; - -// Simulation - Don't change - -sim_type = gpgpusim; -//sim_type = latency; -injection_rate = 0.1; - -subnets = 2; - -// Always use read and write no matter following line -//use_read_write = 1; - - -read_request_subnet = 0; -read_reply_subnet = 1; -write_request_subnet = 0; -write_reply_subnet = 1; - -read_request_begin_vc = 0; -read_request_end_vc = 0; -write_request_begin_vc = 0; -write_request_end_vc = 0; -read_reply_begin_vc = 0; -read_reply_end_vc = 0; -write_reply_begin_vc = 0; -write_reply_end_vc = 0; - diff --git a/configs/4.x-cfgs/SM6_P100_64SMs/gpgpusim.config b/configs/4.x-cfgs/SM6_P100_64SMs/gpgpusim.config deleted file mode 100644 index edcd919..0000000 --- a/configs/4.x-cfgs/SM6_P100_64SMs/gpgpusim.config +++ /dev/null @@ -1,174 +0,0 @@ -# functional simulator specification --gpgpu_ptx_instruction_classification 0 --gpgpu_ptx_sim_mode 0 --gpgpu_ptx_force_max_capability 60 - -# SASS execution (only supported with CUDA >= 4.0) --gpgpu_ptx_convert_to_ptxplus 0 --gpgpu_ptx_save_converted_ptxplus 0 - -# high level architecture configuration --gpgpu_n_clusters 32 --gpgpu_n_cores_per_cluster 2 --gpgpu_n_mem 32 --gpgpu_n_sub_partition_per_mchannel 1 - -# Pscal clock domains -#-gpgpu_clock_domains ::: -# Pascal NVIDIA GP100 clock domains are adopted from -# https://en.wikipedia.org/wiki/Nvidia_Tesla --gpgpu_clock_domains 1480.0:1480.0:1480.0:715.0 - -# shader core pipeline config --gpgpu_shader_registers 65536 - -# This implies a maximum of 64 warps/SM --gpgpu_shader_core_pipeline 2048:32 --gpgpu_shader_cta 32 --gpgpu_simd_model 1 - -# Pipeline widths and number of FUs -# ID_OC_SP,ID_OC_DP,ID_OC_SFU,ID_OC_MEM,OC_EX_SP,OC_EX_DP,OC_EX_SFU,OC_EX_MEM,EX_WB -## Pascal GP100 has 2 SP SIMD units, 2 SFU units, 2 DP units per core -## we need to scale the number of pipeline registers to be equal to the number of SP units --gpgpu_pipeline_widths 2,2,2,1,2,2,2,1,6 --gpgpu_num_sp_units 2 --gpgpu_num_sfu_units 2 --gpgpu_num_dp_units 2 - -# Instruction latencies and initiation intervals -# "ADD,MAX,MUL,MAD,DIV" -# All Div operations are executed on SFU unit -# Throughput (initiation latency) are adopted from CUDA SDK document V8, section 5.4.1, Table 2 --ptx_opcode_latency_int 4,13,4,5,145 --ptx_opcode_initiation_int 1,1,1,1,4 --ptx_opcode_latency_fp 4,13,4,5,39 --ptx_opcode_initiation_fp 1,2,1,1,4 --ptx_opcode_latency_dp 8,19,8,8,330 --ptx_opcode_initiation_dp 2,2,2,2,130 --ptx_opcode_latency_sfu 8 --ptx_opcode_initiation_sfu 4 - - -# ::,::::,::,:** -# ** Optional parameter - Required when mshr_type==Texture Fifo -# Note: Hashing set index function (H) only applies to a set size of 32 or 64. -# Pascal GP100 has 64KB Shared memory --gpgpu_cache:dl1 S:64:128:6,L:L:f:N:H,A:256:8,16:0,32 --gpgpu_cache:dl1PrefL1 S:64:128:6,L:L:f:N:H,A:256:8,16:0,32 --gpgpu_cache:dl1PrefShared S:64:128:6,L:L:f:N:H,A:256:8,16:0,32 --gpgpu_shmem_size 65536 --gpgpu_shmem_size_PrefL1 65536 --gpgpu_shmem_size_PrefShared 65536 --gmem_skip_L1D 0 --icnt_flit_size 40 --gpgpu_n_cluster_ejection_buffer_size 32 - -# 32 sets, each 128 bytes 16-way for each memory sub partition (128 KB per memory sub partition). This gives 4MB L2 cache --gpgpu_cache:dl2 S:64:128:16,L:B:m:L:L,A:256:4,32:0,32 --gpgpu_cache:dl2_texture_only 0 --gpgpu_dram_partition_queues 64:64:64:64 --perf_sim_memcpy 0 --memory_partition_indexing 2 - -# 4 KB Inst. --gpgpu_cache:il1 N:8:128:4,L:R:f:N:L,S:2:48,4 -# 48 KB Tex --gpgpu_tex_cache:l1 N:16:128:24,L:R:m:N:L,F:128:4,128:2 -# 12 KB Const --gpgpu_const_cache:l1 N:128:64:2,L:R:f:N:L,S:2:64,4 - -# enable operand collector --gpgpu_operand_collector_num_units_sp 12 --gpgpu_operand_collector_num_units_sfu 6 --gpgpu_operand_collector_num_units_mem 8 --gpgpu_operand_collector_num_units_dp 6 --gpgpu_operand_collector_num_in_ports_sp 4 --gpgpu_operand_collector_num_out_ports_sp 4 --gpgpu_operand_collector_num_in_ports_sfu 1 --gpgpu_operand_collector_num_out_ports_sfu 1 --gpgpu_operand_collector_num_in_ports_mem 1 --gpgpu_operand_collector_num_out_ports_mem 1 --gpgpu_operand_collector_num_in_ports_dp 1 --gpgpu_operand_collector_num_out_ports_dp 1 --gpgpu_num_reg_banks 32 - -# shared memory bankconflict detection --gpgpu_shmem_num_banks 32 --gpgpu_shmem_limited_broadcast 0 --gpgpu_shmem_warp_parts 1 --gpgpu_coalesce_arch 60 - -## In Pascal, a warp scheduler can issue 2 insts per cycle using 2 diff execution units --gpgpu_max_insn_issue_per_warp 2 --gpgpu_dual_issue_diff_exec_units 1 - -# interconnection --network_mode 1 --inter_config_file config_fermi_islip.icnt - -# memory partition latency config --rop_latency 120 --dram_latency 100 - -# dram model config --gpgpu_dram_scheduler 1 -# The DRAM return queue and the scheduler queue together should provide buffer -# to sustain the memory level parallelism to tolerate DRAM latency -# To allow 100% DRAM utility, there should at least be enough buffer to sustain -# the minimum DRAM latency (100 core cycles). I.e. -# Total buffer space required = 100 x 924MHz / 700MHz = 132 --gpgpu_frfcfs_dram_sched_queue_size 64 --gpgpu_dram_return_queue_size 192 - -# for HBM, 32 channles, each (128 bits) 16 bytes width --gpgpu_n_mem_per_ctrlr 1 --gpgpu_dram_buswidth 16 --gpgpu_dram_burst_length 2 --dram_data_command_freq_ratio 2 # HBM is DDR --gpgpu_mem_address_mask 1 --gpgpu_mem_addr_mapping dramid@8;00000000.00000000.00000000.00000000.0000RRRR.RRRRRRRR.RBBBBCCC.CCCSSSSS - -# HBM timing are adopted from hynix JESD235 standered and nVidia HPCA 2017 paper (http://www.cs.utah.edu/~nil/pubs/hpca17.pdf) -# Timing for 1 GHZ -# tRRDl and tWTR are missing, need to be added -#-gpgpu_dram_timing_opt "nbk=16:CCD=1:RRD=4:RCD=14:RAS=33:RP=14:RC=47: -# CL=14:WL=2:CDLR=3:WR=12:nbkgrp=4:CCDL=2:RTPL=4" - -# Timing for 715 MHZ, Tesla Pascal P100 HBM runs at 715 MHZ --gpgpu_dram_timing_opt "nbk=16:CCD=1:RRD=3:RCD=10:RAS=24:RP=10:RC=34: - CL=10:WL=2:CDLR=3:WR=9:nbkgrp=4:CCDL=2:RTPL=3" - -# HBM has dual bus interface, in which it can issue two col and row commands at a time --dual_bus_interface 1 -# select lower bits for bnkgrp to increase bnkgrp parallelism --dram_bnk_indexing_policy 0 --dram_bnkgrp_indexing_policy 1 - -#-Seperate_Write_Queue_Enable 1 -#-Write_Queue_Size 64:56:32 - -# Pascal has two schedulers per core --gpgpu_num_sched_per_core 2 -# Two Level Scheduler with active and pending pools -#-gpgpu_scheduler two_level_active:6:0:1 -# Loose round robbin scheduler -#-gpgpu_scheduler lrr -# Greedy then oldest scheduler --gpgpu_scheduler gto - -# stat collection --gpgpu_memlatency_stat 14 --gpgpu_runtime_stat 500 --enable_ptx_file_line_stats 1 --visualizer_enabled 0 - -# power model configs, disable it untill we create a real energy model for Pascal 100 --power_simulation_enabled 0 --gpuwattch_xml_file gpuwattch_gtx480.xml - -# tracing functionality -#-trace_enabled 1 -#-trace_components WARP_SCHEDULER,SCOREBOARD -#-trace_sampling_core 0 - diff --git a/configs/4.x-cfgs/SM6_TITANX/gpgpusim.config b/configs/4.x-cfgs/SM6_TITANX/gpgpusim.config index 7368882..9ea7202 100644 --- a/configs/4.x-cfgs/SM6_TITANX/gpgpusim.config +++ b/configs/4.x-cfgs/SM6_TITANX/gpgpusim.config @@ -56,24 +56,29 @@ -ptx_opcode_initiation_sfu 4 -ptx_opcode_latency_sfu 8 + +# latencies and cache configs are adopted from: +# https://arxiv.org/pdf/1804.06826.pdf # ::,::::,::,:** # ** Optional parameter - Required when mshr_type==Texture Fifo # Note: Hashing set index function (H) only applies to a set size of 32 or 64. -# Pascal GP102 has 96KB Shared memory -# Pascal GP102 has 24KB L1 cache -# The defulat is to disable the L1 cache, unless cache modifieres is used --gpgpu_cache:dl1 S:32:128:6,L:L:f:N:H,A:256:8,16:0,32 --gpgpu_cache:dl1PrefL1 S:32:128:6,L:L:f:N:H,A:256:8,16:0,32 --gpgpu_cache:dl1PrefShared S:32:128:6,L:L:f:N:H,A:256:8,16:0,32 +# Pascal GP102 has 96KB Shared memory divided over 2 cores, each has 48KB +# Pascal GP102 has 2 banks L1 cache, where each is 24KB L1 cache +# The defulat is to disable the L1 cache, unless cache modifieres are used +-gpgpu_cache:dl1 S:48:128:4,L:L:s:N:H,A:256:8,16:0,32 +-gpgpu_cache:dl1PrefL1 S:48:128:4,L:L:s:N:H,A:256:8,16:0,32 +-gpgpu_cache:dl1PrefShared S:48:128:4,L:L:s:N:H,A:256:8,16:0,32 -gpgpu_shmem_size 49152 -gpgpu_shmem_size_PrefL1 49152 -gpgpu_shmem_size_PrefShared 49152 -gmem_skip_L1D 1 -icnt_flit_size 40 -gpgpu_n_cluster_ejection_buffer_size 32 +-l1_latency 82 +-smem_latency 24 # 64 sets, each 128 bytes 16-way for each memory sub partition (128 KB per memory sub partition). This gives 3MB L2 cache --gpgpu_cache:dl2 S:64:128:16,L:B:m:L:L,A:128:4,16:0,32 +-gpgpu_cache:dl2 S:64:128:16,L:B:m:L:L,A:256:64,16:0,32 -gpgpu_cache:dl2_texture_only 0 -gpgpu_dram_partition_queues 32:32:32:32 -perf_sim_memcpy 0 @@ -81,8 +86,7 @@ # 4 KB Inst. -gpgpu_cache:il1 N:8:128:4,L:R:f:N:L,S:2:48,4 # 48 KB Tex -# this is unused --gpgpu_tex_cache:l1 N:16:128:24,L:R:m:N:L,F:128:4,128:2 +-gpgpu_tex_cache:l1 N:16:128:24,L:R:m:N:L,T:128:4,128:2 # 12 KB Const -gpgpu_const_cache:l1 N:128:64:2,L:R:f:N:L,S:2:64,4 @@ -99,7 +103,6 @@ -gpgpu_operand_collector_num_out_ports_mem 1 -gpgpu_operand_collector_num_in_ports_dp 1 -gpgpu_operand_collector_num_out_ports_dp 1 -# gpgpu_num_reg_banks should be increased to 32 -gpgpu_num_reg_banks 32 # shared memory bankconflict detection @@ -118,7 +121,7 @@ -inter_config_file config_fermi_islip.icnt # memory partition latency config --rop_latency 100 +-rop_latency 120 -dram_latency 100 # dram model config @@ -128,7 +131,7 @@ # To allow 100% DRAM utility, there should at least be enough buffer to sustain # the minimum DRAM latency (100 core cycles). I.e. # Total buffer space required = 100 x 924MHz / 700MHz = 132 --gpgpu_frfcfs_dram_sched_queue_size 16 +-gpgpu_frfcfs_dram_sched_queue_size 64 -gpgpu_dram_return_queue_size 240 # for NVIDIA TITAN X, bus width is 384bits (12 DRAM chips x 32 bits) diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index 1b764e2..a70b077 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -392,6 +392,7 @@ protected: #define LOCAL_MEM_SIZE_MAX (8*1024) #define MAX_STREAMING_MULTIPROCESSORS 64 #define MAX_THREAD_PER_SM 2048 +#define MAX_WARP_PER_SM 64 #define TOTAL_LOCAL_MEM_PER_SM (MAX_THREAD_PER_SM*LOCAL_MEM_SIZE_MAX) #define TOTAL_SHARED_MEM (MAX_STREAMING_MULTIPROCESSORS*SHARED_MEM_SIZE_MAX) #define TOTAL_LOCAL_MEM (MAX_STREAMING_MULTIPROCESSORS*MAX_THREAD_PER_SM*LOCAL_MEM_SIZE_MAX) diff --git a/src/gpgpu-sim/gpu-cache.cc b/src/gpgpu-sim/gpu-cache.cc index f181f20..a11853a 100644 --- a/src/gpgpu-sim/gpu-cache.cc +++ b/src/gpgpu-sim/gpu-cache.cc @@ -71,6 +71,7 @@ unsigned l1d_cache_config::set_index(new_addr_type addr) const{ switch(m_set_index_function){ case FERMI_HASH_SET_FUNCTION: + case BITWISE_XORING_FUNCTION: /* * Set Indexing function from "A Detailed GPU Cache Model Based on Reuse Distance Theory" * Cedric Nugteren et al. @@ -1581,7 +1582,7 @@ enum cache_request_status tex_cache::access( new_addr_type addr, mem_fetch *mf, if ( status == MISS ) { // we need to send a memory request... unsigned rob_index = m_rob.push( rob_entry(cache_index, mf, block_addr) ); - m_extra_mf_fields[mf] = extra_mf_fields(rob_index); + m_extra_mf_fields[mf] = extra_mf_fields(rob_index, m_config); mf->set_data_size(m_config.get_line_sz()); m_tags.fill(cache_index,time,mf); // mark block as valid m_request_fifo.push(mf); @@ -1636,6 +1637,23 @@ void tex_cache::cycle(){ /// Place returning cache block into reorder buffer void tex_cache::fill( mem_fetch *mf, unsigned time ) { + if(m_config.m_mshr_type == SECTOR_TEX_FIFO) { + assert(mf->get_original_mf()); + extra_mf_fields_lookup::iterator e = m_extra_mf_fields.find(mf->get_original_mf()); + assert( e != m_extra_mf_fields.end() ); + e->second.pending_read--; + + if(e->second.pending_read > 0) { + //wait for the other requests to come back + delete mf; + return; + } else { + mem_fetch *temp = mf; + mf = mf->get_original_mf(); + delete temp; + } + } + extra_mf_fields_lookup::iterator e = m_extra_mf_fields.find(mf); assert( e != m_extra_mf_fields.end() ); assert( e->second.m_valid ); diff --git a/src/gpgpu-sim/gpu-cache.h b/src/gpgpu-sim/gpu-cache.h index dee43f2..4ed382c 100644 --- a/src/gpgpu-sim/gpu-cache.h +++ b/src/gpgpu-sim/gpu-cache.h @@ -455,7 +455,8 @@ enum write_policy_t { enum allocation_policy_t { ON_MISS, - ON_FILL + ON_FILL, + STREAMING }; @@ -467,8 +468,9 @@ enum write_allocate_policy_t { }; enum mshr_config_t { - TEX_FIFO, + TEX_FIFO, // Tex cache ASSOC, // normal cache + SECTOR_TEX_FIFO, //Tex cache sends requests to high-level sector cache SECTOR_ASSOC // normal cache sends requests to high-level sector cache }; @@ -485,6 +487,12 @@ enum cache_type{ SECTOR }; +#define MAX_WARP_PER_SHADER 64 +#define INCT_TOTAL_BUFFER 64 +#define L2_TOTAL 64 +#define MAX_WARP_PER_SHADER 64 +#define MAX_WARP_PER_SHADER 64 + class cache_config { public: cache_config() @@ -544,10 +552,27 @@ public: switch (ap) { case 'm': m_alloc_policy = ON_MISS; break; case 'f': m_alloc_policy = ON_FILL; break; + case 's': m_alloc_policy = STREAMING; break; default: exit_parse_error(); } + if(m_alloc_policy == STREAMING) { + //For streaming cache, we set the alloc policy to be on-fill to remove all line_alloc_fail stalls + //we set the MSHRs to be equal to the cache line. This is possible by moving TAG to be shared between cache line and MSHR enrty (i.e. for each cache line, there is an MSHR rntey associated with it) + // This is the easiest think we can think about to model (mimics) L1 streaming cache in Pascal and Volta + //Based on our microbenchmakrs, MSHRs entries have been increasing substantially in Pascal and Volta + //For more information about streaming cache, see: + // http://on-demand.gputechconf.com/gtc/2017/presentation/s7798-luke-durant-inside-volta.pdf + // https://ieeexplore.ieee.org/document/8344474/ + + m_alloc_policy = ON_FILL; + m_mshr_entries = m_nset*m_assoc; + if(m_cache_type == SECTOR) + m_mshr_entries *= SECTOR_CHUNCK_SIZE; + m_mshr_max_merge = MAX_WARP_PER_SM; + } switch (mshr_type) { case 'F': m_mshr_type = TEX_FIFO; assert(ntok==14); break; + case 'T': m_mshr_type = SECTOR_TEX_FIFO; assert(ntok==14); break; case 'A': m_mshr_type = ASSOC; break; case 'S' : m_mshr_type = SECTOR_ASSOC; break; default: exit_parse_error(); @@ -722,6 +747,7 @@ class l1d_cache_config : public cache_config{ public: l1d_cache_config() : cache_config(){} virtual unsigned set_index(new_addr_type addr) const; + unsigned l1_latency; }; class l2_cache_config : public cache_config { @@ -1442,7 +1468,7 @@ public: m_result_fifo(config.m_result_fifo_entries) { m_name = name; - assert(config.m_mshr_type == TEX_FIFO); + assert(config.m_mshr_type == TEX_FIFO || config.m_mshr_type == SECTOR_TEX_FIFO ); assert(config.m_write_policy == READ_ONLY); assert(config.m_alloc_policy == ON_MISS); m_memport=memport; @@ -1595,13 +1621,15 @@ private: struct extra_mf_fields { extra_mf_fields() { m_valid = false;} - extra_mf_fields( unsigned i ) + extra_mf_fields( unsigned i, const cache_config &m_config ) { m_valid = true; m_rob_index = i; + pending_read = m_config.m_mshr_type == SECTOR_TEX_FIFO? m_config.m_line_sz/SECTOR_SIZE : 0; } bool m_valid; unsigned m_rob_index; + unsigned pending_read; }; cache_stats m_stats; diff --git a/src/gpgpu-sim/gpu-sim.cc b/src/gpgpu-sim/gpu-sim.cc index ea2dfba..08d4525 100644 --- a/src/gpgpu-sim/gpu-sim.cc +++ b/src/gpgpu-sim/gpu-sim.cc @@ -250,6 +250,12 @@ void shader_core_config::reg_options(class OptionParser * opp) "per-shader L1 data cache config " " {::,:::,::, | none}", "none" ); + option_parser_register(opp, "-l1_latency", OPT_UINT32, &m_L1D_config.l1_latency, + "L1 Hit Latency", + "0"); + option_parser_register(opp, "-smem_latency", OPT_UINT32, &smem_latency, + "smem Latency", + "3"); option_parser_register(opp, "-gpgpu_cache:dl1PrefL1", OPT_CSTR, &m_L1D_config.m_config_stringPrefL1, "per-shader L1 data cache config " " {::,:::,::, | none}", diff --git a/src/gpgpu-sim/l2cache.cc b/src/gpgpu-sim/l2cache.cc index f42610f..25da107 100644 --- a/src/gpgpu-sim/l2cache.cc +++ b/src/gpgpu-sim/l2cache.cc @@ -609,7 +609,7 @@ std::vector memory_sub_partition::breakdown_request_to_sector_reques } else { printf("Invalid sector received, address = 0x%06x, sector mask = %s, data size = %d", - mf->get_addr(), mf->get_access_sector_mask(), mf->get_data_size(), mf->get_data_size()); + mf->get_addr(), mf->get_access_sector_mask(), mf->get_data_size()); assert(0 && "Undefined sector mask is received"); } @@ -640,7 +640,11 @@ std::vector memory_sub_partition::breakdown_request_to_sector_reques result.push_back(n_mf); byte_sector_mask <<= SECTOR_SIZE; } - } else assert(0 && "Undefined data size is received"); + } else { + printf("Invalid sector received, address = 0x%06x, sector mask = %d, byte mask = , data size = %d", + mf->get_addr(), mf->get_access_sector_mask().count(), mf->get_data_size()); + assert(0 && "Undefined data size is received"); + } return result; } diff --git a/src/gpgpu-sim/shader.cc b/src/gpgpu-sim/shader.cc index b59e5d2..51689e3 100644 --- a/src/gpgpu-sim/shader.cc +++ b/src/gpgpu-sim/shader.cc @@ -1488,6 +1488,111 @@ mem_stage_stall_type ldst_unit::process_memory_access_queue( cache_t *cache, war return process_cache_access( cache, mf->get_addr(), inst, events, mf, status ); } +mem_stage_stall_type ldst_unit::process_memory_access_queue_l1cache( l1_cache *cache, warp_inst_t &inst ) +{ + mem_stage_stall_type result = NO_RC_FAIL; + if( inst.accessq_empty() ) + return result; + + mem_fetch *mf = m_mf_allocator->alloc(inst,inst.accessq_back()); + + if(m_config->m_L1D_config.l1_latency > 0) + { + if((l1_latency_queue[m_config->m_L1D_config.l1_latency-1]) == NULL) + { + l1_latency_queue[m_config->m_L1D_config.l1_latency-1] = mf; + + if( mf->get_inst().is_store() ) { + unsigned inc_ack = (m_config->m_L1D_config.get_mshr_type() == SECTOR_ASSOC)? + (mf->get_data_size()/SECTOR_SIZE) : 1; + + for(unsigned i=0; i< inc_ack; ++i) + m_core->inc_store_req( inst.warp_id() ); + } + + inst.accessq_pop_back(); + } + else + { + result = BK_CONF; + delete mf; + } + if( !inst.accessq_empty() && result !=BK_CONF) + result = COAL_STALL; + return result; + } + else + { + std::list events; + enum cache_request_status status = cache->access(mf->get_addr(),mf,gpu_sim_cycle+gpu_tot_sim_cycle,events); + return process_cache_access( cache, mf->get_addr(), inst, events, mf, status ); + } +} + +void ldst_unit::L1_latency_queue_cycle() +{ + //std::deque< std::pair >::iterator it = m_latency_queue.begin(); + if((l1_latency_queue[0]) != NULL) + { + mem_fetch* mf_next = l1_latency_queue[0]; + std::list events; + enum cache_request_status status = m_L1D->access(mf_next->get_addr(),mf_next,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 ) { + assert( !read_sent ); + l1_latency_queue[0] = NULL; + if ( mf_next->get_inst().is_load() ) { + for ( unsigned r=0; r < 4; r++) + if (mf_next->get_inst().out[r] > 0) + { + assert(m_pending_writes[mf_next->get_inst().warp_id()][mf_next->get_inst().out[r]]>0); + unsigned still_pending = --m_pending_writes[mf_next->get_inst().warp_id()][mf_next->get_inst().out[r]]; + if(!still_pending) + { + m_pending_writes[mf_next->get_inst().warp_id()].erase(mf_next->get_inst().out[r]); + m_scoreboard->releaseRegister(mf_next->get_inst().warp_id(),mf_next->get_inst().out[r]); + m_core->warp_inst_complete(mf_next->get_inst()); + } + } + } + + //For write hit in WB policy + if(mf_next->get_inst().is_store() && !write_sent) + { + unsigned dec_ack = (m_config->m_L1D_config.get_mshr_type() == SECTOR_ASSOC)? + (mf_next->get_data_size()/SECTOR_SIZE) : 1; + + mf_next->set_reply(); + + for(unsigned i=0; i< dec_ack; ++i) + m_core->store_ack(mf_next); + } + + if( !write_sent ) + delete mf_next; + + } else if ( status == RESERVATION_FAIL ) { + assert( !read_sent ); + assert( !write_sent ); + } else { + assert( status == MISS || status == HIT_RESERVED ); + l1_latency_queue[0] = NULL; + } + } + + for( unsigned stage = 0; stagem_L1D_config.l1_latency-1; ++stage) + if( l1_latency_queue[stage] == NULL) { + l1_latency_queue[stage] = l1_latency_queue[stage+1] ; + l1_latency_queue[stage+1] = NULL; + } + +} + + + bool ldst_unit::constant_cycle( warp_inst_t &inst, mem_stage_stall_type &rc_fail, mem_stage_access_type &fail_type) { if( inst.empty() || ((inst.space.get_type() != const_space) && (inst.space.get_type() != param_space_kernel)) ) @@ -1561,7 +1666,7 @@ bool ldst_unit::memory_cycle( warp_inst_t &inst, mem_stage_stall_type &stall_rea } } else { assert( CACHE_UNDEFINED != inst.cache_op ); - stall_cond = process_memory_access_queue(m_L1D,inst); + stall_cond = process_memory_access_queue_l1cache(m_L1D,inst); } if( !inst.accessq_empty() && stall_cond == NO_RC_FAIL) stall_cond = COAL_STALL; @@ -1771,8 +1876,9 @@ ldst_unit::ldst_unit( mem_fetch_interface *icnt, const memory_config *mem_config, shader_core_stats *stats, unsigned sid, - unsigned tpc ) : pipelined_simd_unit(NULL,config,3,core), m_next_wb(config) + unsigned tpc ) : pipelined_simd_unit(NULL,config,config->smem_latency,core), m_next_wb(config) { + assert(config->smem_latency > 1); init( icnt, mf_allocator, core, @@ -1793,6 +1899,12 @@ ldst_unit::ldst_unit( mem_fetch_interface *icnt, m_icnt, m_mf_allocator, IN_L1D_MISS_QUEUE ); + + if(m_config->m_L1D_config.l1_latency > 0) + { + for(int i=0; im_L1D_config.l1_latency; i++ ) + l1_latency_queue.push_back((mem_fetch*)NULL); + } } } @@ -2019,7 +2131,11 @@ void ldst_unit::cycle() m_L1T->cycle(); m_L1C->cycle(); - if( m_L1D ) m_L1D->cycle(); + if( m_L1D ) { + m_L1D->cycle(); + if(m_config->m_L1D_config.l1_latency > 0) + L1_latency_queue_cycle(); + } warp_inst_t &pipe_reg = *m_dispatch_reg; enum mem_stage_stall_type rc_fail = NO_RC_FAIL; @@ -2042,9 +2158,9 @@ void ldst_unit::cycle() unsigned warp_id = pipe_reg.warp_id(); if( pipe_reg.is_load() ) { if( pipe_reg.space.get_type() == shared_space ) { - if( m_pipeline_reg[2]->empty() ) { + if( m_pipeline_reg[m_config->smem_latency-1]->empty() ) { // new shared memory request - move_warp(m_pipeline_reg[2],m_dispatch_reg); + move_warp(m_pipeline_reg[m_config->smem_latency-1],m_dispatch_reg); m_dispatch_reg->clear(); } } else { diff --git a/src/gpgpu-sim/shader.h b/src/gpgpu-sim/shader.h index cc441b3..e07096e 100644 --- a/src/gpgpu-sim/shader.h +++ b/src/gpgpu-sim/shader.h @@ -1220,6 +1220,7 @@ protected: mem_fetch *mf, enum cache_request_status status ); mem_stage_stall_type process_memory_access_queue( cache_t *cache, warp_inst_t &inst ); + mem_stage_stall_type process_memory_access_queue_l1cache( l1_cache *cache, warp_inst_t &inst ); const memory_config *m_memory_config; class mem_fetch_interface *m_icnt; @@ -1248,6 +1249,9 @@ protected: // for debugging unsigned long long m_last_inst_gpu_sim_cycle; unsigned long long m_last_inst_gpu_tot_sim_cycle; + + std::deque l1_latency_queue; + void L1_latency_queue_cycle(); }; enum pipeline_stage_name_t { @@ -1399,6 +1403,8 @@ struct shader_core_config : public core_config int simt_core_sim_order; + unsigned smem_latency; + unsigned mem2device(unsigned memid) const { return memid + n_simt_clusters; } //Jin: concurrent kernel on sm -- cgit v1.3 From 2522f06a47ab854ade2bdada3eaff63c0df36bf4 Mon Sep 17 00:00:00 2001 From: tgrogers Date: Mon, 8 Oct 2018 14:56:25 -0400 Subject: fixing an error about address length in the cache --- src/gpgpu-sim/gpu-cache.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/gpgpu-sim/gpu-cache.h') diff --git a/src/gpgpu-sim/gpu-cache.h b/src/gpgpu-sim/gpu-cache.h index 4ed382c..0b77f47 100644 --- a/src/gpgpu-sim/gpu-cache.h +++ b/src/gpgpu-sim/gpu-cache.h @@ -222,7 +222,7 @@ struct line_cache_block: public cache_block_t { return m_readable; } virtual void print_status() { - printf("m_block_addr is %u, status = %u\n", m_block_addr, m_status); + printf("m_block_addr is %llu, status = %u\n", m_block_addr, m_status); } -- cgit v1.3 From a43799f779a2cf23728659733649506a2d5420df Mon Sep 17 00:00:00 2001 From: tgrogers Date: Tue, 9 Oct 2018 09:55:54 -0400 Subject: Adding in an occupancy metric to match the nvprof metric --- src/gpgpu-sim/gpu-cache.h | 2 +- src/gpgpu-sim/gpu-sim.cc | 20 ++++++++++++++++---- src/gpgpu-sim/gpu-sim.h | 30 ++++++++++++++++++++++++++++++ src/gpgpu-sim/shader.cc | 27 ++++++++++++++++++++++++++- src/gpgpu-sim/shader.h | 3 +++ 5 files changed, 76 insertions(+), 6 deletions(-) (limited to 'src/gpgpu-sim/gpu-cache.h') diff --git a/src/gpgpu-sim/gpu-cache.h b/src/gpgpu-sim/gpu-cache.h index 0b77f47..70d3790 100644 --- a/src/gpgpu-sim/gpu-cache.h +++ b/src/gpgpu-sim/gpu-cache.h @@ -414,7 +414,7 @@ struct sector_cache_block : public cache_block_t { } virtual void print_status() { - printf("m_block_addr is %u, status = %u %u %u %u\n", m_block_addr, m_status[0], m_status[1], m_status[2], m_status[3]); + printf("m_block_addr is %llu, status = %u %u %u %u\n", m_block_addr, m_status[0], m_status[1], m_status[2], m_status[3]); } diff --git a/src/gpgpu-sim/gpu-sim.cc b/src/gpgpu-sim/gpu-sim.cc index 08d4525..9e0801c 100644 --- a/src/gpgpu-sim/gpu-sim.cc +++ b/src/gpgpu-sim/gpu-sim.cc @@ -845,6 +845,7 @@ void gpgpu_sim::update_stats() { partiton_replys_in_parallel_total += partiton_replys_in_parallel; partiton_reqs_in_parallel_util_total += partiton_reqs_in_parallel_util; gpu_tot_sim_cycle_parition_util += gpu_sim_cycle_parition_util ; + gpu_tot_occupancy += gpu_occupancy; gpu_sim_cycle = 0; partiton_reqs_in_parallel = 0; @@ -853,6 +854,7 @@ void gpgpu_sim::update_stats() { gpu_sim_cycle_parition_util = 0; gpu_sim_insn = 0; m_total_cta_launched = 0; + gpu_occupancy = occupancy_stats(); } void gpgpu_sim::print_stats() @@ -1026,6 +1028,9 @@ void gpgpu_sim::gpu_print_stat() printf("gpu_tot_sim_insn = %lld\n", gpu_tot_sim_insn+gpu_sim_insn); printf("gpu_tot_ipc = %12.4f\n", (float)(gpu_tot_sim_insn+gpu_sim_insn) / (gpu_tot_sim_cycle+gpu_sim_cycle)); printf("gpu_tot_issued_cta = %lld\n", gpu_tot_issued_cta + m_total_cta_launched); + printf("gpu_occupancy = %.4f\% \n", gpu_occupancy.get_occ_fraction() * 100); + printf("gpu_tot_occupancy = %.4f\% \n", (gpu_occupancy + gpu_tot_occupancy).get_occ_fraction() * 100); + extern unsigned long long g_max_total_param_size; fprintf(statfout, "max_total_param_size = %llu\n", g_max_total_param_size); @@ -1529,6 +1534,8 @@ void gpgpu_sim::cycle() // Update core icnt/cache stats for GPUWattch m_cluster[i]->get_icnt_stats(m_power_stats->pwr_mem_stat->n_simt_to_mem[CURRENT_STAT_IDX][i], m_power_stats->pwr_mem_stat->n_mem_to_simt[CURRENT_STAT_IDX][i]); m_cluster[i]->get_cache_stats(m_power_stats->pwr_mem_stat->core_cache_stats[CURRENT_STAT_IDX]); + m_cluster[i]->get_current_occupancy(gpu_occupancy.aggregate_warp_slot_filled, gpu_occupancy.aggregate_theoretical_warp_slots); + } float temp=0; for (unsigned i=0;inum_shader();i++){ @@ -1594,15 +1601,20 @@ void gpgpu_sim::cycle() time_t curr_time; time(&curr_time); unsigned long long elapsed_time = MAX(curr_time - g_simulation_starttime, 1); - if ( (elapsed_time - last_liveness_message_time) >= m_config.liveness_message_freq ) { + if ( (elapsed_time - last_liveness_message_time) >= m_config.liveness_message_freq && DTRACE(LIVENESS) ) { days = elapsed_time/(3600*24); hrs = elapsed_time/3600 - 24*days; minutes = elapsed_time/60 - 60*(hrs + 24*days); sec = elapsed_time - 60*(minutes + 60*(hrs + 24*days)); - - DPRINTF(LIVENESS, "GPGPU-Sim uArch: cycles simulated: %lld inst.: %lld (ipc=%4.1f) sim_rate=%u (inst/sec) elapsed = %u:%u:%02u:%02u / %s", - gpu_tot_sim_cycle + gpu_sim_cycle, gpu_tot_sim_insn + gpu_sim_insn, + + unsigned long long active = 0, total = 0; + for (unsigned i=0;in_simt_clusters;i++) { + m_cluster[i]->get_current_occupancy(active, total); + } + DPRINTF(LIVENESS, "uArch: inst.: %lld (ipc=%4.1f, occ=%0.4f\% [%llu / %llu]) sim_rate=%u (inst/sec) elapsed = %u:%u:%02u:%02u / %s", + gpu_tot_sim_insn + gpu_sim_insn, (double)gpu_sim_insn/(double)gpu_sim_cycle, + float(active)/float(total) * 100, active, total, (unsigned)((gpu_tot_sim_insn+gpu_sim_insn) / elapsed_time), (unsigned)days,(unsigned)hrs,(unsigned)minutes,(unsigned)sec, ctime(&curr_time)); diff --git a/src/gpgpu-sim/gpu-sim.h b/src/gpgpu-sim/gpu-sim.h index 1778008..1bae1fa 100644 --- a/src/gpgpu-sim/gpu-sim.h +++ b/src/gpgpu-sim/gpu-sim.h @@ -383,6 +383,32 @@ private: friend class gpgpu_sim; }; +struct occupancy_stats { + occupancy_stats() : aggregate_warp_slot_filled(0), aggregate_theoretical_warp_slots(0){} + occupancy_stats( unsigned long long wsf, unsigned long long tws ) + : aggregate_warp_slot_filled(wsf), aggregate_theoretical_warp_slots(tws){} + + unsigned long long aggregate_warp_slot_filled; + unsigned long long aggregate_theoretical_warp_slots; + + float get_occ_fraction() const { + return float(aggregate_warp_slot_filled) / float(aggregate_theoretical_warp_slots); + } + + occupancy_stats& operator+=(const occupancy_stats& rhs) { + aggregate_warp_slot_filled += rhs.aggregate_warp_slot_filled; + aggregate_theoretical_warp_slots += rhs.aggregate_theoretical_warp_slots; + return *this; + } + + occupancy_stats operator+(const occupancy_stats& rhs) const{ + return occupancy_stats( aggregate_warp_slot_filled + rhs.aggregate_warp_slot_filled, + aggregate_theoretical_warp_slots + rhs.aggregate_theoretical_warp_slots + ); + } +}; + + class gpgpu_sim : public gpgpu_t { public: gpgpu_sim( const gpgpu_sim_config &config ); @@ -521,6 +547,9 @@ public: unsigned long long gpu_tot_sim_insn; unsigned long long gpu_sim_insn_last_update; unsigned gpu_sim_insn_last_update_sid; + occupancy_stats gpu_occupancy; + occupancy_stats gpu_tot_occupancy; + FuncCache get_cache_config(std::string kernel_name); void set_cache_config(std::string kernel_name, FuncCache cacheConfig ); @@ -549,4 +578,5 @@ public: } }; + #endif diff --git a/src/gpgpu-sim/shader.cc b/src/gpgpu-sim/shader.cc index 0e2e1c2..bb8e4b6 100644 --- a/src/gpgpu-sim/shader.cc +++ b/src/gpgpu-sim/shader.cc @@ -74,7 +74,7 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, shader_core_stats *stats ) : core_t( gpu, NULL, config->warp_size, config->n_thread_per_shader ), m_barriers( this, config->max_warps_per_shader, config->max_cta_per_core, config->max_barriers_per_cta, config->warp_size ), - m_dynamic_warp_id(0) + m_dynamic_warp_id(0), m_active_warps(0) { m_cluster = cluster; m_config = config; @@ -357,6 +357,7 @@ void shader_core_ctx::reinit(unsigned start_thread, unsigned end_thread, bool re m_occupied_ctas = 0; m_occupied_hwtid.reset(); m_occupied_cta_to_hwtid.clear(); + m_active_warps = 0; } for (unsigned i = start_thread; iget_pdom_stack_top_info(pc,rpc); } +float shader_core_ctx::get_current_occupancy( unsigned long long & active, unsigned long long & total ) const +{ + // To match the achieved_occupancy in nvprof, only SMs that are active are counted toward the occupancy. + if ( m_active_warps > 0 ) { + total += m_warp.size(); + active += m_active_warps; + return float(active) / float(total); + } else { + return 0; + } +} + void shader_core_stats::print( FILE* fout ) const { unsigned long long thread_icount_uarch=0; @@ -692,6 +706,8 @@ void shader_core_ctx::fetch() } if( did_exit ) m_warp[warp_id].set_done_exit(); + --m_active_warps; + assert(m_active_warps >= 0); } // this code fetches instructions from the i-cache or generates memory requests @@ -3524,6 +3540,15 @@ void simt_core_cluster::print_not_completed( FILE *fp ) const } } + +float simt_core_cluster::get_current_occupancy( unsigned long long& active, unsigned long long& total ) const { + float aggregate = 0.f; + for( unsigned i=0; i < m_config->n_simt_cores_per_cluster; i++ ) { + aggregate+=m_core[i]->get_current_occupancy( active, total ); + } + return aggregate / m_config->n_simt_cores_per_cluster; +} + unsigned simt_core_cluster::get_n_active_cta() const { unsigned n=0; diff --git a/src/gpgpu-sim/shader.h b/src/gpgpu-sim/shader.h index e07096e..f7b13e2 100644 --- a/src/gpgpu-sim/shader.h +++ b/src/gpgpu-sim/shader.h @@ -1691,6 +1691,7 @@ public: // accessors virtual bool warp_waiting_at_barrier( unsigned warp_id ) const; void get_pdom_stack_top_info( unsigned tid, unsigned *pc, unsigned *rpc ) const; + float get_current_occupancy( unsigned long long & active, unsigned long long & total ) const; // used by pipeline timing model components: // modifiers @@ -1897,6 +1898,7 @@ public: std::vector m_pipeline_reg; Scoreboard *m_scoreboard; opndcoll_rfu_t m_operand_collector; + int m_active_warps; //schedule std::vector schedulers; @@ -1986,6 +1988,7 @@ public: void get_L1T_sub_stats(struct cache_sub_stats &css) const; void get_icnt_stats(long &n_simt_to_mem, long &n_mem_to_simt) const; + float get_current_occupancy( unsigned long long& active, unsigned long long & total ) const; private: unsigned m_cluster_id; -- cgit v1.3 From 0e46a261dfeba9c19d1637f46277986d7eb1b9d8 Mon Sep 17 00:00:00 2001 From: Mahmoud Date: Tue, 9 Oct 2018 17:12:57 -0400 Subject: adding adaptive volta cache config --- configs/4.x-cfgs/SM7_TITANV/gpgpusim.config | 19 ++++++++++-------- src/abstract_hardware_model.cc | 2 ++ src/abstract_hardware_model.h | 2 ++ src/gpgpu-sim/gpu-cache.cc | 9 ++++----- src/gpgpu-sim/gpu-cache.h | 31 +++++++++++++++++++++++++---- src/gpgpu-sim/gpu-sim.cc | 3 +++ src/gpgpu-sim/shader.cc | 29 +++++++++++++++++++++++++++ src/gpgpu-sim/shader.h | 2 ++ 8 files changed, 80 insertions(+), 17 deletions(-) (limited to 'src/gpgpu-sim/gpu-cache.h') diff --git a/configs/4.x-cfgs/SM7_TITANV/gpgpusim.config b/configs/4.x-cfgs/SM7_TITANV/gpgpusim.config index cc4c931..a7056db 100644 --- a/configs/4.x-cfgs/SM7_TITANV/gpgpusim.config +++ b/configs/4.x-cfgs/SM7_TITANV/gpgpusim.config @@ -65,19 +65,21 @@ # ::,::::,::,:** # ** Optional parameter - Required when mshr_type==Texture Fifo -# Defualt config is 64KB DL1 and 64KB shared memory --gpgpu_cache:dl1 S:4:128:128,L:L:s:N:L,A:256:8,16:0,32 --gpgpu_cache:dl1PrefL1 S:4:128:192,L:L:s:N:L,A:256:8,16:0,32 --gpgpu_cache:dl1PrefShared S:4:128:64,L:L:s:N:L,A:256:8,16:0,32 --gpgpu_shmem_size 65536 --gpgpu_shmem_size_PrefL1 32768 --gpgpu_shmem_size_PrefShared 98304 +# Defualt config is 32KB DL1 and 96KB shared memory +# In Volta, we assign the remaining shared memory to L1 cache +# if the assigned shd mem = 0, then L1 cache = 128KB +# For more info, see https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#shared-memory-7-x +# disable this mode in case of multi kernels/apps execution +-adpative_volta_cache_config 1 +-gpgpu_cache:dl1 S:4:128:64,L:L:s:N:L,A:256:8,16:0,32 +-gpgpu_shmem_size 98304 -gmem_skip_L1D 0 -icnt_flit_size 40 -gpgpu_n_cluster_ejection_buffer_size 32 -l1_latency 28 -smem_latency 19 -gpgpu_flush_l1_cache 1 +-adpative_volta_cache_config 1 # 64 sets, each 128 bytes 24-way for each memory sub partition (192 KB per memory sub partition). This gives 4.5MB L2 cache -gpgpu_cache:dl2 S:64:128:24,L:B:m:L:L,A:384:4,32:0,32 @@ -87,7 +89,8 @@ # 128 KB Inst. -gpgpu_cache:il1 N:64:128:16,L:R:f:N:L,S:2:48,4 -# 48 KB Tex +# 48 KB Tex +# Note, TEX is deprected in Volta, It is used for legacy apps only. Use L1D cache instead with .nc modifier or __ldg mehtod -gpgpu_tex_cache:l1 N:16:128:24,L:R:m:N:L,T:128:4,128:2 # 64 KB Const -gpgpu_const_cache:l1 N:128:64:8,L:R:f:N:L,S:2:64,4 diff --git a/src/abstract_hardware_model.cc b/src/abstract_hardware_model.cc index d2a155c..39ed81c 100644 --- a/src/abstract_hardware_model.cc +++ b/src/abstract_hardware_model.cc @@ -591,6 +591,8 @@ kernel_info_t::kernel_info_t( dim3 gridDim, dim3 blockDim, class function_info * //Jin: launch latency management m_launch_latency = g_kernel_launch_latency; + + volta_cache_config_set=false; } kernel_info_t::~kernel_info_t() diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index e708fa7..6fa2ba0 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -301,6 +301,8 @@ public: unsigned long long start_cycle; unsigned long long end_cycle; unsigned m_launch_latency; + + mutable bool volta_cache_config_set; }; struct core_config { diff --git a/src/gpgpu-sim/gpu-cache.cc b/src/gpgpu-sim/gpu-cache.cc index a11853a..8ae4702 100644 --- a/src/gpgpu-sim/gpu-cache.cc +++ b/src/gpgpu-sim/gpu-cache.cc @@ -29,7 +29,6 @@ #include "stat-tool.h" #include -#define MAX_DEFAULT_CACHE_SIZE_MULTIBLIER 4 // used to allocate memory that is large enough to adapt the changes in cache size across kernels const char * cache_request_status_str(enum cache_request_status status) @@ -165,7 +164,7 @@ unsigned l2_cache_config::set_index(new_addr_type addr) const{ tag_array::~tag_array() { - unsigned cache_lines_num = MAX_DEFAULT_CACHE_SIZE_MULTIBLIER*m_config.get_num_lines(); + unsigned cache_lines_num = m_config.get_max_num_lines(); for(unsigned i=0; iis_modified_line()) { for(unsigned j=0; j < SECTOR_CHUNCK_SIZE; j++) m_lines[i]->set_status(INVALID, mem_access_sector_mask_t().set(j)) ; @@ -396,7 +395,7 @@ void tag_array::flush() void tag_array::invalidate() { - for (unsigned i=0; i < m_config.get_num_lines(); i++) + for (unsigned i=0; i < m_config.get_max_num_lines(); i++) for(unsigned j=0; j < SECTOR_CHUNCK_SIZE; j++) m_lines[i]->set_status(INVALID, mem_access_sector_mask_t().set(j)) ; } diff --git a/src/gpgpu-sim/gpu-cache.h b/src/gpgpu-sim/gpu-cache.h index 4ed382c..9174d7f 100644 --- a/src/gpgpu-sim/gpu-cache.h +++ b/src/gpgpu-sim/gpu-cache.h @@ -38,6 +38,8 @@ #include "addrdec.h" #include +#define MAX_DEFAULT_CACHE_SIZE_MULTIBLIER 4 + enum cache_block_state { INVALID=0, RESERVED, @@ -557,15 +559,15 @@ public: } if(m_alloc_policy == STREAMING) { //For streaming cache, we set the alloc policy to be on-fill to remove all line_alloc_fail stalls - //we set the MSHRs to be equal to the cache line. This is possible by moving TAG to be shared between cache line and MSHR enrty (i.e. for each cache line, there is an MSHR rntey associated with it) - // This is the easiest think we can think about to model (mimics) L1 streaming cache in Pascal and Volta + //we set the MSHRs to be equal to max allocated cache lines. This is possible by moving TAG to be shared between cache line and MSHR enrty (i.e. for each cache line, there is an MSHR rntey associated with it) + //This is the easiest think we can think about to model (mimic) L1 streaming cache in Pascal and Volta //Based on our microbenchmakrs, MSHRs entries have been increasing substantially in Pascal and Volta //For more information about streaming cache, see: // http://on-demand.gputechconf.com/gtc/2017/presentation/s7798-luke-durant-inside-volta.pdf // https://ieeexplore.ieee.org/document/8344474/ m_alloc_policy = ON_FILL; - m_mshr_entries = m_nset*m_assoc; + m_mshr_entries = m_nset*m_assoc*MAX_DEFAULT_CACHE_SIZE_MULTIBLIER; if(m_cache_type == SECTOR) m_mshr_entries *= SECTOR_CHUNCK_SIZE; m_mshr_max_merge = MAX_WARP_PER_SM; @@ -581,6 +583,7 @@ public: m_nset_log2 = LOGB2(m_nset); m_valid = true; m_atom_sz = (m_cache_type == SECTOR)? SECTOR_SIZE : m_line_sz; + original_m_assoc = m_assoc; //For more details about difference between FETCH_ON_WRITE and WRITE VALIDAE policies //Read: Jouppi, Norman P. "Cache write policies and performance". ISCA 93. @@ -646,7 +649,11 @@ public: assert( m_valid ); return m_nset * m_assoc; } - + unsigned get_max_num_lines() const + { + assert( m_valid ); + return MAX_DEFAULT_CACHE_SIZE_MULTIBLIER * m_nset * original_m_assoc; + } void print( FILE *fp ) const { fprintf( fp, "Size = %d B (%d Set x %d-way x %d byte line)\n", @@ -687,6 +694,21 @@ public: { return m_mshr_type; } + void set_assoc(unsigned n) + { + //set new assoc. L1 cache dynamically resized in Volta + m_assoc = n; + } + unsigned get_nset() const + { + assert( m_valid ); + return m_nset; + } + unsigned get_total_size_inKB() const + { + assert( m_valid ); + return (m_assoc*m_nset*m_line_sz)/1024; + } FuncCache get_cache_status() {return cache_status;} char *m_config_string; char *m_config_stringPrefL1; @@ -708,6 +730,7 @@ protected: unsigned m_nset_log2; unsigned m_assoc; unsigned m_atom_sz; + unsigned original_m_assoc; enum replacement_policy_t m_replacement_policy; // 'L' = LRU, 'F' = FIFO enum write_policy_t m_write_policy; // 'T' = write through, 'B' = write back, 'R' = read only diff --git a/src/gpgpu-sim/gpu-sim.cc b/src/gpgpu-sim/gpu-sim.cc index 08d4525..080cbac 100644 --- a/src/gpgpu-sim/gpu-sim.cc +++ b/src/gpgpu-sim/gpu-sim.cc @@ -307,6 +307,9 @@ void shader_core_config::reg_options(class OptionParser * opp) option_parser_register(opp, "-gpgpu_shmem_size", OPT_UINT32, &gpgpu_shmem_size, "Size of shared memory per shader core (default 16kB)", "16384"); + option_parser_register(opp, "-adpative_volta_cache_config", OPT_BOOL, &adpative_volta_cache_config, + "adpative_volta_cache_config", + "0"); option_parser_register(opp, "-gpgpu_shmem_size", OPT_UINT32, &gpgpu_shmem_sizeDefault, "Size of shared memory per shader core (default 16kB)", "16384"); diff --git a/src/gpgpu-sim/shader.cc b/src/gpgpu-sim/shader.cc index 0e2e1c2..2cc8a2e 100644 --- a/src/gpgpu-sim/shader.cc +++ b/src/gpgpu-sim/shader.cc @@ -2744,6 +2744,35 @@ unsigned int shader_core_config::max_cta( const kernel_info_t &k ) const abort(); } + if(adpative_volta_cache_config && !k.volta_cache_config_set) { + //For Volta, we assign the remaining shared memory to L1 cache + //For more info, see https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#shared-memory-7-x + unsigned total_shmed = kernel_info->smem * result; + assert(total_shmed >=0 && total_shmed <= gpgpu_shmem_size); + assert(gpgpu_shmem_size == 98304); //Volta has 96 KB shared + assert(m_L1D_config.get_nset() == 4); //Volta L1 has four sets + if(total_shmed < gpgpu_shmem_size){ + if(total_shmed == 0) + m_L1D_config.set_assoc(256); //L1 is 128KB ans shd=0 + else if(total_shmed > 0 && total_shmed <= 8192) + m_L1D_config.set_assoc(240); //L1 is 120KB ans shd=8KB + else if(total_shmed > 8192 && total_shmed <= 16384) + m_L1D_config.set_assoc(224); //L1 is 112KB ans shd=16KB + else if(total_shmed > 16384 && total_shmed <= 32768) + m_L1D_config.set_assoc(192); //L1 is 96KB ans shd=32KB + else if(total_shmed > 32768 && total_shmed <= 65536) + m_L1D_config.set_assoc(128); //L1 is 64KB ans shd=64KB + else if(total_shmed > 65536 && total_shmed <= gpgpu_shmem_size) + m_L1D_config.set_assoc(64); //L1 is 32KB and shd=96KB + else + assert(0); + + printf ("GPGPU-Sim: Reconfigure L1 cache in Volta Archi to %uKB\n", m_L1D_config.get_total_size_inKB()); + } + + k.volta_cache_config_set = true; + } + return result; } diff --git a/src/gpgpu-sim/shader.h b/src/gpgpu-sim/shader.h index e07096e..92b4159 100644 --- a/src/gpgpu-sim/shader.h +++ b/src/gpgpu-sim/shader.h @@ -1409,6 +1409,8 @@ struct shader_core_config : public core_config //Jin: concurrent kernel on sm bool gpgpu_concurrent_kernel_sm; + + bool adpative_volta_cache_config; }; struct shader_core_stats_pod { -- cgit v1.3 From d78eab6fdc4eb9ab9e0a86088a16872c2c6f9755 Mon Sep 17 00:00:00 2001 From: Mahmoud Date: Thu, 11 Oct 2018 12:55:10 -0400 Subject: improving the performance of cache flushing --- src/gpgpu-sim/gpu-cache.cc | 16 ++++++++++++++-- src/gpgpu-sim/gpu-cache.h | 2 ++ 2 files changed, 16 insertions(+), 2 deletions(-) (limited to 'src/gpgpu-sim/gpu-cache.h') diff --git a/src/gpgpu-sim/gpu-cache.cc b/src/gpgpu-sim/gpu-cache.cc index 8ae4702..fdcbdaf 100644 --- a/src/gpgpu-sim/gpu-cache.cc +++ b/src/gpgpu-sim/gpu-cache.cc @@ -222,6 +222,7 @@ void tag_array::init( int core_id, int type_id ) m_prev_snapshot_pending_hit = 0; m_core_id = core_id; m_type_id = type_id; + is_used = false; } @@ -316,6 +317,7 @@ enum cache_request_status tag_array::access( new_addr_type addr, unsigned time, enum cache_request_status tag_array::access( new_addr_type addr, unsigned time, unsigned &idx, bool &wb, evicted_block_info &evicted, mem_fetch* mf ) { m_access++; + is_used = true; shader_cache_access_log(m_core_id, m_type_id, 0); // log accesses to cache enum cache_request_status status = probe(addr,idx,mf); switch (status) { @@ -386,18 +388,28 @@ void tag_array::fill( unsigned index, unsigned time, mem_fetch* mf) //TODO: we need write back the flushed data to the upper level void tag_array::flush() { - for (unsigned i=0; i < m_config.get_max_num_lines(); i++) + if(!is_used) + return; + + for (unsigned i=0; i < m_config.get_num_lines(); i++) if(m_lines[i]->is_modified_line()) { for(unsigned j=0; j < SECTOR_CHUNCK_SIZE; j++) m_lines[i]->set_status(INVALID, mem_access_sector_mask_t().set(j)) ; } + + is_used = false; } void tag_array::invalidate() { - for (unsigned i=0; i < m_config.get_max_num_lines(); i++) + if(!is_used) + return; + + for (unsigned i=0; i < m_config.get_num_lines(); i++) for(unsigned j=0; j < SECTOR_CHUNCK_SIZE; j++) m_lines[i]->set_status(INVALID, mem_access_sector_mask_t().set(j)) ; + + is_used = false; } float tag_array::windowed_miss_rate( ) const diff --git a/src/gpgpu-sim/gpu-cache.h b/src/gpgpu-sim/gpu-cache.h index 9174d7f..cd98945 100644 --- a/src/gpgpu-sim/gpu-cache.h +++ b/src/gpgpu-sim/gpu-cache.h @@ -839,6 +839,8 @@ protected: int m_core_id; // which shader core is using this int m_type_id; // what kind of cache is this (normal, texture, constant) + + bool is_used; //a flag if the whole cache has ever been accessed before }; class mshr_table { -- cgit v1.3 From d7f9c5cc3d91b4290977c61ae9d3cf93ae591ebb Mon Sep 17 00:00:00 2001 From: Mahmoud Date: Thu, 11 Oct 2018 23:25:24 -0400 Subject: count misses of pending req as sector miss in streaming cache --- src/gpgpu-sim/gpu-cache.cc | 44 +++++++++++++++++++++++++++++++++++++++----- src/gpgpu-sim/gpu-cache.h | 18 +++++++++++++++--- 2 files changed, 54 insertions(+), 8 deletions(-) (limited to 'src/gpgpu-sim/gpu-cache.h') diff --git a/src/gpgpu-sim/gpu-cache.cc b/src/gpgpu-sim/gpu-cache.cc index fdcbdaf..35a5e3a 100644 --- a/src/gpgpu-sim/gpu-cache.cc +++ b/src/gpgpu-sim/gpu-cache.cc @@ -225,14 +225,31 @@ void tag_array::init( int core_id, int type_id ) is_used = false; } +void tag_array::add_pending_line(mem_fetch *mf){ + assert(mf); + new_addr_type addr = m_config.block_addr(mf->get_addr()); + line_table::const_iterator i = pending_lines.find(addr); + if ( i == pending_lines.end() ) { + pending_lines[addr] = mf->get_inst().get_uid(); + } +} + +void tag_array::remove_pending_line(mem_fetch *mf){ + assert(mf); + new_addr_type addr = m_config.block_addr(mf->get_addr()); + line_table::const_iterator i = pending_lines.find(addr); + if ( i != pending_lines.end() ) { + pending_lines.erase(addr); + } +} -enum cache_request_status tag_array::probe( new_addr_type addr, unsigned &idx, mem_fetch* mf) const { +enum cache_request_status tag_array::probe( new_addr_type addr, unsigned &idx, mem_fetch* mf, bool probe_mode) const { mem_access_sector_mask_t mask = mf->get_access_sector_mask(); - return probe(addr, idx, mask); + return probe(addr, idx, mask, probe_mode, mf); } -enum cache_request_status tag_array::probe( new_addr_type addr, unsigned &idx, mem_access_sector_mask_t mask) const { +enum cache_request_status tag_array::probe( new_addr_type addr, unsigned &idx, mem_access_sector_mask_t mask, bool probe_mode, mem_fetch* mf) const { //assert( m_config.m_write_policy == READ_ONLY ); unsigned set_index = m_config.set_index(addr); new_addr_type tag = m_config.tag(addr); @@ -302,6 +319,16 @@ enum cache_request_status tag_array::probe( new_addr_type addr, unsigned &idx, m idx = valid_line; } else abort(); // if an unreserved block exists, it is either invalid or replaceable + + if(probe_mode && m_config.is_streaming()){ + line_table::const_iterator i = pending_lines.find(m_config.block_addr(addr)); + assert(mf); + if ( !mf->is_write() && i != pending_lines.end() ) { + if(i->second != mf->get_inst().get_uid()) + return SECTOR_MISS; + } + } + return MISS; } @@ -951,8 +978,11 @@ void baseline_cache::fill(mem_fetch *mf, unsigned time){ mf->set_addr( e->second.m_addr ); if ( m_config.m_alloc_policy == ON_MISS ) m_tag_array->fill(e->second.m_cache_index,time,mf); - else if ( m_config.m_alloc_policy == ON_FILL ) + else if ( m_config.m_alloc_policy == ON_FILL ) { m_tag_array->fill(e->second.m_block_addr,time,mf); + if(m_config.is_streaming()) + m_tag_array->remove_pending_line(mf); + } else abort(); bool has_atomic = false; m_mshrs.mark_ready(e->second.m_block_addr, has_atomic); @@ -1006,6 +1036,7 @@ void baseline_cache::send_read_request(new_addr_type addr, new_addr_type block_a m_mshrs.add(mshr_addr,mf); do_miss = true; + } else if ( !mshr_hit && mshr_avail && (m_miss_queue.size() < m_config.m_miss_queue_size) ) { if(read_only) m_tag_array->access(block_addr,time,cache_index,mf); @@ -1013,6 +1044,9 @@ void baseline_cache::send_read_request(new_addr_type addr, new_addr_type block_a m_tag_array->access(block_addr,time,cache_index,wb,evicted,mf); m_mshrs.add(mshr_addr,mf); + if(m_config.is_streaming() && m_config.m_cache_type == SECTOR){ + m_tag_array->add_pending_line(mf); + } m_extra_mf_fields[mf] = extra_mf_fields(mshr_addr,mf->get_addr(),cache_index, mf->get_data_size(), m_config); mf->set_data_size( m_config.get_atom_sz() ); mf->set_addr( mshr_addr ); @@ -1536,7 +1570,7 @@ data_cache::access( new_addr_type addr, new_addr_type block_addr = m_config.block_addr(addr); unsigned cache_index = (unsigned)-1; enum cache_request_status probe_status - = m_tag_array->probe( block_addr, cache_index, mf ); + = m_tag_array->probe( block_addr, cache_index, mf, true); enum cache_request_status access_status = process_tag_probe( wr, probe_status, addr, cache_index, mf, time, events ); m_stats.inc_stats(mf->get_access_type(), diff --git a/src/gpgpu-sim/gpu-cache.h b/src/gpgpu-sim/gpu-cache.h index d1cba78..e663cf6 100644 --- a/src/gpgpu-sim/gpu-cache.h +++ b/src/gpgpu-sim/gpu-cache.h @@ -506,6 +506,7 @@ public: m_config_stringPrefShared = NULL; m_data_port_width = 0; m_set_index_function = LINEAR_SET_FUNCTION; + m_is_streaming = false; } void init(char * config, FuncCache status) { @@ -565,7 +566,7 @@ public: //For more information about streaming cache, see: // http://on-demand.gputechconf.com/gtc/2017/presentation/s7798-luke-durant-inside-volta.pdf // https://ieeexplore.ieee.org/document/8344474/ - + m_is_streaming = true; m_alloc_policy = ON_FILL; m_mshr_entries = m_nset*m_assoc*MAX_DEFAULT_CACHE_SIZE_MULTIBLIER; if(m_cache_type == SECTOR) @@ -709,6 +710,9 @@ public: assert( m_valid ); return (m_assoc*m_nset*m_line_sz)/1024; } + bool is_streaming() { + return m_is_streaming; + } FuncCache get_cache_status() {return cache_status;} char *m_config_string; char *m_config_stringPrefL1; @@ -731,6 +735,7 @@ protected: unsigned m_assoc; unsigned m_atom_sz; unsigned original_m_assoc; + bool m_is_streaming; enum replacement_policy_t m_replacement_policy; // 'L' = LRU, 'F' = FIFO enum write_policy_t m_write_policy; // 'T' = write through, 'B' = write back, 'R' = read only @@ -789,8 +794,8 @@ public: tag_array(cache_config &config, int core_id, int type_id ); ~tag_array(); - enum cache_request_status probe( new_addr_type addr, unsigned &idx, mem_fetch* mf ) const; - enum cache_request_status probe( new_addr_type addr, unsigned &idx, mem_access_sector_mask_t mask ) const; + enum cache_request_status probe( new_addr_type addr, unsigned &idx, mem_fetch* mf, bool probe_mode=false ) const; + enum cache_request_status probe( new_addr_type addr, unsigned &idx, mem_access_sector_mask_t mask, bool probe_mode=false, mem_fetch* mf = NULL ) const; enum cache_request_status access( new_addr_type addr, unsigned time, unsigned &idx, mem_fetch* mf ); enum cache_request_status access( new_addr_type addr, unsigned time, unsigned &idx, bool &wb, evicted_block_info &evicted, mem_fetch* mf ); @@ -810,6 +815,8 @@ public: void get_stats(unsigned &total_access, unsigned &total_misses, unsigned &total_hit_res, unsigned &total_res_fail) const; void update_cache_parameters(cache_config &config); + void add_pending_line(mem_fetch *mf); + void remove_pending_line(mem_fetch *mf); protected: // This constructor is intended for use only from derived classes that wish to // avoid unnecessary memory allocation that takes place in the @@ -841,6 +848,9 @@ protected: int m_type_id; // what kind of cache is this (normal, texture, constant) bool is_used; //a flag if the whole cache has ever been accessed before + + typedef tr1_hash_map line_table; + line_table pending_lines; }; class mshr_table { @@ -890,7 +900,9 @@ private: mshr_entry() : m_has_atomic(false) { } }; typedef tr1_hash_map table; + typedef tr1_hash_map line_table; table m_data; + line_table pending_lines; // it may take several cycles to process the merged requests bool m_current_response_ready; -- cgit v1.3