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

📄 iq_seg.cc

📁 linux下基于c++的处理器仿真平台。具有处理器流水线
💻 CC
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (c) 2001, 2002, 2003, 2004, 2005 * The Regents of The University of Michigan * All Rights Reserved * * This code is part of the M5 simulator, developed by Nathan Binkert, * Erik Hallnor, Steve Raasch, and Steve Reinhardt, with contributions * from Ron Dreslinski, Dave Greene, Lisa Hsu, Kevin Lim, Ali Saidi, * and Andrew Schultz. * * Permission is granted to use, copy, create derivative works and * redistribute this software and such derivative works for any * purpose, so long as the copyright notice above, this grant of * permission, and the disclaimer below appear in all copies made; and * so long as the name of The University of Michigan is not used in * any advertising or publicity pertaining to the use or distribution * of this software without specific, written prior authorization. * * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE * UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND * WITHOUT WARRANTY BY THE UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER * EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE. THE REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE * LIABLE FOR ANY DAMAGES, INCLUDING DIRECT, SPECIAL, INDIRECT, * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM * ARISING OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH * DAMAGES. */#include <iomanip>#include <iostream>#include <map>#include <sstream>#include "base/cprintf.hh"#include "base/statistics.hh"#include "encumbered/cpu/full/cpu.hh"#include "encumbered/cpu/full/create_vector.hh"#include "encumbered/cpu/full/dep_link.hh"#include "encumbered/cpu/full/iq/iqueue.hh"#include "encumbered/cpu/full/iq/segmented/iq_seg.hh"#include "encumbered/cpu/full/iq/segmented/iq_segmented.hh"#include "encumbered/cpu/full/iq/segmented/seg_chain.hh"#include "encumbered/cpu/full/issue.hh"#include "encumbered/cpu/full/ls_queue.hh"#include "encumbered/cpu/full/reg_info.hh"#include "sim/eventq.hh"#include "sim/stats.hh"using namespace std;#define use_dest_sort   1#define use_pushdown    1//==========================================================================////  The segment implementation////==========================================================================////  Constructor//segment_t::segment_t(SegmentedIQ *iq, string n,		     unsigned seg_num, unsigned num_segs,		     unsigned sz, unsigned n_chains, unsigned thresh,		     bool pipelined, bool en_pri){    //  Allows us to reference our own queue data    seg_queue = iq;    name_string = n;    segment_number = seg_num;    num_segments = num_segs;    size = sz;    num_chains = n_chains;    threshold = thresh;    // we need to set this after the chain info table gets built    chain_info = 0;    //    //  The list of iterators to the instructions we're tracking    //    //  ["size" elements, allocated, doesn't grow]    //    queue = new iq_iterator_list(size, true, 0);    chains = new iq_iterator_list * [num_chains];    for (int i = 0; i < num_chains; ++i)	chains[i] = new iq_iterator_list(20, true, 2);    self_timed_list = new iq_iterator_list(20, true, 2);    //  Keep track of which instructions are "ready" to promote (or issue)    //    //  NOTE: Segment zero uses a different ready-list policy!    string seg_name = name() + ":RQ";    if (seg_num != 0) {	ready_list =	    new ready_queue_t<IQStation, RQ_Seg_Policy>	    (&(seg_queue->cpu), seg_name, size, en_pri);    } else {	ready_list =	    new ready_queue_t<IQStation, RQ_Issue_Policy>	    (&(seg_queue->cpu), seg_name, size, en_pri);    }    //    //  Initilize statistics, etc    //    total_insts = 0;    segment_full = 0;    segment_empty = 0;    cycles_low_ready = 0;    insts_fanout_loads = 0;    insts_waiting_for_loads = 0;    insts_waiting_for_unissued = 0;    for (int i = 0; i < SMT_MAX_THREADS; ++i) {	insts[i] = 0;    }}////  Copy an instruction into this segment. Add this instruction to//  the correct specified chain.////  The instruction is checked to see if it is in the "right" segment//  and if not, is automatically marked as ready to promote. This assumes//  that the queue _forward_of_this_segment_ is in a consistent state.////  This allows instructions that have not reached their correct segment//  to move forward, even though their chain-head isn't moving.//segment_t::iq_iteratorsegment_t::add(segment_t::iq_iterator &p){    unsigned n_chains = 0;    //  Add this iterator to this segment's queue    iq_it_list_iterator q = queue->add_tail(p);    if (q.isnull())	return 0;    //  So we can remove it from the segment queue    p->queue_entry = q;    p->queued = false;    p->rq_entry = 0;    p->segment_number = segment_number;    //    //  Add this instruction to it's chain(s)    //    for (int i = 0; i < TheISA::MaxInstSrcRegs; ++i) {	if (p->idep_info[i].chained) {	    unsigned c_num = p->idep_info[i].follows_chain;	    bool duplicate = false;	    for (int j = 0; j < i; ++j) {		if (p->idep_info[j].chained &&		    (p->idep_info[j].follows_chain == c_num)) {		    duplicate = true;		    break;		}	    }	    if (! duplicate) {		p->idep_info[i].chain_entry = chains[c_num]->add_tail(p);		++n_chains;	    } else {		p->idep_info[i].chain_entry = 0;	    }	}    }    //    //  Only if this instruction is completely unchained, do we add it    //  to the self-timed list    //    if (n_chains == 0)	p->idep_info[0].chain_entry = self_timed_list->add_tail(p);    //  Has this instruction reached the "right" segment yet?    if (segment_number != 0 && promotable(p))	enqueue(p);    ++insts[p->thread_number()];    ++total_insts;    //    //  SEGMENT 0:  Enqueue incoming instructions if their input    //              dependencies have been met.    //    if ((segment_number == 0) && p->ops_ready()) {	// we shouldn't become ready too early	//	assert(p->delay == 0);	enqueue(p);    }    return p;}////  Removing an instruction (actually an iterator to an instruction) from//  this queue segment////    (1) Remove the inst from the chain it's following (or the unchained list)//    (2) Remove the inst from the chain it's the head of//    (3) Remove the inst from the ready-queue (if queued)//    (4) Remove the iterator from the queue//segment_t::iq_iteratorsegment_t::remove(segment_t::iq_iterator &e){    iq_iterator next = e.next();    unsigned n_chains = 0;    if (e.notnull()) {	--insts[e->thread_number()];	--total_insts;	for (int i = 0; i < TheISA::MaxInstSrcRegs; ++i) {	    //	    //  Remove it from the correct chain...	    //	    if (e->idep_info[i].chained) {		unsigned chain = e->idep_info[i].follows_chain;		chains[chain]->remove(e->idep_info[i].chain_entry);		++n_chains;	    }	}	if (n_chains == 0)	    self_timed_list->remove(e->idep_info[0].chain_entry);	//	//  If this inst was queued	//	if (e->queued)	    ready_list->remove(e->rq_entry);	//	//  Finally, remove it from the segment queue list	//	queue->remove(e->queue_entry);    }    return next;}////  When the head instruction issues, we leave the instructions on//  the chain, but tell it to self-time.////  We may want to stop the self-time operation later...//voidsegment_t::self_time(ROBStation *rob){    if (rob->seq == (*chain_info)[rob->head_chain].creator)	(*chain_info)[rob->head_chain].self_timed = true;}////  Stop the chain from self-timing//voidsegment_t::stop_self_time(ROBStation *rob){    if (rob->seq == (*chain_info)[rob->head_chain].creator)	(*chain_info)[rob->head_chain].self_timed = false;}////  When the head instruction writes-back, we'll free the chain,//  Allowing the individual instructions to sit on the self_timed_list//voidsegment_t::release_chain(ROBStation *rob_entry){    iq_it_list_iterator n;    unsigned t_count = 0;    unsigned chain_num = rob_entry->head_chain;#if 0    // We don't want to free a chain that really belongs to someone else!    if (rob_entry->seq != seg_queue->chain_info[chain_num]->creator) 	return;#endif    //    //  Walk the list of instructions on this chain    //    iq_it_list_iterator i = chains[chain_num]->head();    for (; i.notnull(); i = n) {	unsigned n_chains = 0;	n = i.next();	for (int j = 0; j < TheISA::MaxInstSrcRegs; ++j) {	    if ((*i)->idep_info[j].chained) {		if ((*i)->idep_info[j].follows_chain == chain_num) {		    (*i)->idep_info[j].chained = false;		    //chains[chain_num]->remove(i);		    ++t_count;		} else {		    ++n_chains;		}	    }	}	//  If this inst is no longer on _any_ chain... put it on the	//  self-timed list	if (n_chains == 0) {	    (*i)->idep_info[0].chain_entry = self_timed_list->add_tail(*i);	    //  We need to set the self-timed flag in any register produced	    //  by this instruction	    ROBStation *rob = (*i)->rob_entry;	    for (int j = 0; j < rob->num_outputs; ++j) {		RegInfoElement &r =		    (*reg_info_table)[rob->thread_number][rob->onames[j]];		//		//  If this ROB entry is responsible for producing this		//  arch register result...		//		if (r.producer() && (r.producer()->seq == rob->seq)) {		    //  Clear the chained flag so that future consumers		    //  will know not to wait on the chain head		    r.unChain();		}	    }	}    }    //  instead of the individual removes above...    assert(chains[chain_num]->count() == t_count);    chains[chain_num]->clear();}voidsegment_t::check_promotable(){    //    //  All segments except segment 0 need to determine which instructions are    //  promotable.    //    //  Segment zero instructions are enqueued either on entry    //  (if no outstanding ideps) or when an instruction writes-back.    //    //    //  Walk the entire list of instructions...    //    (1)  Decrement the delay values as necessary    //    (2)  Enqueue instructions that are promotable    //    iq_it_list_iterator i = queue->head();    for (; i.notnull(); i = i.next()) {	bool recalc_position = false;	//	//  Do the easy case first	//	//  (this works because any instruction that is ops-ready MUST be	//   self-timed)	//	if ((*i)->ops_ready() && !(*i)->queued)	    enqueue(*i);	//	// Decrement the delay counters depending on the state of the chain	//	for (int j = 0; j < TheISA::MaxInstSrcRegs; ++j) {	    if (!(*i)->idep_ready[j]) {		if ((*i)->idep_info[j].chained) {		    unsigned c_num = (*i)->idep_info[j].follows_chain;		    //  If the head of this chain was promoted,		    //  or is self-timed, then we need to see if we are		    //  promotable		    if (chain_info->head_was_promoted(c_num, segment_number) ||			(*chain_info)[c_num].self_timed)		    {			if ((*chain_info)[c_num].self_timed) {			    decrement_delay(*i, j);			    recalc_position = true;			}			//  Don't enqueue for segment zero

⌨️ 快捷键说明

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