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/l2cache.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/gpgpu-sim/l2cache.h') diff --git a/src/gpgpu-sim/l2cache.h b/src/gpgpu-sim/l2cache.h index 2cc0e76..b613a94 100644 --- a/src/gpgpu-sim/l2cache.h +++ b/src/gpgpu-sim/l2cache.h @@ -72,6 +72,7 @@ public: void print_stat( FILE *fp ) { m_dram->print_stat(fp); } void visualize() const { m_dram->visualize(); } void print( FILE *fp ) const; + void handle_memcpy_to_gpu( size_t dst_start_addr, unsigned subpart_id, mem_access_sector_mask_t mask ); class memory_sub_partition * get_sub_partition(int sub_partition_id) { @@ -178,6 +179,11 @@ public: void accumulate_L2cache_stats(class cache_stats &l2_stats) const; void get_L2cache_sub_stats(struct cache_sub_stats &css) const; + void force_l2_tag_update(new_addr_type addr, unsigned time, mem_access_sector_mask_t mask) + { + m_L2cache->force_tag_access( addr, time, mask ); + } + private: // data unsigned m_id; //< the global sub partition ID -- cgit v1.3 From 21528f301886ffdba5e921091658446d23c9c377 Mon Sep 17 00:00:00 2001 From: tgrogers Date: Sat, 18 Nov 2017 21:00:17 -0500 Subject: fixing the cycle issues with using the cudamemcpies --- src/gpgpu-sim/gpu-sim.cc | 4 +--- src/gpgpu-sim/l2cache.cc | 5 +++-- src/gpgpu-sim/l2cache.h | 10 +++++++++- 3 files changed, 13 insertions(+), 6 deletions(-) (limited to 'src/gpgpu-sim/l2cache.h') diff --git a/src/gpgpu-sim/gpu-sim.cc b/src/gpgpu-sim/gpu-sim.cc index 0267c31..8dc80d2 100644 --- a/src/gpgpu-sim/gpu-sim.cc +++ b/src/gpgpu-sim/gpu-sim.cc @@ -1602,8 +1602,7 @@ void gpgpu_sim::perf_memcpy_to_gpu( size_t dst_start_addr, size_t count ) { if (m_memory_config->m_perf_sim_memcpy) { assert (dst_start_addr % 32 == 0); - // Right now - I am just going to assume you write the whole last cache line... - // assert (count % 128 == 0); + for ( unsigned counter = 0; counter < count; counter += 32 ) { const unsigned wr_addr = dst_start_addr + counter; addrdec_t raw_addr; @@ -1612,7 +1611,6 @@ void gpgpu_sim::perf_memcpy_to_gpu( size_t dst_start_addr, size_t count ) m_memory_config->m_address_mapping.addrdec_tlx( wr_addr, &raw_addr ); const unsigned partition_id = raw_addr.sub_partition / m_memory_config->m_n_sub_partition_per_memory_channel; m_memory_partition_unit[ partition_id ]->handle_memcpy_to_gpu( wr_addr, raw_addr.sub_partition, mask ); - gpu_sim_cycle += 1; } } } diff --git a/src/gpgpu-sim/l2cache.cc b/src/gpgpu-sim/l2cache.cc index fb0d588..b1465a8 100644 --- a/src/gpgpu-sim/l2cache.cc +++ b/src/gpgpu-sim/l2cache.cc @@ -315,6 +315,7 @@ memory_sub_partition::memory_sub_partition( unsigned sub_partition_id, m_id = sub_partition_id; m_config=config; m_stats=stats; + m_memcpy_cycle_offset = 0; assert(m_id < m_config->m_n_mem_sub_partition); @@ -378,7 +379,7 @@ void memory_sub_partition::cache_cycle( unsigned cycle ) if ( !m_config->m_L2_config.disabled() && m_L2cache->waiting_for_fill(mf) ) { if (m_L2cache->fill_port_free()) { mf->set_status(IN_PARTITION_L2_FILL_QUEUE,gpu_sim_cycle+gpu_tot_sim_cycle); - m_L2cache->fill(mf,gpu_sim_cycle+gpu_tot_sim_cycle); + m_L2cache->fill(mf,gpu_sim_cycle+gpu_tot_sim_cycle+m_memcpy_cycle_offset); m_dram_L2_queue->pop(); } } else if ( !m_L2_icnt_queue->full() ) { @@ -404,7 +405,7 @@ void memory_sub_partition::cache_cycle( unsigned cycle ) bool port_free = m_L2cache->data_port_free(); if ( !output_full && port_free ) { std::list events; - enum cache_request_status status = m_L2cache->access(mf->get_addr(),mf,gpu_sim_cycle+gpu_tot_sim_cycle,events); + enum cache_request_status status = m_L2cache->access(mf->get_addr(),mf,gpu_sim_cycle+gpu_tot_sim_cycle+m_memcpy_cycle_offset,events); bool write_sent = was_write_sent(events); bool read_sent = was_read_sent(events); MEM_SUBPART_DPRINTF("Probing L2 cache Address=%llx, status=%u\n", mf->get_addr(), status); diff --git a/src/gpgpu-sim/l2cache.h b/src/gpgpu-sim/l2cache.h index b613a94..2d13918 100644 --- a/src/gpgpu-sim/l2cache.h +++ b/src/gpgpu-sim/l2cache.h @@ -181,7 +181,8 @@ public: void force_l2_tag_update(new_addr_type addr, unsigned time, mem_access_sector_mask_t mask) { - m_L2cache->force_tag_access( addr, time, mask ); + m_L2cache->force_tag_access( addr, m_memcpy_cycle_offset + time, mask ); + m_memcpy_cycle_offset += 1; } private: @@ -216,6 +217,13 @@ private: friend class L2interface; std::vector breakdown_request_to_sector_requests(mem_fetch* mf); + + // This is a cycle offset that has to be applied to the l2 accesses to account for + // the cudamemcpy read/writes. We want GPGPU-Sim to only count cycles for kernel execution + // but we want cudamemcpy to go through the L2. Everytime an access is made from cudamemcpy + // this counter is incremented, and when the l2 is accessed (in both cudamemcpyies and otherwise) + // this value is added to the gpgpu-sim cycle counters. + unsigned m_memcpy_cycle_offset; }; class L2interface : public mem_fetch_interface { -- 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/l2cache.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