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

📄 dd_queue.cc

📁 linux下基于c++的处理器仿真平台。具有处理器流水线
💻 CC
字号:
/* * Copyright (c) 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 "base/statistics.hh"#include "encumbered/cpu/full/cpu.hh"#include "encumbered/cpu/full/dd_queue.hh"#include "sim/stats.hh"using namespace std;//============================================================================////  The Decode-Dispatch Queue places instructions one at a time into a//  packetizing instruction pipeline. If the entire queue is N cycles long,//  the instruction pipeline is N-1 stages.////  If the queue is BLOCKING, the instructions leave the pipeline for a single//  skid buffer from which they can be pulled one at a time.////  If the queue is NON-BLOCKING, the instructions leave the pipeline for a//  small skid buffer (only holds one packet) during tick(). The packet is//  de-composed into individual fetch records at this time.//   -> Instructions can be dispatched from this buffer//   -> If the instructions are there during the next cycle, they are moved//      into the appropriate per-thread skid buffer.//      NOTE: instructions in the per-thread skid buffers are ALWAYS OLDER//            than the instructions in the small skid buffer!//////  Constructor//DecodeDispatchQueue::DecodeDispatchQueue(FullCPU *_cpu,					 unsigned length, unsigned bw,					 bool nonblocking){    bandwidth = bw;    nonBlocking = nonblocking;    maxInst = bw * length;    cpu = _cpu;    //  We need a 2-stage length, at minimum...    assert(length > 1);    pipeline = new InstructionPipe(length - 1, bw);    dispatchBuffer = new InstructionFifo(bw);    if (nonBlocking) {	for (int i = 0; i < SMT_MAX_THREADS; ++i) {	    // each skid buffer must be able to hold all the instructions	    // in the pipeline	    skidBuffers[i] = new InstructionFifo(maxInst);	}    }    instsTotal = 0;    memset(instsThread, 0, sizeof(instsThread));}unsignedDecodeDispatchQueue::addBW(unsigned thread){    int bw;    if (!nonBlocking) {	bw = pipeline->addBW();    } else {	// the number of slots available for this thread in the ENTIRE queue	bw = maxInst - pipeline->count(thread) - dispatchBuffer->count(thread)	    - skidBuffers[thread]->count();	// ... limited by the pipe bw	if (bw > pipeline->addBW())	    bw = pipeline->addBW();    }    return bw;}voidDecodeDispatchQueue::add(DynInst *inst){    // instructions added to the queue must NOT be squashed!    assert(addBW(inst->thread_number) > 0);    pipeline->add(inst);    ++instsTotal;    ++instsThread[inst->thread_number];#if 0    if (pipeline->count() > 112 || dispatchBuffer->count() > 8	|| skidBuffers[0]->count() > 120)    {	cerr << "OOPS! total is " << instsTotal << ", pipe="	     << pipeline->count() << ", dbuf=" << dispatchBuffer->count()	     << ", skid=" << skidBuffers[0]->count() << endl;    }    if (pipeline->count() + dispatchBuffer->count() + skidBuffers[0]->count()	> 120)    {	cerr << "OOPS 2! total is " << instsTotal << ", pipe="	     << pipeline->count() << ", dbuf=" << dispatchBuffer->count()	     << ", skid=" << skidBuffers[0]->count() << endl;    }    if (pipeline->count() + dispatchBuffer->count() + skidBuffers[0]->count()	!= instsTotal)    {	cerr << "OOPS 3! total is " << instsTotal << ", pipe="	     << pipeline->count() << ", dbuf=" << dispatchBuffer->count()	     << ", skid=" << skidBuffers[0]->count() << endl;    }#endif}boolDecodeDispatchQueue::loadable(){    return pipeline->stageOccupancy(0) == 0;}DynInst *DecodeDispatchQueue::peek(unsigned thread){    DynInst *inst = 0;    if (!nonBlocking) {	//	//  No skid-buffers, just grab the next instruction from the end of	//  the pipeline (which is actually the dispatchBuffer)	//  ==> Ignore the thread arg!!!	//	inst = dispatchBuffer->peek();    } else {	//	//  First, look to the skid buffer associated with this thread. If	//  that is empty, look to the dispatchBuffer	//	if (skidBuffers[thread]->count()) {	    inst = skidBuffers[thread]->peek();	} else {	    inst = dispatchBuffer->peek();	    // the dispatch buffer should only contain instructions from	    // one thread...	    // we shouldn't be peeking unless we know that there are	    // instructions from the thread available!	    // (squashed instructions have inst == NULL)	    assert(inst == 0 || inst->thread_number == thread);	}    }    return inst;}voidDecodeDispatchQueue::remove(unsigned thread){    if (!nonBlocking) {	//	//  No skid-buffers, remove the next instruction from the end of	//  the pipeline (which is actually the dispatchBuffer)	//  ==> Ignore the thread arg!!!	//	dispatchBuffer->remove();    } else {	//	//  First, look to the skid buffer associated with this thread. If	//  that is empty, look to the dispatchBuffer	//	if (skidBuffers[thread]->count())	    skidBuffers[thread]->remove();	else	    dispatchBuffer->remove();    }    --instsTotal;    --instsThread[thread];#if 0    if (pipeline->count() > 112 || dispatchBuffer->count() > 8	|| skidBuffers[0]->count() > 120)    {	cerr << "OOPS! total is " << instsTotal << ", pipe="	     << pipeline->count() << ", dbuf=" << dispatchBuffer->count()	     << ", skid=" << skidBuffers[0]->count() << endl;    }    if (pipeline->count() + dispatchBuffer->count() + skidBuffers[0]->count()	> 120)    {	cerr << "OOPS 2! total is " << instsTotal << ", pipe="	     << pipeline->count() << ", dbuf=" << dispatchBuffer->count()	     << ", skid=" << skidBuffers[0]->count() << endl;    }    if (pipeline->count() + dispatchBuffer->count() + skidBuffers[0]->count()	!= instsTotal)    {	cerr << "OOPS 3! total is " << instsTotal << ", pipe="	     << pipeline->count() << ", dbuf=" << dispatchBuffer->count()	     << ", skid=" << skidBuffers[0]->count() << endl;    }#endif}unsignedDecodeDispatchQueue::squash(){    unsigned cnt = pipeline->squash();    cnt += dispatchBuffer->squash();    if (nonBlocking)	for (int i = 0; i < SMT_MAX_THREADS; ++i)	    cnt += skidBuffers[i]->squash();    return cnt;}unsignedDecodeDispatchQueue::squash(unsigned thread){    unsigned cnt = pipeline->squash(thread);    cnt += dispatchBuffer->squash(thread);    if (nonBlocking)	cnt += skidBuffers[thread]->squash(thread);    return cnt;}////  This should NOT be called between dispatch() and decode()//voidDecodeDispatchQueue::tick_stats(){    for (int i = 0; i < cpu->number_of_threads; ++i)	cum_insts[i] += instsThread[i];#if 0    if (pipeline->count() > 112 || dispatchBuffer->count() > 8	|| skidBuffers[0]->count() > 120)    {	cerr << "OOPS! total is " << instsTotal << ", pipe="	     << pipeline->count() << ", dbuf=" << dispatchBuffer->count()	     << ", skid=" << skidBuffers[0]->count() << endl;    }    if (pipeline->count() + dispatchBuffer->count() + skidBuffers[0]->count()	> 120)    {	cerr << "OOPS 2! total is " << instsTotal << ", pipe="	     << pipeline->count() << ", dbuf=" << dispatchBuffer->count()	     << ", skid=" << skidBuffers[0]->count() << endl;    }    if (pipeline->count() + dispatchBuffer->count() + skidBuffers[0]->count()	!= instsTotal)    {	cerr << "OOPS 3! total is " << instsTotal << ", pipe="	     << pipeline->count() << ", dbuf=" << dispatchBuffer->count()	     << ", skid=" << skidBuffers[0]->count() << endl;    }#endif}////  This should be called between dispatch() and decode()//voidDecodeDispatchQueue::tick(){    //    //  First: For a non-blocking queue, move any instructions remaining in the    //         dispatch buffer to the appropriate skid buffer    //    if (nonBlocking && dispatchBuffer->count()) {	do {	    unsigned thread;	    //  Returns the thread number via arg list...	    DynInst * inst = dispatchBuffer->remove(&thread);	    if (inst != 0) {		skidBuffers[thread]->add(inst);	    } else {		// we'll drop it here... not really different from dropping it		// at dispatch or before it would go into skid buffers...		--instsTotal;		--instsThread[thread];	    }	} while (dispatchBuffer->count());    }    //    //  Second: Move any instructions in the bottom of the pipeline into the    //          dispatch buffer    //    //          This is where we de-packetize the instructions    //    if (pipeline->instsAvailable()) {	InstructionPacket &pkt = pipeline->peek();	for (int idx = 0; idx < pipeline->instsAvailable(); ++idx) {	    if (pkt.inst(idx) != 0) {		dispatchBuffer->add( pkt.inst(idx) );	    } else {		// ==> Instruction was squashed		//   Since we don't put squashed instructions into		//   the dispatch buffer, we need to decrement the		//   instruction count here		--instsThread[pkt.threadNumber()];		--instsTotal;	    }	}	// clear the end of the pipeline	pipeline->clearTail();    }    //    //  Third: Advance the pipeline    //    pipeline->tick();}unsignedDecodeDispatchQueue::count(){    unsigned cnt = pipeline->count() + dispatchBuffer->count();    if (nonBlocking)	for (int i = 0; i < SMT_MAX_THREADS; ++i)	    cnt += skidBuffers[i]->count();    return cnt;}unsignedDecodeDispatchQueue::count(unsigned thread){    unsigned cnt = pipeline->count(thread) + dispatchBuffer->count(thread);    if (nonBlocking)	cnt += skidBuffers[thread]->count();    return cnt;}unsignedDecodeDispatchQueue::instsAvailable(){    unsigned cnt = dispatchBuffer->count();    if (nonBlocking)	for (int i = 0; i < SMT_MAX_THREADS; ++i)	    cnt += skidBuffers[i]->count();    return cnt;}unsignedDecodeDispatchQueue::instsAvailable(unsigned thread){    unsigned cnt = dispatchBuffer->count(thread);    if (nonBlocking)	cnt += skidBuffers[thread]->count();    return cnt;}voidDecodeDispatchQueue::dump(){    cout << "===========================================" << endl;    cout << "Decode-Dispatch Queue (" << count() << ") elements" << endl;    for (int i = 0; i < SMT_MAX_THREADS; ++i) {	cout << "  Thread " << i << " = " << count(i) << endl;    }    cout << "-------------------------------------------" << endl;    pipeline->dump();    cout << "-------------------------------------------" << endl;    dispatchBuffer->dump();    cout << "-------------------------------------------" << endl;    if (nonBlocking) {	for (int i = 0; i < SMT_MAX_THREADS; ++i) {	    cout << "-------------------------------------------" << endl;	    cout << "  Thread " << i << " Skid Buffer:" << endl;	    skidBuffers[i]->dump();	}    }    cout << "===========================================" << endl << endl;}voidDecodeDispatchQueue::dump(unsigned thread){    cout << "===========================================" << endl;    cout << "Decode-Dispatch Queue (" << count() << ") elements" << endl;    cout << "  Thread " << thread << " = " << count(thread) << endl;    cout << "-------------------------------------------" << endl;    pipeline->dumpThread(thread);    cout << "-------------------------------------------" << endl;    dispatchBuffer->dump(thread);    if (nonBlocking) {	cout << "-------------------------------------------" << endl;	cout << "  Thread " << thread << " Skid Buffer:" << endl;	skidBuffers[thread]->dump();    }    cout << "===========================================" << endl << endl;}////  This should be called between dispatch() and decode()//voidDecodeDispatchQueue::regStats(){    using namespace Stats;    cum_insts	.init(cpu->number_of_threads)	.name(cpu->name() + ".DDQ:count")	.desc("cum count of instructions")	.flags(total)	;}voidDecodeDispatchQueue::regFormulas(){    using namespace Stats;    ddq_rate	.name(cpu->name() + ".DDQ:rate")	.desc("average number of instructions")	.flags(total)	.precision(0)	;    ddq_rate = cum_insts / cpu->numCycles;}

⌨️ 快捷键说明

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