From 50b7ac49a78948f61fa685d717de90feaa277b9b Mon Sep 17 00:00:00 2001 From: Mahmoud Date: Wed, 25 Oct 2017 13:15:44 -0400 Subject: The commits includes: 1- REEAD/WERITE buffer for DRAM 2- Fixing FETCH_ON_WRITE cahce policy bug --- src/gpgpu-sim/l2cache.cc | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) (limited to 'src/gpgpu-sim/l2cache.cc') diff --git a/src/gpgpu-sim/l2cache.cc b/src/gpgpu-sim/l2cache.cc index f7323c5..cac59f1 100644 --- a/src/gpgpu-sim/l2cache.cc +++ b/src/gpgpu-sim/l2cache.cc @@ -93,7 +93,9 @@ memory_partition_unit::arbitration_metadata::arbitration_metadata(const struct m m_private_credit_limit = 1; m_shared_credit_limit = config->gpgpu_frfcfs_dram_sched_queue_size + config->gpgpu_dram_return_queue_size - - (config->m_n_sub_partition_per_memory_channel - 1); + - (config->m_n_sub_partition_per_memory_channel - 1); + if(config->seperate_write_queue_enabled ) + m_shared_credit_limit += config->gpgpu_frfcfs_dram_write_queue_size; if (config->gpgpu_frfcfs_dram_sched_queue_size == 0 or config->gpgpu_dram_return_queue_size == 0) { @@ -220,7 +222,8 @@ void memory_partition_unit::dram_cycle() m_dram->cycle(); m_dram->dram_log(SAMPLELOG); - if( !m_dram->full() ) { + // mem_fetch *mf = m_sub_partition[spid]->L2_dram_queue_top(); + //if( !m_dram->full(mf->is_write()) ) { // L2->DRAM queue to DRAM latency queue // Arbitrate among multiple L2 subpartitions int last_issued_partition = m_arbitration_metadata.last_borrower(); @@ -228,6 +231,9 @@ void memory_partition_unit::dram_cycle() int spid = (p + last_issued_partition + 1) % m_config->m_n_sub_partition_per_memory_channel; if (!m_sub_partition[spid]->L2_dram_queue_empty() && can_issue_to_dram(spid)) { mem_fetch *mf = m_sub_partition[spid]->L2_dram_queue_top(); + if(m_dram->full(mf->is_write()) ) + break; + m_sub_partition[spid]->L2_dram_queue_pop(); MEMPART_DPRINTF("Issue mem_fetch request %p from sub partition %d to dram\n", mf, spid); dram_delay_t d; @@ -239,12 +245,13 @@ void memory_partition_unit::dram_cycle() break; // the DRAM should only accept one request per cycle } } - } + //} // DRAM latency queue - if( !m_dram_latency_queue.empty() && ( (gpu_sim_cycle+gpu_tot_sim_cycle) >= m_dram_latency_queue.front().ready_cycle ) && !m_dram->full() ) { - mem_fetch* mf = m_dram_latency_queue.front().req; - m_dram_latency_queue.pop_front(); + + if( !m_dram_latency_queue.empty() && ( (gpu_sim_cycle+gpu_tot_sim_cycle) >= m_dram_latency_queue.front().ready_cycle ) && !m_dram->full(m_dram_latency_queue.front().req->is_write()) ) { + mem_fetch* mf = m_dram_latency_queue.front().req; + m_dram_latency_queue.pop_front(); m_dram->push(mf); } } @@ -343,12 +350,12 @@ void memory_sub_partition::cache_cycle( unsigned cycle ) mf->set_status(IN_PARTITION_L2_TO_ICNT_QUEUE,gpu_sim_cycle+gpu_tot_sim_cycle); m_L2_icnt_queue->push(mf); }else{ - if(m_config->m_L2_config.m_write_alloc_policy == FETCH_ON_WRITE && mf->original_mf) + if(m_config->m_L2_config.m_write_alloc_policy == FETCH_ON_WRITE) { - assert(mf->original_mf); - mf->original_mf->set_reply(); - mf->original_mf->set_status(IN_PARTITION_L2_TO_ICNT_QUEUE,gpu_sim_cycle+gpu_tot_sim_cycle); - m_L2_icnt_queue->push(mf->original_mf); + 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); } m_request_tracker.erase(mf); delete mf; -- cgit v1.3 From f23021ad8663636e1103bd75a742480cb6238435 Mon Sep 17 00:00:00 2001 From: Mahmoud Date: Fri, 27 Oct 2017 22:35:52 -0400 Subject: add more statistics and chaging Pascal config --- configs/Pascal-P102-GDDR5X/gpgpusim.config | 12 +++++++----- src/abstract_hardware_model.cc | 2 +- src/gpgpu-sim/dram.cc | 3 ++- src/gpgpu-sim/dram_sched.cc | 2 ++ src/gpgpu-sim/gpu-cache.cc | 2 ++ src/gpgpu-sim/gpu-sim.cc | 2 +- src/gpgpu-sim/gpu-sim.h | 2 +- src/gpgpu-sim/l2cache.cc | 2 +- src/gpgpu-sim/mem_latency_stat.cc | 17 +++++++++++++---- src/gpgpu-sim/mem_latency_stat.h | 4 ++++ src/gpgpu-sim/shader.cc | 8 ++++---- 11 files changed, 38 insertions(+), 18 deletions(-) (limited to 'src/gpgpu-sim/l2cache.cc') diff --git a/configs/Pascal-P102-GDDR5X/gpgpusim.config b/configs/Pascal-P102-GDDR5X/gpgpusim.config index 5419c51..e830023 100644 --- a/configs/Pascal-P102-GDDR5X/gpgpusim.config +++ b/configs/Pascal-P102-GDDR5X/gpgpusim.config @@ -59,22 +59,24 @@ # ** 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 64KB L1 cache +# Pascal GP102 has 24KB L1 cache # The defulat is to disable the L1 cache, unless cache modifieres is used --gpgpu_cache:dl1 S:64:128:6,L:L:m:N:H,A:128:8,8 +-gpgpu_cache:dl1 N:32:128:6,L:L:m:N:H,S:128:8,16 -gpgpu_shmem_size 49152 -gmem_skip_L1D 1 -icnt_flit_size 40 -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:256:4,4:0,32 +-gpgpu_cache:dl2 S:64:128:16,L:B:m:F:L,A:128:4,16:0,32 -gpgpu_cache:dl2_texture_only 0 -gpgpu_dram_partition_queues 32:32:32:32 +#-gpgpu_flush_l2_cache 1 # 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 # 12 KB Const -gpgpu_const_cache:l1 N:128:64:2,L:R:f:N:L,S:2:64,4 @@ -100,7 +102,7 @@ -gpgpu_shmem_limited_broadcast 0 -gpgpu_shmem_warp_parts 1 # Use Fermi Coalsce arhitetecture which is the same as Pascal --gpgpu_coalesce_arch 20 +-gpgpu_coalesce_arch 61 ## In Pascal, a warp scheduler can issue 2 insts per cycle using 2 diff execution units -gpgpu_max_insn_issue_per_warp 2 @@ -143,7 +145,7 @@ -dram_bnkgrp_indexing_policy 1 #-Seperate_Write_Queue_Enable 1 -#-Write_Queue_Size 32:28:16 +#-Write_Queue_Size 64:56:32 # Pascal 102 has four schedulers per core -gpgpu_num_sched_per_core 2 diff --git a/src/abstract_hardware_model.cc b/src/abstract_hardware_model.cc index 51265fd..d2a155c 100644 --- a/src/abstract_hardware_model.cc +++ b/src/abstract_hardware_model.cc @@ -314,7 +314,7 @@ void warp_inst_t::generate_mem_accesses() break; case global_space: case local_space: case param_space_local: - if( m_config->gpgpu_coalesce_arch == 13 || m_config->gpgpu_coalesce_arch == 20) { + if( m_config->gpgpu_coalesce_arch >= 13 && m_config->gpgpu_coalesce_arch <= 62) { if(isatomic()) memory_coalescing_arch_atomic(is_write, access_type); else diff --git a/src/gpgpu-sim/dram.cc b/src/gpgpu-sim/dram.cc index 7ed7b6f..de37f64 100644 --- a/src/gpgpu-sim/dram.cc +++ b/src/gpgpu-sim/dram.cc @@ -570,9 +570,10 @@ bool dram_t::issue_col_command(int j) bkgrp[grp]->RTPLc = m_config->tRTPL; issued = true; if(bk[j]->mrq->data->get_access_type() == L2_WR_ALLOC_R) - n_rd_L2_A++; + n_rd_L2_A++; else n_rd++; + bwutil += m_config->BL/m_config->data_command_freq_ratio; bwutil_partial += m_config->BL/m_config->data_command_freq_ratio; bk[j]->n_access++; diff --git a/src/gpgpu-sim/dram_sched.cc b/src/gpgpu-sim/dram_sched.cc index 7a140c5..ac4c827 100644 --- a/src/gpgpu-sim/dram_sched.cc +++ b/src/gpgpu-sim/dram_sched.cc @@ -220,6 +220,8 @@ void dram_t::scheduler_frfcfs() bk[b]->mrq = req; if (m_config->gpgpu_memlatency_stat) { mrq_latency = gpu_sim_cycle + gpu_tot_sim_cycle - bk[b]->mrq->timestamp; + m_stats->tot_mrq_latency += mrq_latency; + m_stats->tot_mrq_num++; bk[b]->mrq->timestamp = gpu_tot_sim_cycle + gpu_sim_cycle; m_stats->mrq_lat_table[LOGB2(mrq_latency)]++; if (mrq_latency > m_stats->max_mrq_latency) { diff --git a/src/gpgpu-sim/gpu-cache.cc b/src/gpgpu-sim/gpu-cache.cc index d199cca..32c2bb1 100644 --- a/src/gpgpu-sim/gpu-cache.cc +++ b/src/gpgpu-sim/gpu-cache.cc @@ -333,8 +333,10 @@ void tag_array::fill( unsigned index, unsigned time, mem_fetch* mf) void tag_array::flush() { 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)) ; + } } float tag_array::windowed_miss_rate( ) const diff --git a/src/gpgpu-sim/gpu-sim.cc b/src/gpgpu-sim/gpu-sim.cc index 6179d46..0e06c5c 100644 --- a/src/gpgpu-sim/gpu-sim.cc +++ b/src/gpgpu-sim/gpu-sim.cc @@ -1412,7 +1412,7 @@ void gpgpu_sim::cycle() if (mf) { unsigned response_size = mf->get_is_write()?mf->get_ctrl_size():mf->size(); if ( ::icnt_has_buffer( m_shader_config->mem2device(i), response_size ) ) { - if (!mf->get_is_write()) + //if (!mf->get_is_write()) mf->set_return_timestamp(gpu_sim_cycle+gpu_tot_sim_cycle); mf->set_status(IN_ICNT_TO_SHADER,gpu_sim_cycle+gpu_tot_sim_cycle); ::icnt_push( m_shader_config->mem2device(i), mf->get_tpc(), mf, response_size ); diff --git a/src/gpgpu-sim/gpu-sim.h b/src/gpgpu-sim/gpu-sim.h index 52c4643..043fcee 100644 --- a/src/gpgpu-sim/gpu-sim.h +++ b/src/gpgpu-sim/gpu-sim.h @@ -199,7 +199,7 @@ struct memory_config { assert(nbkgrp>0 && "Number of bank groups cannot be zero"); tRCDWR = tRCD-(WL+1); tRTW = (CL+(BL/data_command_freq_ratio)+2-WL); - tWTR = (WL+(BL/data_command_freq_ratio)+tCDLR); + tWTR = (WL+(BL/data_command_freq_ratio)+tCDLR); tWTP = (WL+(BL/data_command_freq_ratio)+tWR); dram_atom_size = BL * busW * gpu_n_mem_per_ctrlr; // burst length x bus width x # chips per partition diff --git a/src/gpgpu-sim/l2cache.cc b/src/gpgpu-sim/l2cache.cc index cac59f1..8fbf448 100644 --- a/src/gpgpu-sim/l2cache.cc +++ b/src/gpgpu-sim/l2cache.cc @@ -628,6 +628,7 @@ std::vector memory_sub_partition::breakdown_request_to_sector_reques void memory_sub_partition::push( mem_fetch* m_req, unsigned long long cycle ) { if (m_req) { + m_stats->memlatstat_icnt2mem_pop(m_req); std::vector reqs; if(m_config->m_L2_config.m_cache_type == SECTOR) reqs = breakdown_request_to_sector_requests(m_req); @@ -637,7 +638,6 @@ void memory_sub_partition::push( mem_fetch* m_req, unsigned long long cycle ) for(unsigned i=0; imemlatstat_icnt2mem_pop(req); if( req->istexture() ) { m_icnt_L2_queue->push(req); req->set_status(IN_PARTITION_ICNT_TO_L2_QUEUE,gpu_sim_cycle+gpu_tot_sim_cycle); diff --git a/src/gpgpu-sim/mem_latency_stat.cc b/src/gpgpu-sim/mem_latency_stat.cc index fde0eff..35d6d84 100644 --- a/src/gpgpu-sim/mem_latency_stat.cc +++ b/src/gpgpu-sim/mem_latency_stat.cc @@ -75,6 +75,10 @@ memory_stats_t::memory_stats_t( unsigned n_shader, const struct shader_core_conf max_mf_latency = 0; max_icnt2mem_latency = 0; max_icnt2sh_latency = 0; + tot_icnt2mem_latency = 0; + tot_icnt2sh_latency = 0; + tot_mrq_num = 0; + tot_mrq_latency = 0; memset(mrq_lat_table, 0, sizeof(unsigned)*32); memset(dq_lat_table, 0, sizeof(unsigned)*32); memset(mf_lat_table, 0, sizeof(unsigned)*32); @@ -158,6 +162,7 @@ void memory_stats_t::memlatstat_read_done(mem_fetch *mf) mf_max_lat_table[mf->get_tlx_addr().chip][mf->get_tlx_addr().bk] = mf_latency; unsigned icnt2sh_latency; icnt2sh_latency = (gpu_tot_sim_cycle+gpu_sim_cycle) - mf->get_return_timestamp(); + tot_icnt2sh_latency += icnt2sh_latency; icnt2sh_lat_table[LOGB2(icnt2sh_latency)]++; if (icnt2sh_latency > max_icnt2sh_latency) max_icnt2sh_latency = icnt2sh_latency; @@ -191,6 +196,7 @@ void memory_stats_t::memlatstat_icnt2mem_pop(mem_fetch *mf) if (m_memory_config->gpgpu_memlatency_stat) { unsigned icnt2mem_latency; icnt2mem_latency = (gpu_tot_sim_cycle+gpu_sim_cycle) - mf->get_timestamp(); + tot_icnt2mem_latency += icnt2mem_latency; icnt2mem_lat_table[LOGB2(icnt2mem_latency)]++; if (icnt2mem_latency > max_icnt2mem_latency) max_icnt2mem_latency = icnt2mem_latency; @@ -216,14 +222,17 @@ void memory_stats_t::memlatstat_print( unsigned n_mem, unsigned gpu_mem_n_bk ) unsigned max_bank_accesses, min_bank_accesses, max_chip_accesses, min_chip_accesses; if (m_memory_config->gpgpu_memlatency_stat) { + printf("maxmflatency = %d \n", max_mf_latency); + printf("max_icnt2mem_latency = %d \n", max_icnt2mem_latency); printf("maxmrqlatency = %d \n", max_mrq_latency); - printf("maxdqlatency = %d \n", max_dq_latency); - printf("maxmflatency = %d \n", max_mf_latency); + //printf("maxdqlatency = %d \n", max_dq_latency); + printf("max_icnt2sh_latency = %d \n", max_icnt2sh_latency); if (num_mfs) { printf("averagemflatency = %lld \n", mf_total_lat/num_mfs); + printf("avg_icnt2mem_latency = %lld \n", tot_icnt2mem_latency/num_mfs); + printf("avg_mrq_latency = %lld \n", tot_mrq_latency/tot_mrq_num); + printf("avg_icnt2sh_latency = %lld \n", tot_icnt2sh_latency/num_mfs); } - printf("max_icnt2mem_latency = %d \n", max_icnt2mem_latency); - printf("max_icnt2sh_latency = %d \n", max_icnt2sh_latency); printf("mrq_lat_table:"); for (i=0; i< 32; i++) { printf("%d \t", mrq_lat_table[i]); diff --git a/src/gpgpu-sim/mem_latency_stat.h b/src/gpgpu-sim/mem_latency_stat.h index 4968a3b..5b89202 100644 --- a/src/gpgpu-sim/mem_latency_stat.h +++ b/src/gpgpu-sim/mem_latency_stat.h @@ -56,6 +56,10 @@ public: unsigned max_dq_latency; unsigned max_mf_latency; unsigned max_icnt2mem_latency; + unsigned long long int tot_icnt2mem_latency; + unsigned long long int tot_icnt2sh_latency; + unsigned long long int tot_mrq_latency; + unsigned long long int tot_mrq_num; unsigned max_icnt2sh_latency; unsigned mrq_lat_table[32]; unsigned dq_lat_table[32]; diff --git a/src/gpgpu-sim/shader.cc b/src/gpgpu-sim/shader.cc index c14e19f..bf482fb 100644 --- a/src/gpgpu-sim/shader.cc +++ b/src/gpgpu-sim/shader.cc @@ -1458,7 +1458,7 @@ ldst_unit::process_cache_access( cache_t* cache, if( !write_sent ) delete mf; } else if ( status == RESERVATION_FAIL ) { - result = COAL_STALL; + result = BK_CONF; assert( !read_sent ); assert( !write_sent ); delete mf; @@ -1467,8 +1467,8 @@ ldst_unit::process_cache_access( cache_t* cache, //inst.clear_active( access.get_warp_mask() ); // threads in mf writeback when mf returns inst.accessq_pop_back(); } - if( !inst.accessq_empty() ) - result = BK_CONF; + if( !inst.accessq_empty() && result == NO_RC_FAIL) + result = COAL_STALL; return result; } @@ -1563,7 +1563,7 @@ bool ldst_unit::memory_cycle( warp_inst_t &inst, mem_stage_stall_type &stall_rea assert( CACHE_UNDEFINED != inst.cache_op ); stall_cond = process_memory_access_queue(m_L1D,inst); } - if( !inst.accessq_empty() ) + if( !inst.accessq_empty() && stall_cond == NO_RC_FAIL) stall_cond = COAL_STALL; if (stall_cond != NO_RC_FAIL) { stall_reason = stall_cond; -- cgit v1.3 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/cuda-sim/cuda-sim.cc | 4 ++++ src/gpgpu-sim/gpu-cache.cc | 23 +++++++++++++++++------ src/gpgpu-sim/gpu-cache.h | 11 +++++++++++ src/gpgpu-sim/gpu-sim.cc | 17 +++++++++++++++++ src/gpgpu-sim/gpu-sim.h | 2 ++ src/gpgpu-sim/l2cache.cc | 9 +++++++++ src/gpgpu-sim/l2cache.h | 6 ++++++ 7 files changed, 66 insertions(+), 6 deletions(-) (limited to 'src/gpgpu-sim/l2cache.cc') diff --git a/src/cuda-sim/cuda-sim.cc b/src/cuda-sim/cuda-sim.cc index a668db1..685ae53 100644 --- a/src/cuda-sim/cuda-sim.cc +++ b/src/cuda-sim/cuda-sim.cc @@ -401,6 +401,10 @@ void gpgpu_t::memcpy_to_gpu( size_t dst_start_addr, const void *src, size_t coun char *src_data = (char*)src; for (unsigned n=0; n < count; n ++ ) m_global_mem->write(dst_start_addr+n,1, src_data+n,NULL,NULL); + + // Copy into the performance model. + extern gpgpu_sim* g_the_gpu; + g_the_gpu->memcpy_to_gpu(dst_start_addr, src, count); if(g_debug_execution >= 3) { printf( " done.\n"); fflush(stdout); diff --git a/src/gpgpu-sim/gpu-cache.cc b/src/gpgpu-sim/gpu-cache.cc index 32c2bb1..37fc5ea 100644 --- a/src/gpgpu-sim/gpu-cache.cc +++ b/src/gpgpu-sim/gpu-cache.cc @@ -190,11 +190,17 @@ void tag_array::init( int core_id, int type_id ) m_type_id = type_id; } + enum cache_request_status tag_array::probe( new_addr_type addr, unsigned &idx, mem_fetch* mf) const { + mem_access_sector_mask_t mask = mf->get_access_sector_mask(); + return probe(addr, idx, mask); +} + + +enum cache_request_status tag_array::probe( new_addr_type addr, unsigned &idx, mem_access_sector_mask_t mask) 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); - mem_access_sector_mask_t mask = mf->get_access_sector_mask(); unsigned invalid_line = (unsigned)-1; unsigned valid_line = (unsigned)-1; @@ -310,18 +316,23 @@ enum cache_request_status tag_array::access( new_addr_type addr, unsigned time, void tag_array::fill( new_addr_type addr, unsigned time, mem_fetch* mf) { - assert( m_config.m_alloc_policy == ON_FILL ); + fill(addr, time, mf->get_access_sector_mask()); +} + +void tag_array::fill( new_addr_type addr, unsigned time, mem_access_sector_mask_t mask ) +{ + //assert( m_config.m_alloc_policy == ON_FILL ); unsigned idx; - enum cache_request_status status = probe(addr,idx,mf); + enum cache_request_status status = probe(addr,idx,mask); assert(status==MISS||status==SECTOR_MISS); // MSHR should have prevented redundant memory request if(status==MISS) - m_lines[idx]->allocate( m_config.tag(addr), m_config.block_addr(addr), time, mf->get_access_sector_mask() ); + m_lines[idx]->allocate( m_config.tag(addr), m_config.block_addr(addr), time, mask ); else if (status==SECTOR_MISS) { assert(m_config.m_cache_type == SECTOR); - ((sector_cache_block*)m_lines[idx])->allocate_sector( time, mf->get_access_sector_mask() ); + ((sector_cache_block*)m_lines[idx])->allocate_sector( time, mask ); } - m_lines[idx]->fill(time, mf->get_access_sector_mask()); + m_lines[idx]->fill(time, mask); } void tag_array::fill( unsigned index, unsigned time, mem_fetch* mf) 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, diff --git a/src/gpgpu-sim/gpu-sim.cc b/src/gpgpu-sim/gpu-sim.cc index 11ac5df..263cbad 100644 --- a/src/gpgpu-sim/gpu-sim.cc +++ b/src/gpgpu-sim/gpu-sim.cc @@ -1595,6 +1595,23 @@ void shader_core_ctx::dump_warp_state( FILE *fout ) const m_warp[w].print(fout); } + +void gpgpu_sim::memcpy_to_gpu( size_t dst_start_addr, const void *src, size_t count ) +{ + 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 size_t wr_addr = dst_start_addr + counter; + addrdec_t raw_addr; + mem_access_sector_mask_t mask; + mask.set(wr_addr % 128 / 32); + 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 ); + } +} + void gpgpu_sim::dump_pipeline( int mask, int s, int m ) const { /* diff --git a/src/gpgpu-sim/gpu-sim.h b/src/gpgpu-sim/gpu-sim.h index c04648c..6382adf 100644 --- a/src/gpgpu-sim/gpu-sim.h +++ b/src/gpgpu-sim/gpu-sim.h @@ -425,6 +425,8 @@ public: void gpu_print_stat(); void dump_pipeline( int mask, int s, int m ) const; + void memcpy_to_gpu( size_t dst_start_addr, const void *src, size_t count ); + //The next three functions added to be used by the functional simulation function //! Get shader core configuration diff --git a/src/gpgpu-sim/l2cache.cc b/src/gpgpu-sim/l2cache.cc index 8fbf448..1df7858 100644 --- a/src/gpgpu-sim/l2cache.cc +++ b/src/gpgpu-sim/l2cache.cc @@ -74,6 +74,15 @@ memory_partition_unit::memory_partition_unit( unsigned partition_id, } } +void memory_partition_unit::handle_memcpy_to_gpu( size_t addr, unsigned global_subpart_id, mem_access_sector_mask_t mask ) +{ + unsigned p = global_sub_partition_id_to_local_id(global_subpart_id); + std::string mystring = + mask.to_string(); + MEMPART_DPRINTF("Copy Engine Request Received For Address=%zu, local_subpart=%u, sector_mask=%s \n", addr, p, mystring.c_str()); + m_sub_partition[p]->force_l2_tag_update(addr,gpu_sim_cycle+gpu_tot_sim_cycle, mask); +} + memory_partition_unit::~memory_partition_unit() { delete m_dram; 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 14fdd4d3d250a33760b4cb04b8b5858531781d08 Mon Sep 17 00:00:00 2001 From: tgrogers Date: Sat, 18 Nov 2017 19:31:28 -0500 Subject: Adding a subpartion trace to help in figuring out what the hell is going on --- src/gpgpu-sim/l2cache.cc | 3 ++- src/gpgpu-sim/l2cache_trace.h | 16 ++++++++++++++++ src/trace_streams.tup | 1 + 3 files changed, 19 insertions(+), 1 deletion(-) (limited to 'src/gpgpu-sim/l2cache.cc') diff --git a/src/gpgpu-sim/l2cache.cc b/src/gpgpu-sim/l2cache.cc index 1df7858..fb0d588 100644 --- a/src/gpgpu-sim/l2cache.cc +++ b/src/gpgpu-sim/l2cache.cc @@ -79,7 +79,7 @@ void memory_partition_unit::handle_memcpy_to_gpu( size_t addr, unsigned global_s unsigned p = global_sub_partition_id_to_local_id(global_subpart_id); std::string mystring = mask.to_string(); - MEMPART_DPRINTF("Copy Engine Request Received For Address=%zu, local_subpart=%u, sector_mask=%s \n", addr, p, mystring.c_str()); + MEMPART_DPRINTF("Copy Engine Request Received For Address=%llx, local_subpart=%u, global_subpart=%u, sector_mask=%s \n", addr, p, global_subpart_id, mystring.c_str()); m_sub_partition[p]->force_l2_tag_update(addr,gpu_sim_cycle+gpu_tot_sim_cycle, mask); } @@ -407,6 +407,7 @@ void memory_sub_partition::cache_cycle( unsigned cycle ) enum cache_request_status status = m_L2cache->access(mf->get_addr(),mf,gpu_sim_cycle+gpu_tot_sim_cycle,events); bool write_sent = was_write_sent(events); bool read_sent = was_read_sent(events); + MEM_SUBPART_DPRINTF("Probing L2 cache Address=%llx, status=%u\n", mf->get_addr(), status); if ( status == HIT ) { if( !write_sent ) { diff --git a/src/gpgpu-sim/l2cache_trace.h b/src/gpgpu-sim/l2cache_trace.h index 3dac87d..2235cdc 100644 --- a/src/gpgpu-sim/l2cache_trace.h +++ b/src/gpgpu-sim/l2cache_trace.h @@ -34,6 +34,9 @@ #define MEMPART_PRINT_STR SIM_PRINT_STR " %d - " #define MEMPART_DTRACE(x) ( DTRACE(x) && (Trace::sampling_memory_partition == -1 || Trace::sampling_memory_partition == (int)get_mpid()) ) +#define MEM_SUBPART_PRINT_STR SIM_PRINT_STR " %d - " +#define MEM_SUBPART_DTRACE(x) ( DTRACE(x) && (Trace::sampling_memory_partition == -1 || Trace::sampling_memory_partition == (int)m_id) ) + // Intended to be called from inside components of a memory partition // Depends on a get_mpid() function #define MEMPART_DPRINTF(...) do {\ @@ -46,10 +49,23 @@ }\ } while (0) +#define MEM_SUBPART_DPRINTF(...) do {\ + if (MEM_SUBPART_DTRACE(MEMORY_PARTITION_UNIT)) {\ + printf( MEM_SUBPART_PRINT_STR,\ + gpu_sim_cycle + gpu_tot_sim_cycle,\ + Trace::trace_streams_str[Trace::MEMORY_SUBPARTITION_UNIT],\ + m_id );\ + printf(__VA_ARGS__);\ + }\ +} while (0) + #else #define MEMPART_DTRACE(x) (false) #define MEMPART_DPRINTF(x, ...) do {} while (0) +#define MEM_SUBPART_DTRACE(x) (false) +#define MEM_SUBPART_DPRINTF(x, ...) do {} while (0) + #endif diff --git a/src/trace_streams.tup b/src/trace_streams.tup index bbc9bb3..3455a00 100644 --- a/src/trace_streams.tup +++ b/src/trace_streams.tup @@ -29,6 +29,7 @@ TS_TUP_BEGIN( trace_streams_type ) TS_TUP( WARP_SCHEDULER ), TS_TUP( SCOREBOARD ), TS_TUP( MEMORY_PARTITION_UNIT ), + TS_TUP( MEMORY_SUBPARTITION_UNIT ), TS_TUP( INTERCONNECT ), TS_TUP( NUM_TRACE_STREAMS ) TS_TUP_END( trace_streams_type ) -- 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.cc') 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.cc') 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/l2cache.cc') 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/l2cache.cc') 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