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

📄 cpu.cc

📁 linux下基于c++的处理器仿真平台。具有处理器流水线
💻 CC
📖 第 1 页 / 共 2 页
字号:
/* * 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 <cmath>#include <cstdio>#include <cstdlib>#include <iostream>#include <iomanip>#include <list>#include <sstream>#include <string>#include "base/cprintf.hh"#include "base/inifile.hh"#include "base/loader/symtab.hh"#include "base/misc.hh"#include "base/pollevent.hh"#include "base/range.hh"#include "base/stats/events.hh"#include "base/trace.hh"#include "cpu/base.hh"#include "cpu/exec_context.hh"#include "cpu/exetrace.hh"#include "cpu/sampler/sampler.hh"#include "cpu/simple/cpu.hh"#include "cpu/smt.hh"#include "cpu/static_inst.hh"#include "mem/base_mem.hh"#include "mem/mem_interface.hh"#include "sim/builder.hh"#include "sim/debug.hh"#include "sim/host.hh"#include "sim/sim_events.hh"#include "sim/sim_object.hh"#include "sim/stats.hh"#if FULL_SYSTEM#include "base/remote_gdb.hh"#include "mem/functional/memory_control.hh"#include "mem/functional/physical.hh"#include "sim/system.hh"#include "targetarch/alpha_memory.hh"#include "targetarch/vtophys.hh"#else // !FULL_SYSTEM#include "mem/functional/functional.hh"#endif // FULL_SYSTEMusing namespace std;SimpleCPU::TickEvent::TickEvent(SimpleCPU *c, int w)    : Event(&mainEventQueue, CPU_Tick_Pri), cpu(c), width(w){}voidSimpleCPU::TickEvent::process(){    int count = width;    do {	cpu->tick();    } while (--count > 0 && cpu->status() == Running);}const char *SimpleCPU::TickEvent::description(){    return "SimpleCPU tick event";}SimpleCPU::CacheCompletionEvent::CacheCompletionEvent(SimpleCPU *_cpu)    : Event(&mainEventQueue), cpu(_cpu){}void SimpleCPU::CacheCompletionEvent::process(){    cpu->processCacheCompletion();}const char *SimpleCPU::CacheCompletionEvent::description(){    return "SimpleCPU cache completion event";}SimpleCPU::SimpleCPU(Params *p)    : BaseCPU(p), tickEvent(this, p->width), xc(NULL),      cacheCompletionEvent(this){    _status = Idle;#if FULL_SYSTEM    xc = new ExecContext(this, 0, p->system, p->itb, p->dtb, p->mem);    // initialize CPU, including PC    TheISA::initCPU(&xc->regs);#else    xc = new ExecContext(this, /* thread_num */ 0, p->process, /* asid */ 0);#endif // !FULL_SYSTEM    icacheInterface = p->icache_interface;    dcacheInterface = p->dcache_interface;    memReq = new MemReq();    memReq->xc = xc;    memReq->asid = 0;    memReq->data = new uint8_t[64];    numInst = 0;    startNumInst = 0;    numLoad = 0;    startNumLoad = 0;    lastIcacheStall = 0;    lastDcacheStall = 0;    execContexts.push_back(xc);}SimpleCPU::~SimpleCPU(){}voidSimpleCPU::switchOut(Sampler *s){    sampler = s;    if (status() == DcacheMissStall) {	DPRINTF(Sampler,"Outstanding dcache access, waiting for completion\n");	_status = DcacheMissSwitch;    }    else {	_status = SwitchedOut;    	if (tickEvent.scheduled())	    tickEvent.squash();	sampler->signalSwitched();    }}voidSimpleCPU::takeOverFrom(BaseCPU *oldCPU){    BaseCPU::takeOverFrom(oldCPU);    assert(!tickEvent.scheduled());    // if any of this CPU's ExecContexts are active, mark the CPU as    // running and schedule its tick event.    for (int i = 0; i < execContexts.size(); ++i) {	ExecContext *xc = execContexts[i];	if (xc->status() == ExecContext::Active && _status != Running) {	    _status = Running;	    tickEvent.schedule(curTick);	}    }}voidSimpleCPU::activateContext(int thread_num, int delay){    assert(thread_num == 0);    assert(xc);    assert(_status == Idle);    notIdleFraction++;    scheduleTickEvent(delay);    _status = Running;}voidSimpleCPU::suspendContext(int thread_num){    assert(thread_num == 0);    assert(xc);    assert(_status == Running);    notIdleFraction--;    unscheduleTickEvent();    _status = Idle;}voidSimpleCPU::deallocateContext(int thread_num){    // for now, these are equivalent    suspendContext(thread_num);}voidSimpleCPU::haltContext(int thread_num){    // for now, these are equivalent    suspendContext(thread_num);}voidSimpleCPU::regStats(){    using namespace Stats;    BaseCPU::regStats();    numInsts	.name(name() + ".num_insts")        .desc("Number of instructions executed")	;    numMemRefs	.name(name() + ".num_refs")	.desc("Number of memory references")	;    notIdleFraction	.name(name() + ".not_idle_fraction")	.desc("Percentage of non-idle cycles")	;	    idleFraction	.name(name() + ".idle_fraction")	.desc("Percentage of idle cycles")	;    icacheStallCycles	.name(name() + ".icache_stall_cycles")	.desc("ICache total stall cycles")	.prereq(icacheStallCycles)	;    dcacheStallCycles	.name(name() + ".dcache_stall_cycles")        .desc("DCache total stall cycles")	.prereq(dcacheStallCycles)	;    idleFraction = constant(1.0) - notIdleFraction;}voidSimpleCPU::resetStats(){    startNumInst = numInst;    notIdleFraction = (_status != Idle);}voidSimpleCPU::serialize(ostream &os){    BaseCPU::serialize(os);    SERIALIZE_ENUM(_status);    SERIALIZE_SCALAR(inst);    nameOut(os, csprintf("%s.xc", name()));    xc->serialize(os);    nameOut(os, csprintf("%s.tickEvent", name()));    tickEvent.serialize(os);    nameOut(os, csprintf("%s.cacheCompletionEvent", name()));    cacheCompletionEvent.serialize(os);}voidSimpleCPU::unserialize(Checkpoint *cp, const string &section){    BaseCPU::unserialize(cp, section);    UNSERIALIZE_ENUM(_status);    UNSERIALIZE_SCALAR(inst);    xc->unserialize(cp, csprintf("%s.xc", section));    tickEvent.unserialize(cp, csprintf("%s.tickEvent", section));    cacheCompletionEvent	.unserialize(cp, csprintf("%s.cacheCompletionEvent", section));}voidchange_thread_state(int thread_number, int activate, int priority){}FaultSimpleCPU::copySrcTranslate(Addr src){    static bool no_warn = true;    int blk_size = (dcacheInterface) ? dcacheInterface->getBlockSize() : 64;    // Only support block sizes of 64 atm.    assert(blk_size == 64);    int offset = src & (blk_size - 1);    // Make sure block doesn't span page    if (no_warn &&	(src & TheISA::PageMask) != ((src + blk_size) & TheISA::PageMask) &&	(src >> 40) != 0xfffffc) {	warn("Copied block source spans pages %x.", src);	no_warn = false;    }    memReq->reset(src & ~(blk_size - 1), blk_size);        // translate to physical address    Fault fault = xc->translateDataReadReq(memReq);        assert(fault != Alignment_Fault);    if (fault == No_Fault) {	xc->copySrcAddr = src;	xc->copySrcPhysAddr = memReq->paddr + offset;    } else {	xc->copySrcAddr = 0;	xc->copySrcPhysAddr = 0;    }    return fault;}FaultSimpleCPU::copy(Addr dest){    static bool no_warn = true;    int blk_size = (dcacheInterface) ? dcacheInterface->getBlockSize() : 64;    // Only support block sizes of 64 atm.    assert(blk_size == 64);    uint8_t data[blk_size];    //assert(xc->copySrcAddr);    int offset = dest & (blk_size - 1);    // Make sure block doesn't span page    if (no_warn &&	(dest & TheISA::PageMask) != ((dest + blk_size) & TheISA::PageMask) &&	(dest >> 40) != 0xfffffc) {	no_warn = false;	warn("Copied block destination spans pages %x. ", dest);    }    memReq->reset(dest & ~(blk_size -1), blk_size);    // translate to physical address    Fault fault = xc->translateDataWriteReq(memReq);        assert(fault != Alignment_Fault);    if (fault == No_Fault) {	Addr dest_addr = memReq->paddr + offset;	// Need to read straight from memory since we have more than 8 bytes.	memReq->paddr = xc->copySrcPhysAddr;	xc->mem->read(memReq, data);	memReq->paddr = dest_addr;	xc->mem->write(memReq, data);	if (dcacheInterface) {	    memReq->cmd = Copy;	    memReq->completionEvent = NULL;	    memReq->paddr = xc->copySrcPhysAddr;	    memReq->dest = dest_addr;	    memReq->size = 64;	    memReq->time = curTick;	    dcacheInterface->access(memReq);	}    }    return fault;}// precise architected memory state accessor macrostemplate <class T>FaultSimpleCPU::read(Addr addr, T &data, unsigned flags){    if (status() == DcacheMissStall || status() == DcacheMissSwitch) {	Fault fault = xc->read(memReq,data);	if (traceData) {	    traceData->setAddr(addr);	}	return fault;    }    memReq->reset(addr, sizeof(T), flags);    // translate to physical address    Fault fault = xc->translateDataReadReq(memReq);    // if we have a cache, do cache access too    if (fault == No_Fault && dcacheInterface) {	memReq->cmd = Read;	memReq->completionEvent = NULL;	memReq->time = curTick;	MemAccessResult result = dcacheInterface->access(memReq);	// Ugly hack to get an event scheduled *only* if the access is	// a miss.  We really should add first-class support for this	// at some point.	if (result != MA_HIT && dcacheInterface->doEvents()) {	    memReq->completionEvent = &cacheCompletionEvent;	    lastDcacheStall = curTick;	    unscheduleTickEvent();	    _status = DcacheMissStall;	} else {	    // do functional access	    fault = xc->read(memReq, data);	    	}    } else if(fault == No_Fault) {	// do functional access	fault = xc->read(memReq, data);	    }    if (!dcacheInterface && (memReq->flags & UNCACHEABLE))	recordEvent("Uncached Read");    return fault;}#ifndef DOXYGEN_SHOULD_SKIP_THIStemplateFaultSimpleCPU::read(Addr addr, uint64_t &data, unsigned flags);templateFaultSimpleCPU::read(Addr addr, uint32_t &data, unsigned flags);templateFaultSimpleCPU::read(Addr addr, uint16_t &data, unsigned flags);

⌨️ 快捷键说明

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