summaryrefslogtreecommitdiff
path: root/src/gpgpu-sim/l2cache.cc
diff options
context:
space:
mode:
authorTor Aamodt <[email protected]>2010-10-18 02:43:17 -0800
committerTor Aamodt <[email protected]>2010-10-18 02:43:17 -0800
commit87e4da5fc6086c3d0a661af1929255a8cbd728d7 (patch)
treea4f40e66f5ca0d6efdf9d51672a1180c8a381170 /src/gpgpu-sim/l2cache.cc
parentb577cbcdf229a2c02d1bf8584c6e82be7a14cb33 (diff)
Re-designed cache model:
- read only cache model with integrated mshrs (no L1D, yet); new cache interface should be easily extendable to support texture cache with latency fifo and separate tag/data arrays, though this is not yet added (currently tags and data arrays are not decoupled for texture) - new partition model using the above removes all old MSHRs, L1D etc... passing CUDA 3.1 regression [git-p4: depot-paths = "//depot/gpgpu_sim_research/fermi/distribution/": change = 7875]
Diffstat (limited to 'src/gpgpu-sim/l2cache.cc')
-rw-r--r--src/gpgpu-sim/l2cache.cc744
1 files changed, 153 insertions, 591 deletions
diff --git a/src/gpgpu-sim/l2cache.cc b/src/gpgpu-sim/l2cache.cc
index d2b61d7..634fa55 100644
--- a/src/gpgpu-sim/l2cache.cc
+++ b/src/gpgpu-sim/l2cache.cc
@@ -83,649 +83,211 @@
#include "shader.h"
#include "mem_latency_stat.h"
-template class fifo_pipeline<mem_fetch>;
-
-address_type L2c_mshr::cache_tag(const mem_fetch *mf) const
-{
- return (mf->get_addr() & ~(m_linesize - 1));
-}
-
-address_type L2c_miss_tracker::cache_tag(const mem_fetch *mf) const
-{
- return (mf->get_addr() & ~(m_linesize - 1));
-}
-
-address_type L2c_access_locality::cache_tag(const mem_fetch *mf) const
-{
- return (mf->get_addr() & ~(m_linesize - 1));
-}
-
void gpgpu_sim::L2c_options(option_parser_t opp)
{
- 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_dram_partition_queues", OPT_CSTR, &m_memory_config->gpgpu_L2_queue_config,
+ "i2$:$2d:d2$:$2i",
+ "8:8:8:8");
- 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, &m_memory_config->l2_ideal,
- "Use a ideal L2 cache that always hit",
- "0");
+ option_parser_register(opp, "-l2_ideal", OPT_BOOL, &m_memory_config->l2_ideal,
+ "Use a ideal L2 cache that always hit",
+ "0");
}
+//////////
-////////////////////////////////////////////////
-// L2 MSHR model
-
-bool L2c_mshr::new_miss(const mem_fetch *mf)
-{
- address_type cacheTag = cache_tag(mf);
- mem_fetch_list &missGroup = m_L2missgroup[cacheTag];
-
- bool mshr_hit = not missGroup.empty();
-
- missGroup.push_front(mf);
-
- m_n_miss += 1;
- if (mshr_hit)
- m_n_mshr_hits += 1;
- m_entries_used += 1;
- m_max_entries_used = std::max(m_max_entries_used, m_entries_used);
-
- return mshr_hit;
-}
-
-void L2c_mshr::miss_serviced(const mem_fetch *mf)
-{
- assert(m_active_mshr_chain.list == NULL);
- address_type cacheTag = cache_tag(mf);
- L2missGroup::iterator missGroup = m_L2missgroup.find(cacheTag);
- if (missGroup == m_L2missgroup.end() || mf->get_type() == L2_WTBK_DATA) {
- assert(mf->get_type() == L2_WTBK_DATA); // only this returning mem req can be missed by the MSHR
- return;
- }
- assert(missGroup->first == cacheTag);
-
- m_active_mshr_chain.cacheTag = cacheTag;
- m_active_mshr_chain.list = &(missGroup->second);
-
- m_n_miss_serviced_by_dram += 1;
-}
-
-bool L2c_mshr::mshr_chain_empty()
-{
- return (m_active_mshr_chain.list == NULL);
-}
-
-mem_fetch *L2c_mshr::mshr_chain_top()
-{
- const mem_fetch *mf = m_active_mshr_chain.list->back();
- assert(cache_tag(mf) == m_active_mshr_chain.cacheTag);
-
- return const_cast<mem_fetch*>(mf);
-}
-
-void L2c_mshr::mshr_chain_pop()
-{
- m_entries_used -= 1;
- m_active_mshr_chain.list->pop_back();
- if (m_active_mshr_chain.list->empty()) {
- address_type cacheTag = m_active_mshr_chain.cacheTag;
- m_L2missgroup.erase(cacheTag);
- m_active_mshr_chain.list = NULL;
- }
-}
-
-void L2c_mshr::print(FILE *fout)
-{
- fprintf(fout, "L2c MSHR: n_entries_used = %zu\n", m_entries_used);
- L2missGroup::iterator missGroup;
- for (missGroup = m_L2missgroup.begin(); missGroup != m_L2missgroup.end(); ++missGroup) {
- fprintf(fout, "%#08x: ", missGroup->first);
- mem_fetch_list &mf_list = missGroup->second;
- for (mem_fetch_list::iterator imf = mf_list.begin(); imf != mf_list.end(); ++imf)
- (*imf)->print(fout);
- fprintf(fout, "\n");
- }
-}
-
-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);
-}
-
-////////////////////////////////////////////////
-// track redundant dram access generated by L2 cache
-
-void L2c_miss_tracker::new_miss(mem_fetch *mf)
-{
- address_type cacheTag = cache_tag(mf);
- mem_fetch_set &missGroup = m_L2missgroup[cacheTag];
-
- if (missGroup.size() != 0) {
- m_L2redundantCnt[cacheTag] += 1;
- m_totalL2redundantAcc += 1;
- }
-
- missGroup.insert(mf);
-}
-
-void L2c_miss_tracker::miss_serviced(mem_fetch *mf)
-{
- address_type cacheTag = cache_tag(mf);
- L2missGroup::iterator iMissGroup = m_L2missgroup.find(cacheTag);
- if (iMissGroup == m_L2missgroup.end()) return; // this is possible for write miss
- mem_fetch_set &missGroup = iMissGroup->second;
-
- missGroup.erase(mf);
-
- // remove the miss group if it goes empty
- if (missGroup.empty()) {
- m_L2missgroup.erase(iMissGroup);
- }
-}
-
-void L2c_miss_tracker::print(FILE *fout, bool brief)
-{
- L2missGroup::iterator iMissGroup;
- for (iMissGroup = m_L2missgroup.begin(); iMissGroup != m_L2missgroup.end(); ++iMissGroup) {
- fprintf(fout, "%#08x: ", iMissGroup->first);
- for (mem_fetch_set::iterator iMemSet = iMissGroup->second.begin(); iMemSet != iMissGroup->second.end(); ++iMemSet) {
- fprintf(fout, "%p ", *iMemSet);
- }
- fprintf(fout, "\n");
- }
-}
-
-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::const_iterator iL2rc = m_L2redundantCnt.begin(); iL2rc != m_L2redundantCnt.end(); ++iL2rc) {
- fprintf(fout, "%#08x:%d ", iL2rc->first, iL2rc->second);
- }
- fprintf(fout, "\n");
-}
-
-////////////////////////////////////////////////
-// track all locality of L2 cache access
-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) 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::const_iterator iL2rc = m_L2accCnt.begin(); iL2rc != m_L2accCnt.end(); ++iL2rc) {
- locality_histo.add2bin(iL2rc->second);
- }
- locality_histo.fprint(fout);
- fprintf(fout, "\n");
-}
-
-memory_partition_unit::~memory_partition_unit()
-{
- delete m_mshr;
- delete m_missTracker;
- delete m_accessLocality;
-}
-
-void memory_partition_unit::cache_cycle()
-{
- 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->m_L2_config.get_num_lines()) { // L2 cache enabled
- L2c_update_stat();
- L2c_log(SAMPLELOG);
- }
-}
-
-unsigned memory_partition_unit::L2c_get_linesize()
-{
- return m_config->m_L2_config.get_line_sz();
-}
-
-bool memory_partition_unit::full() const
-{
- if (m_config->m_L2_config.get_num_lines()) {
- return m_icnt2cache_queue->full() || m_icnt2cache_write_queue->full();
- } else {
- return( m_config->gpgpu_dram_sched_queue_size && m_dram->full() );
- }
-}
-
-////////////////////////////////////////////////
-// L2 access functions
-
-// L2 Cache Creation
memory_partition_unit::memory_partition_unit( unsigned partition_id,
struct memory_config *config,
class memory_stats_t *stats )
{
- m_id = partition_id;
- m_config=config;
- m_stats=stats;
- m_dram = new dram_t(m_id,m_config,m_stats);
+ m_id = partition_id;
+ m_config=config;
+ m_stats=stats;
+ m_dram = new dram_t(m_id,m_config,m_stats);
- if( m_config->m_L2_config.get_num_lines() ) {
- char L2c_name[32];
- snprintf(L2c_name, 32, "L2_bank_%03d", m_id);
- m_L2cache = new cache_t(L2c_name,m_config->m_L2_config,-1,-1);
- unsigned l2_line_sz = m_config->m_L2_config.get_line_sz();
- m_mshr = new L2c_mshr( l2_line_sz );
- m_missTracker = new L2c_miss_tracker( l2_line_sz );
- m_accessLocality = new L2c_access_locality( l2_line_sz );
- } else {
- m_L2cache=NULL;
- m_mshr=NULL;
- m_missTracker=NULL;
- m_accessLocality=NULL;
- }
+ char L2c_name[32];
+ snprintf(L2c_name, 32, "L2_bank_%03d", m_id);
+ m_L2interface = new L2interface(this);
+ m_L2cache = new cache_t(L2c_name,m_config->m_L2_config,-1,-1,m_L2interface);
- unsigned int L2c_cb_L2_length;
- unsigned int L2c_cb_L2w_length;
- unsigned int L2c_L2_dm_length;
- unsigned int L2c_dm_L2_length;
- unsigned int L2c_dm_L2w_length;
- unsigned int L2c_L2_cb_length;
- unsigned int L2c_L2_cb_minlength;
- unsigned int L2c_L2_dm_minlength;
+ unsigned int icnt_L2;
+ unsigned int L2_dram;
+ unsigned int dram_L2;
+ unsigned int L2_icnt;
- 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>)
- m_icnt2cache_queue = new fifo_pipeline<mem_fetch>("cbtoL2queue", 0,L2c_cb_L2_length, gpu_sim_cycle);
- m_icnt2cache_write_queue = 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);
- L2dramout = NULL;
- wb_addr=-1;
- if (m_config->m_L2_config.get_num_lines() && 1) {
- cbtol2_Dist = StatCreate("cbtoL2",1, m_icnt2cache_queue->get_max_len());
- cbtoL2wr_Dist = StatCreate("cbtoL2write",1, m_icnt2cache_write_queue->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;
- }
+ 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;
}
-void memory_partition_unit::L2c_service_mem_req()
+memory_partition_unit::~memory_partition_unit()
{
- // service memory request in icnt-to-L2 queue, writing to L2 as necessary
- if( L2tocbqueue->full() || L2todramqueue->full() )
- return;
- mem_fetch* mf = m_icnt2cache_queue->pop(gpu_sim_cycle);
- if( !mf )
- mf = m_icnt2cache_write_queue->pop(gpu_sim_cycle);
- if( !mf )
- return;
- switch (mf->get_type()) {
- case RD_REQ:
- case WT_REQ: {
- address_type rep_block;
- enum cache_request_status status = MISS_NO_WB;
- if( mf->istexture() )
- status = m_L2cache->access( mf->get_partition_addr(), mf->get_is_write(), gpu_sim_cycle, &rep_block);
- if( (status==HIT) || m_config->l2_ideal ) {
- mf->set_type( REPLY_DATA );
- assert( mf != NULL );
- L2tocbqueue->push(mf,gpu_sim_cycle);
- if (!mf->get_is_write()) {
- m_stats->L2_read_hit++;
- mf->set_return_timestamp(gpu_sim_cycle+gpu_tot_sim_cycle);
- mf->set_status(IN_L2TOCBQUEUE_HIT,MR_DRAM_OUTQ,gpu_sim_cycle+gpu_tot_sim_cycle);
- } else {
- m_stats->L2_write_hit++;
- }
- } else {
- // L2 Cache Miss
- // if a miss hits in 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 = m_mshr->new_miss(mf);
- if (not mshr_hit)
- L2todramqueue->push(mf,gpu_sim_cycle);
- mf->set_status(IN_L2TODRAMQUEUE,MR_DRAM_OUTQ,gpu_sim_cycle+gpu_tot_sim_cycle);
- }
- }
- break;
- default: assert(0);
- }
+ 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;
}
-// service memory request in L2todramqueue, pushing to dram
-void memory_partition_unit::L2c_push_miss_to_dram()
+void memory_partition_unit::cache_cycle()
{
- if ( m_config->gpgpu_dram_sched_queue_size && m_dram->full() )
- return;
- mem_fetch* mf = L2todram_wbqueue->pop(gpu_sim_cycle); //prioritize writeback
- if (!mf) mf = L2todramqueue->pop(gpu_sim_cycle);
- if (mf) {
- if (mf->get_is_write())
- m_stats->L2_write_miss++;
- else
- m_stats->L2_read_miss++;
- m_missTracker->new_miss(mf);
- m_dram->push(mf);
- mf->set_status(IN_DRAM_REQ_QUEUE, MR_DRAMQ, gpu_sim_cycle+gpu_tot_sim_cycle);
- }
-}
+ // L2 fill responses
+ if ( m_L2cache->access_ready() && !m_L2_icnt_queue->full() ) {
+ mem_fetch *mf = m_L2cache->next_access();
+ mf->set_type(REPLY_DATA);
+ mf->set_status(IN_PARTITION_L2_TO_ICNT_QUEUE,gpu_sim_cycle+gpu_tot_sim_cycle);
+ m_L2_icnt_queue->push(mf);
+ }
+ // DRAM to L2 (texture) and icnt (not texture)
+ if ( !m_dram_L2_queue->empty() ) {
+ mem_fetch *mf = m_dram_L2_queue->top();
+ if ( mf->istexture() ) {
+ mf->set_status(IN_PARTITION_L2_FILL_QUEUE,gpu_sim_cycle+gpu_tot_sim_cycle);
+ m_L2cache->fill(mf,gpu_sim_cycle+gpu_tot_sim_cycle);
+ m_dram_L2_queue->pop();
+ } else if ( !m_L2_icnt_queue->full() ) {
+ mf->set_status(IN_PARTITION_L2_TO_ICNT_QUEUE,gpu_sim_cycle+gpu_tot_sim_cycle);
+ m_L2_icnt_queue->push(mf);
+ m_dram_L2_queue->pop();
+ }
+ }
-// service memory request in dramtoL2queue, writing to L2 as necessary
-// (may cause cache eviction and subsequent writeback)
-void memory_partition_unit::process_dram_output()
-{
- if (L2dramout == NULL) {
- // pop from mshr chain if it is not empty, otherwise, pop a new cacheline from dram output queue
- if (m_mshr->mshr_chain_empty() == false) {
- L2dramout = m_mshr->mshr_chain_top();
- m_mshr->mshr_chain_pop();
- } else {
- L2dramout = dramtoL2queue->pop(gpu_sim_cycle);
- if (!L2dramout)
- L2dramout = dramtoL2writequeue->pop(gpu_sim_cycle);
- if (L2dramout != NULL) {
- m_mshr->miss_serviced(L2dramout);
- 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* mf = L2dramout;
- if (mf) {
- if (!mf->get_is_write()) { //service L2 read miss
- // it is a pre-fill dramout mf
- if (wb_addr == (unsigned long long int)-1) {
- if ( L2tocbqueue->full() ) {
- assert (L2dramout || wb_addr == (unsigned long long int)-1);
- return;
- }
- mf->set_status(IN_L2TOCBQUEUE_MISS,MR_DRAM_OUTQ,gpu_sim_cycle+gpu_tot_sim_cycle);
- //only transfer across icnt once the whole line has been received by L2 cache
- mf->set_type(REPLY_DATA);
- L2tocbqueue->push(mf,gpu_sim_cycle);
- if( mf->istexture() )
- wb_addr = m_L2cache->fill(mf->get_partition_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 != (unsigned long long int)-1) {
- // performing L2 writeback (no false sharing for memory-side cache)
- int wb_succeed = L2c_write_back(wb_addr, m_config->m_L2_config.get_line_sz());
- if (!wb_succeed) {
- assert (L2dramout || wb_addr == (unsigned long long int)-1);
- return;
+ // prior L2 misses inserted into m_L2_dram_queue here
+ 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 ( mf->istexture() ) {
+ // in this model, L2 is for texture only
+ if ( !m_L2_icnt_queue->full() ) {
+ enum cache_request_status status = m_L2cache->access(mf->get_partition_addr(),mf,gpu_sim_cycle+gpu_tot_sim_cycle);
+ if ( status == HIT ) {
+ // L2 cache replies with data
+ mf->set_type(REPLY_DATA);
+ m_L2_icnt_queue->push(mf);
+ m_icnt_L2_queue->pop();
+ } else if ( status != RESERVATION_FAIL ) {
+ // L2 cache accepted request
+ m_icnt_L2_queue->pop();
+ } else {
+ // L2 cache lock-up: will try again next cycle
+ }
}
- }
- m_missTracker->miss_serviced(mf);
- L2dramout = NULL;
- wb_addr = -1;
- } else { //service L2 write miss
- m_missTracker->miss_serviced(mf);
- mf->set_type(REPLY_DATA);
- L2tocbqueue->push(mf,gpu_sim_cycle);
- L2dramout = NULL;
- wb_addr = -1;
- }
- }
- assert (L2dramout || wb_addr == (unsigned long long int)-1);
+ } else {
+ // non-texture access
+ mf->set_status(IN_PARTITION_L2_TO_DRAM_QUEUE,gpu_sim_cycle+gpu_tot_sim_cycle);
+ m_L2_dram_queue->push(mf);
+ m_icnt_L2_queue->pop();
+ }
+ }
}
-// 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
-bool memory_partition_unit::L2c_write_back( unsigned long long int addr, int bsize )
+bool memory_partition_unit::full() const
{
- if ( L2todram_wbqueue->full() )
- return false;
- mem_fetch *mf = new mem_fetch(addr,
- bsize,
- READ_PACKET_SIZE,
- (unsigned)-1/*sid*/,
- (unsigned)-1/*tpc*/,
- (unsigned)-1/*wid*/,
- (unsigned)-1/*mshr_id*/,
- NULL/*inst*/,
- true/*write*/,
- partial_write_mask_t(),
- L2_WRBK_ACC,
- L2_WTBK_DATA,
- m_config );
- L2todram_wbqueue->push(mf,gpu_sim_cycle);
- return true;
+ return m_icnt_L2_queue->full();
}
-void memory_partition_unit::L2c_print_cache_stat(unsigned &accesses, unsigned &misses) const
+void memory_partition_unit::print_cache_stat(unsigned &accesses, unsigned &misses) const
{
- FILE *fp = stdout;
- m_L2cache->print(fp,accesses,misses);
- m_mshr->print_stat(fp);
- m_missTracker->print_stat(fp);
- m_accessLocality->print_stat(fp, false);
+ FILE *fp = stdout;
+ m_L2cache->print(fp,accesses,misses);
}
void memory_partition_unit::print( FILE *fp ) const
{
- if( !m_request_tracker.empty() ) {
- fprintf(fp,"Memory 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");
- }
- }
- m_dram->print(fp);
-}
-
-void memory_partition_unit::L2c_update_stat()
-{
- unsigned i=m_id;
- if (m_icnt2cache_queue->get_length() > m_stats->L2_cbtoL2length[i])
- m_stats->L2_cbtoL2length[i] = m_icnt2cache_queue->get_length();
- if (m_icnt2cache_write_queue->get_length() > m_stats->L2_cbtoL2writelength[i])
- m_stats->L2_cbtoL2writelength[i] = m_icnt2cache_write_queue->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 memory_stats_t::L2c_print_stat( unsigned n_mem )
-{
- unsigned i;
-
- printf(" ");
- for (i=0;i<n_mem;i++) {
- printf(" dram[%d]", i);
- }
- printf("\n");
-
- printf("cbtoL2 queue maximum length =");
- for (i=0;i<n_mem;i++) {
- printf("%8d", L2_cbtoL2length[i]);
- }
- printf("\n");
-
- printf("cbtoL2 write queue maximum length =");
- for (i=0;i<n_mem;i++) {
- printf("%8d", L2_cbtoL2writelength[i]);
- }
- printf("\n");
-
- printf("L2tocb queue maximum length =");
- for (i=0;i<n_mem;i++) {
- printf("%8d", L2_L2tocblength[i]);
- }
- printf("\n");
-
- printf("dramtoL2 queue maximum length =");
- for (i=0;i<n_mem;i++) {
- printf("%8d", L2_dramtoL2length[i]);
- }
- printf("\n");
-
- printf("dramtoL2 write queue maximum length =");
- for (i=0;i<n_mem;i++) {
- printf("%8d", L2_dramtoL2writelength[i]);
- }
- printf("\n");
-
- printf("L2todram queue maximum length =");
- for (i=0;i<n_mem;i++) {
- printf("%8d", L2_L2todramlength[i]);
- }
- printf("\n");
+ if ( !m_request_tracker.empty() ) {
+ fprintf(fp,"Memory 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");
+ }
+ }
+ m_dram->print(fp);
}
void memory_stats_t::print( FILE *fp )
{
- 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);
+ 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);
}
void gpgpu_sim::L2c_print_cache_stat() const
{
- unsigned i, j, k;
- for (i=0,j=0,k=0;i<m_memory_config->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);
+ unsigned i, j, k;
+ for (i=0,j=0,k=0;i<m_memory_config->m_n_mem;i++)
+ m_memory_partition_unit[i]->print_cache_stat(k,j);
+ printf("L2 Cache Total Miss Rate = %0.3f\n", (float)j/k);
}
-void gpgpu_sim::L2c_print_debug()
-{
- unsigned i;
-
- printf(" ");
- for (i=0;i<m_memory_config->m_n_mem;i++)
- printf(" dram[%d]", i);
- printf("\n");
-
- printf("cbtoL2 queue length =");
- for (i=0;i<m_memory_config->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<m_memory_config->m_n_mem;i++)
- printf("%8d", m_memory_partition_unit[i]->get_cbtoL2writequeue_length());
- printf("\n");
-
- printf("L2tocb queue length =");
- for (i=0;i<m_memory_config->m_n_mem;i++) {
- printf("%8d", m_memory_partition_unit[i]->get_L2tocbqueue_length());
- }
- printf("\n");
-
- printf("dramtoL2 queue length =");
- for (i=0;i<m_memory_config->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<m_memory_config->m_n_mem;i++) {
- printf("%8d", m_memory_partition_unit[i]->get_dramtoL2writequeue_length());
- }
- printf("\n");
-
- printf("L2todram queue length =");
- for (i=0;i<m_memory_config->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<m_memory_config->m_n_mem;i++) {
- printf("%8d", m_memory_partition_unit[i]->get_L2todram_wbqueue_length());
- }
- printf("\n");
+unsigned memory_partition_unit::flushL2()
+{
+ m_L2cache->flush();
+ return 0; // L2 is read only in this version
}
-#define CREATELOG 111
-#define SAMPLELOG 222
-#define DUMPLOG 333
-
-void memory_partition_unit::L2c_log(int task)
+bool memory_partition_unit::busy() const
{
- if (task == SAMPLELOG) {
- StatAddSample(cbtol2_Dist, m_icnt2cache_queue->get_length());
- StatAddSample(cbtoL2wr_Dist, m_icnt2cache_write_queue->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) {
- 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);
- }
+ return !m_request_tracker.empty();
}
-unsigned memory_partition_unit::flushL2()
-{
- return m_L2cache->flush();
-}
-
-void gpgpu_sim::L2c_latency_log_dump()
+void memory_partition_unit::push( mem_fetch* req, unsigned long long cycle )
{
- for (unsigned i=0;i<m_memory_config->m_n_mem;i++)
- m_memory_partition_unit[i]->L2c_latency_log_dump();
+ if (req) {
+ m_request_tracker.insert(req);
+ rop_delay_t r;
+ r.req = req;
+ r.ready_cycle = cycle + 115; // Add 115*4=460 delay cycles
+ m_rop.push(r);
+ req->set_status(IN_PARTITION_ROP_DELAY,gpu_sim_cycle+gpu_tot_sim_cycle);
+ }
+ if ( !m_rop.empty() && (cycle >= m_rop.front().ready_cycle) ) {
+ mem_fetch* mf = m_rop.front().req;
+ m_rop.pop();
+ m_stats->memlatstat_icnt2mem_pop(mf);
+ m_icnt_L2_queue->push(mf);
+ mf->set_status(IN_PARTITION_ICNT_TO_L2_QUEUE,gpu_sim_cycle+gpu_tot_sim_cycle);
+ }
}
-void memory_partition_unit::L2c_latency_log_dump()
+mem_fetch* memory_partition_unit::pop()
{
- printf ("(LOGB2)Latency DRAM[%u] ",m_id); StatDisp(m_icnt2cache_queue->get_lat_stat());
- printf ("(LOGB2)Latency DRAM[%u] ",m_id); StatDisp(m_icnt2cache_write_queue->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());
+ mem_fetch* mf = m_L2_icnt_queue->pop();
+ if ( mf && mf->isatomic() )
+ mf->do_atomic();
+ m_request_tracker.erase(mf);
+ return mf;
}
-bool memory_partition_unit::busy() const
+mem_fetch* memory_partition_unit::top()
{
- return !m_request_tracker.empty();
+ return m_L2_icnt_queue->top();
}
+void memory_partition_unit::dram_cycle()
+{
+ // pop completed memory request from dram and push it to dram-to-L2 queue
+ if ( !m_dram_L2_queue->full() ) {
+ mem_fetch* mf = m_dram->pop();
+ if (mf) {
+ m_dram_L2_queue->push(mf);
+ mf->set_status(IN_PARTITION_DRAM_TO_L2_QUEUE,gpu_sim_cycle+gpu_tot_sim_cycle);
+ }
+ }
+ m_dram->cycle();
+ m_dram->dram_log(SAMPLELOG);
+
+ if( !m_dram->full() && !m_L2_dram_queue->empty() ) {
+ mem_fetch *mf = m_L2_dram_queue->pop();
+ m_dram->push(mf);
+ }
+}