aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/abstract_hardware_model.h2
-rw-r--r--src/cuda-sim/cuda-sim.cc32
-rw-r--r--src/gpgpu-sim/dram.cc597
-rw-r--r--src/gpgpu-sim/dram.h60
-rw-r--r--src/gpgpu-sim/dram_sched.cc11
-rw-r--r--src/gpgpu-sim/gpu-sim.cc27
-rw-r--r--src/gpgpu-sim/gpu-sim.h4
-rw-r--r--src/gpgpu-sim/shader.cc70
-rw-r--r--src/gpgpu-sim/shader.h41
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;