📄 bus.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. *//** * @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 + -