diff options
Diffstat (limited to 'src/gpgpu-sim/l2cache.cc')
| -rw-r--r-- | src/gpgpu-sim/l2cache.cc | 1366 |
1 files changed, 703 insertions, 663 deletions
diff --git a/src/gpgpu-sim/l2cache.cc b/src/gpgpu-sim/l2cache.cc index 4a312d1..6651b21 100644 --- a/src/gpgpu-sim/l2cache.cc +++ b/src/gpgpu-sim/l2cache.cc @@ -7,816 +7,856 @@ // // 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. +// 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. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. -#include <stdlib.h> #include <stdio.h> +#include <stdlib.h> #include <string.h> #include <list> #include <set> +#include "../abstract_hardware_model.h" #include "../option_parser.h" -#include "mem_fetch.h" +#include "../statwrapper.h" #include "dram.h" #include "gpu-cache.h" +#include "gpu-sim.h" #include "histogram.h" #include "l2cache.h" -#include "../statwrapper.h" -#include "../abstract_hardware_model.h" -#include "gpu-sim.h" -#include "shader.h" -#include "mem_latency_stat.h" #include "l2cache_trace.h" +#include "mem_fetch.h" +#include "mem_latency_stat.h" +#include "shader.h" - -mem_fetch * partition_mf_allocator::alloc(new_addr_type addr, mem_access_type type, unsigned size, bool wr, unsigned long long cycle ) const -{ - assert( wr ); - mem_access_t access( type, addr, size, wr, m_memory_config->gpgpu_ctx ); - mem_fetch *mf = new mem_fetch( access, - NULL, - WRITE_PACKET_SIZE, - -1, - -1, - -1, - m_memory_config, - cycle); - return mf; +mem_fetch *partition_mf_allocator::alloc(new_addr_type addr, + mem_access_type type, unsigned size, + bool wr, + unsigned long long cycle) const { + assert(wr); + mem_access_t access(type, addr, size, wr, m_memory_config->gpgpu_ctx); + mem_fetch *mf = new mem_fetch(access, NULL, WRITE_PACKET_SIZE, -1, -1, -1, + m_memory_config, cycle); + return mf; } -memory_partition_unit::memory_partition_unit( unsigned partition_id, - const memory_config *config, - class memory_stats_t *stats, - class gpgpu_sim* gpu) -: m_id(partition_id), m_config(config), m_stats(stats), m_arbitration_metadata(config), m_gpu(gpu) -{ - m_dram = new dram_t(m_id,m_config,m_stats,this,gpu); - - m_sub_partition = new memory_sub_partition*[m_config->m_n_sub_partition_per_memory_channel]; - for (unsigned p = 0; p < m_config->m_n_sub_partition_per_memory_channel; p++) { - unsigned sub_partition_id = m_id * m_config->m_n_sub_partition_per_memory_channel + p; - m_sub_partition[p] = new memory_sub_partition(sub_partition_id, m_config, stats, gpu); - } +memory_partition_unit::memory_partition_unit(unsigned partition_id, + const memory_config *config, + class memory_stats_t *stats, + class gpgpu_sim *gpu) + : m_id(partition_id), + m_config(config), + m_stats(stats), + m_arbitration_metadata(config), + m_gpu(gpu) { + m_dram = new dram_t(m_id, m_config, m_stats, this, gpu); + m_sub_partition = new memory_sub_partition + *[m_config->m_n_sub_partition_per_memory_channel]; + for (unsigned p = 0; p < m_config->m_n_sub_partition_per_memory_channel; + p++) { + unsigned sub_partition_id = + m_id * m_config->m_n_sub_partition_per_memory_channel + p; + m_sub_partition[p] = + new memory_sub_partition(sub_partition_id, m_config, stats, gpu); + } } -void memory_partition_unit::handle_memcpy_to_gpu( size_t addr, unsigned global_subpart_id, mem_access_sector_mask_t mask ) -{ - unsigned p = global_sub_partition_id_to_local_id(global_subpart_id); - std::string mystring = - mask.to_string<char,std::string::traits_type,std::string::allocator_type>(); - MEMPART_DPRINTF("Copy Engine Request Received For Address=%zx, local_subpart=%u, global_subpart=%u, sector_mask=%s \n", addr, p, global_subpart_id, mystring.c_str()); - m_sub_partition[p]->force_l2_tag_update(addr,m_gpu->gpu_sim_cycle+m_gpu->gpu_tot_sim_cycle, mask); +void memory_partition_unit::handle_memcpy_to_gpu( + size_t addr, unsigned global_subpart_id, mem_access_sector_mask_t mask) { + unsigned p = global_sub_partition_id_to_local_id(global_subpart_id); + std::string mystring = mask.to_string<char, std::string::traits_type, + std::string::allocator_type>(); + MEMPART_DPRINTF( + "Copy Engine Request Received For Address=%zx, local_subpart=%u, " + "global_subpart=%u, sector_mask=%s \n", + addr, p, global_subpart_id, mystring.c_str()); + m_sub_partition[p]->force_l2_tag_update( + addr, m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle, mask); } -memory_partition_unit::~memory_partition_unit() -{ - delete m_dram; - for (unsigned p = 0; p < m_config->m_n_sub_partition_per_memory_channel; p++) { - delete m_sub_partition[p]; - } - delete[] m_sub_partition; +memory_partition_unit::~memory_partition_unit() { + delete m_dram; + for (unsigned p = 0; p < m_config->m_n_sub_partition_per_memory_channel; + p++) { + delete m_sub_partition[p]; + } + delete[] m_sub_partition; } -memory_partition_unit::arbitration_metadata::arbitration_metadata(const memory_config *config) -: m_last_borrower(config->m_n_sub_partition_per_memory_channel - 1), - m_private_credit(config->m_n_sub_partition_per_memory_channel, 0), - m_shared_credit(0) -{ - // each sub partition get at least 1 credit for forward progress - // the rest is shared among with other partitions - m_private_credit_limit = 1; - m_shared_credit_limit = config->gpgpu_frfcfs_dram_sched_queue_size - + config->gpgpu_dram_return_queue_size - - (config->m_n_sub_partition_per_memory_channel - 1); - if(config->seperate_write_queue_enabled ) - m_shared_credit_limit += config->gpgpu_frfcfs_dram_write_queue_size; - if (config->gpgpu_frfcfs_dram_sched_queue_size == 0 - or config->gpgpu_dram_return_queue_size == 0) - { - m_shared_credit_limit = 0; // no limit if either of the queue has no limit in size - } - assert(m_shared_credit_limit >= 0); +memory_partition_unit::arbitration_metadata::arbitration_metadata( + const memory_config *config) + : m_last_borrower(config->m_n_sub_partition_per_memory_channel - 1), + m_private_credit(config->m_n_sub_partition_per_memory_channel, 0), + m_shared_credit(0) { + // each sub partition get at least 1 credit for forward progress + // the rest is shared among with other partitions + m_private_credit_limit = 1; + m_shared_credit_limit = config->gpgpu_frfcfs_dram_sched_queue_size + + config->gpgpu_dram_return_queue_size - + (config->m_n_sub_partition_per_memory_channel - 1); + if (config->seperate_write_queue_enabled) + m_shared_credit_limit += config->gpgpu_frfcfs_dram_write_queue_size; + if (config->gpgpu_frfcfs_dram_sched_queue_size == 0 or + config->gpgpu_dram_return_queue_size == 0) { + m_shared_credit_limit = + 0; // no limit if either of the queue has no limit in size + } + assert(m_shared_credit_limit >= 0); } -bool memory_partition_unit::arbitration_metadata::has_credits(int inner_sub_partition_id) const -{ - int spid = inner_sub_partition_id; - if (m_private_credit[spid] < m_private_credit_limit) { - return true; - } else if (m_shared_credit_limit == 0 || m_shared_credit < m_shared_credit_limit) { - return true; - } else { - return false; - } +bool memory_partition_unit::arbitration_metadata::has_credits( + int inner_sub_partition_id) const { + int spid = inner_sub_partition_id; + if (m_private_credit[spid] < m_private_credit_limit) { + return true; + } else if (m_shared_credit_limit == 0 || + m_shared_credit < m_shared_credit_limit) { + return true; + } else { + return false; + } } -void memory_partition_unit::arbitration_metadata::borrow_credit(int inner_sub_partition_id) -{ - int spid = inner_sub_partition_id; - if (m_private_credit[spid] < m_private_credit_limit) { - m_private_credit[spid] += 1; - } else if (m_shared_credit_limit == 0 || m_shared_credit < m_shared_credit_limit) { - m_shared_credit += 1; - } else { - assert(0 && "DRAM arbitration error: Borrowing from depleted credit!"); - } - m_last_borrower = spid; +void memory_partition_unit::arbitration_metadata::borrow_credit( + int inner_sub_partition_id) { + int spid = inner_sub_partition_id; + if (m_private_credit[spid] < m_private_credit_limit) { + m_private_credit[spid] += 1; + } else if (m_shared_credit_limit == 0 || + m_shared_credit < m_shared_credit_limit) { + m_shared_credit += 1; + } else { + assert(0 && "DRAM arbitration error: Borrowing from depleted credit!"); + } + m_last_borrower = spid; } -void memory_partition_unit::arbitration_metadata::return_credit(int inner_sub_partition_id) -{ - int spid = inner_sub_partition_id; - if (m_private_credit[spid] > 0) { - m_private_credit[spid] -= 1; - } else { - m_shared_credit -= 1; - } - assert((m_shared_credit >= 0) && "DRAM arbitration error: Returning more than available credits!"); +void memory_partition_unit::arbitration_metadata::return_credit( + int inner_sub_partition_id) { + int spid = inner_sub_partition_id; + if (m_private_credit[spid] > 0) { + m_private_credit[spid] -= 1; + } else { + m_shared_credit -= 1; + } + assert((m_shared_credit >= 0) && + "DRAM arbitration error: Returning more than available credits!"); } -void memory_partition_unit::arbitration_metadata::print( FILE *fp ) const -{ - fprintf(fp, "private_credit = "); - for (unsigned p = 0; p < m_private_credit.size(); p++) { - fprintf(fp, "%d ", m_private_credit[p]); - } - fprintf(fp, "(limit = %d)\n", m_private_credit_limit); - fprintf(fp, "shared_credit = %d (limit = %d)\n", m_shared_credit, m_shared_credit_limit); +void memory_partition_unit::arbitration_metadata::print(FILE *fp) const { + fprintf(fp, "private_credit = "); + for (unsigned p = 0; p < m_private_credit.size(); p++) { + fprintf(fp, "%d ", m_private_credit[p]); + } + fprintf(fp, "(limit = %d)\n", m_private_credit_limit); + fprintf(fp, "shared_credit = %d (limit = %d)\n", m_shared_credit, + m_shared_credit_limit); } -bool memory_partition_unit::busy() const -{ - bool busy = false; - for (unsigned p = 0; p < m_config->m_n_sub_partition_per_memory_channel; p++) { - if (m_sub_partition[p]->busy()) { - busy = true; - } +bool memory_partition_unit::busy() const { + bool busy = false; + for (unsigned p = 0; p < m_config->m_n_sub_partition_per_memory_channel; + p++) { + if (m_sub_partition[p]->busy()) { + busy = true; } - return busy; + } + return busy; } -void memory_partition_unit::cache_cycle(unsigned cycle) -{ - for (unsigned p = 0; p < m_config->m_n_sub_partition_per_memory_channel; p++) { - m_sub_partition[p]->cache_cycle(cycle); - } +void memory_partition_unit::cache_cycle(unsigned cycle) { + for (unsigned p = 0; p < m_config->m_n_sub_partition_per_memory_channel; + p++) { + m_sub_partition[p]->cache_cycle(cycle); + } } -void memory_partition_unit::visualizer_print( gzFile visualizer_file ) const -{ - m_dram->visualizer_print(visualizer_file); - for (unsigned p = 0; p < m_config->m_n_sub_partition_per_memory_channel; p++) { - m_sub_partition[p]->visualizer_print(visualizer_file); - } +void memory_partition_unit::visualizer_print(gzFile visualizer_file) const { + m_dram->visualizer_print(visualizer_file); + for (unsigned p = 0; p < m_config->m_n_sub_partition_per_memory_channel; + p++) { + m_sub_partition[p]->visualizer_print(visualizer_file); + } } -// determine whether a given subpartition can issue to DRAM -bool memory_partition_unit::can_issue_to_dram(int inner_sub_partition_id) -{ - int spid = inner_sub_partition_id; - bool sub_partition_contention = m_sub_partition[spid]->dram_L2_queue_full(); - bool has_dram_resource = m_arbitration_metadata.has_credits(spid); +// determine whether a given subpartition can issue to DRAM +bool memory_partition_unit::can_issue_to_dram(int inner_sub_partition_id) { + int spid = inner_sub_partition_id; + bool sub_partition_contention = m_sub_partition[spid]->dram_L2_queue_full(); + bool has_dram_resource = m_arbitration_metadata.has_credits(spid); - MEMPART_DPRINTF("sub partition %d sub_partition_contention=%c has_dram_resource=%c\n", - spid, (sub_partition_contention)? 'T':'F', (has_dram_resource)? 'T':'F'); + MEMPART_DPRINTF( + "sub partition %d sub_partition_contention=%c has_dram_resource=%c\n", + spid, (sub_partition_contention) ? 'T' : 'F', + (has_dram_resource) ? 'T' : 'F'); - return (has_dram_resource && !sub_partition_contention); + return (has_dram_resource && !sub_partition_contention); } -int memory_partition_unit::global_sub_partition_id_to_local_id(int global_sub_partition_id) const -{ - return (global_sub_partition_id - m_id * m_config->m_n_sub_partition_per_memory_channel); +int memory_partition_unit::global_sub_partition_id_to_local_id( + int global_sub_partition_id) const { + return (global_sub_partition_id - + m_id * m_config->m_n_sub_partition_per_memory_channel); } -void memory_partition_unit::simple_dram_model_cycle() -{ - - // pop completed memory request from dram and push it to dram-to-L2 queue - // of the original sub partition - if (!m_dram_latency_queue.empty() && ( (m_gpu->gpu_sim_cycle+m_gpu->gpu_tot_sim_cycle) >= m_dram_latency_queue.front().ready_cycle )) { - mem_fetch* mf_return = m_dram_latency_queue.front().req; - if( mf_return->get_access_type() != L1_WRBK_ACC && mf_return->get_access_type() != L2_WRBK_ACC ) { - mf_return->set_reply(); +void memory_partition_unit::simple_dram_model_cycle() { + // pop completed memory request from dram and push it to dram-to-L2 queue + // of the original sub partition + if (!m_dram_latency_queue.empty() && + ((m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle) >= + m_dram_latency_queue.front().ready_cycle)) { + mem_fetch *mf_return = m_dram_latency_queue.front().req; + if (mf_return->get_access_type() != L1_WRBK_ACC && + mf_return->get_access_type() != L2_WRBK_ACC) { + mf_return->set_reply(); - unsigned dest_global_spid = mf_return->get_sub_partition_id(); - int dest_spid = global_sub_partition_id_to_local_id(dest_global_spid); - assert(m_sub_partition[dest_spid]->get_id() == dest_global_spid); - if (!m_sub_partition[dest_spid]->dram_L2_queue_full()) { - if( mf_return->get_access_type() == L1_WRBK_ACC ) { - m_sub_partition[dest_spid]->set_done(mf_return); - delete mf_return; - } else { - m_sub_partition[dest_spid]->dram_L2_queue_push(mf_return); - mf_return->set_status(IN_PARTITION_DRAM_TO_L2_QUEUE,m_gpu->gpu_sim_cycle+m_gpu->gpu_tot_sim_cycle); - m_arbitration_metadata.return_credit(dest_spid); - MEMPART_DPRINTF("mem_fetch request %p return from dram to sub partition %d\n", mf_return, dest_spid); - } - m_dram_latency_queue.pop_front(); - } - - } else { - this->set_done(mf_return); - delete mf_return; - m_dram_latency_queue.pop_front(); - } - } + unsigned dest_global_spid = mf_return->get_sub_partition_id(); + int dest_spid = global_sub_partition_id_to_local_id(dest_global_spid); + assert(m_sub_partition[dest_spid]->get_id() == dest_global_spid); + if (!m_sub_partition[dest_spid]->dram_L2_queue_full()) { + if (mf_return->get_access_type() == L1_WRBK_ACC) { + m_sub_partition[dest_spid]->set_done(mf_return); + delete mf_return; + } else { + m_sub_partition[dest_spid]->dram_L2_queue_push(mf_return); + mf_return->set_status( + IN_PARTITION_DRAM_TO_L2_QUEUE, + m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle); + m_arbitration_metadata.return_credit(dest_spid); + MEMPART_DPRINTF( + "mem_fetch request %p return from dram to sub partition %d\n", + mf_return, dest_spid); + } + m_dram_latency_queue.pop_front(); + } - // mem_fetch *mf = m_sub_partition[spid]->L2_dram_queue_top(); - //if( !m_dram->full(mf->is_write()) ) { - // L2->DRAM queue to DRAM latency queue - // Arbitrate among multiple L2 subpartitions - int last_issued_partition = m_arbitration_metadata.last_borrower(); - for (unsigned p = 0; p < m_config->m_n_sub_partition_per_memory_channel; p++) { - int spid = (p + last_issued_partition + 1) % m_config->m_n_sub_partition_per_memory_channel; - if (!m_sub_partition[spid]->L2_dram_queue_empty() && can_issue_to_dram(spid)) { - mem_fetch *mf = m_sub_partition[spid]->L2_dram_queue_top(); - if(m_dram->full(mf->is_write()) ) - break; + } else { + this->set_done(mf_return); + delete mf_return; + m_dram_latency_queue.pop_front(); + } + } - m_sub_partition[spid]->L2_dram_queue_pop(); - MEMPART_DPRINTF("Issue mem_fetch request %p from sub partition %d to dram\n", mf, spid); - dram_delay_t d; - d.req = mf; - d.ready_cycle = m_gpu->gpu_sim_cycle+m_gpu->gpu_tot_sim_cycle + m_config->dram_latency; - m_dram_latency_queue.push_back(d); - mf->set_status(IN_PARTITION_DRAM_LATENCY_QUEUE,m_gpu->gpu_sim_cycle+m_gpu->gpu_tot_sim_cycle); - m_arbitration_metadata.borrow_credit(spid); - break; // the DRAM should only accept one request per cycle - } - } - //} + // mem_fetch *mf = m_sub_partition[spid]->L2_dram_queue_top(); + // if( !m_dram->full(mf->is_write()) ) { + // L2->DRAM queue to DRAM latency queue + // Arbitrate among multiple L2 subpartitions + int last_issued_partition = m_arbitration_metadata.last_borrower(); + for (unsigned p = 0; p < m_config->m_n_sub_partition_per_memory_channel; + p++) { + int spid = (p + last_issued_partition + 1) % + m_config->m_n_sub_partition_per_memory_channel; + if (!m_sub_partition[spid]->L2_dram_queue_empty() && + can_issue_to_dram(spid)) { + mem_fetch *mf = m_sub_partition[spid]->L2_dram_queue_top(); + if (m_dram->full(mf->is_write())) break; + m_sub_partition[spid]->L2_dram_queue_pop(); + MEMPART_DPRINTF( + "Issue mem_fetch request %p from sub partition %d to dram\n", mf, + spid); + dram_delay_t d; + d.req = mf; + d.ready_cycle = m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle + + m_config->dram_latency; + m_dram_latency_queue.push_back(d); + mf->set_status(IN_PARTITION_DRAM_LATENCY_QUEUE, + m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle); + m_arbitration_metadata.borrow_credit(spid); + break; // the DRAM should only accept one request per cycle + } + } + //} } -void memory_partition_unit::dram_cycle() -{ - // pop completed memory request from dram and push it to dram-to-L2 queue - // of the original sub partition - mem_fetch* mf_return = m_dram->return_queue_top(); - if (mf_return) { - unsigned dest_global_spid = mf_return->get_sub_partition_id(); - int dest_spid = global_sub_partition_id_to_local_id(dest_global_spid); - assert(m_sub_partition[dest_spid]->get_id() == dest_global_spid); - if (!m_sub_partition[dest_spid]->dram_L2_queue_full()) { - if( mf_return->get_access_type() == L1_WRBK_ACC ) { - m_sub_partition[dest_spid]->set_done(mf_return); - delete mf_return; - } else { - m_sub_partition[dest_spid]->dram_L2_queue_push(mf_return); - mf_return->set_status(IN_PARTITION_DRAM_TO_L2_QUEUE,m_gpu->gpu_sim_cycle+m_gpu->gpu_tot_sim_cycle); - m_arbitration_metadata.return_credit(dest_spid); - MEMPART_DPRINTF("mem_fetch request %p return from dram to sub partition %d\n", mf_return, dest_spid); - } - m_dram->return_queue_pop(); - } - } else { - m_dram->return_queue_pop(); +void memory_partition_unit::dram_cycle() { + // pop completed memory request from dram and push it to dram-to-L2 queue + // of the original sub partition + mem_fetch *mf_return = m_dram->return_queue_top(); + if (mf_return) { + unsigned dest_global_spid = mf_return->get_sub_partition_id(); + int dest_spid = global_sub_partition_id_to_local_id(dest_global_spid); + assert(m_sub_partition[dest_spid]->get_id() == dest_global_spid); + if (!m_sub_partition[dest_spid]->dram_L2_queue_full()) { + if (mf_return->get_access_type() == L1_WRBK_ACC) { + m_sub_partition[dest_spid]->set_done(mf_return); + delete mf_return; + } else { + m_sub_partition[dest_spid]->dram_L2_queue_push(mf_return); + mf_return->set_status(IN_PARTITION_DRAM_TO_L2_QUEUE, + m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle); + m_arbitration_metadata.return_credit(dest_spid); + MEMPART_DPRINTF( + "mem_fetch request %p return from dram to sub partition %d\n", + mf_return, dest_spid); + } + m_dram->return_queue_pop(); } - - m_dram->cycle(); - m_dram->dram_log(SAMPLELOG); + } else { + m_dram->return_queue_pop(); + } - // mem_fetch *mf = m_sub_partition[spid]->L2_dram_queue_top(); - //if( !m_dram->full(mf->is_write()) ) { - // L2->DRAM queue to DRAM latency queue - // Arbitrate among multiple L2 subpartitions - int last_issued_partition = m_arbitration_metadata.last_borrower(); - for (unsigned p = 0; p < m_config->m_n_sub_partition_per_memory_channel; p++) { - int spid = (p + last_issued_partition + 1) % m_config->m_n_sub_partition_per_memory_channel; - if (!m_sub_partition[spid]->L2_dram_queue_empty() && can_issue_to_dram(spid)) { - mem_fetch *mf = m_sub_partition[spid]->L2_dram_queue_top(); - if(m_dram->full(mf->is_write()) ) - break; + m_dram->cycle(); + m_dram->dram_log(SAMPLELOG); - m_sub_partition[spid]->L2_dram_queue_pop(); - MEMPART_DPRINTF("Issue mem_fetch request %p from sub partition %d to dram\n", mf, spid); - dram_delay_t d; - d.req = mf; - d.ready_cycle = m_gpu->gpu_sim_cycle+m_gpu->gpu_tot_sim_cycle + m_config->dram_latency; - m_dram_latency_queue.push_back(d); - mf->set_status(IN_PARTITION_DRAM_LATENCY_QUEUE,m_gpu->gpu_sim_cycle+m_gpu->gpu_tot_sim_cycle); - m_arbitration_metadata.borrow_credit(spid); - break; // the DRAM should only accept one request per cycle - } - } - //} + // mem_fetch *mf = m_sub_partition[spid]->L2_dram_queue_top(); + // if( !m_dram->full(mf->is_write()) ) { + // L2->DRAM queue to DRAM latency queue + // Arbitrate among multiple L2 subpartitions + int last_issued_partition = m_arbitration_metadata.last_borrower(); + for (unsigned p = 0; p < m_config->m_n_sub_partition_per_memory_channel; + p++) { + int spid = (p + last_issued_partition + 1) % + m_config->m_n_sub_partition_per_memory_channel; + if (!m_sub_partition[spid]->L2_dram_queue_empty() && + can_issue_to_dram(spid)) { + mem_fetch *mf = m_sub_partition[spid]->L2_dram_queue_top(); + if (m_dram->full(mf->is_write())) break; - // DRAM latency queue - if( !m_dram_latency_queue.empty() && ( (m_gpu->gpu_sim_cycle+m_gpu->gpu_tot_sim_cycle) >= m_dram_latency_queue.front().ready_cycle ) && !m_dram->full(m_dram_latency_queue.front().req->is_write()) ) { - mem_fetch* mf = m_dram_latency_queue.front().req; - m_dram_latency_queue.pop_front(); - m_dram->push(mf); + m_sub_partition[spid]->L2_dram_queue_pop(); + MEMPART_DPRINTF( + "Issue mem_fetch request %p from sub partition %d to dram\n", mf, + spid); + dram_delay_t d; + d.req = mf; + d.ready_cycle = m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle + + m_config->dram_latency; + m_dram_latency_queue.push_back(d); + mf->set_status(IN_PARTITION_DRAM_LATENCY_QUEUE, + m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle); + m_arbitration_metadata.borrow_credit(spid); + break; // the DRAM should only accept one request per cycle } + } + //} + + // DRAM latency queue + if (!m_dram_latency_queue.empty() && + ((m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle) >= + m_dram_latency_queue.front().ready_cycle) && + !m_dram->full(m_dram_latency_queue.front().req->is_write())) { + mem_fetch *mf = m_dram_latency_queue.front().req; + m_dram_latency_queue.pop_front(); + m_dram->push(mf); + } } -void memory_partition_unit::set_done( mem_fetch *mf ) -{ - unsigned global_spid = mf->get_sub_partition_id(); - int spid = global_sub_partition_id_to_local_id(global_spid); - assert(m_sub_partition[spid]->get_id() == global_spid); - if (mf->get_access_type() == L1_WRBK_ACC || mf->get_access_type() == L2_WRBK_ACC) { - m_arbitration_metadata.return_credit(spid); - MEMPART_DPRINTF("mem_fetch request %p return from dram to sub partition %d\n", mf, spid); - } - m_sub_partition[spid]->set_done(mf); +void memory_partition_unit::set_done(mem_fetch *mf) { + unsigned global_spid = mf->get_sub_partition_id(); + int spid = global_sub_partition_id_to_local_id(global_spid); + assert(m_sub_partition[spid]->get_id() == global_spid); + if (mf->get_access_type() == L1_WRBK_ACC || + mf->get_access_type() == L2_WRBK_ACC) { + m_arbitration_metadata.return_credit(spid); + MEMPART_DPRINTF( + "mem_fetch request %p return from dram to sub partition %d\n", mf, + spid); + } + m_sub_partition[spid]->set_done(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 -{ - m_dram->set_dram_power_stats(n_cmd, n_activity, n_nop, n_act, n_pre, n_rd, n_wr, n_req); +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 { + m_dram->set_dram_power_stats(n_cmd, n_activity, n_nop, n_act, n_pre, n_rd, + n_wr, n_req); } -void memory_partition_unit::print( FILE *fp ) const -{ - fprintf(fp, "Memory Partition %u: \n", m_id); - for (unsigned p = 0; p < m_config->m_n_sub_partition_per_memory_channel; p++) { - m_sub_partition[p]->print(fp); - } - fprintf(fp, "In Dram Latency Queue (total = %zd): \n", m_dram_latency_queue.size()); - for (std::list<dram_delay_t>::const_iterator mf_dlq = m_dram_latency_queue.begin(); - mf_dlq != m_dram_latency_queue.end(); ++mf_dlq) { - mem_fetch *mf = mf_dlq->req; - fprintf(fp, "Ready @ %llu - ", mf_dlq->ready_cycle); - if (mf) - mf->print(fp); - else - fprintf(fp, " <NULL mem_fetch?>\n"); - } - m_dram->print(fp); +void memory_partition_unit::print(FILE *fp) const { + fprintf(fp, "Memory Partition %u: \n", m_id); + for (unsigned p = 0; p < m_config->m_n_sub_partition_per_memory_channel; + p++) { + m_sub_partition[p]->print(fp); + } + fprintf(fp, "In Dram Latency Queue (total = %zd): \n", + m_dram_latency_queue.size()); + for (std::list<dram_delay_t>::const_iterator mf_dlq = + m_dram_latency_queue.begin(); + mf_dlq != m_dram_latency_queue.end(); ++mf_dlq) { + mem_fetch *mf = mf_dlq->req; + fprintf(fp, "Ready @ %llu - ", mf_dlq->ready_cycle); + if (mf) + mf->print(fp); + else + fprintf(fp, " <NULL mem_fetch?>\n"); + } + m_dram->print(fp); } -memory_sub_partition::memory_sub_partition( unsigned sub_partition_id, - const memory_config *config, - class memory_stats_t *stats, - class gpgpu_sim* gpu) -{ - m_id = sub_partition_id; - m_config=config; - m_stats=stats; - m_gpu = gpu; - m_memcpy_cycle_offset = 0; +memory_sub_partition::memory_sub_partition(unsigned sub_partition_id, + const memory_config *config, + class memory_stats_t *stats, + class gpgpu_sim *gpu) { + m_id = sub_partition_id; + m_config = config; + m_stats = stats; + m_gpu = gpu; + m_memcpy_cycle_offset = 0; - assert(m_id < m_config->m_n_mem_sub_partition); + assert(m_id < m_config->m_n_mem_sub_partition); - char L2c_name[32]; - snprintf(L2c_name, 32, "L2_bank_%03d", m_id); - m_L2interface = new L2interface(this); - m_mf_allocator = new partition_mf_allocator(config); + char L2c_name[32]; + snprintf(L2c_name, 32, "L2_bank_%03d", m_id); + m_L2interface = new L2interface(this); + m_mf_allocator = new partition_mf_allocator(config); - if(!m_config->m_L2_config.disabled()) - m_L2cache = new l2_cache(L2c_name,m_config->m_L2_config,-1,-1,m_L2interface,m_mf_allocator,IN_PARTITION_L2_MISS_QUEUE, gpu); + if (!m_config->m_L2_config.disabled()) + m_L2cache = + new l2_cache(L2c_name, m_config->m_L2_config, -1, -1, m_L2interface, + m_mf_allocator, IN_PARTITION_L2_MISS_QUEUE, gpu); - unsigned int icnt_L2; - unsigned int L2_dram; - unsigned int dram_L2; - unsigned int L2_icnt; - sscanf(m_config->gpgpu_L2_queue_config,"%u:%u:%u:%u", &icnt_L2,&L2_dram,&dram_L2,&L2_icnt ); - m_icnt_L2_queue = new fifo_pipeline<mem_fetch>("icnt-to-L2",0,icnt_L2); - m_L2_dram_queue = new fifo_pipeline<mem_fetch>("L2-to-dram",0,L2_dram); - m_dram_L2_queue = new fifo_pipeline<mem_fetch>("dram-to-L2",0,dram_L2); - m_L2_icnt_queue = new fifo_pipeline<mem_fetch>("L2-to-icnt",0,L2_icnt); - wb_addr=-1; + unsigned int icnt_L2; + unsigned int L2_dram; + unsigned int dram_L2; + unsigned int L2_icnt; + sscanf(m_config->gpgpu_L2_queue_config, "%u:%u:%u:%u", &icnt_L2, &L2_dram, + &dram_L2, &L2_icnt); + m_icnt_L2_queue = new fifo_pipeline<mem_fetch>("icnt-to-L2", 0, icnt_L2); + m_L2_dram_queue = new fifo_pipeline<mem_fetch>("L2-to-dram", 0, L2_dram); + m_dram_L2_queue = new fifo_pipeline<mem_fetch>("dram-to-L2", 0, dram_L2); + m_L2_icnt_queue = new fifo_pipeline<mem_fetch>("L2-to-icnt", 0, L2_icnt); + wb_addr = -1; } -memory_sub_partition::~memory_sub_partition() -{ - delete m_icnt_L2_queue; - delete m_L2_dram_queue; - delete m_dram_L2_queue; - delete m_L2_icnt_queue; - delete m_L2cache; - delete m_L2interface; +memory_sub_partition::~memory_sub_partition() { + delete m_icnt_L2_queue; + delete m_L2_dram_queue; + delete m_dram_L2_queue; + delete m_L2_icnt_queue; + delete m_L2cache; + delete m_L2interface; } -void memory_sub_partition::cache_cycle( unsigned cycle ) -{ - // L2 fill responses - if( !m_config->m_L2_config.disabled()) { - if ( m_L2cache->access_ready() && !m_L2_icnt_queue->full() ) { - mem_fetch *mf = m_L2cache->next_access(); - if(mf->get_access_type() != L2_WR_ALLOC_R){ // Don't pass write allocate read request back to upper level cache - 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); - }else{ - if(m_config->m_L2_config.m_write_alloc_policy == FETCH_ON_WRITE) - { - mem_fetch* original_wr_mf = mf->get_original_wr_mf(); - assert(original_wr_mf); - original_wr_mf->set_reply(); - original_wr_mf->set_status(IN_PARTITION_L2_TO_ICNT_QUEUE,m_gpu->gpu_sim_cycle+m_gpu->gpu_tot_sim_cycle); - m_L2_icnt_queue->push(original_wr_mf); - } - m_request_tracker.erase(mf); - delete mf; - } - } +void memory_sub_partition::cache_cycle(unsigned cycle) { + // L2 fill responses + if (!m_config->m_L2_config.disabled()) { + if (m_L2cache->access_ready() && !m_L2_icnt_queue->full()) { + mem_fetch *mf = m_L2cache->next_access(); + if (mf->get_access_type() != + L2_WR_ALLOC_R) { // Don't pass write allocate read request back to + // upper level cache + 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); + } else { + if (m_config->m_L2_config.m_write_alloc_policy == FETCH_ON_WRITE) { + mem_fetch *original_wr_mf = mf->get_original_wr_mf(); + assert(original_wr_mf); + original_wr_mf->set_reply(); + original_wr_mf->set_status( + IN_PARTITION_L2_TO_ICNT_QUEUE, + m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle); + m_L2_icnt_queue->push(original_wr_mf); + } + m_request_tracker.erase(mf); + delete mf; + } } + } - // DRAM to L2 (texture) and icnt (not texture) - if ( !m_dram_L2_queue->empty() ) { - mem_fetch *mf = m_dram_L2_queue->top(); - if ( !m_config->m_L2_config.disabled() && m_L2cache->waiting_for_fill(mf) ) { - if (m_L2cache->fill_port_free()) { - mf->set_status(IN_PARTITION_L2_FILL_QUEUE,m_gpu->gpu_sim_cycle+m_gpu->gpu_tot_sim_cycle); - m_L2cache->fill(mf,m_gpu->gpu_sim_cycle+m_gpu->gpu_tot_sim_cycle+m_memcpy_cycle_offset); - m_dram_L2_queue->pop(); - } - } else if ( !m_L2_icnt_queue->full() ) { - if(mf->is_write() && mf->get_type() == WRITE_ACK) - 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); - m_dram_L2_queue->pop(); - } + // DRAM to L2 (texture) and icnt (not texture) + if (!m_dram_L2_queue->empty()) { + mem_fetch *mf = m_dram_L2_queue->top(); + if (!m_config->m_L2_config.disabled() && m_L2cache->waiting_for_fill(mf)) { + if (m_L2cache->fill_port_free()) { + mf->set_status(IN_PARTITION_L2_FILL_QUEUE, + m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle); + m_L2cache->fill(mf, m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle + + m_memcpy_cycle_offset); + m_dram_L2_queue->pop(); + } + } else if (!m_L2_icnt_queue->full()) { + if (mf->is_write() && mf->get_type() == WRITE_ACK) + 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); + m_dram_L2_queue->pop(); } + } - // prior L2 misses inserted into m_L2_dram_queue here - if( !m_config->m_L2_config.disabled() ) - m_L2cache->cycle(); + // prior L2 misses inserted into m_L2_dram_queue here + if (!m_config->m_L2_config.disabled()) m_L2cache->cycle(); - // new L2 texture accesses and/or non-texture accesses - if ( !m_L2_dram_queue->full() && !m_icnt_L2_queue->empty() ) { - mem_fetch *mf = m_icnt_L2_queue->top(); - if ( !m_config->m_L2_config.disabled() && - ( (m_config->m_L2_texure_only && mf->istexture()) || (!m_config->m_L2_texure_only) ) - ) { - // L2 is enabled and access is for L2 - bool output_full = m_L2_icnt_queue->full(); - bool port_free = m_L2cache->data_port_free(); - if ( !output_full && port_free ) { - std::list<cache_event> events; - enum cache_request_status status = m_L2cache->access(mf->get_addr(),mf,m_gpu->gpu_sim_cycle+m_gpu->gpu_tot_sim_cycle+m_memcpy_cycle_offset,events); - bool write_sent = was_write_sent(events); - bool read_sent = was_read_sent(events); - MEM_SUBPART_DPRINTF("Probing L2 cache Address=%llx, status=%u\n", mf->get_addr(), status); + // new L2 texture accesses and/or non-texture accesses + if (!m_L2_dram_queue->full() && !m_icnt_L2_queue->empty()) { + mem_fetch *mf = m_icnt_L2_queue->top(); + if (!m_config->m_L2_config.disabled() && + ((m_config->m_L2_texure_only && mf->istexture()) || + (!m_config->m_L2_texure_only))) { + // L2 is enabled and access is for L2 + bool output_full = m_L2_icnt_queue->full(); + bool port_free = m_L2cache->data_port_free(); + if (!output_full && port_free) { + std::list<cache_event> events; + enum cache_request_status status = + m_L2cache->access(mf->get_addr(), mf, + m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle + + m_memcpy_cycle_offset, + events); + bool write_sent = was_write_sent(events); + bool read_sent = was_read_sent(events); + MEM_SUBPART_DPRINTF("Probing L2 cache Address=%llx, status=%u\n", + mf->get_addr(), status); - if ( status == HIT ) { - if( !write_sent ) { - // L2 cache replies - assert(!read_sent); - 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); - } - m_icnt_L2_queue->pop(); - } else { - assert(write_sent); - m_icnt_L2_queue->pop(); - } - } else if ( status != RESERVATION_FAIL ) { - if(mf->is_write() && (m_config->m_L2_config.m_write_alloc_policy == FETCH_ON_WRITE || 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); - } - // L2 cache accepted request - m_icnt_L2_queue->pop(); - } else { - assert(!write_sent); - assert(!read_sent); - // L2 cache lock-up: will try again next cycle - } + if (status == HIT) { + if (!write_sent) { + // L2 cache replies + assert(!read_sent); + 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); } - } else { - // L2 is disabled or non-texture access to texture-only L2 - mf->set_status(IN_PARTITION_L2_TO_DRAM_QUEUE,m_gpu->gpu_sim_cycle+m_gpu->gpu_tot_sim_cycle); - m_L2_dram_queue->push(mf); m_icnt_L2_queue->pop(); + } else { + assert(write_sent); + m_icnt_L2_queue->pop(); + } + } else if (status != RESERVATION_FAIL) { + if (mf->is_write() && + (m_config->m_L2_config.m_write_alloc_policy == FETCH_ON_WRITE || + 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); + } + // L2 cache accepted request + m_icnt_L2_queue->pop(); + } else { + assert(!write_sent); + assert(!read_sent); + // L2 cache lock-up: will try again next cycle } + } + } else { + // L2 is disabled or non-texture access to texture-only L2 + mf->set_status(IN_PARTITION_L2_TO_DRAM_QUEUE, + m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle); + m_L2_dram_queue->push(mf); + m_icnt_L2_queue->pop(); } + } - // ROP delay queue - if( !m_rop.empty() && (cycle >= m_rop.front().ready_cycle) && !m_icnt_L2_queue->full() ) { - mem_fetch* mf = m_rop.front().req; - m_rop.pop(); - m_icnt_L2_queue->push(mf); - mf->set_status(IN_PARTITION_ICNT_TO_L2_QUEUE,m_gpu->gpu_sim_cycle+m_gpu->gpu_tot_sim_cycle); - } + // ROP delay queue + if (!m_rop.empty() && (cycle >= m_rop.front().ready_cycle) && + !m_icnt_L2_queue->full()) { + mem_fetch *mf = m_rop.front().req; + m_rop.pop(); + m_icnt_L2_queue->push(mf); + mf->set_status(IN_PARTITION_ICNT_TO_L2_QUEUE, + m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle); + } } -bool memory_sub_partition::full() const -{ - return m_icnt_L2_queue->full(); -} +bool memory_sub_partition::full() const { return m_icnt_L2_queue->full(); } -bool memory_sub_partition::full(unsigned size) const -{ - return m_icnt_L2_queue->is_avilable_size(size); +bool memory_sub_partition::full(unsigned size) const { + return m_icnt_L2_queue->is_avilable_size(size); } -bool memory_sub_partition::L2_dram_queue_empty() const -{ - return m_L2_dram_queue->empty(); +bool memory_sub_partition::L2_dram_queue_empty() const { + return m_L2_dram_queue->empty(); } -class mem_fetch* memory_sub_partition::L2_dram_queue_top() const -{ - return m_L2_dram_queue->top(); +class mem_fetch *memory_sub_partition::L2_dram_queue_top() const { + return m_L2_dram_queue->top(); } -void memory_sub_partition::L2_dram_queue_pop() -{ - m_L2_dram_queue->pop(); -} +void memory_sub_partition::L2_dram_queue_pop() { m_L2_dram_queue->pop(); } -bool memory_sub_partition::dram_L2_queue_full() const -{ - return m_dram_L2_queue->full(); +bool memory_sub_partition::dram_L2_queue_full() const { + return m_dram_L2_queue->full(); } -void memory_sub_partition::dram_L2_queue_push( class mem_fetch* mf ) -{ - m_dram_L2_queue->push(mf); +void memory_sub_partition::dram_L2_queue_push(class mem_fetch *mf) { + m_dram_L2_queue->push(mf); } -void memory_sub_partition::print_cache_stat(unsigned &accesses, unsigned &misses) const -{ - FILE *fp = stdout; - if( !m_config->m_L2_config.disabled() ) - m_L2cache->print(fp,accesses,misses); +void memory_sub_partition::print_cache_stat(unsigned &accesses, + unsigned &misses) const { + FILE *fp = stdout; + if (!m_config->m_L2_config.disabled()) m_L2cache->print(fp, accesses, misses); } -void memory_sub_partition::print( FILE *fp ) const -{ - if ( !m_request_tracker.empty() ) { - fprintf(fp,"Memory Sub Parition %u: pending memory requests:\n", m_id); - for ( std::set<mem_fetch*>::const_iterator r=m_request_tracker.begin(); r != m_request_tracker.end(); ++r ) { - mem_fetch *mf = *r; - if ( mf ) - mf->print(fp); - else - fprintf(fp," <NULL mem_fetch?>\n"); - } +void memory_sub_partition::print(FILE *fp) const { + if (!m_request_tracker.empty()) { + fprintf(fp, "Memory Sub Parition %u: pending memory requests:\n", m_id); + for (std::set<mem_fetch *>::const_iterator r = m_request_tracker.begin(); + r != m_request_tracker.end(); ++r) { + mem_fetch *mf = *r; + if (mf) + mf->print(fp); + else + fprintf(fp, " <NULL mem_fetch?>\n"); } - if( !m_config->m_L2_config.disabled() ) - m_L2cache->display_state(fp); + } + if (!m_config->m_L2_config.disabled()) m_L2cache->display_state(fp); } -void memory_stats_t::visualizer_print( gzFile visualizer_file ) -{ - gzprintf(visualizer_file, "Ltwowritemiss: %d\n", L2_write_miss); - gzprintf(visualizer_file, "Ltwowritehit: %d\n", L2_write_hit); - gzprintf(visualizer_file, "Ltworeadmiss: %d\n", L2_read_miss); - gzprintf(visualizer_file, "Ltworeadhit: %d\n", L2_read_hit); - clear_L2_stats_pw(); +void memory_stats_t::visualizer_print(gzFile visualizer_file) { + gzprintf(visualizer_file, "Ltwowritemiss: %d\n", L2_write_miss); + gzprintf(visualizer_file, "Ltwowritehit: %d\n", L2_write_hit); + gzprintf(visualizer_file, "Ltworeadmiss: %d\n", L2_read_miss); + gzprintf(visualizer_file, "Ltworeadhit: %d\n", L2_read_hit); + clear_L2_stats_pw(); - if (num_mfs) - gzprintf(visualizer_file, "averagemflatency: %lld\n", mf_total_lat/num_mfs); + if (num_mfs) + gzprintf(visualizer_file, "averagemflatency: %lld\n", + mf_total_lat / num_mfs); } -void memory_stats_t::clear_L2_stats_pw(){ - L2_write_miss = 0; - L2_write_hit = 0; - L2_read_miss = 0; - L2_read_hit = 0; +void memory_stats_t::clear_L2_stats_pw() { + L2_write_miss = 0; + L2_write_hit = 0; + L2_read_miss = 0; + L2_read_hit = 0; } -void gpgpu_sim::print_dram_stats(FILE *fout) const -{ - unsigned cmd=0; - unsigned activity=0; - unsigned nop=0; - unsigned act=0; - unsigned pre=0; - unsigned rd=0; - unsigned wr=0; - unsigned req=0; - unsigned tot_cmd=0; - unsigned tot_nop=0; - unsigned tot_act=0; - unsigned tot_pre=0; - unsigned tot_rd=0; - unsigned tot_wr=0; - unsigned tot_req=0; +void gpgpu_sim::print_dram_stats(FILE *fout) const { + unsigned cmd = 0; + unsigned activity = 0; + unsigned nop = 0; + unsigned act = 0; + unsigned pre = 0; + unsigned rd = 0; + unsigned wr = 0; + unsigned req = 0; + unsigned tot_cmd = 0; + unsigned tot_nop = 0; + unsigned tot_act = 0; + unsigned tot_pre = 0; + unsigned tot_rd = 0; + unsigned tot_wr = 0; + unsigned tot_req = 0; - 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); - tot_cmd+=cmd; - tot_nop+=nop; - tot_act+=act; - tot_pre+=pre; - tot_rd+=rd; - tot_wr+=wr; - tot_req+=req; - } - fprintf(fout,"gpgpu_n_dram_reads = %d\n",tot_rd ); - fprintf(fout,"gpgpu_n_dram_writes = %d\n",tot_wr ); - fprintf(fout,"gpgpu_n_dram_activate = %d\n",tot_act ); - fprintf(fout,"gpgpu_n_dram_commands = %d\n",tot_cmd); - fprintf(fout,"gpgpu_n_dram_noops = %d\n",tot_nop ); - fprintf(fout,"gpgpu_n_dram_precharges = %d\n",tot_pre ); - fprintf(fout,"gpgpu_n_dram_requests = %d\n",tot_req ); -} - -unsigned memory_sub_partition::flushL2() -{ - if (!m_config->m_L2_config.disabled()) { - m_L2cache->flush(); - } - return 0; //TODO: write the flushed data to the main memory + 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); + tot_cmd += cmd; + tot_nop += nop; + tot_act += act; + tot_pre += pre; + tot_rd += rd; + tot_wr += wr; + tot_req += req; + } + fprintf(fout, "gpgpu_n_dram_reads = %d\n", tot_rd); + fprintf(fout, "gpgpu_n_dram_writes = %d\n", tot_wr); + fprintf(fout, "gpgpu_n_dram_activate = %d\n", tot_act); + fprintf(fout, "gpgpu_n_dram_commands = %d\n", tot_cmd); + fprintf(fout, "gpgpu_n_dram_noops = %d\n", tot_nop); + fprintf(fout, "gpgpu_n_dram_precharges = %d\n", tot_pre); + fprintf(fout, "gpgpu_n_dram_requests = %d\n", tot_req); } -unsigned memory_sub_partition::invalidateL2() -{ - if (!m_config->m_L2_config.disabled()) { - m_L2cache->invalidate(); - } - return 0; +unsigned memory_sub_partition::flushL2() { + if (!m_config->m_L2_config.disabled()) { + m_L2cache->flush(); + } + return 0; // TODO: write the flushed data to the main memory } -bool memory_sub_partition::busy() const -{ - return !m_request_tracker.empty(); +unsigned memory_sub_partition::invalidateL2() { + if (!m_config->m_L2_config.disabled()) { + m_L2cache->invalidate(); + } + return 0; } -std::vector<mem_fetch*> memory_sub_partition::breakdown_request_to_sector_requests(mem_fetch* mf) -{ - std::vector<mem_fetch*> result; +bool memory_sub_partition::busy() const { return !m_request_tracker.empty(); } - if(mf->get_data_size() == SECTOR_SIZE && mf->get_access_sector_mask().count() == 1) { - result.push_back(mf); - } else if (mf->get_data_size() == 128 || mf->get_data_size() == 64) { - //We only accept 32, 64 and 128 bytes reqs - unsigned start=0, end=0; - if(mf->get_data_size() == 128) { - start=0; end=3; - } else if (mf->get_data_size() == 64 && mf->get_access_sector_mask().to_string() == "1100") { - start=2; end=3; - } else if (mf->get_data_size() == 64 && mf->get_access_sector_mask().to_string() == "0011") { - start=0; end=1; - } else if (mf->get_data_size() == 64 && (mf->get_access_sector_mask().to_string() == "1111" || mf->get_access_sector_mask().to_string() == "0000")) { - if(mf->get_addr() % 128 == 0) { - start=0; end=1; - } else { - start=2; end=3; - } - } else - { - 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::vector<mem_fetch *> +memory_sub_partition::breakdown_request_to_sector_requests(mem_fetch *mf) { + std::vector<mem_fetch *> result; - 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); + if (mf->get_data_size() == SECTOR_SIZE && + mf->get_access_sector_mask().count() == 1) { + result.push_back(mf); + } else if (mf->get_data_size() == 128 || mf->get_data_size() == 64) { + // We only accept 32, 64 and 128 bytes reqs + unsigned start = 0, end = 0; + if (mf->get_data_size() == 128) { + start = 0; + end = 3; + } else if (mf->get_data_size() == 64 && + mf->get_access_sector_mask().to_string() == "1100") { + start = 2; + end = 3; + } else if (mf->get_data_size() == 64 && + mf->get_access_sector_mask().to_string() == "0011") { + start = 0; + end = 1; + } else if (mf->get_data_size() == 64 && + (mf->get_access_sector_mask().to_string() == "1111" || + mf->get_access_sector_mask().to_string() == "0000")) { + if (mf->get_addr() % 128 == 0) { + start = 0; + end = 1; + } else { + start = 2; + end = 3; + } + } else { + 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"); + } - for(unsigned j=start, i=0; j<= end ; ++j, ++i){ + 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); - 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); + 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 = + new mem_fetch(*ma, NULL, mf->get_ctrl_size(), mf->get_wid(), + mf->get_sid(), mf->get_tpc(), mf->get_mem_config(), + m_gpu->gpu_tot_sim_cycle + m_gpu->gpu_sim_cycle, mf); - result.push_back(n_mf); - 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"); - } + 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"); + } - return result; + return result; } -void memory_sub_partition::push( mem_fetch* m_req, unsigned long long cycle ) -{ - if (m_req) { - m_stats->memlatstat_icnt2mem_pop(m_req); - std::vector<mem_fetch*> reqs; - if(m_config->m_L2_config.m_cache_type == SECTOR) - reqs = breakdown_request_to_sector_requests(m_req); - else - reqs.push_back(m_req); +void memory_sub_partition::push(mem_fetch *m_req, unsigned long long cycle) { + if (m_req) { + m_stats->memlatstat_icnt2mem_pop(m_req); + std::vector<mem_fetch *> reqs; + if (m_config->m_L2_config.m_cache_type == SECTOR) + reqs = breakdown_request_to_sector_requests(m_req); + else + reqs.push_back(m_req); - for(unsigned i=0; i<reqs.size(); ++i) { - mem_fetch* req = reqs[i]; - m_request_tracker.insert(req); - if( req->istexture() ) { - m_icnt_L2_queue->push(req); - req->set_status(IN_PARTITION_ICNT_TO_L2_QUEUE,m_gpu->gpu_sim_cycle+m_gpu->gpu_tot_sim_cycle); - } else { - rop_delay_t r; - r.req = req; - r.ready_cycle = cycle + m_config->rop_latency; - m_rop.push(r); - req->set_status(IN_PARTITION_ROP_DELAY,m_gpu->gpu_sim_cycle+m_gpu->gpu_tot_sim_cycle); - } - } + for (unsigned i = 0; i < reqs.size(); ++i) { + mem_fetch *req = reqs[i]; + m_request_tracker.insert(req); + if (req->istexture()) { + m_icnt_L2_queue->push(req); + req->set_status(IN_PARTITION_ICNT_TO_L2_QUEUE, + m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle); + } else { + rop_delay_t r; + r.req = req; + r.ready_cycle = cycle + m_config->rop_latency; + m_rop.push(r); + req->set_status(IN_PARTITION_ROP_DELAY, + m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle); + } } + } } -mem_fetch* memory_sub_partition::pop() -{ - mem_fetch* mf = m_L2_icnt_queue->pop(); - m_request_tracker.erase(mf); +mem_fetch *memory_sub_partition::pop() { + mem_fetch *mf = m_L2_icnt_queue->pop(); + m_request_tracker.erase(mf); if ( mf && mf->isatomic() && !m_gpu->get_config().is_trace_driven_mode() ){ mf->do_atomic(); } - if( mf && (mf->get_access_type() == L2_WRBK_ACC || mf->get_access_type() == L1_WRBK_ACC) ) { - delete mf; - mf = NULL; - } - return mf; + if (mf && (mf->get_access_type() == L2_WRBK_ACC || + mf->get_access_type() == L1_WRBK_ACC)) { + delete mf; + mf = NULL; + } + return mf; } -mem_fetch* memory_sub_partition::top() -{ - mem_fetch *mf = m_L2_icnt_queue->top(); - if( mf && (mf->get_access_type() == L2_WRBK_ACC || mf->get_access_type() == L1_WRBK_ACC) ) { - m_L2_icnt_queue->pop(); - m_request_tracker.erase(mf); - delete mf; - mf = NULL; - } - return mf; +mem_fetch *memory_sub_partition::top() { + mem_fetch *mf = m_L2_icnt_queue->top(); + if (mf && (mf->get_access_type() == L2_WRBK_ACC || + mf->get_access_type() == L1_WRBK_ACC)) { + m_L2_icnt_queue->pop(); + m_request_tracker.erase(mf); + delete mf; + mf = NULL; + } + return mf; } -void memory_sub_partition::set_done( mem_fetch *mf ) -{ - m_request_tracker.erase(mf); +void memory_sub_partition::set_done(mem_fetch *mf) { + m_request_tracker.erase(mf); } -void memory_sub_partition::accumulate_L2cache_stats(class cache_stats &l2_stats) const { - if (!m_config->m_L2_config.disabled()) { - l2_stats += m_L2cache->get_stats(); - } +void memory_sub_partition::accumulate_L2cache_stats( + class cache_stats &l2_stats) const { + if (!m_config->m_L2_config.disabled()) { + l2_stats += m_L2cache->get_stats(); + } } -void memory_sub_partition::get_L2cache_sub_stats(struct cache_sub_stats &css) const{ - if (!m_config->m_L2_config.disabled()) { - m_L2cache->get_sub_stats(css); - } +void memory_sub_partition::get_L2cache_sub_stats( + struct cache_sub_stats &css) const { + if (!m_config->m_L2_config.disabled()) { + m_L2cache->get_sub_stats(css); + } } -void memory_sub_partition::get_L2cache_sub_stats_pw(struct cache_sub_stats_pw &css) const{ - if (!m_config->m_L2_config.disabled()) { - m_L2cache->get_sub_stats_pw(css); - } +void memory_sub_partition::get_L2cache_sub_stats_pw( + struct cache_sub_stats_pw &css) const { + if (!m_config->m_L2_config.disabled()) { + m_L2cache->get_sub_stats_pw(css); + } } void memory_sub_partition::clear_L2cache_stats_pw() { - if (!m_config->m_L2_config.disabled()) { - m_L2cache->clear_pw(); - } + if (!m_config->m_L2_config.disabled()) { + m_L2cache->clear_pw(); + } } -void memory_sub_partition::visualizer_print( gzFile visualizer_file ) -{ - // Support for L2 AerialVision stats - // Per-sub-partition stats would be trivial to extend from this - cache_sub_stats_pw temp_sub_stats; - get_L2cache_sub_stats_pw(temp_sub_stats); +void memory_sub_partition::visualizer_print(gzFile visualizer_file) { + // Support for L2 AerialVision stats + // Per-sub-partition stats would be trivial to extend from this + cache_sub_stats_pw temp_sub_stats; + get_L2cache_sub_stats_pw(temp_sub_stats); - m_stats->L2_read_miss += temp_sub_stats.read_misses; - m_stats->L2_write_miss += temp_sub_stats.write_misses; - m_stats->L2_read_hit += temp_sub_stats.read_hits; - m_stats->L2_write_hit += temp_sub_stats.write_hits; + m_stats->L2_read_miss += temp_sub_stats.read_misses; + m_stats->L2_write_miss += temp_sub_stats.write_misses; + m_stats->L2_read_hit += temp_sub_stats.read_hits; + m_stats->L2_write_hit += temp_sub_stats.write_hits; - clear_L2cache_stats_pw(); + clear_L2cache_stats_pw(); } |
