diff options
Diffstat (limited to 'src/gpgpu-sim/dram.cc')
| -rw-r--r-- | src/gpgpu-sim/dram.cc | 630 |
1 files changed, 317 insertions, 313 deletions
diff --git a/src/gpgpu-sim/dram.cc b/src/gpgpu-sim/dram.cc index 9f76b96..3182b38 100644 --- a/src/gpgpu-sim/dram.cc +++ b/src/gpgpu-sim/dram.cc @@ -68,195 +68,163 @@ #include "gpu-misc.h" #include "dram.h" #include "mem_latency_stat.h" +#include "dram_sched.h" #ifdef DRAM_VERIFY int PRINT_CYCLE = 0; #endif -dram_t* dram_create( unsigned int id, unsigned int nbk, - unsigned int tCCD, unsigned int tRRD, - unsigned int tRCD, unsigned int tRAS, - unsigned int tRP, unsigned int tRC, - unsigned int CL, unsigned int WL, - unsigned int BL, unsigned int tWTR, - unsigned int busW, unsigned int queue_limit, - unsigned char scheduler_type ) +template class fifo_pipeline<mem_fetch>; +template class fifo_pipeline<dram_req_t>; + +dram_t::dram_t( unsigned int partition_id, struct memory_config *config ) { - dram_t *dm; - unsigned i; + id = partition_id; + m_stats = NULL; + m_config = config; - dm = (dram_t*)calloc(1,sizeof(dram_t)); - dm = new (dm) dram_t(); + BL=m_config->gpgpu_dram_burst_length; + busW=m_config->gpgpu_dram_buswidth; - dm->id = id; + sscanf(m_config->gpgpu_dram_timing_opt,"%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",&nbk,&tCCD,&tRRD,&tRCD,&tRAS,&tRP,&tRC,&CL,&WL,&tWTR); + m_config->gpu_mem_n_bk = nbk; - dm->nbk = nbk; - dm->tCCD = tCCD; - dm->tRRD = tRRD; - dm->tRCD = tRCD; - dm->tRCDWR = tRCD - (WL + 1); //formula given in datasheet - dm->tRAS = tRAS; - dm->tRP = tRP; - dm->tRC = tRC; - dm->CL = CL; - dm->WL = WL; - dm->BL = BL; + tRCDWR = tRCD - (WL + 1); //formula given in datasheet + tRTW = (CL+(BL/2)+2-WL); //read to write time according to datasheet - dm->tRTW = (CL+(BL/2)+2-WL); //read to write time according to datasheet - dm->tWTR = tWTR; + CCDc = 0; + RRDc = 0; + RTWc = 0; + WTRc = 0; - dm->busW = busW; + rw = READ; //read mode is default - dm->CCDc = 0; - dm->RRDc = 0; - dm->RTWc = 0; - dm->WTRc = 0; + bk = (bank_t**) calloc(sizeof(bank_t*),nbk); + bk[0] = (bank_t*) calloc(sizeof(bank_t),nbk); + for (unsigned i=1;i<nbk;i++) + bk[i] = bk[0] + i; + for (unsigned i=0;i<nbk;i++) + bk[i]->state = BANK_IDLE; - dm->rw = READ; //read mode is default + prio = 0; + rwq = new fifo_pipeline<dram_req_t>("rwq",CL,CL+1,gpu_sim_cycle); + mrqq = new fifo_pipeline<dram_req_t>("mrqq",0,0,gpu_sim_cycle); + returnq = new fifo_pipeline<mem_fetch>("dramreturnq",0,m_config->gpgpu_dram_sched_queue_size,gpu_sim_cycle); + m_fast_ideal_scheduler = NULL; + if ( m_config->scheduler_type == DRAM_IDEAL_FAST ) + m_fast_ideal_scheduler = new ideal_dram_scheduler(this); + n_cmd = 0; + n_activity = 0; + n_nop = 0; + n_act = 0; + n_pre = 0; + n_rd = 0; + n_wr = 0; + n_req = 0; + max_mrqs_temp = 0; + bwutil = 0; + max_mrqs = 0; - dm->bk = (bank_t**) calloc(sizeof(bank_t*),dm->nbk); - dm->bk[0] = (bank_t*) calloc(sizeof(bank_t),dm->nbk); - for (i=1;i<dm->nbk;i++) { - dm->bk[i] = dm->bk[0] + i; + for (unsigned i=0;i<10;i++) { + dram_util_bins[i]=0; + dram_eff_bins[i]=0; } - for (i=0;i<dm->nbk;i++) { - dm->bk[i]->state = BANK_IDLE; - } - dm->prio = 0; - dm->rwq = dq_create("rwq",0,dm->CL,dm->CL+1); - dm->mrqq = dq_create("mrqq",0,0,0); - dm->queue_limit = queue_limit; - - dm->returnq = dq_create("dramreturnq",0,0, queue_limit); - - dm->m_fast_ideal_scheduler = NULL; - if ( scheduler_type == DRAM_IDEAL_FAST ) - dm->m_fast_ideal_scheduler = alloc_fast_ideal_scheduler(dm); - - - dm->n_cmd = 0; - dm->n_activity = 0; - dm->n_nop = 0; - dm->n_act = 0; - dm->n_pre = 0; - dm->n_rd = 0; - dm->n_wr = 0; - dm->n_req = 0; - dm->max_mrqs_temp = 0; + last_n_cmd = last_n_activity = last_bwutil = 0; - dm->bwutil = 0; + n_cmd_partial = 0; + n_activity_partial = 0; + n_nop_partial = 0; + n_act_partial = 0; + n_pre_partial = 0; + n_req_partial = 0; + ave_mrqs_partial = 0; + bwutil_partial = 0; - dm->max_mrqs = 0; - - dm->scheduler_type = scheduler_type; - - dm->realistic_scheduler_mode = READ; //realistic scheduler defaults to read - for (i=0;i<10;i++) { - dm->dram_util_bins[i]=0; - dm->dram_eff_bins[i]=0; - } - dm->last_n_cmd = dm->last_n_activity = dm->last_bwutil = 0; - - dm->n_cmd_partial = 0; - dm->n_activity_partial = 0; - dm->n_nop_partial = 0; - dm->n_act_partial = 0; - dm->n_pre_partial = 0; - dm->n_req_partial = 0; - dm->ave_mrqs_partial = 0; - dm->bwutil_partial = 0; - return dm; + if ( queue_limit() ) + mrqq_Dist = StatCreate("mrqq_length",1, queue_limit()); + else //queue length is unlimited; + mrqq_Dist = StatCreate("mrqq_length",1,64); //track up to 64 entries } -void dram_free( dram_t *dm ) -{ - dq_free(dm->mrqq); - dq_free(dm->rwq); - dq_free( dm->returnq ); - - free(dm->bk[0]); - free(dm->bk); - free(dm); -} - -int dram_full( dram_t *dm ) +int dram_t::full() { int full = 0; - if ( dm->queue_limit == 0 ) return 0; - if ( dm->scheduler_type == DRAM_IDEAL_FAST ) { - unsigned nreqs = fast_scheduler_queue_length(dm) + dq_n_element(dm->mrqq); - full = (nreqs >= dm->queue_limit); + if ( m_config->gpgpu_dram_sched_queue_size == 0 ) return 0; + if ( m_config->scheduler_type == DRAM_IDEAL_FAST ) { + unsigned nreqs = m_fast_ideal_scheduler->num_pending() + mrqq->get_n_element(); + full = (nreqs >= m_config->gpgpu_dram_sched_queue_size); } else { - full = (dm->mrqq->length >= dm->queue_limit); + full = (mrqq->get_length() >= m_config->gpgpu_dram_sched_queue_size); } return full; } -unsigned int dram_que_length( dram_t *dm ) +unsigned int dram_t::que_length() const { unsigned nreqs = 0; - if (dm->scheduler_type == DRAM_IDEAL_FAST ) { - nreqs = fast_scheduler_queue_length(dm); + if (m_config->scheduler_type == DRAM_IDEAL_FAST ) { + nreqs = m_fast_ideal_scheduler->num_pending(); } else { - nreqs = dm->mrqq->length ; + nreqs = mrqq->get_length(); } return nreqs; } -void dram_push( dram_t *dm, unsigned int bank, - unsigned int row, unsigned int col, - unsigned int nbytes, unsigned int write, - unsigned int wid, - unsigned int sid, int cache_hits_waiting, unsigned long long addr, - void *data ) +bool dram_t::returnq_full() const { - dram_req_t *mrq; - - if (bank>=dm->nbk) printf("ERROR: no such bank exist in DRAM %d\n", bank); + return returnq->full(); +} - mrq = (dram_req_t *) malloc(sizeof(dram_req_t)); +unsigned int dram_t::queue_limit() const +{ + return m_config->gpgpu_dram_sched_queue_size; +} - mrq->bk = bank; - mrq->row = row; - mrq->col = col; - mrq->nbytes = nbytes; - mrq->txbytes = 0; - mrq->dqbytes = 0; - mrq->data = data; - mrq->timestamp = gpu_tot_sim_cycle + gpu_sim_cycle; - mrq->cache_hits_waiting = cache_hits_waiting; - mrq->addr = addr; - mrq->insertion_time = (unsigned) gpu_sim_cycle; - if (!write) { - mrq->rw = READ; //request is a read - } else { - mrq->rw = WRITE; //request is a write - } +dram_req_t::dram_req_t( class mem_fetch *mf ) +{ + bk = mf->tlx.bk; + row = mf->tlx.row; + col = mf->tlx.col; + nbytes = mf->nbytes_L1; + txbytes = 0; + dqbytes = 0; + data = mf; + timestamp = gpu_tot_sim_cycle + gpu_sim_cycle; + cache_hits_waiting = mf->cache_hits_waiting; + addr = mf->addr; + insertion_time = (unsigned) gpu_sim_cycle; + rw = data->m_write?WRITE:READ; +} - dq_push(dm->mrqq,mrq); - dm->n_req += 1; - dm->n_req_partial += 1; +void dram_t::push( class mem_fetch *data ) +{ + assert(data->tlx.bk<nbk); + dram_req_t *mrq = new dram_req_t(data); + mrqq->push(mrq,gpu_sim_cycle); - if ( dm->scheduler_type == DRAM_IDEAL_FAST ) { - unsigned nreqs = fast_scheduler_queue_length(dm); - if ( nreqs > dm->max_mrqs_temp) - dm->max_mrqs_temp = nreqs; + // stats... + n_req += 1; + n_req_partial += 1; + if ( m_config->scheduler_type == DRAM_IDEAL_FAST ) { + unsigned nreqs = m_fast_ideal_scheduler->num_pending(); + if ( nreqs > max_mrqs_temp) + max_mrqs_temp = nreqs; } else { - dm->max_mrqs_temp = (dm->max_mrqs_temp > dm->mrqq->length)? dm->max_mrqs_temp : dm->mrqq->length; + max_mrqs_temp = (max_mrqs_temp > mrqq->get_length())? max_mrqs_temp : mrqq->get_length(); } + m_stats->memlatstat_dram_access(data); } -void scheduler_fifo(dram_t* dm) +void dram_t::scheduler_fifo() { - if (dm->mrqq->head) { - dram_req_t *head_mrqq; + if (!mrqq->empty()) { unsigned int bkn; - head_mrqq = (dram_req_t *)dm->mrqq->head->data; + dram_req_t *head_mrqq = mrqq->top(); bkn = head_mrqq->bk; - if (!dm->bk[bkn]->mrq) { - dm->bk[bkn]->mrq = (dram_req_t*) dq_pop(dm->mrqq); + if (!bk[bkn]->mrq) { + bk[bkn]->mrq = mrqq->pop(gpu_sim_cycle); } } } @@ -265,7 +233,7 @@ void scheduler_fifo(dram_t* dm) #define DEC2ZERO(x) x = (x)? (x-1) : 0; #define SWAP(a,b) a ^= b; b ^= a; a ^= b; -void dram_issueCMD (dram_t* dm) +void dram_t::issueCMD() { unsigned i,j,k; unsigned char issued; @@ -274,206 +242,196 @@ void dram_issueCMD (dram_t* dm) /* check if the upcoming request is on an idle bank */ /* Should we modify this so that multiple requests are checked? */ - switch (dm->scheduler_type) { - case DRAM_FIFO: - scheduler_fifo(dm); - break; - case DRAM_IDEAL_FAST: - fast_scheduler_ideal(dm); - break; + switch (m_config->scheduler_type) { + case DRAM_FIFO: scheduler_fifo(); break; + case DRAM_IDEAL_FAST: fast_scheduler_ideal(); break; default: printf("Error: Unknown DRAM scheduler type\n"); assert(0); } - if ( dm->scheduler_type == DRAM_IDEAL_FAST ) { - unsigned nreqs = fast_scheduler_queue_length(dm); - if ( nreqs > dm->max_mrqs) { - dm->max_mrqs = nreqs; + if ( m_config->scheduler_type == DRAM_IDEAL_FAST ) { + unsigned nreqs = m_fast_ideal_scheduler->num_pending(); + if ( nreqs > max_mrqs) { + max_mrqs = nreqs; } - dm->ave_mrqs += nreqs; - dm->ave_mrqs_partial += nreqs; + ave_mrqs += nreqs; + ave_mrqs_partial += nreqs; } else { - if (dm->mrqq->length > dm->max_mrqs) { - dm->max_mrqs = dm->mrqq->length; + if (mrqq->get_length() > max_mrqs) { + max_mrqs = mrqq->get_length(); } - dm->ave_mrqs += dm->mrqq->length; - dm->ave_mrqs_partial += dm->mrqq->length; + ave_mrqs += mrqq->get_length(); + ave_mrqs_partial += mrqq->get_length(); } - k=dm->nbk; + k=nbk; // check if any bank is ready to issue a new read - for (i=0;i<dm->nbk;i++) { - j = (i + dm->prio) % dm->nbk; - if (dm->bk[j]->mrq) { //if currently servicing a memory request + for (i=0;i<nbk;i++) { + j = (i + prio) % nbk; + if (bk[j]->mrq) { //if currently servicing a memory request // correct row activated for a READ - if ( !issued && !dm->CCDc && !dm->bk[j]->RCDc && - (dm->bk[j]->curr_row == dm->bk[j]->mrq->row) && - (dm->bk[j]->mrq->rw == READ) && (dm->WTRc == 0 ) && - (dm->bk[j]->state == BANK_ACTIVE) && - !dq_full(dm->rwq) ) { - if (dm->rw==WRITE) { - dm->rw=READ; - dq_set_min_length(dm->rwq, dm->CL); + if ( !issued && !CCDc && !bk[j]->RCDc && + (bk[j]->curr_row == bk[j]->mrq->row) && + (bk[j]->mrq->rw == READ) && (WTRc == 0 ) && + (bk[j]->state == BANK_ACTIVE) && + !rwq->full() ) { + if (rw==WRITE) { + rw=READ; + rwq->set_min_length(CL,gpu_sim_cycle); } - dq_push(dm->rwq,(void*)dm->bk[j]->mrq); //only push when rwq empty? - dm->bk[j]->mrq->txbytes += dm->BL * dm->busW * gpu_n_mem_per_ctrlr; //16 bytes - dm->CCDc = dm->tCCD; - dm->RTWc = dm->tRTW; + rwq->push(bk[j]->mrq,gpu_sim_cycle); + bk[j]->mrq->txbytes += BL * busW * gpu_n_mem_per_ctrlr; //16 bytes + CCDc = tCCD; + RTWc = tRTW; issued = 1; - dm->n_rd++; - //printf("\tn_rd++ Bank: %d Row: %d Col: %d\n", j, dm->bk[j]->mrq->row, dm->bk[j]->mrq->col); - dm->bwutil+= dm->BL/2; - dm->bwutil_partial += dm->BL/2; - dm->bk[j]->n_access++; + n_rd++; + bwutil+= BL/2; + bwutil_partial += BL/2; + bk[j]->n_access++; #ifdef DRAM_VERIFY PRINT_CYCLE=1; printf("\tRD Bk:%d Row:%03x Col:%03x \n", - j, dm->bk[j]->curr_row, - dm->bk[j]->mrq->col+dm->bk[j]->mrq->txbytes-dm->BL*dm->busW); + j, bk[j]->curr_row, + bk[j]->mrq->col+bk[j]->mrq->txbytes-BL*busW); #endif // transfer done - if ( !(dm->bk[j]->mrq->txbytes < dm->bk[j]->mrq->nbytes) ) { - dm->bk[j]->mrq = NULL; + if ( !(bk[j]->mrq->txbytes < bk[j]->mrq->nbytes) ) { + bk[j]->mrq = NULL; } } else // correct row activated for a WRITE - if ( !issued && !dm->CCDc && !dm->bk[j]->RCDWRc && - (dm->bk[j]->curr_row == dm->bk[j]->mrq->row) && - (dm->bk[j]->mrq->rw == WRITE) && (dm->RTWc == 0 ) && - (dm->bk[j]->state == BANK_ACTIVE) && - !dq_full(dm->rwq) ) { - if (dm->rw==READ) { - dm->rw=WRITE; - dq_set_min_length(dm->rwq, dm->WL); + if ( !issued && !CCDc && !bk[j]->RCDWRc && + (bk[j]->curr_row == bk[j]->mrq->row) && + (bk[j]->mrq->rw == WRITE) && (RTWc == 0 ) && + (bk[j]->state == BANK_ACTIVE) && + !rwq->full() ) { + if (rw==READ) { + rw=WRITE; + rwq->set_min_length(WL,gpu_sim_cycle); } - dq_push(dm->rwq,(void*)dm->bk[j]->mrq); + rwq->push(bk[j]->mrq,gpu_sim_cycle); - dm->bk[j]->mrq->txbytes += dm->BL * dm->busW * gpu_n_mem_per_ctrlr; /*16 bytes*/ - dm->CCDc = dm->tCCD; + bk[j]->mrq->txbytes += BL * busW * gpu_n_mem_per_ctrlr; /*16 bytes*/ + CCDc = tCCD; issued = 1; - dm->n_wr++; - dm->bwutil+=2; - dm->bwutil_partial += dm->BL/2; + n_wr++; + bwutil+=2; + bwutil_partial += BL/2; #ifdef DRAM_VERIFY PRINT_CYCLE=1; printf("\tWR Bk:%d Row:%03x Col:%03x \n", - j, dm->bk[j]->curr_row, - dm->bk[j]->mrq->col+dm->bk[j]->mrq->txbytes-dm->BL*dm->busW); + j, bk[j]->curr_row, + bk[j]->mrq->col+bk[j]->mrq->txbytes-BL*busW); #endif // transfer done - if ( !(dm->bk[j]->mrq->txbytes < dm->bk[j]->mrq->nbytes) ) { - dm->bk[j]->mrq = NULL; + if ( !(bk[j]->mrq->txbytes < bk[j]->mrq->nbytes) ) { + bk[j]->mrq = NULL; } } else // bank is idle - if ( !issued && !dm->RRDc && - (dm->bk[j]->state == BANK_IDLE) && - !dm->bk[j]->RPc && !dm->bk[j]->RCc ) { + if ( !issued && !RRDc && + (bk[j]->state == BANK_IDLE) && + !bk[j]->RPc && !bk[j]->RCc ) { #ifdef DRAM_VERIFY PRINT_CYCLE=1; printf("\tACT BK:%d NewRow:%03x From:%03x \n", - j,dm->bk[j]->mrq->row,dm->bk[j]->curr_row); + j,bk[j]->mrq->row,bk[j]->curr_row); #endif // activate the row with current memory request - dm->bk[j]->curr_row = dm->bk[j]->mrq->row; - dm->bk[j]->state = BANK_ACTIVE; - dm->RRDc = dm->tRRD; - dm->bk[j]->RCDc = dm->tRCD; - dm->bk[j]->RCDWRc = dm->tRCDWR; - dm->bk[j]->RASc = dm->tRAS; - dm->bk[j]->RCc = dm->tRC; - dm->prio = (j + 1) % dm->nbk; + bk[j]->curr_row = bk[j]->mrq->row; + bk[j]->state = BANK_ACTIVE; + RRDc = tRRD; + bk[j]->RCDc = tRCD; + bk[j]->RCDWRc = tRCDWR; + bk[j]->RASc = tRAS; + bk[j]->RCc = tRC; + prio = (j + 1) % nbk; issued = 1; - dm->n_act_partial++; - dm->n_act++; + n_act_partial++; + n_act++; } else // different row activated if ( (!issued) && - (dm->bk[j]->curr_row != dm->bk[j]->mrq->row) && - (dm->bk[j]->state == BANK_ACTIVE) && - (!dm->bk[j]->RASc) ) { - //printf("\tRASc: %d \n", dm->bk[j]->RASc); + (bk[j]->curr_row != bk[j]->mrq->row) && + (bk[j]->state == BANK_ACTIVE) && + (!bk[j]->RASc) ) { // make the bank idle again - dm->bk[j]->state = BANK_IDLE; - dm->bk[j]->RPc = dm->tRP; - dm->prio = (j + 1) % dm->nbk; + bk[j]->state = BANK_IDLE; + bk[j]->RPc = tRP; + prio = (j + 1) % nbk; issued = 1; - dm->n_pre++; - dm->n_pre_partial++; + n_pre++; + n_pre_partial++; #ifdef DRAM_VERIFY PRINT_CYCLE=1; - printf("\tPRE BK:%d Row:%03x \n", j,dm->bk[j]->curr_row); - //printf("\tRASc: %d \n", dm->bk[j]->RASc); + printf("\tPRE BK:%d Row:%03x \n", j,bk[j]->curr_row); #endif } } else { - if (!dm->CCDc && !dm->RRDc && !dm->RTWc && !dm->WTRc && !dm->bk[j]->RCDc && !dm->bk[j]->RASc - && !dm->bk[j]->RCc && !dm->bk[j]->RPc && !dm->bk[j]->RCDWRc) k--; - dm->bk[i]->n_idle++; + if (!CCDc && !RRDc && !RTWc && !WTRc && !bk[j]->RCDc && !bk[j]->RASc + && !bk[j]->RCc && !bk[j]->RPc && !bk[j]->RCDWRc) k--; + bk[i]->n_idle++; } } if (!issued) { - dm->n_nop++; - dm->n_nop_partial++; + n_nop++; + n_nop_partial++; #ifdef DRAM_VIEWCMD printf("\tNOP "); #endif } if (k) { - dm->n_activity++; - dm->n_activity_partial++; + n_activity++; + n_activity_partial++; } - dm->n_cmd++; - dm->n_cmd_partial++; + n_cmd++; + n_cmd_partial++; // decrements counters once for each time dram_issueCMD is called - DEC2ZERO(dm->RRDc); - DEC2ZERO(dm->CCDc); - DEC2ZERO(dm->RTWc); - DEC2ZERO(dm->WTRc); - for (j=0;j<dm->nbk;j++) { - DEC2ZERO(dm->bk[j]->RCDc); - DEC2ZERO(dm->bk[j]->RASc); - DEC2ZERO(dm->bk[j]->RCc); - DEC2ZERO(dm->bk[j]->RPc); - DEC2ZERO(dm->bk[j]->RCDWRc); + DEC2ZERO(RRDc); + DEC2ZERO(CCDc); + DEC2ZERO(RTWc); + DEC2ZERO(WTRc); + for (j=0;j<nbk;j++) { + DEC2ZERO(bk[j]->RCDc); + DEC2ZERO(bk[j]->RASc); + DEC2ZERO(bk[j]->RCc); + DEC2ZERO(bk[j]->RPc); + DEC2ZERO(bk[j]->RCDWRc); } #ifdef DRAM_VISUALIZE - dram_visualize(dm); + visualize(); #endif } //if mrq is being serviced by dram, gets popped after CL latency fulfilled -void* dram_pop( dram_t *dm ) -{ +class mem_fetch* dram_t::pop() +{ dram_req_t *mrq; - void *data; + class mem_fetch *data; unsigned dq_latency; data = NULL; - mrq = (dram_req_t*)dq_pop(dm->rwq); + mrq = rwq->pop(gpu_sim_cycle); if (mrq) { - // data = mrq->data; #ifdef DRAM_VIEWCMD printf("\tDQ: BK%d Row:%03x Col:%03x", mrq->bk, mrq->row, mrq->col + mrq->dqbytes); #endif - mrq->dqbytes += dm->BL * dm->busW * gpu_n_mem_per_ctrlr; /*16 bytes*/ + mrq->dqbytes += BL * busW * gpu_n_mem_per_ctrlr; /*16 bytes*/ if (mrq->dqbytes >= mrq->nbytes) { - - if (gpgpu_memlatency_stat) { + if (m_config->gpgpu_memlatency_stat) { dq_latency = gpu_sim_cycle + gpu_tot_sim_cycle - mrq->timestamp; - dq_lat_table[LOGB2(dq_latency)]++; - if (dq_latency > max_dq_latency) - max_dq_latency = dq_latency; + m_stats->dq_lat_table[LOGB2(dq_latency)]++; + if (dq_latency > m_stats->max_dq_latency) + m_stats->max_dq_latency = dq_latency; } data = mrq->data; - - free(mrq); + delete mrq; } } #ifdef DRAM_VIEWCMD @@ -483,17 +441,33 @@ void* dram_pop( dram_t *dm ) return data; } +void dram_t::returnq_push( class mem_fetch *mf, unsigned long long gpu_sim_cycle) +{ + returnq->push(mf,gpu_sim_cycle); +} + +class mem_fetch* dram_t::returnq_pop( unsigned long long gpu_sim_cycle) +{ + return returnq->pop(gpu_sim_cycle); +} + +class mem_fetch* dram_t::returnq_top() +{ + return returnq->top(); +} + + // a hack to allow peeking into what memory request will be serviced. -void* dram_top( dram_t *dm ) +class mem_fetch* dram_t::top() { dram_req_t *mrq; - void *data; + class mem_fetch *data; data = NULL; - mrq = (dram_req_t*)dq_top(dm->rwq); + mrq = rwq->top(); if (mrq) { // number of bytes returned from dram if this is ever popped - unsigned tobe_dqbytes = mrq->dqbytes + dm->BL * dm->busW * gpu_n_mem_per_ctrlr; + unsigned tobe_dqbytes = mrq->dqbytes + BL * busW * gpu_n_mem_per_ctrlr; if (tobe_dqbytes >= mrq->nbytes) { data = mrq->data; } @@ -502,82 +476,112 @@ void* dram_top( dram_t *dm ) return data; } -void dram_print( dram_t* dm, FILE* simFile) +void dram_t::print( FILE* simFile) const { unsigned i; fprintf(simFile,"DRAM[%d]: %d bks, busW=%d BL=%d CL=%d, ", - dm->id, dm->nbk, dm->busW, dm->BL, dm->CL ); + id, nbk, busW, BL, CL ); fprintf(simFile,"tRRD=%d tCCD=%d, tRCD=%d tRAS=%d tRP=%d tRC=%d\n", - dm->tCCD, dm->tRRD, dm->tRCD, dm->tRAS, dm->tRP, dm->tRC ); + tCCD, tRRD, tRCD, tRAS, tRP, tRC ); fprintf(simFile,"n_cmd=%d n_nop=%d n_act=%d n_pre=%d n_req=%d n_rd=%d n_write=%d bw_util=%.4g\n", - dm->n_cmd, dm->n_nop, dm->n_act, dm->n_pre, dm->n_req, dm->n_rd, dm->n_wr, - (float)dm->bwutil/dm->n_cmd); + n_cmd, n_nop, n_act, n_pre, n_req, n_rd, n_wr, + (float)bwutil/n_cmd); fprintf(simFile,"n_activity=%d dram_eff=%.4g\n", - dm->n_activity, (float)dm->bwutil/dm->n_activity); - for (i=0;i<dm->nbk;i++) { - fprintf(simFile, "bk%d: %da %di ",i,dm->bk[i]->n_access,dm->bk[i]->n_idle); + n_activity, (float)bwutil/n_activity); + for (i=0;i<nbk;i++) { + fprintf(simFile, "bk%d: %da %di ",i,bk[i]->n_access,bk[i]->n_idle); } fprintf(simFile, "\n"); fprintf(simFile, "dram_util_bins:"); - for (i=0;i<10;i++) fprintf(simFile, " %d", dm->dram_util_bins[i]); + for (i=0;i<10;i++) fprintf(simFile, " %d", dram_util_bins[i]); fprintf(simFile, "\ndram_eff_bins:"); - for (i=0;i<10;i++) fprintf(simFile, " %d", dm->dram_eff_bins[i]); + for (i=0;i<10;i++) fprintf(simFile, " %d", dram_eff_bins[i]); fprintf(simFile, "\n"); - /* - { - delay_data* mrq; - mrq = dm->mrqq->head; - while (mrq) { - printf("%d",((dram_req_t*)mrq->data)->bk); - mrq = mrq->next; - } - printf("\n"); - } - */ - fprintf(simFile, "mrqq: max=%d avg=%g\n", dm->max_mrqs, (float)dm->ave_mrqs/dm->n_cmd); + fprintf(simFile, "mrqq: max=%d avg=%g\n", max_mrqs, (float)ave_mrqs/n_cmd); } -void dram_visualize( dram_t* dm ) +void dram_t::visualize() const { - unsigned i; - printf("RRDc=%d CCDc=%d mrqq.Length=%d rwq.Length=%d\n", - dm->RRDc, dm->CCDc, dm->mrqq->length,dm->rwq->length); - for (i=0;i<dm->nbk;i++) { + RRDc, CCDc, mrqq->get_length(),rwq->get_length()); + for (unsigned i=0;i<nbk;i++) { printf("BK%d: state=%c curr_row=%03x, %2d %2d %2d %2d %p ", - i, dm->bk[i]->state, dm->bk[i]->curr_row, - dm->bk[i]->RCDc, dm->bk[i]->RASc, - dm->bk[i]->RPc, dm->bk[i]->RCc, - dm->bk[i]->mrq ); - if (dm->bk[i]->mrq) - printf("txf: %d %d", dm->bk[i]->mrq->nbytes, dm->bk[i]->mrq->txbytes); + i, bk[i]->state, bk[i]->curr_row, + bk[i]->RCDc, bk[i]->RASc, + bk[i]->RPc, bk[i]->RCc, + bk[i]->mrq ); + if (bk[i]->mrq) + printf("txf: %d %d", bk[i]->mrq->nbytes, bk[i]->mrq->txbytes); printf("\n"); } - if ( dm->m_fast_ideal_scheduler ) { - dump_fast_ideal_scheduler( dm ); - } - + if ( m_fast_ideal_scheduler ) + m_fast_ideal_scheduler->print(stdout); } -void dram_print_stat( dram_t* dm, FILE* simFile ) +void dram_t::print_stat( FILE* simFile ) { - int i; fprintf(simFile,"DRAM (%d): n_cmd=%d n_nop=%d n_act=%d n_pre=%d n_req=%d n_rd=%d n_write=%d bw_util=%.4g ", - dm->id, dm->n_cmd, dm->n_nop, dm->n_act, dm->n_pre, dm->n_req, dm->n_rd, dm->n_wr, - (float)dm->bwutil/dm->n_cmd); - fprintf(simFile, "mrqq: %d %.4g mrqsmax=%d ", dm->max_mrqs, (float)dm->ave_mrqs/dm->n_cmd, dm->max_mrqs_temp); + id, n_cmd, n_nop, n_act, n_pre, n_req, n_rd, n_wr, + (float)bwutil/n_cmd); + fprintf(simFile, "mrqq: %d %.4g mrqsmax=%d ", max_mrqs, (float)ave_mrqs/n_cmd, max_mrqs_temp); fprintf(simFile, "\n"); fprintf(simFile, "dram_util_bins:"); - for (i=0;i<10;i++) fprintf(simFile, " %d", dm->dram_util_bins[i]); + for (unsigned i=0;i<10;i++) fprintf(simFile, " %d", dram_util_bins[i]); fprintf(simFile, "\ndram_eff_bins:"); - for (i=0;i<10;i++) fprintf(simFile, " %d", dm->dram_eff_bins[i]); + for (unsigned i=0;i<10;i++) fprintf(simFile, " %d", dram_eff_bins[i]); fprintf(simFile, "\n"); - dm->max_mrqs_temp = 0; + max_mrqs_temp = 0; } - -unsigned dram_busy( dram_t* dm) +void dram_t::queue_latency_log_dump( FILE *fp ) { - return !dm->m_request_tracker.empty(); + fprintf(fp,"(LOGB2)Latency DRAM[%d] ",id); + StatDisp(mrqq->get_lat_stat()); + fprintf(fp,"(LOGB2)Latency DRAM[%d] ",id); + StatDisp(rwq->get_lat_stat()); + dram_log(DUMPLOG); } +void dram_t::visualizer_print( gzFile visualizer_file ) +{ + // dram specific statistics + gzprintf(visualizer_file,"dramncmd: %u %u\n",id, n_cmd_partial); + gzprintf(visualizer_file,"dramnop: %u %u\n",id,n_nop_partial); + gzprintf(visualizer_file,"dramnact: %u %u\n",id,n_act_partial); + gzprintf(visualizer_file,"dramnpre: %u %u\n",id,n_pre_partial); + gzprintf(visualizer_file,"dramnreq: %u %u\n",id,n_req_partial); + gzprintf(visualizer_file,"dramavemrqs: %u %u\n",id, + n_cmd_partial?(ave_mrqs_partial/n_cmd_partial ):0); + + // utilization and efficiency + gzprintf(visualizer_file,"dramutil: %u %u\n", + id,n_cmd_partial?100*bwutil_partial/n_cmd_partial:0); + gzprintf(visualizer_file,"drameff: %u %u\n", + id,n_activity_partial?100*bwutil_partial/n_activity_partial:0); + + // reset for next interval + bwutil_partial = 0; + n_activity_partial = 0; + ave_mrqs_partial = 0; + n_cmd_partial = 0; + n_nop_partial = 0; + n_act_partial = 0; + n_pre_partial = 0; + n_req_partial = 0; + + // dram access type classification + for (unsigned j = 0; j < m_config->gpu_mem_n_bk; j++) { + gzprintf(visualizer_file,"dramglobal_acc_r: %u %u %u\n", id, j, + m_stats->mem_access_type_stats[GLOBAL_ACC_R][id][j]); + gzprintf(visualizer_file,"dramglobal_acc_w: %u %u %u\n", id, j, + m_stats->mem_access_type_stats[GLOBAL_ACC_W][id][j]); + gzprintf(visualizer_file,"dramlocal_acc_r: %u %u %u\n", id, j, + m_stats->mem_access_type_stats[LOCAL_ACC_R][id][j]); + gzprintf(visualizer_file,"dramlocal_acc_w: %u %u %u\n", id, j, + m_stats->mem_access_type_stats[LOCAL_ACC_W][id][j]); + gzprintf(visualizer_file,"dramconst_acc_r: %u %u %u\n", id, j, + m_stats->mem_access_type_stats[CONST_ACC_R][id][j]); + gzprintf(visualizer_file,"dramtexture_acc_r: %u %u %u\n", id, j, + m_stats->mem_access_type_stats[TEXTURE_ACC_R][id][j]); + } +} |
