📄 bus.cc
字号:
int responding_interface_id = -1; MemAccessResult retval = BA_NO_RESULT; MemAccessResult tmp_retval = BA_NO_RESULT; DPRINTF(Bus, "issuing req %s addr %x from id %d, name %s\n", req->cmd.toString(), req->paddr, req->busId, interfaces[req->busId]->name()); for (int i = 0; i < numInterfaces; i++) { if (interfaces[req->busId] != transmitInterfaces[i]) { tmp_retval = transmitInterfaces[i]->access(req); } else { tmp_retval = BA_NO_RESULT; } if (req->isNacked()) { //Can only get a NACK if the block was owned, it won't satisfy assert(!req->isSatisfied()); //Clear the flags before retrying request DPRINTF(Bus, "Blk: %x Nacked by id:%d\n", req->paddr & (((ULL(1))<<48)-1), i); req->flags &= ~NACKED_LINE; return false; //Signal failure, it will retry for bus } if (tmp_retval != BA_NO_RESULT) { if (retval != BA_NO_RESULT) { fatal("Two suppliers for address %#x on bus %s", req->paddr, name()); } retval = tmp_retval; responding_interface_id = transmitInterfaces[i]->getId(); } } if (retval == BA_NO_RESULT && (req->cmd.isRead() || req->cmd.isWrite())) { fatal("No supplier for address %#x on bus %s", req->paddr, name()); } if (retval == BA_SUCCESS) { DPRINTF(Bus, "request for blk %x from id:%d satisfied by id:%d\n", req->paddr & (((ULL(1))<<48)-1), req->busId, responding_interface_id); } // If any request if blocked by a memory interface, it blocks // the whole bus because the request is still outstanding on // the wire. We cannot let _any_ other request go through. switch (retval) { case BA_BLOCKED: DPRINTF(Bus, "Bus Blocked, waiting for id:%d on blk_adr: %x\n", responding_interface_id, req->paddr & (((ULL(1))<<48)-1)); blockedReq = req; blockSync = true; //This is a synchronus block return true; break; case BA_SUCCESS: break; case BA_NO_RESULT: break; default: panic("Illegal bus result %d\n", retval); break; }; assert(curTick % clockRate == 0); //New callback function //May want to use this to move some requests in front of a NACKED //request (depending on consistency model interfaces[req->busId]->snoopResponseCall(req); return true;}void Bus::delayData(int size){ int transfer_cycles = DivCeil(size, width); //int transfer_time = transfer_cycles * clockRate; assert(curTick >= nextDataFree); dataIdleCycles += (curTick - nextDataFree); // assumes we are cycle aligned right now assert(curTick % clockRate == 0); nextDataFree = nextBusClock(curTick,transfer_cycles);}voidBus::sendData(MemReqPtr &req, Tick origReqTime){ // put it here so we know requesting thread dataRequests[req->thread_num]++; assert(doEvents()); int transfer_cycles = DivCeil(req->size, width); assert(curTick >= nextDataFree); dataQdly[req->thread_num] += curTick - origReqTime; dataIdleCycles += (curTick - nextDataFree); nextDataFree = nextBusClock(curTick,transfer_cycles); DeliverEvent *tmp = new DeliverEvent(interfaces[req->busId], req); // let the cache figure out Critical word first // schedule event after first block delivered tmp->schedule(curTick + clockRate);}voidBus::sendAck(MemReqPtr &req, Tick origReqTime){ addrRequests[req->thread_num]++; assert(doEvents()); addrQdly[req->thread_num] += curTick - origReqTime; addrIdleCycles += curTick - nextAddrFree; // Advance nextAddrFree to next clock cycle nextAddrFree = nextBusClock(curTick); DeliverEvent *tmp = new DeliverEvent(interfaces[req->busId], req); tmp->schedule(curTick + clockRate); DPRINTF(Bus, "sendAck: scheduling deliver for %x on id %d @ %d\n", req->paddr, req->busId, curTick + clockRate);}intBus::registerInterface(BusInterface<Bus> *bi, bool master){ assert(numInterfaces == interfaces.size()); interfaces.push_back(bi); addrBusRequests.push_back(BusRequestRecord()); dataBusRequests.push_back(BusRequestRecord()); DPRINTF(Bus, "registering interface %s as %s\n", bi->name(), master ? "master" : "slave"); if (master) { transmitInterfaces.insert(transmitInterfaces.begin(),bi); } else { transmitInterfaces.push_back(bi); } return numInterfaces++;}voidBus::clearBlocked(int id){ assert(!isBlocked() || doEvents()); if (isBlocked() && waitingFor == id) { DPRINTF(Bus, "Unblocking\n"); if (blockSync) { DPRINTF(Bus, "Bus UnBlocked, waiting for id:%d on blk_adr: %x\n", id, blockedReq->paddr & (((ULL(1))<<48)-1)); } //Only arbitrate if request exists //Need to make sure it wasn't requested for later time int grant_id, old_grant_id; // used for rescheduling if (findOldestRequest(addrBusRequests,grant_id,old_grant_id)) { nextAddrFree = nextBusClock(curTick,1); Tick time = addrBusRequests[grant_id].requestTime; if (time <= curTick) { addrArbiterEvent->schedule(nextBusClock(curTick,2)); } else { scheduleArbitrationEvent(addrArbiterEvent,time,nextAddrFree,2); } } blocked = false; waitingFor = -1; busBlockedCycles += curTick - busBlockedTime; }}voidBus::setBlocked(int id){ if (blocked) warn("Blocking on a second cause???\n"); DPRINTF(Bus, "Blocked, waiting for id:%d\n", id); blocked = true; waitingFor = id; busBlockedTime = curTick; busBlocked++; blockSync = false; if (addrArbiterEvent->scheduled()) { addrArbiterEvent->deschedule(); }}boolBus::findOldestRequest(std::vector<BusRequestRecord> & requests, int & grant_id, int & old_grant_id){ grant_id = -1; old_grant_id = -1; Tick grant_time = TICK_T_MAX; // set to arbitrarily large number Tick old_grant_time = TICK_T_MAX; for (int i=0; i<numInterfaces; i++) { if (requests[i].requested) { if (requests[i].requestTime < grant_time) { old_grant_time = grant_time; grant_time = requests[i].requestTime; old_grant_id = grant_id; grant_id = i; } else if (requests[i].requestTime < old_grant_time) { old_grant_time = requests[i].requestTime; old_grant_id = i; } } } return (grant_id != -1);}voidBus::scheduleArbitrationEvent(Event * arbiterEvent, Tick reqTime, Tick nextFreeCycle, Tick idleAdvance){ bool bus_idle = (nextFreeCycle <= curTick); Tick next_schedule_time; if (bus_idle) { if (reqTime < curTick) { next_schedule_time = nextBusClock(curTick,idleAdvance); } else { next_schedule_time = nextBusClock(reqTime,idleAdvance); } } else { if (reqTime < nextFreeCycle) { next_schedule_time = nextFreeCycle; } else { next_schedule_time = nextBusClock(reqTime,idleAdvance); } } if (arbiterEvent->scheduled()) { if (arbiterEvent->when() > next_schedule_time) { arbiterEvent->reschedule(next_schedule_time); DPRINTF(Bus, "Rescheduling arbiter event for cycle %d\n", next_schedule_time); } } else { arbiterEvent->schedule(next_schedule_time); DPRINTF(Bus, "scheduling arbiter event for cycle %d\n", next_schedule_time); }}TickBus::probe(MemReqPtr &req, bool update){ bool satisfied = req->isSatisfied(); Tick time_sat = 0; for (int i = 0; i < numInterfaces; i++) { if (interfaces[req->busId] != transmitInterfaces[i]) { if (!satisfied) { time_sat = transmitInterfaces[i]->probe(req, update); satisfied = req->isSatisfied(); } else { transmitInterfaces[i]->probe(req, update); } } } assert(satisfied); return time_sat;}voidBus::collectRanges(list<Range<Addr> > &range_list){ for (int i = 0; i < numInterfaces; ++i) { interfaces[i]->getRange(range_list); }}voidBus::rangeChange(){ for (int i = 0; i < numInterfaces; ++i) { interfaces[i]->rangeChange(); }}// Event implementationsvoidAddrArbiterEvent::process(){ bus->arbitrateAddrBus();}const char *AddrArbiterEvent::description(){ return "address bus arbitration";}voidDataArbiterEvent::process(){ DPRINTF(Bus, "Data Arb processing event\n"); bus->arbitrateDataBus();}const char *DataArbiterEvent::description(){ return "data bus arbitration";}voidDeliverEvent::process(){ bi->deliver(req); delete this;}const char *DeliverEvent::description(){ return "bus deliver";}#ifndef DOXYGEN_SHOULD_SKIP_THISBEGIN_DECLARE_SIM_OBJECT_PARAMS(Bus) Param<int> width; Param<int> clock; SimObjectParam<HierParams *> hier;END_DECLARE_SIM_OBJECT_PARAMS(Bus)BEGIN_INIT_SIM_OBJECT_PARAMS(Bus) INIT_PARAM(width, "bus width in bytes"), INIT_PARAM(clock, "bus frequency"), INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams)END_INIT_SIM_OBJECT_PARAMS(Bus)CREATE_SIM_OBJECT(Bus){ return new Bus(getInstanceName(), hier, width, clock);}REGISTER_SIM_OBJECT("Bus", Bus)#endif //DOXYGEN_SHOULD_SKIP_THIS
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -