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

📄 issue.cc

📁 linux下基于c++的处理器仿真平台。具有处理器流水线
💻 CC
📖 第 1 页 / 共 4 页
字号:
    if (fu_lat == -2)	fatal("Function unit type not available!");    if (!dcacheInterface->isBlocked()) {	if (fu_lat >= 0) {	    stat_issued_inst_type[i->thread_number()][MemWriteOp]++;	    MemReqPtr req = new MemReq();            req->thread_num = i->thread_number();	    req->asid = i->asid;	    if (i->isCopy) {		req->cmd = Copy;		req->vaddr = i->srcVirtAddr;		req->paddr = i->srcPhysAddr;		req->dest = i->phys_addr;	    } else {		req->cmd = Write;		req->vaddr = i->virt_addr;		req->paddr = i->phys_addr;		Event *completion_event =		    new SimCompleteStoreEvent(storebuffer, i, req);				req->completionEvent = completion_event;	    }	    req->flags = i->mem_req_flags;	    req->size = i->size;	    req->time = curTick;            req->data = new uint8_t[i->size];	    if (i->data) {		memcpy(req->data, i->data, i->size);	    }	    req->xc = i->xc;	    assert((req->paddr & ((Addr)req->size-1)) == 0);	    dcacheInterface->access(req);	    i->issued = true;	} else {	    //	    //  This problem is accounted for when the store-buffer	    //  fills up.	    //	    stat_fu_busy[MemWriteOp]++;	    stat_fuBusy[pool_num][MemWriteOp]++;	    fu_busy[i->thread_number()]++;	}    }    return i->issued;}// ////  Issue an instruction from the IQ//boolFullCPU::iq_issue(BaseIQ::iterator i, unsigned fu_pool_num){    bool issued = false;    int fu_lat;    /*     *  check to make sure that the instruction has spent enough time     *  in the "issue stage" to be issued     */    if (curTick < (i->dispatch_timestamp + dispatch_to_issue_latency)) {	if (floss_state.issue_end_cause[0] == ISSUE_CAUSE_NOT_SET)	    floss_state.issue_end_cause[0] = ISSUE_AGE; 	//  note the reason this inst didn't issue	dist_unissued[UNISSUED_TOO_YOUNG]++;	return false;    }    OpClass fu_type = i->opClass();    // instructions that don't need a function unit usually don't make    // it out of dispatch... the "faulting no-op" introduced on an    // ifetch TLB miss is the exception.  Route it through an integer    // ALU just to get it to WB.    if (fu_type == No_OpClass) {	assert(i->inst->fault != No_Fault);	fu_type = IntAluOp;    }    unsigned thread = i->thread_number();    fu_lat = FUPools[fu_pool_num]->getUnit(fu_type);    assert(!i->inst->isInstPrefetch() &&	   "Issued instruction prefetch! (should never do so)");    if (fu_lat == -2)	panic("Function unit type not available!");    if (fu_lat >= 0) {	issued = true;	stat_issued_inst_type[i->thread_number()][i->opClass()]++;	assert(!i->inst->isInstPrefetch() &&	       "Instruction prefetch in issue stage!");    } else {	//	//  No FU available	//	// Indicate that we couldn't issue because no fu available	stat_fu_busy[fu_type]++;	stat_fuBusy[fu_pool_num][fu_type]++;	fu_busy[thread]++;	if (floss_state.issue_end_cause[0] == ISSUE_CAUSE_NOT_SET) {	    floss_state.issue_end_cause[0] = ISSUE_FU;	    // only use element zero for ISSUE_FU	    floss_state.issue_fu[0][0] = fu_type;	}	//  note the reason this inst didn't issue	dist_unissued[fu_type]++;    }    if (issued) { 	//  Inform the LSQ that this instruction is issuing	LSQ->inform_issue(i);	i->rob_entry->issued = true;	/* Schedule writeback event after i->latency cycles unless:	 * - it's a store (which completes immediately), indicated by	 * i->rob_entry->completed already being set	 * or	 * - it's a cache miss load (for which the writeback event will	 * be scheduled on a later callback from the memory system),	 * indicated by a negative value for latency	 */	/* queue up the rob entry, since we're going to delete	 *  the iq entry	 *	 *  even stores need to go through writeback...	 *  (they need to have their entry removed from the lsq	 *   and mark the rob entry as ready for the storebuffer)	 */	if (!i->rob_entry->completed && (fu_lat >= 0)) {	    WritebackEvent *wb_event =		new WritebackEvent(this, i->rob_entry);	    // so we can invalidate on a squash	    i->rob_entry->wb_event = wb_event;	    wb_event->schedule(curTick + cycles(fu_lat));	}	(i->rob_entry)->iq_entry = NULL;	/* ROB ptr to IQ */    }    return issued;}// boolFullCPU::lsq_issue(BaseIQ::iterator i, unsigned fu_pool_num){    bool issued = false;    int fu_lat = 0;    int latency = 0;    bool store_inst = false;    /*     *  check to make sure that the instruction has spent enough time     *  in the "issue stage" to be issued     */    if (curTick < (i->dispatch_timestamp + dispatch_to_issue_latency)) {	if (floss_state.issue_end_cause[0] == ISSUE_CAUSE_NOT_SET)	    floss_state.issue_end_cause[0] = ISSUE_AGE; 	//  note the reason this inst didn't issue	dist_unissued[UNISSUED_TOO_YOUNG]++;	return false;    }    unsigned thread = i->thread_number();    OpClass fu_type = i->opClass();    //    //  If this is the LSQ portion of a STORE.    //    //  (All stores pass through this code)    //    if (i->in_LSQ && i->inst->isStore()) {	issued = true;	latency = cycles(1);	store_inst = true;    } else if (fu_type != No_OpClass) {  // this "if" is probably a waste...	//	//  Load instructions require a functional unit	//	fu_type = i->opClass();	fu_lat = FUPools[fu_pool_num]->getUnit(fu_type);	if (fu_lat == -2) {	    fatal("Function unit type not available!");	}	if (fu_lat >= 0) {	    //  the default...	    latency = cycles(fu_lat);	    if (i->inst->isLoad()) {		//		//  Don't do anything if the cache is blocked		//		bool isPrefetch = i->inst->isDataPrefetch();		if (!dcacheInterface->isBlocked()) {		    //  Actually, unless the ALAT is being used, this op		    //  will ALWAYS issue...		    // LSQ part of load: May or may not issue.		    // "latency" is returned via arg list... negative value		    //    indicates that issue should not generate a WB event		    if (isPrefetch)			issued = issue_prefetch(i, &latency);		    else			issued = issue_load(i, &latency);		} else {		    //		    //  Set cause the first time through only		    //		    if (floss_state.issue_end_cause[0] == ISSUE_CAUSE_NOT_SET)		    {			floss_state.issue_end_cause[0] = ISSUE_MEM_BLOCKED;			//  FIXME!			// This information needs to come out of the cache			floss_state.issue_mem_result[0] = MA_MSHRS_FULL;		    }		    //  note the reason this inst didn't issue		    dist_unissued[UNISSUED_CACHE_BLOCKED]++;		}	    } else {		//		//  Store instruction... Issue to FU		//		issued = true;	    }	    if (issued) {		// reserve the functional unit		stat_issued_inst_type[i->thread_number()][i->opClass()]++;	    }	}	else {	    //	    //  No FU available	    //	    // Indicate that we couldn't issue because no fu available	    stat_fu_busy[fu_type]++;	    stat_fuBusy[fu_pool_num][fu_type]++;	    fu_busy[thread]++;	    if (floss_state.issue_end_cause[0] == ISSUE_CAUSE_NOT_SET) {		floss_state.issue_end_cause[0] = ISSUE_FU;		// only use element zero for ISSUE_FU		floss_state.issue_fu[0][0] = fu_type;	    }	    //  note the reason this inst didn't issue	    dist_unissued[fu_type]++;	}    }    else {	issued = true;	latency = cycles(1);    }    //    //  If the instruction was issued...    //    if (issued) {	//  Inform the IQ that this instruction is issuing	//	//  NOTE: Store instructions whose data value is ready prior to	//        the EA will NOT pass through here!	//	//  we do this later, when we inform all clusters	//  that this inst issued...	//      IQ[i->rob_entry->queue_num]->inform_issue(i); 	i->rob_entry->issued = true;	// Schedule writeback event after i->latency cycles unless:	//   - it's a cache miss load	//     (for which the writeback event will be scheduled on a later	//      callback from the memory system)	//     ==> indicated by a negative value for latency	//   - it's a load prefetch (these get marked completed when issued)	//     (note that store prefetches that potentially modify cache data,	//      e.g. wh64, still get writeback events, as they need to be	//      ordered w.r.t. other stores)	//	//  even stores need to go through writeback...	//  (they need to have their entry removed from the lsq	//   and mark the rob entry as ready for the storebuffer)	//	if (latency < 0 || (i->inst->isDataPrefetch() && i->inst->isLoad())) {	    //	    //  Do not create a writeback event	    //	} else {	    WritebackEvent *wb_event =		new WritebackEvent(this, i->rob_entry);	    // so we can invalidate on a squash	    i->rob_entry->wb_event = wb_event;            assert(latency >= clock);	    wb_event->schedule(curTick + latency);	}	if (DTRACE(Pipeline)) {	    string s;	    i->inst->dump(s);	    DPRINTF(Pipeline, "Issue %s\n", s);	}    }    return issued;}// ////  Find the Input Dependants that are not ready... not the type of//  function unit that produces the operand//boolFullCPU::find_idep_to_blame(BaseIQ::iterator inst, int thread){    bool found_fu = false;    if (!inst->in_LSQ) {	for (int i = 0; i < inst->num_ideps; ++i) {	    if (!inst->idep_ready[i]) {		found_fu = true;		ROBStation *rob = inst->idep_ptr[i]->rob_producer;		OpClass op_class = rob->inst->opClass();		assert(op_class != No_OpClass);		floss_state.issue_fu[thread][i] = op_class;	    }	    else {		floss_state.issue_fu[thread][i] = No_OpClass;	    }	}    } else {	//	//  If the problem is an instruction from the LSQ	//	if (inst->inst->isStore() && !inst->idep_ready[STORE_DATA_INDEX]) {	    //  store is waiting for its data...	    ROBStation *rob		= inst->idep_ptr[STORE_DATA_INDEX]->rob_producer;	    floss_state.issue_fu[thread][STORE_DATA_INDEX]		= rob->inst->opClass();	    found_fu = true;	}	//  This works for both loads & stores	if (!inst->idep_ready[MEM_ADDR_INDEX]) {	    floss_state.issue_fu[thread][MEM_ADDR_INDEX] = IntAluOp;	    found_fu = true;	}    }    return found_fu;}// class IQList{  private:    unsigned number_of_queues;    vector<bool> done_with_queue;    unsigned num_done;  public:    IQList(unsigned num_iq) {	number_of_queues = num_iq;	done_with_queue.resize(number_of_queues, false);	num_done = 0;    }    bool allDone() {return num_done == number_of_queues;}    bool markDone(unsigned q) {	assert(q < number_of_queues);	if (!done_with_queue[q]) {	    done_with_queue[q] = true;	    ++num_done;	}	return allDone();    }    bool done(unsigned q) {	assert(q < number_of_queues);	return done_with_queue[q];    }    //  find the next NOT Done queue    //  return false if there's a problem    bool next(unsigned &q) {	assert(q < number_of_queues);	assert(num_done < number_of_queues);	if (number_of_queues == 1) {	    return false;	}	bool done = false;	bool rv = true;	unsigned next_queue = q;	do {	    //  increment to the NEXT index (w/ wrap)	    next_queue = (next_queue + 1) % number_of_queues;	    //  if we've wrapped all the way around, deal with it	    if (next_queue == q) {		done = true;		rv = false;	    }	    else {		//  haven't wrapped yet ...		//  if this queue is not done, return it...		if (!done_with_queue[next_queue]) {		    q = next_queue;		    done = true;		}	    }	} while (!done);	return rv;    }};//   attempt to issue all operations in the ready queue; insts in the//   ready instruction queue have all register dependencies satisfied,//   this function must then 1) ensure the instructions memory//   dependencies have been satisfied (see lsq_refresh() for details//   on this process) and 2) a function unit is available in this//   cycle to commence execution of the operation; if all goes well,//   the function unit is allocated, a writeback event is scheduled,//   and the instruction begins executionvoidFullCPU::issue(){    int n_issued;    bool done_with_sb = false;    bool done_with_iq = false;    bool done_with_lsq = false;    unsigned issued_by_thread[SMT_MAX_THREADS];    unsigned iq_count = 0;    unsigned lsq_count = 0;    unsigned sb_count = 0;    enum inst_source {none, iq, lsq, sb};    inst_source source;    BaseIQ::iterator evil_inst = 0;    BaseIQ::rq_iterator *iq_rq_iterator = new BaseIQ::rq_iterator[numIQueues];#ifdef DEBUG_ISSUE    std::cerr << "-------------------------------" << std::endl;    std::cerr << " ISSUE cycle: " << curTick << std::endl;    std::cerr << "-------------------------------" << std::endl;#endif    //  for each queue, the list of RQ iterators to instructions belonging    //  to the high-priority thread    list<BaseIQ::rq_iterator> *hp_rq_it_list	= new list<BaseIQ::rq_iterator>[numIQueues];    for (int i = 0; i < SMT_MAX_THREADS; ++i)	issued_by_thread[i] = 0;    BaseIQ::rq_iterator lsq_rq_iterator  = LSQ->issuable_list();    StoreBuffer::rq_iterator sb_rq_iterator = storebuffer->issuable_list();    //  We will start issuing out of this IQ    unsigned current_iq = issue_starting_iqueue;    unsigned current_fu_pool = issue_starting_fu_pool;    //  Increment the last_iq index (RR fashion) for next cycle    issue_starting_iqueue = (++issue_starting_iqueue % numIQueues);    issue_starting_fu_pool = (++issue_starting_fu_pool % numFUPools);    // visit all ready instructions (i.e., insts whose register input    // dependencies have been satisfied, stop issue when no more instructions    // are available or issue bandwidth is exhausted    n_issued = 0;    //    //  Check to see if we need to change HP thread    //    if (prioritize_issue && (hp_thread_change <= curTick)) {	hp_thread = ++hp_thread % number_of_threads;	// schedule the next change	hp_thread_change = curTick + issue_thread_weights[hp_thread];    }#if DUMP_ISSUE    cerr << "@" << curTick << endl;    list<issue_info> issued_list;#endif    //    //  If there are no ready instructions, blame the stopage on the oldest    //  instruction found in the IQ or LSQ.    //    //     THERE ARE THREE SUB-CASES:    //       (a)  No instructions anywhere  ==> ISSUE_NO_INSN    //       (a)  The oldest instruction has not-ready operands    //              => ISSUE_DEPS

⌨️ 快捷键说明

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