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

📄 bus.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. *//** * @file * Definition of the Bus class, DeliverEvent, and arbitration events. */#include <cassert>#include <sstream>#include <string>#include <vector>#include "base/cprintf.hh"#include "base/intmath.hh"#include "base/misc.hh"#include "base/callback.hh"#include "cpu/smt.hh"#include "mem/bus/bus.hh"#include "mem/bus/bus_interface.hh"#include "sim/builder.hh"#include "sim/host.hh"#include "sim/stats.hh"using namespace std;/** The maximum value of type Tick. */#define TICK_T_MAX ULL(0x3FFFFFFFFFFFFF)// NOTE: all times are stored internally as cpu ticks//       A conversion is made from provided time to//       bus cycles// bus constructorBus::Bus(const string &_name,	 HierParams *hier_params,	 int _width,	 int _clock)    : BaseHier(_name, hier_params){    width = _width;    clockRate = _clock;    if (width < 1 || (width & (width - 1)) != 0)	fatal("memory bus width must be positive non-zero and a power of two");    if (clockRate < 1)	fatal("memory bus clock must be positive and non-zero");    nextDataFree = 0;    nextAddrFree = 0;    runAddrLast = 0;    runDataLast = 0;    busBlockedTime = 0;    numInterfaces = 0;    blocked = false;    waitingFor = -1;    addrArbiterEvent = new AddrArbiterEvent(this);    dataArbiterEvent = new DataArbiterEvent(this);}Bus::~Bus(){    delete addrArbiterEvent;    delete dataArbiterEvent;}/* register bus stats */voidBus::regStats(){    using namespace Stats;    addrIdleCycles	.name(name() + ".addr_idle_cycles")	.desc("number of cycles bus was idle")	;    addrIdleFraction	.name(name() + ".addr_idle_fraction")	.desc("fraction of time addr bus was idle")	;    addrIdleFraction = addrIdleCycles / simTicks;    addrQdly	.init(maxThreadsPerCPU)	.name(name() + ".addr_queued_cycles")	.desc("total number of queued cycles for all requests")	.flags(total)	;    addrRequests	.init(maxThreadsPerCPU)	.name(name() + ".addr_requests")	.desc("number of transmissions on bus")	.flags(total)	;    addrQueued	.name(name() + ".addr_queued")	.desc("average queueing delay seen by bus request")	.flags(total)	;    addrQueued = addrQdly / addrRequests;    dataIdleCycles	.name(name() + ".data_idle_cycles")	.desc("number of cycles bus was idle")	;    dataIdleFraction	.name(name() + ".data_idle_fraction")	.desc("fraction of time data bus was idle")	;    dataIdleFraction = dataIdleCycles / simTicks;    dataQdly	.init(maxThreadsPerCPU)	.name(name() + ".data_queued_cycles")	.desc("total number of queued cycles for all requests")	.flags(total)	;    dataRequests	.init(maxThreadsPerCPU)	.name(name() + ".data_requests")	.desc("number of transmissions on bus")	.flags(total)	;    dataQueued	.name(name() + ".data_queued")	.desc("average queueing delay seen by bus request")	.flags(total)	;    dataQueued = dataQdly / dataRequests;    busBlocked	.name(name() + ".bus_blocked")	.desc("number of times bus was blocked")	;    busBlockedCycles	.name(name() + ".bus_blocked_cycles")	.desc("number of cycles bus was blocked")	;    busBlockedFraction	.name(name() + ".bus_blocked_fraction")	.desc("fraction of time bus was blocked")	;    busBlockedFraction = busBlockedCycles / simTicks;    nullGrants	.name(name() + ".null_grants")	.desc("number of null grants (wasted cycles)")	;}voidBus::resetStats(){    nextDataFree = curTick;    nextAddrFree = curTick;}voidBus::requestDataBus(int id, Tick time){    assert(doEvents());    assert(time>=curTick);    DPRINTF(Bus, "id:%d Requesting Data Bus for cycle: %d\n", id, time);    if (dataBusRequests[id].requested) {	return;    }    dataBusRequests[id].requested = true;    // fix this: should we set the time to bus cycle?    dataBusRequests[id].requestTime = time;    scheduleArbitrationEvent(dataArbiterEvent,time,nextDataFree);}voidBus::requestAddrBus(int id, Tick time){    assert(doEvents());    assert(time>=curTick);    DPRINTF(Bus, "id:%d Requesting Address Bus for cycle: %d\n", id, time);    if (addrBusRequests[id].requested) {	return; // already requested    }    addrBusRequests[id].requested = true;    addrBusRequests[id].requestTime = time;    if (!isBlocked()) {	scheduleArbitrationEvent(addrArbiterEvent,time,nextAddrFree,2);    }}voidBus::arbitrateAddrBus(){    assert(curTick > runAddrLast);    runAddrLast = curTick;    assert(doEvents());    int grant_id;    int old_grant_id;; // used for rescheduling#ifndef NDEBUG    bool found =#endif	findOldestRequest(addrBusRequests,grant_id,old_grant_id);    assert(found);    // grant_id is earliest outstanding request    // old_grant_id is second earliest request    DPRINTF(Bus, "addr bus granted to id %d\n", grant_id);    addrBusRequests[grant_id].requested = false; // clear request bit    bool do_request = interfaces[grant_id]->grantAddr();    if (do_request) {	addrBusRequests[grant_id].requested = true;	addrBusRequests[grant_id].requestTime = curTick;    }    Tick grant_time;    Tick old_grant_time = (old_grant_id == -1) ? TICK_T_MAX :	addrBusRequests[old_grant_id].requestTime;    if (!isBlocked()) {	grant_time = old_grant_time;	// find earliest outstand request, need to re-search because could have	// rerequests in grantAddr()	if (addrBusRequests[grant_id].requested	    && addrBusRequests[grant_id].requestTime < old_grant_time) {	    grant_time = addrBusRequests[grant_id].requestTime;	}	if (grant_time != TICK_T_MAX) {	    if (!addrArbiterEvent->scheduled()) {		scheduleArbitrationEvent(addrArbiterEvent,grant_time,nextAddrFree,2);	    }	} else {	    // fix up any scheduling errors	    if (addrArbiterEvent->scheduled() && nextAddrFree > addrArbiterEvent->when()) {		addrArbiterEvent->reschedule(nextAddrFree);	    }	}    } else {	if (addrArbiterEvent->scheduled()) {	    addrArbiterEvent->deschedule();	}    }}voidBus::arbitrateDataBus(){    assert(curTick>runDataLast);    runDataLast = curTick;    assert(doEvents());    int grant_id;    int old_grant_id;#ifndef NDEBUG    bool found =#endif	findOldestRequest(dataBusRequests,grant_id,old_grant_id);    assert(found);    DPRINTF(Bus, "Data bus granted to id %d\n", grant_id);    dataBusRequests[grant_id].requested = false; // clear request bit    interfaces[grant_id]->grantData();    Tick grant_time;    Tick old_grant_time = (old_grant_id == -1) ? TICK_T_MAX :	dataBusRequests[old_grant_id].requestTime;    //reschedule arbiter here    grant_time = old_grant_time;    // find earliest outstand request, need to re-search because could have    // rerequests in grantData()    if (dataBusRequests[grant_id].requested	&& dataBusRequests[grant_id].requestTime < old_grant_time) {	grant_time = dataBusRequests[grant_id].requestTime;    }    if (grant_time != TICK_T_MAX) {	scheduleArbitrationEvent(dataArbiterEvent,grant_time,nextDataFree);    }}boolBus::sendAddr(MemReqPtr &req, Tick origReqTime){    // update statistics       assert(doEvents());    if (!req) {	// if the bus was granted in error	nullGrants++;	DPRINTF(Bus, "null request");	return false;    }        addrQdly[req->thread_num] += curTick - origReqTime;    addrIdleCycles += curTick - nextAddrFree;    // Advance nextAddrFree to next clock cycle    nextAddrFree = nextBusClock(curTick);    // put it here so we know requesting thread    addrRequests[req->thread_num]++;

⌨️ 快捷键说明

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