X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Fmem%2Fbridge.cc;h=9c4241097ea21e33613e4641e3b1c84e00f92669;hb=e33b3aa6692b172f6db5957774a9e0289e81fa5b;hp=b26da57e3d10749e014c9b33c7f4901efeddecdc;hpb=5c84157c291dceb8040ab4dd29142a4d141fd2ed;p=gem5.git diff --git a/src/mem/bridge.cc b/src/mem/bridge.cc index b26da57e3..9c4241097 100644 --- a/src/mem/bridge.cc +++ b/src/mem/bridge.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2013 ARM Limited + * Copyright (c) 2011-2013, 2015 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -48,9 +48,10 @@ * and a slave through a request and response queue. */ +#include "mem/bridge.hh" + #include "base/trace.hh" #include "debug/Bridge.hh" -#include "mem/bridge.hh" #include "params/Bridge.hh" Bridge::BridgeSlavePort::BridgeSlavePort(const std::string& _name, @@ -60,8 +61,8 @@ Bridge::BridgeSlavePort::BridgeSlavePort(const std::string& _name, std::vector _ranges) : SlavePort(_name, &_bridge), bridge(_bridge), masterPort(_masterPort), delay(_delay), ranges(_ranges.begin(), _ranges.end()), - outstandingResponses(0), retryReq(false), - respQueueLimit(_resp_limit), sendEvent(*this) + outstandingResponses(0), retryReq(false), respQueueLimit(_resp_limit), + sendEvent([this]{ trySendTiming(); }, _name) { } @@ -70,12 +71,13 @@ Bridge::BridgeMasterPort::BridgeMasterPort(const std::string& _name, BridgeSlavePort& _slavePort, Cycles _delay, int _req_limit) : MasterPort(_name, &_bridge), bridge(_bridge), slavePort(_slavePort), - delay(_delay), reqQueueLimit(_req_limit), sendEvent(*this) + delay(_delay), reqQueueLimit(_req_limit), + sendEvent([this]{ trySendTiming(); }, _name) { } Bridge::Bridge(Params *p) - : MemObject(p), + : ClockedObject(p), slavePort(p->name + ".slave", *this, masterPort, ticksToCycles(p->delay), p->resp_size, p->ranges), masterPort(p->name + ".master", *this, slavePort, @@ -83,24 +85,16 @@ Bridge::Bridge(Params *p) { } -BaseMasterPort& -Bridge::getMasterPort(const std::string &if_name, PortID idx) +Port & +Bridge::getPort(const std::string &if_name, PortID idx) { if (if_name == "master") return masterPort; - else - // pass it along to our super class - return MemObject::getMasterPort(if_name, idx); -} - -BaseSlavePort& -Bridge::getSlavePort(const std::string &if_name, PortID idx) -{ - if (if_name == "slave") + else if (if_name == "slave") return slavePort; else // pass it along to our super class - return MemObject::getSlavePort(if_name, idx); + return ClockedObject::getPort(if_name, idx); } void @@ -136,10 +130,14 @@ Bridge::BridgeMasterPort::recvTimingResp(PacketPtr pkt) DPRINTF(Bridge, "Request queue size: %d\n", transmitList.size()); - // @todo: We need to pay for this and not just zero it out - pkt->firstWordDelay = pkt->lastWordDelay = 0; + // technically the packet only reaches us after the header delay, + // and typically we also need to deserialise any payload (unless + // the two sides of the bridge are synchronous) + Tick receive_delay = pkt->headerDelay + pkt->payloadDelay; + pkt->headerDelay = pkt->payloadDelay = 0; - slavePort.schedTimingResp(pkt, bridge.clockEdge(delay)); + slavePort.schedTimingResp(pkt, bridge.clockEdge(delay) + + receive_delay); return true; } @@ -150,8 +148,14 @@ Bridge::BridgeSlavePort::recvTimingReq(PacketPtr pkt) DPRINTF(Bridge, "recvTimingReq: %s addr 0x%x\n", pkt->cmdString(), pkt->getAddr()); - // we should not see a timing request if we are already in a retry - assert(!retryReq); + panic_if(pkt->cacheResponding(), "Should not see packets where cache " + "is responding"); + + // we should not get a new request after committing to retry the + // current one, but unfortunately the CPU violates this rule, so + // simply ignore it for now + if (retryReq) + return false; DPRINTF(Bridge, "Response queue size: %d outresp: %d\n", transmitList.size(), outstandingResponses); @@ -162,8 +166,7 @@ Bridge::BridgeSlavePort::recvTimingReq(PacketPtr pkt) retryReq = true; } else { // look at the response queue if we expect to see a response - bool expects_response = pkt->needsResponse() && - !pkt->memInhibitAsserted(); + bool expects_response = pkt->needsResponse(); if (expects_response) { if (respQueueFull()) { DPRINTF(Bridge, "Response queue full\n"); @@ -180,10 +183,15 @@ Bridge::BridgeSlavePort::recvTimingReq(PacketPtr pkt) } if (!retryReq) { - // @todo: We need to pay for this and not just zero it out - pkt->firstWordDelay = pkt->lastWordDelay = 0; - - masterPort.schedTimingReq(pkt, bridge.clockEdge(delay)); + // technically the packet only reaches us after the header + // delay, and typically we also need to deserialise any + // payload (unless the two sides of the bridge are + // synchronous) + Tick receive_delay = pkt->headerDelay + pkt->payloadDelay; + pkt->headerDelay = pkt->payloadDelay = 0; + + masterPort.schedTimingReq(pkt, bridge.clockEdge(delay) + + receive_delay); } } @@ -200,22 +208,13 @@ Bridge::BridgeSlavePort::retryStalledReq() if (retryReq) { DPRINTF(Bridge, "Request waiting for retry, now retrying\n"); retryReq = false; - sendRetry(); + sendRetryReq(); } } void Bridge::BridgeMasterPort::schedTimingReq(PacketPtr pkt, Tick when) { - // If we expect to see a response, we need to restore the source - // and destination field that is potentially changed by a second - // crossbar - if (!pkt->memInhibitAsserted() && pkt->needsResponse()) { - // Update the sender state so we can deal with the response - // appropriately - pkt->pushSenderState(new RequestState(pkt->getSrc())); - } - // If we're about to put this packet at the head of the queue, we // need to schedule an event to do the transmit. Otherwise there // should already be an event scheduled for sending the head @@ -226,26 +225,13 @@ Bridge::BridgeMasterPort::schedTimingReq(PacketPtr pkt, Tick when) assert(transmitList.size() != reqQueueLimit); - transmitList.push_back(DeferredPacket(pkt, when)); + transmitList.emplace_back(pkt, when); } void Bridge::BridgeSlavePort::schedTimingResp(PacketPtr pkt, Tick when) { - // This is a response for a request we forwarded earlier. The - // corresponding request state should be stored in the packet's - // senderState field. - RequestState *req_state = - dynamic_cast(pkt->popSenderState()); - assert(req_state != NULL); - pkt->setDest(req_state->origSrc); - delete req_state; - - // the bridge sets the destination irrespective of it is valid or - // not, as it is checked in the crossbar - DPRINTF(Bridge, "response, new dest %d\n", pkt->getDest()); - // If we're about to put this packet at the head of the queue, we // need to schedule an event to do the transmit. Otherwise there // should already be an event scheduled for sending the head @@ -254,7 +240,7 @@ Bridge::BridgeSlavePort::schedTimingResp(PacketPtr pkt, Tick when) bridge.schedule(sendEvent, when); } - transmitList.push_back(DeferredPacket(pkt, when)); + transmitList.emplace_back(pkt, when); } void @@ -331,7 +317,7 @@ Bridge::BridgeSlavePort::trySendTiming() if (!masterPort.reqQueueFull() && retryReq) { DPRINTF(Bridge, "Request waiting for retry, now retrying\n"); retryReq = false; - sendRetry(); + sendRetryReq(); } } @@ -340,13 +326,13 @@ Bridge::BridgeSlavePort::trySendTiming() } void -Bridge::BridgeMasterPort::recvRetry() +Bridge::BridgeMasterPort::recvReqRetry() { trySendTiming(); } void -Bridge::BridgeSlavePort::recvRetry() +Bridge::BridgeSlavePort::recvRespRetry() { trySendTiming(); } @@ -354,6 +340,9 @@ Bridge::BridgeSlavePort::recvRetry() Tick Bridge::BridgeSlavePort::recvAtomic(PacketPtr pkt) { + panic_if(pkt->cacheResponding(), "Should not see packets where cache " + "is responding"); + return delay * bridge.clockPeriod() + masterPort.sendAtomic(pkt); } @@ -364,14 +353,14 @@ Bridge::BridgeSlavePort::recvFunctional(PacketPtr pkt) // check the response queue for (auto i = transmitList.begin(); i != transmitList.end(); ++i) { - if (pkt->checkFunctional((*i).pkt)) { + if (pkt->trySatisfyFunctional((*i).pkt)) { pkt->makeResponse(); return; } } // also check the master port's request queue - if (masterPort.checkFunctional(pkt)) { + if (masterPort.trySatisfyFunctional(pkt)) { return; } @@ -382,13 +371,13 @@ Bridge::BridgeSlavePort::recvFunctional(PacketPtr pkt) } bool -Bridge::BridgeMasterPort::checkFunctional(PacketPtr pkt) +Bridge::BridgeMasterPort::trySatisfyFunctional(PacketPtr pkt) { bool found = false; auto i = transmitList.begin(); - while(i != transmitList.end() && !found) { - if (pkt->checkFunctional((*i).pkt)) { + while (i != transmitList.end() && !found) { + if (pkt->trySatisfyFunctional((*i).pkt)) { pkt->makeResponse(); found = true; }