summaryrefslogtreecommitdiff
path: root/src/gpgpu-sim/l2cache.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/gpgpu-sim/l2cache.cc')
-rw-r--r--src/gpgpu-sim/l2cache.cc940
1 files changed, 378 insertions, 562 deletions
diff --git a/src/gpgpu-sim/l2cache.cc b/src/gpgpu-sim/l2cache.cc
index f27c940..cbed2e9 100644
--- a/src/gpgpu-sim/l2cache.cc
+++ b/src/gpgpu-sim/l2cache.cc
@@ -1,10 +1,75 @@
+/*
+ * l2cache.cc
+ *
+ * Copyright (c) 2009 by Tor M. Aamodt and
+ * University of British Columbia
+ * Vancouver, BC V6T 1Z4
+ * All Rights Reserved.
+ *
+ * THIS IS A LEGAL DOCUMENT BY DOWNLOADING GPGPU-SIM, YOU ARE AGREEING TO THESE
+ * TERMS AND CONDITIONS.
+ *
+ * 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 OWNERS 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.
+ *
+ * NOTE: The files libcuda/cuda_runtime_api.c and src/cuda-sim/cuda-math.h
+ * are derived from the CUDA Toolset available from http://www.nvidia.com/cuda
+ * (property of NVIDIA). The files benchmarks/BlackScholes/ and
+ * benchmarks/template/ are derived from the CUDA SDK available from
+ * http://www.nvidia.com/cuda (also property of NVIDIA). The files from
+ * src/intersim/ are derived from Booksim (a simulator provided with the
+ * textbook "Principles and Practices of Interconnection Networks" available
+ * from http://cva.stanford.edu/books/ppin/). As such, those files are bound by
+ * the corresponding legal terms and conditions set forth separately (original
+ * copyright notices are left in files from these sources and where we have
+ * modified a file our copyright notice appears before the original copyright
+ * notice).
+ *
+ * Using this version of GPGPU-Sim requires a complete installation of CUDA
+ * which is distributed seperately by NVIDIA under separate terms and
+ * conditions. To use this version of GPGPU-Sim with OpenCL requires a
+ * recent version of NVIDIA's drivers which support OpenCL.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 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 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.
+ *
+ * 4. This version of GPGPU-SIM is distributed freely for non-commercial use only.
+ *
+ * 5. No nonprofit user may place any restrictions on the use of this software,
+ * including as modified by the user, by any other authorized user.
+ *
+ * 6. GPGPU-SIM was developed primarily by Tor M. Aamodt, Wilson W. L. Fung,
+ * Ali Bakhoda, George L. Yuan, at the University of British Columbia,
+ * Vancouver, BC V6T 1Z4
+ */
+
+
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <list>
#include <set>
-#include "../tr1_hash_map.h" // for unordered_map failback
#include "../option_parser.h"
#include "mem_fetch.h"
@@ -15,137 +80,52 @@
#include "../intersim/statwraper.h"
#include "../abstract_hardware_model.h"
#include "gpu-sim.h"
+#include "shader.h"
+#include "mem_latency_stat.h"
-class L2c_mshr;
-class L2c_miss_tracker;
-class L2c_access_locality;
-
-mem_fetch_t* g_debug_mf = NULL;
-
-// L2 cache block (include the cache model + flow controls)
-struct L2cacheblk
-{
- shd_cache_t *L2cache;
-
- delay_queue *cbtoL2queue; //latency 10
- delay_queue *cbtoL2writequeue;
- delay_queue *dramtoL2queue; //latency 10
- delay_queue *dramtoL2writequeue;
- delay_queue *L2todramqueue; //latency 0
- delay_queue *L2todram_wbqueue;
- delay_queue *L2tocbqueue; //latency 0
-
- mem_fetch_t *L2request; //request currently being serviced by the L2 Cache
-
- L2c_mshr *m_mshr; // mshr model
- L2c_miss_tracker *m_missTracker; // tracker observing for redundant misses
- L2c_access_locality *m_accessLocality; // tracking true locality of L2 Cache access
-
- L2cacheblk(size_t linesize);
- ~L2cacheblk();
-};
+template class fifo_pipeline<mem_fetch>;
// external dependencies
extern unsigned long long int addrdec_mask[5];
-extern int gpgpu_dram_sched_queue_size;
extern unsigned made_write_mfs;
extern unsigned freed_L1write_mfs;
extern unsigned freed_L2write_mfs;
-void memlatstat_icnt2sh_push(mem_fetch_t *mf);
-void memlatstat_dram_access(mem_fetch_t *mf, unsigned dram_id, unsigned bank);
-void memlatstat_start(mem_fetch_t *mf);
-unsigned memlatstat_done(mem_fetch_t *mf);
+address_type L2c_mshr::cache_tag(const mem_fetch *mf) const
+{
+ return (mf->addr & ~(m_linesize - 1));
+}
+
+address_type L2c_miss_tracker::cache_tag(const mem_fetch *mf) const
+{
+ return (mf->addr & ~(m_linesize - 1));
+}
-// option
-char *gpgpu_L2_queue_config;
-bool gpgpu_l2_readoverwrite;
-bool l2_ideal;
+address_type L2c_access_locality::cache_tag(const mem_fetch *mf) const
+{
+ return (mf->addr & ~(m_linesize - 1));
+}
-void L2c_options(option_parser_t opp)
+void gpgpu_sim::L2c_options(option_parser_t opp)
{
- option_parser_register(opp, "-gpgpu_L2_queue", OPT_CSTR, &gpgpu_L2_queue_config,
+ option_parser_register(opp, "-gpgpu_L2_queue", OPT_CSTR, &m_memory_config->gpgpu_L2_queue_config,
"L2 data cache queue length and latency config",
"0:0:0:0:0:0:10:10");
- option_parser_register(opp, "-gpgpu_l2_readoverwrite", OPT_BOOL, &gpgpu_l2_readoverwrite,
+ option_parser_register(opp, "-gpgpu_l2_readoverwrite", OPT_BOOL, &m_memory_config->gpgpu_l2_readoverwrite,
"Prioritize read requests over write requests for L2",
"0");
- option_parser_register(opp, "-l2_ideal", OPT_BOOL, &l2_ideal,
+ option_parser_register(opp, "-l2_ideal", OPT_BOOL, &m_memory_config->l2_ideal,
"Use a ideal L2 cache that always hit",
"0");
}
-// stats
-unsigned L2_write_miss = 0;
-unsigned L2_write_hit = 0;
-unsigned L2_read_hit = 0;
-unsigned L2_read_miss = 0;
-unsigned int *L2_cbtoL2length;
-unsigned int *L2_cbtoL2writelength;
-unsigned int *L2_L2tocblength;
-unsigned int *L2_dramtoL2length;
-unsigned int *L2_dramtoL2writelength;
-unsigned int *L2_L2todramlength;
////////////////////////////////////////////////
// L2 MSHR model
-class L2c_mshr
-{
-private:
- typedef std::list<const mem_fetch_t*> mem_fetch_list;
- typedef tr1_hash_map<address_type, mem_fetch_list> L2missGroup;
- L2missGroup m_L2missgroup; // structure tracking redundant dram access
-
- struct active_chain {
- address_type cacheTag;
- mem_fetch_list *list;
- active_chain() : cacheTag(0xDEADBEEF), list(NULL) { }
- };
- active_chain m_active_mshr_chain;
- size_t m_linesize; // L2 cache line size
-
- const size_t m_n_entries; // total number of entries available
- size_t m_entries_used; // number of entries in use
-
- int m_n_miss;
- int m_n_miss_serviced_by_dram;
- int m_n_mshr_hits;
- size_t m_max_entries_used;
-
- address_type cache_tag(const mem_fetch_t *mf) const
- {
- // return mf->addr;
- return (mf->addr & ~(m_linesize - 1));
- }
-
-public:
- L2c_mshr(size_t linesize, size_t n_entries = 64)
- : m_linesize(linesize), m_n_entries(n_entries), m_entries_used(0),
- m_n_miss(0), m_n_miss_serviced_by_dram(0), m_n_mshr_hits(0), m_max_entries_used(0) { }
-
- // add a cache miss to MSHR, return true if this access is hit another existing entry and merges with it
- bool new_miss(const mem_fetch_t *mf);
-
- // notify MSHR that a new cache line has been fetched, activate the associated MSHR chain
- void miss_serviced(const mem_fetch_t *mf);
-
- // probe if there are pending hits left in this MSHR chain
- bool mshr_chain_empty();
-
- // peek the first entry in the active MSHR chain
- mem_fetch_t *mshr_chain_top();
-
- // pop the first entry in the active MSHR chain
- void mshr_chain_pop();
-
- void print(FILE *fout = stdout);
- void print_stat(FILE *fout = stdout);
-};
-
-bool L2c_mshr::new_miss(const mem_fetch_t *mf)
+bool L2c_mshr::new_miss(const mem_fetch *mf)
{
address_type cacheTag = cache_tag(mf);
mem_fetch_list &missGroup = m_L2missgroup[cacheTag];
@@ -163,7 +143,7 @@ bool L2c_mshr::new_miss(const mem_fetch_t *mf)
return mshr_hit;
}
-void L2c_mshr::miss_serviced(const mem_fetch_t *mf)
+void L2c_mshr::miss_serviced(const mem_fetch *mf)
{
assert(m_active_mshr_chain.list == NULL);
address_type cacheTag = cache_tag(mf);
@@ -185,12 +165,12 @@ bool L2c_mshr::mshr_chain_empty()
return (m_active_mshr_chain.list == NULL);
}
-mem_fetch_t *L2c_mshr::mshr_chain_top()
+mem_fetch *L2c_mshr::mshr_chain_top()
{
- const mem_fetch_t *mf = m_active_mshr_chain.list->back();
+ const mem_fetch *mf = m_active_mshr_chain.list->back();
assert(cache_tag(mf) == m_active_mshr_chain.cacheTag);
- return const_cast<mem_fetch_t*>(mf);
+ return const_cast<mem_fetch*>(mf);
}
void L2c_mshr::mshr_chain_pop()
@@ -218,7 +198,7 @@ void L2c_mshr::print(FILE *fout)
}
}
-void L2c_mshr::print_stat(FILE *fout)
+void L2c_mshr::print_stat(FILE *fout) const
{
fprintf(fout, "L2c MSHR: max_entry = %zu, n_miss = %d, n_mshr_hits = %d, n_serviced_by_dram %d\n",
m_max_entries_used, m_n_miss, m_n_mshr_hits, m_n_miss_serviced_by_dram);
@@ -226,36 +206,8 @@ void L2c_mshr::print_stat(FILE *fout)
////////////////////////////////////////////////
// track redundant dram access generated by L2 cache
-class L2c_miss_tracker
-{
-private:
- typedef std::set<mem_fetch_t*> mem_fetch_set;
- typedef tr1_hash_map<address_type, mem_fetch_set> L2missGroup;
- L2missGroup m_L2missgroup; // structure tracking redundant dram access
- size_t m_linesize; // L2 cache line size
-
- typedef tr1_hash_map<address_type, int> L2redundantCnt;
- L2redundantCnt m_L2redundantCnt;
-
- int m_totalL2redundantAcc;
-
- address_type cache_tag(const mem_fetch_t *mf) const
- {
- // return mf->addr;
- return (mf->addr & ~(m_linesize - 1));
- }
-public:
- L2c_miss_tracker(size_t linesize) : m_linesize(linesize), m_totalL2redundantAcc(0) { }
- void new_miss(mem_fetch_t *mf);
- void miss_serviced(mem_fetch_t *mf);
-
- void print(FILE *fout, bool brief = true);
- void print_stat(FILE *fout, bool brief = true);
-
-};
-
-void L2c_miss_tracker::new_miss(mem_fetch_t *mf)
+void L2c_miss_tracker::new_miss(mem_fetch *mf)
{
address_type cacheTag = cache_tag(mf);
mem_fetch_set &missGroup = m_L2missgroup[cacheTag];
@@ -268,7 +220,7 @@ void L2c_miss_tracker::new_miss(mem_fetch_t *mf)
missGroup.insert(mf);
}
-void L2c_miss_tracker::miss_serviced(mem_fetch_t *mf)
+void L2c_miss_tracker::miss_serviced(mem_fetch *mf)
{
address_type cacheTag = cache_tag(mf);
L2missGroup::iterator iMissGroup = m_L2missgroup.find(cacheTag);
@@ -295,12 +247,12 @@ void L2c_miss_tracker::print(FILE *fout, bool brief)
}
}
-void L2c_miss_tracker::print_stat(FILE *fout, bool brief)
+void L2c_miss_tracker::print_stat(FILE *fout, bool brief) const
{
fprintf(fout, "RedundantMiss = %d\n", m_totalL2redundantAcc);
if (brief == true) return;
fprintf(fout, " Detail:");
- for (L2redundantCnt::iterator iL2rc = m_L2redundantCnt.begin(); iL2rc != m_L2redundantCnt.end(); ++iL2rc) {
+ for (L2redundantCnt::const_iterator iL2rc = m_L2redundantCnt.begin(); iL2rc != m_L2redundantCnt.end(); ++iL2rc) {
fprintf(fout, "%#08x:%d ", iL2rc->first, iL2rc->second);
}
fprintf(fout, "\n");
@@ -308,76 +260,90 @@ void L2c_miss_tracker::print_stat(FILE *fout, bool brief)
////////////////////////////////////////////////
// track all locality of L2 cache access
-class L2c_access_locality
-{
-private:
- size_t m_linesize; // L2 cache line size
-
- typedef tr1_hash_map<address_type, int> L2accCnt;
- L2accCnt m_L2accCnt;
-
- int m_totalL2accAcc;
-
- address_type cache_tag(const mem_fetch_t *mf) const
- {
- // return mf->addr;
- return (mf->addr & ~(m_linesize - 1));
- }
-
-public:
- L2c_access_locality(size_t linesize) : m_linesize(linesize), m_totalL2accAcc(0) { }
- void access(mem_fetch_t *mf);
-
- void print_stat(FILE *fout, bool brief = true);
-
-};
-
-void L2c_access_locality::access(mem_fetch_t *mf)
+void L2c_access_locality::access(mem_fetch *mf)
{
address_type cacheTag = cache_tag(mf);
m_L2accCnt[cacheTag] += 1;
m_totalL2accAcc += 1;
}
-void L2c_access_locality::print_stat(FILE *fout, bool brief)
+void L2c_access_locality::print_stat(FILE *fout, bool brief) const
{
float access_locality = (float) m_totalL2accAcc / m_L2accCnt.size();
fprintf(fout, "Access Locality = %d / %zu (%f) \n", m_totalL2accAcc, m_L2accCnt.size(), access_locality);
if (brief == true) return;
fprintf(fout, " Detail:");
pow2_histogram locality_histo(" Hits");
- for (L2accCnt::iterator iL2rc = m_L2accCnt.begin(); iL2rc != m_L2accCnt.end(); ++iL2rc) {
+ for (L2accCnt::const_iterator iL2rc = m_L2accCnt.begin(); iL2rc != m_L2accCnt.end(); ++iL2rc) {
locality_histo.add2bin(iL2rc->second);
- // fprintf(fout, "%#08x:%d\n", iL2rc->first, iL2rc->second);
}
locality_histo.fprint(fout);
fprintf(fout, "\n");
}
-L2cacheblk::L2cacheblk(size_t linesize)
-: m_mshr(new L2c_mshr(linesize)),
- m_missTracker(new L2c_miss_tracker(linesize)),
- m_accessLocality(new L2c_access_locality(linesize))
-{ }
-
-L2cacheblk::~L2cacheblk()
+memory_partition_unit::~memory_partition_unit()
{
delete m_mshr;
delete m_missTracker;
delete m_accessLocality;
}
+void memory_partition_unit::set_stats( class memory_stats_t *stats )
+{
+ m_stats=stats;
+ m_dram->set_stats(stats);
+}
+
+void memory_partition_unit::cache_cycle()
+{
+ L2c_process_dram_output(); // pop from dram
+ L2c_push_miss_to_dram(); // push to dram
+ L2c_service_mem_req(); // pop(push) from(to) icnt2l2(l2toicnt) queues; service l2 requests
+ if (m_config->gpgpu_cache_dl2_opt) { // L2 cache enabled
+ L2c_update_stat();
+ L2c_log(SAMPLELOG);
+ }
+}
+
+unsigned memory_partition_unit::L2c_get_linesize()
+{
+ return L2cache->line_sz;
+}
+
+bool memory_partition_unit::full() const
+{
+ if (m_config->gpgpu_cache_dl2_opt) {
+ return cbtoL2queue->full() || cbtoL2writequeue->full();
+ } else {
+ return( m_config->gpgpu_dram_sched_queue_size && m_dram->full() );
+ }
+}
////////////////////////////////////////////////
// L2 access functions
// L2 Cache Creation
-void L2c_create ( dram_t* dram_p, const char* cache_opt )
+memory_partition_unit::memory_partition_unit( unsigned partition_id, struct memory_config *config )
{
- unsigned int shd_n_set;
- unsigned int shd_linesize;
- unsigned int shd_n_assoc;
- unsigned char shd_policy;
+ m_id = partition_id;
+ m_config=config;
+ m_stats=NULL;
+ m_dram = new dram_t(m_id, m_config);
+
+ char L2c_name[32];
+ snprintf(L2c_name, 32, "L2_%03d", m_id);
+
+ if( m_config->gpgpu_cache_dl2_opt ) {
+ L2cache = shd_cache_create(L2c_name,m_config->gpgpu_cache_dl2_opt, 16, ~addrdec_mask[CHIP], write_through);
+ m_mshr = new L2c_mshr(L2cache->line_sz);
+ m_missTracker = new L2c_miss_tracker(L2cache->line_sz);
+ m_accessLocality = new L2c_access_locality(L2cache->line_sz);
+ } else {
+ L2cache=NULL;
+ m_mshr=NULL;
+ m_missTracker=NULL;
+ m_accessLocality=NULL;
+ }
unsigned int L2c_cb_L2_length;
unsigned int L2c_cb_L2w_length;
@@ -388,173 +354,116 @@ void L2c_create ( dram_t* dram_p, const char* cache_opt )
unsigned int L2c_L2_cb_minlength;
unsigned int L2c_L2_dm_minlength;
- sscanf(cache_opt,"%d:%d:%d:%c",
- &shd_n_set, &shd_linesize, &shd_n_assoc, &shd_policy);
-
- L2cacheblk *p_L2c = new L2cacheblk(shd_linesize);
-
- char L2c_name[32];
- snprintf(L2c_name, 32, "L2c_%03d", dram_p->id);
- p_L2c->L2cache = shd_cache_create(L2c_name,
- shd_n_set, shd_n_assoc, shd_linesize,
- shd_policy, 16, ~addrdec_mask[CHIP],
- write_through); //write_through maintains old behavior for now
-
- sscanf(gpgpu_L2_queue_config,"%d:%d:%d:%d:%d:%d:%d:%d",
+ sscanf(m_config->gpgpu_L2_queue_config,"%d:%d:%d:%d:%d:%d:%d:%d",
&L2c_cb_L2_length, &L2c_cb_L2w_length, &L2c_L2_dm_length,
&L2c_dm_L2_length, &L2c_dm_L2w_length, &L2c_L2_cb_length,
&L2c_L2_cb_minlength, &L2c_L2_dm_minlength );
//(<name>,<latency>,<min_length>,<max_length>)
- p_L2c->cbtoL2queue = dq_create("cbtoL2queue", 0,0,L2c_cb_L2_length);
- p_L2c->cbtoL2writequeue = dq_create("cbtoL2writequeue", 0,0,L2c_cb_L2w_length);
- p_L2c->L2todramqueue = dq_create("L2todramqueue", 0,L2c_L2_dm_minlength,L2c_L2_dm_length);
- p_L2c->dramtoL2queue = dq_create("dramtoL2queue", 0,0,L2c_dm_L2_length);
- p_L2c->dramtoL2writequeue = dq_create("dramtoL2writequeue",0,0,L2c_dm_L2w_length);
- p_L2c->L2tocbqueue = dq_create("L2tocbqueue", 0,L2c_L2_cb_minlength,L2c_L2_cb_length);
-
- p_L2c->L2todram_wbqueue = dq_create("L2todram_wbqueue", 0,L2c_L2_dm_minlength,
- L2c_L2_dm_minlength + gpgpu_dram_sched_queue_size + L2c_dm_L2_length);
-
- p_L2c->L2request = NULL;
-
- assert(dram_p->m_L2cache == NULL);
- dram_p->m_L2cache = reinterpret_cast<void*>(p_L2c);
-}
-
-unsigned L2c_get_linesize( dram_t *dram_p )
-{
- assert(dram_p->m_L2cache != NULL);
- L2cacheblk *p_L2c = reinterpret_cast<L2cacheblk*>(dram_p->m_L2cache);
- return p_L2c->L2cache->line_sz;
-}
-
-int L2c_full( dram_t *dram_p )
-{
- assert(dram_p->m_L2cache != NULL);
- L2cacheblk *p_L2c = reinterpret_cast<L2cacheblk*>(dram_p->m_L2cache);
- return(dq_full(p_L2c->cbtoL2queue) || dq_full(p_L2c->cbtoL2writequeue));
-}
-
-void L2c_push( dram_t *dram_p, mem_fetch_t *mf )
-{
- assert(dram_p->m_L2cache != NULL);
- L2cacheblk *p_L2c = reinterpret_cast<L2cacheblk*>(dram_p->m_L2cache);
-
- if (gpgpu_l2_readoverwrite && mf->write)
- dq_push(p_L2c->cbtoL2writequeue, mf);
- else
- dq_push(p_L2c->cbtoL2queue, mf);
- p_L2c->m_accessLocality->access(mf);
- if (mf->mshr) mshr_update_status(mf->mshr, IN_CBTOL2QUEUE);
+ cbtoL2queue = new fifo_pipeline<mem_fetch>("cbtoL2queue", 0,L2c_cb_L2_length, gpu_sim_cycle);
+ cbtoL2writequeue = new fifo_pipeline<mem_fetch>("cbtoL2writequeue", 0,L2c_cb_L2w_length, gpu_sim_cycle);
+ L2todramqueue = new fifo_pipeline<mem_fetch>("L2todramqueue", L2c_L2_dm_minlength, L2c_L2_dm_length, gpu_sim_cycle);
+ dramtoL2queue = new fifo_pipeline<mem_fetch>("dramtoL2queue", 0,L2c_dm_L2_length, gpu_sim_cycle);
+ dramtoL2writequeue = new fifo_pipeline<mem_fetch>("dramtoL2writequeue",0,L2c_dm_L2w_length, gpu_sim_cycle);
+ L2tocbqueue = new fifo_pipeline<mem_fetch>("L2tocbqueue", L2c_L2_cb_minlength, L2c_L2_cb_length, gpu_sim_cycle);
+ L2todram_wbqueue = new fifo_pipeline<mem_fetch>("L2todram_wbqueue", L2c_L2_dm_minlength, L2c_L2_dm_minlength + m_config->gpgpu_dram_sched_queue_size + L2c_dm_L2_length, gpu_sim_cycle);
+ L2request = NULL;
+ L2dramout = NULL;
+ wb_addr=-1;
+ if (m_config->gpgpu_cache_dl2_opt && 1) {
+ cbtol2_Dist = StatCreate("cbtoL2",1, cbtoL2queue->get_max_len());
+ cbtoL2wr_Dist = StatCreate("cbtoL2write",1, cbtoL2writequeue->get_max_len());
+ L2tocb_Dist = StatCreate("L2tocb",1, L2tocbqueue->get_max_len());
+ dramtoL2_Dist = StatCreate("dramtoL2",1, dramtoL2queue->get_max_len());
+ dramtoL2wr_Dist = StatCreate("dramtoL2write",1, dramtoL2writequeue->get_max_len());
+ L2todram_Dist = StatCreate("L2todram",1, L2todramqueue->get_max_len());
+ L2todram_wb_Dist = StatCreate("L2todram_wb",1, L2todram_wbqueue->get_max_len());
+ } else {
+ cbtol2_Dist = NULL;
+ cbtoL2wr_Dist = NULL;
+ L2tocb_Dist = NULL;
+ dramtoL2_Dist = NULL;
+ dramtoL2wr_Dist = NULL;
+ L2todram_Dist = NULL;
+ L2todram_wb_Dist = NULL;
+ }
}
-mem_fetch_t* L2c_pop( dram_t *dram_p )
+mem_fetch* memory_partition_unit::L2c_pop( dram_t *dram_p )
{
- assert(dram_p->m_L2cache != NULL);
- L2cacheblk *p_L2c = reinterpret_cast<L2cacheblk*>(dram_p->m_L2cache);
+ assert(dram_p->m_memory_partition_unit != NULL);
+ memory_partition_unit *p_L2c = reinterpret_cast<memory_partition_unit*>(dram_p->m_memory_partition_unit);
- mem_fetch_t *mf;
- mf = (mem_fetch_t*)dq_pop(p_L2c->L2tocbqueue);
+ mem_fetch *mf;
+ mf = p_L2c->L2tocbqueue->pop(gpu_sim_cycle);
return mf;
}
-mem_fetch_t* L2c_top( dram_t *dram_p )
-{
- assert(dram_p->m_L2cache != NULL);
- L2cacheblk *p_L2c = reinterpret_cast<L2cacheblk*>(dram_p->m_L2cache);
-
- return (mem_fetch_t*)dq_top(p_L2c->L2tocbqueue);
-}
-
-void L2c_qlen ( dram_t *dram_p )
-{
- assert(dram_p->m_L2cache != NULL);
- L2cacheblk *p_L2c = reinterpret_cast<L2cacheblk*>(dram_p->m_L2cache);
-
- printf("\n");
- printf("cb->L2{%d}\tcb->L2w{%d}\tL2->cb{%d}\n",
- p_L2c->cbtoL2queue->length,
- p_L2c->cbtoL2writequeue->length,
- p_L2c->L2tocbqueue->length);
- printf("dm->L2{%d}\tdm->L2w{%d}\tL2->dm{%d}\tL2->wb_dm{%d}\n",
- p_L2c->dramtoL2queue->length,
- p_L2c->dramtoL2writequeue->length,
- p_L2c->L2todramqueue->length,
- p_L2c->L2todram_wbqueue->length);
-}
-
// service memory request in icnt-to-L2 queue, writing to L2 as necessary
// (if L2 writeback miss, writeback to memory)
-void L2c_service_mem_req ( dram_t* dram_p, int dm_id )
+void memory_partition_unit::L2c_service_mem_req()
{
- assert(dram_p->m_L2cache != NULL);
- L2cacheblk *p_L2c = reinterpret_cast<L2cacheblk*>(dram_p->m_L2cache);
-
- mem_fetch_t* mf;
-
- if (!p_L2c->L2request) {
+ if (!L2request) {
//if not servicing L2 cache request..
- p_L2c->L2request = (mem_fetch_t*) dq_pop(p_L2c->cbtoL2queue); //..then get one
- if (!p_L2c->L2request) {
- p_L2c->L2request = (mem_fetch_t*) dq_pop(p_L2c->cbtoL2writequeue);
- }
+ L2request = cbtoL2queue->pop(gpu_sim_cycle); //..then get one
+ if (!L2request)
+ L2request = cbtoL2writequeue->pop(gpu_sim_cycle);
}
- mf = p_L2c->L2request;
+ mem_fetch* mf = L2request;
if (!mf) return;
switch (mf->type) {
case RD_REQ:
case WT_REQ: {
- shd_cache_line_t *hit_cacheline = shd_cache_access(p_L2c->L2cache,
+ shd_cache_line_t *hit_cacheline = shd_cache_access(L2cache,
mf->addr,
- 4, mf->write,
+ 4, mf->m_write,
gpu_sim_cycle);
- if (hit_cacheline || l2_ideal) { //L2 Cache Hit; reads are sent as a single command and need to be stored
- if (!mf->write) { //L2 Cache Read
- if ( dq_full(p_L2c->L2tocbqueue) ) {
- p_L2c->L2cache->access--;
+ if (hit_cacheline || m_config->l2_ideal) { //L2 Cache Hit; reads are sent as a single command and need to be stored
+ if (!mf->m_write) { //L2 Cache Read
+ if ( L2tocbqueue->full() ) {
+ L2cache->access--;
} else {
mf->type = REPLY_DATA;
- dq_push(p_L2c->L2tocbqueue, mf);
+ L2tocbqueue->push(mf,gpu_sim_cycle);
// at this point, should first check if earlier L2 miss is ready to be serviced
// if so, service earlier L2 miss first
- p_L2c->L2request = NULL; //finished servicing
- L2_read_hit++;
- memlatstat_icnt2sh_push(mf);
- if (mf->mshr) mshr_update_status(mf->mshr, IN_L2TOCBQUEUE_HIT);
+ L2request = NULL; //finished servicing
+ m_stats->L2_read_hit++;
+ m_stats->memlatstat_icnt2sh_push(mf);
+ if (mf->mshr) mf->mshr->set_status(IN_L2TOCBQUEUE_HIT);
}
} else { //L2 Cache Write aka servicing L1 Writeback
- p_L2c->L2request = NULL;
- L2_write_hit++;
+ L2request = NULL;
+ m_stats->L2_write_hit++;
freed_L1write_mfs++;
free(mf); //writeback from L1 successful
gpgpu_n_processed_writes++;
}
} else {
// L2 Cache Miss; issue commands accordingly
- if ( dq_full(p_L2c->L2todramqueue) ) {
- p_L2c->L2cache->miss--;
- p_L2c->L2cache->access--;
+ if ( L2todramqueue->full() ) {
+ L2cache->miss--;
+ L2cache->access--;
} else {
// if a miss hit the mshr, that means there is another inflight request for the same data
// this miss just need to access the cache later when this request is serviced
- bool mshr_hit = p_L2c->m_mshr->new_miss(mf);
+ bool mshr_hit = m_mshr->new_miss(mf);
if (not mshr_hit) {
- if (!mf->write) {
- dq_push(p_L2c->L2todramqueue, mf);
+ if (!mf->m_write) {
+ L2todramqueue->push(mf,gpu_sim_cycle);
} else {
// if request is writeback from L1 and misses,
// then redirect mf writes to dram (no write allocate)
mf->nbytes_L2 = mf->nbytes_L1 - READ_PACKET_SIZE;
- dq_push(p_L2c->L2todramqueue, mf);
+ L2todramqueue->push(mf,gpu_sim_cycle);
}
}
- if (mf->mshr) mshr_update_status(mf->mshr, IN_L2TODRAMQUEUE);
- p_L2c->L2request = NULL;
+ if (mf->mshr) mf->mshr->set_status(IN_L2TODRAMQUEUE);
+ L2request = NULL;
}
}
}
@@ -564,188 +473,135 @@ void L2c_service_mem_req ( dram_t* dram_p, int dm_id )
}
// service memory request in L2todramqueue, pushing to dram
-void L2c_push_miss_to_dram ( dram_t* dram_p )
+void memory_partition_unit::L2c_push_miss_to_dram()
{
- assert(dram_p->m_L2cache != NULL);
- L2cacheblk *p_L2c = reinterpret_cast<L2cacheblk*>(dram_p->m_L2cache);
-
- mem_fetch_t* mf;
+ if ( m_config->gpgpu_dram_sched_queue_size && m_dram->full() )
+ return;
- if ( gpgpu_dram_sched_queue_size && dram_full(dram_p) ) return;
-
- mf = (mem_fetch_t*) dq_pop(p_L2c->L2todram_wbqueue); //prioritize writeback
- if (!mf) mf = (mem_fetch_t*) dq_pop(p_L2c->L2todramqueue);
+ mem_fetch* mf = L2todram_wbqueue->pop(gpu_sim_cycle); //prioritize writeback
+ if (!mf) mf = L2todramqueue->pop(gpu_sim_cycle);
if (mf) {
- if (mf->write) {
- L2_write_miss++;
+ if (mf->m_write) {
+ m_stats->L2_write_miss++;
} else {
- L2_read_miss++;
+ m_stats->L2_read_miss++;
}
- p_L2c->m_missTracker->new_miss(mf);
- memlatstat_dram_access(mf, dram_p->id, mf->tlx.bk);
- dram_push(dram_p,
- mf->tlx.bk, mf->tlx.row, mf->tlx.col,
- mf->nbytes_L2, mf->write,
- mf->wid, mf->sid, mf->cache_hits_waiting, mf->addr, mf);
- if (mf->mshr) mshr_update_status(mf->mshr, IN_DRAM_REQ_QUEUE);
+ m_missTracker->new_miss(mf);
+ m_dram->push(mf);
+ if (mf->mshr) mf->mshr->set_status(IN_DRAM_REQ_QUEUE);
}
}
-//Service writes that are finished in Dram
-//only updates the stats and frees the mf
-void dramtoL2_service_write(mem_fetch_t * mf) {
- freed_L2write_mfs++;
- free(mf);
- gpgpu_n_processed_writes++;
-}
-
// pop completed memory request from dram and push it to dram-to-L2 queue
-void L2c_get_dram_output ( dram_t* dram_p )
+void memory_partition_unit::L2c_get_dram_output ()
{
- assert(dram_p->m_L2cache != NULL);
- L2cacheblk *p_L2c = reinterpret_cast<L2cacheblk*>(dram_p->m_L2cache);
-
- mem_fetch_t* mf;
- mem_fetch_t* mf_top;
- if ( dq_full(p_L2c->dramtoL2queue) || dq_full(p_L2c->dramtoL2writequeue) ) return;
- mf_top = (mem_fetch_t*) dram_top(dram_p); //test
- mf = (mem_fetch_t*) dram_pop(dram_p);
+ mem_fetch* mf;
+ mem_fetch* mf_top;
+ if ( dramtoL2queue->full() || dramtoL2writequeue->full() ) return;
+ mf_top = m_dram->top();
+ mf = m_dram->pop();
assert (mf_top==mf );
if (mf) {
- if (gpgpu_l2_readoverwrite && mf->write)
- dq_push(p_L2c->dramtoL2writequeue, mf);
+ if (m_config->gpgpu_l2_readoverwrite && mf->m_write)
+ dramtoL2writequeue->push(mf,gpu_sim_cycle);
else
- dq_push(p_L2c->dramtoL2queue, mf);
- if (mf->mshr) mshr_update_status(mf->mshr, IN_DRAMTOL2QUEUE);
+ dramtoL2queue->push(mf,gpu_sim_cycle);
+ if (mf->mshr) mf->mshr->set_status(IN_DRAMTOL2QUEUE);
}
}
// service memory request in dramtoL2queue, writing to L2 as necessary
// (may cause cache eviction and subsequent writeback)
-void L2c_process_dram_output ( dram_t* dram_p, int dm_id )
+void memory_partition_unit::L2c_process_dram_output()
{
- assert(dram_p->m_L2cache != NULL);
- L2cacheblk *p_L2c = reinterpret_cast<L2cacheblk*>(dram_p->m_L2cache);
-
- static mem_fetch_t **L2dramout = NULL;
- static unsigned long long int *wb_addr = NULL;
- if (!L2dramout) L2dramout = (mem_fetch_t**)calloc(gpu_n_mem, sizeof(mem_fetch_t*));
- if (!wb_addr) {
- wb_addr = (unsigned long long int*)calloc(gpu_n_mem, sizeof(unsigned long long int));
- for (unsigned i = 0; i < gpu_n_mem; i++) wb_addr[i] = -1;
- }
-
- if (L2dramout[dm_id] == NULL) {
+ if (L2dramout == NULL) {
// pop from mshr chain if it is not empty, otherwise, pop a new cacheline from dram output queue
- if (p_L2c->m_mshr->mshr_chain_empty() == false) {
- L2dramout[dm_id] = p_L2c->m_mshr->mshr_chain_top();
- p_L2c->m_mshr->mshr_chain_pop();
+ if (m_mshr->mshr_chain_empty() == false) {
+ L2dramout = m_mshr->mshr_chain_top();
+ m_mshr->mshr_chain_pop();
} else {
- L2dramout[dm_id] = (mem_fetch_t*) dq_pop(p_L2c->dramtoL2queue);
- if (!L2dramout[dm_id]) L2dramout[dm_id] = (mem_fetch_t*) dq_pop(p_L2c->dramtoL2writequeue);
+ L2dramout = dramtoL2queue->pop(gpu_sim_cycle);
+ if (!L2dramout) L2dramout = dramtoL2writequeue->pop(gpu_sim_cycle);
- if (L2dramout[dm_id] != NULL) {
- p_L2c->m_mshr->miss_serviced(L2dramout[dm_id]);
+ if (L2dramout != NULL) {
+ m_mshr->miss_serviced(L2dramout);
- if (p_L2c->m_mshr->mshr_chain_empty() == false) { // possible if this is a L2 writeback
- L2dramout[dm_id] = p_L2c->m_mshr->mshr_chain_top();
- p_L2c->m_mshr->mshr_chain_pop();
+ if (m_mshr->mshr_chain_empty() == false) { // possible if this is a L2 writeback
+ L2dramout = m_mshr->mshr_chain_top();
+ m_mshr->mshr_chain_pop();
}
}
}
}
- mem_fetch_t* mf = L2dramout[dm_id];
+ mem_fetch* mf = L2dramout;
if (mf) {
- if (!mf->write) { //service L2 read miss
+ if (!mf->m_write) { //service L2 read miss
// it is a pre-fill dramout mf
- if (wb_addr[dm_id] == (unsigned long long int)-1) {
- if ( dq_full(p_L2c->L2tocbqueue) ) goto RETURN;
+ if (wb_addr == (unsigned long long int)-1) {
+ if ( L2tocbqueue->full() ) goto RETURN;
- if (mf->mshr) mshr_update_status(mf->mshr, IN_L2TOCBQUEUE_MISS);
+ if (mf->mshr) mf->mshr->set_status(IN_L2TOCBQUEUE_MISS);
//only transfer across icnt once the whole line has been received by L2 cache
mf->type = REPLY_DATA;
- dq_push(p_L2c->L2tocbqueue, mf);
+ L2tocbqueue->push(mf,gpu_sim_cycle);
- assert(mf->sid <= (int)gpu_n_shader);
- shd_cache_line_t *fetch_line_exist = shd_cache_probe(p_L2c->L2cache, mf->addr);
+ shd_cache_line_t *fetch_line_exist = shd_cache_probe(L2cache, mf->addr);
if (fetch_line_exist == NULL) {
- wb_addr[dm_id] = L2_shd_cache_fill(p_L2c->L2cache, mf->addr, gpu_sim_cycle );
+ wb_addr = L2_shd_cache_fill(L2cache, mf->addr, gpu_sim_cycle );
}
}
// only perform a write on cache eviction (write-back policy)
// it is the 1st or nth time trial to writeback
- if (wb_addr[dm_id] != (unsigned long long int)-1) {
+ if (wb_addr != (unsigned long long int)-1) {
// performing L2 writeback (no false sharing for memory-side cache)
- int wb_succeed = L2c_write_back(wb_addr[dm_id], p_L2c->L2cache->line_sz, dm_id );
+ int wb_succeed = L2c_write_back(wb_addr, L2cache->line_sz);
if (!wb_succeed) goto RETURN; //try again next cycle
}
- p_L2c->m_missTracker->miss_serviced(mf);
- L2dramout[dm_id] = NULL;
- wb_addr[dm_id] = -1;
+ m_missTracker->miss_serviced(mf);
+ L2dramout = NULL;
+ wb_addr = -1;
} else { //service L2 write miss
- p_L2c->m_missTracker->miss_serviced(mf);
- dramtoL2_service_write(mf);
- L2dramout[dm_id] = NULL;
- wb_addr[dm_id] = -1;
+ m_missTracker->miss_serviced(mf);
+ freed_L2write_mfs++;
+ free(mf);
+ gpgpu_n_processed_writes++;
+ L2dramout = NULL;
+ wb_addr = -1;
}
}
RETURN:
- assert (L2dramout[dm_id] || wb_addr[dm_id] == (unsigned long long int)-1);
+ assert (L2dramout || wb_addr == (unsigned long long int)-1);
}
// Writeback from L2 to DRAM:
// - Takes in memory address and their parameters and pushes to dram request queue
// - This is used only for L2 writeback
-unsigned char L2c_write_back(unsigned long long int addr, int bsize, int dram_id )
+bool memory_partition_unit::L2c_write_back( unsigned long long int addr, int bsize )
{
- addrdec_t tlx;
- addrdec_tlx(addr,&tlx);
-
- assert(dram[dram_id]->m_L2cache != NULL);
- L2cacheblk *p_L2c = reinterpret_cast<L2cacheblk*>(dram[dram_id]->m_L2cache);
-
- if ( dq_full(p_L2c->L2todram_wbqueue) ) return 0;
-
- mem_fetch_t *mf;
-
- mf = (mem_fetch_t*) malloc(sizeof(mem_fetch_t));
+ if ( L2todram_wbqueue->full() )
+ return false;
+ mem_fetch *mf = new mem_fetch(addr,
+ bsize+READ_PACKET_SIZE/*l1*/,
+ bsize/*l2*/,
+ 0/*sid*/,0/*tpc*/,0/*wid*/,0/*cache_hits_waiting*/,NULL,true,
+ partial_write_mask_t(),
+ L2_WRBK_ACC,
+ L2_WTBK_DATA,
+ -1/*pc*/);
+ m_stats->memlatstat_start(mf);
made_write_mfs++;
- mf->request_uid = g_next_mf_request_uid++;
- mf->addr = addr;
- mf->nbytes_L1 = bsize + READ_PACKET_SIZE;
- mf->txbytes_L1 = 0;
- mf->rxbytes_L1 = 0;
- mf->nbytes_L2 = bsize;
- mf->sid = gpu_n_shader; // (gpu_n_shader+1);
- mf->wid = 0;
- mf->txbytes_L2 = 0;
- mf->rxbytes_L2 = 0;
- mf->mshr = NULL;
- mf->pc = -1; // disable ptx_file_line_stats
- mf->write = 1; // it is writeback
- mf->mem_acc = L2_WRBK_ACC;
- memlatstat_start(mf);
- mf->tlx = tlx;
- mf->bank = mf->tlx.bk;
- mf->chip = mf->tlx.chip;
-
-
- //writeback
- mf->type = L2_WTBK_DATA;
- if (!dq_push(p_L2c->L2todram_wbqueue, mf)) assert(0);
+ L2todram_wbqueue->push(mf,gpu_sim_cycle);
gpgpu_n_sent_writes++;
- return 1;
+ return true;
}
-unsigned int L2c_cache_flush ( dram_t* dram_p) {
- assert(dram_p->m_L2cache != NULL);
- L2cacheblk *p_L2c = reinterpret_cast<L2cacheblk*>(dram_p->m_L2cache);
-
- shd_cache_t *cp = p_L2c->L2cache;
+unsigned int memory_partition_unit::L2c_cache_flush()
+{
+ shd_cache_t *cp = L2cache;
int dirty_lines_flushed = 0 ;
for (unsigned i = 0; i < cp->nset * cp->assoc ; i++) {
if ( (cp->lines[i].status & (DIRTY|VALID)) == (DIRTY|VALID) ) {
@@ -757,158 +613,141 @@ unsigned int L2c_cache_flush ( dram_t* dram_p) {
return dirty_lines_flushed;
}
-void L2c_init_stat()
+void memory_partition_unit::L2c_print_cache_stat(unsigned &accesses, unsigned &misses) const
{
- L2_cbtoL2length = (unsigned int*) calloc(gpu_n_mem, sizeof(unsigned int));
- L2_cbtoL2writelength = (unsigned int*) calloc(gpu_n_mem, sizeof(unsigned int));
- L2_L2tocblength = (unsigned int*) calloc(gpu_n_mem, sizeof(unsigned int));
- L2_dramtoL2length = (unsigned int*) calloc(gpu_n_mem, sizeof(unsigned int));
- L2_dramtoL2writelength = (unsigned int*) calloc(gpu_n_mem, sizeof(unsigned int));
- L2_L2todramlength = (unsigned int*) calloc(gpu_n_mem, sizeof(unsigned int));
+ FILE *fp = stdout;
+ shd_cache_print(L2cache,fp,accesses,misses);
+ m_mshr->print_stat(fp);
+ m_missTracker->print_stat(fp);
+ m_accessLocality->print_stat(fp, false);
}
-void L2c_update_stat( dram_t* dram_p)
+void memory_partition_unit::L2c_update_stat()
{
- assert(dram_p->m_L2cache != NULL);
- L2cacheblk *p_L2c = reinterpret_cast<L2cacheblk*>(dram_p->m_L2cache);
-
- int i = dram_p->id;
-
- if (p_L2c->cbtoL2queue->length > L2_cbtoL2length[i])
- L2_cbtoL2length[i] = p_L2c->cbtoL2queue->length;
- if (p_L2c->cbtoL2writequeue->length > L2_cbtoL2writelength[i])
- L2_cbtoL2writelength[i] = p_L2c->cbtoL2writequeue->length;
- if (p_L2c->L2tocbqueue->length > L2_L2tocblength[i])
- L2_L2tocblength[i] = p_L2c->L2tocbqueue->length;
- if (p_L2c->dramtoL2queue->length > L2_dramtoL2length[i])
- L2_dramtoL2length[i] = p_L2c->dramtoL2queue->length;
- if (p_L2c->dramtoL2writequeue->length > L2_dramtoL2writelength[i])
- L2_dramtoL2writelength[i] = p_L2c->dramtoL2writequeue->length;
- if (p_L2c->L2todramqueue->length > L2_L2todramlength[i])
- L2_L2todramlength[i] = p_L2c->L2todramqueue->length;
+ unsigned i=m_id;
+ if (cbtoL2queue->get_length() > m_stats->L2_cbtoL2length[i])
+ m_stats->L2_cbtoL2length[i] = cbtoL2queue->get_length();
+ if (cbtoL2writequeue->get_length() > m_stats->L2_cbtoL2writelength[i])
+ m_stats->L2_cbtoL2writelength[i] = cbtoL2writequeue->get_length();
+ if (L2tocbqueue->get_length() > m_stats->L2_L2tocblength[i])
+ m_stats->L2_L2tocblength[i] = L2tocbqueue->get_length();
+ if (dramtoL2queue->get_length() > m_stats->L2_dramtoL2length[i])
+ m_stats->L2_dramtoL2length[i] = dramtoL2queue->get_length();
+ if (dramtoL2writequeue->get_length() > m_stats->L2_dramtoL2writelength[i])
+ m_stats->L2_dramtoL2writelength[i] = dramtoL2writequeue->get_length();
+ if (L2todramqueue->get_length() > m_stats->L2_L2todramlength[i])
+ m_stats->L2_L2todramlength[i] = L2todramqueue->get_length();
}
-void L2c_print_stat( )
+void memory_stats_t::L2c_print_stat( unsigned n_mem )
{
unsigned i;
printf(" ");
- for (i=0;i<gpu_n_mem;i++) {
+ for (i=0;i<n_mem;i++) {
printf(" dram[%d]", i);
}
printf("\n");
printf("cbtoL2 queue maximum length =");
- for (i=0;i<gpu_n_mem;i++) {
+ for (i=0;i<n_mem;i++) {
printf("%8d", L2_cbtoL2length[i]);
}
printf("\n");
printf("cbtoL2 write queue maximum length =");
- for (i=0;i<gpu_n_mem;i++) {
+ for (i=0;i<n_mem;i++) {
printf("%8d", L2_cbtoL2writelength[i]);
}
printf("\n");
printf("L2tocb queue maximum length =");
- for (i=0;i<gpu_n_mem;i++) {
+ for (i=0;i<n_mem;i++) {
printf("%8d", L2_L2tocblength[i]);
}
printf("\n");
printf("dramtoL2 queue maximum length =");
- for (i=0;i<gpu_n_mem;i++) {
+ for (i=0;i<n_mem;i++) {
printf("%8d", L2_dramtoL2length[i]);
}
printf("\n");
printf("dramtoL2 write queue maximum length =");
- for (i=0;i<gpu_n_mem;i++) {
+ for (i=0;i<n_mem;i++) {
printf("%8d", L2_dramtoL2writelength[i]);
}
printf("\n");
printf("L2todram queue maximum length =");
- for (i=0;i<gpu_n_mem;i++) {
+ for (i=0;i<n_mem;i++) {
printf("%8d", L2_L2todramlength[i]);
}
printf("\n");
}
-void L2c_print_cache_stat()
+void memory_stats_t::print( FILE *fp )
{
- unsigned i;
- int j, k;
- for (i=0,j=0,k=0;i<gpu_n_mem;i++) {
- assert(dram[i]->m_L2cache != NULL);
- L2cacheblk *p_L2c = reinterpret_cast<L2cacheblk*>(dram[i]->m_L2cache);
+ fprintf(fp,"L2_write_miss = %d\n", L2_write_miss);
+ fprintf(fp,"L2_write_hit = %d\n", L2_write_hit);
+ fprintf(fp,"L2_read_miss = %d\n", L2_read_miss);
+ fprintf(fp,"L2_read_hit = %d\n", L2_read_hit);
+}
- shd_cache_print(p_L2c->L2cache,stdout);
- j += p_L2c->L2cache->miss;
- k += p_L2c->L2cache->access;
- p_L2c->m_mshr->print_stat(stdout);
- p_L2c->m_missTracker->print_stat(stdout);
- p_L2c->m_accessLocality->print_stat(stdout, false);
- }
+void gpgpu_sim::L2c_print_cache_stat() const
+{
+ unsigned i, j, k;
+ for (i=0,j=0,k=0;i<m_n_mem;i++)
+ m_memory_partition_unit[i]->L2c_print_cache_stat(k,j);
printf("L2 Cache Total Miss Rate = %0.3f\n", (float)j/k);
}
-void L2c_print_debug( )
+void gpgpu_sim::L2c_print_debug()
{
unsigned i;
printf(" ");
- for (i=0;i<gpu_n_mem;i++) {
+ for (i=0;i<m_n_mem;i++)
printf(" dram[%d]", i);
- }
printf("\n");
printf("cbtoL2 queue length =");
- for (i=0;i<gpu_n_mem;i++) {
- L2cacheblk *p_L2c = reinterpret_cast<L2cacheblk*>(dram[i]->m_L2cache);
- printf("%8d", p_L2c->cbtoL2queue->length);
- }
+ for (i=0;i<m_n_mem;i++)
+ printf("%8d", m_memory_partition_unit[i]->get_cbtoL2queue_length() );
printf("\n");
printf("cbtoL2 write queue length =");
- for (i=0;i<gpu_n_mem;i++) {
- L2cacheblk *p_L2c = reinterpret_cast<L2cacheblk*>(dram[i]->m_L2cache);
- printf("%8d", p_L2c->cbtoL2writequeue->length);
- }
+ for (i=0;i<m_n_mem;i++)
+ printf("%8d", m_memory_partition_unit[i]->get_cbtoL2writequeue_length());
printf("\n");
printf("L2tocb queue length =");
- for (i=0;i<gpu_n_mem;i++) {
- L2cacheblk *p_L2c = reinterpret_cast<L2cacheblk*>(dram[i]->m_L2cache);
- printf("%8d", p_L2c->L2tocbqueue->length);
+ for (i=0;i<m_n_mem;i++) {
+ printf("%8d", m_memory_partition_unit[i]->get_L2tocbqueue_length());
}
printf("\n");
printf("dramtoL2 queue length =");
- for (i=0;i<gpu_n_mem;i++) {
- L2cacheblk *p_L2c = reinterpret_cast<L2cacheblk*>(dram[i]->m_L2cache);
- printf("%8d", p_L2c->dramtoL2queue->length);
+ for (i=0;i<m_n_mem;i++) {
+ printf("%8d", m_memory_partition_unit[i]->get_dramtoL2queue_length());
}
printf("\n");
printf("dramtoL2 write queue length =");
- for (i=0;i<gpu_n_mem;i++) {
- L2cacheblk *p_L2c = reinterpret_cast<L2cacheblk*>(dram[i]->m_L2cache);
- printf("%8d", p_L2c->dramtoL2writequeue->length);
+ for (i=0;i<m_n_mem;i++) {
+ printf("%8d", m_memory_partition_unit[i]->get_dramtoL2writequeue_length());
}
printf("\n");
printf("L2todram queue length =");
- for (i=0;i<gpu_n_mem;i++) {
- L2cacheblk *p_L2c = reinterpret_cast<L2cacheblk*>(dram[i]->m_L2cache);
- printf("%8d", p_L2c->L2todramqueue->length);
+ for (i=0;i<m_n_mem;i++) {
+ printf("%8d", m_memory_partition_unit[i]->get_L2todramqueue_length());
}
printf("\n");
printf("L2todram writeback queue length =");
- for (i=0;i<gpu_n_mem;i++) {
- L2cacheblk *p_L2c = reinterpret_cast<L2cacheblk*>(dram[i]->m_L2cache);
- printf("%8d", p_L2c->L2todram_wbqueue->length);
+ for (i=0;i<m_n_mem;i++) {
+ printf("%8d", m_memory_partition_unit[i]->get_L2todram_wbqueue_length());
}
printf("\n");
}
@@ -917,78 +756,55 @@ void L2c_print_debug( )
#define SAMPLELOG 222
#define DUMPLOG 333
-void L2c_log(int task)
+void memory_partition_unit::L2c_log(int task)
{
- unsigned i;
- static void ** cbtol2_Dist ;
- static void ** cbtoL2wr_Dist ;
- static void ** L2tocb_Dist ;
- static void ** dramtoL2_Dist ;
- static void ** dramtoL2wr_Dist ;
- static void ** L2todram_Dist ;
- static void ** L2todram_wb_Dist ;
- if (task == CREATELOG) {
- cbtol2_Dist = (void **) calloc(gpu_n_mem,sizeof(void*));
- cbtoL2wr_Dist = (void **) calloc(gpu_n_mem,sizeof(void*));
- L2tocb_Dist = (void **) calloc(gpu_n_mem,sizeof(void*));
- dramtoL2_Dist = (void **)calloc(gpu_n_mem,sizeof(void*));
- dramtoL2wr_Dist = (void **)calloc(gpu_n_mem,sizeof(void*));
- L2todram_Dist = (void **)calloc(gpu_n_mem,sizeof(void*));
- L2todram_wb_Dist = (void **)calloc(gpu_n_mem,sizeof(void*));
-
- for (i=0;i<gpu_n_mem;i++) {
- assert(dram[i]->m_L2cache != NULL);
- L2cacheblk *p_L2c = reinterpret_cast<L2cacheblk*>(dram[i]->m_L2cache);
-
- cbtol2_Dist[i] = StatCreate("cbtoL2",1,p_L2c->cbtoL2queue->max_len);
- cbtoL2wr_Dist[i] = StatCreate("cbtoL2write",1,p_L2c->cbtoL2writequeue->max_len);
- L2tocb_Dist[i] = StatCreate("L2tocb",1,p_L2c->L2tocbqueue->max_len);
- dramtoL2_Dist[i] = StatCreate("dramtoL2",1,p_L2c->dramtoL2queue->max_len);
- dramtoL2wr_Dist[i] = StatCreate("dramtoL2write",1,p_L2c->dramtoL2writequeue->max_len);
- L2todram_Dist[i] = StatCreate("L2todram",1,p_L2c->L2todramqueue->max_len);
- L2todram_wb_Dist[i] = StatCreate("L2todram_wb",1,p_L2c->L2todram_wbqueue->max_len);
- }
- } else if (task == SAMPLELOG) {
- for (i=0;i<gpu_n_mem;i++) {
- assert(dram[i]->m_L2cache != NULL);
- L2cacheblk *p_L2c = reinterpret_cast<L2cacheblk*>(dram[i]->m_L2cache);
-
- StatAddSample(cbtol2_Dist[i], p_L2c->cbtoL2queue->length);
- StatAddSample(cbtoL2wr_Dist[i], p_L2c->cbtoL2writequeue->length);
- StatAddSample(L2tocb_Dist[i], p_L2c->L2tocbqueue->length);
- StatAddSample(dramtoL2_Dist[i], p_L2c->dramtoL2queue->length);
- StatAddSample(dramtoL2wr_Dist[i], p_L2c->dramtoL2writequeue->length);
- StatAddSample(L2todram_Dist[i], p_L2c->L2todramqueue->length);
- StatAddSample(L2todram_wb_Dist[i], p_L2c->L2todram_wbqueue->length);
- }
+ if (task == SAMPLELOG) {
+ StatAddSample(cbtol2_Dist, cbtoL2queue->get_length());
+ StatAddSample(cbtoL2wr_Dist, cbtoL2writequeue->get_length());
+ StatAddSample(L2tocb_Dist, L2tocbqueue->get_length());
+ StatAddSample(dramtoL2_Dist, dramtoL2queue->get_length());
+ StatAddSample(dramtoL2wr_Dist, dramtoL2writequeue->get_length());
+ StatAddSample(L2todram_Dist, L2todramqueue->get_length());
+ StatAddSample(L2todram_wb_Dist, L2todram_wbqueue->get_length());
} else if (task == DUMPLOG) {
- for (i=0;i<gpu_n_mem;i++) {
- printf ("Queue Length DRAM[%d] ",i); StatDisp(cbtol2_Dist[i]);
- printf ("Queue Length DRAM[%d] ",i); StatDisp(cbtoL2wr_Dist[i]);
- printf ("Queue Length DRAM[%d] ",i); StatDisp(L2tocb_Dist[i]);
- printf ("Queue Length DRAM[%d] ",i); StatDisp(dramtoL2_Dist[i]);
- printf ("Queue Length DRAM[%d] ",i); StatDisp(dramtoL2wr_Dist[i]);
- printf ("Queue Length DRAM[%d] ",i); StatDisp(L2todram_Dist[i]);
- printf ("Queue Length DRAM[%d] ",i); StatDisp(L2todram_wb_Dist[i]);
- }
+ printf ("Queue Length DRAM[%d] ",m_id); StatDisp(cbtol2_Dist);
+ printf ("Queue Length DRAM[%d] ",m_id); StatDisp(cbtoL2wr_Dist);
+ printf ("Queue Length DRAM[%d] ",m_id); StatDisp(L2tocb_Dist);
+ printf ("Queue Length DRAM[%d] ",m_id); StatDisp(dramtoL2_Dist);
+ printf ("Queue Length DRAM[%d] ",m_id); StatDisp(dramtoL2wr_Dist);
+ printf ("Queue Length DRAM[%d] ",m_id); StatDisp(L2todram_Dist);
+ printf ("Queue Length DRAM[%d] ",m_id); StatDisp(L2todram_wb_Dist);
}
}
-void L2c_latency_log_dump()
+void gpgpu_sim::L2c_latency_log_dump()
{
- unsigned i;
- for (i=0;i<gpu_n_mem;i++) {
- assert(dram[i]->m_L2cache != NULL);
- L2cacheblk *p_L2c = reinterpret_cast<L2cacheblk*>(dram[i]->m_L2cache);
+ for (unsigned i=0;i<m_n_mem;i++)
+ m_memory_partition_unit[i]->L2c_latency_log_dump();
+}
- printf ("(LOGB2)Latency DRAM[%d] ",i); StatDisp(p_L2c->cbtoL2queue->lat_stat);
- printf ("(LOGB2)Latency DRAM[%d] ",i); StatDisp(p_L2c->cbtoL2writequeue->lat_stat);
- printf ("(LOGB2)Latency DRAM[%d] ",i); StatDisp(p_L2c->L2tocbqueue->lat_stat);
- printf ("(LOGB2)Latency DRAM[%d] ",i); StatDisp(p_L2c->dramtoL2queue->lat_stat);
- printf ("(LOGB2)Latency DRAM[%d] ",i); StatDisp(p_L2c->dramtoL2writequeue->lat_stat);
- printf ("(LOGB2)Latency DRAM[%d] ",i); StatDisp(p_L2c->L2todramqueue->lat_stat);
- printf ("(LOGB2)Latency DRAM[%d] ",i); StatDisp(p_L2c->L2todram_wbqueue->lat_stat);
- }
+void memory_partition_unit::L2c_latency_log_dump()
+{
+ printf ("(LOGB2)Latency DRAM[%u] ",m_id); StatDisp(cbtoL2queue->get_lat_stat());
+ printf ("(LOGB2)Latency DRAM[%u] ",m_id); StatDisp(cbtoL2writequeue->get_lat_stat());
+ printf ("(LOGB2)Latency DRAM[%u] ",m_id); StatDisp(L2tocbqueue->get_lat_stat());
+ printf ("(LOGB2)Latency DRAM[%u] ",m_id); StatDisp(dramtoL2queue->get_lat_stat());
+ printf ("(LOGB2)Latency DRAM[%u] ",m_id); StatDisp(dramtoL2writequeue->get_lat_stat());
+ printf ("(LOGB2)Latency DRAM[%u] ",m_id); StatDisp(L2todramqueue->get_lat_stat());
+ printf ("(LOGB2)Latency DRAM[%u] ",m_id); StatDisp(L2todram_wbqueue->get_lat_stat());
+}
+
+bool memory_partition_unit::busy() const
+{
+ return !m_request_tracker.empty();
}
+void memory_partition_unit::request_tracker_insert(class mem_fetch *mf)
+{
+ m_request_tracker.insert(mf);
+}
+void memory_partition_unit::request_tracker_erase(class mem_fetch *mf)
+{
+ m_request_tracker.erase(mf);
+}