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

📄 dispatch.cc

📁 linux下基于c++的处理器仿真平台。具有处理器流水线
💻 CC
📖 第 1 页 / 共 4 页
字号:
		//  If we run out of chains...		//	      case FLOSS_DIS_POLICY:		done = true;		break;	      case FLOSS_DIS_CAUSE_NOT_SET:		done = false;		break;	      default:		warn("need to adjust endCauses for dispatch_thread()");		done = false;	    }	    if (queue_endCause == FLOSS_DIS_CAUSE_NOT_SET) {		if (decodeQueue->instsAvailable(thread) == 0) {		    SET_FIRST_FLOSS_CAUSE(endCause, FLOSS_DIS_NO_INSN);		    done = true; // nothing left to dispatch		}	    }	    if (dispatched_this_cycle == dispatch_width) {		SET_FIRST_FLOSS_CAUSE(endCause, FLOSS_DIS_BW);		done = true;  // we used all available BW	    }	    if (done)		SET_FIRST_FLOSS_CAUSE(endCause, queue_endCause);	} while (!done);	assert(endCause != FLOSS_DIS_CAUSE_NOT_SET);	break;      case MODULO_N:	//	//  We dispatch A SINGLE thread to as many IQ's as necessary.	//	//  rotate through all the IQ's until:	//    (1) We run out of instructions to dispatch	//    (2) We try to dispatch to an IQ, and fail	//	//  ==> This means that we have to check each IQ for caps, etc	//      as we rotate through...	//	lastDispatchTime[thread] = curTick;	do {	    DispatchEndCause queue_endCause = FLOSS_DIS_CAUSE_NOT_SET;	    unsigned dispatched_this_queue =		dispatch_thread(thread, iq_idx, dispatch_width,				queue_endCause);	    dispatched_this_cycle += dispatched_this_queue;	    switch (queue_endCause) {		//		// The following end-causes indicate that we can't dispatch		// any more instructions this cycle		//	      case FLOSS_DIS_ROB_FULL:	      case FLOSS_DIS_LSQ_FULL:	      case FLOSS_DIS_IREG_FULL:	      case FLOSS_DIS_FPREG_FULL:		done = true;		endCause = queue_endCause;		break;		//		// The following end-causes indicate that we can't continue		// dispatching this thread this cycle		//	      case FLOSS_DIS_ROB_CAP:	      case FLOSS_DIS_NO_INSN:		done = true;		endCause = queue_endCause;		break;		//		// The following end-causes indicate that we can't continue		// dispatching to this Queue, but should try the next one		//	      case FLOSS_DIS_IQ_FULL:	      case FLOSS_DIS_IQ_CAP:	      case FLOSS_DIS_BW:	      case FLOSS_DIS_POLICY:		endCause = queue_endCause;		//		done = false;		done = true;		break;	      case FLOSS_DIS_CAUSE_NOT_SET:		done = false;		break;	      default:		warn("need to adjust endCauses for dispatch_thread()");		done = false;	    }	    if (queue_endCause == FLOSS_DIS_CAUSE_NOT_SET) {		if (decodeQueue->instsAvailable(thread) == 0) {		    SET_FIRST_FLOSS_CAUSE(endCause, FLOSS_DIS_NO_INSN);		    done = true; // nothing left to dispatch		}	    }	    if (dispatched_this_cycle == dispatch_width) {		SET_FIRST_FLOSS_CAUSE(endCause, FLOSS_DIS_BW);		done = true;  // we used all available BW	    }	    if (!done) {#if 0		//  Rotate to the next IQ		iq_idx = choose_iqueue(thread);		if ((iq_idx < 0) || (iq_idx == first)) {		    done = true;		    // we call this policy...		    SET_FIRST_FLOSS_CAUSE(endCause, FLOSS_DIS_POLICY);		}#endif	    } else		SET_FIRST_FLOSS_CAUSE(endCause, queue_endCause);	} while (!done);	assert(endCause != FLOSS_DIS_CAUSE_NOT_SET);	break;      case THREAD_PER_QUEUE:	//	//  Walk the sorted list of threads, dispatching as many insts	//  from each as possible.	//	for (unsigned t = 0; t < SMT_MAX_THREADS; ++t) {	    if (tlist[t].eligable) {		unsigned dispatched_this_thread = 0;		unsigned iq_idx = tlist[t].iq_idx;		unsigned thread = tlist[t].thread_number;		unsigned possible_dispatches =		    dispatch_width - dispatched_this_cycle;		dispatched_this_thread =		    dispatch_thread(thread, iq_idx, possible_dispatches,				    endCause);		dispatched_this_cycle += dispatched_this_thread;		bool done;		switch (endCause) {		    //		    // The following end-causes indicate that we can't dispatch		    // any more instructions this cycle		    //		  case FLOSS_DIS_ROB_FULL:		  case FLOSS_DIS_LSQ_FULL:		  case FLOSS_DIS_IREG_FULL:		  case FLOSS_DIS_FPREG_FULL:		    done = true;  // stop dispatching		    break;		    //		    // The following end-causes indicate that we can't		    // continue dispatching this thread this cycle		    //		  case FLOSS_DIS_ROB_CAP:		  case FLOSS_DIS_NO_INSN:		  case FLOSS_DIS_POLICY:		    done = false; // continue dispatching		    break;		    //		    // The following end-causes indicate that we can't continue		    // dispatching to this Queue, but should try the next one		    //		  case FLOSS_DIS_IQ_FULL:		  case FLOSS_DIS_IQ_CAP:		  case FLOSS_DIS_BW:		    done = false; // continue dispatching		    break;		  case FLOSS_DIS_CAUSE_NOT_SET:		    done = false;		    break;		  default:		    warn("need to adjust endCauses for dispatch_thread()");		    done = false;		}		if (done)		    break;		if (dispatched_this_cycle == dispatch_width) {		    SET_FIRST_FLOSS_CAUSE(endCause, FLOSS_DIS_BW);		    break;  // we used _all_ available BW		}		//		//  If we dispatched all available instructions		//  for this thread, and the "next" thread is going		//  to try to dispatch, then reset the endCause		//		if (dispatched_this_thread == tlist[t].disp_insts &&		    t < (SMT_MAX_THREADS - 1) && tlist[t + 1].eligable)		    endCause = FLOSS_DIS_CAUSE_NOT_SET;	    } else {		//  endCause will have been set earlier, when we assigned		//  scores		break;  // no other threads will be eligible	    }	}	break;    }    //    //  Anything that we didn't set a cause for before this point, MUST    //  be a thread that we _could_ have dispatched, but chose not to    //    if (floss_state.dispatch_end_cause == FLOSS_DIS_CAUSE_NOT_SET)	floss_state.dispatch_end_cause = FLOSS_DIS_BROKEN;#if DUMP_IQ    IQ[0]->dump(0);#endif}////  Return the desired cluster//unsignedFullCPU::choose_dependence_cluster(DynInst *inst){    unsigned thread = inst->thread_number;    RegInfoTable * rit = clusterSharedInfo->ri_table;    bool chained = false;    Tick pred_ready = 0;    unsigned pred_cluster = IQLeastFull();  // default if no chained idep    for (int i = 0; i < inst->numSrcRegs(); ++i) {	unsigned ireg = inst->srcRegIdx(i);	//	//  If we have an input register that is not yet ready and is chained	//	chained = (*rit)[thread][ireg].isChained();	if (create_vector[thread].entry(ireg).rs != 0) {	    if ((*rit)[thread][ireg].predReady() > pred_ready) {		pred_ready = (*rit)[thread][ireg].predReady();		pred_cluster = (*rit)[thread][ireg].cluster();	    }	} else {	    // sanity check: if the input reg does not have a creator,	    // it had better not be chained...	    assert(!chained);	}    }    return pred_cluster;}////  Dispatch the next 'max' instructions for thread number 'thread' to//  Instruction queue 'iq_idx'.////  Returns://     - The number of instructions actually dispatched//       (squashed instructions _do_ count)//     - The reason we stopped dispatching//       (this value will NOT be set if we stop due to reaching 'max')////  Dispatch End Causes Returned://     FLOSS_DIS_NO_INSN   --> No more instructions to dispatch for this thread//     FLOSS_DIS_BW        --> No BW left for this queue////     FLOSS_DIS_IQ_FULL     {via checkThreadForDispatch()}//     FLOSS_DIS_IQ_CAP      {via checkThreadForDispatch()}//     FLOSS_DIS_LSQ_FULL    {via checkThreadForDispatch()}//     FLOSS_DIS_ROB_FULL    {via checkThreadForDispatch()}//     FLOSS_DIS_ROB_CAP     {via checkThreadForDispatch()}//     FLOSS_DIS_IREG_FULL   {via checkThreadForDispatch()}//     FLOSS_DIS_FPREG_FULL  {via checkThreadForDispatch()}//unsignedFullCPU::dispatch_thread(unsigned thread, unsigned iq_idx, unsigned max,		     DispatchEndCause &endCause){    ROBStation *rob;    unsigned dCount = 0;    unsigned first_idx;    bool using_loose_mod_n = false;    DPRINTF(Pipeline, "DISP:     dispatch_thread (thread %d) (clust %d)\n", thread, iq_idx);    //  Default case... no maximum value    if (max == 0) {	max = dispatch_width;    }    first_idx = iq_idx;    //    //  Dispatch until:    //    (1) An instruction fails to dispatch    //    (2) We dispatch the "max" number of instructions    //    (3) We run out of decodeQueue bandwidth    //    do {	DynInst * inst = decodeQueue->peek(thread);	//	//  If this inst hasn't been squashed...	//	if (inst != 0) {	    // If it's a serializing instruction, flush the pipeline	    // by stalling here until all older instructions have	    // committed.  Do this before checking for No_OpClass,	    // since instructions that only serialize (e.g. Alpha	    // trapb) will have No_OpClass and thus get discarded	    // before being dispatched once the serialization is	    // complete.	    if (inst->isSerializing() && ROB.num_thread(thread) != 0) {		SET_FIRST_FLOSS_CAUSE(endCause, FLOSS_DIS_SERIALIZING);		++dispatch_serialize_stall_cycles[thread];		break;	    } else if (inst->fault == No_Fault		       && (inst->opClass() == No_OpClass || inst->isNop()			   || inst->isInstPrefetch())) {		// Drop things that don't need to go any farther in the		// pipeline.  This includes all instructions that do not		// use a function unit (i.e. have No_OpClass for their op		// class).  This should include all instructions that		// declare themselves as no-ops (isNop()), but just to be		// sure we'll check that too.  We're also dropping		// instruction prefetches here for historical reasons (in		// practice we don't have any, I believe).		if (ptrace) {		    ptrace->moveInst(inst, PipeTrace::Dispatch, 0, 0, 0);		    ptrace->deleteInst(inst);		}		// Copied this here from dispatch_one_inst() since		// insts that get discarded here never make it to that		// function.  Causes minor inconsistencies since these		// don't get counted in some other stats, but oh well.		if (inst->isSerializing())		    ++dispatched_serializing[thread];		delete inst;		inst = 0;		// not going to need this one...		decodeQueue->remove(thread);		++dCount;	    } else {		DispatchEndCause cause;		unsigned output_reg = 0;		bool output_reg_valid = false;		if (numIQueues == 1) {		    cause = checkThreadForDispatch(thread, iq_idx, 1);		} else {		    //		    //  Some dispatch policies require decisions to be made		    //  for each instruction...		    //		    switch (dispatch_policy) {		      case DEPENDENCE:			//			//  Find the output register			//  (--> assumes only one output register per			//  instruction)			//			for (int i = 0; i < inst->numDestRegs(); ++i) {			    output_reg = inst->destRegIdx(i);			    output_reg_valid = true;			    break;			}			//			//  Now pick the Cluster...			//			iq_idx = choose_dependence_cluster(inst);			//			//  Check for available resources			//			cause = checkThreadForDispatch(thread, iq_idx, 1);			//			//  Just because we can't put the instruction where			//  we want it doesn't mean that we shouldn't dispatch			//  it...			//			if (cause == FLOSS_DIS_BW) {			    //  No IQ bandwidth for our preferred IQ...			    //  --> try to dispatch to the least full IQ, but			    //      if that also fails, blame the original IQ			    //      BW problem			    unsigned new_idx = IQLeastFull();			    DispatchEndCause new_cause =				checkThreadForDispatch(thread, new_idx, 1);			    if (new_cause == FLOSS_DIS_CAUSE_NOT_SET) {				// go with the new IQ				cause = new_cause;				iq_idx = new_idx;			    }			}			break;		      case MODULO_N:			cause = checkThreadForDispatch(thread, iq_idx, 1);			if (cause == FLOSS_DIS_IQ_FULL ||			    cause == FLOSS_DIS_IQ_CAP ||			    cause == FLOSS_DIS_BW)			{			    DispatchEndCause temp = cause;			    unsigned n = IQFreeSlotsX(iq_idx);			    if (n) {				++mod_n_disp_stalls[thread];				mod_n_disp_stall_free[thread] += n;				//				//  Loose Mod-N:				//				//  if we'd normally just quit, try to find a				//  different cluster for these instructions				//				if (loose_mod_n_policy) {				    do {					iq_idx = (iq_idx+1) % numIQueues;					if (iq_idx == first_idx) {					    cause = temp;					    break;					}					cause = checkThreadForDispatch					    (thread, iq_idx, 1);				    } while (cause != FLOSS_DIS_CAUSE_NOT_SET);				    if (cause == FLOSS_DIS_CAUSE_NOT_SET)					using_loose_mod_n = true;				}			    }			}			break;		      default:			//			//  "normal case": Just check for available resources			//			cause = checkThreadForDispatch(thread, iq_idx, 1);			break;		    }		}		if (cause != FLOSS_DIS_CAUSE_NOT_SET) {		    SET_FIRST_FLOSS_CAUSE(endCause, cause);		    break;		}		//		//  Dispatch this instruction		//		rob = dispatch_one_inst(inst, iq_idx);		//		//  Policy-Dependant post-processing		//		if (numIQueues > 1) {		    switch (dispatch_policy) {		      case MODULO_N:			if ((rob != 0) &&			    ((dispatch_count[thread]) % MODULO_VAL))			{			    mod_n_queue_idx = ++mod_n_queue_idx % numIQueues;			    if (!using_loose_mod_n) {				iq_idx = mod_n_queue_idx;				first_idx = iq_idx;			    }			}			break;		      default:			break;		    }		}		//		//  If we dispatched the instruction...		//		if (rob != 0) {		    //  remove it from the decode queue		    decodeQueue->remove(thread);		    ++dCount;		    if (dispatch_policy == DEPENDENCE) {			if (output_reg_valid) {			    rob->output_reg = output_reg;			    (*clusterSharedInfo->ri_table)[thread][output_reg].				setCluster(iq_idx);			}		    }		    if (decodeQueue->instsAvailable(thread) == 0) {			SET_FIRST_FLOSS_CAUSE(endCause, FLOSS_DIS_NO_INSN);			break;		    }		} else {		    //  this should really never happen...		    //  ==> It can if the segmented IQ enters deadlock		    //      recovery mode!		    // warn("dispatch_one_inst() failed @%d!", curTick);		    endCause = FLOSS_DIS_POLICY;		    break;		}	    }	} else {	    //	    //  Squashed instruction	    //	    decodeQueue->remove(thread);	    ++dCount;	}	//	//  We must have instructions to continue...	//	if (decodeQueue->instsAvailable(thread) == 0) {	    SET_FIRST_FLOSS_CAUSE(endCause, FLOSS_DIS_NO_INSN);	    break;	}	DispatchEndCause c = checkGlobalResourcesForDispatch(1);	if (c != FLOSS_DIS_CAUSE_NOT_SET) {	    SET_FIRST_FLOSS_CAUSE(endCause, c);	    break;	}	//  Check to see if we've dispatched the specified maximum number of	//  instructions	if (dCount >= max)	    break;    } while (true);    return dCount;}//////  Dispatch this instruction to the specified queue////ROBStation *FullCPU::dispatch_one_inst(DynInst *inst, unsigned iq_idx){    if (dispatch_break && (dispatch_break == dispatch_seq))	dispatch_breakpoint();    unsigned thread = inst->thread_number;    if (DTRACE(Pipeline)) {	string s;	inst->dump(s);	DPRINTF(Pipeline, "Dispatch %s\n", s);    }

⌨️ 快捷键说明

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