diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/abstract_hardware_model.h | 2 | ||||
| -rw-r--r-- | src/cuda-sim/cuda-sim.cc | 32 | ||||
| -rw-r--r-- | src/gpgpu-sim/dram.cc | 597 | ||||
| -rw-r--r-- | src/gpgpu-sim/dram.h | 60 | ||||
| -rw-r--r-- | src/gpgpu-sim/dram_sched.cc | 11 | ||||
| -rw-r--r-- | src/gpgpu-sim/gpu-sim.cc | 27 | ||||
| -rw-r--r-- | src/gpgpu-sim/gpu-sim.h | 4 | ||||
| -rw-r--r-- | src/gpgpu-sim/shader.cc | 70 | ||||
| -rw-r--r-- | src/gpgpu-sim/shader.h | 41 |
9 files changed, 678 insertions, 166 deletions
diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index 910a9ed..7d7773c 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -76,6 +76,7 @@ enum uarch_op_t { NO_OP=-1, ALU_OP=1, SFU_OP, + DP_OP, ALU_SFU_OP, LOAD_OP, STORE_OP, @@ -131,6 +132,7 @@ typedef enum special_operations_t special_ops; // Required to identify for the p enum operation_pipeline_t { UNKOWN_OP, SP__OP, + DP__OP, SFU__OP, MEM__OP }; diff --git a/src/cuda-sim/cuda-sim.cc b/src/cuda-sim/cuda-sim.cc index d4ace76..48d1219 100644 --- a/src/cuda-sim/cuda-sim.cc +++ b/src/cuda-sim/cuda-sim.cc @@ -62,8 +62,8 @@ addr_t g_debug_pc = 0xBEEF1518; unsigned g_ptx_sim_num_insn = 0; unsigned gpgpu_param_num_shaders = 0; -char *opcode_latency_int, *opcode_latency_fp, *opcode_latency_dp; -char *opcode_initiation_int, *opcode_initiation_fp, *opcode_initiation_dp; +char *opcode_latency_int, *opcode_latency_fp, *opcode_latency_dp,*opcode_latency_sfu; +char *opcode_initiation_int, *opcode_initiation_fp, *opcode_initiation_dp,*opcode_initiation_sfu; char *cdp_latency_str; unsigned cdp_latency[5]; @@ -80,6 +80,10 @@ void ptx_opcocde_latency_options (option_parser_t opp) { "Opcode latencies for double precision floating points <ADD,MAX,MUL,MAD,DIV>" "Default 8,8,8,8,335", "8,8,8,8,335"); + option_parser_register(opp, "-opcode_latency_sfu", OPT_CSTR, &opcode_latency_sfu, + "Opcode latencies for SFU instructions" + "Default 8", + "8"); option_parser_register(opp, "-ptx_opcode_initiation_int", OPT_CSTR, &opcode_initiation_int, "Opcode initiation intervals for integers <ADD,MAX,MUL,MAD,DIV>" "Default 1,1,4,4,32", @@ -92,6 +96,10 @@ void ptx_opcocde_latency_options (option_parser_t opp) { "Opcode initiation intervals for double precision floating points <ADD,MAX,MUL,MAD,DIV>" "Default 8,8,8,8,130", "8,8,8,8,130"); + option_parser_register(opp, "-ptx_opcode_initiation_sfu", OPT_CSTR, &opcode_initiation_sfu, + "Opcode initiation intervals for sfu instructions" + "Default 8", + "8"); option_parser_register(opp, "-cdp_latency", OPT_CSTR, &cdp_latency_str, "CDP API latency <cudaStreamCreateWithFlags, \ cudaGetParameterBufferV2_init_perWarp, cudaGetParameterBufferV2_perKernel, \ @@ -589,9 +597,11 @@ void ptx_instruction::set_opcode_and_latency() unsigned int_latency[5]; unsigned fp_latency[5]; unsigned dp_latency[5]; + unsigned sfu_latency; unsigned int_init[5]; unsigned fp_init[5]; unsigned dp_init[5]; + unsigned sfu_init; /* * [0] ADD,SUB * [1] MAX,Min @@ -608,6 +618,8 @@ void ptx_instruction::set_opcode_and_latency() sscanf(opcode_latency_dp, "%u,%u,%u,%u,%u", &dp_latency[0],&dp_latency[1],&dp_latency[2], &dp_latency[3],&dp_latency[4]); + sscanf(opcode_latency_sfu, "%u", + &sfu_latency); sscanf(opcode_initiation_int, "%u,%u,%u,%u,%u", &int_init[0],&int_init[1],&int_init[2], &int_init[3],&int_init[4]); @@ -617,8 +629,10 @@ void ptx_instruction::set_opcode_and_latency() sscanf(opcode_initiation_dp, "%u,%u,%u,%u,%u", &dp_init[0],&dp_init[1],&dp_init[2], &dp_init[3],&dp_init[4]); + sscanf(opcode_initiation_sfu, "%u", + &sfu_init); sscanf(cdp_latency_str, "%u,%u,%u,%u,%u", - &cdp_latency[0],&cdp_latency[1],&cdp_latency[2], + &cdp_latency[0],&cdp_latency[1],&cdp_latency[2], &cdp_latency[3],&cdp_latency[4]); if(!m_operands.empty()){ @@ -678,6 +692,7 @@ void ptx_instruction::set_opcode_and_latency() case FF64_TYPE: latency = dp_latency[0]; initiation_interval = dp_init[0]; + op = DP_OP; break; case B32_TYPE: case U32_TYPE: @@ -699,6 +714,7 @@ void ptx_instruction::set_opcode_and_latency() case FF64_TYPE: latency = dp_latency[1]; initiation_interval = dp_init[1]; + op = DP_OP; break; case B32_TYPE: case U32_TYPE: @@ -715,13 +731,12 @@ void ptx_instruction::set_opcode_and_latency() case F32_TYPE: latency = fp_latency[2]; initiation_interval = fp_init[2]; - op = ALU_SFU_OP; break; case F64_TYPE: case FF64_TYPE: latency = dp_latency[2]; initiation_interval = dp_init[2]; - op = ALU_SFU_OP; + op = DP_OP; break; case B32_TYPE: case U32_TYPE: @@ -744,6 +759,7 @@ void ptx_instruction::set_opcode_and_latency() case FF64_TYPE: latency = dp_latency[3]; initiation_interval = dp_init[3]; + op = DP_OP; break; case B32_TYPE: case U32_TYPE: @@ -779,13 +795,13 @@ void ptx_instruction::set_opcode_and_latency() break; case SQRT_OP: case SIN_OP: case COS_OP: case EX2_OP: case LG2_OP: case RSQRT_OP: case RCP_OP: //Using double to approximate those - latency = dp_latency[2]; - initiation_interval = dp_init[2]; + latency = sfu_latency; + initiation_interval = sfu_init; op = SFU_OP; break; case SHFL_OP: latency = 32; - initiation_interval = 15; + initiation_interval = 4; break; default: break; diff --git a/src/gpgpu-sim/dram.cc b/src/gpgpu-sim/dram.cc index a0e024b..5c1ddab 100644 --- a/src/gpgpu-sim/dram.cc +++ b/src/gpgpu-sim/dram.cc @@ -49,11 +49,41 @@ dram_t::dram_t( unsigned int partition_id, const struct memory_config *config, m m_stats = stats; m_config = config; + //rowblp + access_num=0; + hits_num=0; + banks_1time=0; + banks_acess_total=0; + banks_acess_total_after=0; + banks_time_ready=0; + banks_access_ready_total=0; + issued_two=0; + issued_total=0; + issued_total_row=0; + issued_total_col=0; + CCDc = 0; RRDc = 0; RTWc = 0; WTRc = 0; + wasted_bw_row=0; + wasted_bw_col=0; + util_bw=0; + idle_bw=0; + RCDc_limit=0; + CCDLc_limit=0; + CCDLc_limit_alone=0; + CCDc_limit=0; + WTRc_limit=0; + WTRc_limit_alone=0; + RCDWRc_limit=0; + RTWc_limit=0; + RTWc_limit_alone=0; + rwq_limit=0; + write_to_read_ratio_blp_rw_average=0; + bkgrp_parallsim_rw=0; + rw = READ; //read mode is default bkgrp = (bankgrp_t**) calloc(sizeof(bankgrp_t*), m_config->nbkgrp); @@ -74,12 +104,13 @@ dram_t::dram_t( unsigned int partition_id, const struct memory_config *config, m bk[i]->state = BANK_IDLE; bk[i]->bkgrpindex = i/(m_config->nbk/m_config->nbkgrp); } - prio = 0; + prio = 0; + rwq = new fifo_pipeline<dram_req_t>("rwq",m_config->CL,m_config->CL+1); mrqq = new fifo_pipeline<dram_req_t>("mrqq",0,2); returnq = new fifo_pipeline<mem_fetch>("dramreturnq",0,m_config->gpgpu_dram_return_queue_size==0?1024:m_config->gpgpu_dram_return_queue_size); m_frfcfs_scheduler = NULL; - if ( m_config->scheduler_type == DRAM_FRFCFS ) + if ( m_config->scheduler_type == DRAM_FRFCFS) m_frfcfs_scheduler = new frfcfs_scheduler(m_config,this,stats); n_cmd = 0; n_activity = 0; @@ -88,6 +119,8 @@ dram_t::dram_t( unsigned int partition_id, const struct memory_config *config, m n_pre = 0; n_rd = 0; n_wr = 0; + n_wr_WB=0; + n_rd_L2_A=0; n_req = 0; max_mrqs_temp = 0; bwutil = 0; @@ -113,11 +146,12 @@ dram_t::dram_t( unsigned int partition_id, const struct memory_config *config, m 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 + } bool dram_t::full() const { - if(m_config->scheduler_type == DRAM_FRFCFS ){ + if(m_config->scheduler_type == DRAM_FRFCFS){ if(m_config->gpgpu_frfcfs_dram_sched_queue_size == 0 ) return false; return m_frfcfs_scheduler->num_pending() >= m_config->gpgpu_frfcfs_dram_sched_queue_size; } @@ -127,7 +161,7 @@ bool dram_t::full() const unsigned dram_t::que_length() const { unsigned nreqs = 0; - if (m_config->scheduler_type == DRAM_FRFCFS ) { + if (m_config->scheduler_type == DRAM_FRFCFS) { nreqs = m_frfcfs_scheduler->num_pending(); } else { nreqs = mrqq->get_length(); @@ -146,7 +180,7 @@ unsigned int dram_t::queue_limit() const } -dram_req_t::dram_req_t( class mem_fetch *mf ) +dram_req_t::dram_req_t( class mem_fetch *mf, unsigned banks, unsigned dram_bnk_indexing_policy) { txbytes = 0; dqbytes = 0; @@ -154,7 +188,16 @@ dram_req_t::dram_req_t( class mem_fetch *mf ) const addrdec_t &tlx = mf->get_tlx_addr(); - bk = tlx.bk; + if(dram_bnk_indexing_policy == 0) { + bk = tlx.bk; + } + else if(dram_bnk_indexing_policy == 1) { + int lbank = log2(banks); + bk = tlx.bk ^ (((1<<lbank)-1) & tlx.row); + } + else + assert(1); + row = tlx.row; col = tlx.col; nbytes = mf->get_data_size(); @@ -169,14 +212,15 @@ void dram_t::push( class mem_fetch *data ) { assert(id == data->get_tlx_addr().chip); // Ensure request is in correct memory partition - dram_req_t *mrq = new dram_req_t(data); + dram_req_t *mrq = new dram_req_t(data,m_config->nbk,m_config->dram_bnk_indexing_policy); + data->set_status(IN_PARTITION_MC_INTERFACE_QUEUE,gpu_sim_cycle+gpu_tot_sim_cycle); - mrqq->push(mrq); + mrqq->push(mrq); // stats... n_req += 1; n_req_partial += 1; - if ( m_config->scheduler_type == DRAM_FRFCFS ) { + if ( m_config->scheduler_type == DRAM_FRFCFS) { unsigned nreqs = m_frfcfs_scheduler->num_pending(); if ( nreqs > max_mrqs_temp) max_mrqs_temp = nreqs; @@ -212,6 +256,7 @@ void dram_t::cycle() printf("\tDQ: BK%d Row:%03x Col:%03x", cmd->bk, cmd->row, cmd->col + cmd->dqbytes); #endif cmd->dqbytes += m_config->dram_atom_size; + if (cmd->dqbytes >= cmd->nbytes) { mem_fetch *data = cmd->data; data->set_status(IN_PARTITION_MC_RETURNQ,gpu_sim_cycle+gpu_tot_sim_cycle); @@ -240,7 +285,7 @@ void dram_t::cycle() printf("Error: Unknown DRAM scheduler type\n"); assert(0); } - if ( m_config->scheduler_type == DRAM_FRFCFS ) { + if ( m_config->scheduler_type == DRAM_FRFCFS) { unsigned nreqs = m_frfcfs_scheduler->num_pending(); if ( nreqs > max_mrqs) { max_mrqs = nreqs; @@ -258,130 +303,123 @@ void dram_t::cycle() unsigned k=m_config->nbk; bool issued = false; - // check if any bank is ready to issue a new read + //collect row buffer locality, BLP and other statistics + ///////////////////////////////////////////////////////////////////////// + unsigned int memory_pending=0; for (unsigned i=0;i<m_config->nbk;i++) { - unsigned j = (i + prio) % m_config->nbk; - unsigned grp = j>>m_config->bk_tag_length; - if (bk[j]->mrq) { //if currently servicing a memory request - bk[j]->mrq->data->set_status(IN_PARTITION_DRAM,gpu_sim_cycle+gpu_tot_sim_cycle); - // correct row activated for a READ - if ( !issued && !CCDc && !bk[j]->RCDc && - !(bkgrp[grp]->CCDLc) && - (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(m_config->CL); - } - rwq->push(bk[j]->mrq); - bk[j]->mrq->txbytes += m_config->dram_atom_size; - CCDc = m_config->tCCD; - bkgrp[grp]->CCDLc = m_config->tCCDL; - RTWc = m_config->tRTW; - bk[j]->RTPc = m_config->BL/m_config->data_command_freq_ratio; - bkgrp[grp]->RTPLc = m_config->tRTPL; - issued = true; - n_rd++; - bwutil += m_config->BL/m_config->data_command_freq_ratio; - bwutil_partial += m_config->BL/m_config->data_command_freq_ratio; - bk[j]->n_access++; -#ifdef DRAM_VERIFY - PRINT_CYCLE=1; - printf("\tRD Bk:%d Row:%03x Col:%03x \n", - j, bk[j]->curr_row, - bk[j]->mrq->col + bk[j]->mrq->txbytes - m_config->dram_atom_size); -#endif - // transfer done - if ( !(bk[j]->mrq->txbytes < bk[j]->mrq->nbytes) ) { - bk[j]->mrq = NULL; - } - } else - // correct row activated for a WRITE - if ( !issued && !CCDc && !bk[j]->RCDWRc && - !(bkgrp[grp]->CCDLc) && - (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(m_config->WL); - } - rwq->push(bk[j]->mrq); + if (bk[i]->mrq) + memory_pending++; + } + banks_1time += memory_pending; + if(memory_pending >0) + banks_acess_total++; - bk[j]->mrq->txbytes += m_config->dram_atom_size; - CCDc = m_config->tCCD; - bkgrp[grp]->CCDLc = m_config->tCCDL; - WTRc = m_config->tWTR; - bk[j]->WTPc = m_config->tWTP; - issued = true; - n_wr++; - bwutil += m_config->BL/m_config->data_command_freq_ratio; - bwutil_partial += m_config->BL/m_config->data_command_freq_ratio; -#ifdef DRAM_VERIFY - PRINT_CYCLE=1; - printf("\tWR Bk:%d Row:%03x Col:%03x \n", - j, bk[j]->curr_row, - bk[j]->mrq->col + bk[j]->mrq->txbytes - m_config->dram_atom_size); -#endif - // transfer done - if ( !(bk[j]->mrq->txbytes < bk[j]->mrq->nbytes) ) { - bk[j]->mrq = NULL; - } - } + unsigned int memory_pending_rw=0; + unsigned read_blp_rw=0; + unsigned write_blp_rw=0; + std::bitset<8> bnkgrp_rw_found; //assume max we have 8 bank groups - else - // bank is idle - 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,bk[j]->mrq->row,bk[j]->curr_row); -#endif - // activate the row with current memory request - bk[j]->curr_row = bk[j]->mrq->row; - bk[j]->state = BANK_ACTIVE; - RRDc = m_config->tRRD; - bk[j]->RCDc = m_config->tRCD; - bk[j]->RCDWRc = m_config->tRCDWR; - bk[j]->RASc = m_config->tRAS; - bk[j]->RCc = m_config->tRC; - prio = (j + 1) % m_config->nbk; - issued = true; - n_act_partial++; - n_act++; - } + for (unsigned j=0;j<m_config->nbk;j++) { + unsigned grp = get_bankgrp_number(j); + if (bk[j]->mrq && (((bk[j]->curr_row == bk[j]->mrq->row) && + (bk[j]->mrq->rw == READ) && + (bk[j]->state == BANK_ACTIVE)))) + { + memory_pending_rw++; + read_blp_rw++; + bnkgrp_rw_found.set(grp); + } + else if + (bk[j]->mrq && (((bk[j]->curr_row == bk[j]->mrq->row) && + (bk[j]->mrq->rw == WRITE) && + (bk[j]->state == BANK_ACTIVE)))) + { + memory_pending_rw++; + write_blp_rw++; + bnkgrp_rw_found.set(grp); + } + } + banks_time_rw += memory_pending_rw; + bkgrp_parallsim_rw += bnkgrp_rw_found.count(); + if(memory_pending_rw >0) + { + write_to_read_ratio_blp_rw_average += (double)write_blp_rw/(write_blp_rw+read_blp_rw); + banks_access_rw_total++; + } - else - // different row activated - if ( (!issued) && - (bk[j]->curr_row != bk[j]->mrq->row) && - (bk[j]->state == BANK_ACTIVE) && - (!bk[j]->RASc && !bk[j]->WTPc && - !bk[j]->RTPc && - !bkgrp[grp]->RTPLc) ) { - // make the bank idle again - bk[j]->state = BANK_IDLE; - bk[j]->RPc = m_config->tRP; - prio = (j + 1) % m_config->nbk; - issued = true; - n_pre++; - n_pre_partial++; -#ifdef DRAM_VERIFY - PRINT_CYCLE=1; - printf("\tPRE BK:%d Row:%03x \n", j,bk[j]->curr_row); -#endif - } - } else { - if (!CCDc && !RRDc && !RTWc && !WTRc && !bk[j]->RCDc && !bk[j]->RASc - && !bk[j]->RCc && !bk[j]->RPc && !bk[j]->RCDWRc) k--; - bk[j]->n_idle++; - } + unsigned int memory_Pending_ready=0; + for (unsigned j=0;j<m_config->nbk;j++) { + unsigned grp = get_bankgrp_number(j); + if (bk[j]->mrq && ((!CCDc && !bk[j]->RCDc && + !(bkgrp[grp]->CCDLc) && + (bk[j]->curr_row == bk[j]->mrq->row) && + (bk[j]->mrq->rw == READ) && (WTRc == 0 ) && + (bk[j]->state == BANK_ACTIVE) && + !rwq->full()) + || + (!CCDc && !bk[j]->RCDWRc && + !(bkgrp[grp]->CCDLc) && + (bk[j]->curr_row == bk[j]->mrq->row) && + (bk[j]->mrq->rw == WRITE) && (RTWc == 0 ) && + (bk[j]->state == BANK_ACTIVE) && + !rwq->full()))) + { + memory_Pending_ready++; + } } + banks_time_ready += memory_Pending_ready; + if(memory_Pending_ready >0) + banks_access_ready_total++; + /////////////////////////////////////////////////////////////////////////////////// + + bool issued_col_cmd = false; + bool issued_row_cmd = false; + + if(m_config->dual_bus_interface) + { + //dual bus interface + //issue one row command and one column command + for (unsigned i=0;i<m_config->nbk;i++) { + unsigned j = (i + prio) % m_config->nbk; + issued_col_cmd = issue_col_command(j); + if(issued_col_cmd) break; + } + for (unsigned i=0;i<m_config->nbk;i++) { + unsigned j = (i + prio) % m_config->nbk; + issued_row_cmd = issue_row_command(j); + if(issued_row_cmd) break; + } + for (unsigned i=0;i<m_config->nbk;i++) { + unsigned j = (i + prio) % m_config->nbk; + if(!bk[j]->mrq) { + if (!CCDc && !RRDc && !RTWc && !WTRc && !bk[j]->RCDc && !bk[j]->RASc + && !bk[j]->RCc && !bk[j]->RPc && !bk[j]->RCDWRc) k--; + bk[j]->n_idle++; + } + } + } + else + { + //single bus interface + //issue only one row/column command + for (unsigned i=0;i<m_config->nbk;i++) { + unsigned j = (i + prio) % m_config->nbk; + if(!issued_col_cmd) + issued_col_cmd = issue_col_command(j); + + if(!issued_col_cmd && !issued_row_cmd) + issued_row_cmd = issue_row_command(j); + + if(!bk[j]->mrq) { + if (!CCDc && !RRDc && !RTWc && !WTRc && !bk[j]->RCDc && !bk[j]->RASc + && !bk[j]->RCc && !bk[j]->RPc && !bk[j]->RCDWRc) k--; + bk[j]->n_idle++; + } + + } + } + + issued = issued_row_cmd || issued_col_cmd; if (!issued) { n_nop++; n_nop_partial++; @@ -395,6 +433,85 @@ void dram_t::cycle() } n_cmd++; n_cmd_partial++; + if(issued) + { + issued_total++; + if(issued_col_cmd && issued_row_cmd) + issued_two++; + } + if(issued_col_cmd) issued_total_col++; + if(issued_row_cmd) issued_total_row++; + + + //Collect some statistics + //check the limitation, see where BW is wasted? + ///////////////////////////////////////////////////////// + unsigned int memory_pending_found=0; + for (unsigned i=0;i<m_config->nbk;i++) { + if (bk[i]->mrq) + memory_pending_found++; + } + if(memory_pending_found>0) + banks_acess_total_after++; + + bool memory_pending_rw_found=false; + for (unsigned j=0;j<m_config->nbk;j++) { + unsigned grp = get_bankgrp_number(j); + if (bk[j]->mrq && (((bk[j]->curr_row == bk[j]->mrq->row) && + (bk[j]->mrq->rw == READ) && + (bk[j]->state == BANK_ACTIVE)) + || + ( + (bk[j]->curr_row == bk[j]->mrq->row) && + (bk[j]->mrq->rw == WRITE) && + (bk[j]->state == BANK_ACTIVE)))) + memory_pending_rw_found=true; + } + + + if(issued_col_cmd || CCDc) + util_bw++; + else if (memory_pending_rw_found) + { + wasted_bw_col++; + for (unsigned j=0;j<m_config->nbk;j++) { + unsigned grp = get_bankgrp_number(j); + //read + if (bk[j]->mrq && (((bk[j]->curr_row == bk[j]->mrq->row) && + (bk[j]->mrq->rw == READ) && + (bk[j]->state == BANK_ACTIVE)))) + { + if(bk[j]->RCDc) RCDc_limit++; + if(bkgrp[grp]->CCDLc) CCDLc_limit++; + if(WTRc) WTRc_limit++; + if(CCDc) CCDc_limit++; + if(rwq->full()) rwq_limit++; + if(bkgrp[grp]->CCDLc && !WTRc) CCDLc_limit_alone++; + if(!bkgrp[grp]->CCDLc && WTRc) WTRc_limit_alone++; + } + //write + else if (bk[j]->mrq && ((bk[j]->curr_row == bk[j]->mrq->row) && + (bk[j]->mrq->rw == WRITE) && + (bk[j]->state == BANK_ACTIVE))) + { + if(bk[j]->RCDWRc) RCDWRc_limit++; + if(bkgrp[grp]->CCDLc) CCDLc_limit++; + if(RTWc) RTWc_limit++; + if(CCDc) CCDc_limit++; + if(rwq->full()) rwq_limit++; + if(bkgrp[grp]->CCDLc && !RTWc) CCDLc_limit_alone++; + if(!bkgrp[grp]->CCDLc && RTWc) RTWc_limit_alone++; + } + } + } + else if (memory_pending_found) + wasted_bw_row++; + else if (!memory_pending_found) + idle_bw++; + else + assert(1); + + ///////////////////////////////////////////////////////// // decrements counters once for each time dram_issueCMD is called DEC2ZERO(RRDc); @@ -420,26 +537,169 @@ void dram_t::cycle() #endif } +bool dram_t::issue_col_command(int j) +{ + bool issued = false; + unsigned grp = get_bankgrp_number(j); + if (bk[j]->mrq) { //if currently servicing a memory request + bk[j]->mrq->data->set_status(IN_PARTITION_DRAM,gpu_sim_cycle+gpu_tot_sim_cycle); + // correct row activated for a READ + if ( !issued && !CCDc && !bk[j]->RCDc && + !(bkgrp[grp]->CCDLc) && + (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(m_config->CL); + } + rwq->push(bk[j]->mrq); + bk[j]->mrq->txbytes += m_config->dram_atom_size; + CCDc = m_config->tCCD; + bkgrp[grp]->CCDLc = m_config->tCCDL; + RTWc = m_config->tRTW; + bk[j]->RTPc = m_config->BL/m_config->data_command_freq_ratio; + bkgrp[grp]->RTPLc = m_config->tRTPL; + issued = true; + if(bk[j]->mrq->data->get_access_type() == L2_WR_ALLOC_R) + n_rd_L2_A++; + else + n_rd++; + bwutil += m_config->BL/m_config->data_command_freq_ratio; + bwutil_partial += m_config->BL/m_config->data_command_freq_ratio; + bk[j]->n_access++; + +#ifdef DRAM_VERIFY + PRINT_CYCLE=1; + printf("\tRD Bk:%d Row:%03x Col:%03x \n", + j, bk[j]->curr_row, + bk[j]->mrq->col + bk[j]->mrq->txbytes - m_config->dram_atom_size); +#endif + // transfer done + if ( !(bk[j]->mrq->txbytes < bk[j]->mrq->nbytes) ) { + bk[j]->mrq = NULL; + } + } else + // correct row activated for a WRITE + if ( !issued && !CCDc && !bk[j]->RCDWRc && + !(bkgrp[grp]->CCDLc) && + (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(m_config->WL); + } + rwq->push(bk[j]->mrq); + + bk[j]->mrq->txbytes += m_config->dram_atom_size; + CCDc = m_config->tCCD; + bkgrp[grp]->CCDLc = m_config->tCCDL; + WTRc = m_config->tWTR; + bk[j]->WTPc = m_config->tWTP; + issued = true; + + if(bk[j]->mrq->data->get_access_type() == L2_WRBK_ACC) + n_wr_WB++; + else + n_wr++; + bwutil += m_config->BL/m_config->data_command_freq_ratio; + bwutil_partial += m_config->BL/m_config->data_command_freq_ratio; +#ifdef DRAM_VERIFY + PRINT_CYCLE=1; + printf("\tWR Bk:%d Row:%03x Col:%03x \n", + j, bk[j]->curr_row, + bk[j]->mrq->col + bk[j]->mrq->txbytes - m_config->dram_atom_size); +#endif + // transfer done + if ( !(bk[j]->mrq->txbytes < bk[j]->mrq->nbytes) ) { + bk[j]->mrq = NULL; + } + } + + } + + return issued; +} + +bool dram_t::issue_row_command(int j) +{ + bool issued = false; + unsigned grp = get_bankgrp_number(j); + if (bk[j]->mrq) { //if currently servicing a memory request + bk[j]->mrq->data->set_status(IN_PARTITION_DRAM,gpu_sim_cycle+gpu_tot_sim_cycle); + // bank is idle + //else + 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,bk[j]->mrq->row,bk[j]->curr_row); +#endif + // activate the row with current memory request + bk[j]->curr_row = bk[j]->mrq->row; + bk[j]->state = BANK_ACTIVE; + RRDc = m_config->tRRD; + bk[j]->RCDc = m_config->tRCD; + bk[j]->RCDWRc = m_config->tRCDWR; + bk[j]->RASc = m_config->tRAS; + bk[j]->RCc = m_config->tRC; + prio = (j + 1) % m_config->nbk; + issued = true; + n_act_partial++; + n_act++; + } + + else + // different row activated + if ( (!issued) && + (bk[j]->curr_row != bk[j]->mrq->row) && + (bk[j]->state == BANK_ACTIVE) && + (!bk[j]->RASc && !bk[j]->WTPc && + !bk[j]->RTPc && + !bkgrp[grp]->RTPLc) ) { + // make the bank idle again + bk[j]->state = BANK_IDLE; + bk[j]->RPc = m_config->tRP; + prio = (j + 1) % m_config->nbk; + issued = true; + n_pre++; + n_pre_partial++; +#ifdef DRAM_VERIFY + PRINT_CYCLE=1; + printf("\tPRE BK:%d Row:%03x \n", j,bk[j]->curr_row); +#endif + } + } + return issued; +} + + //if mrq is being serviced by dram, gets popped after CL latency fulfilled -class mem_fetch* dram_t::return_queue_pop() +class mem_fetch* dram_t::return_queue_pop() { return returnq->pop(); } -class mem_fetch* dram_t::return_queue_top() +class mem_fetch* dram_t::return_queue_top() { return returnq->top(); } + void dram_t::print( FILE* simFile) const { unsigned i; fprintf(simFile,"DRAM[%d]: %d bks, busW=%d BL=%d CL=%d, ", id, m_config->nbk, m_config->busW, m_config->BL, m_config->CL ); fprintf(simFile,"tRRD=%d tCCD=%d, tRCD=%d tRAS=%d tRP=%d tRC=%d\n", - m_config->tCCD, m_config->tRRD, m_config->tRCD, m_config->tRAS, m_config->tRP, m_config->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", - n_cmd, n_nop, n_act, n_pre, n_req, n_rd, n_wr, + m_config->tRRD, m_config->tCCD, m_config->tRCD, m_config->tRAS, m_config->tRP, m_config->tRC ); + fprintf(simFile,"n_cmd=%d n_nop=%d n_act=%d n_pre=%d n_ref_event=%d n_req=%d n_rd=%d n_rd_L2_A=%d n_write=%d n_wr_bk=%d bw_util=%.4g\n", + n_cmd, n_nop, n_act, n_pre, n_ref, n_req, n_rd, n_rd_L2_A, n_wr, n_wr_WB, (float)bwutil/n_cmd); fprintf(simFile,"n_activity=%d dram_eff=%.4g\n", n_activity, (float)bwutil/n_activity); @@ -447,12 +707,61 @@ void dram_t::print( FILE* simFile) const fprintf(simFile, "bk%d: %da %di ",i,bk[i]->n_access,bk[i]->n_idle); } fprintf(simFile, "\n"); + fprintf(simFile, "\n------------------------------------------------------------------------\n"); + + printf("\nRow_Buffer_Locality = %.6f", (float)hits_num / access_num); + printf("\nBank_Level_Parallism = %.6f", (float)banks_1time / banks_acess_total); + printf("\nBank_Level_Parallism_Col = %.6f", (float)banks_time_rw / banks_access_rw_total); + printf("\nBank_Level_Parallism_Ready = %.6f", (float)banks_time_ready /banks_access_ready_total); + printf("\nwrite_to_read_ratio_blp_rw_average = %.6f", write_to_read_ratio_blp_rw_average /banks_access_rw_total); + printf("\nGrpLevelPara = %.6f \n", (float)bkgrp_parallsim_rw /banks_access_rw_total); + + printf("\nbwutil = %.6f \n", (float)bwutil/n_cmd); + printf("total_CMD = %d \n", n_cmd); + printf("util_bw = %d \n", util_bw); + printf("Wasted_Col = %d \n", wasted_bw_col); + printf("Wasted_Row %d \n", wasted_bw_row); + printf("Idle = %d \n\n", idle_bw); + + printf("RCDc_limit = %d \n", RCDc_limit); + printf("RCDWRc_limit = %d \n", RCDWRc_limit); + printf("WTRc_limit = %d \n", WTRc_limit); + printf("RTWc_limit = %d \n", RTWc_limit); + printf("CCDLc_limit %d \n", CCDLc_limit); + printf("rwq = %d \n", rwq_limit); + printf("CCDLc_limit_alone = %d \n", CCDLc_limit_alone); + printf("WTRc_limit_alone = %d \n", WTRc_limit_alone); + printf("RTWc_limit_alone = %d \n", RTWc_limit_alone); + + printf("total_CMD = %d \n", n_cmd); + printf("n_nop = %d \n", n_nop); + printf("Read = %d \n", n_rd); + printf("Write = %d \n",n_wr); + printf("L2_Alloc = %d \n", n_rd_L2_A); + printf("L2_WB = %d \n", n_wr_WB); + printf("n_act = %d \n", n_act); + printf("n_pre = %d \n", n_pre); + printf("n_ref = %d \n", n_ref); + printf("n_req = %d \n", n_req ); + printf("n_req4 = %d \n", n_req*4 ); + printf("total_req = %d \n\n", n_rd+n_wr+n_rd_L2_A+n_wr_WB); + + printf("issued_total_row = %lu \n", issued_total_row); + printf("issued_total_col = %lu \n", issued_total_col); + printf("Row_Bus_Util = %.6f \n", (float)issued_total_row / n_cmd); + printf("CoL_Bus_Util = %.6f \n", (float)issued_total_col / n_cmd); + printf("Either_Row_CoL_Bus_Util %.6f \n", (float)issued_total / n_cmd); + printf("Issued_on_Two_Bus_Simul_Util %.6f \n", (float)issued_two /n_cmd); + printf("issued_two_Eff = %.6f \n", (float)issued_two /issued_total); + printf("queue_avg = %.6f \n\n", (float)ave_mrqs/n_cmd ); + + fprintf(simFile, "\n"); fprintf(simFile, "dram_util_bins:"); 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", dram_eff_bins[i]); fprintf(simFile, "\n"); - if(m_config->scheduler_type== DRAM_FRFCFS) + if(m_config->scheduler_type== DRAM_FRFCFS) fprintf(simFile, "mrqq: max=%d avg=%g\n", max_mrqs, (float)ave_mrqs/n_cmd); } @@ -476,8 +785,8 @@ void dram_t::visualize() const void dram_t::print_stat( FILE* simFile ) { - 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 ", - id, n_cmd, n_nop, n_act, n_pre, n_req, n_rd, n_wr, + fprintf(simFile,"DRAM (%d): n_cmd=%d n_nop=%d n_act=%d n_pre=%d n_ref=%d n_req=%d n_rd=%d n_write=%d bw_util=%.4g ", + id, n_cmd, n_nop, n_act, n_pre, n_ref, 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"); @@ -516,6 +825,7 @@ void dram_t::visualizer_print( gzFile visualizer_file ) n_pre_partial = 0; n_req_partial = 0; + // dram access type classification for (unsigned j = 0; j < m_config->nbk; j++) { gzprintf(visualizer_file,"dramglobal_acc_r: %u %u %u\n", id, j, @@ -553,3 +863,16 @@ void dram_t::set_dram_power_stats( unsigned &cmd, wr = n_wr; req = n_req; } + +unsigned dram_t::get_bankgrp_number(unsigned i) +{ + if(m_config->dram_bnkgrp_indexing_policy == 0) { //higher bits + return i>>m_config->bk_tag_length; + } + else if (m_config->dram_bnkgrp_indexing_policy == 1) { //lower bits + return i&((m_config->nbkgrp-1)); + } + else { + assert(1); + } +} diff --git a/src/gpgpu-sim/dram.h b/src/gpgpu-sim/dram.h index a8bff14..331b4f1 100644 --- a/src/gpgpu-sim/dram.h +++ b/src/gpgpu-sim/dram.h @@ -31,9 +31,15 @@ #include "delayqueue.h" #include <set> +#include <vector> +#include <bitset> +#include <sstream> +#include <string> +#include <fstream> #include <zlib.h> #include <stdio.h> #include <stdlib.h> +#include<iomanip> #define READ 'R' //define read and write states #define WRITE 'W' @@ -42,7 +48,7 @@ class dram_req_t { public: - dram_req_t( class mem_fetch *data ); + dram_req_t( class mem_fetch *data , unsigned banks, unsigned dram_bnk_indexing_policy); unsigned int row; unsigned int col; @@ -106,6 +112,7 @@ public: class mem_fetch* return_queue_pop(); class mem_fetch* return_queue_top(); + void push( class mem_fetch *data ); void cycle(); void dram_log (int task); @@ -123,17 +130,24 @@ public: unsigned &wr, unsigned &req) const; -private: - void scheduler_fifo(); - void scheduler_frfcfs(); + const struct memory_config *m_config; +private: bankgrp_t **bkgrp; bank_t **bk; unsigned int prio; + unsigned get_bankgrp_number(unsigned i); + + void scheduler_fifo(); + void scheduler_frfcfs(); + + bool issue_col_command(int j); + bool issue_row_command(int j); + unsigned int RRDc; unsigned int CCDc; unsigned int RTWc; //read to write penalty applies across banks @@ -146,7 +160,7 @@ private: fifo_pipeline<dram_req_t> *rwq; fifo_pipeline<dram_req_t> *mrqq; //buffer to hold packets when DRAM processing is over - //should be filled with dram clock and popped with l2or icnt clock + //should be filled with dram clock and popped with l2or icnt clock fifo_pipeline<mem_fetch> *returnq; unsigned int dram_util_bins[10]; @@ -158,11 +172,47 @@ private: unsigned int n_nop; unsigned int n_act; unsigned int n_pre; + unsigned int n_ref; unsigned int n_rd; + unsigned int n_rd_L2_A; unsigned int n_wr; + unsigned int n_wr_WB; unsigned int n_req; unsigned int max_mrqs_temp; + //some statistics to collect to see where BW is wasted? + unsigned wasted_bw_row; + unsigned wasted_bw_col; + unsigned util_bw; + unsigned idle_bw; + unsigned RCDc_limit; + unsigned CCDLc_limit; + unsigned CCDLc_limit_alone; + unsigned CCDc_limit; + unsigned WTRc_limit; + unsigned WTRc_limit_alone; + unsigned RCDWRc_limit; + unsigned RTWc_limit; + unsigned RTWc_limit_alone; + unsigned rwq_limit; + + //row locality, BLP and other statistics + unsigned long access_num; + unsigned long long hits_num; + unsigned long long banks_1time; + unsigned long long banks_acess_total; + unsigned long long banks_acess_total_after; + unsigned long long banks_time_rw; + unsigned long long banks_access_rw_total; + unsigned long long banks_time_ready; + unsigned long long banks_access_ready_total; + unsigned long long issued_two; + unsigned long long issued_total; + unsigned long long issued_total_row; + unsigned long long issued_total_col; + double write_to_read_ratio_blp_rw_average; + unsigned long long bkgrp_parallsim_rw; + unsigned int bwutil; unsigned int max_mrqs; unsigned int ave_mrqs; diff --git a/src/gpgpu-sim/dram_sched.cc b/src/gpgpu-sim/dram_sched.cc index 8303e86..008b5bb 100644 --- a/src/gpgpu-sim/dram_sched.cc +++ b/src/gpgpu-sim/dram_sched.cc @@ -78,6 +78,9 @@ void frfcfs_scheduler::data_collection(unsigned int bank) dram_req_t *frfcfs_scheduler::schedule( unsigned bank, unsigned curr_row ) { + //row + bool rowhit = true; + if ( m_last_row[bank] == NULL ) { if ( m_queue[bank].empty() ) return NULL; @@ -89,11 +92,17 @@ dram_req_t *frfcfs_scheduler::schedule( unsigned bank, unsigned curr_row ) assert( bin_ptr != m_bins[bank].end() ); // where did the request go??? m_last_row[bank] = &(bin_ptr->second); data_collection(bank); + rowhit = false; } else { m_last_row[bank] = &(bin_ptr->second); - + rowhit = true; } } + //rowblp + m_dram->access_num++; + if(rowhit) + m_dram->hits_num++; + std::list<dram_req_t*>::iterator next = m_last_row[bank]->back(); dram_req_t *req = (*next); diff --git a/src/gpgpu-sim/gpu-sim.cc b/src/gpgpu-sim/gpu-sim.cc index 483a7b6..b424d2c 100644 --- a/src/gpgpu-sim/gpu-sim.cc +++ b/src/gpgpu-sim/gpu-sim.cc @@ -192,6 +192,15 @@ void memory_config::reg_options(class OptionParser * opp) option_parser_register(opp, "-dram_latency", OPT_UINT32, &dram_latency, "DRAM latency (default 30)", "30"); + option_parser_register(opp, "-dual_bus_interface", OPT_UINT32, &dual_bus_interface, + "dual_bus_interface (default = 0) ", + "0"); + option_parser_register(opp, "-dram_bnk_indexing_policy", OPT_UINT32, &dram_bnk_indexing_policy, + "dram_bnk_indexing_policy (0 = normal indexing, 1 = Xoring with the higher bits) (Default = 0)", + "0"); + option_parser_register(opp, "-dram_bnkgrp_indexing_policy", OPT_UINT32, &dram_bnkgrp_indexing_policy, + "dram_bnkgrp_indexing_policy (0 = take higher bits, 1 = take lower bits) (Default = 0)", + "0"); m_address_mapping.addrdec_setoption(opp); } @@ -312,6 +321,9 @@ void shader_core_config::reg_options(class OptionParser * opp) option_parser_register(opp, "-gpgpu_operand_collector_num_units_sp", OPT_INT32, &gpgpu_operand_collector_num_units_sp, "number of collector units (default = 4)", "4"); + option_parser_register(opp, "-gpgpu_operand_collector_num_units_dp", OPT_INT32, &gpgpu_operand_collector_num_units_dp, + "number of collector units (default = 0)", + "0"); option_parser_register(opp, "-gpgpu_operand_collector_num_units_sfu", OPT_INT32, &gpgpu_operand_collector_num_units_sfu, "number of collector units (default = 4)", "4"); @@ -324,6 +336,9 @@ void shader_core_config::reg_options(class OptionParser * opp) option_parser_register(opp, "-gpgpu_operand_collector_num_in_ports_sp", OPT_INT32, &gpgpu_operand_collector_num_in_ports_sp, "number of collector unit in ports (default = 1)", "1"); + option_parser_register(opp, "-gpgpu_operand_collector_num_in_ports_dp", OPT_INT32, &gpgpu_operand_collector_num_in_ports_dp, + "number of collector unit in ports (default = 0)", + "0"); option_parser_register(opp, "-gpgpu_operand_collector_num_in_ports_sfu", OPT_INT32, &gpgpu_operand_collector_num_in_ports_sfu, "number of collector unit in ports (default = 1)", "1"); @@ -336,6 +351,9 @@ void shader_core_config::reg_options(class OptionParser * opp) option_parser_register(opp, "-gpgpu_operand_collector_num_out_ports_sp", OPT_INT32, &gpgpu_operand_collector_num_out_ports_sp, "number of collector unit in ports (default = 1)", "1"); + option_parser_register(opp, "-gpgpu_operand_collector_num_out_ports_dp", OPT_INT32, &gpgpu_operand_collector_num_out_ports_dp, + "number of collector unit in ports (default = 0)", + "0"); option_parser_register(opp, "-gpgpu_operand_collector_num_out_ports_sfu", OPT_INT32, &gpgpu_operand_collector_num_out_ports_sfu, "number of collector unit in ports (default = 1)", "1"); @@ -355,18 +373,21 @@ void shader_core_config::reg_options(class OptionParser * opp) "Max number of instructions that can be issued per warp in one cycle by scheduler (either 1 or 2)", "2"); option_parser_register(opp, "-gpgpu_dual_issue_diff_exec_units", OPT_BOOL, &gpgpu_dual_issue_diff_exec_units, - "should dual issue use two different execution unit resources", + "should dual issue use two different execution unit resources (Default = 1)", "1"); option_parser_register(opp, "-gpgpu_simt_core_sim_order", OPT_INT32, &simt_core_sim_order, "Select the simulation order of cores in a cluster (0=Fix, 1=Round-Robin)", "1"); option_parser_register(opp, "-gpgpu_pipeline_widths", OPT_CSTR, &pipeline_widths_string, "Pipeline widths " - "ID_OC_SP,ID_OC_SFU,ID_OC_MEM,OC_EX_SP,OC_EX_SFU,OC_EX_MEM,EX_WB", - "1,1,1,1,1,1,1" ); + "ID_OC_SP,ID_OC_DP,ID_OC_SFU,ID_OC_MEM,OC_EX_SP,OC_EX_DP,OC_EX_SFU,OC_EX_MEM,EX_WB", + "1,1,1,1,1,1,1,1,1" ); option_parser_register(opp, "-gpgpu_num_sp_units", OPT_INT32, &gpgpu_num_sp_units, "Number of SP units (default=1)", "1"); + option_parser_register(opp, "-gpgpu_num_dp_units", OPT_INT32, &gpgpu_num_dp_units, + "Number of DP units (default=0)", + "0"); option_parser_register(opp, "-gpgpu_num_sfu_units", OPT_INT32, &gpgpu_num_sfu_units, "Number of SF units (default=1)", "1"); diff --git a/src/gpgpu-sim/gpu-sim.h b/src/gpgpu-sim/gpu-sim.h index 7d92c66..f379a17 100644 --- a/src/gpgpu-sim/gpu-sim.h +++ b/src/gpgpu-sim/gpu-sim.h @@ -270,6 +270,10 @@ struct memory_config { linear_to_raw_address_translation m_address_mapping; unsigned icnt_flit_size; + + unsigned dram_bnk_indexing_policy; + unsigned dram_bnkgrp_indexing_policy; + bool dual_bus_interface; }; // global counters and flags (please try not to add to this list!!!) diff --git a/src/gpgpu-sim/shader.cc b/src/gpgpu-sim/shader.cc index bb2cf0e..5547a18 100644 --- a/src/gpgpu-sim/shader.cc +++ b/src/gpgpu-sim/shader.cc @@ -150,6 +150,7 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, m_simt_stack, &m_warp, &m_pipeline_reg[ID_OC_SP], + &m_pipeline_reg[ID_OC_DP], &m_pipeline_reg[ID_OC_SFU], &m_pipeline_reg[ID_OC_MEM], i @@ -164,6 +165,7 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, m_simt_stack, &m_warp, &m_pipeline_reg[ID_OC_SP], + &m_pipeline_reg[ID_OC_DP], &m_pipeline_reg[ID_OC_SFU], &m_pipeline_reg[ID_OC_MEM], i, @@ -179,6 +181,7 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, m_simt_stack, &m_warp, &m_pipeline_reg[ID_OC_SP], + &m_pipeline_reg[ID_OC_DP], &m_pipeline_reg[ID_OC_SFU], &m_pipeline_reg[ID_OC_MEM], i @@ -193,6 +196,7 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, m_simt_stack, &m_warp, &m_pipeline_reg[ID_OC_SP], + &m_pipeline_reg[ID_OC_DP], &m_pipeline_reg[ID_OC_SFU], &m_pipeline_reg[ID_OC_MEM], i @@ -207,6 +211,7 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, m_simt_stack, &m_warp, &m_pipeline_reg[ID_OC_SP], + &m_pipeline_reg[ID_OC_DP], &m_pipeline_reg[ID_OC_SFU], &m_pipeline_reg[ID_OC_MEM], i, @@ -228,8 +233,9 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, } //op collector configuration - enum { SP_CUS, SFU_CUS, MEM_CUS, GEN_CUS }; + enum { SP_CUS, DP_CUS, SFU_CUS, MEM_CUS, GEN_CUS }; m_operand_collector.add_cu_set(SP_CUS, m_config->gpgpu_operand_collector_num_units_sp, m_config->gpgpu_operand_collector_num_out_ports_sp); + m_operand_collector.add_cu_set(DP_CUS, m_config->gpgpu_operand_collector_num_units_sp, m_config->gpgpu_operand_collector_num_out_ports_dp); m_operand_collector.add_cu_set(SFU_CUS, m_config->gpgpu_operand_collector_num_units_sfu, m_config->gpgpu_operand_collector_num_out_ports_sfu); m_operand_collector.add_cu_set(MEM_CUS, m_config->gpgpu_operand_collector_num_units_mem, m_config->gpgpu_operand_collector_num_out_ports_mem); m_operand_collector.add_cu_set(GEN_CUS, m_config->gpgpu_operand_collector_num_units_gen, m_config->gpgpu_operand_collector_num_out_ports_gen); @@ -246,6 +252,15 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, in_ports.clear(),out_ports.clear(),cu_sets.clear(); } + for (unsigned i = 0; i < m_config->gpgpu_operand_collector_num_in_ports_dp; i++) { + in_ports.push_back(&m_pipeline_reg[ID_OC_DP]); + out_ports.push_back(&m_pipeline_reg[OC_EX_DP]); + cu_sets.push_back((unsigned)DP_CUS); + cu_sets.push_back((unsigned)GEN_CUS); + m_operand_collector.add_port(in_ports,out_ports,cu_sets); + in_ports.clear(),out_ports.clear(),cu_sets.clear(); + } + for (unsigned i = 0; i < m_config->gpgpu_operand_collector_num_in_ports_sfu; i++) { in_ports.push_back(&m_pipeline_reg[ID_OC_SFU]); out_ports.push_back(&m_pipeline_reg[OC_EX_SFU]); @@ -280,7 +295,7 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, m_operand_collector.init( m_config->gpgpu_num_reg_banks, this ); // execute - m_num_function_units = m_config->gpgpu_num_sp_units + m_config->gpgpu_num_sfu_units + 1; // sp_unit, sfu, ldst_unit + m_num_function_units = m_config->gpgpu_num_sp_units + m_config->gpgpu_num_dp_units + m_config->gpgpu_num_sfu_units + 1; // sp_unit, sfu, ldst_unit //m_dispatch_port = new enum pipeline_stage_name_t[ m_num_function_units ]; //m_issue_port = new enum pipeline_stage_name_t[ m_num_function_units ]; @@ -292,12 +307,18 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, m_issue_port.push_back(OC_EX_SP); } + for (int k = 0; k < m_config->gpgpu_num_dp_units; k++) { + m_fu.push_back(new dp_unit( &m_pipeline_reg[EX_WB], m_config, this )); + m_dispatch_port.push_back(ID_OC_DP); + m_issue_port.push_back(OC_EX_DP); + } + for (int k = 0; k < m_config->gpgpu_num_sfu_units; k++) { m_fu.push_back(new sfu( &m_pipeline_reg[EX_WB], m_config, this )); m_dispatch_port.push_back(ID_OC_SFU); m_issue_port.push_back(OC_EX_SFU); } - + m_ldst_unit = new ldst_unit( m_icnt, m_mem_fetch_allocator, this, &m_operand_collector, m_scoreboard, config, mem_config, stats, shader_id, tpc_id ); m_fu.push_back(m_ldst_unit); m_dispatch_port.push_back(ID_OC_MEM); @@ -754,7 +775,7 @@ void shader_core_ctx::issue(){ unsigned j; for (unsigned i = 0; i < schedulers.size(); i++) { j = (Issue_Prio + i) % schedulers.size(); - schedulers[j]->cycle(); + schedulers[j]->cycle(); } Issue_Prio = (Issue_Prio+1)% schedulers.size(); @@ -879,6 +900,7 @@ void scheduler_unit::cycle() exec_unit_type_t previous_issued_inst_exec_type = exec_unit_type_t::NONE; unsigned max_issue = m_shader->m_config->gpgpu_max_insn_issue_per_warp; bool diff_exec_units = m_shader->m_config->gpgpu_dual_issue_diff_exec_units; + while( !warp(warp_id).waiting() && !warp(warp_id).ibuffer_empty() && (checked < max_issue) && (checked <= issued) && (issued < max_issue) ) { const warp_inst_t *pI = warp(warp_id).ibuffer_next_inst(); //Jin: handle cdp latency; @@ -920,9 +942,11 @@ void scheduler_unit::cycle() previous_issued_inst_exec_type = exec_unit_type_t::MEM; } } else { + bool sp_pipe_avail = m_sp_out->has_free(); bool sfu_pipe_avail = m_sfu_out->has_free(); - if( sp_pipe_avail && (pI->op != SFU_OP) && (!diff_exec_units || previous_issued_inst_exec_type != exec_unit_type_t::SP)) { + bool dp_pipe_avail = m_dp_out->has_free(); + if( sp_pipe_avail && (pI->op != SFU_OP && pI->op != DP_OP) && (!diff_exec_units || previous_issued_inst_exec_type != exec_unit_type_t::SP)) { //Jin: special for CDP api if(pI->m_is_cdp && !warp(warp_id).m_cdp_dummy) { @@ -948,7 +972,17 @@ void scheduler_unit::cycle() issued_inst=true; warp_inst_issued = true; previous_issued_inst_exec_type = exec_unit_type_t::SP; - } else if ( (pI->op == SFU_OP) || (pI->op == ALU_SFU_OP) && (!diff_exec_units || previous_issued_inst_exec_type != exec_unit_type_t::SFU)) { + } else if ( (m_shader->m_config->gpgpu_num_dp_units != 0) && (pI->op == DP_OP) && (!diff_exec_units || previous_issued_inst_exec_type != exec_unit_type_t::DP)) { + if( dp_pipe_avail ) { + m_shader->issue_warp(*m_dp_out,pI,active_mask,warp_id); + issued++; + issued_inst=true; + warp_inst_issued = true; + previous_issued_inst_exec_type = exec_unit_type_t::DP; + std::cout<<"DP inst is issued"<<std::endl; + } + } //If the DP units = 0 (like in Fermi archi), then change DP inst to SFU inst + else if ( ((m_shader->m_config->gpgpu_num_dp_units == 0 && pI->op == DP_OP) || (pI->op == SFU_OP) || (pI->op == ALU_SFU_OP)) && (!diff_exec_units || previous_issued_inst_exec_type != exec_unit_type_t::SFU)) { if( sfu_pipe_avail ) { m_shader->issue_warp(*m_sfu_out,pI,active_mask,warp_id); issued++; @@ -1139,11 +1173,12 @@ swl_scheduler::swl_scheduler ( shader_core_stats* stats, shader_core_ctx* shader Scoreboard* scoreboard, simt_stack** simt, std::vector<shd_warp_t>* warp, register_set* sp_out, + register_set* dp_out, register_set* sfu_out, register_set* mem_out, int id, char* config_string ) - : scheduler_unit ( stats, shader, scoreboard, simt, warp, sp_out, sfu_out, mem_out, id ) + : scheduler_unit ( stats, shader, scoreboard, simt, warp, sp_out, dp_out, sfu_out, mem_out, id ) { unsigned m_prioritization_readin; int ret = sscanf( config_string, @@ -1588,6 +1623,13 @@ void sp_unit::active_lanes_in_pipeline(){ m_core->incfuactivelanes_stat(active_count); m_core->incfumemactivelanes_stat(active_count); } +void dp_unit::active_lanes_in_pipeline(){ + unsigned active_count=pipelined_simd_unit::get_active_lanes_in_pipeline(); + assert(active_count<=m_core->get_config()->warp_size); + m_core->incspactivelanes_stat(active_count); + m_core->incfuactivelanes_stat(active_count); + m_core->incfumemactivelanes_stat(active_count); +} void sfu::active_lanes_in_pipeline(){ unsigned active_count=pipelined_simd_unit::get_active_lanes_in_pipeline(); @@ -1603,6 +1645,12 @@ sp_unit::sp_unit( register_set* result_port, const shader_core_config *config,sh m_name = "SP "; } +dp_unit::dp_unit( register_set* result_port, const shader_core_config *config,shader_core_ctx *core) + : pipelined_simd_unit(result_port,config,config->max_sfu_latency,core) +{ + m_name = "DP "; +} + void sp_unit :: issue(register_set& source_reg) { warp_inst_t** ready_reg = source_reg.get_ready(); @@ -1612,6 +1660,14 @@ void sp_unit :: issue(register_set& source_reg) pipelined_simd_unit::issue(source_reg); } +void dp_unit :: issue(register_set& source_reg) +{ + warp_inst_t** ready_reg = source_reg.get_ready(); + //m_core->incexecstat((*ready_reg)); + (*ready_reg)->op_pipe=DP__OP; + m_core->incsp_stat(m_core->get_config()->warp_size,(*ready_reg)->latency); + pipelined_simd_unit::issue(source_reg); +} pipelined_simd_unit::pipelined_simd_unit( register_set* result_port, const shader_core_config *config, unsigned max_latency,shader_core_ctx *core ) : simd_function_unit(config) diff --git a/src/gpgpu-sim/shader.h b/src/gpgpu-sim/shader.h index 2fed420..544d8d8 100644 --- a/src/gpgpu-sim/shader.h +++ b/src/gpgpu-sim/shader.h @@ -326,12 +326,13 @@ public: Scoreboard* scoreboard, simt_stack** simt, std::vector<shd_warp_t>* warp, register_set* sp_out, + register_set* dp_out, register_set* sfu_out, register_set* mem_out, int id) : m_supervised_warps(), m_stats(stats), m_shader(shader), m_scoreboard(scoreboard), m_simt_stack(simt), /*m_pipeline_reg(pipe_regs),*/ m_warp(warp), - m_sp_out(sp_out),m_sfu_out(sfu_out),m_mem_out(mem_out), m_id(id){} + m_sp_out(sp_out),m_dp_out(dp_out),m_sfu_out(sfu_out),m_mem_out(mem_out), m_id(id){} virtual ~scheduler_unit(){} virtual void add_supervised_warp_id(int i) { m_supervised_warps.push_back(&warp(i)); @@ -403,6 +404,7 @@ protected: //warp_inst_t** m_pipeline_reg; std::vector<shd_warp_t>* m_warp; register_set* m_sp_out; + register_set* m_dp_out; register_set* m_sfu_out; register_set* m_mem_out; @@ -415,10 +417,11 @@ public: Scoreboard* scoreboard, simt_stack** simt, std::vector<shd_warp_t>* warp, register_set* sp_out, + register_set* dp_out, register_set* sfu_out, register_set* mem_out, int id ) - : scheduler_unit ( stats, shader, scoreboard, simt, warp, sp_out, sfu_out, mem_out, id ){} + : scheduler_unit ( stats, shader, scoreboard, simt, warp, sp_out, dp_out, sfu_out, mem_out, id ){} virtual ~lrr_scheduler () {} virtual void order_warps (); virtual void done_adding_supervised_warps() { @@ -432,10 +435,11 @@ public: Scoreboard* scoreboard, simt_stack** simt, std::vector<shd_warp_t>* warp, register_set* sp_out, + register_set* dp_out, register_set* sfu_out, register_set* mem_out, int id ) - : scheduler_unit ( stats, shader, scoreboard, simt, warp, sp_out, sfu_out, mem_out, id ){} + : scheduler_unit ( stats, shader, scoreboard, simt, warp, sp_out, dp_out, sfu_out, mem_out, id ){} virtual ~gto_scheduler () {} virtual void order_warps (); virtual void done_adding_supervised_warps() { @@ -450,10 +454,11 @@ public: Scoreboard* scoreboard, simt_stack** simt, std::vector<shd_warp_t>* warp, register_set* sp_out, + register_set* dp_out, register_set* sfu_out, register_set* mem_out, int id ) - : scheduler_unit ( stats, shader, scoreboard, simt, warp, sp_out, sfu_out, mem_out, id ){} + : scheduler_unit ( stats, shader, scoreboard, simt, warp, sp_out, dp_out, sfu_out, mem_out, id ){} virtual ~oldest_scheduler () {} virtual void order_warps (); virtual void done_adding_supervised_warps() { @@ -468,11 +473,12 @@ public: Scoreboard* scoreboard, simt_stack** simt, std::vector<shd_warp_t>* warp, register_set* sp_out, + register_set* dp_out, register_set* sfu_out, register_set* mem_out, int id, char* config_str ) - : scheduler_unit ( stats, shader, scoreboard, simt, warp, sp_out, sfu_out, mem_out, id ), + : scheduler_unit ( stats, shader, scoreboard, simt, warp, sp_out, dp_out, sfu_out, mem_out, id ), m_pending_warps() { unsigned inner_level_readin; @@ -518,6 +524,7 @@ public: Scoreboard* scoreboard, simt_stack** simt, std::vector<shd_warp_t>* warp, register_set* sp_out, + register_set* dp_out, register_set* sfu_out, register_set* mem_out, int id, @@ -1088,6 +1095,22 @@ public: virtual void issue( register_set& source_reg ); }; +class dp_unit : public pipelined_simd_unit +{ +public: + dp_unit( register_set* result_port, const shader_core_config *config, shader_core_ctx *core ); + virtual bool can_issue( const warp_inst_t &inst ) const + { + switch(inst.op) { + case DP_OP: break; + default: return false; + } + return pipelined_simd_unit::can_issue(inst); + } + virtual void active_lanes_in_pipeline(); + virtual void issue( register_set& source_reg ); +}; + class sp_unit : public pipelined_simd_unit { public: @@ -1226,9 +1249,11 @@ protected: enum pipeline_stage_name_t { ID_OC_SP=0, + ID_OC_DP, ID_OC_SFU, ID_OC_MEM, OC_EX_SP, + OC_EX_DP, OC_EX_SFU, OC_EX_MEM, EX_WB, @@ -1237,9 +1262,11 @@ enum pipeline_stage_name_t { const char* const pipeline_stage_name_decode[] = { "ID_OC_SP", + "ID_OC_DP", "ID_OC_SFU", "ID_OC_MEM", "OC_EX_SP", + "OC_EX_DP", "OC_EX_SFU", "OC_EX_MEM", "EX_WB", @@ -1328,21 +1355,25 @@ struct shader_core_config : public core_config //op collector int gpgpu_operand_collector_num_units_sp; + int gpgpu_operand_collector_num_units_dp; int gpgpu_operand_collector_num_units_sfu; int gpgpu_operand_collector_num_units_mem; int gpgpu_operand_collector_num_units_gen; unsigned int gpgpu_operand_collector_num_in_ports_sp; + unsigned int gpgpu_operand_collector_num_in_ports_dp; unsigned int gpgpu_operand_collector_num_in_ports_sfu; unsigned int gpgpu_operand_collector_num_in_ports_mem; unsigned int gpgpu_operand_collector_num_in_ports_gen; unsigned int gpgpu_operand_collector_num_out_ports_sp; + unsigned int gpgpu_operand_collector_num_out_ports_dp; unsigned int gpgpu_operand_collector_num_out_ports_sfu; unsigned int gpgpu_operand_collector_num_out_ports_mem; unsigned int gpgpu_operand_collector_num_out_ports_gen; int gpgpu_num_sp_units; + int gpgpu_num_dp_units; int gpgpu_num_sfu_units; int gpgpu_num_mem_units; |
