⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 iq_seg.cc

📁 linux下基于c++的处理器仿真平台。具有处理器流水线
💻 CC
📖 第 1 页 / 共 3 页
字号:
			if (segment_number > 0)			    if (!(*i)->queued && promotable(*i))				enqueue(*i);		    }		} else {		    //  Self-timed...		    decrement_delay(*i, j);		    recalc_position = true;		    //  Don't enqueue for segment zero		    if (segment_number > 0 && !(*i)->queued && promotable(*i))			enqueue(*i);		}	    } else {		decrement_delay(*i, j);		recalc_position = true;	    }	}	if (recalc_position)	    (*i)->dest_seg = proper_segment(*i);    }}voidsegment_t::decrement_delay(iq_iterator i, int op_num){    bool all_zero = true;    if (i->idep_info[op_num].delay != 0) {	--(i->idep_info[op_num].delay);	// if this delay counter just went to zero...	if (i->idep_info[op_num].delay == 0) {	    //  check all ideps for zero delay	    for (int j = 0; j < TheISA::MaxInstSrcRegs; ++j) {		if (i->idep_info[j].delay != 0) {		    all_zero = false;		    break;		}	    }	    if (all_zero)		i->st_zero_time = curTick;	}    }}////  Determine if this instruction should be promoted////  Assumes that the queue _forward_of_this_instruction_//  is in a consistent state.//boolsegment_t::promotable(iq_iterator &inst){    bool rv = false;    unsigned pred_wait;    unsigned max_wait=0;    int max_wait_index=-1;    //  We NEVER 'promote' from segment zero    if (segment_number == 0)	return false;    //  If this instruction is ready, then hurry it on down...    //  This shouldn't make any performance difference, but keeps us    //  from messing around with the code below...    if (inst->ops_ready())	return true;    //    //  Figure out which operand we should be waiting for...    //    //  This loop calculates the predicted wait time before each head    //  instruction should be ready to isssue. We compare these values    //  in order to determine which chain we should be following.    //    //    for (int i = 0; i < TheISA::MaxInstSrcRegs; ++i) {	if (!inst->idep_ready[i]) {	    if (inst->idep_info[i].chained) {		unsigned c_num = inst->idep_info[i].follows_chain;		unsigned head_level = (*chain_info)[c_num].head_level;		if (head_level == 0)		    pred_wait = 0 + inst->idep_info[i].delay;		else		    pred_wait = seg_queue->seg_thresholds[head_level - 1]			+ inst->idep_info[i].delay;	    } else {		pred_wait = inst->idep_info[i].delay;	    }	    if (max_wait <= pred_wait) {		max_wait = pred_wait;		max_wait_index = i;	    }	}    }    assert(max_wait_index >= 0);    IQStation::IDEP_info *idep_info = &inst->idep_info[max_wait_index];    if (idep_info->chained) {	unsigned head_level =	    (*chain_info)[idep_info->follows_chain].head_level;	//  Be sure not to promote ahead of the chain-head	if (head_level < segment_number) {	    if ((*chain_info)[idep_info->follows_chain].self_timed) {		if (idep_info->delay <		    seg_queue->seg_thresholds[segment_number - 1])		{		    rv = true;		}	    } else {		unsigned head_thresh;		unsigned inst_thresh		    = seg_queue->seg_thresholds[segment_number - 1];		if (head_level == 0)		    head_thresh = 0;		else		    head_thresh = seg_queue->seg_thresholds[head_level - 1];		// calculate this instructions distance from the head		// (the head_level remains at 0 after the head has issued)		unsigned dist = inst_thresh - head_thresh;		//  If this instruction is too far behind the head...		if (idep_info->delay < dist)		    rv = true;	    }	}    } else {	//  Instructions that are not chained don't need to worry about	//  a chain-head... they just use their built-in delay counter	if (idep_info->delay < seg_queue->seg_thresholds[segment_number - 1]) {	    rv = true;	}    }    return rv;}voidsegment_t::regStats(FullCPU *cpu, std::string &n){    using namespace Stats;    number_of_threads = cpu->number_of_threads;    stringstream label, desc, formula;    string c = cpu->name() + '.';    //  Occupancy stats    label << n << setw(2) << setfill('0') << segment_number	  << ":cum_num_insts";    cum_insts	.init(cpu->number_of_threads)	.name(label.str())	.desc("number of insts in this segment")	.flags(total)	;    label.str("");    label << n << setw(2) << setfill('0') << segment_number	  << ":full_cycles";    segment_full	.name(label.str())	.desc("number of cycles segment was full")	;    label.str("");    label << n << setw(2) << setfill('0') << segment_number	  << ":empty_cycles";    segment_empty	.name(label.str())	.desc("number of cycles segment was empty")	;    label.str("");    //  Segment promotion stats    cum_promotions.init(number_of_threads);    if (segment_number != 0) {	label << n << setw(2) << setfill('0') << segment_number	      << ":cum_num_prom";	cum_promotions	    .name(label.str())	    .desc("number of promotions out of this segment")	    .flags(total)	    ;	label.str("");    }    //    //  Use issue rate to determine residency for segment zero... rest use    //  promotion rate    //    if (segment_number == 0) {	//	//  load-counting stats, etc.	//	cycles_low_ready	    .name(n+"00:L:cycle_low_ready")	    .desc("number of cycles segment had < 2 ready insts")	    ;	insts_waiting_for_loads	    .name(n+"00:L:inst_wait_loads")	    .desc("number of insts waiting for issued loads")	    ;	insts_waiting_for_unissued	    .name(n+"00:L:inst_wait_uniss")	    .desc("number of insts waiting for unissued insts")	    ;	insts_fanout_loads	    .name(n+"00:L:inst_loads")	    .desc("number of issued load insts waited on")	    ;    }    label << n << setw(2) << setfill('0') << segment_number	  << ":chained_cum";    cum_chained	.init(cpu->number_of_threads)	.name(label.str())	.desc("number of chained insts in this segment")	.flags(total)	;    label.str("");    cum_ops_ready.init(cpu->number_of_threads);    if (segment_number != 0) {	label << n << setw(2) << setfill('0') << segment_number	      << ":cum_ops_ready";	cum_ops_ready	    .name(label.str())	    .desc("number of ops-ready insts")	    ;	label.str("");    }    if (use_pushdown && segment_number < num_segments - 1 &&	segment_number > 0)    {	label << n << setw(2) << setfill('0') << segment_number	      << ":pd_inst";	seg_queue->pushdown_count[segment_number]	    .name(label.str())	    .desc("number of instructions into this segment")	    ;	label.str("");	label << n << setw(2) << setfill('0') << segment_number	      << ":pd_events";	seg_queue->pushdown_events[segment_number]	    .name(label.str())	    .desc("number of pushed-down events")	    ;	label.str("");    }    //  Stats for the ready-queue    label.str("");    label << n << setw(2) << setfill('0') << segment_number << ":RQ";    ready_list->regStats(label.str(), cpu->number_of_threads);}voidsegment_t::regFormulas(FullCPU *cpu, std::string &n){    using namespace Stats;    stringstream label, desc, formula;    string c = cpu->name() + '.';    //  Occupancy stats    label << n << setw(2) << setfill('0') << segment_number	  << ":occ_rate";    occ_rate	.name(label.str())	.desc("Average segment occupancy")	;    occ_rate = cum_insts / cpu->numCycles;    label.str("");    label << n << setw(2) << setfill('0') << segment_number	  << ":full_frac";    full_frac	.name(label.str())	.desc("fraction of cycles where segment was full")	;    full_frac = 100 * segment_full / cpu->numCycles;    label.str("");    label << n << setw(2) << setfill('0') << segment_number	  << ":empty_frac";    empty_frac	.name(label.str())	.desc("fraction of cycles where segment was empty")	;    empty_frac = 100 * segment_empty / cpu->numCycles;    label.str("");    //  Segment promotion stats    if (segment_number != 0) {	label << n << setw(2) << setfill('0') << segment_number	      << ":prom_rate";	prom_rate	    .name(label.str())	    .desc("promotions per cycle from this segment")	    ;	prom_rate = cum_promotions / cpu->numCycles;	label.str("");    }    //    //  Use issue rate to determine residency for segment zero... rest use    //  promotion rate    //    if (segment_number != 0) {	label << n << setw(2) << setfill('0') << segment_number	      << ":residency";	seg_residency	    .name(label.str())	    .desc("segment residency (cycles)")	    ;	seg_residency = occ_rate / prom_rate;	label.str("");    } else {	seg_residency	    .name(n+"00:residency")	    .desc("segment residency (cycles)")	    ;	seg_residency = occ_rate / cpu->issue_rate;	rate_loads	    .name(n+"00:L:rate_loads")	    .desc("number of issued loads waited on per cycle")	    ;	rate_loads = insts_fanout_loads / cycles_low_ready;	rate_wait_loads	    .name(n+"00:L:rate_wait_loads")	    .desc("number of insts waiting for issued loads per cycle")	    ;	rate_wait_loads = insts_waiting_for_loads / cycles_low_ready;	rate_wait_uniss	    .name( n+"00:L:rate_wait_uniss")	    .desc("number of insts waiting for unissued insts per cycle")	    ;	rate_wait_uniss = insts_waiting_for_unissued / cycles_low_ready;	avg_wait_load	    .name(n+"00:L:avg_wait_load")	    .desc("avg number of insts waiting for each load")	    ;	avg_wait_load = insts_waiting_for_loads / insts_fanout_loads;	frac_low_ready	    .name(n+"00:L:frac_low_ready")	    .desc("fraction of all cycles with low ready rates")	    ;	frac_low_ready = cycles_low_ready / cpu->numCycles;    }    label << n << setw(2) << setfill('0') << segment_number	  << ":chained_frac";    chained_frac	.name(label.str())	.desc("fraction of insts chained")	;    chained_frac = 100 * cum_chained / cum_insts;    label.str("");    if (segment_number != 0) {	label << n << setw(2) << setfill('0') << segment_number	      << ":ops_ready_rate";	ops_ready_rate	    .name(label.str())	    .desc("average number of ops-ready insts")	    ;	ops_ready_rate = cum_ops_ready / cpu->numCycles;	label.str("");    }    if (use_pushdown && segment_number < num_segments - 1 &&	segment_number > 0)    {	label << n << setw(2) << setfill('0') << segment_number	      << ":pd_rate";	pd_rate	    .name(label.str())	    .desc("average push-down events per cycle")	    ;	pd_rate = seg_queue->pushdown_events[segment_number] / cpu->numCycles;	label.str("");	label << n << setw(2) << setfill('0') << segment_number	      << ":pd_inst_rate";	pd_inst_rate	    .name(label.str())

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -