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

📄 storebuffer.cc

📁 linux下基于c++的处理器仿真平台。具有处理器流水线
💻 CC
字号:
/* * Copyright (c) 2000, 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 <cassert>#include <string>#include <vector>#include "base/cprintf.hh"#include "base/statistics.hh"#include "base/trace.hh"#include "cpu/exec_context.hh"#include "cpu/smt.hh"#include "encumbered/cpu/full/cpu.hh"#include "encumbered/cpu/full/readyq.hh"#include "encumbered/cpu/full/storebuffer.hh"#include "sim/stats.hh"using namespace std;voidStoreBufferEntry::dump(){    cprintf("%d: T%d PC=%#x EA=%#x\t%s%s%s\n",	    seq, thread, pc, virt_addr,	    FLAG_STRING(queued), FLAG_STRING(issued),	    FLAG_STRING(writeBarrierFlag));}////////////////////////////////////////////////////////////////////////////StoreBuffer::StoreBuffer(FullCPU *c, const string &n, unsigned _size)    : cpu(c), _name(n), size(_size){    queue = new res_list<StoreBufferEntry>(size, true, 0);    ready_list = new ready_queue_t<StoreBufferEntry,	storebuffer_readyq_policy>(&cpu, name() + ":RQ", true);    for (int i = 0; i < SMT_MAX_THREADS; ++i) {	insts[i] = 0;	writeBarrierPending[i] = false;    }}voidStoreBuffer::tick(){    //  Do stats    for (int i = 0; i < cpu->number_of_threads; ++i) {	occupancy[i] += insts[i];	if (writeBarrierPending[i]) {	    ++writeBarrierPendingCycles[i];	}    }    if (full()) {	++full_count;    }}voidStoreBuffer::regStats(){    using namespace Stats;    ready_list->regStats(name() + ":RQ", cpu->number_of_threads);    occupancy	.init(cpu->number_of_threads)	.name(name() + ":occupancy")	.desc("store buffer occupancy (cumulative)")	.flags(total)	;    full_count	.name(name() + ":full_count")	.desc("store buffer full events (cumulative)")	;    writeBarriers	.init(cpu->number_of_threads)	.name(name() + ":write_barriers")	.desc("number of write barrier operations")	.flags(total)	;    writeBarrierPendingCycles	.init(cpu->number_of_threads)	.name(name() + ":write_barrier_pending_cycles")	.desc("number of cycles write barriers were pending")	;}voidStoreBuffer::regFormulas(FullCPU *cpu){    using namespace Stats;    ready_list->regFormulas(name() + ":RQ", cpu->number_of_threads);    occ_rate	.name(name() + ":occ_rate")	.desc("store buffer occupancy rate")	.flags(total)	;    occ_rate = occupancy / cpu->numCycles;/** @todo Is this the right formula occ/sec/sec?? */    full_rate	.name(name() + ":full_rate")	.desc("store buffer full rate")	;    full_rate = full_count / cpu->numCycles;}boolStoreBuffer::add(unsigned thread_number, unsigned asid, int size,		 IntReg data,		 ExecContext *xc, Addr vaddr, Addr paddr,		 unsigned mem_req_flags, Addr pc, InstSeqNum seq,		 InstSeqNum fseq, unsigned queue_num){    if (full())	return false;    iterator p = queue->add_tail();    p->init_entry(thread_number, asid, size, xc,		  vaddr, paddr, mem_req_flags, pc, seq, fseq,		  queue_num);    p->data = new uint8_t[size];    memcpy(p->data, &data, size);    ++insts[thread_number];    if (!writeBarrierPending[thread_number]) {	//  Queue it immediately if there's no pending barrier	ready_list_enqueue(p);    } else {	DPRINTF(WriteBarrier, "deferring store seq %d T%d due to wmb\n",		p->seq, thread_number);    }    return true;}boolStoreBuffer::addCopy(unsigned thread_number, unsigned asid, int size,		     ExecContext *xc, Addr vaddr, Addr paddr,		     Addr src_vaddr, Addr src_paddr,		     unsigned mem_req_flags, Addr pc, InstSeqNum seq,		     InstSeqNum fseq, unsigned queue_num){    if (full())	return false;    iterator p = queue->add_tail();    p->initCopy(thread_number, asid, size, xc, vaddr, paddr, src_vaddr, 		src_paddr, mem_req_flags, pc, seq, fseq, queue_num);    ++insts[thread_number];    if (!writeBarrierPending[thread_number]) {	//  Queue it immediately if there's no pending barrier	ready_list_enqueue(p);    } else {	DPRINTF(WriteBarrier, "deferring store seq %d T%d due to wmb\n",		p->seq, thread_number);    }    return true;}StoreBuffer::iteratorStoreBuffer::findPrevInThread(int thread, iterator start){    // handle default case: start from tail    iterator p = start.notnull() ? start.prev() : queue->tail();    for (; p.notnull(); p = p.prev()) {	if (p->thread == thread) {	    return p;	}    }        return 0;}voidStoreBuffer::addWriteBarrier(int thread){    // Look for the most recent write from this thread.    iterator entry = findPrevInThread(thread);    if (entry.notnull()) {	// Found... mark it as the barrier, and set the barrier	// flag on this thread to keep new stores from being	// marked ready.	DPRINTF(WriteBarrier, "wmb T%d: marking seq %d\n", thread, entry->seq);	entry->writeBarrierFlag = true;	writeBarrierPending[thread] = true;    } else {	// Not found: no outstanding writes from this thread in the	// buffer.  The write barrier is just a no-op then.	DPRINTF(WriteBarrier, "wmb T%d: store buffer empty\n", thread);    }    ++writeBarriers[thread];}StoreBuffer::iteratorStoreBuffer::remove(iterator e){    iterator next = 0;    if (e.notnull()) {	next = e.next();	--insts[e->thread_number()];	queue->remove(e);	assert(!e->queued);	if (e->data) {	    delete [] e->data;	}    }    return next;}//  For debugging purposes, we don't want these functions inlinedvoidStoreBuffer::dump(){    cprintf("======================================================\n"	    "%s Dump (cycle %n)\n"	    "------------------------------------------------------\n"	    "  Total instruction: %u\n", name(), curTick, queue->count());    for (int i = 0; i < SMT_MAX_THREADS; ++i)	cprintf("  Thread %d instructions: %u\n", i, insts[i]);    cout << "------------------------------------------------------\n";    queue->dump();    cout << "======================================================\n\n";}voidStoreBuffer::raw_dump(){    cprintf("======================================================\n"	    "%s RAW Dump (cycle %n)\n"	    "------------------------------------------------------\n"	    "  Total instruction: %u\n", name(), curTick, queue->count());    for (int i = 0; i < SMT_MAX_THREADS; ++i)	cprintf("  Thread %d instructions: %u\n", i, insts[i]);    cout << "------------------------------------------------------\n";    queue->raw_dump();    cout << "======================================================\n\n";}voidStoreBuffer::rq_raw_dump(){    ready_list->raw_dump();}////////////////////////////////////////////////////////////////////////////voidStoreBuffer::completeStore(iterator entry){    assert(entry->issued);    if (entry->writeBarrierFlag) {	// There's a write barrier after this write. If there are	// older writes outstanding, transfer the barrier flag to the	// next older write.  If not, then the barrier is satisfied,	// and we can mark all younger writes as ready (up to the next	// barrier, if any).		DPRINTF(WriteBarrier, "wmb store seq %d completed\n", entry->seq);	int thread = entry->thread;	iterator p = findPrevInThread(thread, entry);	if (p.notnull()) {	    DPRINTF(WriteBarrier, "wmb moved to seq %d\n", p->seq);	    p->writeBarrierFlag = true;	}	else {	    bool stillPending = false; // assume we're going to clear flag	    p = entry.next();	    while (p.notnull()) {		if (p->thread == thread) {		    DPRINTF(WriteBarrier, "waking store seq %d\n", p->seq);		    ready_list_enqueue(p);		    if (p->writeBarrierFlag) {			// another barrier: stop waking up stores,			// and don't clear thread flag either			DPRINTF(WriteBarrier, "wmb encountered seq %d\n",				p->seq);			stillPending = true;			break;		    }		}		p = p.next();	    }	    assert(writeBarrierPending[thread]);	    writeBarrierPending[thread] = stillPending;	}    }    remove(entry);}voidSimCompleteStoreEvent::process(){    sb->completeStore(entry);}const char *SimCompleteStoreEvent::description(){    return "store completion";}

⌨️ 快捷键说明

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