diff options
| author | JRPan <[email protected]> | 2023-05-10 14:57:09 -0400 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-05-10 14:57:09 -0400 |
| commit | 57aa5ab28bdcb59b32762bd746586824707282eb (patch) | |
| tree | c8ab3b5ed3660283b9f95ec63cb620331aac94a7 /src/gpgpu-sim | |
| parent | da6a16a990a007edb7a760a2eb5b9b48ccc06e4c (diff) | |
| parent | 948c0e1a0e379e37e60c83b9ab622217522aea86 (diff) | |
Merge branch 'dev' into fix_different_latencies_to_same_ex_unit
Diffstat (limited to 'src/gpgpu-sim')
| -rw-r--r-- | src/gpgpu-sim/dram.cc | 27 | ||||
| -rw-r--r-- | src/gpgpu-sim/dram.h | 26 | ||||
| -rw-r--r-- | src/gpgpu-sim/gpu-cache.cc | 247 | ||||
| -rw-r--r-- | src/gpgpu-sim/gpu-cache.h | 225 | ||||
| -rw-r--r-- | src/gpgpu-sim/gpu-sim.cc | 195 | ||||
| -rw-r--r-- | src/gpgpu-sim/gpu-sim.h | 64 | ||||
| -rw-r--r-- | src/gpgpu-sim/l2cache.cc | 162 | ||||
| -rw-r--r-- | src/gpgpu-sim/l2cache.h | 31 | ||||
| -rw-r--r-- | src/gpgpu-sim/power_interface.cc | 457 | ||||
| -rw-r--r-- | src/gpgpu-sim/power_interface.h | 36 | ||||
| -rw-r--r-- | src/gpgpu-sim/power_stat.cc | 468 | ||||
| -rw-r--r-- | src/gpgpu-sim/power_stat.h | 833 | ||||
| -rw-r--r-- | src/gpgpu-sim/shader.cc | 473 | ||||
| -rw-r--r-- | src/gpgpu-sim/shader.h | 521 | ||||
| -rw-r--r-- | src/gpgpu-sim/stat-tool.cc | 2 | ||||
| -rw-r--r-- | src/gpgpu-sim/stat-tool.h | 2 |
16 files changed, 2726 insertions, 1043 deletions
diff --git a/src/gpgpu-sim/dram.cc b/src/gpgpu-sim/dram.cc index ca47c46..662c2ed 100644 --- a/src/gpgpu-sim/dram.cc +++ b/src/gpgpu-sim/dram.cc @@ -1,19 +1,21 @@ -// Copyright (c) 2009-2011, Tor M. Aamodt, Wilson W.L. Fung, Ali Bakhoda, -// Ivan Sham, George L. Yuan, -// The University of British Columbia +// Copyright (c) 2009-2021, Tor M. Aamodt, Wilson W.L. Fung, Ali Bakhoda, +// Ivan Sham, George L. Yuan, Vijay Kandiah, Nikos Hardavellas, +// Mahmoud Khairy, Junrui Pan, Timothy G. Rogers +// The University of British Columbia, Northwestern University, Purdue University // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // -// Redistributions of source code must retain the above copyright notice, this -// list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. Neither the name of -// The University of British Columbia nor the names of its contributors may be -// used to endorse or promote products derived from this software without -// specific prior written permission. +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer; +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution; +// 3. Neither the names of The University of British Columbia, Northwestern +// University nor the names of their contributors may be used to +// endorse or promote products derived from this software without specific +// prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE @@ -855,7 +857,7 @@ void dram_t::visualizer_print(gzFile visualizer_file) { void dram_t::set_dram_power_stats(unsigned &cmd, unsigned &activity, unsigned &nop, unsigned &act, unsigned &pre, - unsigned &rd, unsigned &wr, + unsigned &rd, unsigned &wr, unsigned &wr_WB, unsigned &req) const { // Point power performance counters to low-level DRAM counters cmd = n_cmd; @@ -865,6 +867,7 @@ void dram_t::set_dram_power_stats(unsigned &cmd, unsigned &activity, pre = n_pre; rd = n_rd; wr = n_wr; + wr_WB = n_wr_WB; req = n_req; } diff --git a/src/gpgpu-sim/dram.h b/src/gpgpu-sim/dram.h index 6c212e9..90ea3e4 100644 --- a/src/gpgpu-sim/dram.h +++ b/src/gpgpu-sim/dram.h @@ -1,19 +1,21 @@ -// Copyright (c) 2009-2011, Tor M. Aamodt, Ivan Sham, Ali Bakhoda, -// George L. Yuan, Wilson W.L. Fung -// The University of British Columbia +// Copyright (c) 2009-2021, Tor M. Aamodt, Ivan Sham, Ali Bakhoda, +// George L. Yuan, Wilson W.L. Fung, Vijay Kandiah, Nikos Hardavellas, +// Mahmoud Khairy, Junrui Pan, Timothy G. Rogers +// The University of British Columbia, Northwestern University, Purdue University // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // -// Redistributions of source code must retain the above copyright notice, this -// list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. Neither the name of -// The University of British Columbia nor the names of its contributors may be -// used to endorse or promote products derived from this software without -// specific prior written permission. +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer; +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution; +// 3. Neither the names of The University of British Columbia, Northwestern +// University nor the names of their contributors may be used to +// endorse or promote products derived from this software without specific +// prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE @@ -135,7 +137,7 @@ class dram_t { // Power Model void set_dram_power_stats(unsigned &cmd, unsigned &activity, unsigned &nop, unsigned &act, unsigned &pre, unsigned &rd, - unsigned &wr, unsigned &req) const; + unsigned &wr, unsigned &wr_WB, unsigned &req) const; const memory_config *m_config; diff --git a/src/gpgpu-sim/gpu-cache.cc b/src/gpgpu-sim/gpu-cache.cc index 75c3691..3a5a67d 100644 --- a/src/gpgpu-sim/gpu-cache.cc +++ b/src/gpgpu-sim/gpu-cache.cc @@ -1,18 +1,21 @@ -// Copyright (c) 2009-2011, Tor M. Aamodt, Tayler Hetherington -// The University of British Columbia +// Copyright (c) 2009-2021, Tor M. Aamodt, Tayler Hetherington, +// Vijay Kandiah, Nikos Hardavellas, Mahmoud Khairy, Junrui Pan, +// Timothy G. Rogers +// The University of British Columbia, Northwestern University, Purdue University // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // -// Redistributions of source code must retain the above copyright notice, this -// list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. Neither the name of -// The University of British Columbia nor the names of its contributors may be -// used to endorse or promote products derived from this software without -// specific prior written permission. +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer; +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution; +// 3. Neither the names of The University of British Columbia, Northwestern +// University nor the names of their contributors may be used to +// endorse or promote products derived from this software without specific +// prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE @@ -37,7 +40,8 @@ const char *cache_request_status_str(enum cache_request_status status) { static const char *static_cache_request_status_str[] = { - "HIT", "HIT_RESERVED", "MISS", "RESERVATION_FAIL", "SECTOR_MISS"}; + "HIT", "HIT_RESERVED", "MISS", "RESERVATION_FAIL", + "SECTOR_MISS", "MSHR_HIT"}; assert(sizeof(static_cache_request_status_str) / sizeof(const char *) == NUM_CACHE_REQUEST_STATUS); @@ -63,9 +67,9 @@ unsigned l1d_cache_config::set_bank(new_addr_type addr) const { // For sector cache, we select one sector per bank (sector interleaving) // This is what was found in Volta (one sector per bank, sector interleaving) // otherwise, line interleaving - return cache_config::hash_function(addr, l1_banks, l1_banks_byte_interleaving, - m_l1_banks_log2, - l1_banks_hashing_function); + return cache_config::hash_function(addr, l1_banks, + l1_banks_byte_interleaving_log2, + l1_banks_log2, l1_banks_hashing_function); } unsigned cache_config::set_index(new_addr_type addr) const { @@ -210,6 +214,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 +236,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 +255,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 +267,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 +283,31 @@ 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 the cacheline is from a load op (not modified), + // or the total dirty cacheline is above a specific value, + // Then this cacheline is eligible to be considered for replacement candidate + // i.e. Only evict clean cachelines until total dirty cachelines reach the limit. + if (!line->is_modified_line() || + dirty_line_percentage >= m_config.m_wr_percent) { + 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; + } } } } @@ -312,15 +327,6 @@ enum cache_request_status tag_array::probe(new_addr_type addr, unsigned &idx, abort(); // if an unreserved block exists, it is either invalid or // replaceable - if (probe_mode && m_config.is_streaming()) { - line_table::const_iterator i = - pending_lines.find(m_config.block_addr(addr)); - assert(mf); - if (!mf->is_write() && i != pending_lines.end()) { - if (i->second != mf->get_inst().get_uid()) return SECTOR_MISS; - } - } - return MISS; } @@ -340,7 +346,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++; @@ -353,8 +359,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()); @@ -365,8 +375,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: @@ -383,31 +397,45 @@ 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()); + bool before = m_lines[index]->is_modified_line(); + m_lines[index]->fill(time, mf->get_access_sector_mask(), mf->get_access_byte_mask()); + if (m_lines[index]->is_modified_line() && !before) { + m_dirty++; + } } // TODO: we need write back the flushed data to the upper level @@ -416,10 +444,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; } @@ -430,6 +460,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; } @@ -485,8 +516,10 @@ bool was_writeback_sent(const std::list<cache_event> &events, cache_event &wb_event) { for (std::list<cache_event>::const_iterator e = events.begin(); e != events.end(); e++) { - if ((*e).m_cache_event_type == WRITE_BACK_REQUEST_SENT) wb_event = *e; - return true; + if ((*e).m_cache_event_type == WRITE_BACK_REQUEST_SENT) { + wb_event = *e; + return true; + } } return false; } @@ -612,6 +645,7 @@ void cache_stats::clear() { /// for (unsigned i = 0; i < NUM_MEM_ACCESS_TYPE; ++i) { std::fill(m_stats[i].begin(), m_stats[i].end(), 0); + std::fill(m_stats_pw[i].begin(), m_stats_pw[i].end(), 0); std::fill(m_fail_stats[i].begin(), m_fail_stats[i].end(), 0); } m_cache_port_available_cycles = 0; @@ -771,7 +805,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]; } } @@ -1057,8 +1093,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); - if (m_config.is_streaming()) m_tag_array->remove_pending_line(mf); + m_tag_array->fill(e->second.m_block_addr, time, mf, mf->is_write()); } else abort(); bool has_atomic = false; @@ -1066,9 +1101,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); @@ -1123,6 +1162,7 @@ void baseline_cache::send_read_request(new_addr_type addr, m_tag_array->access(block_addr, time, cache_index, wb, evicted, mf); m_mshrs.add(mshr_addr, mf); + m_stats.inc_stats(mf->get_access_type(), MSHR_HIT); do_miss = true; } else if (!mshr_hit && mshr_avail && @@ -1133,9 +1173,6 @@ void baseline_cache::send_read_request(new_addr_type addr, m_tag_array->access(block_addr, time, cache_index, wb, evicted, mf); m_mshrs.add(mshr_addr, mf); - if (m_config.is_streaming() && m_config.m_cache_type == SECTOR) { - m_tag_array->add_pending_line(mf); - } m_extra_mf_fields[mf] = extra_mf_fields( mshr_addr, mf->get_addr(), cache_index, mf->get_data_size(), m_config); mf->set_data_size(m_config.get_atom_sz()); @@ -1162,6 +1199,25 @@ void data_cache::send_write_request(mem_fetch *mf, cache_event request, mf->set_status(m_miss_queue_status, time); } +void data_cache::update_m_readable(mem_fetch *mf, unsigned cache_index) { + cache_block_t *block = m_tag_array->get_block(cache_index); + for (unsigned i = 0; i < SECTOR_CHUNCK_SIZE; i++) { + if (mf->get_access_sector_mask().test(i)) { + bool all_set = true; + for (unsigned k = i * SECTOR_SIZE; k < (i + 1) * SECTOR_SIZE; k++) { + // If any bit in the byte mask (within the sector) is not set, + // the sector is unreadble + if (!block->get_dirty_byte_mask().test(k)) { + all_set = false; + break; + } + } + if (all_set) + block->set_m_readable(true, mf->get_access_sector_mask()); + } + } +} + /****** Write-hit functions (Set by config file) ******/ /// Write-back hit: Mark block as modified @@ -1173,7 +1229,12 @@ 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); + update_m_readable(mf,cache_index); return HIT; } @@ -1192,7 +1253,12 @@ 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); + update_m_readable(mf,cache_index); // generate a write-through send_write_request(mf, cache_event(WRITE_REQUEST_SENT), time, events); @@ -1302,8 +1368,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, -1, -1, -1, + NULL); // 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); @@ -1340,7 +1408,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()); @@ -1349,8 +1421,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, -1, -1, -1, + NULL); // 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); @@ -1411,6 +1485,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)); @@ -1419,8 +1494,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, -1, -1, -1, + NULL); // 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); @@ -1448,6 +1525,10 @@ enum cache_request_status data_cache::wr_miss_wa_lazy_fetch_on_read( return RESERVATION_FAIL; // cannot handle request this cycle } + if (m_config.m_write_policy == WRITE_THROUGH) { + send_write_request(mf, cache_event(WRITE_REQUEST_SENT), time, events); + } + bool wb = false; evicted_block_info evicted; @@ -1455,25 +1536,35 @@ 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()); + block->set_byte_mask_on_fill(true); } 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 == HIT_RESERVED) + block->set_readable_on_fill(true, mf->get_access_sector_mask()); } + update_m_readable(mf,cache_index); 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, - 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, -1, -1, -1, + NULL); // 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); @@ -1516,8 +1607,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; } @@ -1548,8 +1643,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, -1, -1, -1, + NULL); // 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); @@ -1572,7 +1669,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) { @@ -1659,7 +1756,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 5c28b41..4bbf7e2 100644 --- a/src/gpgpu-sim/gpu-cache.h +++ b/src/gpgpu-sim/gpu-cache.h @@ -1,18 +1,20 @@ -// Copyright (c) 2009-2011, Tor M. Aamodt, Tayler Hetherington -// The University of British Columbia +// Copyright (c) 2009-2021, Tor M. Aamodt, Tayler Hetherington, Vijay Kandiah, Nikos Hardavellas, +// Mahmoud Khairy, Junrui Pan, Timothy G. Rogers +// The University of British Columbia, Northwestern University, Purdue University // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // -// Redistributions of source code must retain the above copyright notice, this -// list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. Neither the name of -// The University of British Columbia nor the names of its contributors may be -// used to endorse or promote products derived from this software without -// specific prior written permission. +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer; +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution; +// 3. Neither the names of The University of British Columbia, Northwestern +// University nor the names of their contributors may be used to +// endorse or promote products derived from this software without specific +// prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE @@ -49,6 +51,7 @@ enum cache_request_status { MISS, RESERVATION_FAIL, SECTOR_MISS, + MSHR_HIT, NUM_CACHE_REQUEST_STATUS }; @@ -71,14 +74,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 { @@ -108,7 +123,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; @@ -119,7 +135,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; @@ -128,6 +147,9 @@ struct cache_block_t { mem_access_sector_mask_t sector_mask) = 0; virtual void set_modified_on_fill(bool m_modified, mem_access_sector_mask_t sector_mask) = 0; + virtual 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; @@ -147,6 +169,7 @@ struct line_cache_block : public cache_block_t { m_status = INVALID; m_ignore_on_fill_status = false; m_set_modified_on_fill = false; + m_set_readable_on_fill = false; m_readable = true; } void allocate(new_addr_type tag, new_addr_type block_addr, unsigned time, @@ -159,13 +182,19 @@ struct line_cache_block : public cache_block_t { m_status = RESERVED; 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 ); m_status = m_set_modified_on_fill ? MODIFIED : VALID; + 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; } virtual bool is_invalid_line() { return m_status == INVALID; } @@ -181,6 +210,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_dirty_byte_mask = m_dirty_byte_mask | mf->get_access_byte_mask(); + } + virtual void set_byte_mask(mem_access_byte_mask_t byte_mask) { + m_dirty_byte_mask = m_dirty_byte_mask | byte_mask; + } + virtual mem_access_byte_mask_t get_dirty_byte_mask() { + return m_dirty_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; } @@ -197,6 +240,13 @@ struct line_cache_block : public cache_block_t { mem_access_sector_mask_t sector_mask) { m_set_modified_on_fill = m_modified; } + virtual void set_readable_on_fill(bool readable, + 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 } @@ -218,7 +268,10 @@ struct line_cache_block : public cache_block_t { cache_block_state m_status; 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_dirty_byte_mask; }; struct sector_cache_block : public cache_block_t { @@ -232,11 +285,13 @@ struct sector_cache_block : public cache_block_t { m_status[i] = INVALID; m_ignore_on_fill_status[i] = false; m_set_modified_on_fill[i] = false; + m_set_readable_on_fill[i] = false; m_readable[i] = true; } m_line_alloc_time = 0; m_line_last_access_time = 0; m_line_fill_time = 0; + m_dirty_byte_mask.reset(); } virtual void allocate(new_addr_type tag, new_addr_type block_addr, @@ -261,6 +316,8 @@ struct sector_cache_block : public cache_block_t { m_status[sidx] = RESERVED; 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 @@ -283,6 +340,8 @@ struct sector_cache_block : public cache_block_t { else m_set_modified_on_fill[sidx] = false; + m_set_readable_on_fill[sidx] = false; + m_status[sidx] = RESERVED; m_ignore_on_fill_status[sidx] = false; // m_set_modified_on_fill[sidx] = false; @@ -293,14 +352,20 @@ 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; } @@ -340,6 +405,22 @@ struct sector_cache_block : public cache_block_t { m_status[sidx] = status; } + virtual void set_byte_mask(mem_fetch *mf) { + m_dirty_byte_mask = m_dirty_byte_mask | mf->get_access_byte_mask(); + } + virtual void set_byte_mask(mem_access_byte_mask_t byte_mask) { + m_dirty_byte_mask = m_dirty_byte_mask | byte_mask; + } + virtual mem_access_byte_mask_t get_dirty_byte_mask() { + return m_dirty_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; } @@ -365,7 +446,15 @@ struct sector_cache_block : public cache_block_t { unsigned sidx = get_sector_index(sector_mask); m_set_modified_on_fill[sidx] = m_modified; } + virtual void set_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) { + unsigned sidx = get_sector_index(sector_mask); + m_set_readable_on_fill[sidx] = readable; + } virtual void set_m_readable(bool readable, mem_access_sector_mask_t sector_mask) { unsigned sidx = get_sector_index(sector_mask); @@ -400,7 +489,10 @@ struct sector_cache_block : public cache_block_t { cache_block_state m_status[SECTOR_CHUNCK_SIZE]; bool m_ignore_on_fill_status[SECTOR_CHUNCK_SIZE]; bool m_set_modified_on_fill[SECTOR_CHUNCK_SIZE]; + bool m_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_dirty_byte_mask; unsigned get_sector_index(mem_access_sector_mask_t sector_mask) { assert(sector_mask.count() == 1); @@ -463,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; @@ -503,16 +596,6 @@ class cache_config { default: exit_parse_error(); } - switch (rp) { - case 'L': - m_replacement_policy = LRU; - break; - case 'F': - m_replacement_policy = FIFO; - break; - default: - exit_parse_error(); - } switch (wp) { case 'R': m_write_policy = READ_ONLY; @@ -546,22 +629,27 @@ class cache_config { 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 max - // allocated cache lines. This is possible by moving TAG to be shared - // between cache line and MSHR enrty (i.e. for each cache line, there is - // an MSHR rntey associated with it) This is the easiest think we can - // think about to model (mimic) L1 streaming cache in Pascal and Volta - // Based on our microbenchmakrs, MSHRs entries have been increasing - // substantially in Pascal and Volta For more information about streaming - // cache, see: - // http://on-demand.gputechconf.com/gtc/2017/presentation/s7798-luke-durant-inside-volta.pdf - // https://ieeexplore.ieee.org/document/8344474/ + /* + For streaming cache: + (1) we set the alloc policy to be on-fill to remove all line_alloc_fail + stalls. if the whole memory is allocated to the L1 cache, then make the + allocation to be on_MISS otherwise, make it ON_FILL to eliminate line + allocation fails. i.e. MSHR throughput is the same, independent on the L1 + cache size/associativity So, we set the allocation policy per kernel + basis, see shader.cc, max_cta() function + + (2) We also set the MSHRs to be equal to max + allocated cache lines. This is possible by moving TAG to be shared + between cache line and MSHR enrty (i.e. for each cache line, there is + an MSHR rntey associated with it). This is the easiest think we can + think of to model (mimic) L1 streaming cache 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_is_streaming = true; m_alloc_policy = ON_FILL; - m_mshr_entries = m_nset * m_assoc * MAX_DEFAULT_CACHE_SIZE_MULTIBLIER; - if (m_cache_type == SECTOR) m_mshr_entries *= SECTOR_CHUNCK_SIZE; - m_mshr_max_merge = MAX_WARP_PER_SM; } switch (mshr_type) { case 'F': @@ -610,7 +698,8 @@ class cache_config { } // detect invalid configuration - if (m_alloc_policy == ON_FILL and m_write_policy == WRITE_BACK) { + if ((m_alloc_policy == ON_FILL || m_alloc_policy == STREAMING) and + m_write_policy == WRITE_BACK) { // A writeback cache with allocate-on-fill policy will inevitably lead to // deadlock: The deadlock happens when an incoming cache-fill evicts a // dirty line, generating a writeback request. If the memory subsystem is @@ -656,6 +745,9 @@ class cache_config { case 'L': m_set_index_function = LINEAR_SET_FUNCTION; break; + case 'X': + m_set_index_function = BITWISE_XORING_FUNCTION; + break; default: exit_parse_error(); } @@ -675,11 +767,11 @@ class cache_config { } unsigned get_max_num_lines() const { assert(m_valid); - return MAX_DEFAULT_CACHE_SIZE_MULTIBLIER * m_nset * original_m_assoc; + return get_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; + return get_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", @@ -688,6 +780,10 @@ class cache_config { virtual unsigned set_index(new_addr_type addr) const; + virtual unsigned get_max_cache_multiplier() const { + return MAX_DEFAULT_CACHE_SIZE_MULTIBLIER; + } + unsigned hash_function(new_addr_type addr, unsigned m_nset, unsigned m_line_sz_log2, unsigned m_nset_log2, unsigned m_index_function) const; @@ -722,10 +818,18 @@ class cache_config { } bool is_streaming() { return m_is_streaming; } FuncCache get_cache_status() { return cache_status; } + void set_allocation_policy(enum allocation_policy_t alloc) { + m_alloc_policy = alloc; + } char *m_config_string; char *m_config_stringPrefL1; char *m_config_stringPrefShared; FuncCache cache_status; + unsigned m_wr_percent; + 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() { @@ -789,16 +893,28 @@ class l1d_cache_config : public cache_config { l1d_cache_config() : cache_config() {} unsigned set_bank(new_addr_type addr) const; void init(char *config, FuncCache status) { - m_banks_byte_interleaving_log2 = LOGB2(l1_banks_byte_interleaving); - m_l1_banks_log2 = LOGB2(l1_banks); + l1_banks_byte_interleaving_log2 = LOGB2(l1_banks_byte_interleaving); + l1_banks_log2 = LOGB2(l1_banks); cache_config::init(config, status); } unsigned l1_latency; unsigned l1_banks; - unsigned m_l1_banks_log2; + unsigned l1_banks_log2; unsigned l1_banks_byte_interleaving; - unsigned m_banks_byte_interleaving_log2; + unsigned l1_banks_byte_interleaving_log2; unsigned l1_banks_hashing_function; + unsigned m_unified_cache_size; + virtual unsigned get_max_cache_multiplier() const { + // set * assoc * cacheline size. Then convert Byte to KB + // gpgpu_unified_cache_size is in KB while original_sz is in B + if (m_unified_cache_size > 0) { + unsigned original_size = m_nset * original_m_assoc * m_line_sz / 1024; + assert(m_unified_cache_size % original_size == 0); + return m_unified_cache_size / original_size; + } else { + return MAX_DEFAULT_CACHE_SIZE_MULTIBLIER; + } + } }; class l2_cache_config : public cache_config { @@ -818,9 +934,10 @@ 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, + 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, @@ -829,9 +946,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]; } @@ -849,6 +967,7 @@ 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 @@ -869,6 +988,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 @@ -1214,7 +1334,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: @@ -1451,7 +1572,7 @@ class data_cache : public baseline_cache { /// Sends write request to lower level memory (write or writeback) void send_write_request(mem_fetch *mf, cache_event request, unsigned time, std::list<cache_event> &events); - + void update_m_readable(mem_fetch *mf, unsigned cache_index); // Member Function pointers - Set by configuration options // to the functions below each grouping /******* Write-hit configs *******/ diff --git a/src/gpgpu-sim/gpu-sim.cc b/src/gpgpu-sim/gpu-sim.cc index 1650688..5af244b 100644 --- a/src/gpgpu-sim/gpu-sim.cc +++ b/src/gpgpu-sim/gpu-sim.cc @@ -1,19 +1,21 @@ -// Copyright (c) 2009-2011, Tor M. Aamodt, Wilson W.L. Fung, George L. Yuan, -// Ali Bakhoda, Andrew Turner, Ivan Sham -// The University of British Columbia +// Copyright (c) 2009-2021, Tor M. Aamodt, Wilson W.L. Fung, George L. Yuan, +// Ali Bakhoda, Andrew Turner, Ivan Sham, Vijay Kandiah, Nikos Hardavellas, +// Mahmoud Khairy, Junrui Pan, Timothy G. Rogers +// The University of British Columbia, Northwestern University, Purdue University // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // -// Redistributions of source code must retain the above copyright notice, this -// list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. Neither the name of -// The University of British Columbia nor the names of its contributors may be -// used to endorse or promote products derived from this software without -// specific prior written permission. +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer; +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution; +// 3. Neither the names of The University of British Columbia, Northwestern +// University nor the names of their contributors may be used to +// endorse or promote products derived from this software without specific +// prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE @@ -95,10 +97,11 @@ tr1_hash_map<new_addr_type, unsigned> address_random_interleaving; #include "mem_latency_stat.h" + void power_config::reg_options(class OptionParser *opp) { - option_parser_register(opp, "-gpuwattch_xml_file", OPT_CSTR, - &g_power_config_name, "GPUWattch XML file", - "gpuwattch.xml"); + option_parser_register(opp, "-accelwattch_xml_file", OPT_CSTR, + &g_power_config_name, "AccelWattch XML file", + "accelwattch_sass_sim.xml"); option_parser_register(opp, "-power_simulation_enabled", OPT_BOOL, &g_power_simulation_enabled, @@ -108,6 +111,92 @@ void power_config::reg_options(class OptionParser *opp) { &g_power_per_cycle_dump, "Dump detailed power output each cycle", "0"); + + + + option_parser_register(opp, "-hw_perf_file_name", OPT_CSTR, + &g_hw_perf_file_name, "Hardware Performance Statistics file", + "hw_perf.csv"); + + option_parser_register(opp, "-hw_perf_bench_name", OPT_CSTR, + &g_hw_perf_bench_name, "Kernel Name in Hardware Performance Statistics file", + ""); + + option_parser_register(opp, "-power_simulation_mode", OPT_INT32, + &g_power_simulation_mode, + "Switch performance counter input for power simulation (0=Sim, 1=HW, 2=HW-Sim Hybrid)", "0"); + + option_parser_register(opp, "-dvfs_enabled", OPT_BOOL, + &g_dvfs_enabled, + "Turn on DVFS for power model", "0"); + option_parser_register(opp, "-aggregate_power_stats", OPT_BOOL, + &g_aggregate_power_stats, + "Accumulate power across all kernels", "0"); + + //Accelwattch Hyrbid Configuration + + option_parser_register(opp, "-accelwattch_hybrid_perfsim_L1_RH", OPT_BOOL, + &accelwattch_hybrid_configuration[HW_L1_RH], + "Get L1 Read Hits for Accelwattch-Hybrid from Accel-Sim", "0"); + option_parser_register(opp, "-accelwattch_hybrid_perfsim_L1_RM", OPT_BOOL, + &accelwattch_hybrid_configuration[HW_L1_RM], + "Get L1 Read Misses for Accelwattch-Hybrid from Accel-Sim", "0"); + option_parser_register(opp, "-accelwattch_hybrid_perfsim_L1_WH", OPT_BOOL, + &accelwattch_hybrid_configuration[HW_L1_WH], + "Get L1 Write Hits for Accelwattch-Hybrid from Accel-Sim", "0"); + option_parser_register(opp, "-accelwattch_hybrid_perfsim_L1_WM", OPT_BOOL, + &accelwattch_hybrid_configuration[HW_L1_WM], + "Get L1 Write Misses for Accelwattch-Hybrid from Accel-Sim", "0"); + + option_parser_register(opp, "-accelwattch_hybrid_perfsim_L2_RH", OPT_BOOL, + &accelwattch_hybrid_configuration[HW_L2_RH], + "Get L2 Read Hits for Accelwattch-Hybrid from Accel-Sim", "0"); + option_parser_register(opp, "-accelwattch_hybrid_perfsim_L2_RM", OPT_BOOL, + &accelwattch_hybrid_configuration[HW_L2_RM], + "Get L2 Read Misses for Accelwattch-Hybrid from Accel-Sim", "0"); + option_parser_register(opp, "-accelwattch_hybrid_perfsim_L2_WH", OPT_BOOL, + &accelwattch_hybrid_configuration[HW_L2_WH], + "Get L2 Write Hits for Accelwattch-Hybrid from Accel-Sim", "0"); + option_parser_register(opp, "-accelwattch_hybrid_perfsim_L2_WM", OPT_BOOL, + &accelwattch_hybrid_configuration[HW_L2_WM], + "Get L2 Write Misses for Accelwattch-Hybrid from Accel-Sim", "0"); + + option_parser_register(opp, "-accelwattch_hybrid_perfsim_CC_ACC", OPT_BOOL, + &accelwattch_hybrid_configuration[HW_CC_ACC], + "Get Constant Cache Acesses for Accelwattch-Hybrid from Accel-Sim", "0"); + + option_parser_register(opp, "-accelwattch_hybrid_perfsim_SHARED_ACC", OPT_BOOL, + &accelwattch_hybrid_configuration[HW_SHRD_ACC], + "Get Shared Memory Acesses for Accelwattch-Hybrid from Accel-Sim", "0"); + + option_parser_register(opp, "-accelwattch_hybrid_perfsim_DRAM_RD", OPT_BOOL, + &accelwattch_hybrid_configuration[HW_DRAM_RD], + "Get DRAM Reads for Accelwattch-Hybrid from Accel-Sim", "0"); + option_parser_register(opp, "-accelwattch_hybrid_perfsim_DRAM_WR", OPT_BOOL, + &accelwattch_hybrid_configuration[HW_DRAM_WR], + "Get DRAM Writes for Accelwattch-Hybrid from Accel-Sim", "0"); + + option_parser_register(opp, "-accelwattch_hybrid_perfsim_NOC", OPT_BOOL, + &accelwattch_hybrid_configuration[HW_NOC], + "Get Interconnect Acesses for Accelwattch-Hybrid from Accel-Sim", "0"); + + option_parser_register(opp, "-accelwattch_hybrid_perfsim_PIPE_DUTY", OPT_BOOL, + &accelwattch_hybrid_configuration[HW_PIPE_DUTY], + "Get Pipeline Duty Cycle Acesses for Accelwattch-Hybrid from Accel-Sim", "0"); + + option_parser_register(opp, "-accelwattch_hybrid_perfsim_NUM_SM_IDLE", OPT_BOOL, + &accelwattch_hybrid_configuration[HW_NUM_SM_IDLE], + "Get Number of Idle SMs for Accelwattch-Hybrid from Accel-Sim", "0"); + + option_parser_register(opp, "-accelwattch_hybrid_perfsim_CYCLES", OPT_BOOL, + &accelwattch_hybrid_configuration[HW_CYCLES], + "Get Executed Cycles for Accelwattch-Hybrid from Accel-Sim", "0"); + + option_parser_register(opp, "-accelwattch_hybrid_perfsim_VOLTAGE", OPT_BOOL, + &accelwattch_hybrid_configuration[HW_VOLTAGE], + "Get Chip Voltage for Accelwattch-Hybrid from Accel-Sim", "0"); + + // Output Data Formats option_parser_register( opp, "-power_trace_enabled", OPT_BOOL, &g_power_trace_enabled, @@ -249,6 +338,8 @@ 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"); @@ -304,7 +395,7 @@ void shader_core_config::reg_options(class OptionParser *opp) { "gpgpu_ignore_resources_limitation (default 0)", "0"); option_parser_register( opp, "-gpgpu_shader_cta", OPT_UINT32, &max_cta_per_core, - "Maximum number of concurrent CTAs in shader (default 8)", "8"); + "Maximum number of concurrent CTAs in shader (default 32)", "32"); option_parser_register( opp, "-gpgpu_num_cta_barriers", OPT_UINT32, &max_barriers_per_cta, "Maximum number of named barriers per CTA (default 16)", "16"); @@ -326,7 +417,14 @@ 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_adaptive_cache_config", OPT_UINT32, + 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( opp, "-gpgpu_shmem_sizeDefault", OPT_UINT32, &gpgpu_shmem_sizeDefault, @@ -603,7 +701,8 @@ void gpgpu_sim_config::reg_options(option_parser_t opp) { "500.0:2000.0:2000.0:2000.0"); option_parser_register( opp, "-gpgpu_max_concurrent_kernel", OPT_INT32, &max_concurrent_kernel, - "maximum kernels that can run concurrently on GPU", "8"); + "maximum kernels that can run concurrently on GPU, set this value " + "according to max resident grids for your compute capability", "32"); option_parser_register( opp, "-gpgpu_cflog_interval", OPT_INT32, &gpgpu_cflog_interval, "Interval between each snapshot in control flow logger", "0"); @@ -826,7 +925,7 @@ gpgpu_sim::gpgpu_sim(const gpgpu_sim_config &config, gpgpu_context *ctx) #ifdef GPGPUSIM_POWER_MODEL m_gpgpusim_wrapper = new gpgpu_sim_wrapper(config.g_power_simulation_enabled, - config.g_power_config_name); + config.g_power_config_name, config.g_power_simulation_mode, config.g_dvfs_enabled); #endif m_shader_stats = new shader_core_stats(m_shader_config); @@ -1001,6 +1100,14 @@ void gpgpu_sim::init() { partiton_reqs_in_parallel_util = 0; gpu_sim_cycle_parition_util = 0; +// McPAT initialization function. Called on first launch of GPU +#ifdef GPGPUSIM_POWER_MODEL + if (m_config.g_power_simulation_enabled) { + init_mcpat(m_config, m_gpgpusim_wrapper, m_config.gpu_stat_sample_freq, + gpu_tot_sim_insn, gpu_sim_insn); + } +#endif + reinit_clock_domains(); gpgpu_ctx->func_sim->set_param_gpgpu_num_shaders(m_config.num_shader()); for (unsigned i = 0; i < m_shader_config->n_simt_clusters; i++) @@ -1026,14 +1133,6 @@ void gpgpu_sim::init() { } if (g_network_mode) icnt_init(); - - // McPAT initialization function. Called on first launch of GPU -#ifdef GPGPUSIM_POWER_MODEL - if (m_config.g_power_simulation_enabled) { - init_mcpat(m_config, m_gpgpusim_wrapper, m_config.gpu_stat_sample_freq, - gpu_tot_sim_insn, gpu_sim_insn); - } -#endif } void gpgpu_sim::update_stats() { @@ -1058,6 +1157,11 @@ void gpgpu_sim::update_stats() { gpu_occupancy = occupancy_stats(); } +PowerscalingCoefficients *gpgpu_sim::get_scaling_coeffs() +{ + return m_gpgpusim_wrapper->get_scaling_coeffs(); +} + void gpgpu_sim::print_stats() { gpgpu_ctx->stats->ptx_file_line_stats_write_file(); gpu_print_stat(); @@ -1137,6 +1241,18 @@ std::string gpgpu_sim::executed_kernel_info_string() { return statout.str(); } + +std::string gpgpu_sim::executed_kernel_name() { + std::stringstream statout; + if( m_executed_kernel_names.size() == 1) + statout << m_executed_kernel_names[0]; + else{ + for (unsigned int k = 0; k < m_executed_kernel_names.size(); k++) { + statout << m_executed_kernel_names[k] << " "; + } + } + return statout.str(); +} void gpgpu_sim::set_cache_config(std::string kernel_name, FuncCache cacheConfig) { m_special_cache_config[kernel_name] = cacheConfig; @@ -1317,10 +1433,20 @@ void gpgpu_sim::gpu_print_stat() { m_shader_stats->print(stdout); #ifdef GPGPUSIM_POWER_MODEL if (m_config.g_power_simulation_enabled) { + if(m_config.g_power_simulation_mode > 0){ + //if(!m_config.g_aggregate_power_stats) + mcpat_reset_perf_count(m_gpgpusim_wrapper); + calculate_hw_mcpat(m_config, getShaderCoreConfig(), m_gpgpusim_wrapper, + m_power_stats, m_config.gpu_stat_sample_freq, + gpu_tot_sim_cycle, gpu_sim_cycle, gpu_tot_sim_insn, + gpu_sim_insn, m_config.g_power_simulation_mode, m_config.g_dvfs_enabled, + m_config.g_hw_perf_file_name, m_config.g_hw_perf_bench_name, executed_kernel_name(), m_config.accelwattch_hybrid_configuration, m_config.g_aggregate_power_stats); + } m_gpgpusim_wrapper->print_power_kernel_stats( gpu_sim_cycle, gpu_tot_sim_cycle, gpu_tot_sim_insn + gpu_sim_insn, kernel_info_str, true); - mcpat_reset_perf_count(m_gpgpusim_wrapper); + //if(!m_config.g_aggregate_power_stats) + mcpat_reset_perf_count(m_gpgpusim_wrapper); } #endif @@ -1514,9 +1640,9 @@ bool shader_core_ctx::occupy_shader_resource_1block(kernel_info_t &k, SHADER_DPRINTF(LIVENESS, "GPGPU-Sim uArch: Occupied %u threads, %u shared mem, %u " - "registers, %u ctas\n", + "registers, %u ctas, on shader %d\n", m_occupied_n_threads, m_occupied_shmem, m_occupied_regs, - m_occupied_ctas); + m_occupied_ctas, m_sid); } return true; @@ -1682,9 +1808,9 @@ void shader_core_ctx::issue_block2core(kernel_info_t &kernel) { shader_CTA_count_log(m_sid, 1); SHADER_DPRINTF(LIVENESS, "GPGPU-Sim uArch: cta:%2u, start_tid:%4u, end_tid:%4u, " - "initialized @(%lld,%lld)\n", + "initialized @(%lld,%lld), kernel_uid:%u, kernel_name:%s\n", free_cta_hw_id, start_thread, end_thread, m_gpu->gpu_sim_cycle, - m_gpu->gpu_tot_sim_cycle); + m_gpu->gpu_tot_sim_cycle, kernel.get_uid(), kernel.get_name().c_str()); } /////////////////////////////////////////////////////////////////////////////////////////// @@ -1787,6 +1913,7 @@ void gpgpu_sim::cycle() { m_power_stats->pwr_mem_stat->n_pre[CURRENT_STAT_IDX][i], m_power_stats->pwr_mem_stat->n_rd[CURRENT_STAT_IDX][i], m_power_stats->pwr_mem_stat->n_wr[CURRENT_STAT_IDX][i], + m_power_stats->pwr_mem_stat->n_wr_WB[CURRENT_STAT_IDX][i], m_power_stats->pwr_mem_stat->n_req[CURRENT_STAT_IDX][i]); } } @@ -1830,7 +1957,7 @@ void gpgpu_sim::cycle() { m_cluster[i]->core_cycle(); *active_sms += m_cluster[i]->get_n_active_sms(); } - // Update core icnt/cache stats for GPUWattch + // Update core icnt/cache stats for AccelWattch m_cluster[i]->get_icnt_stats( m_power_stats->pwr_mem_stat->n_simt_to_mem[CURRENT_STAT_IDX][i], m_power_stats->pwr_mem_stat->n_mem_to_simt[CURRENT_STAT_IDX][i]); @@ -1860,10 +1987,12 @@ void gpgpu_sim::cycle() { // McPAT main cycle (interface with McPAT) #ifdef GPGPUSIM_POWER_MODEL if (m_config.g_power_simulation_enabled) { + if(m_config.g_power_simulation_mode == 0){ mcpat_cycle(m_config, getShaderCoreConfig(), m_gpgpusim_wrapper, m_power_stats, m_config.gpu_stat_sample_freq, gpu_tot_sim_cycle, gpu_sim_cycle, gpu_tot_sim_insn, - gpu_sim_insn); + gpu_sim_insn, m_config.g_dvfs_enabled); + } } #endif diff --git a/src/gpgpu-sim/gpu-sim.h b/src/gpgpu-sim/gpu-sim.h index 2e6820d..de69ef8 100644 --- a/src/gpgpu-sim/gpu-sim.h +++ b/src/gpgpu-sim/gpu-sim.h @@ -1,18 +1,20 @@ -// Copyright (c) 2009-2011, Tor M. Aamodt, Wilson W.L. Fung -// The University of British Columbia +// Copyright (c) 2009-2021, Tor M. Aamodt, Wilson W.L. Fung, Vijay Kandiah, Nikos Hardavellas +// Mahmoud Khairy, Junrui Pan, Timothy G. Rogers +// The University of British Columbia, Northwestern University, Purdue University // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // -// Redistributions of source code must retain the above copyright notice, this -// list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. Neither the name of -// The University of British Columbia nor the names of its contributors may be -// used to endorse or promote products derived from this software without -// specific prior written permission. +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer; +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution; +// 3. Neither the names of The University of British Columbia, Northwestern +// University nor the names of their contributors may be used to +// endorse or promote products derived from this software without specific +// prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE @@ -26,6 +28,7 @@ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. + #ifndef GPU_SIM_H #define GPU_SIM_H @@ -68,6 +71,29 @@ extern tr1_hash_map<new_addr_type, unsigned> address_random_interleaving; enum dram_ctrl_t { DRAM_FIFO = 0, DRAM_FRFCFS = 1 }; +enum hw_perf_t { + HW_BENCH_NAME=0, + HW_KERNEL_NAME, + HW_L1_RH, + HW_L1_RM, + HW_L1_WH, + HW_L1_WM, + HW_CC_ACC, + HW_SHRD_ACC, + HW_DRAM_RD, + HW_DRAM_WR, + HW_L2_RH, + HW_L2_RM, + HW_L2_WH, + HW_L2_WM, + HW_NOC, + HW_PIPE_DUTY, + HW_NUM_SM_IDLE, + HW_CYCLES, + HW_VOLTAGE, + HW_TOTAL_STATS +}; + struct power_config { power_config() { m_valid = true; } void init() { @@ -82,7 +108,8 @@ struct power_config { s++; } char buf1[1024]; - snprintf(buf1, 1024, "gpgpusim_power_report__%s.log", date); + //snprintf(buf1, 1024, "accelwattch_power_report__%s.log", date); + snprintf(buf1, 1024, "accelwattch_power_report.log"); g_power_filename = strdup(buf1); char buf2[1024]; snprintf(buf2, 1024, "gpgpusim_power_trace_report__%s.log.gz", date); @@ -94,6 +121,9 @@ struct power_config { snprintf(buf4, 1024, "gpgpusim_steady_state_tracking_report__%s.log.gz", date); g_steady_state_tracking_filename = strdup(buf4); + // for(int i =0; i< hw_perf_t::HW_TOTAL_STATS; i++){ + // accelwattch_hybrid_configuration[i] = 0; + // } if (g_steady_power_levels_enabled) { sscanf(gpu_steady_state_definition, "%lf:%lf", @@ -125,6 +155,14 @@ struct power_config { double gpu_steady_power_deviation; double gpu_steady_min_period; + + char *g_hw_perf_file_name; + char *g_hw_perf_bench_name; + int g_power_simulation_mode; + bool g_dvfs_enabled; + bool g_aggregate_power_stats; + bool accelwattch_hybrid_configuration[hw_perf_t::HW_TOTAL_STATS]; + // Nonlinear power model bool g_use_nonlinear_model; char *gpu_nonlinear_model_config; @@ -357,7 +395,7 @@ class gpgpu_sim_config : public power_config, m_valid = true; } - + unsigned get_core_freq() const { return core_freq; } unsigned num_shader() const { return m_shader_config.num_shader(); } unsigned num_cluster() const { return m_shader_config.n_simt_clusters; } unsigned get_max_concurrent_kernel() const { return max_concurrent_kernel; } @@ -527,6 +565,7 @@ class gpgpu_sim : public gpgpu_t { bool kernel_more_cta_left(kernel_info_t *kernel) const; bool hit_max_cta_count() const; kernel_info_t *select_kernel(); + PowerscalingCoefficients *get_scaling_coeffs(); void decrement_kernel_latency(); const gpgpu_sim_config &get_config() const { return m_config; } @@ -634,6 +673,7 @@ class gpgpu_sim : public gpgpu_t { std::string executed_kernel_info_string(); //< format the kernel information // into a string for stat printout + std::string executed_kernel_name(); void clear_executed_kernel_info(); //< clear the kernel information after // stat printout virtual void createSIMTCluster() = 0; diff --git a/src/gpgpu-sim/l2cache.cc b/src/gpgpu-sim/l2cache.cc index ab6e5c2..44d793c 100644 --- a/src/gpgpu-sim/l2cache.cc +++ b/src/gpgpu-sim/l2cache.cc @@ -1,18 +1,20 @@ -// Copyright (c) 2009-2011, Tor M. Aamodt -// The University of British Columbia +// Copyright (c) 2009-2021, Tor M. Aamodt, Vijay Kandiah, Nikos Hardavellas, +// Mahmoud Khairy, Junrui Pan, Timothy G. Rogers +// The University of British Columbia, Northwestern University, Purdue University // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // -// Redistributions of source code must retain the above copyright notice, this -// list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. Neither the name of -// The University of British Columbia nor the names of its contributors may be -// used to endorse or promote products derived from this software without -// specific prior written permission. +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer; +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution; +// 3. Neither the names of The University of British Columbia, Northwestern +// University nor the names of their contributors may be used to +// endorse or promote products derived from this software without specific +// prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE @@ -57,6 +59,19 @@ 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, unsigned wid, unsigned sid, unsigned tpc, + mem_fetch *original_mf) 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, + wid, sid, tpc, m_memory_config, cycle, original_mf); + return mf; +} memory_partition_unit::memory_partition_unit(unsigned partition_id, const memory_config *config, class memory_stats_t *stats, @@ -375,9 +390,9 @@ void memory_partition_unit::set_done(mem_fetch *mf) { void memory_partition_unit::set_dram_power_stats( unsigned &n_cmd, unsigned &n_activity, unsigned &n_nop, unsigned &n_act, - unsigned &n_pre, unsigned &n_rd, unsigned &n_wr, unsigned &n_req) const { + unsigned &n_pre, unsigned &n_rd, unsigned &n_wr, unsigned &n_wr_WB, unsigned &n_req) const { m_dram->set_dram_power_stats(n_cmd, n_activity, n_nop, n_act, n_pre, n_rd, - n_wr, n_req); + n_wr, n_wr_WB, n_req); } void memory_partition_unit::print(FILE *fp) const { @@ -541,10 +556,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(); @@ -646,6 +666,7 @@ void gpgpu_sim::print_dram_stats(FILE *fout) const { unsigned pre = 0; unsigned rd = 0; unsigned wr = 0; + unsigned wr_WB = 0; unsigned req = 0; unsigned tot_cmd = 0; unsigned tot_nop = 0; @@ -657,13 +678,13 @@ void gpgpu_sim::print_dram_stats(FILE *fout) const { for (unsigned i = 0; i < m_memory_config->m_n_mem; i++) { m_memory_partition_unit[i]->set_dram_power_stats(cmd, activity, nop, act, - pre, rd, wr, req); + pre, rd, wr, wr_WB, req); tot_cmd += cmd; tot_nop += nop; tot_act += act; tot_pre += pre; tot_rd += rd; - tot_wr += wr; + tot_wr += wr + wr_WB; tot_req += req; } fprintf(fout, "gpgpu_n_dram_reads = %d\n", tot_rd); @@ -694,71 +715,68 @@ 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) { + } else if (mf->get_data_size() == MAX_MEMORY_ACCESS_SIZE) { + // 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); + } + mem_fetch *n_mf = m_mf_allocator->alloc( + mf->get_addr() + SECTOR_SIZE * i, mf->get_access_type(), + mf->get_access_warp_mask(), mf->get_access_byte_mask() & mask, + std::bitset<SECTOR_CHUNCK_SIZE>().set(i), SECTOR_SIZE, mf->is_write(), + m_gpu->gpu_tot_sim_cycle + m_gpu->gpu_sim_cycle, mf->get_wid(), + mf->get_sid(), mf->get_tpc(), mf); + + result.push_back(n_mf); + } + // This is for constant cache + } else if (mf->get_data_size() == 64 && + (mf->get_access_sector_mask().all() || + mf->get_access_sector_mask().none())) { + unsigned start; + if (mf->get_addr() % MAX_MEMORY_ACCESS_SIZE == 0) start = 0; - end = 3; - } else if (mf->get_data_size() == 64 && - mf->get_access_sector_mask().to_string() == "1100") { + else 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; + 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); } - } 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"); - } - - 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); - - for (unsigned j = start, i = 0; j <= end; ++j, ++i) { - 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() & byte_sector_mask, - std::bitset<SECTOR_CHUNCK_SIZE>().set(j), 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); + mem_fetch *n_mf = m_mf_allocator->alloc( + mf->get_addr(), mf->get_access_type(), mf->get_access_warp_mask(), + mf->get_access_byte_mask() & mask, + std::bitset<SECTOR_CHUNCK_SIZE>().set(i), SECTOR_SIZE, mf->is_write(), + m_gpu->gpu_tot_sim_cycle + m_gpu->gpu_sim_cycle, mf->get_wid(), + mf->get_sid(), mf->get_tpc(), 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); + } + mem_fetch *n_mf = m_mf_allocator->alloc( + mf->get_addr() + SECTOR_SIZE * i, mf->get_access_type(), + mf->get_access_warp_mask(), mf->get_access_byte_mask() & mask, + std::bitset<SECTOR_CHUNCK_SIZE>().set(i), SECTOR_SIZE, + mf->is_write(), m_gpu->gpu_tot_sim_cycle + m_gpu->gpu_sim_cycle, + mf->get_wid(), mf->get_sid(), mf->get_tpc(), 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..7fa1f29 100644 --- a/src/gpgpu-sim/l2cache.h +++ b/src/gpgpu-sim/l2cache.h @@ -1,18 +1,20 @@ -// Copyright (c) 2009-2011, Tor M. Aamodt -// The University of British Columbia +// Copyright (c) 2009-2021, Tor M. Aamodt, Vijay Kandiah, Nikos Hardavellas, +// Mahmoud Khairy, Junrui Pan, Timothy G. Rogers +// The University of British Columbia, Northwestern University, Purdue University // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // -// Redistributions of source code must retain the above copyright notice, this -// list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. Neither the name of -// The University of British Columbia nor the names of its contributors may be -// used to endorse or promote products derived from this software without -// specific prior written permission. +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer; +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution; +// 3. Neither the names of The University of British Columbia, Northwestern +// University nor the names of their contributors may be used to +// endorse or promote products derived from this software without specific +// prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE @@ -51,6 +53,13 @@ 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, + unsigned wid, unsigned sid, unsigned tpc, + mem_fetch *original_mf) const; private: const memory_config *m_memory_config; @@ -88,7 +97,7 @@ class memory_partition_unit { // Power model void set_dram_power_stats(unsigned &n_cmd, unsigned &n_activity, unsigned &n_nop, unsigned &n_act, unsigned &n_pre, - unsigned &n_rd, unsigned &n_wr, + unsigned &n_rd, unsigned &n_wr, unsigned &n_wr_WB, unsigned &n_req) const; int global_sub_partition_id_to_local_id(int global_sub_partition_id) const; diff --git a/src/gpgpu-sim/power_interface.cc b/src/gpgpu-sim/power_interface.cc index c637d84..470f2f9 100644 --- a/src/gpgpu-sim/power_interface.cc +++ b/src/gpgpu-sim/power_interface.cc @@ -1,18 +1,20 @@ -// Copyright (c) 2009-2011, Tor M. Aamodt, Ahmed El-Shafiey, Tayler Hetherington -// The University of British Columbia +// Copyright (c) 2009-2021, Tor M. Aamodt, Ahmed El-Shafiey, Tayler Hetherington, Vijay Kandiah, Nikos Hardavellas, +// Mahmoud Khairy, Junrui Pan, Timothy G. Rogers +// The University of British Columbia, Northwestern University, Purdue University // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // -// Redistributions of source code must retain the above copyright notice, this -// list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. Neither the name of -// The University of British Columbia nor the names of its contributors may be -// used to endorse or promote products derived from this software without -// specific prior written permission. +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer; +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution; +// 3. Neither the names of The University of British Columbia, Northwestern +// University nor the names of their contributors may be used to +// endorse or promote products derived from this software without specific +// prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE @@ -26,8 +28,10 @@ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. + #include "power_interface.h" + void init_mcpat(const gpgpu_sim_config &config, class gpgpu_sim_wrapper *wrapper, unsigned stat_sample_freq, unsigned tot_inst, unsigned inst) { @@ -38,7 +42,11 @@ void init_mcpat(const gpgpu_sim_config &config, config.g_power_simulation_enabled, config.g_power_trace_enabled, config.g_steady_power_levels_enabled, config.g_power_per_cycle_dump, config.gpu_steady_power_deviation, config.gpu_steady_min_period, - config.g_power_trace_zlevel, tot_inst + inst, stat_sample_freq); + config.g_power_trace_zlevel, tot_inst + inst, stat_sample_freq, + config.g_power_simulation_mode, + config.g_dvfs_enabled, + config.get_core_freq()/1000000, + config.num_shader()); } void mcpat_cycle(const gpgpu_sim_config &config, @@ -46,7 +54,7 @@ void mcpat_cycle(const gpgpu_sim_config &config, class gpgpu_sim_wrapper *wrapper, class power_stat_t *power_stats, unsigned stat_sample_freq, unsigned tot_cycle, unsigned cycle, unsigned tot_inst, - unsigned inst) { + unsigned inst, bool dvfs_enabled) { static bool mcpat_init = true; if (mcpat_init) { // If first cycle, don't have any power numbers yet @@ -55,41 +63,45 @@ void mcpat_cycle(const gpgpu_sim_config &config, } if ((tot_cycle + cycle) % stat_sample_freq == 0) { + if(dvfs_enabled){ + wrapper->set_model_voltage(1); //performance model needs to support this. + } + wrapper->set_inst_power( shdr_config->gpgpu_clock_gated_lanes, stat_sample_freq, - stat_sample_freq, power_stats->get_total_inst(), - power_stats->get_total_int_inst(), power_stats->get_total_fp_inst(), - power_stats->get_l1d_read_accesses(), - power_stats->get_l1d_write_accesses(), - power_stats->get_committed_inst()); + stat_sample_freq, power_stats->get_total_inst(0), + power_stats->get_total_int_inst(0), power_stats->get_total_fp_inst(0), + power_stats->get_l1d_read_accesses(0), + power_stats->get_l1d_write_accesses(0), + power_stats->get_committed_inst(0)); // Single RF for both int and fp ops - wrapper->set_regfile_power(power_stats->get_regfile_reads(), - power_stats->get_regfile_writes(), - power_stats->get_non_regfile_operands()); + wrapper->set_regfile_power(power_stats->get_regfile_reads(0), + power_stats->get_regfile_writes(0), + power_stats->get_non_regfile_operands(0)); // Instruction cache stats - wrapper->set_icache_power(power_stats->get_inst_c_hits(), - power_stats->get_inst_c_misses()); + wrapper->set_icache_power(power_stats->get_inst_c_hits(0), + power_stats->get_inst_c_misses(0)); // Constant Cache, shared memory, texture cache - wrapper->set_ccache_power(power_stats->get_constant_c_hits(), - power_stats->get_constant_c_misses()); + wrapper->set_ccache_power(power_stats->get_const_accessess(0), 0); //assuming all HITS in constant cache for now wrapper->set_tcache_power(power_stats->get_texture_c_hits(), power_stats->get_texture_c_misses()); - wrapper->set_shrd_mem_power(power_stats->get_shmem_read_access()); + wrapper->set_shrd_mem_power(power_stats->get_shmem_access(0)); wrapper->set_l1cache_power( - power_stats->get_l1d_read_hits(), power_stats->get_l1d_read_misses(), - power_stats->get_l1d_write_hits(), power_stats->get_l1d_write_misses()); + power_stats->get_l1d_read_hits(0), power_stats->get_l1d_read_misses(0), + power_stats->get_l1d_write_hits(0), power_stats->get_l1d_write_misses(0)); wrapper->set_l2cache_power( - power_stats->get_l2_read_hits(), power_stats->get_l2_read_misses(), - power_stats->get_l2_write_hits(), power_stats->get_l2_write_misses()); + power_stats->get_l2_read_hits(0), power_stats->get_l2_read_misses(0), + power_stats->get_l2_write_hits(0), power_stats->get_l2_write_misses(0)); float active_sms = (*power_stats->m_active_sms) / stat_sample_freq; float num_cores = shdr_config->num_shader(); float num_idle_core = num_cores - active_sms; + wrapper->set_num_cores(num_cores); wrapper->set_idle_core_power(num_idle_core); // pipeline power - pipeline_duty_cycle *= percent_active_sms; @@ -101,38 +113,64 @@ void mcpat_cycle(const gpgpu_sim_config &config, wrapper->set_duty_cycle_power(pipeline_duty_cycle); // Memory Controller - wrapper->set_mem_ctrl_power(power_stats->get_dram_rd(), - power_stats->get_dram_wr(), - power_stats->get_dram_pre()); + wrapper->set_mem_ctrl_power(power_stats->get_dram_rd(0), + power_stats->get_dram_wr(0), + power_stats->get_dram_pre(0)); // Execution pipeline accesses // FPU (SP) accesses, Integer ALU (not present in Tesla), Sfu accesses - wrapper->set_exec_unit_power(power_stats->get_tot_fpu_accessess(), - power_stats->get_ialu_accessess(), - power_stats->get_tot_sfu_accessess()); + + wrapper->set_int_accesses(power_stats->get_ialu_accessess(0), + power_stats->get_intmul24_accessess(0), + power_stats->get_intmul32_accessess(0), + power_stats->get_intmul_accessess(0), + power_stats->get_intdiv_accessess(0)); + + wrapper->set_dp_accesses(power_stats->get_dp_accessess(0), + power_stats->get_dpmul_accessess(0), + power_stats->get_dpdiv_accessess(0)); + + wrapper->set_fp_accesses(power_stats->get_fp_accessess(0), + power_stats->get_fpmul_accessess(0), + power_stats->get_fpdiv_accessess(0)); + + wrapper->set_trans_accesses(power_stats->get_sqrt_accessess(0), + power_stats->get_log_accessess(0), + power_stats->get_sin_accessess(0), + power_stats->get_exp_accessess(0)); + + wrapper->set_tensor_accesses(power_stats->get_tensor_accessess(0)); + + wrapper->set_tex_accesses(power_stats->get_tex_accessess(0)); + + wrapper->set_exec_unit_power(power_stats->get_tot_fpu_accessess(0), + power_stats->get_ialu_accessess(0), + power_stats->get_tot_sfu_accessess(0)); + + wrapper->set_avg_active_threads(power_stats->get_active_threads(0)); // Average active lanes for sp and sfu pipelines float avg_sp_active_lanes = (power_stats->get_sp_active_lanes()) / stat_sample_freq; float avg_sfu_active_lanes = (power_stats->get_sfu_active_lanes()) / stat_sample_freq; + if(avg_sp_active_lanes >32.0 ) + avg_sp_active_lanes = 32.0; + if(avg_sfu_active_lanes >32.0 ) + avg_sfu_active_lanes = 32.0; assert(avg_sp_active_lanes <= 32); assert(avg_sfu_active_lanes <= 32); - wrapper->set_active_lanes_power( - (power_stats->get_sp_active_lanes()) / stat_sample_freq, - (power_stats->get_sfu_active_lanes()) / stat_sample_freq); + wrapper->set_active_lanes_power(avg_sp_active_lanes, avg_sfu_active_lanes); double n_icnt_simt_to_mem = (double) - power_stats->get_icnt_simt_to_mem(); // # flits from SIMT clusters + power_stats->get_icnt_simt_to_mem(0); // # flits from SIMT clusters // to memory partitions double n_icnt_mem_to_simt = (double) - power_stats->get_icnt_mem_to_simt(); // # flits from memory + power_stats->get_icnt_mem_to_simt(0); // # flits from memory // partitions to SIMT clusters - wrapper->set_NoC_power( - n_icnt_mem_to_simt, - n_icnt_simt_to_mem); // Number of flits traversing the interconnect + wrapper->set_NoC_power(n_icnt_mem_to_simt + n_icnt_simt_to_mem); // Number of flits traversing the interconnect wrapper->compute(); @@ -152,3 +190,336 @@ void mcpat_cycle(const gpgpu_sim_config &config, void mcpat_reset_perf_count(class gpgpu_sim_wrapper *wrapper) { wrapper->reset_counters(); } + +bool parse_hw_file(char* hwpowerfile, bool find_target_kernel, vector<string> &hw_data, char* benchname, std::string executed_kernelname){ + fstream hw_file; + hw_file.open(hwpowerfile, ios::in); + string line, word, temp; + while(!hw_file.eof()){ + hw_data.clear(); + getline(hw_file, line); + stringstream s(line); + while (getline(s,word,',')){ + hw_data.push_back(word); + } + if(hw_data[HW_BENCH_NAME] == std::string(benchname)){ + if(find_target_kernel){ + if(hw_data[HW_KERNEL_NAME] == ""){ + hw_file.close(); + return true; + } + else{ + if(hw_data[HW_KERNEL_NAME] == executed_kernelname){ + hw_file.close(); + return true; + } + } + } + else{ + hw_file.close(); + return true; + } + } + } + hw_file.close(); + return false; +} + + +void calculate_hw_mcpat(const gpgpu_sim_config &config, + const shader_core_config *shdr_config, + class gpgpu_sim_wrapper *wrapper, + class power_stat_t *power_stats, unsigned stat_sample_freq, + unsigned tot_cycle, unsigned cycle, unsigned tot_inst, + unsigned inst, int power_simulation_mode, bool dvfs_enabled, char* hwpowerfile, + char* benchname, std::string executed_kernelname, + const bool *accelwattch_hybrid_configuration, bool aggregate_power_stats){ + + /* Reading HW data from CSV file */ + + vector<string> hw_data; + bool kernel_found = false; + kernel_found = parse_hw_file(hwpowerfile, true, hw_data, benchname, executed_kernelname); //Searching for matching executed_kernelname. + if(!kernel_found) + kernel_found = parse_hw_file(hwpowerfile, false, hw_data, benchname, executed_kernelname); //Searching for any kernel with same benchname. + assert("Could not find perf stats for the target benchmark in hwpowerfile.\n" && (kernel_found)); + unsigned perf_cycles = static_cast<unsigned int>(std::stod(hw_data[HW_CYCLES]) + 0.5); + if((power_simulation_mode == 2) && (accelwattch_hybrid_configuration[HW_CYCLES])) + perf_cycles = cycle; + wrapper->init_mcpat_hw_mode(perf_cycles); //total PERF MODEL cycles for current kernel + + if(dvfs_enabled){ + if((power_simulation_mode == 2) && (accelwattch_hybrid_configuration[HW_VOLTAGE])) + wrapper->set_model_voltage(1); //performance model needs to support this + else + wrapper->set_model_voltage(std::stod(hw_data[HW_VOLTAGE])); //performance model needs to support this + } + + double l1_read_hits = std::stod(hw_data[HW_L1_RH]); + double l1_read_misses = std::stod(hw_data[HW_L1_RM]); + double l1_write_hits = std::stod(hw_data[HW_L1_WH]); + double l1_write_misses = std::stod(hw_data[HW_L1_WM]); + + if((power_simulation_mode == 2) && (accelwattch_hybrid_configuration[HW_L1_RH])) + l1_read_hits = power_stats->get_l1d_read_hits(1) - power_stats->l1r_hits_kernel; + if((power_simulation_mode == 2) && (accelwattch_hybrid_configuration[HW_L1_RM])) + l1_read_misses = power_stats->get_l1d_read_misses(1) - power_stats->l1r_misses_kernel; + if((power_simulation_mode == 2) && (accelwattch_hybrid_configuration[HW_L1_WH])) + l1_write_hits = power_stats->get_l1d_write_hits(1) - power_stats->l1w_hits_kernel; + if((power_simulation_mode == 2) && (accelwattch_hybrid_configuration[HW_L1_WM])) + l1_write_misses = power_stats->get_l1d_write_misses(1) - power_stats->l1w_misses_kernel; + + if(aggregate_power_stats){ + power_stats->tot_inst_execution += power_stats->get_total_inst(1); + power_stats->tot_int_inst_execution += power_stats->get_total_int_inst(1); + power_stats->tot_fp_inst_execution += power_stats->get_total_fp_inst(1); + power_stats->commited_inst_execution += power_stats->get_committed_inst(1); + wrapper->set_inst_power( + shdr_config->gpgpu_clock_gated_lanes, cycle, //TODO: core.[0] cycles counts don't matter, remove this + cycle, power_stats->tot_inst_execution, + power_stats->tot_int_inst_execution, power_stats->tot_fp_inst_execution, + l1_read_hits + l1_read_misses, + l1_write_hits + l1_write_misses, + power_stats->commited_inst_execution); + } + else{ + wrapper->set_inst_power( + shdr_config->gpgpu_clock_gated_lanes, cycle, //TODO: core.[0] cycles counts don't matter, remove this + cycle, power_stats->get_total_inst(1), + power_stats->get_total_int_inst(1), power_stats->get_total_fp_inst(1), + l1_read_hits + l1_read_misses, + l1_write_hits + l1_write_misses, + power_stats->get_committed_inst(1)); + } + + // Single RF for both int and fp ops -- activity factor set to 0 for Accelwattch HW and Accelwattch Hybrid because no HW Perf Stats for register files + wrapper->set_regfile_power(power_stats->get_regfile_reads(1), + power_stats->get_regfile_writes(1), + power_stats->get_non_regfile_operands(1)); + + // Instruction cache stats -- activity factor set to 0 for Accelwattch HW and Accelwattch Hybrid because no HW Perf Stats for instruction cache + wrapper->set_icache_power(power_stats->get_inst_c_hits(1) - power_stats->l1i_hits_kernel, + power_stats->get_inst_c_misses(1) - power_stats->l1i_misses_kernel); + + // Constant Cache, shared memory, texture cache + if((power_simulation_mode == 2) && (accelwattch_hybrid_configuration[HW_CC_ACC])) + wrapper->set_ccache_power(power_stats->get_const_accessess(1) - power_stats->cc_accesses_kernel, 0); //assuming all HITS in constant cache for now + else + wrapper->set_ccache_power(std::stod(hw_data[HW_CC_ACC]), 0); //assuming all HITS in constant cache for now + + + // wrapper->set_tcache_power(power_stats->get_texture_c_hits(), + // power_stats->get_texture_c_misses()); + + if((power_simulation_mode == 2) && (accelwattch_hybrid_configuration[HW_SHRD_ACC])) + wrapper->set_shrd_mem_power(power_stats->get_shmem_access(1) - power_stats->shared_accesses_kernel); + else + wrapper->set_shrd_mem_power(std::stod(hw_data[HW_SHRD_ACC])); + + wrapper->set_l1cache_power( l1_read_hits, l1_read_misses, l1_write_hits, l1_write_misses); + + double l2_read_hits = std::stod(hw_data[HW_L2_RH]); + double l2_read_misses = std::stod(hw_data[HW_L2_RM]); + double l2_write_hits = std::stod(hw_data[HW_L2_WH]); + double l2_write_misses = std::stod(hw_data[HW_L2_WM]); + + if((power_simulation_mode == 2) && (accelwattch_hybrid_configuration[HW_L2_RH])) + l2_read_hits = power_stats->get_l2_read_hits(1) - power_stats->l2r_hits_kernel; + if((power_simulation_mode == 2) && (accelwattch_hybrid_configuration[HW_L2_RM])) + l2_read_misses = power_stats->get_l2_read_misses(1) - power_stats->l2r_misses_kernel; + if((power_simulation_mode == 2) && (accelwattch_hybrid_configuration[HW_L2_WH])) + l2_write_hits = power_stats->get_l2_write_hits(1) - power_stats->l2w_hits_kernel; + if((power_simulation_mode == 2) && (accelwattch_hybrid_configuration[HW_L2_WM])) + l2_write_misses = power_stats->get_l2_write_misses(1) - power_stats->l2w_misses_kernel; + + wrapper->set_l2cache_power(l2_read_hits, l2_read_misses, l2_write_hits, l2_write_misses); + + float active_sms = (*power_stats->m_active_sms) / stat_sample_freq; + float num_cores = shdr_config->num_shader(); + float num_idle_core = num_cores - active_sms; + wrapper->set_num_cores(num_cores); + if((power_simulation_mode == 2) && (accelwattch_hybrid_configuration[HW_NUM_SM_IDLE])) + wrapper->set_idle_core_power(num_idle_core); + else + wrapper->set_idle_core_power(std::stod(hw_data[HW_NUM_SM_IDLE])); + + float pipeline_duty_cycle = + ((*power_stats->m_average_pipeline_duty_cycle / (stat_sample_freq)) < + 0.8) + ? ((*power_stats->m_average_pipeline_duty_cycle) / stat_sample_freq) + : 0.8; + + if((power_simulation_mode == 2) && (accelwattch_hybrid_configuration[HW_PIPE_DUTY])) + wrapper->set_duty_cycle_power(pipeline_duty_cycle); + else + wrapper->set_duty_cycle_power(std::stod(hw_data[HW_PIPE_DUTY])); + + // Memory Controller + + double dram_reads = std::stod(hw_data[HW_DRAM_RD]); + double dram_writes = std::stod(hw_data[HW_DRAM_WR]); + double dram_pre = 0; + if((power_simulation_mode == 2) && (accelwattch_hybrid_configuration[HW_DRAM_RD])) + dram_reads = power_stats->get_dram_rd(1) - power_stats->dram_rd_kernel; + if((power_simulation_mode == 2) && (accelwattch_hybrid_configuration[HW_DRAM_WR])) + dram_writes = power_stats->get_dram_wr(1) - power_stats->dram_wr_kernel; + if((power_simulation_mode == 2) && (accelwattch_hybrid_configuration[HW_DRAM_RD])) + dram_pre = power_stats->get_dram_pre(1) - power_stats->dram_pre_kernel; + + + wrapper->set_mem_ctrl_power(dram_reads, dram_writes, dram_pre); + + if(aggregate_power_stats){ + power_stats->ialu_acc_execution += power_stats->get_ialu_accessess(1); + power_stats->imul24_acc_execution += power_stats->get_intmul24_accessess(1); + power_stats->imul32_acc_execution += power_stats->get_intmul32_accessess(1); + power_stats->imul_acc_execution += power_stats->get_intmul_accessess(1); + power_stats->idiv_acc_execution += power_stats->get_intdiv_accessess(1); + power_stats->dp_acc_execution += power_stats->get_dp_accessess(1); + power_stats->dpmul_acc_execution += power_stats->get_dpmul_accessess(1); + power_stats->dpdiv_acc_execution += power_stats->get_dpdiv_accessess(1); + power_stats->fp_acc_execution += power_stats->get_fp_accessess(1); + power_stats->fpmul_acc_execution += power_stats->get_fpmul_accessess(1); + power_stats->fpdiv_acc_execution += power_stats->get_fpdiv_accessess(1); + power_stats->sqrt_acc_execution += power_stats->get_sqrt_accessess(1); + power_stats->log_acc_execution += power_stats->get_log_accessess(1); + power_stats->sin_acc_execution += power_stats->get_sin_accessess(1); + power_stats->exp_acc_execution += power_stats->get_exp_accessess(1); + power_stats->tensor_acc_execution += power_stats->get_tensor_accessess(1); + power_stats->tex_acc_execution += power_stats->get_tex_accessess(1); + power_stats->tot_fpu_acc_execution += power_stats->get_tot_fpu_accessess(1); + power_stats->tot_sfu_acc_execution += power_stats->get_tot_sfu_accessess(1); + power_stats->tot_threads_acc_execution += power_stats->get_tot_threads_kernel(1); + power_stats->tot_warps_acc_execution += power_stats->get_tot_warps_kernel(1); + + power_stats->sp_active_lanes_execution += (power_stats->get_sp_active_lanes() * shdr_config->num_shader() * shdr_config->gpgpu_num_sp_units); + power_stats->sfu_active_lanes_execution += (power_stats->get_sfu_active_lanes() * shdr_config->num_shader() * shdr_config->gpgpu_num_sp_units); + + wrapper->set_int_accesses(power_stats->ialu_acc_execution, + power_stats->imul24_acc_execution, + power_stats->imul32_acc_execution, + power_stats->imul_acc_execution, + power_stats->idiv_acc_execution); + + wrapper->set_dp_accesses(power_stats->dp_acc_execution, + power_stats->dpmul_acc_execution, + power_stats->dpdiv_acc_execution); + + wrapper->set_fp_accesses(power_stats->fp_acc_execution, + power_stats->fpmul_acc_execution, + power_stats->fpdiv_acc_execution); + + wrapper->set_trans_accesses(power_stats->sqrt_acc_execution, + power_stats->log_acc_execution, + power_stats->sin_acc_execution, + power_stats->exp_acc_execution); + + wrapper->set_tensor_accesses(power_stats->tensor_acc_execution); + + wrapper->set_tex_accesses(power_stats->tex_acc_execution); + + wrapper->set_exec_unit_power(power_stats->ialu_acc_execution, + power_stats->tot_fpu_acc_execution, + power_stats->tot_sfu_acc_execution); + + wrapper->set_avg_active_threads((double)((double)power_stats->tot_threads_acc_execution / (double)power_stats->tot_warps_acc_execution)); + + // Average active lanes for sp and sfu pipelines + float avg_sp_active_lanes = + (power_stats->sp_active_lanes_execution) / shdr_config->num_shader() / shdr_config->gpgpu_num_sp_units / stat_sample_freq; + float avg_sfu_active_lanes = + (power_stats->sfu_active_lanes_execution) / shdr_config->num_shader() / shdr_config->gpgpu_num_sp_units / stat_sample_freq; + if(avg_sp_active_lanes >32.0 ) + avg_sp_active_lanes = 32.0; + if(avg_sfu_active_lanes >32.0 ) + avg_sfu_active_lanes = 32.0; + assert(avg_sp_active_lanes <= 32); + assert(avg_sfu_active_lanes <= 32); + wrapper->set_active_lanes_power(avg_sp_active_lanes, avg_sfu_active_lanes); + } + else{ + wrapper->set_int_accesses(power_stats->get_ialu_accessess(1), + power_stats->get_intmul24_accessess(1), + power_stats->get_intmul32_accessess(1), + power_stats->get_intmul_accessess(1), + power_stats->get_intdiv_accessess(1)); + + wrapper->set_dp_accesses(power_stats->get_dp_accessess(1), + power_stats->get_dpmul_accessess(1), + power_stats->get_dpdiv_accessess(1)); + + wrapper->set_fp_accesses(power_stats->get_fp_accessess(1), + power_stats->get_fpmul_accessess(1), + power_stats->get_fpdiv_accessess(1)); + + wrapper->set_trans_accesses(power_stats->get_sqrt_accessess(1), + power_stats->get_log_accessess(1), + power_stats->get_sin_accessess(1), + power_stats->get_exp_accessess(1)); + + wrapper->set_tensor_accesses(power_stats->get_tensor_accessess(1)); + + wrapper->set_tex_accesses(power_stats->get_tex_accessess(1)); + + wrapper->set_exec_unit_power(power_stats->get_tot_fpu_accessess(1), + power_stats->get_ialu_accessess(1), + power_stats->get_tot_sfu_accessess(1)); + + wrapper->set_avg_active_threads(power_stats->get_active_threads(1)); + + // Average active lanes for sp and sfu pipelines + float avg_sp_active_lanes = + (power_stats->get_sp_active_lanes()) / stat_sample_freq; + float avg_sfu_active_lanes = + (power_stats->get_sfu_active_lanes()) / stat_sample_freq; + if(avg_sp_active_lanes >32.0 ) + avg_sp_active_lanes = 32.0; + if(avg_sfu_active_lanes >32.0 ) + avg_sfu_active_lanes = 32.0; + assert(avg_sp_active_lanes <= 32); + assert(avg_sfu_active_lanes <= 32); + wrapper->set_active_lanes_power(avg_sp_active_lanes, avg_sfu_active_lanes); + } + + + double n_icnt_simt_to_mem = + (double) + (power_stats->get_icnt_simt_to_mem(1) - power_stats->noc_tr_kernel); // # flits from SIMT clusters + // to memory partitions + double n_icnt_mem_to_simt = + (double) + (power_stats->get_icnt_mem_to_simt(1)- power_stats->noc_rc_kernel); // # flits from memory + // partitions to SIMT clusters + if((power_simulation_mode == 2) && (accelwattch_hybrid_configuration[HW_NOC])) + wrapper->set_NoC_power(n_icnt_mem_to_simt + n_icnt_simt_to_mem); // Number of flits traversing the interconnect from Accel-Sim + else + wrapper->set_NoC_power(std::stod(hw_data[HW_NOC])); // Number of flits traversing the interconnect from HW + + wrapper->compute(); + + wrapper->update_components_power(); + + wrapper->power_metrics_calculations(); + + wrapper->dump(); + power_stats->l1r_hits_kernel = power_stats->get_l1d_read_hits(1); + power_stats->l1r_misses_kernel = power_stats->get_l1d_read_misses(1); + power_stats->l1w_hits_kernel = power_stats->get_l1d_write_hits(1); + power_stats->l1w_misses_kernel = power_stats->get_l1d_write_misses(1); + power_stats->shared_accesses_kernel = power_stats->get_const_accessess(1); + power_stats->cc_accesses_kernel = power_stats->get_shmem_access(1); + power_stats->dram_rd_kernel = power_stats->get_dram_rd(1); + power_stats->dram_wr_kernel = power_stats->get_dram_wr(1); + power_stats->dram_pre_kernel = power_stats->get_dram_pre(1); + power_stats->l1i_hits_kernel = power_stats->get_inst_c_hits(1); + power_stats->l1i_misses_kernel = power_stats->get_inst_c_misses(1); + power_stats->l2r_hits_kernel = power_stats->get_l2_read_hits(1); + power_stats->l2r_misses_kernel = power_stats->get_l2_read_misses(1); + power_stats->l2w_hits_kernel = power_stats->get_l2_write_hits(1); + power_stats->l2w_misses_kernel = power_stats->get_l2_write_misses(1); + power_stats->noc_tr_kernel = power_stats->get_icnt_simt_to_mem(1); + power_stats->noc_rc_kernel = power_stats->get_icnt_mem_to_simt(1); + + + power_stats->clear(); +}
\ No newline at end of file diff --git a/src/gpgpu-sim/power_interface.h b/src/gpgpu-sim/power_interface.h index 2bfd4d5..1c6c510 100644 --- a/src/gpgpu-sim/power_interface.h +++ b/src/gpgpu-sim/power_interface.h @@ -1,18 +1,20 @@ -// Copyright (c) 2009-2011, Tor M. Aamodt, Ahmed El-Shafiey, Tayler Hetherington -// The University of British Columbia +// Copyright (c) 2009-2021, Tor M. Aamodt, Ahmed El-Shafiey, Tayler Hetherington, Vijay Kandiah, Nikos Hardavellas, +// Mahmoud Khairy, Junrui Pan, Timothy G. Rogers +// The University of British Columbia, Northwestern University, Purdue University // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // -// Redistributions of source code must retain the above copyright notice, this -// list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. Neither the name of -// The University of British Columbia nor the names of its contributors may be -// used to endorse or promote products derived from this software without -// specific prior written permission. +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer; +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution; +// 3. Neither the names of The University of British Columbia, Northwestern +// University nor the names of their contributors may be used to +// endorse or promote products derived from this software without specific +// prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE @@ -43,7 +45,19 @@ void mcpat_cycle(const gpgpu_sim_config &config, class gpgpu_sim_wrapper *wrapper, class power_stat_t *power_stats, unsigned stat_sample_freq, unsigned tot_cycle, unsigned cycle, unsigned tot_inst, - unsigned inst); + unsigned inst, bool dvfs_enabled); + +void calculate_hw_mcpat(const gpgpu_sim_config &config, + const shader_core_config *shdr_config, + class gpgpu_sim_wrapper *wrapper, + class power_stat_t *power_stats, unsigned stat_sample_freq, + unsigned tot_cycle, unsigned cycle, unsigned tot_inst, + unsigned inst, int power_simulation_mode, bool dvfs_enabled, + char* hwpowerfile, char* benchname, std::string executed_kernelname, + const bool *accelwattch_hybrid_configuration, bool aggregate_power_stats); + +bool parse_hw_file(char* hwpowerfile, bool find_target_kernel, vector<string> &hw_data, char* benchname, std::string executed_kernelname); + void mcpat_reset_perf_count(class gpgpu_sim_wrapper *wrapper); #endif /* POWER_INTERFACE_H_ */ diff --git a/src/gpgpu-sim/power_stat.cc b/src/gpgpu-sim/power_stat.cc index 7b60ddf..d0e673c 100644 --- a/src/gpgpu-sim/power_stat.cc +++ b/src/gpgpu-sim/power_stat.cc @@ -1,18 +1,20 @@ -// Copyright (c) 2009-2011, Tor M. Aamodt, Ahmed El-Shafiey, Tayler Hetherington -// The University of British Columbia +// Copyright (c) 2009-2021, Tor M. Aamodt, Ahmed El-Shafiey, Tayler Hetherington, Vijay Kandiah, Nikos Hardavellas, +// Mahmoud Khairy, Junrui Pan, Timothy G. Rogers +// The University of British Columbia, Northwestern University, Purdue University // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // -// Redistributions of source code must retain the above copyright notice, this -// list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. Neither the name of -// The University of British Columbia nor the names of its contributors may be -// used to endorse or promote products derived from this software without -// specific prior written permission. +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer; +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution; +// 3. Neither the names of The University of British Columbia, Northwestern +// University nor the names of their contributors may be used to +// endorse or promote products derived from this software without specific +// prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE @@ -54,10 +56,64 @@ power_mem_stat_t::power_mem_stat_t(const memory_config *mem_config, init(); } +void power_stat_t::clear(){ + for(unsigned i=0; i< NUM_STAT_IDX; ++i){ + pwr_mem_stat->core_cache_stats[i].clear(); + pwr_mem_stat->l2_cache_stats[i].clear(); + for(unsigned j=0; j<m_config->num_shader(); ++j){ + pwr_core_stat->m_pipeline_duty_cycle[i][j]=0; + pwr_core_stat->m_num_decoded_insn[i][j]=0; + pwr_core_stat->m_num_FPdecoded_insn[i][j]=0; + pwr_core_stat->m_num_INTdecoded_insn[i][j]=0; + pwr_core_stat->m_num_storequeued_insn[i][j]=0; + pwr_core_stat->m_num_loadqueued_insn[i][j]=0; + pwr_core_stat->m_num_tex_inst[i][j]=0; + pwr_core_stat->m_num_ialu_acesses[i][j]=0; + pwr_core_stat->m_num_fp_acesses[i][j]=0; + pwr_core_stat->m_num_imul_acesses[i][j]=0; + pwr_core_stat->m_num_imul24_acesses[i][j]=0; + pwr_core_stat->m_num_imul32_acesses[i][j]=0; + pwr_core_stat->m_num_fpmul_acesses[i][j]=0; + pwr_core_stat->m_num_idiv_acesses[i][j]=0; + pwr_core_stat->m_num_fpdiv_acesses[i][j]=0; + pwr_core_stat->m_num_dp_acesses[i][j]=0; + pwr_core_stat->m_num_dpmul_acesses[i][j]=0; + pwr_core_stat->m_num_dpdiv_acesses[i][j]=0; + pwr_core_stat->m_num_tensor_core_acesses[i][j]=0; + pwr_core_stat->m_num_const_acesses[i][j]=0; + pwr_core_stat->m_num_tex_acesses[i][j]=0; + pwr_core_stat->m_num_sp_acesses[i][j]=0; + pwr_core_stat->m_num_sfu_acesses[i][j]=0; + pwr_core_stat->m_num_sqrt_acesses[i][j]=0; + pwr_core_stat->m_num_log_acesses[i][j]=0; + pwr_core_stat->m_num_sin_acesses[i][j]=0; + pwr_core_stat->m_num_exp_acesses[i][j]=0; + pwr_core_stat->m_num_mem_acesses[i][j]=0; + pwr_core_stat->m_num_sp_committed[i][j]=0; + pwr_core_stat->m_num_sfu_committed[i][j]=0; + pwr_core_stat->m_num_mem_committed[i][j]=0; + pwr_core_stat->m_read_regfile_acesses[i][j]=0; + pwr_core_stat->m_write_regfile_acesses[i][j]=0; + pwr_core_stat->m_non_rf_operands[i][j]=0; + pwr_core_stat->m_active_sp_lanes[i][j]=0; + pwr_core_stat->m_active_sfu_lanes[i][j]=0; + pwr_core_stat->m_active_exu_threads[i][j]=0; + pwr_core_stat->m_active_exu_warps[i][j]=0; + } + for (unsigned j = 0; j < m_mem_config->m_n_mem; ++j) { + pwr_mem_stat->n_rd[i][j]=0; + pwr_mem_stat->n_wr[i][j]=0; + pwr_mem_stat->n_pre[i][j]=0; + } + } +} + + + void power_mem_stat_t::init() { - shmem_read_access[CURRENT_STAT_IDX] = + shmem_access[CURRENT_STAT_IDX] = m_core_stats->gpgpu_n_shmem_bank_access; // Shared memory access - shmem_read_access[PREV_STAT_IDX] = + shmem_access[PREV_STAT_IDX] = (unsigned *)calloc(m_core_config->num_shader(), sizeof(unsigned)); for (unsigned i = 0; i < NUM_STAT_IDX; ++i) { @@ -71,6 +127,7 @@ void power_mem_stat_t::init() { n_pre[i] = (unsigned *)calloc(m_config->m_n_mem, sizeof(unsigned)); n_rd[i] = (unsigned *)calloc(m_config->m_n_mem, sizeof(unsigned)); n_wr[i] = (unsigned *)calloc(m_config->m_n_mem, sizeof(unsigned)); + n_wr_WB[i] = (unsigned *)calloc(m_config->m_n_mem, sizeof(unsigned)); n_req[i] = (unsigned *)calloc(m_config->m_n_mem, sizeof(unsigned)); // Interconnect stats @@ -86,8 +143,8 @@ void power_mem_stat_t::save_stats() { l2_cache_stats[PREV_STAT_IDX] = l2_cache_stats[CURRENT_STAT_IDX]; for (unsigned i = 0; i < m_core_config->num_shader(); ++i) { - shmem_read_access[PREV_STAT_IDX][i] = - shmem_read_access[CURRENT_STAT_IDX][i]; // Shared memory access + shmem_access[PREV_STAT_IDX][i] = + shmem_access[CURRENT_STAT_IDX][i]; // Shared memory access } for (unsigned i = 0; i < m_config->m_n_mem; ++i) { @@ -98,6 +155,7 @@ void power_mem_stat_t::save_stats() { n_pre[PREV_STAT_IDX][i] = n_pre[CURRENT_STAT_IDX][i]; n_rd[PREV_STAT_IDX][i] = n_rd[CURRENT_STAT_IDX][i]; n_wr[PREV_STAT_IDX][i] = n_wr[CURRENT_STAT_IDX][i]; + n_wr_WB[PREV_STAT_IDX][i] = n_wr_WB[CURRENT_STAT_IDX][i]; n_req[PREV_STAT_IDX][i] = n_req[CURRENT_STAT_IDX][i]; } @@ -117,7 +175,7 @@ void power_mem_stat_t::print(FILE *fout) const { unsigned total_mem_writes = 0; for (unsigned i = 0; i < m_config->m_n_mem; ++i) { total_mem_reads += n_rd[CURRENT_STAT_IDX][i]; - total_mem_writes += n_wr[CURRENT_STAT_IDX][i]; + total_mem_writes += n_wr[CURRENT_STAT_IDX][i] + n_wr_WB[CURRENT_STAT_IDX][i]; } fprintf(fout, "Total memory controller accesses: %u\n", total_mem_reads + total_mem_writes); @@ -147,198 +205,165 @@ void power_core_stat_t::print(FILE *fout) { // per core statistics fprintf(fout, "Power Metrics: \n"); for (unsigned i = 0; i < m_config->num_shader(); i++) { - fprintf(fout, "core %u:\n", i); - fprintf(fout, "\tpipeline duty cycle =%f\n", - m_pipeline_duty_cycle[CURRENT_STAT_IDX][i]); - fprintf(fout, "\tTotal Deocded Instructions=%u\n", - m_num_decoded_insn[CURRENT_STAT_IDX][i]); - fprintf(fout, "\tTotal FP Deocded Instructions=%u\n", - m_num_FPdecoded_insn[CURRENT_STAT_IDX][i]); - fprintf(fout, "\tTotal INT Deocded Instructions=%u\n", - m_num_INTdecoded_insn[CURRENT_STAT_IDX][i]); - fprintf(fout, "\tTotal LOAD Queued Instructions=%u\n", - m_num_loadqueued_insn[CURRENT_STAT_IDX][i]); - fprintf(fout, "\tTotal STORE Queued Instructions=%u\n", - m_num_storequeued_insn[CURRENT_STAT_IDX][i]); - fprintf(fout, "\tTotal IALU Acesses=%u\n", - m_num_ialu_acesses[CURRENT_STAT_IDX][i]); - fprintf(fout, "\tTotal FP Acesses=%u\n", - m_num_fp_acesses[CURRENT_STAT_IDX][i]); - fprintf(fout, "\tTotal IMUL Acesses=%u\n", - m_num_imul_acesses[CURRENT_STAT_IDX][i]); - fprintf(fout, "\tTotal IMUL24 Acesses=%u\n", - m_num_imul24_acesses[CURRENT_STAT_IDX][i]); - fprintf(fout, "\tTotal IMUL32 Acesses=%u\n", - m_num_imul32_acesses[CURRENT_STAT_IDX][i]); - fprintf(fout, "\tTotal IDIV Acesses=%u\n", - m_num_idiv_acesses[CURRENT_STAT_IDX][i]); - fprintf(fout, "\tTotal FPMUL Acesses=%u\n", - m_num_fpmul_acesses[CURRENT_STAT_IDX][i]); - fprintf(fout, "\tTotal SFU Acesses=%u\n", - m_num_trans_acesses[CURRENT_STAT_IDX][i]); - fprintf(fout, "\tTotal FPDIV Acesses=%u\n", - m_num_fpdiv_acesses[CURRENT_STAT_IDX][i]); - fprintf(fout, "\tTotal SFU Acesses=%u\n", - m_num_sfu_acesses[CURRENT_STAT_IDX][i]); - fprintf(fout, "\tTotal SP Acesses=%u\n", - m_num_sp_acesses[CURRENT_STAT_IDX][i]); - fprintf(fout, "\tTotal MEM Acesses=%u\n", - m_num_mem_acesses[CURRENT_STAT_IDX][i]); - fprintf(fout, "\tTotal SFU Commissions=%u\n", - m_num_sfu_committed[CURRENT_STAT_IDX][i]); - fprintf(fout, "\tTotal SP Commissions=%u\n", - m_num_sp_committed[CURRENT_STAT_IDX][i]); - fprintf(fout, "\tTotal MEM Commissions=%u\n", - m_num_mem_committed[CURRENT_STAT_IDX][i]); - fprintf(fout, "\tTotal REG Reads=%u\n", - m_read_regfile_acesses[CURRENT_STAT_IDX][i]); - fprintf(fout, "\tTotal REG Writes=%u\n", - m_write_regfile_acesses[CURRENT_STAT_IDX][i]); - fprintf(fout, "\tTotal NON REG=%u\n", - m_non_rf_operands[CURRENT_STAT_IDX][i]); + fprintf(fout,"core %u:\n",i); + fprintf(fout,"\tpipeline duty cycle =%f\n",m_pipeline_duty_cycle[CURRENT_STAT_IDX][i]); + fprintf(fout,"\tTotal Deocded Instructions=%u\n",m_num_decoded_insn[CURRENT_STAT_IDX][i]); + fprintf(fout,"\tTotal FP Deocded Instructions=%u\n",m_num_FPdecoded_insn[CURRENT_STAT_IDX][i]); + fprintf(fout,"\tTotal INT Deocded Instructions=%u\n",m_num_INTdecoded_insn[CURRENT_STAT_IDX][i]); + fprintf(fout,"\tTotal LOAD Queued Instructions=%u\n",m_num_loadqueued_insn[CURRENT_STAT_IDX][i]); + fprintf(fout,"\tTotal STORE Queued Instructions=%u\n",m_num_storequeued_insn[CURRENT_STAT_IDX][i]); + fprintf(fout,"\tTotal IALU Acesses=%f\n",m_num_ialu_acesses[CURRENT_STAT_IDX][i]); + fprintf(fout,"\tTotal FP Acesses=%f\n",m_num_fp_acesses[CURRENT_STAT_IDX][i]); + fprintf(fout,"\tTotal DP Acesses=%f\n",m_num_dp_acesses[CURRENT_STAT_IDX][i]); + fprintf(fout,"\tTotal IMUL Acesses=%f\n",m_num_imul_acesses[CURRENT_STAT_IDX][i]); + fprintf(fout,"\tTotal IMUL24 Acesses=%f\n",m_num_imul24_acesses[CURRENT_STAT_IDX][i]); + fprintf(fout,"\tTotal IMUL32 Acesses=%f\n",m_num_imul32_acesses[CURRENT_STAT_IDX][i]); + fprintf(fout,"\tTotal IDIV Acesses=%f\n",m_num_idiv_acesses[CURRENT_STAT_IDX][i]); + fprintf(fout,"\tTotal FPMUL Acesses=%f\n",m_num_fpmul_acesses[CURRENT_STAT_IDX][i]); + fprintf(fout,"\tTotal DPMUL Acesses=%f\n",m_num_dpmul_acesses[CURRENT_STAT_IDX][i]); + fprintf(fout,"\tTotal SQRT Acesses=%f\n",m_num_sqrt_acesses[CURRENT_STAT_IDX][i]); + fprintf(fout,"\tTotal LOG Acesses=%f\n",m_num_log_acesses[CURRENT_STAT_IDX][i]); + fprintf(fout,"\tTotal SIN Acesses=%f\n",m_num_sin_acesses[CURRENT_STAT_IDX][i]); + fprintf(fout,"\tTotal EXP Acesses=%f\n",m_num_exp_acesses[CURRENT_STAT_IDX][i]); + fprintf(fout,"\tTotal FPDIV Acesses=%f\n",m_num_fpdiv_acesses[CURRENT_STAT_IDX][i]); + fprintf(fout,"\tTotal DPDIV Acesses=%f\n",m_num_dpdiv_acesses[CURRENT_STAT_IDX][i]); + fprintf(fout,"\tTotal TENSOR Acesses=%f\n",m_num_tensor_core_acesses[CURRENT_STAT_IDX][i]); + fprintf(fout,"\tTotal CONST Acesses=%f\n",m_num_const_acesses[CURRENT_STAT_IDX][i]); + fprintf(fout,"\tTotal TEX Acesses=%f\n",m_num_tex_acesses[CURRENT_STAT_IDX][i]); + fprintf(fout,"\tTotal SFU Acesses=%f\n",m_num_sfu_acesses[CURRENT_STAT_IDX][i]); + fprintf(fout,"\tTotal SP Acesses=%f\n",m_num_sp_acesses[CURRENT_STAT_IDX][i]); + fprintf(fout,"\tTotal MEM Acesses=%f\n",m_num_mem_acesses[CURRENT_STAT_IDX][i]); + fprintf(fout,"\tTotal SFU Commissions=%u\n",m_num_sfu_committed[CURRENT_STAT_IDX][i]); + fprintf(fout,"\tTotal SP Commissions=%u\n",m_num_sp_committed[CURRENT_STAT_IDX][i]); + fprintf(fout,"\tTotal MEM Commissions=%u\n",m_num_mem_committed[CURRENT_STAT_IDX][i]); + fprintf(fout,"\tTotal REG Reads=%u\n",m_read_regfile_acesses[CURRENT_STAT_IDX][i]); + fprintf(fout,"\tTotal REG Writes=%u\n",m_write_regfile_acesses[CURRENT_STAT_IDX][i]); + fprintf(fout,"\tTotal NON REG=%u\n",m_non_rf_operands[CURRENT_STAT_IDX][i]); } } void power_core_stat_t::init() { - m_pipeline_duty_cycle[CURRENT_STAT_IDX] = m_core_stats->m_pipeline_duty_cycle; - m_num_decoded_insn[CURRENT_STAT_IDX] = m_core_stats->m_num_decoded_insn; - m_num_FPdecoded_insn[CURRENT_STAT_IDX] = m_core_stats->m_num_FPdecoded_insn; - m_num_INTdecoded_insn[CURRENT_STAT_IDX] = m_core_stats->m_num_INTdecoded_insn; - m_num_storequeued_insn[CURRENT_STAT_IDX] = - m_core_stats->m_num_storequeued_insn; - m_num_loadqueued_insn[CURRENT_STAT_IDX] = m_core_stats->m_num_loadqueued_insn; - m_num_ialu_acesses[CURRENT_STAT_IDX] = m_core_stats->m_num_ialu_acesses; - m_num_fp_acesses[CURRENT_STAT_IDX] = m_core_stats->m_num_fp_acesses; - m_num_imul_acesses[CURRENT_STAT_IDX] = m_core_stats->m_num_imul_acesses; - m_num_imul24_acesses[CURRENT_STAT_IDX] = m_core_stats->m_num_imul24_acesses; - m_num_imul32_acesses[CURRENT_STAT_IDX] = m_core_stats->m_num_imul32_acesses; - m_num_fpmul_acesses[CURRENT_STAT_IDX] = m_core_stats->m_num_fpmul_acesses; - m_num_idiv_acesses[CURRENT_STAT_IDX] = m_core_stats->m_num_idiv_acesses; - m_num_fpdiv_acesses[CURRENT_STAT_IDX] = m_core_stats->m_num_fpdiv_acesses; - m_num_sp_acesses[CURRENT_STAT_IDX] = m_core_stats->m_num_sp_acesses; - m_num_sfu_acesses[CURRENT_STAT_IDX] = m_core_stats->m_num_sfu_acesses; - m_num_trans_acesses[CURRENT_STAT_IDX] = m_core_stats->m_num_trans_acesses; - m_num_mem_acesses[CURRENT_STAT_IDX] = m_core_stats->m_num_mem_acesses; - m_num_sp_committed[CURRENT_STAT_IDX] = m_core_stats->m_num_sp_committed; - m_num_sfu_committed[CURRENT_STAT_IDX] = m_core_stats->m_num_sfu_committed; - m_num_mem_committed[CURRENT_STAT_IDX] = m_core_stats->m_num_mem_committed; - m_read_regfile_acesses[CURRENT_STAT_IDX] = - m_core_stats->m_read_regfile_acesses; - m_write_regfile_acesses[CURRENT_STAT_IDX] = - m_core_stats->m_write_regfile_acesses; - m_non_rf_operands[CURRENT_STAT_IDX] = m_core_stats->m_non_rf_operands; - m_active_sp_lanes[CURRENT_STAT_IDX] = m_core_stats->m_active_sp_lanes; - m_active_sfu_lanes[CURRENT_STAT_IDX] = m_core_stats->m_active_sfu_lanes; - m_num_tex_inst[CURRENT_STAT_IDX] = m_core_stats->m_num_tex_inst; + m_pipeline_duty_cycle[CURRENT_STAT_IDX]=m_core_stats->m_pipeline_duty_cycle; + m_num_decoded_insn[CURRENT_STAT_IDX]=m_core_stats->m_num_decoded_insn; + m_num_FPdecoded_insn[CURRENT_STAT_IDX]=m_core_stats->m_num_FPdecoded_insn; + m_num_INTdecoded_insn[CURRENT_STAT_IDX]=m_core_stats->m_num_INTdecoded_insn; + m_num_storequeued_insn[CURRENT_STAT_IDX]=m_core_stats->m_num_storequeued_insn; + m_num_loadqueued_insn[CURRENT_STAT_IDX]=m_core_stats->m_num_loadqueued_insn; + m_num_ialu_acesses[CURRENT_STAT_IDX]=m_core_stats->m_num_ialu_acesses; + m_num_fp_acesses[CURRENT_STAT_IDX]=m_core_stats->m_num_fp_acesses; + m_num_imul_acesses[CURRENT_STAT_IDX]=m_core_stats->m_num_imul_acesses; + m_num_imul24_acesses[CURRENT_STAT_IDX]=m_core_stats->m_num_imul24_acesses; + m_num_imul32_acesses[CURRENT_STAT_IDX]=m_core_stats->m_num_imul32_acesses; + m_num_fpmul_acesses[CURRENT_STAT_IDX]=m_core_stats->m_num_fpmul_acesses; + m_num_idiv_acesses[CURRENT_STAT_IDX]=m_core_stats->m_num_idiv_acesses; + m_num_fpdiv_acesses[CURRENT_STAT_IDX]=m_core_stats->m_num_fpdiv_acesses; + m_num_dp_acesses[CURRENT_STAT_IDX]=m_core_stats->m_num_dp_acesses; + m_num_dpmul_acesses[CURRENT_STAT_IDX]=m_core_stats->m_num_dpmul_acesses; + m_num_dpdiv_acesses[CURRENT_STAT_IDX]=m_core_stats->m_num_dpdiv_acesses; + m_num_sp_acesses[CURRENT_STAT_IDX]=m_core_stats->m_num_sp_acesses; + m_num_sfu_acesses[CURRENT_STAT_IDX]=m_core_stats->m_num_sfu_acesses; + m_num_sqrt_acesses[CURRENT_STAT_IDX]=m_core_stats->m_num_sqrt_acesses; + m_num_log_acesses[CURRENT_STAT_IDX]=m_core_stats->m_num_log_acesses; + m_num_sin_acesses[CURRENT_STAT_IDX]=m_core_stats->m_num_sin_acesses; + m_num_exp_acesses[CURRENT_STAT_IDX]=m_core_stats->m_num_exp_acesses; + m_num_tensor_core_acesses[CURRENT_STAT_IDX]=m_core_stats->m_num_tensor_core_acesses; + m_num_const_acesses[CURRENT_STAT_IDX]=m_core_stats->m_num_const_acesses; + m_num_tex_acesses[CURRENT_STAT_IDX]=m_core_stats->m_num_tex_acesses; + m_num_mem_acesses[CURRENT_STAT_IDX]=m_core_stats->m_num_mem_acesses; + m_num_sp_committed[CURRENT_STAT_IDX]=m_core_stats->m_num_sp_committed; + m_num_sfu_committed[CURRENT_STAT_IDX]=m_core_stats->m_num_sfu_committed; + m_num_mem_committed[CURRENT_STAT_IDX]=m_core_stats->m_num_mem_committed; + m_read_regfile_acesses[CURRENT_STAT_IDX]=m_core_stats->m_read_regfile_acesses; + m_write_regfile_acesses[CURRENT_STAT_IDX]=m_core_stats->m_write_regfile_acesses; + m_non_rf_operands[CURRENT_STAT_IDX]=m_core_stats->m_non_rf_operands; + m_active_sp_lanes[CURRENT_STAT_IDX]=m_core_stats->m_active_sp_lanes; + m_active_sfu_lanes[CURRENT_STAT_IDX]=m_core_stats->m_active_sfu_lanes; + m_active_exu_threads[CURRENT_STAT_IDX]=m_core_stats->m_active_exu_threads; + m_active_exu_warps[CURRENT_STAT_IDX]=m_core_stats->m_active_exu_warps; + m_num_tex_inst[CURRENT_STAT_IDX]=m_core_stats->m_num_tex_inst; + + m_pipeline_duty_cycle[PREV_STAT_IDX]=(float*)calloc(m_config->num_shader(),sizeof(float)); + m_num_decoded_insn[PREV_STAT_IDX]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_num_FPdecoded_insn[PREV_STAT_IDX]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_num_INTdecoded_insn[PREV_STAT_IDX]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_num_storequeued_insn[PREV_STAT_IDX]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_num_loadqueued_insn[PREV_STAT_IDX]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_num_tex_inst[PREV_STAT_IDX]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + + m_num_ialu_acesses[PREV_STAT_IDX]=(double *)calloc(m_config->num_shader(),sizeof(double)); + m_num_fp_acesses[PREV_STAT_IDX]=(double *)calloc(m_config->num_shader(),sizeof(double)); + m_num_imul_acesses[PREV_STAT_IDX]=(double *)calloc(m_config->num_shader(),sizeof(double)); + m_num_imul24_acesses[PREV_STAT_IDX]=(double *)calloc(m_config->num_shader(),sizeof(double)); + m_num_imul32_acesses[PREV_STAT_IDX]=(double *)calloc(m_config->num_shader(),sizeof(double)); + m_num_fpmul_acesses[PREV_STAT_IDX]=(double *)calloc(m_config->num_shader(),sizeof(double)); + m_num_idiv_acesses[PREV_STAT_IDX]=(double *)calloc(m_config->num_shader(),sizeof(double)); + m_num_fpdiv_acesses[PREV_STAT_IDX]=(double *)calloc(m_config->num_shader(),sizeof(double)); + m_num_dp_acesses[PREV_STAT_IDX]=(double *)calloc(m_config->num_shader(),sizeof(double)); + m_num_dpmul_acesses[PREV_STAT_IDX]=(double *)calloc(m_config->num_shader(),sizeof(double)); + m_num_dpdiv_acesses[PREV_STAT_IDX]=(double *)calloc(m_config->num_shader(),sizeof(double)); + m_num_tensor_core_acesses[PREV_STAT_IDX]=(double *)calloc(m_config->num_shader(),sizeof(double)); + m_num_const_acesses[PREV_STAT_IDX]=(double *)calloc(m_config->num_shader(),sizeof(double)); + m_num_tex_acesses[PREV_STAT_IDX]=(double *)calloc(m_config->num_shader(),sizeof(double)); + m_num_sp_acesses[PREV_STAT_IDX]=(double *)calloc(m_config->num_shader(),sizeof(double)); + m_num_sfu_acesses[PREV_STAT_IDX]=(double *)calloc(m_config->num_shader(),sizeof(double)); + m_num_sqrt_acesses[PREV_STAT_IDX]=(double *)calloc(m_config->num_shader(),sizeof(double)); + m_num_log_acesses[PREV_STAT_IDX]=(double *)calloc(m_config->num_shader(),sizeof(double)); + m_num_sin_acesses[PREV_STAT_IDX]=(double *)calloc(m_config->num_shader(),sizeof(double)); + m_num_exp_acesses[PREV_STAT_IDX]=(double *)calloc(m_config->num_shader(),sizeof(double)); + m_num_mem_acesses[PREV_STAT_IDX]=(double *)calloc(m_config->num_shader(),sizeof(double)); + m_num_sp_committed[PREV_STAT_IDX]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_num_sfu_committed[PREV_STAT_IDX]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_num_mem_committed[PREV_STAT_IDX]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_read_regfile_acesses[PREV_STAT_IDX]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_write_regfile_acesses[PREV_STAT_IDX]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_non_rf_operands[PREV_STAT_IDX]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_active_sp_lanes[PREV_STAT_IDX]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_active_sfu_lanes[PREV_STAT_IDX]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_active_exu_threads[PREV_STAT_IDX]=(double *)calloc(m_config->num_shader(),sizeof(double)); + m_active_exu_warps[PREV_STAT_IDX]=(double *)calloc(m_config->num_shader(),sizeof(double)); + - m_pipeline_duty_cycle[PREV_STAT_IDX] = - (float *)calloc(m_config->num_shader(), sizeof(float)); - m_num_decoded_insn[PREV_STAT_IDX] = - (unsigned *)calloc(m_config->num_shader(), sizeof(unsigned)); - m_num_FPdecoded_insn[PREV_STAT_IDX] = - (unsigned *)calloc(m_config->num_shader(), sizeof(unsigned)); - m_num_INTdecoded_insn[PREV_STAT_IDX] = - (unsigned *)calloc(m_config->num_shader(), sizeof(unsigned)); - m_num_storequeued_insn[PREV_STAT_IDX] = - (unsigned *)calloc(m_config->num_shader(), sizeof(unsigned)); - m_num_loadqueued_insn[PREV_STAT_IDX] = - (unsigned *)calloc(m_config->num_shader(), sizeof(unsigned)); - m_num_ialu_acesses[PREV_STAT_IDX] = - (unsigned *)calloc(m_config->num_shader(), sizeof(unsigned)); - m_num_fp_acesses[PREV_STAT_IDX] = - (unsigned *)calloc(m_config->num_shader(), sizeof(unsigned)); - m_num_tex_inst[PREV_STAT_IDX] = - (unsigned *)calloc(m_config->num_shader(), sizeof(unsigned)); - m_num_imul_acesses[PREV_STAT_IDX] = - (unsigned *)calloc(m_config->num_shader(), sizeof(unsigned)); - m_num_imul24_acesses[PREV_STAT_IDX] = - (unsigned *)calloc(m_config->num_shader(), sizeof(unsigned)); - m_num_imul32_acesses[PREV_STAT_IDX] = - (unsigned *)calloc(m_config->num_shader(), sizeof(unsigned)); - m_num_fpmul_acesses[PREV_STAT_IDX] = - (unsigned *)calloc(m_config->num_shader(), sizeof(unsigned)); - m_num_idiv_acesses[PREV_STAT_IDX] = - (unsigned *)calloc(m_config->num_shader(), sizeof(unsigned)); - m_num_fpdiv_acesses[PREV_STAT_IDX] = - (unsigned *)calloc(m_config->num_shader(), sizeof(unsigned)); - m_num_sp_acesses[PREV_STAT_IDX] = - (unsigned *)calloc(m_config->num_shader(), sizeof(unsigned)); - m_num_sfu_acesses[PREV_STAT_IDX] = - (unsigned *)calloc(m_config->num_shader(), sizeof(unsigned)); - m_num_trans_acesses[PREV_STAT_IDX] = - (unsigned *)calloc(m_config->num_shader(), sizeof(unsigned)); - m_num_mem_acesses[PREV_STAT_IDX] = - (unsigned *)calloc(m_config->num_shader(), sizeof(unsigned)); - m_num_sp_committed[PREV_STAT_IDX] = - (unsigned *)calloc(m_config->num_shader(), sizeof(unsigned)); - m_num_sfu_committed[PREV_STAT_IDX] = - (unsigned *)calloc(m_config->num_shader(), sizeof(unsigned)); - m_num_mem_committed[PREV_STAT_IDX] = - (unsigned *)calloc(m_config->num_shader(), sizeof(unsigned)); - m_read_regfile_acesses[PREV_STAT_IDX] = - (unsigned *)calloc(m_config->num_shader(), sizeof(unsigned)); - m_write_regfile_acesses[PREV_STAT_IDX] = - (unsigned *)calloc(m_config->num_shader(), sizeof(unsigned)); - m_non_rf_operands[PREV_STAT_IDX] = - (unsigned *)calloc(m_config->num_shader(), sizeof(unsigned)); - m_active_sp_lanes[PREV_STAT_IDX] = - (unsigned *)calloc(m_config->num_shader(), sizeof(unsigned)); - m_active_sfu_lanes[PREV_STAT_IDX] = - (unsigned *)calloc(m_config->num_shader(), sizeof(unsigned)); } void power_core_stat_t::save_stats() { for (unsigned i = 0; i < m_config->num_shader(); ++i) { - m_pipeline_duty_cycle[PREV_STAT_IDX][i] = - m_pipeline_duty_cycle[CURRENT_STAT_IDX][i]; - m_num_decoded_insn[PREV_STAT_IDX][i] = - m_num_decoded_insn[CURRENT_STAT_IDX][i]; - m_num_FPdecoded_insn[PREV_STAT_IDX][i] = - m_num_FPdecoded_insn[CURRENT_STAT_IDX][i]; - m_num_INTdecoded_insn[PREV_STAT_IDX][i] = - m_num_INTdecoded_insn[CURRENT_STAT_IDX][i]; - m_num_storequeued_insn[PREV_STAT_IDX][i] = - m_num_storequeued_insn[CURRENT_STAT_IDX][i]; - m_num_loadqueued_insn[PREV_STAT_IDX][i] = - m_num_loadqueued_insn[CURRENT_STAT_IDX][i]; - m_num_ialu_acesses[PREV_STAT_IDX][i] = - m_num_ialu_acesses[CURRENT_STAT_IDX][i]; - m_num_fp_acesses[PREV_STAT_IDX][i] = m_num_fp_acesses[CURRENT_STAT_IDX][i]; - m_num_tex_inst[PREV_STAT_IDX][i] = m_num_tex_inst[CURRENT_STAT_IDX][i]; - m_num_imul_acesses[PREV_STAT_IDX][i] = - m_num_imul_acesses[CURRENT_STAT_IDX][i]; - m_num_imul24_acesses[PREV_STAT_IDX][i] = - m_num_imul24_acesses[CURRENT_STAT_IDX][i]; - m_num_imul32_acesses[PREV_STAT_IDX][i] = - m_num_imul32_acesses[CURRENT_STAT_IDX][i]; - m_num_fpmul_acesses[PREV_STAT_IDX][i] = - m_num_fpmul_acesses[CURRENT_STAT_IDX][i]; - m_num_idiv_acesses[PREV_STAT_IDX][i] = - m_num_idiv_acesses[CURRENT_STAT_IDX][i]; - m_num_fpdiv_acesses[PREV_STAT_IDX][i] = - m_num_fpdiv_acesses[CURRENT_STAT_IDX][i]; - m_num_sp_acesses[PREV_STAT_IDX][i] = m_num_sp_acesses[CURRENT_STAT_IDX][i]; - m_num_sfu_acesses[PREV_STAT_IDX][i] = - m_num_sfu_acesses[CURRENT_STAT_IDX][i]; - m_num_trans_acesses[PREV_STAT_IDX][i] = - m_num_trans_acesses[CURRENT_STAT_IDX][i]; - m_num_mem_acesses[PREV_STAT_IDX][i] = - m_num_mem_acesses[CURRENT_STAT_IDX][i]; - m_num_sp_committed[PREV_STAT_IDX][i] = - m_num_sp_committed[CURRENT_STAT_IDX][i]; - m_num_sfu_committed[PREV_STAT_IDX][i] = - m_num_sfu_committed[CURRENT_STAT_IDX][i]; - m_num_mem_committed[PREV_STAT_IDX][i] = - m_num_mem_committed[CURRENT_STAT_IDX][i]; - m_read_regfile_acesses[PREV_STAT_IDX][i] = - m_read_regfile_acesses[CURRENT_STAT_IDX][i]; - m_write_regfile_acesses[PREV_STAT_IDX][i] = - m_write_regfile_acesses[CURRENT_STAT_IDX][i]; - m_non_rf_operands[PREV_STAT_IDX][i] = - m_non_rf_operands[CURRENT_STAT_IDX][i]; - m_active_sp_lanes[PREV_STAT_IDX][i] = - m_active_sp_lanes[CURRENT_STAT_IDX][i]; - m_active_sfu_lanes[PREV_STAT_IDX][i] = - m_active_sfu_lanes[CURRENT_STAT_IDX][i]; + m_pipeline_duty_cycle[PREV_STAT_IDX][i]=m_pipeline_duty_cycle[CURRENT_STAT_IDX][i]; + m_num_decoded_insn[PREV_STAT_IDX][i]= m_num_decoded_insn[CURRENT_STAT_IDX][i]; + m_num_FPdecoded_insn[PREV_STAT_IDX][i]=m_num_FPdecoded_insn[CURRENT_STAT_IDX][i]; + m_num_INTdecoded_insn[PREV_STAT_IDX][i]=m_num_INTdecoded_insn[CURRENT_STAT_IDX][i]; + m_num_storequeued_insn[PREV_STAT_IDX][i]=m_num_storequeued_insn[CURRENT_STAT_IDX][i]; + m_num_loadqueued_insn[PREV_STAT_IDX][i]=m_num_loadqueued_insn[CURRENT_STAT_IDX][i]; + m_num_ialu_acesses[PREV_STAT_IDX][i]=m_num_ialu_acesses[CURRENT_STAT_IDX][i]; + m_num_fp_acesses[PREV_STAT_IDX][i]=m_num_fp_acesses[CURRENT_STAT_IDX][i]; + m_num_tex_inst[PREV_STAT_IDX][i]=m_num_tex_inst[CURRENT_STAT_IDX][i]; + m_num_imul_acesses[PREV_STAT_IDX][i]=m_num_imul_acesses[CURRENT_STAT_IDX][i]; + m_num_imul24_acesses[PREV_STAT_IDX][i]=m_num_imul24_acesses[CURRENT_STAT_IDX][i]; + m_num_imul32_acesses[PREV_STAT_IDX][i]=m_num_imul32_acesses[CURRENT_STAT_IDX][i]; + m_num_fpmul_acesses[PREV_STAT_IDX][i]=m_num_fpmul_acesses[CURRENT_STAT_IDX][i]; + m_num_idiv_acesses[PREV_STAT_IDX][i]=m_num_idiv_acesses[CURRENT_STAT_IDX][i]; + m_num_fpdiv_acesses[PREV_STAT_IDX][i]=m_num_fpdiv_acesses[CURRENT_STAT_IDX][i]; + m_num_sp_acesses[PREV_STAT_IDX][i]=m_num_sp_acesses[CURRENT_STAT_IDX][i]; + m_num_sfu_acesses[PREV_STAT_IDX][i]=m_num_sfu_acesses[CURRENT_STAT_IDX][i]; + m_num_sqrt_acesses[PREV_STAT_IDX][i]=m_num_sqrt_acesses[CURRENT_STAT_IDX][i]; + m_num_log_acesses[PREV_STAT_IDX][i]=m_num_log_acesses[CURRENT_STAT_IDX][i]; + m_num_sin_acesses[PREV_STAT_IDX][i]=m_num_sin_acesses[CURRENT_STAT_IDX][i]; + m_num_exp_acesses[PREV_STAT_IDX][i]=m_num_exp_acesses[CURRENT_STAT_IDX][i]; + m_num_dp_acesses[PREV_STAT_IDX][i]=m_num_dp_acesses[CURRENT_STAT_IDX][i]; + m_num_dpmul_acesses[PREV_STAT_IDX][i]=m_num_dpmul_acesses[CURRENT_STAT_IDX][i]; + m_num_dpdiv_acesses[PREV_STAT_IDX][i]=m_num_dpdiv_acesses[CURRENT_STAT_IDX][i]; + m_num_tensor_core_acesses[PREV_STAT_IDX][i]=m_num_tensor_core_acesses[CURRENT_STAT_IDX][i]; + m_num_const_acesses[PREV_STAT_IDX][i]=m_num_const_acesses[CURRENT_STAT_IDX][i]; + m_num_tex_acesses[PREV_STAT_IDX][i]=m_num_tex_acesses[CURRENT_STAT_IDX][i]; + m_num_mem_acesses[PREV_STAT_IDX][i]=m_num_mem_acesses[CURRENT_STAT_IDX][i]; + m_num_sp_committed[PREV_STAT_IDX][i]=m_num_sp_committed[CURRENT_STAT_IDX][i]; + m_num_sfu_committed[PREV_STAT_IDX][i]=m_num_sfu_committed[CURRENT_STAT_IDX][i]; + m_num_mem_committed[PREV_STAT_IDX][i]=m_num_mem_committed[CURRENT_STAT_IDX][i]; + m_read_regfile_acesses[PREV_STAT_IDX][i]=m_read_regfile_acesses[CURRENT_STAT_IDX][i]; + m_write_regfile_acesses[PREV_STAT_IDX][i]=m_write_regfile_acesses[CURRENT_STAT_IDX][i]; + m_non_rf_operands[PREV_STAT_IDX][i]=m_non_rf_operands[CURRENT_STAT_IDX][i]; + m_active_sp_lanes[PREV_STAT_IDX][i]=m_active_sp_lanes[CURRENT_STAT_IDX][i]; + m_active_sfu_lanes[PREV_STAT_IDX][i]=m_active_sfu_lanes[CURRENT_STAT_IDX][i]; + m_active_exu_threads[PREV_STAT_IDX][i]=m_active_exu_threads[CURRENT_STAT_IDX][i]; + m_active_exu_warps[PREV_STAT_IDX][i]=m_active_exu_warps[CURRENT_STAT_IDX][i]; } } @@ -356,6 +381,51 @@ power_stat_t::power_stat_t(const shader_core_config *shader_config, m_active_sms = active_sms; m_config = shader_config; m_mem_config = mem_config; + l1r_hits_kernel = 0; + l1r_misses_kernel = 0; + l1w_hits_kernel = 0; + l1w_misses_kernel = 0; + shared_accesses_kernel = 0; + cc_accesses_kernel = 0; + dram_rd_kernel = 0; + dram_wr_kernel = 0; + dram_pre_kernel = 0; + l1i_hits_kernel =0; + l1i_misses_kernel =0; + l2r_hits_kernel =0; + l2r_misses_kernel =0; + l2w_hits_kernel =0; + l2w_misses_kernel =0; + noc_tr_kernel = 0; + noc_rc_kernel = 0; + + tot_inst_execution = 0; + tot_int_inst_execution = 0; + tot_fp_inst_execution = 0; + commited_inst_execution = 0; + ialu_acc_execution = 0; + imul24_acc_execution = 0; + imul32_acc_execution = 0; + imul_acc_execution = 0; + idiv_acc_execution = 0; + dp_acc_execution = 0; + dpmul_acc_execution = 0; + dpdiv_acc_execution = 0; + fp_acc_execution = 0; + fpmul_acc_execution = 0; + fpdiv_acc_execution = 0; + sqrt_acc_execution = 0; + log_acc_execution = 0; + sin_acc_execution = 0; + exp_acc_execution = 0; + tensor_acc_execution = 0; + tex_acc_execution = 0; + tot_fpu_acc_execution = 0; + tot_sfu_acc_execution = 0; + tot_threads_acc_execution = 0; + tot_warps_acc_execution = 0; + sp_active_lanes_execution = 0; + sfu_active_lanes_execution = 0; } void power_stat_t::visualizer_print(gzFile visualizer_file) { diff --git a/src/gpgpu-sim/power_stat.h b/src/gpgpu-sim/power_stat.h index c469db3..d40f1d9 100644 --- a/src/gpgpu-sim/power_stat.h +++ b/src/gpgpu-sim/power_stat.h @@ -1,18 +1,20 @@ -// Copyright (c) 2009-2011, Tor M. Aamodt, Ahmed El-Shafiey, Tayler Hetherington -// The University of British Columbia +// Copyright (c) 2009-2021, Tor M. Aamodt, Ahmed El-Shafiey, Tayler Hetherington, Vijay Kandiah, Nikos Hardavellas, +// Mahmoud Khairy, Junrui Pan, Timothy G. Rogers +// The University of British Columbia, Northwestern University, Purdue University // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // -// Redistributions of source code must retain the above copyright notice, this -// list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. Neither the name of -// The University of British Columbia nor the names of its contributors may be -// used to endorse or promote products derived from this software without -// specific prior written permission. +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer; +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution; +// 3. Neither the names of The University of British Columbia, Northwestern +// University nor the names of their contributors may be used to +// endorse or promote products derived from this software without specific +// prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE @@ -51,29 +53,40 @@ struct shader_core_power_stats_pod { unsigned *m_num_INTdecoded_insn[NUM_STAT_IDX]; // number of instructions committed // by this shader core - unsigned *m_num_storequeued_insn[NUM_STAT_IDX]; - unsigned *m_num_loadqueued_insn[NUM_STAT_IDX]; - unsigned *m_num_ialu_acesses[NUM_STAT_IDX]; - unsigned *m_num_fp_acesses[NUM_STAT_IDX]; - unsigned *m_num_tex_inst[NUM_STAT_IDX]; - unsigned *m_num_imul_acesses[NUM_STAT_IDX]; - unsigned *m_num_imul32_acesses[NUM_STAT_IDX]; - unsigned *m_num_imul24_acesses[NUM_STAT_IDX]; - unsigned *m_num_fpmul_acesses[NUM_STAT_IDX]; - unsigned *m_num_idiv_acesses[NUM_STAT_IDX]; - unsigned *m_num_fpdiv_acesses[NUM_STAT_IDX]; - unsigned *m_num_sp_acesses[NUM_STAT_IDX]; - unsigned *m_num_sfu_acesses[NUM_STAT_IDX]; - unsigned *m_num_trans_acesses[NUM_STAT_IDX]; - unsigned *m_num_mem_acesses[NUM_STAT_IDX]; - unsigned *m_num_sp_committed[NUM_STAT_IDX]; - unsigned *m_num_sfu_committed[NUM_STAT_IDX]; - unsigned *m_num_mem_committed[NUM_STAT_IDX]; - unsigned *m_active_sp_lanes[NUM_STAT_IDX]; - unsigned *m_active_sfu_lanes[NUM_STAT_IDX]; - unsigned *m_read_regfile_acesses[NUM_STAT_IDX]; - unsigned *m_write_regfile_acesses[NUM_STAT_IDX]; - unsigned *m_non_rf_operands[NUM_STAT_IDX]; + unsigned *m_num_storequeued_insn[NUM_STAT_IDX]; + unsigned *m_num_loadqueued_insn[NUM_STAT_IDX]; + unsigned *m_num_tex_inst[NUM_STAT_IDX]; + double *m_num_ialu_acesses[NUM_STAT_IDX]; + double *m_num_fp_acesses[NUM_STAT_IDX]; + double *m_num_imul_acesses[NUM_STAT_IDX]; + double *m_num_imul32_acesses[NUM_STAT_IDX]; + double *m_num_imul24_acesses[NUM_STAT_IDX]; + double *m_num_fpmul_acesses[NUM_STAT_IDX]; + double *m_num_idiv_acesses[NUM_STAT_IDX]; + double *m_num_fpdiv_acesses[NUM_STAT_IDX]; + double *m_num_dp_acesses[NUM_STAT_IDX]; + double *m_num_dpmul_acesses[NUM_STAT_IDX]; + double *m_num_dpdiv_acesses[NUM_STAT_IDX]; + double *m_num_sp_acesses[NUM_STAT_IDX]; + double *m_num_sfu_acesses[NUM_STAT_IDX]; + double *m_num_sqrt_acesses[NUM_STAT_IDX]; + double *m_num_log_acesses[NUM_STAT_IDX]; + double *m_num_sin_acesses[NUM_STAT_IDX]; + double *m_num_exp_acesses[NUM_STAT_IDX]; + double *m_num_tensor_core_acesses[NUM_STAT_IDX]; + double *m_num_const_acesses[NUM_STAT_IDX]; + double *m_num_tex_acesses[NUM_STAT_IDX]; + double *m_num_mem_acesses[NUM_STAT_IDX]; + unsigned *m_num_sp_committed[NUM_STAT_IDX]; + unsigned *m_num_sfu_committed[NUM_STAT_IDX]; + unsigned *m_num_mem_committed[NUM_STAT_IDX]; + unsigned *m_active_sp_lanes[NUM_STAT_IDX]; + unsigned *m_active_sfu_lanes[NUM_STAT_IDX]; + double *m_active_exu_threads[NUM_STAT_IDX]; + double *m_active_exu_warps[NUM_STAT_IDX]; + unsigned *m_read_regfile_acesses[NUM_STAT_IDX]; + unsigned *m_write_regfile_acesses[NUM_STAT_IDX]; + unsigned *m_non_rf_operands[NUM_STAT_IDX]; }; class power_core_stat_t : public shader_core_power_stats_pod { @@ -84,6 +97,7 @@ class power_core_stat_t : public shader_core_power_stats_pod { void print(FILE *fout); void init(); void save_stats(); + private: shader_core_stats *m_core_stats; @@ -96,8 +110,7 @@ struct mem_power_stats_pod { class cache_stats core_cache_stats[NUM_STAT_IDX]; // Total core stats class cache_stats l2_cache_stats[NUM_STAT_IDX]; // Total L2 partition stats - unsigned *shmem_read_access[NUM_STAT_IDX]; // Shared memory access - + unsigned *shmem_access[NUM_STAT_IDX]; // Shared memory access // Low level DRAM stats unsigned *n_cmd[NUM_STAT_IDX]; unsigned *n_activity[NUM_STAT_IDX]; @@ -106,6 +119,7 @@ struct mem_power_stats_pod { unsigned *n_pre[NUM_STAT_IDX]; unsigned *n_rd[NUM_STAT_IDX]; unsigned *n_wr[NUM_STAT_IDX]; + unsigned *n_wr_WB[NUM_STAT_IDX]; unsigned *n_req[NUM_STAT_IDX]; // Interconnect stats @@ -144,34 +158,88 @@ class power_stat_t { *m_average_pipeline_duty_cycle = 0; *m_active_sms = 0; } - - unsigned get_total_inst() { - unsigned total_inst = 0; + void clear(); + unsigned l1i_misses_kernel; + unsigned l1i_hits_kernel; + unsigned long long l1r_hits_kernel; + unsigned long long l1r_misses_kernel; + unsigned long long l1w_hits_kernel; + unsigned long long l1w_misses_kernel; + unsigned long long shared_accesses_kernel; + unsigned long long cc_accesses_kernel; + unsigned long long dram_rd_kernel; + unsigned long long dram_wr_kernel; + unsigned long long dram_pre_kernel; + unsigned long long l2r_hits_kernel; + unsigned long long l2r_misses_kernel; + unsigned long long l2w_hits_kernel; + unsigned long long l2w_misses_kernel; + unsigned long long noc_tr_kernel; + unsigned long long noc_rc_kernel; + unsigned long long tot_inst_execution; + unsigned long long tot_int_inst_execution; + unsigned long long tot_fp_inst_execution; + unsigned long long commited_inst_execution; + unsigned long long ialu_acc_execution; + unsigned long long imul24_acc_execution; + unsigned long long imul32_acc_execution; + unsigned long long imul_acc_execution; + unsigned long long idiv_acc_execution; + unsigned long long dp_acc_execution; + unsigned long long dpmul_acc_execution; + unsigned long long dpdiv_acc_execution; + unsigned long long fp_acc_execution; + unsigned long long fpmul_acc_execution; + unsigned long long fpdiv_acc_execution; + unsigned long long sqrt_acc_execution; + unsigned long long log_acc_execution; + unsigned long long sin_acc_execution; + unsigned long long exp_acc_execution; + unsigned long long tensor_acc_execution; + unsigned long long tex_acc_execution; + unsigned long long tot_fpu_acc_execution; + unsigned long long tot_sfu_acc_execution; + unsigned long long tot_threads_acc_execution; + unsigned long long tot_warps_acc_execution; + unsigned long long sp_active_lanes_execution; + unsigned long long sfu_active_lanes_execution; + double get_total_inst(bool aggregate_stat) { + double total_inst = 0; for (unsigned i = 0; i < m_config->num_shader(); i++) { - total_inst += (pwr_core_stat->m_num_decoded_insn[CURRENT_STAT_IDX][i]) - + if(aggregate_stat) + total_inst += (pwr_core_stat->m_num_decoded_insn[CURRENT_STAT_IDX][i]); + else + total_inst += (pwr_core_stat->m_num_decoded_insn[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_num_decoded_insn[PREV_STAT_IDX][i]); } return total_inst; } - unsigned get_total_int_inst() { - unsigned total_inst = 0; + double get_total_int_inst(bool aggregate_stat) { + double total_inst = 0; for (unsigned i = 0; i < m_config->num_shader(); i++) { - total_inst += + if(aggregate_stat) + total_inst += + (pwr_core_stat->m_num_INTdecoded_insn[CURRENT_STAT_IDX][i]); + else + total_inst += (pwr_core_stat->m_num_INTdecoded_insn[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_num_INTdecoded_insn[PREV_STAT_IDX][i]); } return total_inst; } - unsigned get_total_fp_inst() { - unsigned total_inst = 0; + double get_total_fp_inst(bool aggregate_stat) { + double total_inst = 0; for (unsigned i = 0; i < m_config->num_shader(); i++) { - total_inst += (pwr_core_stat->m_num_FPdecoded_insn[CURRENT_STAT_IDX][i]) - + if(aggregate_stat) + total_inst += (pwr_core_stat->m_num_FPdecoded_insn[CURRENT_STAT_IDX][i]); + else + total_inst += (pwr_core_stat->m_num_FPdecoded_insn[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_num_FPdecoded_insn[PREV_STAT_IDX][i]); } return total_inst; } - unsigned get_total_load_inst() { - unsigned total_inst = 0; + double get_total_load_inst() { + double total_inst = 0; for (unsigned i = 0; i < m_config->num_shader(); i++) { total_inst += (pwr_core_stat->m_num_loadqueued_insn[CURRENT_STAT_IDX][i]) - @@ -179,8 +247,8 @@ class power_stat_t { } return total_inst; } - unsigned get_total_store_inst() { - unsigned total_inst = 0; + double get_total_store_inst() { + double total_inst = 0; for (unsigned i = 0; i < m_config->num_shader(); i++) { total_inst += (pwr_core_stat->m_num_storequeued_insn[CURRENT_STAT_IDX][i]) - @@ -188,34 +256,39 @@ class power_stat_t { } return total_inst; } - unsigned get_sp_committed_inst() { - unsigned total_inst = 0; + double get_sp_committed_inst() { + double total_inst = 0; for (unsigned i = 0; i < m_config->num_shader(); i++) { total_inst += (pwr_core_stat->m_num_sp_committed[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_num_sp_committed[PREV_STAT_IDX][i]); } return total_inst; } - unsigned get_sfu_committed_inst() { - unsigned total_inst = 0; + double get_sfu_committed_inst() { + double total_inst = 0; for (unsigned i = 0; i < m_config->num_shader(); i++) { total_inst += (pwr_core_stat->m_num_sfu_committed[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_num_sfu_committed[PREV_STAT_IDX][i]); } return total_inst; } - unsigned get_mem_committed_inst() { - unsigned total_inst = 0; + double get_mem_committed_inst() { + double total_inst = 0; for (unsigned i = 0; i < m_config->num_shader(); i++) { total_inst += (pwr_core_stat->m_num_mem_committed[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_num_mem_committed[PREV_STAT_IDX][i]); } return total_inst; } - unsigned get_committed_inst() { - unsigned total_inst = 0; + double get_committed_inst(bool aggregate_stat) { + double total_inst = 0; for (unsigned i = 0; i < m_config->num_shader(); i++) { - total_inst += (pwr_core_stat->m_num_mem_committed[CURRENT_STAT_IDX][i]) - + if(aggregate_stat) + total_inst += (pwr_core_stat->m_num_mem_committed[CURRENT_STAT_IDX][i]) + + (pwr_core_stat->m_num_sfu_committed[CURRENT_STAT_IDX][i]) + + (pwr_core_stat->m_num_sp_committed[CURRENT_STAT_IDX][i]); + else + total_inst += (pwr_core_stat->m_num_mem_committed[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_num_mem_committed[PREV_STAT_IDX][i]) + (pwr_core_stat->m_num_sfu_committed[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_num_sfu_committed[PREV_STAT_IDX][i]) + @@ -224,19 +297,27 @@ class power_stat_t { } return total_inst; } - unsigned get_regfile_reads() { - unsigned total_inst = 0; + double get_regfile_reads(bool aggregate_stat) { + double total_inst = 0; for (unsigned i = 0; i < m_config->num_shader(); i++) { - total_inst += + if(aggregate_stat) + total_inst += + (pwr_core_stat->m_read_regfile_acesses[CURRENT_STAT_IDX][i]); + else + total_inst += (pwr_core_stat->m_read_regfile_acesses[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_read_regfile_acesses[PREV_STAT_IDX][i]); } return total_inst; } - unsigned get_regfile_writes() { - unsigned total_inst = 0; + double get_regfile_writes(bool aggregate_stat) { + double total_inst = 0; for (unsigned i = 0; i < m_config->num_shader(); i++) { - total_inst += + if(aggregate_stat) + total_inst += + (pwr_core_stat->m_write_regfile_acesses[CURRENT_STAT_IDX][i]); + else + total_inst += (pwr_core_stat->m_write_regfile_acesses[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_write_regfile_acesses[PREV_STAT_IDX][i]); } @@ -253,17 +334,20 @@ class power_stat_t { return total_inst; } - unsigned get_non_regfile_operands() { - unsigned total_inst = 0; + double get_non_regfile_operands(bool aggregate_stat) { + double total_inst = 0; for (unsigned i = 0; i < m_config->num_shader(); i++) { - total_inst += (pwr_core_stat->m_non_rf_operands[CURRENT_STAT_IDX][i]) - + if(aggregate_stat) + total_inst += (pwr_core_stat->m_non_rf_operands[CURRENT_STAT_IDX][i]); + else + total_inst += (pwr_core_stat->m_non_rf_operands[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_non_rf_operands[PREV_STAT_IDX][i]); } return total_inst; } - unsigned get_sp_accessess() { - unsigned total_inst = 0; + double get_sp_accessess() { + double total_inst = 0; for (unsigned i = 0; i < m_config->num_shader(); i++) { total_inst += (pwr_core_stat->m_num_sp_acesses[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_num_sp_acesses[PREV_STAT_IDX][i]); @@ -271,25 +355,58 @@ class power_stat_t { return total_inst; } - unsigned get_sfu_accessess() { - unsigned total_inst = 0; + double get_sfu_accessess() { + double total_inst = 0; for (unsigned i = 0; i < m_config->num_shader(); i++) { total_inst += (pwr_core_stat->m_num_sfu_acesses[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_num_sfu_acesses[PREV_STAT_IDX][i]); } return total_inst; } - unsigned get_trans_accessess() { - unsigned total_inst = 0; - for (unsigned i = 0; i < m_config->num_shader(); i++) { - total_inst += (pwr_core_stat->m_num_trans_acesses[CURRENT_STAT_IDX][i]) - - (pwr_core_stat->m_num_trans_acesses[PREV_STAT_IDX][i]); - } - return total_inst; + + double get_sqrt_accessess(bool aggregate_stat){ + double total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + if(aggregate_stat) + total_inst+=(pwr_core_stat->m_num_sqrt_acesses[CURRENT_STAT_IDX][i]); + else + total_inst+=(pwr_core_stat->m_num_sqrt_acesses[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_num_sqrt_acesses[PREV_STAT_IDX][i]); + } + return total_inst; + } + double get_log_accessess(bool aggregate_stat){ + double total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + if(aggregate_stat) + total_inst+=(pwr_core_stat->m_num_log_acesses[CURRENT_STAT_IDX][i]); + else + total_inst+=(pwr_core_stat->m_num_log_acesses[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_num_log_acesses[PREV_STAT_IDX][i]); + } + return total_inst; + } + double get_sin_accessess(bool aggregate_stat){ + double total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + if(aggregate_stat) + total_inst+=(pwr_core_stat->m_num_sin_acesses[CURRENT_STAT_IDX][i]); + else + total_inst+=(pwr_core_stat->m_num_sin_acesses[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_num_sin_acesses[PREV_STAT_IDX][i]); + } + return total_inst; + } + double get_exp_accessess(bool aggregate_stat){ + double total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + if(aggregate_stat) + total_inst+=(pwr_core_stat->m_num_exp_acesses[CURRENT_STAT_IDX][i]); + else + total_inst+=(pwr_core_stat->m_num_exp_acesses[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_num_exp_acesses[PREV_STAT_IDX][i]); + } + return total_inst; } - unsigned get_mem_accessess() { - unsigned total_inst = 0; + double get_mem_accessess() { + double total_inst = 0; for (unsigned i = 0; i < m_config->num_shader(); i++) { total_inst += (pwr_core_stat->m_num_mem_acesses[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_num_mem_acesses[PREV_STAT_IDX][i]); @@ -297,66 +414,164 @@ class power_stat_t { return total_inst; } - unsigned get_intdiv_accessess() { - unsigned total_inst = 0; + double get_intdiv_accessess(bool aggregate_stat) { + double total_inst = 0; for (unsigned i = 0; i < m_config->num_shader(); i++) { - total_inst += (pwr_core_stat->m_num_idiv_acesses[CURRENT_STAT_IDX][i]) - + if(aggregate_stat) + total_inst += (pwr_core_stat->m_num_idiv_acesses[CURRENT_STAT_IDX][i]); + else + total_inst += (pwr_core_stat->m_num_idiv_acesses[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_num_idiv_acesses[PREV_STAT_IDX][i]); } return total_inst; } - unsigned get_fpdiv_accessess() { - unsigned total_inst = 0; + double get_fpdiv_accessess(bool aggregate_stat) { + double total_inst = 0; for (unsigned i = 0; i < m_config->num_shader(); i++) { - total_inst += (pwr_core_stat->m_num_fpdiv_acesses[CURRENT_STAT_IDX][i]) - + if(aggregate_stat) + total_inst += (pwr_core_stat->m_num_fpdiv_acesses[CURRENT_STAT_IDX][i]); + else + total_inst += (pwr_core_stat->m_num_fpdiv_acesses[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_num_fpdiv_acesses[PREV_STAT_IDX][i]); } return total_inst; } - unsigned get_intmul32_accessess() { - unsigned total_inst = 0; + double get_intmul32_accessess(bool aggregate_stat) { + double total_inst = 0; for (unsigned i = 0; i < m_config->num_shader(); i++) { - total_inst += (pwr_core_stat->m_num_imul32_acesses[CURRENT_STAT_IDX][i]) - + if(aggregate_stat) + total_inst += (pwr_core_stat->m_num_imul32_acesses[CURRENT_STAT_IDX][i]); + else + total_inst += (pwr_core_stat->m_num_imul32_acesses[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_num_imul32_acesses[PREV_STAT_IDX][i]); } return total_inst; } - unsigned get_intmul24_accessess() { - unsigned total_inst = 0; + double get_intmul24_accessess(bool aggregate_stat) { + double total_inst = 0; for (unsigned i = 0; i < m_config->num_shader(); i++) { - total_inst += (pwr_core_stat->m_num_imul24_acesses[CURRENT_STAT_IDX][i]) - + if(aggregate_stat) + total_inst += (pwr_core_stat->m_num_imul24_acesses[CURRENT_STAT_IDX][i]); + else + total_inst += (pwr_core_stat->m_num_imul24_acesses[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_num_imul24_acesses[PREV_STAT_IDX][i]); } return total_inst; } - unsigned get_intmul_accessess() { - unsigned total_inst = 0; - for (unsigned i = 0; i < m_config->num_shader(); i++) { - total_inst += (pwr_core_stat->m_num_imul_acesses[CURRENT_STAT_IDX][i]) - - (pwr_core_stat->m_num_imul_acesses[PREV_STAT_IDX][i]) + - (pwr_core_stat->m_num_imul24_acesses[CURRENT_STAT_IDX][i]) - - (pwr_core_stat->m_num_imul24_acesses[PREV_STAT_IDX][i]) + - (pwr_core_stat->m_num_imul32_acesses[CURRENT_STAT_IDX][i]) - - (pwr_core_stat->m_num_imul32_acesses[PREV_STAT_IDX][i]); + double get_intmul_accessess(bool aggregate_stat){ + double total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + if(aggregate_stat) + total_inst+= (pwr_core_stat->m_num_imul_acesses[CURRENT_STAT_IDX][i]); + else + total_inst+= (pwr_core_stat->m_num_imul_acesses[CURRENT_STAT_IDX][i]) - + (pwr_core_stat->m_num_imul_acesses[PREV_STAT_IDX][i]); + } + return total_inst; + } + + double get_fpmul_accessess(bool aggregate_stat){ + double total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + if(aggregate_stat) + total_inst += (pwr_core_stat->m_num_fpmul_acesses[CURRENT_STAT_IDX][i]); + else + total_inst += (pwr_core_stat->m_num_fpmul_acesses[CURRENT_STAT_IDX][i]) - + (pwr_core_stat->m_num_fpmul_acesses[PREV_STAT_IDX][i]); } return total_inst; } - unsigned get_fpmul_accessess() { - unsigned total_inst = 0; - for (unsigned i = 0; i < m_config->num_shader(); i++) { - total_inst += (pwr_core_stat->m_num_fp_acesses[CURRENT_STAT_IDX][i]) - - (pwr_core_stat->m_num_fp_acesses[PREV_STAT_IDX][i]); + double get_fp_accessess(bool aggregate_stat){ + double total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + if(aggregate_stat) + total_inst += (pwr_core_stat->m_num_fp_acesses[CURRENT_STAT_IDX][i]); + else + total_inst += (pwr_core_stat->m_num_fp_acesses[CURRENT_STAT_IDX][i]) - + (pwr_core_stat->m_num_fp_acesses[PREV_STAT_IDX][i]); } return total_inst; } - float get_sp_active_lanes() { - unsigned total_inst = 0; + double get_dp_accessess(bool aggregate_stat){ + double total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + if(aggregate_stat) + total_inst += (pwr_core_stat->m_num_dp_acesses[CURRENT_STAT_IDX][i]); + else + total_inst += (pwr_core_stat->m_num_dp_acesses[CURRENT_STAT_IDX][i]) - + (pwr_core_stat->m_num_dp_acesses[PREV_STAT_IDX][i]); + } + return total_inst; + } + + double get_dpmul_accessess(bool aggregate_stat){ + double total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + if(aggregate_stat) + total_inst += (pwr_core_stat->m_num_dpmul_acesses[CURRENT_STAT_IDX][i]); + else + total_inst += (pwr_core_stat->m_num_dpmul_acesses[CURRENT_STAT_IDX][i]) - + (pwr_core_stat->m_num_dpmul_acesses[PREV_STAT_IDX][i]); + } + return total_inst; + } + + double get_dpdiv_accessess(bool aggregate_stat){ + double total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + if(aggregate_stat) + total_inst += (pwr_core_stat->m_num_dpdiv_acesses[CURRENT_STAT_IDX][i]); + else + total_inst += (pwr_core_stat->m_num_dpdiv_acesses[CURRENT_STAT_IDX][i]) - + (pwr_core_stat->m_num_dpdiv_acesses[PREV_STAT_IDX][i]); + } + return total_inst; + } + + double get_tensor_accessess(bool aggregate_stat){ + double total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + if(aggregate_stat) + total_inst += (pwr_core_stat->m_num_tensor_core_acesses[CURRENT_STAT_IDX][i]); + else + total_inst += (pwr_core_stat->m_num_tensor_core_acesses[CURRENT_STAT_IDX][i]) - + (pwr_core_stat->m_num_tensor_core_acesses[PREV_STAT_IDX][i]); + } + return total_inst; + } + + double get_const_accessess(bool aggregate_stat){ + double total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + if(aggregate_stat) + total_inst += pwr_core_stat->m_num_const_acesses[CURRENT_STAT_IDX][i]; + else + total_inst += (pwr_core_stat->m_num_const_acesses[CURRENT_STAT_IDX][i]) - + (pwr_core_stat->m_num_const_acesses[PREV_STAT_IDX][i]); + } + return (total_inst); + } + + double get_tex_accessess(bool aggregate_stat){ + double total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + if(aggregate_stat) + total_inst += (pwr_core_stat->m_num_tex_acesses[CURRENT_STAT_IDX][i]); + else + total_inst += (pwr_core_stat->m_num_tex_acesses[CURRENT_STAT_IDX][i]) - + (pwr_core_stat->m_num_tex_acesses[PREV_STAT_IDX][i]); + } + return total_inst; + } + + double get_sp_active_lanes() { + double total_inst = 0; for (unsigned i = 0; i < m_config->num_shader(); i++) { total_inst += (pwr_core_stat->m_active_sp_lanes[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_active_sp_lanes[PREV_STAT_IDX][i]); @@ -365,7 +580,7 @@ class power_stat_t { } float get_sfu_active_lanes() { - unsigned total_inst = 0; + double total_inst = 0; for (unsigned i = 0; i < m_config->num_shader(); i++) { total_inst += (pwr_core_stat->m_active_sfu_lanes[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_active_sfu_lanes[PREV_STAT_IDX][i]); @@ -375,49 +590,141 @@ class power_stat_t { m_config->gpgpu_num_sfu_units; } - unsigned get_tot_fpu_accessess() { - unsigned total_inst = 0; + + float get_active_threads(bool aggregate_stat) { + unsigned total_threads = 0; + unsigned total_warps = 0; + for (unsigned i = 0; i < m_config->num_shader(); i++) { + if(aggregate_stat){ + total_threads += (pwr_core_stat->m_active_exu_threads[CURRENT_STAT_IDX][i]) ; + total_warps += (pwr_core_stat->m_active_exu_warps[CURRENT_STAT_IDX][i]); + } + else{ + total_threads += (pwr_core_stat->m_active_exu_threads[CURRENT_STAT_IDX][i]) - + (pwr_core_stat->m_active_exu_threads[PREV_STAT_IDX][i]); + total_warps += (pwr_core_stat->m_active_exu_warps[CURRENT_STAT_IDX][i]) - + (pwr_core_stat->m_active_exu_warps[PREV_STAT_IDX][i]); + } + } + if(total_warps != 0) + return (float)((float)total_threads / (float)total_warps); + else + return 0; + } + + unsigned long long get_tot_threads_kernel(bool aggregate_stat) { + unsigned total_threads = 0; + for (unsigned i = 0; i < m_config->num_shader(); i++) { + if(aggregate_stat){ + total_threads += (pwr_core_stat->m_active_exu_threads[CURRENT_STAT_IDX][i]) ; + } + else{ + total_threads += (pwr_core_stat->m_active_exu_threads[CURRENT_STAT_IDX][i]) - + (pwr_core_stat->m_active_exu_threads[PREV_STAT_IDX][i]); + } + } + + return total_threads; + } + unsigned long long get_tot_warps_kernel(bool aggregate_stat) { + unsigned long long total_warps = 0; for (unsigned i = 0; i < m_config->num_shader(); i++) { - total_inst += (pwr_core_stat->m_num_fp_acesses[CURRENT_STAT_IDX][i]) - + if(aggregate_stat){ + total_warps += (pwr_core_stat->m_active_exu_warps[CURRENT_STAT_IDX][i]); + } + else{ + total_warps += (pwr_core_stat->m_active_exu_warps[CURRENT_STAT_IDX][i]) - + (pwr_core_stat->m_active_exu_warps[PREV_STAT_IDX][i]); + } + } + return total_warps; + } + + + double get_tot_fpu_accessess(bool aggregate_stat){ + double total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + if(aggregate_stat) + total_inst += (pwr_core_stat->m_num_fp_acesses[CURRENT_STAT_IDX][i])+ + (pwr_core_stat->m_num_dp_acesses[CURRENT_STAT_IDX][i]); + else + total_inst += (pwr_core_stat->m_num_fp_acesses[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_num_fp_acesses[PREV_STAT_IDX][i]) + - (pwr_core_stat->m_num_fpdiv_acesses[CURRENT_STAT_IDX][i]) - - (pwr_core_stat->m_num_fpdiv_acesses[PREV_STAT_IDX][i]) + - (pwr_core_stat->m_num_fpmul_acesses[CURRENT_STAT_IDX][i]) - - (pwr_core_stat->m_num_fpmul_acesses[PREV_STAT_IDX][i]) + - (pwr_core_stat->m_num_imul24_acesses[CURRENT_STAT_IDX][i]) - - (pwr_core_stat->m_num_imul24_acesses[PREV_STAT_IDX][i]) + - (pwr_core_stat->m_num_imul_acesses[CURRENT_STAT_IDX][i]) - - (pwr_core_stat->m_num_imul_acesses[PREV_STAT_IDX][i]); + (pwr_core_stat->m_num_dp_acesses[CURRENT_STAT_IDX][i]) - + (pwr_core_stat->m_num_dp_acesses[PREV_STAT_IDX][i]); } - total_inst += - get_total_load_inst() + get_total_store_inst() + get_tex_inst(); + //total_inst += get_total_load_inst()+get_total_store_inst()+get_tex_inst(); return total_inst; } - unsigned get_tot_sfu_accessess() { - unsigned total_inst = 0; - for (unsigned i = 0; i < m_config->num_shader(); i++) { - total_inst += (pwr_core_stat->m_num_idiv_acesses[CURRENT_STAT_IDX][i]) - + + + double get_tot_sfu_accessess(bool aggregate_stat){ + double total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + if(aggregate_stat) + total_inst += (pwr_core_stat->m_num_idiv_acesses[CURRENT_STAT_IDX][i])+ + (pwr_core_stat->m_num_imul32_acesses[CURRENT_STAT_IDX][i])+ + (pwr_core_stat->m_num_sqrt_acesses[CURRENT_STAT_IDX][i])+ + (pwr_core_stat->m_num_log_acesses[CURRENT_STAT_IDX][i])+ + (pwr_core_stat->m_num_sin_acesses[CURRENT_STAT_IDX][i])+ + (pwr_core_stat->m_num_exp_acesses[CURRENT_STAT_IDX][i])+ + (pwr_core_stat->m_num_fpdiv_acesses[CURRENT_STAT_IDX][i])+ + (pwr_core_stat->m_num_fpmul_acesses[CURRENT_STAT_IDX][i])+ + (pwr_core_stat->m_num_dpmul_acesses[CURRENT_STAT_IDX][i])+ + (pwr_core_stat->m_num_dpdiv_acesses[CURRENT_STAT_IDX][i])+ + (pwr_core_stat->m_num_imul24_acesses[CURRENT_STAT_IDX][i]) + + (pwr_core_stat->m_num_imul_acesses[CURRENT_STAT_IDX][i])+ + (pwr_core_stat->m_num_tensor_core_acesses[CURRENT_STAT_IDX][i])+ + (pwr_core_stat->m_num_tex_acesses[CURRENT_STAT_IDX][i]); + else + total_inst += (pwr_core_stat->m_num_idiv_acesses[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_num_idiv_acesses[PREV_STAT_IDX][i]) + - (pwr_core_stat->m_num_imul32_acesses[CURRENT_STAT_IDX][i]) - + (pwr_core_stat->m_num_imul32_acesses[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_num_imul32_acesses[PREV_STAT_IDX][i]) + - (pwr_core_stat->m_num_trans_acesses[CURRENT_STAT_IDX][i]) - - (pwr_core_stat->m_num_trans_acesses[PREV_STAT_IDX][i]); + (pwr_core_stat->m_num_sqrt_acesses[CURRENT_STAT_IDX][i]) - + (pwr_core_stat->m_num_sqrt_acesses[PREV_STAT_IDX][i]) + + (pwr_core_stat->m_num_log_acesses[CURRENT_STAT_IDX][i]) - + (pwr_core_stat->m_num_log_acesses[PREV_STAT_IDX][i]) + + (pwr_core_stat->m_num_sin_acesses[CURRENT_STAT_IDX][i]) - + (pwr_core_stat->m_num_sin_acesses[PREV_STAT_IDX][i]) + + (pwr_core_stat->m_num_exp_acesses[CURRENT_STAT_IDX][i]) - + (pwr_core_stat->m_num_exp_acesses[PREV_STAT_IDX][i]) + + (pwr_core_stat->m_num_fpdiv_acesses[CURRENT_STAT_IDX][i]) - + (pwr_core_stat->m_num_fpdiv_acesses[PREV_STAT_IDX][i]) + + (pwr_core_stat->m_num_fpmul_acesses[CURRENT_STAT_IDX][i]) - + (pwr_core_stat->m_num_fpmul_acesses[PREV_STAT_IDX][i]) + + (pwr_core_stat->m_num_dpmul_acesses[CURRENT_STAT_IDX][i]) - + (pwr_core_stat->m_num_dpmul_acesses[PREV_STAT_IDX][i]) + + (pwr_core_stat->m_num_dpdiv_acesses[CURRENT_STAT_IDX][i]) - + (pwr_core_stat->m_num_dpdiv_acesses[PREV_STAT_IDX][i]) + + (pwr_core_stat->m_num_imul24_acesses[CURRENT_STAT_IDX][i]) - + (pwr_core_stat->m_num_imul24_acesses[PREV_STAT_IDX][i]) + + (pwr_core_stat->m_num_imul_acesses[CURRENT_STAT_IDX][i]) - + (pwr_core_stat->m_num_imul_acesses[PREV_STAT_IDX][i]) + + (pwr_core_stat->m_num_tensor_core_acesses[CURRENT_STAT_IDX][i]) - + (pwr_core_stat->m_num_tensor_core_acesses[PREV_STAT_IDX][i]) + + (pwr_core_stat->m_num_tex_acesses[CURRENT_STAT_IDX][i]) - + (pwr_core_stat->m_num_tex_acesses[PREV_STAT_IDX][i]); + } return total_inst; } - unsigned get_ialu_accessess() { - unsigned total_inst = 0; + double get_ialu_accessess(bool aggregate_stat) { + double total_inst = 0; for (unsigned i = 0; i < m_config->num_shader(); i++) { - total_inst += (pwr_core_stat->m_num_ialu_acesses[CURRENT_STAT_IDX][i]) - + if(aggregate_stat) + total_inst += (pwr_core_stat->m_num_ialu_acesses[CURRENT_STAT_IDX][i]); + else + total_inst += (pwr_core_stat->m_num_ialu_acesses[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_num_ialu_acesses[PREV_STAT_IDX][i]); } return total_inst; } - unsigned get_tex_inst() { - unsigned total_inst = 0; + double get_tex_inst() { + double total_inst = 0; for (unsigned i = 0; i < m_config->num_shader(); i++) { total_inst += (pwr_core_stat->m_num_tex_inst[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_num_tex_inst[PREV_STAT_IDX][i]); @@ -425,7 +732,7 @@ class power_stat_t { return total_inst; } - unsigned get_constant_c_accesses() { + double get_constant_c_accesses() { enum mem_access_type access_type[] = {CONST_ACC_R}; enum cache_request_status request_status[] = {HIT, MISS, HIT_RESERVED}; unsigned num_access_type = @@ -440,7 +747,7 @@ class power_stat_t { access_type, num_access_type, request_status, num_request_status)); } - unsigned get_constant_c_misses() { + double get_constant_c_misses() { enum mem_access_type access_type[] = {CONST_ACC_R}; enum cache_request_status request_status[] = {MISS}; unsigned num_access_type = @@ -455,10 +762,10 @@ class power_stat_t { access_type, num_access_type, request_status, num_request_status)); } - unsigned get_constant_c_hits() { + double get_constant_c_hits() { return (get_constant_c_accesses() - get_constant_c_misses()); } - unsigned get_texture_c_accesses() { + double get_texture_c_accesses() { enum mem_access_type access_type[] = {TEXTURE_ACC_R}; enum cache_request_status request_status[] = {HIT, MISS, HIT_RESERVED}; unsigned num_access_type = @@ -473,7 +780,7 @@ class power_stat_t { access_type, num_access_type, request_status, num_request_status)); } - unsigned get_texture_c_misses() { + double get_texture_c_misses() { enum mem_access_type access_type[] = {TEXTURE_ACC_R}; enum cache_request_status request_status[] = {MISS}; unsigned num_access_type = @@ -488,205 +795,268 @@ class power_stat_t { access_type, num_access_type, request_status, num_request_status)); } - unsigned get_texture_c_hits() { + double get_texture_c_hits() { return (get_texture_c_accesses() - get_texture_c_misses()); } - unsigned get_inst_c_accesses() { + double get_inst_c_accesses(bool aggregate_stat) { enum mem_access_type access_type[] = {INST_ACC_R}; enum cache_request_status request_status[] = {HIT, MISS, HIT_RESERVED}; unsigned num_access_type = sizeof(access_type) / sizeof(enum mem_access_type); unsigned num_request_status = sizeof(request_status) / sizeof(enum cache_request_status); - - return (pwr_mem_stat->core_cache_stats[CURRENT_STAT_IDX].get_stats( + if(aggregate_stat) + return (pwr_mem_stat->core_cache_stats[CURRENT_STAT_IDX].get_stats( + access_type, num_access_type, request_status, + num_request_status)); + else + return (pwr_mem_stat->core_cache_stats[CURRENT_STAT_IDX].get_stats( access_type, num_access_type, request_status, num_request_status)) - (pwr_mem_stat->core_cache_stats[PREV_STAT_IDX].get_stats( access_type, num_access_type, request_status, num_request_status)); } - unsigned get_inst_c_misses() { + double get_inst_c_misses(bool aggregate_stat) { enum mem_access_type access_type[] = {INST_ACC_R}; enum cache_request_status request_status[] = {MISS}; unsigned num_access_type = sizeof(access_type) / sizeof(enum mem_access_type); unsigned num_request_status = sizeof(request_status) / sizeof(enum cache_request_status); - - return (pwr_mem_stat->core_cache_stats[CURRENT_STAT_IDX].get_stats( + if(aggregate_stat) + return (pwr_mem_stat->core_cache_stats[CURRENT_STAT_IDX].get_stats( + access_type, num_access_type, request_status, + num_request_status)); + else + return (pwr_mem_stat->core_cache_stats[CURRENT_STAT_IDX].get_stats( access_type, num_access_type, request_status, num_request_status)) - (pwr_mem_stat->core_cache_stats[PREV_STAT_IDX].get_stats( access_type, num_access_type, request_status, num_request_status)); } - unsigned get_inst_c_hits() { - return (get_inst_c_accesses() - get_inst_c_misses()); + double get_inst_c_hits(bool aggregate_stat) { + return (get_inst_c_accesses(aggregate_stat) - get_inst_c_misses(aggregate_stat)); } - unsigned get_l1d_read_accesses() { + double get_l1d_read_accesses(bool aggregate_stat) { enum mem_access_type access_type[] = {GLOBAL_ACC_R, LOCAL_ACC_R}; - enum cache_request_status request_status[] = {HIT, MISS, HIT_RESERVED}; + enum cache_request_status request_status[] = {HIT, MISS, SECTOR_MISS}; unsigned num_access_type = sizeof(access_type) / sizeof(enum mem_access_type); unsigned num_request_status = sizeof(request_status) / sizeof(enum cache_request_status); - return (pwr_mem_stat->core_cache_stats[CURRENT_STAT_IDX].get_stats( + if(aggregate_stat){ + return (pwr_mem_stat->core_cache_stats[CURRENT_STAT_IDX].get_stats( + access_type, num_access_type, request_status, + num_request_status)); + } + else{ + return (pwr_mem_stat->core_cache_stats[CURRENT_STAT_IDX].get_stats( access_type, num_access_type, request_status, num_request_status)) - (pwr_mem_stat->core_cache_stats[PREV_STAT_IDX].get_stats( access_type, num_access_type, request_status, num_request_status)); + } } - unsigned get_l1d_read_misses() { + double get_l1d_read_misses(bool aggregate_stat) { + return (get_l1d_read_accesses(aggregate_stat) - get_l1d_read_hits(aggregate_stat)); + } + double get_l1d_read_hits(bool aggregate_stat) { enum mem_access_type access_type[] = {GLOBAL_ACC_R, LOCAL_ACC_R}; - enum cache_request_status request_status[] = {MISS}; + enum cache_request_status request_status[] = {HIT, MSHR_HIT}; unsigned num_access_type = sizeof(access_type) / sizeof(enum mem_access_type); unsigned num_request_status = sizeof(request_status) / sizeof(enum cache_request_status); - return (pwr_mem_stat->core_cache_stats[CURRENT_STAT_IDX].get_stats( + if(aggregate_stat){ + return (pwr_mem_stat->core_cache_stats[CURRENT_STAT_IDX].get_stats( + access_type, num_access_type, request_status, + num_request_status)); + } + else{ + return (pwr_mem_stat->core_cache_stats[CURRENT_STAT_IDX].get_stats( access_type, num_access_type, request_status, num_request_status)) - (pwr_mem_stat->core_cache_stats[PREV_STAT_IDX].get_stats( access_type, num_access_type, request_status, num_request_status)); + } } - unsigned get_l1d_read_hits() { - return (get_l1d_read_accesses() - get_l1d_read_misses()); - } - unsigned get_l1d_write_accesses() { + double get_l1d_write_accesses(bool aggregate_stat) { enum mem_access_type access_type[] = {GLOBAL_ACC_W, LOCAL_ACC_W}; - enum cache_request_status request_status[] = {HIT, MISS, HIT_RESERVED}; + enum cache_request_status request_status[] = {HIT, MISS, SECTOR_MISS}; unsigned num_access_type = sizeof(access_type) / sizeof(enum mem_access_type); unsigned num_request_status = sizeof(request_status) / sizeof(enum cache_request_status); - return (pwr_mem_stat->core_cache_stats[CURRENT_STAT_IDX].get_stats( + if(aggregate_stat){ + return (pwr_mem_stat->core_cache_stats[CURRENT_STAT_IDX].get_stats( + access_type, num_access_type, request_status, + num_request_status)); + } + else{ + return (pwr_mem_stat->core_cache_stats[CURRENT_STAT_IDX].get_stats( access_type, num_access_type, request_status, num_request_status)) - (pwr_mem_stat->core_cache_stats[PREV_STAT_IDX].get_stats( access_type, num_access_type, request_status, num_request_status)); + } } - unsigned get_l1d_write_misses() { + double get_l1d_write_misses(bool aggregate_stat) { + return (get_l1d_write_accesses(aggregate_stat) - get_l1d_write_hits(aggregate_stat)); + } + double get_l1d_write_hits(bool aggregate_stat) { enum mem_access_type access_type[] = {GLOBAL_ACC_W, LOCAL_ACC_W}; - enum cache_request_status request_status[] = {MISS}; + enum cache_request_status request_status[] = {HIT, MSHR_HIT}; unsigned num_access_type = sizeof(access_type) / sizeof(enum mem_access_type); unsigned num_request_status = sizeof(request_status) / sizeof(enum cache_request_status); - return (pwr_mem_stat->core_cache_stats[CURRENT_STAT_IDX].get_stats( + if(aggregate_stat){ + return (pwr_mem_stat->core_cache_stats[CURRENT_STAT_IDX].get_stats( + access_type, num_access_type, request_status, + num_request_status)); + } + else{ + return (pwr_mem_stat->core_cache_stats[CURRENT_STAT_IDX].get_stats( access_type, num_access_type, request_status, num_request_status)) - (pwr_mem_stat->core_cache_stats[PREV_STAT_IDX].get_stats( access_type, num_access_type, request_status, num_request_status)); + } } - unsigned get_l1d_write_hits() { - return (get_l1d_write_accesses() - get_l1d_write_misses()); - } - unsigned get_cache_misses() { - return get_l1d_read_misses() + get_constant_c_misses() + - get_l1d_write_misses() + get_texture_c_misses(); + double get_cache_misses() { + return get_l1d_read_misses(0) + get_constant_c_misses() + + get_l1d_write_misses(0) + get_texture_c_misses(); } - unsigned get_cache_read_misses() { - return get_l1d_read_misses() + get_constant_c_misses() + + double get_cache_read_misses() { + return get_l1d_read_misses(0) + get_constant_c_misses() + get_texture_c_misses(); } - unsigned get_cache_write_misses() { return get_l1d_write_misses(); } + double get_cache_write_misses() { return get_l1d_write_misses(0); } - unsigned get_shmem_read_access() { + double get_shmem_access(bool aggregate_stat) { unsigned total_inst = 0; for (unsigned i = 0; i < m_config->num_shader(); i++) { - total_inst += (pwr_mem_stat->shmem_read_access[CURRENT_STAT_IDX][i]) - - (pwr_mem_stat->shmem_read_access[PREV_STAT_IDX][i]); + if(aggregate_stat) + total_inst += (pwr_mem_stat->shmem_access[CURRENT_STAT_IDX][i]); + else + total_inst += (pwr_mem_stat->shmem_access[CURRENT_STAT_IDX][i]) - + (pwr_mem_stat->shmem_access[PREV_STAT_IDX][i]); } return total_inst; } - unsigned get_l2_read_accesses() { + unsigned long long get_l2_read_accesses(bool aggregate_stat) { enum mem_access_type access_type[] = { GLOBAL_ACC_R, LOCAL_ACC_R, CONST_ACC_R, TEXTURE_ACC_R, INST_ACC_R}; - enum cache_request_status request_status[] = {HIT, MISS, HIT_RESERVED}; + enum cache_request_status request_status[] = {HIT, HIT_RESERVED, MISS, SECTOR_MISS}; unsigned num_access_type = sizeof(access_type) / sizeof(enum mem_access_type); unsigned num_request_status = sizeof(request_status) / sizeof(enum cache_request_status); - - return (pwr_mem_stat->l2_cache_stats[CURRENT_STAT_IDX].get_stats( + if(aggregate_stat){ + return (pwr_mem_stat->l2_cache_stats[CURRENT_STAT_IDX].get_stats( + access_type, num_access_type, request_status, + num_request_status)); + } + else{ + return (pwr_mem_stat->l2_cache_stats[CURRENT_STAT_IDX].get_stats( access_type, num_access_type, request_status, num_request_status)) - (pwr_mem_stat->l2_cache_stats[PREV_STAT_IDX].get_stats( access_type, num_access_type, request_status, num_request_status)); + } } - unsigned get_l2_read_misses() { - enum mem_access_type access_type[] = { + unsigned long long get_l2_read_misses(bool aggregate_stat) { + return (get_l2_read_accesses(aggregate_stat) - get_l2_read_hits(aggregate_stat)); + } + + unsigned long long get_l2_read_hits(bool aggregate_stat) { + enum mem_access_type access_type[] = { GLOBAL_ACC_R, LOCAL_ACC_R, CONST_ACC_R, TEXTURE_ACC_R, INST_ACC_R}; - enum cache_request_status request_status[] = {MISS}; + enum cache_request_status request_status[] = {HIT, HIT_RESERVED}; unsigned num_access_type = sizeof(access_type) / sizeof(enum mem_access_type); unsigned num_request_status = sizeof(request_status) / sizeof(enum cache_request_status); - - return (pwr_mem_stat->l2_cache_stats[CURRENT_STAT_IDX].get_stats( + if(aggregate_stat){ + return (pwr_mem_stat->l2_cache_stats[CURRENT_STAT_IDX].get_stats( + access_type, num_access_type, request_status, + num_request_status)); + } + else{ + return (pwr_mem_stat->l2_cache_stats[CURRENT_STAT_IDX].get_stats( access_type, num_access_type, request_status, num_request_status)) - (pwr_mem_stat->l2_cache_stats[PREV_STAT_IDX].get_stats( access_type, num_access_type, request_status, num_request_status)); + } } - unsigned get_l2_read_hits() { - return (get_l2_read_accesses() - get_l2_read_misses()); - } - - unsigned get_l2_write_accesses() { + unsigned long long get_l2_write_accesses(bool aggregate_stat) { enum mem_access_type access_type[] = {GLOBAL_ACC_W, LOCAL_ACC_W, L1_WRBK_ACC}; - enum cache_request_status request_status[] = {HIT, MISS, HIT_RESERVED}; + enum cache_request_status request_status[] = {HIT, HIT_RESERVED, MISS, SECTOR_MISS}; unsigned num_access_type = sizeof(access_type) / sizeof(enum mem_access_type); unsigned num_request_status = sizeof(request_status) / sizeof(enum cache_request_status); - - return (pwr_mem_stat->l2_cache_stats[CURRENT_STAT_IDX].get_stats( + if(aggregate_stat){ + return (pwr_mem_stat->l2_cache_stats[CURRENT_STAT_IDX].get_stats( + access_type, num_access_type, request_status, + num_request_status)); + } + else{ + return (pwr_mem_stat->l2_cache_stats[CURRENT_STAT_IDX].get_stats( access_type, num_access_type, request_status, num_request_status)) - (pwr_mem_stat->l2_cache_stats[PREV_STAT_IDX].get_stats( access_type, num_access_type, request_status, num_request_status)); + } } - unsigned get_l2_write_misses() { - enum mem_access_type access_type[] = {GLOBAL_ACC_W, LOCAL_ACC_W, + unsigned long long get_l2_write_misses(bool aggregate_stat) { + return (get_l2_write_accesses(aggregate_stat) - get_l2_write_hits(aggregate_stat)); + } + unsigned long long get_l2_write_hits(bool aggregate_stat) { + enum mem_access_type access_type[] = {GLOBAL_ACC_W, LOCAL_ACC_W, L1_WRBK_ACC}; - enum cache_request_status request_status[] = {MISS}; + enum cache_request_status request_status[] = {HIT, HIT_RESERVED}; unsigned num_access_type = sizeof(access_type) / sizeof(enum mem_access_type); unsigned num_request_status = sizeof(request_status) / sizeof(enum cache_request_status); - - return (pwr_mem_stat->l2_cache_stats[CURRENT_STAT_IDX].get_stats( + if(aggregate_stat){ + return (pwr_mem_stat->l2_cache_stats[CURRENT_STAT_IDX].get_stats( + access_type, num_access_type, request_status, + num_request_status)); + } + else{ + return (pwr_mem_stat->l2_cache_stats[CURRENT_STAT_IDX].get_stats( access_type, num_access_type, request_status, num_request_status)) - (pwr_mem_stat->l2_cache_stats[PREV_STAT_IDX].get_stats( access_type, num_access_type, request_status, num_request_status)); + } } - unsigned get_l2_write_hits() { - return (get_l2_write_accesses() - get_l2_write_misses()); - } - unsigned get_dram_cmd() { + double get_dram_cmd() { unsigned total = 0; for (unsigned i = 0; i < m_mem_config->m_n_mem; ++i) { total += (pwr_mem_stat->n_cmd[CURRENT_STAT_IDX][i] - @@ -694,7 +1064,7 @@ class power_stat_t { } return total; } - unsigned get_dram_activity() { + double get_dram_activity() { unsigned total = 0; for (unsigned i = 0; i < m_mem_config->m_n_mem; ++i) { total += (pwr_mem_stat->n_activity[CURRENT_STAT_IDX][i] - @@ -702,7 +1072,7 @@ class power_stat_t { } return total; } - unsigned get_dram_nop() { + double get_dram_nop() { unsigned total = 0; for (unsigned i = 0; i < m_mem_config->m_n_mem; ++i) { total += (pwr_mem_stat->n_nop[CURRENT_STAT_IDX][i] - @@ -710,7 +1080,7 @@ class power_stat_t { } return total; } - unsigned get_dram_act() { + double get_dram_act() { unsigned total = 0; for (unsigned i = 0; i < m_mem_config->m_n_mem; ++i) { total += (pwr_mem_stat->n_act[CURRENT_STAT_IDX][i] - @@ -718,31 +1088,49 @@ class power_stat_t { } return total; } - unsigned get_dram_pre() { + double get_dram_pre(bool aggregate_stat) { unsigned total = 0; for (unsigned i = 0; i < m_mem_config->m_n_mem; ++i) { - total += (pwr_mem_stat->n_pre[CURRENT_STAT_IDX][i] - + if(aggregate_stat){ + total += pwr_mem_stat->n_pre[CURRENT_STAT_IDX][i]; + } + else{ + total += (pwr_mem_stat->n_pre[CURRENT_STAT_IDX][i] - pwr_mem_stat->n_pre[PREV_STAT_IDX][i]); + } } return total; } - unsigned get_dram_rd() { + double get_dram_rd(bool aggregate_stat) { unsigned total = 0; for (unsigned i = 0; i < m_mem_config->m_n_mem; ++i) { - total += (pwr_mem_stat->n_rd[CURRENT_STAT_IDX][i] - + if(aggregate_stat){ + total += pwr_mem_stat->n_rd[CURRENT_STAT_IDX][i]; + } + else{ + total += (pwr_mem_stat->n_rd[CURRENT_STAT_IDX][i] - pwr_mem_stat->n_rd[PREV_STAT_IDX][i]); + } } return total; } - unsigned get_dram_wr() { + double get_dram_wr(bool aggregate_stat) { unsigned total = 0; for (unsigned i = 0; i < m_mem_config->m_n_mem; ++i) { - total += (pwr_mem_stat->n_wr[CURRENT_STAT_IDX][i] - - pwr_mem_stat->n_wr[PREV_STAT_IDX][i]); + if(aggregate_stat){ + total += pwr_mem_stat->n_wr[CURRENT_STAT_IDX][i] + + pwr_mem_stat->n_wr_WB[CURRENT_STAT_IDX][i]; + } + else{ + total += (pwr_mem_stat->n_wr[CURRENT_STAT_IDX][i] - + pwr_mem_stat->n_wr[PREV_STAT_IDX][i]) + + (pwr_mem_stat->n_wr_WB[CURRENT_STAT_IDX][i] - + pwr_mem_stat->n_wr_WB[PREV_STAT_IDX][i]); + } } return total; } - unsigned get_dram_req() { + double get_dram_req() { unsigned total = 0; for (unsigned i = 0; i < m_mem_config->m_n_mem; ++i) { total += (pwr_mem_stat->n_req[CURRENT_STAT_IDX][i] - @@ -751,20 +1139,31 @@ class power_stat_t { return total; } - long get_icnt_simt_to_mem() { + unsigned long long get_icnt_simt_to_mem(bool aggregate_stat) { long total = 0; - for (unsigned i = 0; i < m_config->n_simt_clusters; ++i) { - total += (pwr_mem_stat->n_simt_to_mem[CURRENT_STAT_IDX][i] - + for (unsigned i = 0; i < m_config->n_simt_clusters; ++i){ + if(aggregate_stat){ + total += pwr_mem_stat->n_simt_to_mem[CURRENT_STAT_IDX][i]; + } + else{ + total += (pwr_mem_stat->n_simt_to_mem[CURRENT_STAT_IDX][i] - pwr_mem_stat->n_simt_to_mem[PREV_STAT_IDX][i]); + } } return total; } - long get_icnt_mem_to_simt() { + unsigned long long get_icnt_mem_to_simt(bool aggregate_stat) { long total = 0; for (unsigned i = 0; i < m_config->n_simt_clusters; ++i) { - total += (pwr_mem_stat->n_mem_to_simt[CURRENT_STAT_IDX][i] - + if(aggregate_stat){ + total += pwr_mem_stat->n_mem_to_simt[CURRENT_STAT_IDX][i]; + } + + else{ + total += (pwr_mem_stat->n_mem_to_simt[CURRENT_STAT_IDX][i] - pwr_mem_stat->n_mem_to_simt[PREV_STAT_IDX][i]); + } } return total; } diff --git a/src/gpgpu-sim/shader.cc b/src/gpgpu-sim/shader.cc index 90bb900..4013ae9 100644 --- a/src/gpgpu-sim/shader.cc +++ b/src/gpgpu-sim/shader.cc @@ -1,19 +1,21 @@ -// Copyright (c) 2009-2011, Tor M. Aamodt, Wilson W.L. Fung, Ali Bakhoda, -// George L. Yuan, Andrew Turner, Inderpreet Singh -// The University of British Columbia +// Copyright (c) 2009-2021, Tor M. Aamodt, Wilson W.L. Fung, Ali Bakhoda, +// George L. Yuan, Andrew Turner, Inderpreet Singh, Vijay Kandiah, Nikos Hardavellas, +// Mahmoud Khairy, Junrui Pan, Timothy G. Rogers +// The University of British Columbia, Northwestern University, Purdue University // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // -// Redistributions of source code must retain the above copyright notice, this -// list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. Neither the name of -// The University of British Columbia nor the names of its contributors may be -// used to endorse or promote products derived from this software without -// specific prior written permission. +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer; +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution; +// 3. Neither the names of The University of British Columbia, Northwestern +// University nor the names of their contributors may be used to +// endorse or promote products derived from this software without specific +// prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE @@ -61,6 +63,20 @@ 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, unsigned wid, unsigned sid, unsigned tpc, + mem_fetch *original_mf) 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, wid, m_core_id, + m_cluster_id, m_memory_config, cycle, original_mf); + return mf; +} ///////////////////////////////////////////////////////////////////////////// std::list<unsigned> shader_core_ctx::get_regs_written(const inst_t &fvt) const { @@ -108,7 +124,7 @@ void shader_core_ctx::create_front_pipeline() { if (m_config->sub_core_model) { // in subcore model, each scheduler should has its own issue register, so - // num scheduler = reg width + // ensure num scheduler = reg width assert(m_config->gpgpu_num_sched_per_core == m_pipeline_reg[ID_OC_SP].get_size()); assert(m_config->gpgpu_num_sched_per_core == @@ -124,6 +140,11 @@ void shader_core_ctx::create_front_pipeline() { if (m_config->gpgpu_num_int_units > 0) assert(m_config->gpgpu_num_sched_per_core == m_pipeline_reg[ID_OC_INT].get_size()); + for (int j = 0; j < m_config->m_specialized_unit.size(); j++) { + if (m_config->m_specialized_unit[j].num_units > 0) + assert(m_config->gpgpu_num_sched_per_core == + m_config->m_specialized_unit[j].id_oc_spec_reg_width); + } } m_threadState = (thread_ctx_t *)calloc(sizeof(thread_ctx_t), @@ -172,6 +193,8 @@ void shader_core_ctx::create_schedulers() { ? CONCRETE_SCHEDULER_TWO_LEVEL_ACTIVE : sched_config.find("gto") != std::string::npos ? CONCRETE_SCHEDULER_GTO + : sched_config.find("rrr") != std::string::npos + ? CONCRETE_SCHEDULER_RRR : sched_config.find("old") != std::string::npos ? CONCRETE_SCHEDULER_OLDEST_FIRST : sched_config.find("warp_limiting") != @@ -206,6 +229,14 @@ void shader_core_ctx::create_schedulers() { &m_pipeline_reg[ID_OC_TENSOR_CORE], m_specilized_dispatch_reg, &m_pipeline_reg[ID_OC_MEM], i)); break; + case CONCRETE_SCHEDULER_RRR: + schedulers.push_back(new rrr_scheduler( + m_stats, this, m_scoreboard, m_simt_stack, &m_warp, + &m_pipeline_reg[ID_OC_SP], &m_pipeline_reg[ID_OC_DP], + &m_pipeline_reg[ID_OC_SFU], &m_pipeline_reg[ID_OC_INT], + &m_pipeline_reg[ID_OC_TENSOR_CORE], m_specilized_dispatch_reg, + &m_pipeline_reg[ID_OC_MEM], i)); + break; case CONCRETE_SCHEDULER_OLDEST_FIRST: schedulers.push_back(new oldest_scheduler( m_stats, this, m_scoreboard, m_simt_stack, &m_warp, @@ -377,41 +408,41 @@ void shader_core_ctx::create_exec_pipeline() { // m_fu = new simd_function_unit*[m_num_function_units]; - for (int k = 0; k < m_config->gpgpu_num_sp_units; k++) { - m_fu.push_back(new sp_unit(&m_pipeline_reg[EX_WB], m_config, this)); + for (unsigned k = 0; k < m_config->gpgpu_num_sp_units; k++) { + m_fu.push_back(new sp_unit(&m_pipeline_reg[EX_WB], m_config, this, k)); m_dispatch_port.push_back(ID_OC_SP); m_issue_port.push_back(OC_EX_SP); } - for (int k = 0; k < m_config->gpgpu_num_dp_units; k++) { - m_fu.push_back(new dp_unit(&m_pipeline_reg[EX_WB], m_config, this)); + for (unsigned k = 0; k < m_config->gpgpu_num_dp_units; k++) { + m_fu.push_back(new dp_unit(&m_pipeline_reg[EX_WB], m_config, this, k)); m_dispatch_port.push_back(ID_OC_DP); m_issue_port.push_back(OC_EX_DP); } - for (int k = 0; k < m_config->gpgpu_num_int_units; k++) { - m_fu.push_back(new int_unit(&m_pipeline_reg[EX_WB], m_config, this)); + for (unsigned k = 0; k < m_config->gpgpu_num_int_units; k++) { + m_fu.push_back(new int_unit(&m_pipeline_reg[EX_WB], m_config, this, k)); m_dispatch_port.push_back(ID_OC_INT); m_issue_port.push_back(OC_EX_INT); } - for (int k = 0; k < m_config->gpgpu_num_sfu_units; k++) { - m_fu.push_back(new sfu(&m_pipeline_reg[EX_WB], m_config, this)); + for (unsigned k = 0; k < m_config->gpgpu_num_sfu_units; k++) { + m_fu.push_back(new sfu(&m_pipeline_reg[EX_WB], m_config, this, k)); m_dispatch_port.push_back(ID_OC_SFU); m_issue_port.push_back(OC_EX_SFU); } - for (int k = 0; k < m_config->gpgpu_num_tensor_core_units; k++) { - m_fu.push_back(new tensor_core(&m_pipeline_reg[EX_WB], m_config, this)); + for (unsigned k = 0; k < m_config->gpgpu_num_tensor_core_units; k++) { + m_fu.push_back(new tensor_core(&m_pipeline_reg[EX_WB], m_config, this, k)); m_dispatch_port.push_back(ID_OC_TENSOR_CORE); m_issue_port.push_back(OC_EX_TENSOR_CORE); } - for (int j = 0; j < m_config->m_specialized_unit.size(); j++) { + for (unsigned j = 0; j < m_config->m_specialized_unit.size(); j++) { for (unsigned k = 0; k < m_config->m_specialized_unit[j].num_units; k++) { m_fu.push_back(new specialized_unit( &m_pipeline_reg[EX_WB], m_config, this, SPEC_UNIT_START_ID + j, m_config->m_specialized_unit[j].name, - m_config->m_specialized_unit[j].latency)); + m_config->m_specialized_unit[j].latency, k)); m_dispatch_port.push_back(m_config->m_specialized_unit[j].ID_OC_SPEC_ID); m_issue_port.push_back(m_config->m_specialized_unit[j].OC_EX_SPEC_ID); } @@ -456,6 +487,10 @@ shader_core_ctx::shader_core_ctx(class gpgpu_sim *gpu, m_sid = shader_id; m_tpc = tpc_id; + if(get_gpu()->get_config().g_power_simulation_enabled){ + scaling_coeffs = get_gpu()->get_scaling_coeffs(); + } + m_last_inst_gpu_sim_cycle = 0; m_last_inst_gpu_tot_sim_cycle = 0; @@ -859,7 +894,7 @@ void shader_core_ctx::decode() { m_warp[m_inst_fetch_buffer.m_warp_id]->inc_inst_in_pipeline(); if (pI1) { m_stats->m_num_decoded_insn[m_sid]++; - if (pI1->oprnd_type == INT_OP) { + if ((pI1->oprnd_type == INT_OP) || (pI1->oprnd_type == UN_OP)) { //these counters get added up in mcPat to compute scheduler power m_stats->m_num_INTdecoded_insn[m_sid]++; } else if (pI1->oprnd_type == FP_OP) { m_stats->m_num_FPdecoded_insn[m_sid]++; @@ -870,7 +905,7 @@ void shader_core_ctx::decode() { m_warp[m_inst_fetch_buffer.m_warp_id]->ibuffer_fill(1, pI2); m_warp[m_inst_fetch_buffer.m_warp_id]->inc_inst_in_pipeline(); m_stats->m_num_decoded_insn[m_sid]++; - if (pI2->oprnd_type == INT_OP) { + if ((pI1->oprnd_type == INT_OP) || (pI1->oprnd_type == UN_OP)) { //these counters get added up in mcPat to compute scheduler power m_stats->m_num_INTdecoded_insn[m_sid]++; } else if (pI2->oprnd_type == FP_OP) { m_stats->m_num_FPdecoded_insn[m_sid]++; @@ -916,7 +951,7 @@ void shader_core_ctx::fetch() { m_threadState[tid].m_active = false; unsigned cta_id = m_warp[warp_id]->get_cta_id(); if (m_thread[tid] == NULL) { - register_cta_thread_exit(cta_id, m_kernel); + register_cta_thread_exit(cta_id, m_warp[warp_id]->get_kernel_info()); } else { register_cta_thread_exit(cta_id, &(m_thread[tid]->get_kernel())); @@ -953,8 +988,10 @@ void shader_core_ctx::fetch() { m_gpu->gpu_tot_sim_cycle + m_gpu->gpu_sim_cycle); std::list<cache_event> events; enum cache_request_status status; - if (m_config->perfect_inst_const_cache) + if (m_config->perfect_inst_const_cache){ status = HIT; + shader_cache_access_log(m_sid, INSTRUCTION, 0); + } else status = m_L1I->access( (new_addr_type)ppc, mf, @@ -1082,6 +1119,33 @@ void scheduler_unit::order_lrr( } } +template <class T> +void scheduler_unit::order_rrr( + std::vector<T> &result_list, const typename std::vector<T> &input_list, + const typename std::vector<T>::const_iterator &last_issued_from_input, + unsigned num_warps_to_add) { + result_list.clear(); + + if (m_num_issued_last_cycle > 0 || warp(m_current_turn_warp).done_exit() || + warp(m_current_turn_warp).waiting()) { + std::vector<shd_warp_t *>::const_iterator iter = + (last_issued_from_input == input_list.end()) ? + input_list.begin() : last_issued_from_input + 1; + for (unsigned count = 0; count < num_warps_to_add; ++iter, ++count) { + if (iter == input_list.end()) { + iter = input_list.begin(); + } + unsigned warp_id = (*iter)->get_warp_id(); + if (!(*iter)->done_exit() && !(*iter)->waiting()) { + result_list.push_back(*iter); + m_current_turn_warp = warp_id; + break; + } + } + } else { + result_list.push_back(&warp(m_current_turn_warp)); + } +} /** * A general function to order things in an priority-based way. * The core usage of the function is similar to order_lrr. @@ -1228,29 +1292,21 @@ void scheduler_unit::cycle() { previous_issued_inst_exec_type = exec_unit_type_t::MEM; } } else { - bool sp_pipe_avail = - (m_shader->m_config->gpgpu_num_sp_units > 0) && - m_sp_out->has_free(m_shader->m_config->sub_core_model, m_id); - bool sfu_pipe_avail = - (m_shader->m_config->gpgpu_num_sfu_units > 0) && - m_sfu_out->has_free(m_shader->m_config->sub_core_model, m_id); - bool tensor_core_pipe_avail = - (m_shader->m_config->gpgpu_num_tensor_core_units > 0) && - m_tensor_core_out->has_free( - m_shader->m_config->sub_core_model, m_id); - bool dp_pipe_avail = - (m_shader->m_config->gpgpu_num_dp_units > 0) && - m_dp_out->has_free(m_shader->m_config->sub_core_model, m_id); - bool int_pipe_avail = - (m_shader->m_config->gpgpu_num_int_units > 0) && - m_int_out->has_free(m_shader->m_config->sub_core_model, m_id); - // This code need to be refactored if (pI->op != TENSOR_CORE_OP && pI->op != SFU_OP && pI->op != DP_OP && !(pI->op >= SPEC_UNIT_START_ID)) { bool execute_on_SP = false; bool execute_on_INT = false; + bool sp_pipe_avail = + (m_shader->m_config->gpgpu_num_sp_units > 0) && + m_sp_out->has_free(m_shader->m_config->sub_core_model, + m_id); + bool int_pipe_avail = + (m_shader->m_config->gpgpu_num_int_units > 0) && + m_int_out->has_free(m_shader->m_config->sub_core_model, + m_id); + // if INT unit pipline exist, then execute ALU and INT // operations on INT unit and SP-FPU on SP unit (like in Volta) // if INT unit pipline does not exist, then execute all ALU, INT @@ -1311,6 +1367,11 @@ void scheduler_unit::cycle() { (pI->op == DP_OP) && !(diff_exec_units && previous_issued_inst_exec_type == exec_unit_type_t::DP)) { + bool dp_pipe_avail = + (m_shader->m_config->gpgpu_num_dp_units > 0) && + m_dp_out->has_free(m_shader->m_config->sub_core_model, + m_id); + if (dp_pipe_avail) { m_shader->issue_warp(*m_dp_out, pI, active_mask, warp_id, m_id); @@ -1326,6 +1387,11 @@ void scheduler_unit::cycle() { (pI->op == SFU_OP) || (pI->op == ALU_SFU_OP)) && !(diff_exec_units && previous_issued_inst_exec_type == exec_unit_type_t::SFU)) { + bool sfu_pipe_avail = + (m_shader->m_config->gpgpu_num_sfu_units > 0) && + m_sfu_out->has_free(m_shader->m_config->sub_core_model, + m_id); + if (sfu_pipe_avail) { m_shader->issue_warp(*m_sfu_out, pI, active_mask, warp_id, m_id); @@ -1337,6 +1403,11 @@ void scheduler_unit::cycle() { } else if ((pI->op == TENSOR_CORE_OP) && !(diff_exec_units && previous_issued_inst_exec_type == exec_unit_type_t::TENSOR)) { + bool tensor_core_pipe_avail = + (m_shader->m_config->gpgpu_num_tensor_core_units > 0) && + m_tensor_core_out->has_free( + m_shader->m_config->sub_core_model, m_id); + if (tensor_core_pipe_avail) { m_shader->issue_warp(*m_tensor_core_out, pI, active_mask, warp_id, m_id); @@ -1407,7 +1478,7 @@ void scheduler_unit::cycle() { m_last_supervised_issued = supervised_iter; } } - + m_num_issued_last_cycle = issued; if (issued == 1) m_stats->single_issue_nums[m_id]++; else if (issued > 1) @@ -1456,6 +1527,10 @@ void lrr_scheduler::order_warps() { order_lrr(m_next_cycle_prioritized_warps, m_supervised_warps, m_last_supervised_issued, m_supervised_warps.size()); } +void rrr_scheduler::order_warps() { + order_rrr(m_next_cycle_prioritized_warps, m_supervised_warps, + m_last_supervised_issued, m_supervised_warps.size()); +} void gto_scheduler::order_warps() { order_by_priority(m_next_cycle_prioritized_warps, m_supervised_warps, @@ -1569,7 +1644,10 @@ void swl_scheduler::order_warps() { } } -void shader_core_ctx::read_operands() {} +void shader_core_ctx::read_operands() { + for (int i = 0; i < m_config->reg_file_port_throughput; ++i) + m_operand_collector.step(); +} address_type coalesced_segment(address_type addr, unsigned segment_size_lg2bytes) { @@ -1669,8 +1747,15 @@ void shader_core_ctx::execute() { m_fu[n]->active_lanes_in_pipeline(); unsigned issue_port = m_issue_port[n]; register_set &issue_inst = m_pipeline_reg[issue_port]; - warp_inst_t **ready_reg = issue_inst.get_ready(); - if (issue_inst.has_ready() && m_fu[n]->can_issue(**ready_reg)) { + unsigned reg_id; + bool partition_issue = + m_config->sub_core_model && m_fu[n]->is_issue_partitioned(); + if (partition_issue) { + reg_id = m_fu[n]->get_issue_reg_id(); + } + warp_inst_t **ready_reg = issue_inst.get_ready(partition_issue, reg_id); + if (issue_inst.has_ready(partition_issue, reg_id) && + m_fu[n]->can_issue(**ready_reg)) { bool schedule_wb_now = !m_fu[n]->stallable(); int resbus = -1; if (schedule_wb_now && @@ -1970,6 +2055,21 @@ 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; + } } } @@ -1992,10 +2092,11 @@ bool ldst_unit::constant_cycle(warp_inst_t &inst, mem_stage_stall_type &rc_fail, mem_stage_stall_type fail; if (m_config->perfect_inst_const_cache) { fail = NO_RC_FAIL; + unsigned access_count = inst.accessq_count(); while (inst.accessq_count() > 0) inst.accessq_pop_back(); if (inst.is_load()) { for (unsigned r = 0; r < MAX_OUTPUT_VALUES; r++) - if (inst.out[r] > 0) m_pending_writes[inst.warp_id()][inst.out[r]]--; + if (inst.out[r] > 0) m_pending_writes[inst.warp_id()][inst.out[r]] -= access_count; } } else { fail = process_memory_access_queue(m_L1C, inst); @@ -2112,22 +2213,32 @@ simd_function_unit::simd_function_unit(const shader_core_config *config) { m_dispatch_reg = new warp_inst_t(config); } +void simd_function_unit::issue(register_set &source_reg) { + bool partition_issue = + m_config->sub_core_model && this->is_issue_partitioned(); + source_reg.move_out_to(partition_issue, this->get_issue_reg_id(), + m_dispatch_reg); + occupied.set(m_dispatch_reg->latency); +} + sfu::sfu(register_set *result_port, const shader_core_config *config, - shader_core_ctx *core) - : pipelined_simd_unit(result_port, config, config->max_sfu_latency, core) { + shader_core_ctx *core, unsigned issue_reg_id) + : pipelined_simd_unit(result_port, config, config->max_sfu_latency, core, + issue_reg_id) { m_name = "SFU"; } tensor_core::tensor_core(register_set *result_port, const shader_core_config *config, - shader_core_ctx *core) + shader_core_ctx *core, unsigned issue_reg_id) : pipelined_simd_unit(result_port, config, config->max_tensor_core_latency, - core) { + core, issue_reg_id) { m_name = "TENSOR_CORE"; } void sfu::issue(register_set &source_reg) { - warp_inst_t **ready_reg = source_reg.get_ready(); + warp_inst_t **ready_reg = + source_reg.get_ready(m_config->sub_core_model, m_issue_reg_id); // m_core->incexecstat((*ready_reg)); (*ready_reg)->op_pipe = SFU__OP; @@ -2136,7 +2247,8 @@ void sfu::issue(register_set &source_reg) { } void tensor_core::issue(register_set &source_reg) { - warp_inst_t **ready_reg = source_reg.get_ready(); + warp_inst_t **ready_reg = + source_reg.get_ready(m_config->sub_core_model, m_issue_reg_id); // m_core->incexecstat((*ready_reg)); (*ready_reg)->op_pipe = TENSOR_CORE__OP; @@ -2172,7 +2284,7 @@ void sp_unit::active_lanes_in_pipeline() { void dp_unit::active_lanes_in_pipeline() { unsigned active_count = pipelined_simd_unit::get_active_lanes_in_pipeline(); assert(active_count <= m_core->get_config()->warp_size); - m_core->incspactivelanes_stat(active_count); + //m_core->incspactivelanes_stat(active_count); m_core->incfuactivelanes_stat(active_count); m_core->incfumemactivelanes_stat(active_count); } @@ -2208,34 +2320,39 @@ void tensor_core::active_lanes_in_pipeline() { } sp_unit::sp_unit(register_set *result_port, const shader_core_config *config, - shader_core_ctx *core) - : pipelined_simd_unit(result_port, config, config->max_sp_latency, core) { + shader_core_ctx *core, unsigned issue_reg_id) + : pipelined_simd_unit(result_port, config, config->max_sp_latency, core, + issue_reg_id) { m_name = "SP "; } specialized_unit::specialized_unit(register_set *result_port, const shader_core_config *config, shader_core_ctx *core, unsigned supported_op, - char *unit_name, unsigned latency) - : pipelined_simd_unit(result_port, config, latency, core) { + char *unit_name, unsigned latency, + unsigned issue_reg_id) + : pipelined_simd_unit(result_port, config, latency, core, issue_reg_id) { m_name = unit_name; m_supported_op = supported_op; } dp_unit::dp_unit(register_set *result_port, const shader_core_config *config, - shader_core_ctx *core) - : pipelined_simd_unit(result_port, config, config->max_dp_latency, core) { + shader_core_ctx *core, unsigned issue_reg_id) + : pipelined_simd_unit(result_port, config, config->max_dp_latency, core, + issue_reg_id) { m_name = "DP "; } int_unit::int_unit(register_set *result_port, const shader_core_config *config, - shader_core_ctx *core) - : pipelined_simd_unit(result_port, config, config->max_int_latency, core) { + shader_core_ctx *core, unsigned issue_reg_id) + : pipelined_simd_unit(result_port, config, config->max_int_latency, core, + issue_reg_id) { m_name = "INT "; } void sp_unit ::issue(register_set &source_reg) { - warp_inst_t **ready_reg = source_reg.get_ready(); + warp_inst_t **ready_reg = + source_reg.get_ready(m_config->sub_core_model, m_issue_reg_id); // m_core->incexecstat((*ready_reg)); (*ready_reg)->op_pipe = SP__OP; m_core->incsp_stat(m_core->get_config()->warp_size, (*ready_reg)->latency); @@ -2243,7 +2360,8 @@ void sp_unit ::issue(register_set &source_reg) { } void dp_unit ::issue(register_set &source_reg) { - warp_inst_t **ready_reg = source_reg.get_ready(); + warp_inst_t **ready_reg = + source_reg.get_ready(m_config->sub_core_model, m_issue_reg_id); // m_core->incexecstat((*ready_reg)); (*ready_reg)->op_pipe = DP__OP; m_core->incsp_stat(m_core->get_config()->warp_size, (*ready_reg)->latency); @@ -2251,7 +2369,8 @@ void dp_unit ::issue(register_set &source_reg) { } void specialized_unit ::issue(register_set &source_reg) { - warp_inst_t **ready_reg = source_reg.get_ready(); + warp_inst_t **ready_reg = + source_reg.get_ready(m_config->sub_core_model, m_issue_reg_id); // m_core->incexecstat((*ready_reg)); (*ready_reg)->op_pipe = SPECIALIZED__OP; m_core->incsp_stat(m_core->get_config()->warp_size, (*ready_reg)->latency); @@ -2259,7 +2378,8 @@ void specialized_unit ::issue(register_set &source_reg) { } void int_unit ::issue(register_set &source_reg) { - warp_inst_t **ready_reg = source_reg.get_ready(); + warp_inst_t **ready_reg = + source_reg.get_ready(m_config->sub_core_model, m_issue_reg_id); // m_core->incexecstat((*ready_reg)); (*ready_reg)->op_pipe = INTP__OP; m_core->incsp_stat(m_core->get_config()->warp_size, (*ready_reg)->latency); @@ -2269,7 +2389,8 @@ void int_unit ::issue(register_set &source_reg) { pipelined_simd_unit::pipelined_simd_unit(register_set *result_port, const shader_core_config *config, unsigned max_latency, - shader_core_ctx *core) + shader_core_ctx *core, + unsigned issue_reg_id) : simd_function_unit(config) { m_result_port = result_port; m_pipeline_depth = max_latency; @@ -2277,6 +2398,7 @@ pipelined_simd_unit::pipelined_simd_unit(register_set *result_port, for (unsigned i = 0; i < m_pipeline_depth; i++) m_pipeline_reg[i] = new warp_inst_t(config); m_core = core; + m_issue_reg_id = issue_reg_id; active_insts_in_pipeline = 0; } @@ -2305,7 +2427,10 @@ void pipelined_simd_unit::cycle() { void pipelined_simd_unit::issue(register_set &source_reg) { // move_warp(m_dispatch_reg,source_reg); - warp_inst_t **ready_reg = source_reg.get_ready(); + bool partition_issue = + m_config->sub_core_model && this->is_issue_partitioned(); + warp_inst_t **ready_reg = + source_reg.get_ready(partition_issue, m_issue_reg_id); m_core->incexecstat((*ready_reg)); // source_reg.move_out_to(m_dispatch_reg); simd_function_unit::issue(source_reg); @@ -2362,7 +2487,7 @@ ldst_unit::ldst_unit(mem_fetch_interface *icnt, Scoreboard *scoreboard, const shader_core_config *config, const memory_config *mem_config, shader_core_stats *stats, unsigned sid, unsigned tpc) - : pipelined_simd_unit(NULL, config, config->smem_latency, core), + : pipelined_simd_unit(NULL, config, config->smem_latency, core, 0), m_next_wb(config) { assert(config->smem_latency > 1); init(icnt, mf_allocator, core, operand_collector, scoreboard, config, @@ -2390,7 +2515,7 @@ ldst_unit::ldst_unit(mem_fetch_interface *icnt, Scoreboard *scoreboard, const shader_core_config *config, const memory_config *mem_config, shader_core_stats *stats, unsigned sid, unsigned tpc, l1_cache *new_l1d_cache) - : pipelined_simd_unit(NULL, config, 3, core), + : pipelined_simd_unit(NULL, config, 3, core, 0), m_L1D(new_l1d_cache), m_next_wb(config) { init(icnt, mf_allocator, core, operand_collector, scoreboard, config, @@ -2552,8 +2677,7 @@ inst->space.get_type() != shared_space) { unsigned warp_id = inst->warp_id(); */ void ldst_unit::cycle() { writeback(); - for (int i = 0; i < m_config->reg_file_port_throughput; ++i) - m_operand_collector->step(); + for (unsigned stage = 0; (stage + 1) < m_pipeline_depth; stage++) if (m_pipeline_reg[stage]->empty() && !m_pipeline_reg[stage + 1]->empty()) move_warp(m_pipeline_reg[stage], m_pipeline_reg[stage + 1]); @@ -2966,52 +3090,69 @@ void warp_inst_t::print(FILE *fout) const { m_config->gpgpu_ctx->func_sim->ptx_print_insn(pc, fout); fprintf(fout, "\n"); } -void shader_core_ctx::incexecstat(warp_inst_t *&inst) { - if (inst->mem_op == TEX) inctex_stat(inst->active_count(), 1); - - // Latency numbers for next operations are used to scale the power values - // for special operations, according observations from microbenchmarking - // TODO: put these numbers in the xml configuration - - switch (inst->sp_op) { +void shader_core_ctx::incexecstat(warp_inst_t *&inst) +{ + // Latency numbers for next operations are used to scale the power values + // for special operations, according observations from microbenchmarking + // TODO: put these numbers in the xml configuration + if(get_gpu()->get_config().g_power_simulation_enabled){ + switch(inst->sp_op){ case INT__OP: - incialu_stat(inst->active_count(), 32); + incialu_stat(inst->active_count(), scaling_coeffs->int_coeff); break; case INT_MUL_OP: - incimul_stat(inst->active_count(), 7.2); + incimul_stat(inst->active_count(), scaling_coeffs->int_mul_coeff); break; case INT_MUL24_OP: - incimul24_stat(inst->active_count(), 4.2); + incimul24_stat(inst->active_count(), scaling_coeffs->int_mul24_coeff); break; case INT_MUL32_OP: - incimul32_stat(inst->active_count(), 4); + incimul32_stat(inst->active_count(), scaling_coeffs->int_mul32_coeff); break; case INT_DIV_OP: - incidiv_stat(inst->active_count(), 40); + incidiv_stat(inst->active_count(), scaling_coeffs->int_div_coeff); break; case FP__OP: - incfpalu_stat(inst->active_count(), 1); + incfpalu_stat(inst->active_count(),scaling_coeffs->fp_coeff); break; case FP_MUL_OP: - incfpmul_stat(inst->active_count(), 1.8); + incfpmul_stat(inst->active_count(), scaling_coeffs->fp_mul_coeff); break; case FP_DIV_OP: - incfpdiv_stat(inst->active_count(), 48); + incfpdiv_stat(inst->active_count(), scaling_coeffs->fp_div_coeff); + break; + case DP___OP: + incdpalu_stat(inst->active_count(), scaling_coeffs->dp_coeff); + break; + case DP_MUL_OP: + incdpmul_stat(inst->active_count(), scaling_coeffs->dp_mul_coeff); + break; + case DP_DIV_OP: + incdpdiv_stat(inst->active_count(), scaling_coeffs->dp_div_coeff); break; case FP_SQRT_OP: - inctrans_stat(inst->active_count(), 25); + incsqrt_stat(inst->active_count(), scaling_coeffs->sqrt_coeff); break; case FP_LG_OP: - inctrans_stat(inst->active_count(), 35); + inclog_stat(inst->active_count(), scaling_coeffs->log_coeff); break; case FP_SIN_OP: - inctrans_stat(inst->active_count(), 12); + incsin_stat(inst->active_count(), scaling_coeffs->sin_coeff); break; case FP_EXP_OP: - inctrans_stat(inst->active_count(), 35); + incexp_stat(inst->active_count(), scaling_coeffs->exp_coeff); + break; + case TENSOR__OP: + inctensor_stat(inst->active_count(), scaling_coeffs->tensor_coeff); + break; + case TEX__OP: + inctex_stat(inst->active_count(), scaling_coeffs->tex_coeff); break; default: break; + } + if(inst->const_cache_operand) //warp has const address space load as one operand + inc_const_accesses(1); } } void shader_core_ctx::print_stage(unsigned int stage, FILE *fout) const { @@ -3266,49 +3407,46 @@ 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 + unsigned total_shmem = kernel_info->smem * result; + assert(total_shmem >= 0 && total_shmem <= shmem_opt_list.back()); - // 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; - } - default: - assert(0); + // Unified cache config is in KB. Converting to B + unsigned total_unified = m_L1D_config.m_unified_cache_size * 1024; + + bool l1d_configured = false; + unsigned max_assoc = m_L1D_config.get_max_assoc(); + + for (std::vector<unsigned>::const_iterator it = shmem_opt_list.begin(); + it < shmem_opt_list.end(); it++) { + if (total_shmem <= *it) { + float l1_ratio = 1 - ((float)*(it) / total_unified); + // make sure the ratio is between 0 and 1 + assert(0 <= l1_ratio && l1_ratio <= 1); + // round to nearest instead of round down + m_L1D_config.set_assoc(max_assoc * l1_ratio + 0.5f); + l1d_configured = true; + break; } + } - printf("GPGPU-Sim: Reconfigure L1 cache to %uKB\n", - m_L1D_config.get_total_size_inKB()); + assert(l1d_configured && "no shared memory option found"); + + 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 + // otherwise, make it ON_FILL to eliminate line allocation fails + // i.e. MSHR throughput is the same, independent on the L1 cache + // size/associativity + if (total_shmem == 0) { + m_L1D_config.set_allocation_policy(ON_MISS); + printf("GPGPU-Sim: Reconfigure L1 allocation to ON_MISS\n"); + } else { + m_L1D_config.set_allocation_policy(ON_FILL); + 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()); k.cache_config_set = true; } @@ -3763,6 +3901,8 @@ void shader_core_ctx::get_icnt_power_stats(long &n_simt_to_mem, n_mem_to_simt += m_stats->n_mem_to_simt[m_sid]; } +kernel_info_t* shd_warp_t::get_kernel_info() const { return m_shader->get_kernel_info(); } + bool shd_warp_t::functional_done() const { return get_n_completed() == m_warp_size; } @@ -3869,15 +4009,26 @@ void opndcoll_rfu_t::init(unsigned num_banks, shader_core_ctx *shader) { assert((m_bank_warp_shift == 5) || (m_warp_size != 32)); sub_core_model = shader->get_config()->sub_core_model; - m_num_warp_sceds = shader->get_config()->gpgpu_num_sched_per_core; - if (sub_core_model) + m_num_warp_scheds = shader->get_config()->gpgpu_num_sched_per_core; + unsigned reg_id; + if (sub_core_model) { assert(num_banks % shader->get_config()->gpgpu_num_sched_per_core == 0); + assert(m_num_warp_scheds <= m_cu.size() && + m_cu.size() % m_num_warp_scheds == 0); + } m_num_banks_per_sched = num_banks / shader->get_config()->gpgpu_num_sched_per_core; for (unsigned j = 0; j < m_cu.size(); j++) { + if (sub_core_model) { + unsigned cusPerSched = m_cu.size() / m_num_warp_scheds; + reg_id = j / cusPerSched; + } m_cu[j]->init(j, num_banks, m_bank_warp_shift, shader->get_config(), this, - sub_core_model, m_num_banks_per_sched); + sub_core_model, reg_id, m_num_banks_per_sched); + } + for (unsigned j = 0; j < m_dispatch_units.size(); j++) { + m_dispatch_units[j].init(sub_core_model,m_num_warp_scheds); } m_initialized = true; } @@ -3976,7 +4127,22 @@ void opndcoll_rfu_t::allocate_cu(unsigned port_num) { for (unsigned j = 0; j < inp.m_cu_sets.size(); j++) { std::vector<collector_unit_t> &cu_set = m_cus[inp.m_cu_sets[j]]; bool allocated = false; - for (unsigned k = 0; k < cu_set.size(); k++) { + unsigned cuLowerBound = 0; + unsigned cuUpperBound = cu_set.size(); + unsigned schd_id; + if (sub_core_model) { + // Sub core model only allocates on the subset of CUs assigned to the + // scheduler that issued + unsigned reg_id = (*inp.m_in[i]).get_ready_reg_id(); + schd_id = (*inp.m_in[i]).get_schd_id(reg_id); + assert(cu_set.size() % m_num_warp_scheds == 0 && + cu_set.size() >= m_num_warp_scheds); + unsigned cusPerSched = cu_set.size() / m_num_warp_scheds; + cuLowerBound = schd_id * cusPerSched; + cuUpperBound = cuLowerBound + cusPerSched; + assert(0 <= cuLowerBound && cuUpperBound <= cu_set.size()); + } + for (unsigned k = cuLowerBound; k < cuUpperBound; k++) { if (cu_set[k].is_free()) { collector_unit_t *cu = &cu_set[k]; allocated = cu->allocate(inp.m_in[i], inp.m_out[i]); @@ -3986,8 +4152,9 @@ void opndcoll_rfu_t::allocate_cu(unsigned port_num) { } if (allocated) break; // cu has been allocated, no need to search more. } - break; // can only service a single input, if it failed it will fail for - // others. + // break; // can only service a single input, if it failed it will fail + // for + // others. } } } @@ -4034,7 +4201,8 @@ void opndcoll_rfu_t::allocate_reads() { } bool opndcoll_rfu_t::collector_unit_t::ready() const { - return (!m_free) && m_not_ready.none() && (*m_output_register).has_free(); + return (!m_free) && m_not_ready.none() && + (*m_output_register).has_free(m_sub_core_model, m_reg_id); } void opndcoll_rfu_t::collector_unit_t::dump( @@ -4052,12 +4220,10 @@ void opndcoll_rfu_t::collector_unit_t::dump( } } -void opndcoll_rfu_t::collector_unit_t::init(unsigned n, unsigned num_banks, - unsigned log2_warp_size, - const core_config *config, - opndcoll_rfu_t *rfu, - bool sub_core_model, - unsigned banks_per_sched) { +void opndcoll_rfu_t::collector_unit_t::init( + unsigned n, unsigned num_banks, unsigned log2_warp_size, + const core_config *config, opndcoll_rfu_t *rfu, bool sub_core_model, + unsigned reg_id, unsigned banks_per_sched) { m_rfu = rfu; m_cuid = n; m_num_banks = num_banks; @@ -4065,6 +4231,7 @@ void opndcoll_rfu_t::collector_unit_t::init(unsigned n, unsigned num_banks, m_warp = new warp_inst_t(config); m_bank_warp_shift = log2_warp_size; m_sub_core_model = sub_core_model; + m_reg_id = reg_id; m_num_banks_per_sched = banks_per_sched; } @@ -4077,12 +4244,19 @@ bool opndcoll_rfu_t::collector_unit_t::allocate(register_set *pipeline_reg_set, warp_inst_t **pipeline_reg = pipeline_reg_set->get_ready(); if ((pipeline_reg) and !((*pipeline_reg)->empty())) { m_warp_id = (*pipeline_reg)->warp_id(); + std::vector<int> prev_regs; // remove duplicate regs within same instr for (unsigned op = 0; op < MAX_REG_OPERANDS; op++) { int reg_num = (*pipeline_reg) ->arch_reg.src[op]; // this math needs to match that used in // function_info::ptx_decode_inst - if (reg_num >= 0) { // valid register + bool new_reg = true; + for (auto r : prev_regs) { + if (r == reg_num) + new_reg = false; + } + if (reg_num >= 0 && new_reg) { // valid register + prev_regs.push_back(reg_num); m_src_op[op] = op_t(this, op, reg_num, m_num_banks, m_bank_warp_shift, m_sub_core_model, m_num_banks_per_sched, (*pipeline_reg)->get_schd_id()); @@ -4099,8 +4273,7 @@ bool opndcoll_rfu_t::collector_unit_t::allocate(register_set *pipeline_reg_set, void opndcoll_rfu_t::collector_unit_t::dispatch() { assert(m_not_ready.none()); - // move_warp(*m_output_register,m_warp); - m_output_register->move_in(m_warp); + m_output_register->move_in(m_sub_core_model, m_reg_id, m_warp); m_free = true; m_output_register = NULL; for (unsigned i = 0; i < MAX_REG_OPERANDS * 2; i++) m_src_op[i].reset(); diff --git a/src/gpgpu-sim/shader.h b/src/gpgpu-sim/shader.h index 6481790..deea1c9 100644 --- a/src/gpgpu-sim/shader.h +++ b/src/gpgpu-sim/shader.h @@ -1,19 +1,21 @@ -// Copyright (c) 2009-2011, Tor M. Aamodt, Wilson W.L. Fung, Andrew Turner, -// Ali Bakhoda -// The University of British Columbia +// Copyright (c) 2009-2021, Tor M. Aamodt, Wilson W.L. Fung, Andrew Turner, +// Ali Bakhoda, Vijay Kandiah, Nikos Hardavellas, +// Mahmoud Khairy, Junrui Pan, Timothy G. Rogers +// The University of British Columbia, Northwestern University, Purdue University // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // -// Redistributions of source code must retain the above copyright notice, this -// list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. Neither the name of -// The University of British Columbia nor the names of its contributors may be -// used to endorse or promote products derived from this software without -// specific prior written permission. +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer; +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution; +// 3. Neither the names of The University of British Columbia, Northwestern +// University nor the names of their contributors may be used to +// endorse or promote products derived from this software without specific +// prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE @@ -169,6 +171,7 @@ class shd_warp_t { void clear_membar() { m_membar = false; } bool get_membar() const { return m_membar; } virtual address_type get_pc() const { return m_next_pc; } + virtual kernel_info_t* get_kernel_info() const; void set_next_pc(address_type pc) { m_next_pc = pc; } void store_info_of_last_inst_at_barrier(const warp_inst_t *pI) { @@ -238,7 +241,10 @@ class shd_warp_t { unsigned get_dynamic_warp_id() const { return m_dynamic_warp_id; } unsigned get_warp_id() const { return m_warp_id; } - class shader_core_ctx * get_shader() { return m_shader; } + class shader_core_ctx *get_shader() { + return m_shader; + } + private: static const unsigned IBUFFER_SIZE = 2; class shader_core_ctx *m_shader; @@ -318,6 +324,7 @@ enum concrete_scheduler { CONCRETE_SCHEDULER_LRR = 0, CONCRETE_SCHEDULER_GTO, CONCRETE_SCHEDULER_TWO_LEVEL_ACTIVE, + CONCRETE_SCHEDULER_RRR, CONCRETE_SCHEDULER_WARP_LIMITING, CONCRETE_SCHEDULER_OLDEST_FIRST, NUM_CONCRETE_SCHEDULERS @@ -369,6 +376,12 @@ class scheduler_unit { // this can be copied freely, so can be used in std const typename std::vector<T> &input_list, const typename std::vector<T>::const_iterator &last_issued_from_input, unsigned num_warps_to_add); + template <typename T> + void order_rrr( + typename std::vector<T> &result_list, + const typename std::vector<T> &input_list, + const typename std::vector<T>::const_iterator &last_issued_from_input, + unsigned num_warps_to_add); enum OrderingType { // The item that issued last is prioritized first then the sorted result @@ -427,6 +440,8 @@ class scheduler_unit { // this can be copied freely, so can be used in std register_set *m_tensor_core_out; register_set *m_mem_out; std::vector<register_set *> &m_spec_cores_out; + unsigned m_num_issued_last_cycle; + unsigned m_current_turn_warp; int m_id; }; @@ -450,6 +465,25 @@ class lrr_scheduler : public scheduler_unit { } }; +class rrr_scheduler : public scheduler_unit { + public: + rrr_scheduler(shader_core_stats *stats, shader_core_ctx *shader, + Scoreboard *scoreboard, simt_stack **simt, + std::vector<shd_warp_t *> *warp, register_set *sp_out, + register_set *dp_out, register_set *sfu_out, + register_set *int_out, register_set *tensor_core_out, + std::vector<register_set *> &spec_cores_out, + register_set *mem_out, int id) + : scheduler_unit(stats, shader, scoreboard, simt, warp, sp_out, dp_out, + sfu_out, int_out, tensor_core_out, spec_cores_out, + mem_out, id) {} + virtual ~rrr_scheduler() {} + virtual void order_warps(); + virtual void done_adding_supervised_warps() { + m_last_supervised_issued = m_supervised_warps.end(); + } +}; + class gto_scheduler : public scheduler_unit { public: gto_scheduler(shader_core_stats *stats, shader_core_ctx *shader, @@ -878,11 +912,13 @@ class opndcoll_rfu_t { // operand collector based register file unit } unsigned get_sp_op() const { return m_warp->sp_op; } unsigned get_id() const { return m_cuid; } // returns CU hw id + unsigned get_reg_id() const { return m_reg_id; } // modifiers void init(unsigned n, unsigned num_banks, unsigned log2_warp_size, const core_config *config, opndcoll_rfu_t *rfu, - bool m_sub_core_model, unsigned num_banks_per_sched); + bool m_sub_core_model, unsigned reg_id, + unsigned num_banks_per_sched); bool allocate(register_set *pipeline_reg, register_set *output_reg); void collect_operand(unsigned op) { m_not_ready.reset(op); } @@ -906,6 +942,7 @@ class opndcoll_rfu_t { // operand collector based register file unit unsigned m_num_banks_per_sched; bool m_sub_core_model; + unsigned m_reg_id; // if sub_core_model enabled, limit regs this cu can r/w }; class dispatch_unit_t { @@ -916,10 +953,19 @@ class opndcoll_rfu_t { // operand collector based register file unit m_num_collectors = (*cus).size(); m_next_cu = 0; } + void init(bool sub_core_model, unsigned num_warp_scheds) { + m_sub_core_model = sub_core_model; + m_num_warp_scheds = num_warp_scheds; + } collector_unit_t *find_ready() { + // With sub-core enabled round robin starts with the next cu assigned to a + // different sub-core than the one that dispatched last + unsigned cusPerSched = m_num_collectors / m_num_warp_scheds; + unsigned rr_increment = m_sub_core_model ? + cusPerSched - (m_last_cu % cusPerSched) : 1; for (unsigned n = 0; n < m_num_collectors; n++) { - unsigned c = (m_last_cu + n + 1) % m_num_collectors; + unsigned c = (m_last_cu + n + rr_increment) % m_num_collectors; if ((*m_collector_units)[c].ready()) { m_last_cu = c; return &((*m_collector_units)[c]); @@ -933,6 +979,8 @@ class opndcoll_rfu_t { // operand collector based register file unit std::vector<collector_unit_t> *m_collector_units; unsigned m_last_cu; // dispatch ready cu's rr unsigned m_next_cu; // for initialization + bool m_sub_core_model; + unsigned m_num_warp_scheds; }; // opndcoll_rfu_t data members @@ -947,7 +995,7 @@ class opndcoll_rfu_t { // operand collector based register file unit arbiter_t m_arbiter; unsigned m_num_banks_per_sched; - unsigned m_num_warp_sceds; + unsigned m_num_warp_scheds; bool sub_core_model; // unsigned m_num_ports; @@ -1039,10 +1087,7 @@ class simd_function_unit { ~simd_function_unit() { delete m_dispatch_reg; } // modifiers - virtual void issue(register_set &source_reg) { - source_reg.move_out_to(m_dispatch_reg); - occupied.set(m_dispatch_reg->latency); - } + virtual void issue(register_set &source_reg); virtual void cycle() = 0; virtual void active_lanes_in_pipeline() = 0; @@ -1051,6 +1096,8 @@ class simd_function_unit { virtual bool can_issue(const warp_inst_t &inst) const { return m_dispatch_reg->empty() && !occupied.test(inst.latency); } + virtual bool is_issue_partitioned() = 0; + virtual unsigned get_issue_reg_id() = 0; virtual bool stallable() const = 0; virtual void print(FILE *fp) const { fprintf(fp, "%s dispatch= ", m_name.c_str()); @@ -1070,7 +1117,7 @@ class pipelined_simd_unit : public simd_function_unit { public: pipelined_simd_unit(register_set *result_port, const shader_core_config *config, unsigned max_latency, - shader_core_ctx *core); + shader_core_ctx *core, unsigned issue_reg_id); // modifiers virtual void cycle(); @@ -1091,6 +1138,8 @@ class pipelined_simd_unit : public simd_function_unit { virtual bool can_issue(const warp_inst_t &inst) const { return simd_function_unit::can_issue(inst); } + virtual bool is_issue_partitioned() = 0; + unsigned get_issue_reg_id() { return m_issue_reg_id; } virtual void print(FILE *fp) const { simd_function_unit::print(fp); for (int s = m_pipeline_depth - 1; s >= 0; s--) { @@ -1106,6 +1155,8 @@ class pipelined_simd_unit : public simd_function_unit { warp_inst_t **m_pipeline_reg; register_set *m_result_port; class shader_core_ctx *m_core; + unsigned m_issue_reg_id; // if sub_core_model is enabled we can only issue + // from a subset of operand collectors unsigned active_insts_in_pipeline; }; @@ -1113,7 +1164,7 @@ class pipelined_simd_unit : public simd_function_unit { class sfu : public pipelined_simd_unit { public: sfu(register_set *result_port, const shader_core_config *config, - shader_core_ctx *core); + shader_core_ctx *core, unsigned issue_reg_id); virtual bool can_issue(const warp_inst_t &inst) const { switch (inst.op) { case SFU_OP: @@ -1129,12 +1180,13 @@ class sfu : public pipelined_simd_unit { } virtual void active_lanes_in_pipeline(); virtual void issue(register_set &source_reg); + bool is_issue_partitioned() { return true; } }; class dp_unit : public pipelined_simd_unit { public: dp_unit(register_set *result_port, const shader_core_config *config, - shader_core_ctx *core); + shader_core_ctx *core, unsigned issue_reg_id); virtual bool can_issue(const warp_inst_t &inst) const { switch (inst.op) { case DP_OP: @@ -1146,12 +1198,13 @@ class dp_unit : public pipelined_simd_unit { } virtual void active_lanes_in_pipeline(); virtual void issue(register_set &source_reg); + bool is_issue_partitioned() { return true; } }; class tensor_core : public pipelined_simd_unit { public: tensor_core(register_set *result_port, const shader_core_config *config, - shader_core_ctx *core); + shader_core_ctx *core, unsigned issue_reg_id); virtual bool can_issue(const warp_inst_t &inst) const { switch (inst.op) { case TENSOR_CORE_OP: @@ -1163,12 +1216,13 @@ class tensor_core : public pipelined_simd_unit { } virtual void active_lanes_in_pipeline(); virtual void issue(register_set &source_reg); + bool is_issue_partitioned() { return true; } }; class int_unit : public pipelined_simd_unit { public: int_unit(register_set *result_port, const shader_core_config *config, - shader_core_ctx *core); + shader_core_ctx *core, unsigned issue_reg_id); virtual bool can_issue(const warp_inst_t &inst) const { switch (inst.op) { case SFU_OP: @@ -1194,12 +1248,13 @@ class int_unit : public pipelined_simd_unit { } virtual void active_lanes_in_pipeline(); virtual void issue(register_set &source_reg); + bool is_issue_partitioned() { return true; } }; class sp_unit : public pipelined_simd_unit { public: sp_unit(register_set *result_port, const shader_core_config *config, - shader_core_ctx *core); + shader_core_ctx *core, unsigned issue_reg_id); virtual bool can_issue(const warp_inst_t &inst) const { switch (inst.op) { case SFU_OP: @@ -1223,13 +1278,14 @@ class sp_unit : public pipelined_simd_unit { } virtual void active_lanes_in_pipeline(); virtual void issue(register_set &source_reg); + bool is_issue_partitioned() { return true; } }; class specialized_unit : public pipelined_simd_unit { public: specialized_unit(register_set *result_port, const shader_core_config *config, shader_core_ctx *core, unsigned supported_op, - char *unit_name, unsigned latency); + char *unit_name, unsigned latency, unsigned issue_reg_id); virtual bool can_issue(const warp_inst_t &inst) const { if (inst.op != m_supported_op) { return false; @@ -1238,6 +1294,7 @@ class specialized_unit : public pipelined_simd_unit { } virtual void active_lanes_in_pipeline(); virtual void issue(register_set &source_reg); + bool is_issue_partitioned() { return true; } private: unsigned m_supported_op; @@ -1259,6 +1316,7 @@ class ldst_unit : public pipelined_simd_unit { // modifiers virtual void issue(register_set &inst); + bool is_issue_partitioned() { return false; } virtual void cycle(); void fill(mem_fetch *mf); @@ -1479,6 +1537,17 @@ class shader_core_config : public core_config { } else break; // we only accept continuous specialized_units, i.e., 1,2,3,4 } + + // parse gpgpu_shmem_option for adpative cache config + if (adaptive_cache_config) { + std::stringstream ss(gpgpu_shmem_option); + while (ss.good()) { + std::string option; + std::getline(ss, option, ','); + shmem_opt_list.push_back((unsigned)std::stoi(option) * 1024); + } + std::sort(shmem_opt_list.begin(), shmem_opt_list.end()); + } } void reg_options(class OptionParser *opp); unsigned max_cta(const kernel_info_t &k) const; @@ -1619,18 +1688,26 @@ struct shader_core_stats_pod { unsigned *m_num_INTdecoded_insn; unsigned *m_num_storequeued_insn; unsigned *m_num_loadqueued_insn; - unsigned *m_num_ialu_acesses; - unsigned *m_num_fp_acesses; - unsigned *m_num_imul_acesses; unsigned *m_num_tex_inst; - unsigned *m_num_fpmul_acesses; - unsigned *m_num_idiv_acesses; - unsigned *m_num_fpdiv_acesses; - unsigned *m_num_sp_acesses; - unsigned *m_num_sfu_acesses; - unsigned *m_num_tensor_core_acesses; - unsigned *m_num_trans_acesses; - unsigned *m_num_mem_acesses; + double *m_num_ialu_acesses; + double *m_num_fp_acesses; + double *m_num_imul_acesses; + double *m_num_fpmul_acesses; + double *m_num_idiv_acesses; + double *m_num_fpdiv_acesses; + double *m_num_sp_acesses; + double *m_num_sfu_acesses; + double *m_num_tensor_core_acesses; + double *m_num_tex_acesses; + double *m_num_const_acesses; + double *m_num_dp_acesses; + double *m_num_dpmul_acesses; + double *m_num_dpdiv_acesses; + double *m_num_sqrt_acesses; + double *m_num_log_acesses; + double *m_num_sin_acesses; + double *m_num_exp_acesses; + double *m_num_mem_acesses; unsigned *m_num_sp_committed; unsigned *m_num_tlb_hits; unsigned *m_num_tlb_accesses; @@ -1640,13 +1717,15 @@ struct shader_core_stats_pod { unsigned *m_read_regfile_acesses; unsigned *m_write_regfile_acesses; unsigned *m_non_rf_operands; - unsigned *m_num_imul24_acesses; - unsigned *m_num_imul32_acesses; + double *m_num_imul24_acesses; + double *m_num_imul32_acesses; unsigned *m_active_sp_lanes; unsigned *m_active_sfu_lanes; unsigned *m_active_tensor_core_lanes; unsigned *m_active_fu_lanes; unsigned *m_active_fu_mem_lanes; + double *m_active_exu_threads; //For power model + double *m_active_exu_warps; //For power model unsigned *m_n_diverge; // number of divergence occurring in this shader unsigned gpgpu_n_load_insn; unsigned gpgpu_n_store_insn; @@ -1717,38 +1796,56 @@ class shader_core_stats : public shader_core_stats_pod { (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); m_num_loadqueued_insn = (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); + m_num_tex_inst = + (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); m_num_INTdecoded_insn = (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); m_num_ialu_acesses = - (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); + (double *)calloc(config->num_shader(), sizeof(double)); m_num_fp_acesses = - (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); - m_num_tex_inst = (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); + (double *)calloc(config->num_shader(), sizeof(double)); m_num_imul_acesses = - (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); + (double *)calloc(config->num_shader(), sizeof(double)); m_num_imul24_acesses = - (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); + (double *)calloc(config->num_shader(), sizeof(double)); m_num_imul32_acesses = - (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); + (double *)calloc(config->num_shader(), sizeof(double)); m_num_fpmul_acesses = - (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); + (double *)calloc(config->num_shader(), sizeof(double)); m_num_idiv_acesses = - (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); + (double *)calloc(config->num_shader(), sizeof(double)); m_num_fpdiv_acesses = - (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); + (double *)calloc(config->num_shader(), sizeof(double)); + m_num_dp_acesses = + (double*) calloc(config->num_shader(),sizeof(double)); + m_num_dpmul_acesses = + (double*) calloc(config->num_shader(),sizeof(double)); + m_num_dpdiv_acesses = + (double*) calloc(config->num_shader(),sizeof(double)); m_num_sp_acesses = - (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); + (double *)calloc(config->num_shader(), sizeof(double)); m_num_sfu_acesses = - (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); - m_num_tensor_core_acesses = - (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); - m_num_trans_acesses = - (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); + (double *)calloc(config->num_shader(), sizeof(double)); + m_num_tensor_core_acesses = + (double *)calloc(config->num_shader(), sizeof(double)); + m_num_const_acesses = + (double *)calloc(config->num_shader(), sizeof(double)); + m_num_tex_acesses = + (double *)calloc(config->num_shader(), sizeof(double)); + m_num_sqrt_acesses = + (double*) calloc(config->num_shader(),sizeof(double)); + m_num_log_acesses = + (double*) calloc(config->num_shader(),sizeof(double)); + m_num_sin_acesses = + (double*) calloc(config->num_shader(),sizeof(double)); + m_num_exp_acesses = + (double*) calloc(config->num_shader(),sizeof(double)); m_num_mem_acesses = - (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); + (double *)calloc(config->num_shader(), sizeof(double)); m_num_sp_committed = (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); - m_num_tlb_hits = (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); + m_num_tlb_hits = + (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); m_num_tlb_accesses = (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); m_active_sp_lanes = @@ -1759,6 +1856,10 @@ class shader_core_stats : public shader_core_stats_pod { (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); m_active_fu_lanes = (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); + m_active_exu_threads = + (double *)calloc(config->num_shader(), sizeof(double)); + m_active_exu_warps = + (double *)calloc(config->num_shader(), sizeof(double)); m_active_fu_mem_lanes = (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); m_num_sfu_committed = @@ -1773,7 +1874,8 @@ class shader_core_stats : public shader_core_stats_pod { (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); m_non_rf_operands = (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); - m_n_diverge = (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); + m_n_diverge = + (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); shader_cycle_distro = (unsigned *)calloc(config->warp_size + 3, sizeof(unsigned)); last_shader_cycle_distro = @@ -1802,6 +1904,48 @@ class shader_core_stats : public shader_core_stats_pod { delete m_incoming_traffic_stats; free(m_num_sim_insn); free(m_num_sim_winsn); + free(m_num_FPdecoded_insn); + free(m_num_INTdecoded_insn); + free(m_num_storequeued_insn); + free(m_num_loadqueued_insn); + free(m_num_ialu_acesses); + free(m_num_fp_acesses); + free(m_num_imul_acesses); + free(m_num_tex_inst); + free(m_num_fpmul_acesses); + free(m_num_idiv_acesses); + free(m_num_fpdiv_acesses); + free(m_num_sp_acesses); + free(m_num_sfu_acesses); + free(m_num_tensor_core_acesses); + free(m_num_tex_acesses); + free(m_num_const_acesses); + free(m_num_dp_acesses); + free(m_num_dpmul_acesses); + free(m_num_dpdiv_acesses); + free(m_num_sqrt_acesses); + free(m_num_log_acesses); + free(m_num_sin_acesses); + free(m_num_exp_acesses); + free(m_num_mem_acesses); + free(m_num_sp_committed); + free(m_num_tlb_hits); + free(m_num_tlb_accesses); + free(m_num_sfu_committed); + free(m_num_tensor_core_committed); + free(m_num_mem_committed); + free(m_read_regfile_acesses); + free(m_write_regfile_acesses); + free(m_non_rf_operands); + free(m_num_imul24_acesses); + free(m_num_imul32_acesses); + free(m_active_sp_lanes); + free(m_active_sfu_lanes); + free(m_active_tensor_core_lanes); + free(m_active_fu_lanes); + free(m_active_exu_threads); + free(m_active_exu_warps); + free(m_active_fu_mem_lanes); free(m_n_diverge); free(shader_cycle_distro); free(last_shader_cycle_distro); @@ -1856,6 +2000,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, unsigned wid, + unsigned sid, unsigned tpc, mem_fetch *original_mf) 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; @@ -1900,7 +2050,7 @@ class shader_core_ctx : public core_t { printf("GPGPU-Sim uArch: Shader %d bind to kernel %u \'%s\'\n", m_sid, m_kernel->get_uid(), m_kernel->name().c_str()); } - + PowerscalingCoefficients *scaling_coeffs; // accessors bool fetch_unit_response_buffer_full() const; bool ldst_unit_response_buffer_full() const; @@ -1958,119 +2108,206 @@ class shader_core_ctx : public core_t { void incload_stat() { m_stats->m_num_loadqueued_insn[m_sid]++; } void incstore_stat() { m_stats->m_num_storequeued_insn[m_sid]++; } - void incialu_stat(unsigned active_count, double latency) { - if (m_config->gpgpu_clock_gated_lanes == false) { - m_stats->m_num_ialu_acesses[m_sid] = - m_stats->m_num_ialu_acesses[m_sid] + active_count * latency + - inactive_lanes_accesses_nonsfu(active_count, latency); - } else { - m_stats->m_num_ialu_acesses[m_sid] = - m_stats->m_num_ialu_acesses[m_sid] + active_count * latency; + void incialu_stat(unsigned active_count,double latency) { + if(m_config->gpgpu_clock_gated_lanes==false){ + m_stats->m_num_ialu_acesses[m_sid]=m_stats->m_num_ialu_acesses[m_sid]+(double)active_count*latency + + inactive_lanes_accesses_nonsfu(active_count, latency); + }else { + m_stats->m_num_ialu_acesses[m_sid]=m_stats->m_num_ialu_acesses[m_sid]+(double)active_count*latency; } + m_stats->m_active_exu_threads[m_sid]+=active_count; + m_stats->m_active_exu_warps[m_sid]++; } - void inctex_stat(unsigned active_count, double latency) { - m_stats->m_num_tex_inst[m_sid] = - m_stats->m_num_tex_inst[m_sid] + active_count * latency; - } - void incimul_stat(unsigned active_count, double latency) { - if (m_config->gpgpu_clock_gated_lanes == false) { - m_stats->m_num_imul_acesses[m_sid] = - m_stats->m_num_imul_acesses[m_sid] + active_count * latency + - inactive_lanes_accesses_nonsfu(active_count, latency); - } else { - m_stats->m_num_imul_acesses[m_sid] = - m_stats->m_num_imul_acesses[m_sid] + active_count * latency; + void incimul_stat(unsigned active_count,double latency) { + if(m_config->gpgpu_clock_gated_lanes==false){ + m_stats->m_num_imul_acesses[m_sid]=m_stats->m_num_imul_acesses[m_sid]+(double)active_count*latency + + inactive_lanes_accesses_nonsfu(active_count, latency); + }else { + m_stats->m_num_imul_acesses[m_sid]=m_stats->m_num_imul_acesses[m_sid]+(double)active_count*latency; } + m_stats->m_active_exu_threads[m_sid]+=active_count; + m_stats->m_active_exu_warps[m_sid]++; } - void incimul24_stat(unsigned active_count, double latency) { - if (m_config->gpgpu_clock_gated_lanes == false) { - m_stats->m_num_imul24_acesses[m_sid] = - m_stats->m_num_imul24_acesses[m_sid] + active_count * latency + - inactive_lanes_accesses_nonsfu(active_count, latency); - } else { - m_stats->m_num_imul24_acesses[m_sid] = - m_stats->m_num_imul24_acesses[m_sid] + active_count * latency; + void incimul24_stat(unsigned active_count,double latency) { + if(m_config->gpgpu_clock_gated_lanes==false){ + m_stats->m_num_imul24_acesses[m_sid]=m_stats->m_num_imul24_acesses[m_sid]+(double)active_count*latency + + inactive_lanes_accesses_nonsfu(active_count, latency); + }else { + m_stats->m_num_imul24_acesses[m_sid]=m_stats->m_num_imul24_acesses[m_sid]+(double)active_count*latency; + } + m_stats->m_active_exu_threads[m_sid]+=active_count; + m_stats->m_active_exu_warps[m_sid]++; + } + void incimul32_stat(unsigned active_count,double latency) { + if(m_config->gpgpu_clock_gated_lanes==false){ + m_stats->m_num_imul32_acesses[m_sid]=m_stats->m_num_imul32_acesses[m_sid]+(double)active_count*latency + + inactive_lanes_accesses_sfu(active_count, latency); + }else{ + m_stats->m_num_imul32_acesses[m_sid]=m_stats->m_num_imul32_acesses[m_sid]+(double)active_count*latency; } + m_stats->m_active_exu_threads[m_sid]+=active_count; + m_stats->m_active_exu_warps[m_sid]++; } - void incimul32_stat(unsigned active_count, double latency) { - if (m_config->gpgpu_clock_gated_lanes == false) { - m_stats->m_num_imul32_acesses[m_sid] = - m_stats->m_num_imul32_acesses[m_sid] + active_count * latency + - inactive_lanes_accesses_sfu(active_count, latency); - } else { - m_stats->m_num_imul32_acesses[m_sid] = - m_stats->m_num_imul32_acesses[m_sid] + active_count * latency; + void incidiv_stat(unsigned active_count,double latency) { + if(m_config->gpgpu_clock_gated_lanes==false){ + m_stats->m_num_idiv_acesses[m_sid]=m_stats->m_num_idiv_acesses[m_sid]+(double)active_count*latency + + inactive_lanes_accesses_sfu(active_count, latency); + }else { + m_stats->m_num_idiv_acesses[m_sid]=m_stats->m_num_idiv_acesses[m_sid]+(double)active_count*latency; } - // printf("Int_Mul -- Active_count: %d\n",active_count); + m_stats->m_active_exu_threads[m_sid]+=active_count; + m_stats->m_active_exu_warps[m_sid]++; } - void incidiv_stat(unsigned active_count, double latency) { - if (m_config->gpgpu_clock_gated_lanes == false) { - m_stats->m_num_idiv_acesses[m_sid] = - m_stats->m_num_idiv_acesses[m_sid] + active_count * latency + - inactive_lanes_accesses_sfu(active_count, latency); - } else { - m_stats->m_num_idiv_acesses[m_sid] = - m_stats->m_num_idiv_acesses[m_sid] + active_count * latency; + void incfpalu_stat(unsigned active_count,double latency) { + if(m_config->gpgpu_clock_gated_lanes==false){ + m_stats->m_num_fp_acesses[m_sid]=m_stats->m_num_fp_acesses[m_sid]+(double)active_count*latency + + inactive_lanes_accesses_nonsfu(active_count, latency); + }else { + m_stats->m_num_fp_acesses[m_sid]=m_stats->m_num_fp_acesses[m_sid]+(double)active_count*latency; } + m_stats->m_active_exu_threads[m_sid]+=active_count; + m_stats->m_active_exu_warps[m_sid]++; } - void incfpalu_stat(unsigned active_count, double latency) { - if (m_config->gpgpu_clock_gated_lanes == false) { - m_stats->m_num_fp_acesses[m_sid] = - m_stats->m_num_fp_acesses[m_sid] + active_count * latency + - inactive_lanes_accesses_nonsfu(active_count, latency); - } else { - m_stats->m_num_fp_acesses[m_sid] = - m_stats->m_num_fp_acesses[m_sid] + active_count * latency; + void incfpmul_stat(unsigned active_count,double latency) { + // printf("FP MUL stat increament\n"); + if(m_config->gpgpu_clock_gated_lanes==false){ + m_stats->m_num_fpmul_acesses[m_sid]=m_stats->m_num_fpmul_acesses[m_sid]+(double)active_count*latency + + inactive_lanes_accesses_nonsfu(active_count, latency); + }else { + m_stats->m_num_fpmul_acesses[m_sid]=m_stats->m_num_fpmul_acesses[m_sid]+(double)active_count*latency; + } + m_stats->m_active_exu_threads[m_sid]+=active_count; + m_stats->m_active_exu_warps[m_sid]++; + } + void incfpdiv_stat(unsigned active_count,double latency) { + if(m_config->gpgpu_clock_gated_lanes==false){ + m_stats->m_num_fpdiv_acesses[m_sid]=m_stats->m_num_fpdiv_acesses[m_sid]+(double)active_count*latency + + inactive_lanes_accesses_sfu(active_count, latency); + }else { + m_stats->m_num_fpdiv_acesses[m_sid]=m_stats->m_num_fpdiv_acesses[m_sid]+(double)active_count*latency; } + m_stats->m_active_exu_threads[m_sid]+=active_count; + m_stats->m_active_exu_warps[m_sid]++; + } + void incdpalu_stat(unsigned active_count,double latency) { + if(m_config->gpgpu_clock_gated_lanes==false){ + m_stats->m_num_dp_acesses[m_sid]=m_stats->m_num_dp_acesses[m_sid]+(double)active_count*latency + + inactive_lanes_accesses_nonsfu(active_count, latency); + }else { + m_stats->m_num_dp_acesses[m_sid]=m_stats->m_num_dp_acesses[m_sid]+(double)active_count*latency; + } + m_stats->m_active_exu_threads[m_sid]+=active_count; + m_stats->m_active_exu_warps[m_sid]++; + } + void incdpmul_stat(unsigned active_count,double latency) { + // printf("FP MUL stat increament\n"); + if(m_config->gpgpu_clock_gated_lanes==false){ + m_stats->m_num_dpmul_acesses[m_sid]=m_stats->m_num_dpmul_acesses[m_sid]+(double)active_count*latency + + inactive_lanes_accesses_nonsfu(active_count, latency); + }else { + m_stats->m_num_dpmul_acesses[m_sid]=m_stats->m_num_dpmul_acesses[m_sid]+(double)active_count*latency; + } + m_stats->m_active_exu_threads[m_sid]+=active_count; + m_stats->m_active_exu_warps[m_sid]++; + } + void incdpdiv_stat(unsigned active_count,double latency) { + if(m_config->gpgpu_clock_gated_lanes==false){ + m_stats->m_num_dpdiv_acesses[m_sid]=m_stats->m_num_dpdiv_acesses[m_sid]+(double)active_count*latency + + inactive_lanes_accesses_sfu(active_count, latency); + }else { + m_stats->m_num_dpdiv_acesses[m_sid]=m_stats->m_num_dpdiv_acesses[m_sid]+(double)active_count*latency; + } + m_stats->m_active_exu_threads[m_sid]+=active_count; + m_stats->m_active_exu_warps[m_sid]++; + } + + void incsqrt_stat(unsigned active_count,double latency) { + if(m_config->gpgpu_clock_gated_lanes==false){ + m_stats->m_num_sqrt_acesses[m_sid]=m_stats->m_num_sqrt_acesses[m_sid]+(double)active_count*latency + + inactive_lanes_accesses_sfu(active_count, latency); + }else{ + m_stats->m_num_sqrt_acesses[m_sid]=m_stats->m_num_sqrt_acesses[m_sid]+(double)active_count*latency; + } + m_stats->m_active_exu_threads[m_sid]+=active_count; + m_stats->m_active_exu_warps[m_sid]++; + } + + void inclog_stat(unsigned active_count,double latency) { + if(m_config->gpgpu_clock_gated_lanes==false){ + m_stats->m_num_log_acesses[m_sid]=m_stats->m_num_log_acesses[m_sid]+(double)active_count*latency + + inactive_lanes_accesses_sfu(active_count, latency); + }else{ + m_stats->m_num_log_acesses[m_sid]=m_stats->m_num_log_acesses[m_sid]+(double)active_count*latency; + } + m_stats->m_active_exu_threads[m_sid]+=active_count; + m_stats->m_active_exu_warps[m_sid]++; + } + + void incexp_stat(unsigned active_count,double latency) { + if(m_config->gpgpu_clock_gated_lanes==false){ + m_stats->m_num_exp_acesses[m_sid]=m_stats->m_num_exp_acesses[m_sid]+(double)active_count*latency + + inactive_lanes_accesses_sfu(active_count, latency); + }else{ + m_stats->m_num_exp_acesses[m_sid]=m_stats->m_num_exp_acesses[m_sid]+(double)active_count*latency; + } + m_stats->m_active_exu_threads[m_sid]+=active_count; + m_stats->m_active_exu_warps[m_sid]++; } - void incfpmul_stat(unsigned active_count, double latency) { - // printf("FP MUL stat increament\n"); - if (m_config->gpgpu_clock_gated_lanes == false) { - m_stats->m_num_fpmul_acesses[m_sid] = - m_stats->m_num_fpmul_acesses[m_sid] + active_count * latency + - inactive_lanes_accesses_nonsfu(active_count, latency); - } else { - m_stats->m_num_fpmul_acesses[m_sid] = - m_stats->m_num_fpmul_acesses[m_sid] + active_count * latency; + + void incsin_stat(unsigned active_count,double latency) { + if(m_config->gpgpu_clock_gated_lanes==false){ + m_stats->m_num_sin_acesses[m_sid]=m_stats->m_num_sin_acesses[m_sid]+(double)active_count*latency + + inactive_lanes_accesses_sfu(active_count, latency); + }else{ + m_stats->m_num_sin_acesses[m_sid]=m_stats->m_num_sin_acesses[m_sid]+(double)active_count*latency; } + m_stats->m_active_exu_threads[m_sid]+=active_count; + m_stats->m_active_exu_warps[m_sid]++; } - void incfpdiv_stat(unsigned active_count, double latency) { - if (m_config->gpgpu_clock_gated_lanes == false) { - m_stats->m_num_fpdiv_acesses[m_sid] = - m_stats->m_num_fpdiv_acesses[m_sid] + active_count * latency + - inactive_lanes_accesses_sfu(active_count, latency); - } else { - m_stats->m_num_fpdiv_acesses[m_sid] = - m_stats->m_num_fpdiv_acesses[m_sid] + active_count * latency; + + + void inctensor_stat(unsigned active_count,double latency) { + if(m_config->gpgpu_clock_gated_lanes==false){ + m_stats->m_num_tensor_core_acesses[m_sid]=m_stats->m_num_tensor_core_acesses[m_sid]+(double)active_count*latency + + inactive_lanes_accesses_sfu(active_count, latency); + }else{ + m_stats->m_num_tensor_core_acesses[m_sid]=m_stats->m_num_tensor_core_acesses[m_sid]+(double)active_count*latency; } + m_stats->m_active_exu_threads[m_sid]+=active_count; + m_stats->m_active_exu_warps[m_sid]++; } - void inctrans_stat(unsigned active_count, double latency) { - if (m_config->gpgpu_clock_gated_lanes == false) { - m_stats->m_num_trans_acesses[m_sid] = - m_stats->m_num_trans_acesses[m_sid] + active_count * latency + - inactive_lanes_accesses_sfu(active_count, latency); - } else { - m_stats->m_num_trans_acesses[m_sid] = - m_stats->m_num_trans_acesses[m_sid] + active_count * latency; + + void inctex_stat(unsigned active_count,double latency) { + if(m_config->gpgpu_clock_gated_lanes==false){ + m_stats->m_num_tex_acesses[m_sid]=m_stats->m_num_tex_acesses[m_sid]+(double)active_count*latency + + inactive_lanes_accesses_sfu(active_count, latency); + }else{ + m_stats->m_num_tex_acesses[m_sid]=m_stats->m_num_tex_acesses[m_sid]+(double)active_count*latency; } + m_stats->m_active_exu_threads[m_sid]+=active_count; + m_stats->m_active_exu_warps[m_sid]++; + } + + void inc_const_accesses(unsigned active_count) { + m_stats->m_num_const_acesses[m_sid]=m_stats->m_num_const_acesses[m_sid]+active_count; } void incsfu_stat(unsigned active_count, double latency) { m_stats->m_num_sfu_acesses[m_sid] = - m_stats->m_num_sfu_acesses[m_sid] + active_count * latency; + m_stats->m_num_sfu_acesses[m_sid] + (double)active_count*latency; } void incsp_stat(unsigned active_count, double latency) { m_stats->m_num_sp_acesses[m_sid] = - m_stats->m_num_sp_acesses[m_sid] + active_count * latency; + m_stats->m_num_sp_acesses[m_sid] + (double)active_count*latency; } void incmem_stat(unsigned active_count, double latency) { if (m_config->gpgpu_clock_gated_lanes == false) { m_stats->m_num_mem_acesses[m_sid] = - m_stats->m_num_mem_acesses[m_sid] + active_count * latency + + m_stats->m_num_mem_acesses[m_sid] + (double)active_count*latency + inactive_lanes_accesses_nonsfu(active_count, latency); } else { m_stats->m_num_mem_acesses[m_sid] = - m_stats->m_num_mem_acesses[m_sid] + active_count * latency; + m_stats->m_num_mem_acesses[m_sid] + (double)active_count*latency; } } void incexecstat(warp_inst_t *&inst); @@ -2133,8 +2370,8 @@ class shader_core_ctx : public core_t { friend class TwoLevelScheduler; friend class LooseRoundRobbinScheduler; virtual void issue_warp(register_set &warp, const warp_inst_t *pI, - const active_mask_t &active_mask, unsigned warp_id, - unsigned sch_id); + const active_mask_t &active_mask, unsigned warp_id, + unsigned sch_id); void create_front_pipeline(); void create_schedulers(); diff --git a/src/gpgpu-sim/stat-tool.cc b/src/gpgpu-sim/stat-tool.cc index 6fafaa6..0513d17 100644 --- a/src/gpgpu-sim/stat-tool.cc +++ b/src/gpgpu-sim/stat-tool.cc @@ -369,8 +369,6 @@ void shader_mem_lat_print(FILE *fout) { static int s_cache_access_logger_n_types = 0; static std::vector<linear_histogram_logger> s_cache_access_logger; -enum cache_access_logger_types { NORMALS, TEXTURE, CONSTANT, INSTRUCTION }; - int get_shader_normal_cache_id() { return NORMALS; } int get_shader_texture_cache_id() { return TEXTURE; } int get_shader_constant_cache_id() { return CONSTANT; } diff --git a/src/gpgpu-sim/stat-tool.h b/src/gpgpu-sim/stat-tool.h index 3a291be..fdf8756 100644 --- a/src/gpgpu-sim/stat-tool.h +++ b/src/gpgpu-sim/stat-tool.h @@ -268,6 +268,8 @@ class linear_histogram_logger : public snap_shot_trigger, static int s_ids; }; +enum cache_access_logger_types { NORMALS, TEXTURE, CONSTANT, INSTRUCTION }; + void try_snap_shot(unsigned long long current_cycle); void set_spill_interval(unsigned long long interval); void spill_log_to_file(FILE *fout, int final, unsigned long long current_cycle); |
