diff options
| author | Mahmoud Khairy A. Abdallah <[email protected]> | 2021-05-19 18:03:13 -0400 |
|---|---|---|
| committer | Mahmoud Khairy A. Abdallah <[email protected]> | 2021-05-19 18:03:13 -0400 |
| commit | 33635368080d125391766d32223b4eaaa50396e6 (patch) | |
| tree | 527a3632df8fb55e0e0981a5620fd1bf8d62d84b /src | |
| parent | 14f22bcdd171cdeb8d8f56f9ed02d6f711189be8 (diff) | |
| parent | 2b2b6a2916e4ed833c707be887bf927167a71fa6 (diff) | |
Merge branch 'dev' of https://github.com/accel-sim/gpgpu-sim_distribution into dev
Diffstat (limited to 'src')
| -rw-r--r-- | src/abstract_hardware_model.h | 9 | ||||
| -rw-r--r-- | src/gpgpu-sim/gpu-cache.cc | 193 | ||||
| -rw-r--r-- | src/gpgpu-sim/gpu-cache.h | 120 | ||||
| -rw-r--r-- | src/gpgpu-sim/gpu-sim.cc | 7 | ||||
| -rw-r--r-- | src/gpgpu-sim/l2cache.cc | 129 | ||||
| -rw-r--r-- | src/gpgpu-sim/l2cache.h | 6 | ||||
| -rw-r--r-- | src/gpgpu-sim/shader.cc | 124 | ||||
| -rw-r--r-- | src/gpgpu-sim/shader.h | 6 |
8 files changed, 438 insertions, 156 deletions
diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index 982e416..17a1cec 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -65,7 +65,7 @@ enum FuncCache { FuncCachePreferL1 = 2 }; -enum AdaptiveCache { FIXED = 0, ADAPTIVE_VOLTA = 1 }; +enum AdaptiveCache { FIXED = 0, ADAPTIVE_CACHE = 1 }; #ifdef __cplusplus @@ -373,6 +373,7 @@ class core_config { } unsigned mem_warp_parts; mutable unsigned gpgpu_shmem_size; + char *gpgpu_shmem_option; unsigned gpgpu_shmem_sizeDefault; unsigned gpgpu_shmem_sizePrefL1; unsigned gpgpu_shmem_sizePrefShared; @@ -869,6 +870,12 @@ class mem_fetch_allocator { virtual mem_fetch *alloc(const class warp_inst_t &inst, const mem_access_t &access, unsigned long long cycle) const = 0; + virtual mem_fetch *alloc(new_addr_type addr, mem_access_type type, + const active_mask_t &active_mask, + const mem_access_byte_mask_t &byte_mask, + const mem_access_sector_mask_t §or_mask, + unsigned size, bool wr, + unsigned long long cycle) const = 0; }; // the maximum number of destination, source, or address uarch operands in a diff --git a/src/gpgpu-sim/gpu-cache.cc b/src/gpgpu-sim/gpu-cache.cc index c6a125d..297a94c 100644 --- a/src/gpgpu-sim/gpu-cache.cc +++ b/src/gpgpu-sim/gpu-cache.cc @@ -210,6 +210,7 @@ void tag_array::init(int core_id, int type_id) { m_core_id = core_id; m_type_id = type_id; is_used = false; + m_dirty = 0; } void tag_array::add_pending_line(mem_fetch *mf) { @@ -231,15 +232,15 @@ void tag_array::remove_pending_line(mem_fetch *mf) { } enum cache_request_status tag_array::probe(new_addr_type addr, unsigned &idx, - mem_fetch *mf, + mem_fetch *mf, bool is_write, bool probe_mode) const { mem_access_sector_mask_t mask = mf->get_access_sector_mask(); - return probe(addr, idx, mask, probe_mode, mf); + return probe(addr, idx, mask,is_write, probe_mode, mf); } enum cache_request_status tag_array::probe(new_addr_type addr, unsigned &idx, mem_access_sector_mask_t mask, - bool probe_mode, + bool is_write, bool probe_mode, mem_fetch *mf) const { // assert( m_config.m_write_policy == READ_ONLY ); unsigned set_index = m_config.set_index(addr); @@ -250,7 +251,6 @@ enum cache_request_status tag_array::probe(new_addr_type addr, unsigned &idx, unsigned long long valid_timestamp = (unsigned)-1; bool all_reserved = true; - // check for hit or pending hit for (unsigned way = 0; way < m_config.m_assoc; way++) { unsigned index = set_index * m_config.m_assoc + way; @@ -263,7 +263,7 @@ enum cache_request_status tag_array::probe(new_addr_type addr, unsigned &idx, idx = index; return HIT; } else if (line->get_status(mask) == MODIFIED) { - if (line->is_readable(mask)) { + if ((!is_write && line->is_readable(mask)) || is_write) { idx = index; return HIT; } else { @@ -279,20 +279,29 @@ enum cache_request_status tag_array::probe(new_addr_type addr, unsigned &idx, } } if (!line->is_reserved_line()) { - all_reserved = false; - if (line->is_invalid_line()) { - invalid_line = index; - } else { - // valid line : keep track of most appropriate replacement candidate - if (m_config.m_replacement_policy == LRU) { - if (line->get_last_access_time() < valid_timestamp) { - valid_timestamp = line->get_last_access_time(); - valid_line = index; - } - } else if (m_config.m_replacement_policy == FIFO) { - if (line->get_alloc_time() < valid_timestamp) { - valid_timestamp = line->get_alloc_time(); - valid_line = index; + // percentage of dirty lines in the cache + // number of dirty lines / total lines in the cache + float dirty_line_percentage = + (float) (m_dirty / (m_config.m_nset * m_config.m_assoc )) * 100; + if (!line->is_modified_line() || + dirty_line_percentage >= m_config.m_wr_percent) { + // if number of dirty lines in the cache is greater than + // a specific value + all_reserved = false; + if (line->is_invalid_line()) { + invalid_line = index; + } else { + // valid line : keep track of most appropriate replacement candidate + if (m_config.m_replacement_policy == LRU) { + if (line->get_last_access_time() < valid_timestamp) { + valid_timestamp = line->get_last_access_time(); + valid_line = index; + } + } else if (m_config.m_replacement_policy == FIFO) { + if (line->get_alloc_time() < valid_timestamp) { + valid_timestamp = line->get_alloc_time(); + valid_line = index; + } } } } @@ -331,7 +340,7 @@ enum cache_request_status tag_array::access(new_addr_type addr, unsigned time, m_access++; is_used = true; shader_cache_access_log(m_core_id, m_type_id, 0); // log accesses to cache - enum cache_request_status status = probe(addr, idx, mf); + enum cache_request_status status = probe(addr, idx, mf, mf->is_write()); switch (status) { case HIT_RESERVED: m_pending_hit++; @@ -344,8 +353,12 @@ enum cache_request_status tag_array::access(new_addr_type addr, unsigned time, if (m_config.m_alloc_policy == ON_MISS) { if (m_lines[idx]->is_modified_line()) { wb = true; + m_lines[idx]->set_byte_mask(mf); evicted.set_info(m_lines[idx]->m_block_addr, - m_lines[idx]->get_modified_size()); + m_lines[idx]->get_modified_size(), + m_lines[idx]->get_dirty_byte_mask(), + m_lines[idx]->get_dirty_sector_mask()); + m_dirty--; } m_lines[idx]->allocate(m_config.tag(addr), m_config.block_addr(addr), time, mf->get_access_sector_mask()); @@ -356,8 +369,12 @@ enum cache_request_status tag_array::access(new_addr_type addr, unsigned time, m_sector_miss++; shader_cache_access_log(m_core_id, m_type_id, 1); // log cache misses if (m_config.m_alloc_policy == ON_MISS) { + bool before = m_lines[idx]->is_modified_line(); ((sector_cache_block *)m_lines[idx]) ->allocate_sector(time, mf->get_access_sector_mask()); + if (before && !m_lines[idx]->is_modified_line()) { + m_dirty--; + } } break; case RESERVATION_FAIL: @@ -374,31 +391,40 @@ enum cache_request_status tag_array::access(new_addr_type addr, unsigned time, return status; } -void tag_array::fill(new_addr_type addr, unsigned time, mem_fetch *mf) { - fill(addr, time, mf->get_access_sector_mask()); +void tag_array::fill(new_addr_type addr, unsigned time, mem_fetch *mf, bool is_write) { + fill(addr, time, mf->get_access_sector_mask(), mf->get_access_byte_mask(), is_write); } void tag_array::fill(new_addr_type addr, unsigned time, - mem_access_sector_mask_t mask) { + mem_access_sector_mask_t mask, mem_access_byte_mask_t byte_mask, + bool is_write) { // assert( m_config.m_alloc_policy == ON_FILL ); unsigned idx; - enum cache_request_status status = probe(addr, idx, mask); + enum cache_request_status status = probe(addr, idx, mask,is_write); + bool before = m_lines[idx]->is_modified_line(); // assert(status==MISS||status==SECTOR_MISS); // MSHR should have prevented // redundant memory request - if (status == MISS) + if (status == MISS) { m_lines[idx]->allocate(m_config.tag(addr), m_config.block_addr(addr), time, mask); - else if (status == SECTOR_MISS) { + } else if (status == SECTOR_MISS) { assert(m_config.m_cache_type == SECTOR); ((sector_cache_block *)m_lines[idx])->allocate_sector(time, mask); } - - m_lines[idx]->fill(time, mask); + if (before && !m_lines[idx]->is_modified_line()) { + m_dirty--; + } + before = m_lines[idx]->is_modified_line(); + m_lines[idx]->fill(time, mask, byte_mask); + if (m_lines[idx]->is_modified_line() && !before) { + m_dirty++; + } } void tag_array::fill(unsigned index, unsigned time, mem_fetch *mf) { assert(m_config.m_alloc_policy == ON_MISS); - m_lines[index]->fill(time, mf->get_access_sector_mask()); + m_lines[index]->fill(time, mf->get_access_sector_mask(), mf->get_access_byte_mask()); + m_dirty++; } // TODO: we need write back the flushed data to the upper level @@ -407,10 +433,12 @@ 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++) + for (unsigned j = 0; j < SECTOR_CHUNCK_SIZE; j++) { m_lines[i]->set_status(INVALID, mem_access_sector_mask_t().set(j)); + } } - + + m_dirty = 0; is_used = false; } @@ -421,6 +449,7 @@ void tag_array::invalidate() { for (unsigned j = 0; j < SECTOR_CHUNCK_SIZE; j++) m_lines[i]->set_status(INVALID, mem_access_sector_mask_t().set(j)); + m_dirty = 0; is_used = false; } @@ -764,7 +793,9 @@ void cache_stats::print_stats(FILE *fout, const char *cache_name) const { cache_request_status_str((enum cache_request_status)status), m_stats[type][status]); - if (status != RESERVATION_FAIL) + if (status != RESERVATION_FAIL && status != MSHR_HIT) + // MSHR_HIT is a special type of SECTOR_MISS + // so its already included in the SECTOR_MISS total_access[type] += m_stats[type][status]; } } @@ -1050,7 +1081,7 @@ void baseline_cache::fill(mem_fetch *mf, unsigned time) { if (m_config.m_alloc_policy == ON_MISS) m_tag_array->fill(e->second.m_cache_index, time, mf); else if (m_config.m_alloc_policy == ON_FILL) { - m_tag_array->fill(e->second.m_block_addr, time, mf); + m_tag_array->fill(e->second.m_block_addr, time, mf, mf->is_write()); } else abort(); bool has_atomic = false; @@ -1058,9 +1089,13 @@ void baseline_cache::fill(mem_fetch *mf, unsigned time) { if (has_atomic) { assert(m_config.m_alloc_policy == ON_MISS); cache_block_t *block = m_tag_array->get_block(e->second.m_cache_index); + if (!block->is_modified_line()) { + m_tag_array->inc_dirty(); + } block->set_status(MODIFIED, mf->get_access_sector_mask()); // mark line as dirty for // atomic operation + block->set_byte_mask(mf); } m_extra_mf_fields.erase(mf); m_bandwidth_management.use_fill_port(mf); @@ -1163,7 +1198,11 @@ cache_request_status data_cache::wr_hit_wb(new_addr_type addr, new_addr_type block_addr = m_config.block_addr(addr); m_tag_array->access(block_addr, time, cache_index, mf); // update LRU state cache_block_t *block = m_tag_array->get_block(cache_index); + if (!block->is_modified_line()) { + m_tag_array->inc_dirty(); + } block->set_status(MODIFIED, mf->get_access_sector_mask()); + block->set_byte_mask(mf); return HIT; } @@ -1182,7 +1221,11 @@ cache_request_status data_cache::wr_hit_wt(new_addr_type addr, new_addr_type block_addr = m_config.block_addr(addr); m_tag_array->access(block_addr, time, cache_index, mf); // update LRU state cache_block_t *block = m_tag_array->get_block(cache_index); + if (!block->is_modified_line()) { + m_tag_array->inc_dirty(); + } block->set_status(MODIFIED, mf->get_access_sector_mask()); + block->set_byte_mask(mf); // generate a write-through send_write_request(mf, cache_event(WRITE_REQUEST_SENT), time, events); @@ -1292,8 +1335,10 @@ enum cache_request_status data_cache::wr_miss_wa_naive( assert(status == MISS); // SECTOR_MISS and HIT_RESERVED should not send write back mem_fetch *wb = m_memfetch_creator->alloc( - evicted.m_block_addr, m_wrbk_type, evicted.m_modified_size, true, - m_gpu->gpu_tot_sim_cycle + m_gpu->gpu_sim_cycle); + evicted.m_block_addr,m_wrbk_type, + mf->get_access_warp_mask(), evicted.m_byte_mask, + evicted.m_sector_mask, evicted.m_modified_size, + true, m_gpu->gpu_tot_sim_cycle + m_gpu->gpu_sim_cycle); // the evicted block may have wrong chip id when advanced L2 hashing is // used, so set the right chip address from the original mf wb->set_chip(mf->get_tlx_addr().chip); @@ -1330,7 +1375,11 @@ enum cache_request_status data_cache::wr_miss_wa_fetch_on_write( m_tag_array->access(block_addr, time, cache_index, wb, evicted, mf); assert(status != HIT); cache_block_t *block = m_tag_array->get_block(cache_index); + if (!block->is_modified_line()) { + m_tag_array->inc_dirty(); + } block->set_status(MODIFIED, mf->get_access_sector_mask()); + block->set_byte_mask(mf); if (status == HIT_RESERVED) block->set_ignore_on_fill(true, mf->get_access_sector_mask()); @@ -1339,8 +1388,10 @@ enum cache_request_status data_cache::wr_miss_wa_fetch_on_write( // (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, - m_gpu->gpu_tot_sim_cycle + m_gpu->gpu_sim_cycle); + evicted.m_block_addr,m_wrbk_type, + mf->get_access_warp_mask(), evicted.m_byte_mask, + evicted.m_sector_mask, evicted.m_modified_size, + true, m_gpu->gpu_tot_sim_cycle + m_gpu->gpu_sim_cycle); // the evicted block may have wrong chip id when advanced L2 hashing is // used, so set the right chip address from the original mf wb->set_chip(mf->get_tlx_addr().chip); @@ -1401,6 +1452,7 @@ enum cache_request_status data_cache::wr_miss_wa_fetch_on_write( cache_block_t *block = m_tag_array->get_block(cache_index); block->set_modified_on_fill(true, mf->get_access_sector_mask()); + block->set_byte_mask_on_fill(true); events.push_back(cache_event(WRITE_ALLOCATE_SENT)); @@ -1409,8 +1461,10 @@ enum cache_request_status data_cache::wr_miss_wa_fetch_on_write( // (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, - m_gpu->gpu_tot_sim_cycle + m_gpu->gpu_sim_cycle); + evicted.m_block_addr,m_wrbk_type, + mf->get_access_warp_mask(), evicted.m_byte_mask, + evicted.m_sector_mask, evicted.m_modified_size, + true, m_gpu->gpu_tot_sim_cycle + m_gpu->gpu_sim_cycle); // the evicted block may have wrong chip id when advanced L2 hashing is // used, so set the right chip address from the original mf wb->set_chip(mf->get_tlx_addr().chip); @@ -1428,16 +1482,39 @@ 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<cache_event> &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 + // Write allocate, maximum 2 requests (write miss, write back request) + // Conservatively ensure the worst-case request can be handled this + // cycle + if (m_config.m_write_policy == WRITE_THROUGH) { + bool mshr_hit = m_mshrs.probe(mshr_addr); + bool mshr_avail = !m_mshrs.full(mshr_addr); + if (miss_queue_full(1) || + (!(mshr_hit && mshr_avail) && + !(!mshr_hit && mshr_avail && + (m_miss_queue.size() < m_config.m_miss_queue_size)))) { + // check what is the exactly the failure reason + if (miss_queue_full(1)) + m_stats.inc_fail_stats(mf->get_access_type(), MISS_QUEUE_FULL); + else if (mshr_hit && !mshr_avail) + m_stats.inc_fail_stats(mf->get_access_type(), MSHR_MERGE_ENRTY_FAIL); + else if (!mshr_hit && !mshr_avail) + m_stats.inc_fail_stats(mf->get_access_type(), MSHR_ENRTY_FAIL); + else + assert(0); + + return RESERVATION_FAIL; + } + + send_write_request(mf, cache_event(WRITE_REQUEST_SENT), time, events); } + bool wb = false; evicted_block_info evicted; @@ -1445,11 +1522,15 @@ enum cache_request_status data_cache::wr_miss_wa_lazy_fetch_on_read( 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); + if (!block->is_modified_line()) { + m_tag_array->inc_dirty(); + } + block->set_status(MODIFIED, mf->get_access_sector_mask()); + block->set_byte_mask(mf); 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()); - } else { - block->set_status(MODIFIED, mf->get_access_sector_mask()); + block->set_byte_mask_on_fill(true); } if (mf->get_access_byte_mask().count() == m_config.get_atom_sz()) { @@ -1465,8 +1546,10 @@ enum cache_request_status data_cache::wr_miss_wa_lazy_fetch_on_read( // (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, - m_gpu->gpu_tot_sim_cycle + m_gpu->gpu_sim_cycle); + evicted.m_block_addr,m_wrbk_type, + mf->get_access_warp_mask(), evicted.m_byte_mask, + evicted.m_sector_mask, evicted.m_modified_size, + true, m_gpu->gpu_tot_sim_cycle + m_gpu->gpu_sim_cycle); // the evicted block may have wrong chip id when advanced L2 hashing is // used, so set the right chip address from the original mf wb->set_chip(mf->get_tlx_addr().chip); @@ -1509,8 +1592,12 @@ enum cache_request_status data_cache::rd_hit_base( if (mf->isatomic()) { assert(mf->get_access_type() == GLOBAL_ACC_R); cache_block_t *block = m_tag_array->get_block(cache_index); + if (!block->is_modified_line()) { + m_tag_array->inc_dirty(); + } block->set_status(MODIFIED, - mf->get_access_sector_mask()); // mark line as dirty + mf->get_access_sector_mask()); // mark line as + block->set_byte_mask(mf); } return HIT; } @@ -1541,8 +1628,10 @@ enum cache_request_status data_cache::rd_miss_base( // (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, - m_gpu->gpu_tot_sim_cycle + m_gpu->gpu_sim_cycle); + evicted.m_block_addr,m_wrbk_type, + mf->get_access_warp_mask(), evicted.m_byte_mask, + evicted.m_sector_mask, evicted.m_modified_size, + true, m_gpu->gpu_tot_sim_cycle + m_gpu->gpu_sim_cycle); // the evicted block may have wrong chip id when advanced L2 hashing is // used, so set the right chip address from the original mf wb->set_chip(mf->get_tlx_addr().chip); @@ -1565,7 +1654,7 @@ enum cache_request_status read_only_cache::access( new_addr_type block_addr = m_config.block_addr(addr); unsigned cache_index = (unsigned)-1; enum cache_request_status status = - m_tag_array->probe(block_addr, cache_index, mf); + m_tag_array->probe(block_addr, cache_index, mf, mf->is_write()); enum cache_request_status cache_status = RESERVATION_FAIL; if (status == HIT) { @@ -1652,7 +1741,7 @@ enum cache_request_status data_cache::access(new_addr_type addr, mem_fetch *mf, new_addr_type block_addr = m_config.block_addr(addr); unsigned cache_index = (unsigned)-1; enum cache_request_status probe_status = - m_tag_array->probe(block_addr, cache_index, mf, true); + m_tag_array->probe(block_addr, cache_index, mf, mf->is_write(), true); enum cache_request_status access_status = process_tag_probe(wr, probe_status, addr, cache_index, mf, time, events); m_stats.inc_stats(mf->get_access_type(), diff --git a/src/gpgpu-sim/gpu-cache.h b/src/gpgpu-sim/gpu-cache.h index b2db1c5..75dce40 100644 --- a/src/gpgpu-sim/gpu-cache.h +++ b/src/gpgpu-sim/gpu-cache.h @@ -72,14 +72,26 @@ enum cache_event_type { struct evicted_block_info { new_addr_type m_block_addr; unsigned m_modified_size; + mem_access_byte_mask_t m_byte_mask; + mem_access_sector_mask_t m_sector_mask; evicted_block_info() { m_block_addr = 0; m_modified_size = 0; + m_byte_mask.reset(); + m_sector_mask.reset(); } void set_info(new_addr_type block_addr, unsigned modified_size) { m_block_addr = block_addr; m_modified_size = modified_size; } + void set_info(new_addr_type block_addr, unsigned modified_size, + mem_access_byte_mask_t byte_mask, + mem_access_sector_mask_t sector_mask) { + m_block_addr = block_addr; + m_modified_size = modified_size; + m_byte_mask = byte_mask; + m_sector_mask = sector_mask; + } }; struct cache_event { @@ -109,7 +121,8 @@ struct cache_block_t { virtual void allocate(new_addr_type tag, new_addr_type block_addr, unsigned time, mem_access_sector_mask_t sector_mask) = 0; - virtual void fill(unsigned time, mem_access_sector_mask_t sector_mask) = 0; + virtual void fill(unsigned time, mem_access_sector_mask_t sector_mask, + mem_access_byte_mask_t byte_mask) = 0; virtual bool is_invalid_line() = 0; virtual bool is_valid_line() = 0; @@ -120,7 +133,10 @@ struct cache_block_t { mem_access_sector_mask_t sector_mask) = 0; virtual void set_status(enum cache_block_state m_status, mem_access_sector_mask_t sector_mask) = 0; - + virtual void set_byte_mask(mem_fetch *mf) = 0; + virtual void set_byte_mask(mem_access_byte_mask_t byte_mask) = 0; + virtual mem_access_byte_mask_t get_dirty_byte_mask() = 0; + virtual mem_access_sector_mask_t get_dirty_sector_mask() = 0; virtual unsigned long long get_last_access_time() = 0; virtual void set_last_access_time(unsigned long long time, mem_access_sector_mask_t sector_mask) = 0; @@ -131,6 +147,7 @@ struct cache_block_t { mem_access_sector_mask_t sector_mask) = 0; virtual void set_readable_on_fill(bool readable, mem_access_sector_mask_t sector_mask) = 0; + virtual void set_byte_mask_on_fill(bool m_modified) = 0; virtual unsigned get_modified_size() = 0; virtual void set_m_readable(bool readable, mem_access_sector_mask_t sector_mask) = 0; @@ -164,8 +181,10 @@ struct line_cache_block : public cache_block_t { m_ignore_on_fill_status = false; m_set_modified_on_fill = false; m_set_readable_on_fill = false; + m_set_byte_mask_on_fill = false; } - void fill(unsigned time, mem_access_sector_mask_t sector_mask) { + virtual void fill(unsigned time, mem_access_sector_mask_t sector_mask, + mem_access_byte_mask_t byte_mask) { // if(!m_ignore_on_fill_status) // assert( m_status == RESERVED ); @@ -173,6 +192,7 @@ struct line_cache_block : public cache_block_t { if (m_set_readable_on_fill) m_readable = true; + if (m_set_byte_mask_on_fill) set_byte_mask(byte_mask); m_fill_time = time; } @@ -189,6 +209,20 @@ struct line_cache_block : public cache_block_t { mem_access_sector_mask_t sector_mask) { m_status = status; } + virtual void set_byte_mask(mem_fetch *mf) { + m_byte_mask = m_byte_mask | mf->get_access_byte_mask(); + } + virtual void set_byte_mask(mem_access_byte_mask_t byte_mask) { + m_byte_mask = m_byte_mask | byte_mask; + } + virtual mem_access_byte_mask_t get_dirty_byte_mask() { + return m_byte_mask; + } + virtual mem_access_sector_mask_t get_dirty_sector_mask() { + mem_access_sector_mask_t sector_mask; + if (m_status == MODIFIED) sector_mask.set(); + return sector_mask; + } virtual unsigned long long get_last_access_time() { return m_last_access_time; } @@ -209,6 +243,9 @@ struct line_cache_block : public cache_block_t { mem_access_sector_mask_t sector_mask) { m_set_readable_on_fill = readable; } + virtual void set_byte_mask_on_fill(bool m_modified) { + m_set_byte_mask_on_fill = m_modified; + } virtual unsigned get_modified_size() { return SECTOR_CHUNCK_SIZE * SECTOR_SIZE; // i.e. cache line size } @@ -231,7 +268,9 @@ struct line_cache_block : public cache_block_t { bool m_ignore_on_fill_status; bool m_set_modified_on_fill; bool m_set_readable_on_fill; + bool m_set_byte_mask_on_fill; bool m_readable; + mem_access_byte_mask_t m_byte_mask; }; struct sector_cache_block : public cache_block_t { @@ -251,6 +290,7 @@ struct sector_cache_block : public cache_block_t { m_line_alloc_time = 0; m_line_last_access_time = 0; m_line_fill_time = 0; + m_byte_mask.reset(); } virtual void allocate(new_addr_type tag, new_addr_type block_addr, @@ -276,6 +316,7 @@ struct sector_cache_block : public cache_block_t { m_ignore_on_fill_status[sidx] = false; m_set_modified_on_fill[sidx] = false; m_set_readable_on_fill[sidx] = false; + m_set_byte_mask_on_fill = false; // set line stats m_line_alloc_time = time; // only set this for the first allocated sector @@ -310,18 +351,19 @@ struct sector_cache_block : public cache_block_t { m_line_fill_time = 0; } - virtual void fill(unsigned time, mem_access_sector_mask_t sector_mask) { + virtual void fill(unsigned time, mem_access_sector_mask_t sector_mask, + mem_access_byte_mask_t byte_mask) { unsigned sidx = get_sector_index(sector_mask); // if(!m_ignore_on_fill_status[sidx]) // assert( m_status[sidx] == RESERVED ); - m_status[sidx] = m_set_modified_on_fill[sidx] ? MODIFIED : VALID; if (m_set_readable_on_fill[sidx]) { m_readable[sidx] = true; m_set_readable_on_fill[sidx] = false; } + if (m_set_byte_mask_on_fill) set_byte_mask(byte_mask); m_sector_fill_time[sidx] = time; m_line_fill_time = time; @@ -362,6 +404,23 @@ struct sector_cache_block : public cache_block_t { m_status[sidx] = status; } + virtual void set_byte_mask(mem_fetch *mf) { + m_byte_mask = m_byte_mask | mf->get_access_byte_mask(); + } + virtual void set_byte_mask(mem_access_byte_mask_t byte_mask) { + m_byte_mask = m_byte_mask | byte_mask; + } + virtual mem_access_byte_mask_t get_dirty_byte_mask() { + return m_byte_mask; + } + virtual mem_access_sector_mask_t get_dirty_sector_mask() { + mem_access_sector_mask_t sector_mask; + for (unsigned i = 0; i < SECTOR_CHUNCK_SIZE; i++) { + if (m_status[i] == MODIFIED) + sector_mask.set(i); + } + return sector_mask; + } virtual unsigned long long get_last_access_time() { return m_line_last_access_time; } @@ -387,6 +446,9 @@ struct sector_cache_block : public cache_block_t { unsigned sidx = get_sector_index(sector_mask); m_set_modified_on_fill[sidx] = m_modified; } + virtual void set_byte_mask_on_fill(bool m_modified) { + m_set_byte_mask_on_fill = m_modified; + } virtual void set_readable_on_fill(bool readable, mem_access_sector_mask_t sector_mask) { @@ -428,7 +490,9 @@ struct sector_cache_block : public cache_block_t { bool m_ignore_on_fill_status[SECTOR_CHUNCK_SIZE]; bool m_set_modified_on_fill[SECTOR_CHUNCK_SIZE]; bool m_set_readable_on_fill[SECTOR_CHUNCK_SIZE]; + bool m_set_byte_mask_on_fill; bool m_readable[SECTOR_CHUNCK_SIZE]; + mem_access_byte_mask_t m_byte_mask; unsigned get_sector_index(mem_access_sector_mask_t sector_mask) { assert(sector_mask.count() == 1); @@ -491,6 +555,7 @@ class cache_config { m_data_port_width = 0; m_set_index_function = LINEAR_SET_FUNCTION; m_is_streaming = false; + m_wr_percent = 0; } void init(char *config, FuncCache status) { cache_status = status; @@ -498,10 +563,10 @@ class cache_config { char ct, rp, wp, ap, mshr_type, wap, sif; int ntok = - sscanf(config, "%c:%u:%u:%u,%c:%c:%c:%c:%c,%c:%u:%u,%u:%u,%u", &ct, + sscanf(config, "%c:%u:%u:%u,%c:%c:%c:%c:%c,%c:%u:%u,%u:%u,%u,%u", &ct, &m_nset, &m_line_sz, &m_assoc, &rp, &wp, &ap, &wap, &sif, &mshr_type, &m_mshr_entries, &m_mshr_max_merge, - &m_miss_queue_size, &m_result_fifo_entries, &m_data_port_width); + &m_miss_queue_size, &m_result_fifo_entries, &m_data_port_width, &m_wr_percent); if (ntok < 12) { if (!strcmp(config, "none")) { @@ -511,6 +576,14 @@ class cache_config { exit_parse_error(); } + // set * assoc * cacheline size. Then convert Byte to KB + unsigned original_size = m_nset * m_assoc * m_line_sz / 1024; + if (m_unified_cache_size > 0) { + max_cache_multiplier = m_unified_cache_size / original_size; + } else { + max_cache_multiplier = MAX_DEFAULT_CACHE_SIZE_MULTIBLIER; + } + switch (ct) { case 'N': m_cache_type = NORMAL; @@ -620,6 +693,7 @@ class cache_config { m_sector_sz_log2 = LOGB2(SECTOR_SIZE); original_m_assoc = m_assoc; + // For more details about difference between FETCH_ON_WRITE and WRITE // VALIDAE policies Read: Jouppi, Norman P. "Cache write policies and // performance". ISCA 93. WRITE_ALLOCATE is the old write policy in @@ -711,11 +785,13 @@ class cache_config { } unsigned get_max_num_lines() const { assert(m_valid); - return MAX_DEFAULT_CACHE_SIZE_MULTIBLIER * m_nset * original_m_assoc; + // gpgpu_unified_cache_size is in KB while original_sz is in B + return max_cache_multiplier * m_nset * original_m_assoc; } unsigned get_max_assoc() const { assert(m_valid); - return MAX_DEFAULT_CACHE_SIZE_MULTIBLIER * original_m_assoc; + // gpgpu_unified_cache_size is in KB while original_sz is in B + return max_cache_multiplier * original_m_assoc; } void print(FILE *fp) const { fprintf(fp, "Size = %d B (%d Set x %d-way x %d byte line)\n", @@ -765,6 +841,14 @@ class cache_config { char *m_config_stringPrefL1; char *m_config_stringPrefShared; FuncCache cache_status; + unsigned m_wr_percent; + unsigned m_unified_cache_size; + write_allocate_policy_t get_write_allocate_policy() { + return m_write_alloc_policy; + } + write_policy_t get_write_policy() { + return m_write_policy; + } protected: void exit_parse_error() { @@ -784,6 +868,7 @@ class cache_config { unsigned m_sector_sz_log2; unsigned original_m_assoc; bool m_is_streaming; + unsigned max_cache_multiplier; enum replacement_policy_t m_replacement_policy; // 'L' = LRU, 'F' = FIFO enum write_policy_t @@ -812,6 +897,7 @@ class cache_config { unsigned m_data_port_width; //< number of byte the cache can access per cycle enum set_index_function m_set_index_function; // Hash, linear, or custom set index function + unsigned m_wr_percent; friend class tag_array; friend class baseline_cache; @@ -857,9 +943,11 @@ class tag_array { ~tag_array(); enum cache_request_status probe(new_addr_type addr, unsigned &idx, - mem_fetch *mf, bool probe_mode = false) const; + mem_fetch *mf, bool is_write, + bool probe_mode = false) const; enum cache_request_status probe(new_addr_type addr, unsigned &idx, mem_access_sector_mask_t mask, + bool is_write, bool probe_mode = false, mem_fetch *mf = NULL) const; enum cache_request_status access(new_addr_type addr, unsigned time, @@ -868,9 +956,10 @@ class tag_array { unsigned &idx, bool &wb, evicted_block_info &evicted, mem_fetch *mf); - void fill(new_addr_type addr, unsigned time, mem_fetch *mf); + void fill(new_addr_type addr, unsigned time, mem_fetch *mf, bool is_write); void fill(unsigned idx, unsigned time, mem_fetch *mf); - void fill(new_addr_type addr, unsigned time, mem_access_sector_mask_t mask); + void fill(new_addr_type addr, unsigned time, mem_access_sector_mask_t mask, + mem_access_byte_mask_t byte_mask, bool is_write); unsigned size() const { return m_config.get_num_lines(); } cache_block_t *get_block(unsigned idx) { return m_lines[idx]; } @@ -888,6 +977,9 @@ class tag_array { void update_cache_parameters(cache_config &config); void add_pending_line(mem_fetch *mf); void remove_pending_line(mem_fetch *mf); + void inc_dirty() { + m_dirty++; + } protected: // This constructor is intended for use only from derived classes that wish to @@ -908,6 +1000,7 @@ class tag_array { // allocated but not filled unsigned m_res_fail; unsigned m_sector_miss; + unsigned m_dirty; // performance counters for calculating the amount of misses within a time // window @@ -1253,7 +1346,8 @@ class baseline_cache : public cache_t { // 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); + mem_access_byte_mask_t byte_mask; + m_tag_array->fill(addr, time, mask, byte_mask, true); } protected: diff --git a/src/gpgpu-sim/gpu-sim.cc b/src/gpgpu-sim/gpu-sim.cc index fd36e00..df30047 100644 --- a/src/gpgpu-sim/gpu-sim.cc +++ b/src/gpgpu-sim/gpu-sim.cc @@ -249,6 +249,7 @@ void shader_core_config::reg_options(class OptionParser *opp) { " {<nsets>:<bsize>:<assoc>,<rep>:<wr>:<alloc>:<wr_" "alloc>,<mshr>:<N>:<merge>,<mq> | none}", "none"); + option_parser_register(opp,"-gpgpu_l1_cache_write_ratio",OPT_UINT32,&m_L1D_config.m_wr_percent,"L1D write ratio","0"); option_parser_register(opp, "-gpgpu_l1_banks", OPT_UINT32, &m_L1D_config.l1_banks, "The number of L1 cache banks", "1"); @@ -326,6 +327,12 @@ void shader_core_config::reg_options(class OptionParser *opp) { option_parser_register( opp, "-gpgpu_shmem_size", OPT_UINT32, &gpgpu_shmem_size, "Size of shared memory per shader core (default 16kB)", "16384"); + option_parser_register( + opp, "-gpgpu_shmem_option", OPT_CSTR, &gpgpu_shmem_option, + "Option list of shared memory sizes", "0"); + option_parser_register( + opp, "-gpgpu_unified_l1d_size", OPT_UINT32, &m_L1D_config.m_unified_cache_size, + "Size of unified data cache(L1D + shared memory) in KB", "0"); option_parser_register(opp, "-gpgpu_adaptive_cache_config", OPT_BOOL, &adaptive_cache_config, "adaptive_cache_config", "0"); option_parser_register( diff --git a/src/gpgpu-sim/l2cache.cc b/src/gpgpu-sim/l2cache.cc index ab6e5c2..00b14d7 100644 --- a/src/gpgpu-sim/l2cache.cc +++ b/src/gpgpu-sim/l2cache.cc @@ -57,6 +57,20 @@ mem_fetch *partition_mf_allocator::alloc(new_addr_type addr, return mf; } +mem_fetch *partition_mf_allocator::alloc(new_addr_type addr, + mem_access_type type, + const active_mask_t &active_mask, + const mem_access_byte_mask_t &byte_mask, + const mem_access_sector_mask_t §or_mask, + unsigned size, bool wr, + unsigned long long cycle) const { + mem_access_t access(type, addr, size, wr, active_mask, byte_mask, + sector_mask, m_memory_config->gpgpu_ctx); + mem_fetch *mf = + new mem_fetch(access, NULL, wr ? WRITE_PACKET_SIZE : READ_PACKET_SIZE, -1, + -1, -1, m_memory_config, cycle); + return mf; +} memory_partition_unit::memory_partition_unit(unsigned partition_id, const memory_config *config, class memory_stats_t *stats, @@ -541,10 +555,15 @@ void memory_sub_partition::cache_cycle(unsigned cycle) { 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, - m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle); - m_L2_icnt_queue->push(mf); + if (mf->get_access_type() == L1_WRBK_ACC) { + m_request_tracker.erase(mf); + delete mf; + } else { + mf->set_reply(); + mf->set_status(IN_PARTITION_L2_TO_ICNT_QUEUE, + m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle); + m_L2_icnt_queue->push(mf); + } } // L2 cache accepted request m_icnt_L2_queue->pop(); @@ -694,53 +713,48 @@ bool memory_sub_partition::busy() const { return !m_request_tracker.empty(); } std::vector<mem_fetch *> memory_sub_partition::breakdown_request_to_sector_requests(mem_fetch *mf) { std::vector<mem_fetch *> result; - + mem_access_sector_mask_t sector_mask = mf->get_access_sector_mask(); if (mf->get_data_size() == SECTOR_SIZE && mf->get_access_sector_mask().count() == 1) { result.push_back(mf); - } else if (mf->get_data_size() == 128 || mf->get_data_size() == 64) { - // We only accept 32, 64 and 128 bytes reqs - unsigned start = 0, end = 0; - if (mf->get_data_size() == 128) { - start = 0; - end = 3; - } else if (mf->get_data_size() == 64 && - mf->get_access_sector_mask().to_string() == "1100") { - start = 2; - end = 3; - } else if (mf->get_data_size() == 64 && - mf->get_access_sector_mask().to_string() == "0011") { - start = 0; - end = 1; - } else if (mf->get_data_size() == 64 && - (mf->get_access_sector_mask().to_string() == "1111" || - mf->get_access_sector_mask().to_string() == "0000")) { - if (mf->get_addr() % 128 == 0) { - start = 0; - end = 1; - } else { - start = 2; - end = 3; + } else if (mf->get_data_size() == 128) { + // break down every sector + mem_access_byte_mask_t mask; + for (unsigned i = 0; i < SECTOR_CHUNCK_SIZE; i++) { + for (unsigned k = i * SECTOR_SIZE; k < (i + 1) * SECTOR_SIZE; k++) { + mask.set(k); } - } else { - printf( - "Invalid sector received, address = 0x%06llx, sector mask = %s, data " - "size = %d", - mf->get_addr(), mf->get_access_sector_mask(), mf->get_data_size()); - assert(0 && "Undefined sector mask is received"); - } + const mem_access_t *ma = new mem_access_t( + mf->get_access_type(), mf->get_addr() + SECTOR_SIZE * i, SECTOR_SIZE, + mf->is_write(), mf->get_access_warp_mask(), + mf->get_access_byte_mask() & mask, + std::bitset<SECTOR_CHUNCK_SIZE>().set(i), m_gpu->gpgpu_ctx); - std::bitset<SECTOR_SIZE * SECTOR_CHUNCK_SIZE> byte_sector_mask; - byte_sector_mask.reset(); - for (unsigned k = start * SECTOR_SIZE; k < SECTOR_SIZE; ++k) - byte_sector_mask.set(k); + mem_fetch *n_mf = + new mem_fetch(*ma, NULL, mf->get_ctrl_size(), mf->get_wid(), + mf->get_sid(), mf->get_tpc(), mf->get_mem_config(), + m_gpu->gpu_tot_sim_cycle + m_gpu->gpu_sim_cycle, mf); - for (unsigned j = start, i = 0; j <= end; ++j, ++i) { + result.push_back(n_mf); + } + } else if (mf->get_data_size() == 64 && + (mf->get_access_sector_mask().to_string() == "1111" || + mf->get_access_sector_mask().to_string() == "0000")) { + unsigned start; + if (mf->get_addr() % 128 == 0) + start = 0; + else + start = 2; + mem_access_byte_mask_t mask; + for (unsigned i = start; i < start + 2; i++) { + for (unsigned k = i * SECTOR_SIZE; k < (i + 1) * SECTOR_SIZE; k++) { + mask.set(k); + } const mem_access_t *ma = new mem_access_t( - mf->get_access_type(), mf->get_addr() + SECTOR_SIZE * i, SECTOR_SIZE, + mf->get_access_type(), mf->get_addr(), SECTOR_SIZE, mf->is_write(), mf->get_access_warp_mask(), - mf->get_access_byte_mask() & byte_sector_mask, - std::bitset<SECTOR_CHUNCK_SIZE>().set(j), m_gpu->gpgpu_ctx); + mf->get_access_byte_mask() & mask, + std::bitset<SECTOR_CHUNCK_SIZE>().set(i), m_gpu->gpgpu_ctx); mem_fetch *n_mf = new mem_fetch(*ma, NULL, mf->get_ctrl_size(), mf->get_wid(), @@ -748,17 +762,30 @@ memory_sub_partition::breakdown_request_to_sector_requests(mem_fetch *mf) { m_gpu->gpu_tot_sim_cycle + m_gpu->gpu_sim_cycle, mf); result.push_back(n_mf); - byte_sector_mask <<= SECTOR_SIZE; } } else { - printf( - "Invalid sector received, address = 0x%06llx, sector mask = %d, byte " - "mask = , data size = %u", - mf->get_addr(), mf->get_access_sector_mask().count(), - mf->get_data_size()); - assert(0 && "Undefined data size is received"); - } + for (unsigned i = 0; i < SECTOR_CHUNCK_SIZE; i++) { + if (sector_mask.test(i)) { + mem_access_byte_mask_t mask; + for (unsigned k = i * SECTOR_SIZE; k < (i + 1) * SECTOR_SIZE; k++) { + mask.set(k); + } + const mem_access_t *ma = new mem_access_t( + mf->get_access_type(), mf->get_addr() + SECTOR_SIZE * i, + SECTOR_SIZE, mf->is_write(), mf->get_access_warp_mask(), + mf->get_access_byte_mask() & mask, + std::bitset<SECTOR_CHUNCK_SIZE>().set(i), m_gpu->gpgpu_ctx); + mem_fetch *n_mf = + new mem_fetch(*ma, NULL, mf->get_ctrl_size(), mf->get_wid(), + mf->get_sid(), mf->get_tpc(), mf->get_mem_config(), + m_gpu->gpu_tot_sim_cycle + m_gpu->gpu_sim_cycle, mf); + + result.push_back(n_mf); + } + } + } + if (result.size() == 0) assert(0 && "no mf sent"); return result; } diff --git a/src/gpgpu-sim/l2cache.h b/src/gpgpu-sim/l2cache.h index 3152db3..1f5d7c4 100644 --- a/src/gpgpu-sim/l2cache.h +++ b/src/gpgpu-sim/l2cache.h @@ -51,6 +51,12 @@ class partition_mf_allocator : public mem_fetch_allocator { virtual mem_fetch *alloc(new_addr_type addr, mem_access_type type, unsigned size, bool wr, unsigned long long cycle) const; + virtual mem_fetch *alloc(new_addr_type addr, mem_access_type type, + const active_mask_t &active_mask, + const mem_access_byte_mask_t &byte_mask, + const mem_access_sector_mask_t §or_mask, + unsigned size, bool wr, + unsigned long long cycle) const; private: const memory_config *m_memory_config; diff --git a/src/gpgpu-sim/shader.cc b/src/gpgpu-sim/shader.cc index 2513dde..db53fca 100644 --- a/src/gpgpu-sim/shader.cc +++ b/src/gpgpu-sim/shader.cc @@ -61,6 +61,21 @@ mem_fetch *shader_core_mem_fetch_allocator::alloc( m_core_id, m_cluster_id, m_memory_config, cycle); return mf; } + +mem_fetch *shader_core_mem_fetch_allocator::alloc( + new_addr_type addr, mem_access_type type, + const active_mask_t &active_mask, + const mem_access_byte_mask_t &byte_mask, + const mem_access_sector_mask_t §or_mask, + unsigned size, bool wr, + unsigned long long cycle) const { + mem_access_t access(type, addr, size, wr, active_mask, byte_mask, + sector_mask, m_memory_config->gpgpu_ctx); + mem_fetch *mf = + new mem_fetch(access, NULL, wr ? WRITE_PACKET_SIZE : READ_PACKET_SIZE, -1, + m_core_id, m_cluster_id, m_memory_config, cycle); + return mf; + } ///////////////////////////////////////////////////////////////////////////// std::list<unsigned> shader_core_ctx::get_regs_written(const inst_t &fvt) const { @@ -1989,6 +2004,19 @@ void ldst_unit::L1_latency_queue_cycle() { } else { assert(status == MISS || status == HIT_RESERVED); l1_latency_queue[j][0] = NULL; + if (m_config->m_L1D_config.get_write_policy() != WRITE_THROUGH && + mf_next->get_inst().is_store() && + (m_config->m_L1D_config.get_write_allocate_policy() == FETCH_ON_WRITE || + m_config->m_L1D_config.get_write_allocate_policy() == LAZY_FETCH_ON_READ) && + !was_writeallocate_sent(events)) { + 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 && !read_sent) delete mf_next; + } } } @@ -3306,50 +3334,64 @@ unsigned int shader_core_config::max_cta(const kernel_info_t &k) const { if (adaptive_cache_config && !k.cache_config_set) { // For more info about adaptive cache, see // https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#shared-memory-7-x - unsigned total_shmed = kernel_info->smem * result; - assert(total_shmed >= 0 && total_shmed <= gpgpu_shmem_size); - // assert(gpgpu_shmem_size == 98304); //Volta has 96 KB shared - // assert(m_L1D_config.get_nset() == 4); //Volta L1 has four sets - if (total_shmed < gpgpu_shmem_size) { - switch (adaptive_cache_config) { - case FIXED: - break; - case ADAPTIVE_VOLTA: { - // For Volta, we assign the remaining shared memory to L1 cache - // For more info about adaptive cache, see - // https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#shared-memory-7-x - // assert(gpgpu_shmem_size == 98304); //Volta has 96 KB shared - - // To Do: make it flexible and not tuned to 9KB share memory - unsigned max_assoc = m_L1D_config.get_max_assoc(); - if (total_shmed == 0) - m_L1D_config.set_assoc(max_assoc); // L1 is 128KB and shd=0 - else if (total_shmed > 0 && total_shmed <= 8192) - m_L1D_config.set_assoc(0.9375 * - max_assoc); // L1 is 120KB and shd=8KB - else if (total_shmed > 8192 && total_shmed <= 16384) - m_L1D_config.set_assoc(0.875 * - max_assoc); // L1 is 112KB and shd=16KB - else if (total_shmed > 16384 && total_shmed <= 32768) - m_L1D_config.set_assoc(0.75 * max_assoc); // L1 is 96KB and - // shd=32KB - else if (total_shmed > 32768 && total_shmed <= 65536) - m_L1D_config.set_assoc(0.5 * max_assoc); // L1 is 64KB and shd=64KB - else if (total_shmed > 65536 && total_shmed <= gpgpu_shmem_size) - m_L1D_config.set_assoc(0.25 * max_assoc); // L1 is 32KB and - // shd=96KB - else - assert(0); - break; + std::vector<unsigned> shmem_list; + for (unsigned i = 0; i < strlen(gpgpu_shmem_option); i++) { + char option[4]; + int j = 0; + while (gpgpu_shmem_option[i] != ',' && i < strlen(gpgpu_shmem_option)) { + if (gpgpu_shmem_option[i] == ' ') { + // skip spaces + i++; + } else { + if (!isdigit(gpgpu_shmem_option[i])) { + // check for non digits, which should not be here + assert(0 && "invalid config: -gpgpu_shmem_option"); + } + option[j] = gpgpu_shmem_option[i]; + j++; + i++; } - default: - assert(0); } + // convert KB -> B + shmem_list.push_back((unsigned)atoi(option) * 1024); + } + + unsigned total_shmem = kernel_info->smem * result; + // Unified cache config is in KB. Converting to B + unsigned total_unified = m_L1D_config.m_unified_cache_size * 1024; + std::sort(shmem_list.begin(), shmem_list.end()); + + assert(total_shmem >= 0 && total_shmem <= shmem_list.back()); + switch (adaptive_cache_config) { + case FIXED: + break; + case ADAPTIVE_CACHE: { + // For more info about adaptive cache, see + bool l1d_configured = false; + unsigned max_assoc = m_L1D_config.get_max_assoc(); - printf("GPGPU-Sim: Reconfigure L1 cache to %uKB\n", - m_L1D_config.get_total_size_inKB()); + if (total_shmem == 0) { + m_L1D_config.set_assoc(max_assoc); + l1d_configured = true; + } else { + for (std::vector<unsigned>::iterator it = shmem_list.begin(); + it < shmem_list.end() - 1; it++) { + if (total_shmem > *it && total_shmem <= *(it + 1)) { + float l1_ratio = 1 - (float) *(it + 1) / total_unified; + m_L1D_config.set_assoc(max_assoc * l1_ratio); + l1d_configured = true; + break; + } + } + } + assert(l1d_configured && "no shared memory option found"); + break; + } + default: + assert(0); } +<<<<<<< HEAD if(m_L1D_config.is_streaming()) { //for streaming cache, if the whole memory is allocated //to the L1 cache, then make the allocation to be on_MISS @@ -3364,6 +3406,10 @@ unsigned int shader_core_config::max_cta(const kernel_info_t &k) const { printf("GPGPU-Sim: Reconfigure L1 allocation to ON_FILL\n"); } } +======= + printf("GPGPU-Sim: Reconfigure L1 cache to %uKB\n", + m_L1D_config.get_total_size_inKB()); +>>>>>>> 2b2b6a2916e4ed833c707be887bf927167a71fa6 k.cache_config_set = true; } diff --git a/src/gpgpu-sim/shader.h b/src/gpgpu-sim/shader.h index 8c02fd7..a7a2c02 100644 --- a/src/gpgpu-sim/shader.h +++ b/src/gpgpu-sim/shader.h @@ -1872,6 +1872,12 @@ class shader_core_mem_fetch_allocator : public mem_fetch_allocator { } mem_fetch *alloc(new_addr_type addr, mem_access_type type, unsigned size, bool wr, unsigned long long cycle) const; + mem_fetch *alloc(new_addr_type addr, mem_access_type type, + const active_mask_t &active_mask, + const mem_access_byte_mask_t &byte_mask, + const mem_access_sector_mask_t §or_mask, + unsigned size, bool wr, + unsigned long long cycle) const; mem_fetch *alloc(const warp_inst_t &inst, const mem_access_t &access, unsigned long long cycle) const { warp_inst_t inst_copy = inst; |
