diff options
Diffstat (limited to 'src/mem')
-rw-r--r-- | src/mem/bridge.cc | 15 | ||||
-rw-r--r-- | src/mem/bridge.hh | 4 | ||||
-rw-r--r-- | src/mem/bus.cc | 294 | ||||
-rw-r--r-- | src/mem/bus.hh | 32 | ||||
-rw-r--r-- | src/mem/cache/base.hh | 4 | ||||
-rw-r--r-- | src/mem/cache/cache.hh | 14 | ||||
-rw-r--r-- | src/mem/cache/cache_impl.hh | 28 | ||||
-rw-r--r-- | src/mem/mport.hh | 4 | ||||
-rw-r--r-- | src/mem/packet_queue.cc | 44 | ||||
-rw-r--r-- | src/mem/packet_queue.hh | 88 | ||||
-rw-r--r-- | src/mem/port.cc | 32 | ||||
-rw-r--r-- | src/mem/port.hh | 187 | ||||
-rw-r--r-- | src/mem/qport.hh | 8 | ||||
-rw-r--r-- | src/mem/ruby/system/RubyPort.cc | 11 | ||||
-rw-r--r-- | src/mem/ruby/system/RubyPort.hh | 8 | ||||
-rw-r--r-- | src/mem/tport.cc | 6 | ||||
-rw-r--r-- | src/mem/tport.hh | 8 |
17 files changed, 463 insertions, 324 deletions
diff --git a/src/mem/bridge.cc b/src/mem/bridge.cc index ddbc154c0..15b41b5ef 100644 --- a/src/mem/bridge.cc +++ b/src/mem/bridge.cc @@ -137,11 +137,8 @@ Bridge::BridgeMasterPort::reqQueueFull() } bool -Bridge::BridgeMasterPort::recvTiming(PacketPtr pkt) +Bridge::BridgeMasterPort::recvTimingResp(PacketPtr pkt) { - // should only see responses on the master side - assert(pkt->isResponse()); - // all checks are done when the request is accepted on the slave // side, so we are guaranteed to have space for the response DPRINTF(BusBridge, "recvTiming: response %s addr 0x%x\n", @@ -155,12 +152,8 @@ Bridge::BridgeMasterPort::recvTiming(PacketPtr pkt) } bool -Bridge::BridgeSlavePort::recvTiming(PacketPtr pkt) +Bridge::BridgeSlavePort::recvTimingReq(PacketPtr pkt) { - // should only see requests on the slave side - assert(pkt->isRequest()); - - DPRINTF(BusBridge, "recvTiming: request %s addr 0x%x\n", pkt->cmdString(), pkt->getAddr()); @@ -318,7 +311,7 @@ Bridge::BridgeMasterPort::trySend() if (!buf->expectResponse) pkt->senderState = NULL; - if (sendTiming(pkt)) { + if (sendTimingReq(pkt)) { // send successful requestQueue.pop_front(); // we no longer own packet, so it's not safe to look at it @@ -365,7 +358,7 @@ Bridge::BridgeSlavePort::trySend() // no need to worry about the sender state since we are not // modifying it - if (sendTiming(pkt)) { + if (sendTimingResp(pkt)) { DPRINTF(BusBridge, " successful\n"); // send successful responseQueue.pop_front(); diff --git a/src/mem/bridge.hh b/src/mem/bridge.hh index 45c7e3057..d7bed9605 100644 --- a/src/mem/bridge.hh +++ b/src/mem/bridge.hh @@ -230,7 +230,7 @@ class Bridge : public MemObject /** When receiving a timing request from the peer port, pass it to the bridge. */ - virtual bool recvTiming(PacketPtr pkt); + virtual bool recvTimingReq(PacketPtr pkt); /** When receiving a retry request from the peer port, pass it to the bridge. */ @@ -353,7 +353,7 @@ class Bridge : public MemObject /** When receiving a timing request from the peer port, pass it to the bridge. */ - virtual bool recvTiming(PacketPtr pkt); + virtual bool recvTimingResp(PacketPtr pkt); /** When receiving a retry request from the peer port, pass it to the bridge. */ diff --git a/src/mem/bus.cc b/src/mem/bus.cc index 911276f75..61b84d82e 100644 --- a/src/mem/bus.cc +++ b/src/mem/bus.cc @@ -198,186 +198,199 @@ Bus::isOccupied(PacketPtr pkt, Port* port) } bool -Bus::recvTiming(PacketPtr pkt) +Bus::recvTimingReq(PacketPtr pkt) { - // get the source id - Packet::NodeID src_id = pkt->getSrc(); - - // determine the source port based on the id and direction - Port *src_port = NULL; - if (pkt->isRequest()) - src_port = slavePorts[src_id]; - else - src_port = masterPorts[src_id]; + // determine the source port based on the id + SlavePort *src_port = slavePorts[pkt->getSrc()]; // test if the bus should be considered occupied for the current // packet, and exclude express snoops from the check if (!pkt->isExpressSnoop() && isOccupied(pkt, src_port)) { - DPRINTF(Bus, "recvTiming: src %s %s 0x%x BUSY\n", + DPRINTF(Bus, "recvTimingReq: src %s %s 0x%x BUSY\n", src_port->name(), pkt->cmdString(), pkt->getAddr()); return false; } - DPRINTF(Bus, "recvTiming: src %s %s 0x%x\n", + DPRINTF(Bus, "recvTimingReq: src %s %s 0x%x\n", src_port->name(), pkt->cmdString(), pkt->getAddr()); Tick headerFinishTime = pkt->isExpressSnoop() ? 0 : calcPacketTiming(pkt); Tick packetFinishTime = pkt->isExpressSnoop() ? 0 : pkt->finishTime; - // decide what to do based on the direction - if (pkt->isRequest()) { - // the packet is a memory-mapped request and should be - // broadcasted to our snoopers but the source - forwardTiming(pkt, src_id); - - // remember if we add an outstanding req so we can undo it if - // necessary, if the packet needs a response, we should add it - // as outstanding and express snoops never fail so there is - // not need to worry about them - bool add_outstanding = !pkt->isExpressSnoop() && pkt->needsResponse(); - - // keep track that we have an outstanding request packet - // matching this request, this is used by the coherency - // mechanism in determining what to do with snoop responses - // (in recvTimingSnoop) - if (add_outstanding) { - // we should never have an exsiting request outstanding - assert(outstandingReq.find(pkt->req) == outstandingReq.end()); - outstandingReq.insert(pkt->req); - } + // the packet is a memory-mapped request and should be + // broadcasted to our snoopers but the source + forwardTiming(pkt, pkt->getSrc()); + + // remember if we add an outstanding req so we can undo it if + // necessary, if the packet needs a response, we should add it + // as outstanding and express snoops never fail so there is + // not need to worry about them + bool add_outstanding = !pkt->isExpressSnoop() && pkt->needsResponse(); + + // keep track that we have an outstanding request packet + // matching this request, this is used by the coherency + // mechanism in determining what to do with snoop responses + // (in recvTimingSnoop) + if (add_outstanding) { + // we should never have an exsiting request outstanding + assert(outstandingReq.find(pkt->req) == outstandingReq.end()); + outstandingReq.insert(pkt->req); + } + + // since it is a normal request, determine the destination + // based on the address and attempt to send the packet + bool success = masterPorts[findPort(pkt->getAddr())]->sendTimingReq(pkt); + + if (!success) { + // inhibited packets should never be forced to retry + assert(!pkt->memInhibitAsserted()); + + // if it was added as outstanding and the send failed, then + // erase it again + if (add_outstanding) + outstandingReq.erase(pkt->req); - // since it is a normal request, determine the destination - // based on the address and attempt to send the packet - bool success = masterPorts[findPort(pkt->getAddr())]->sendTiming(pkt); + DPRINTF(Bus, "recvTimingReq: src %s %s 0x%x RETRY\n", + src_port->name(), pkt->cmdString(), pkt->getAddr()); - if (!success) { - // inhibited packets should never be forced to retry - assert(!pkt->memInhibitAsserted()); + addToRetryList(src_port); + occupyBus(headerFinishTime); - // if it was added as outstanding and the send failed, then - // erase it again - if (add_outstanding) - outstandingReq.erase(pkt->req); + return false; + } - DPRINTF(Bus, "recvTiming: src %s %s 0x%x RETRY\n", - src_port->name(), pkt->cmdString(), pkt->getAddr()); + succeededTiming(packetFinishTime); - addToRetryList(src_port); - occupyBus(headerFinishTime); + return true; +} - return false; - } - } else { - // the packet is a normal response to a request that we should - // have seen passing through the bus - assert(outstandingReq.find(pkt->req) != outstandingReq.end()); +bool +Bus::recvTimingResp(PacketPtr pkt) +{ + // determine the source port based on the id + MasterPort *src_port = masterPorts[pkt->getSrc()]; - // remove it as outstanding - outstandingReq.erase(pkt->req); + // test if the bus should be considered occupied for the current + // packet + if (isOccupied(pkt, src_port)) { + DPRINTF(Bus, "recvTimingResp: src %s %s 0x%x BUSY\n", + src_port->name(), pkt->cmdString(), pkt->getAddr()); + return false; + } - // send the packet to the destination through one of our slave - // ports, as determined by the destination field - bool success M5_VAR_USED = slavePorts[pkt->getDest()]->sendTiming(pkt); + DPRINTF(Bus, "recvTimingResp: src %s %s 0x%x\n", + src_port->name(), pkt->cmdString(), pkt->getAddr()); - // currently it is illegal to block responses... can lead to - // deadlock - assert(success); - } + calcPacketTiming(pkt); + Tick packetFinishTime = pkt->finishTime; + + // the packet is a normal response to a request that we should + // have seen passing through the bus + assert(outstandingReq.find(pkt->req) != outstandingReq.end()); + + // remove it as outstanding + outstandingReq.erase(pkt->req); + + // send the packet to the destination through one of our slave + // ports, as determined by the destination field + bool success M5_VAR_USED = slavePorts[pkt->getDest()]->sendTimingResp(pkt); + + // currently it is illegal to block responses... can lead to + // deadlock + assert(success); succeededTiming(packetFinishTime); return true; } -bool -Bus::recvTimingSnoop(PacketPtr pkt) +void +Bus::recvTimingSnoopReq(PacketPtr pkt) { - // get the source id - Packet::NodeID src_id = pkt->getSrc(); + DPRINTF(Bus, "recvTimingSnoopReq: src %s %s 0x%x\n", + masterPorts[pkt->getSrc()]->name(), pkt->cmdString(), + pkt->getAddr()); - if (pkt->isRequest()) { - DPRINTF(Bus, "recvTimingSnoop: src %d %s 0x%x\n", - src_id, pkt->cmdString(), pkt->getAddr()); + // we should only see express snoops from caches + assert(pkt->isExpressSnoop()); - // the packet is an express snoop request and should be - // broadcasted to our snoopers - assert(pkt->isExpressSnoop()); + // forward to all snoopers + forwardTiming(pkt, Port::INVALID_PORT_ID); - // forward to all snoopers - forwardTiming(pkt, Port::INVALID_PORT_ID); + // a snoop request came from a connected slave device (one of + // our master ports), and if it is not coming from the slave + // device responsible for the address range something is + // wrong, hence there is nothing further to do as the packet + // would be going back to where it came from + assert(pkt->getSrc() == findPort(pkt->getAddr())); - // a snoop request came from a connected slave device (one of - // our master ports), and if it is not coming from the slave - // device responsible for the address range something is - // wrong, hence there is nothing further to do as the packet - // would be going back to where it came from - assert(src_id == findPort(pkt->getAddr())); + // this is an express snoop and is never forced to retry + assert(!inRetry); +} - // this is an express snoop and is never forced to retry - assert(!inRetry); +bool +Bus::recvTimingSnoopResp(PacketPtr pkt) +{ + // determine the source port based on the id + SlavePort* src_port = slavePorts[pkt->getSrc()]; - return true; - } else { - // determine the source port based on the id - SlavePort* src_port = slavePorts[src_id]; + if (isOccupied(pkt, src_port)) { + DPRINTF(Bus, "recvTimingSnoopResp: src %s %s 0x%x BUSY\n", + src_port->name(), pkt->cmdString(), pkt->getAddr()); + return false; + } - if (isOccupied(pkt, src_port)) { - DPRINTF(Bus, "recvTimingSnoop: src %s %s 0x%x BUSY\n", - src_port->name(), pkt->cmdString(), pkt->getAddr()); - return false; - } + DPRINTF(Bus, "recvTimingSnoop: src %s %s 0x%x\n", + src_port->name(), pkt->cmdString(), pkt->getAddr()); - DPRINTF(Bus, "recvTimingSnoop: src %s %s 0x%x\n", - src_port->name(), pkt->cmdString(), pkt->getAddr()); + // get the destination from the packet + Packet::NodeID dest = pkt->getDest(); - // get the destination from the packet - Packet::NodeID dest = pkt->getDest(); - - // responses are never express snoops - assert(!pkt->isExpressSnoop()); - - calcPacketTiming(pkt); - Tick packetFinishTime = pkt->finishTime; - - // determine if the response is from a snoop request we - // created as the result of a normal request (in which case it - // should be in the outstandingReq), or if we merely forwarded - // someone else's snoop request - if (outstandingReq.find(pkt->req) == outstandingReq.end()) { - // this is a snoop response to a snoop request we - // forwarded, e.g. coming from the L1 and going to the L2 - // this should be forwarded as a snoop response - bool success M5_VAR_USED = masterPorts[dest]->sendTimingSnoop(pkt); - assert(success); - } else { - // we got a snoop response on one of our slave ports, - // i.e. from a coherent master connected to the bus, and - // since we created the snoop request as part of - // recvTiming, this should now be a normal response again - outstandingReq.erase(pkt->req); + // responses are never express snoops + assert(!pkt->isExpressSnoop()); - // this is a snoop response from a coherent master, with a - // destination field set on its way through the bus as - // request, hence it should never go back to where the - // snoop response came from, but instead to where the - // original request came from - assert(src_id != dest); + calcPacketTiming(pkt); + Tick packetFinishTime = pkt->finishTime; - // as a normal response, it should go back to a master - // through one of our slave ports - bool success M5_VAR_USED = slavePorts[dest]->sendTiming(pkt); + // determine if the response is from a snoop request we + // created as the result of a normal request (in which case it + // should be in the outstandingReq), or if we merely forwarded + // someone else's snoop request + if (outstandingReq.find(pkt->req) == outstandingReq.end()) { + // this is a snoop response to a snoop request we + // forwarded, e.g. coming from the L1 and going to the L2 + // this should be forwarded as a snoop response + bool success M5_VAR_USED = masterPorts[dest]->sendTimingSnoopResp(pkt); + assert(success); + } else { + // we got a snoop response on one of our slave ports, + // i.e. from a coherent master connected to the bus, and + // since we created the snoop request as part of + // recvTiming, this should now be a normal response again + outstandingReq.erase(pkt->req); - // currently it is illegal to block responses... can lead - // to deadlock - assert(success); - } + // this is a snoop response from a coherent master, with a + // destination field set on its way through the bus as + // request, hence it should never go back to where the + // snoop response came from, but instead to where the + // original request came from + assert(pkt->getSrc() != dest); - succeededTiming(packetFinishTime); + // as a normal response, it should go back to a master + // through one of our slave ports + bool success M5_VAR_USED = slavePorts[dest]->sendTimingResp(pkt); - return true; + // currently it is illegal to block responses... can lead + // to deadlock + assert(success); } + + succeededTiming(packetFinishTime); + + return true; } + void Bus::succeededTiming(Tick busy_time) { @@ -405,8 +418,7 @@ Bus::forwardTiming(PacketPtr pkt, int exclude_slave_port_id) if (exclude_slave_port_id == Port::INVALID_PORT_ID || p->getId() != exclude_slave_port_id) { // cache is not allowed to refuse snoop - bool success M5_VAR_USED = p->sendTimingSnoop(pkt); - assert(success); + p->sendTimingSnoopReq(pkt); } } } @@ -531,9 +543,6 @@ Bus::recvAtomic(PacketPtr pkt) slavePorts[pkt->getSrc()]->name(), pkt->getAddr(), pkt->cmdString()); - // we should always see a request routed based on the address - assert(pkt->isRequest()); - // forward to all snoopers but the source std::pair<MemCmd, Tick> snoop_result = forwardAtomic(pkt, pkt->getSrc()); MemCmd snoop_response_cmd = snoop_result.first; @@ -565,9 +574,6 @@ Bus::recvAtomicSnoop(PacketPtr pkt) masterPorts[pkt->getSrc()]->name(), pkt->getAddr(), pkt->cmdString()); - // we should always see a request routed based on the address - assert(pkt->isRequest()); - // forward to all snoopers std::pair<MemCmd, Tick> snoop_result = forwardAtomic(pkt, Port::INVALID_PORT_ID); @@ -637,9 +643,6 @@ Bus::recvFunctional(PacketPtr pkt) pkt->cmdString()); } - // we should always see a request routed based on the address - assert(pkt->isRequest()); - // forward to all snoopers but the source forwardFunctional(pkt, pkt->getSrc()); @@ -663,9 +666,6 @@ Bus::recvFunctionalSnoop(PacketPtr pkt) pkt->cmdString()); } - // we should always see a request routed based on the address - assert(pkt->isRequest()); - // forward to all snoopers forwardFunctional(pkt, Port::INVALID_PORT_ID); } diff --git a/src/mem/bus.hh b/src/mem/bus.hh index bf64203bf..4ccb586e3 100644 --- a/src/mem/bus.hh +++ b/src/mem/bus.hh @@ -89,14 +89,14 @@ class Bus : public MemObject /** * When receiving a timing request, pass it to the bus. */ - virtual bool recvTiming(PacketPtr pkt) - { pkt->setSrc(id); return bus->recvTiming(pkt); } + virtual bool recvTimingReq(PacketPtr pkt) + { pkt->setSrc(id); return bus->recvTimingReq(pkt); } /** * When receiving a timing snoop response, pass it to the bus. */ - virtual bool recvTimingSnoop(PacketPtr pkt) - { pkt->setSrc(id); return bus->recvTimingSnoop(pkt); } + virtual bool recvTimingSnoopResp(PacketPtr pkt) + { pkt->setSrc(id); return bus->recvTimingSnoopResp(pkt); } /** * When receiving an atomic request, pass it to the bus. @@ -163,14 +163,14 @@ class Bus : public MemObject /** * When receiving a timing response, pass it to the bus. */ - virtual bool recvTiming(PacketPtr pkt) - { pkt->setSrc(id); return bus->recvTiming(pkt); } + virtual bool recvTimingResp(PacketPtr pkt) + { pkt->setSrc(id); return bus->recvTimingResp(pkt); } /** * When receiving a timing snoop request, pass it to the bus. */ - virtual bool recvTimingSnoop(PacketPtr pkt) - { pkt->setSrc(id); return bus->recvTimingSnoop(pkt); } + virtual void recvTimingSnoopReq(PacketPtr pkt) + { pkt->setSrc(id); return bus->recvTimingSnoopReq(pkt); } /** * When receiving an atomic snoop request, pass it to the bus. @@ -228,12 +228,20 @@ class Bus : public MemObject std::set<RequestPtr> outstandingReq; /** Function called by the port when the bus is recieving a Timing - transaction.*/ - bool recvTiming(PacketPtr pkt); + request packet.*/ + bool recvTimingReq(PacketPtr pkt); + + /** Function called by the port when the bus is recieving a Timing + response packet.*/ + bool recvTimingResp(PacketPtr pkt); /** Function called by the port when the bus is recieving a timing - snoop transaction.*/ - bool recvTimingSnoop(PacketPtr pkt); + snoop request.*/ + void recvTimingSnoopReq(PacketPtr pkt); + + /** Function called by the port when the bus is recieving a timing + snoop response.*/ + bool recvTimingSnoopResp(PacketPtr pkt); /** * Forward a timing packet to our snoopers, potentially excluding diff --git a/src/mem/cache/base.hh b/src/mem/cache/base.hh index b24e595b7..55d5e85e1 100644 --- a/src/mem/cache/base.hh +++ b/src/mem/cache/base.hh @@ -148,7 +148,7 @@ class BaseCache : public MemObject protected: CacheMasterPort(const std::string &_name, BaseCache *_cache, - PacketQueue &_queue) : + MasterPacketQueue &_queue) : QueuedMasterPort(_name, _cache, _queue) { } @@ -196,7 +196,7 @@ class BaseCache : public MemObject const std::string &_label); /** A normal packet queue used to store responses. */ - PacketQueue queue; + SlavePacketQueue queue; bool blocked; diff --git a/src/mem/cache/cache.hh b/src/mem/cache/cache.hh index a774a356c..d2110adce 100644 --- a/src/mem/cache/cache.hh +++ b/src/mem/cache/cache.hh @@ -90,9 +90,9 @@ class Cache : public BaseCache protected: - virtual bool recvTimingSnoop(PacketPtr pkt); + virtual bool recvTimingSnoopResp(PacketPtr pkt); - virtual bool recvTiming(PacketPtr pkt); + virtual bool recvTimingReq(PacketPtr pkt); virtual Tick recvAtomic(PacketPtr pkt); @@ -116,7 +116,7 @@ class Cache : public BaseCache * current MSHR status. This queue has a pointer to our specific * cache implementation and is used by the MemSidePort. */ - class MemSidePacketQueue : public PacketQueue + class MemSidePacketQueue : public MasterPacketQueue { protected: @@ -125,9 +125,9 @@ class Cache : public BaseCache public: - MemSidePacketQueue(Cache<TagStore> &cache, Port &port, + MemSidePacketQueue(Cache<TagStore> &cache, MasterPort &port, const std::string &label) : - PacketQueue(cache, port, label), cache(cache) { } + MasterPacketQueue(cache, port, label), cache(cache) { } /** * Override the normal sendDeferredPacket and do not only @@ -154,9 +154,9 @@ class Cache : public BaseCache protected: - virtual bool recvTimingSnoop(PacketPtr pkt); + virtual void recvTimingSnoopReq(PacketPtr pkt); - virtual bool recvTiming(PacketPtr pkt); + virtual bool recvTimingResp(PacketPtr pkt); virtual Tick recvAtomicSnoop(PacketPtr pkt); diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh index fcdac1116..008bbb8d9 100644 --- a/src/mem/cache/cache_impl.hh +++ b/src/mem/cache/cache_impl.hh @@ -417,7 +417,7 @@ Cache<TagStore>::timingAccess(PacketPtr pkt) Packet *snoopPkt = new Packet(pkt, true); // clear flags snoopPkt->setExpressSnoop(); snoopPkt->assertMemInhibit(); - memSidePort->sendTiming(snoopPkt); + memSidePort->sendTimingReq(snoopPkt); // main memory will delete snoopPkt } // since we're the official target but we aren't responding, @@ -1181,7 +1181,7 @@ Cache<TagStore>::handleSnoop(PacketPtr pkt, BlkType *blk, Packet snoopPkt(pkt, true); // clear flags snoopPkt.setExpressSnoop(); snoopPkt.senderState = new ForwardResponseRecord(pkt, this); - cpuSidePort->sendTimingSnoop(&snoopPkt); + cpuSidePort->sendTimingSnoopReq(&snoopPkt); if (snoopPkt.memInhibitAsserted()) { // cache-to-cache response from some upper cache assert(!alreadyResponded); @@ -1336,11 +1336,9 @@ Cache<TagStore>::snoopTiming(PacketPtr pkt) template<class TagStore> bool -Cache<TagStore>::CpuSidePort::recvTimingSnoop(PacketPtr pkt) +Cache<TagStore>::CpuSidePort::recvTimingSnoopResp(PacketPtr pkt) { // Express snoop responses from master to slave, e.g., from L1 to L2 - assert(pkt->isResponse()); - cache->timingAccess(pkt); return true; } @@ -1492,7 +1490,7 @@ Cache<TagStore>::getTimingPacket() PacketPtr snoop_pkt = new Packet(tgt_pkt, true); snoop_pkt->setExpressSnoop(); snoop_pkt->senderState = mshr; - cpuSidePort->sendTimingSnoop(snoop_pkt); + cpuSidePort->sendTimingSnoopReq(snoop_pkt); if (snoop_pkt->memInhibitAsserted()) { markInService(mshr, snoop_pkt); @@ -1557,9 +1555,8 @@ Cache<TagStore>::CpuSidePort::getAddrRanges() template<class TagStore> bool -Cache<TagStore>::CpuSidePort::recvTiming(PacketPtr pkt) +Cache<TagStore>::CpuSidePort::recvTimingReq(PacketPtr pkt) { - assert(pkt->isRequest()); // always let inhibited requests through even if blocked if (!pkt->memInhibitAsserted() && blocked) { DPRINTF(Cache,"Scheduling a retry while blocked\n"); @@ -1575,7 +1572,6 @@ template<class TagStore> Tick Cache<TagStore>::CpuSidePort::recvAtomic(PacketPtr pkt) { - assert(pkt->isRequest()); // atomic request return cache->atomicAccess(pkt); } @@ -1584,7 +1580,6 @@ template<class TagStore> void Cache<TagStore>::CpuSidePort::recvFunctional(PacketPtr pkt) { - assert(pkt->isRequest()); // functional request cache->functionalAccess(pkt, true); } @@ -1605,7 +1600,7 @@ CpuSidePort::CpuSidePort(const std::string &_name, Cache<TagStore> *_cache, template<class TagStore> bool -Cache<TagStore>::MemSidePort::recvTiming(PacketPtr pkt) +Cache<TagStore>::MemSidePort::recvTimingResp(PacketPtr pkt) { // this needs to be fixed so that the cache updates the mshr and sends the // packet back out on the link, but it probably won't happen so until this @@ -1613,27 +1608,23 @@ Cache<TagStore>::MemSidePort::recvTiming(PacketPtr pkt) if (pkt->wasNacked()) panic("Need to implement cache resending nacked packets!\n"); - assert(pkt->isResponse()); cache->handleResponse(pkt); return true; } // Express snooping requests to memside port template<class TagStore> -bool -Cache<TagStore>::MemSidePort::recvTimingSnoop(PacketPtr pkt) +void +Cache<TagStore>::MemSidePort::recvTimingSnoopReq(PacketPtr pkt) { // handle snooping requests - assert(pkt->isRequest()); cache->snoopTiming(pkt); - return true; } template<class TagStore> Tick Cache<TagStore>::MemSidePort::recvAtomicSnoop(PacketPtr pkt) { - assert(pkt->isRequest()); // atomic snoop return cache->snoopAtomic(pkt); } @@ -1642,7 +1633,6 @@ template<class TagStore> void Cache<TagStore>::MemSidePort::recvFunctionalSnoop(PacketPtr pkt) { - assert(pkt->isRequest()); // functional snoop (note that in contrast to atomic we don't have // a specific functionalSnoop method, as they have the same // behaviour regardless) @@ -1668,7 +1658,7 @@ Cache<TagStore>::MemSidePacketQueue::sendDeferredPacket() } else { MSHR *mshr = dynamic_cast<MSHR*>(pkt->senderState); - waitingOnRetry = !port.sendTiming(pkt); + waitingOnRetry = !masterPort.sendTimingReq(pkt); if (waitingOnRetry) { DPRINTF(CachePort, "now waiting on a retry\n"); diff --git a/src/mem/mport.hh b/src/mem/mport.hh index 7f9e8f4e0..b74761256 100644 --- a/src/mem/mport.hh +++ b/src/mem/mport.hh @@ -82,12 +82,12 @@ class MessageMasterPort : public QueuedMasterPort virtual ~MessageMasterPort() {} - bool recvTiming(PacketPtr pkt) { recvResponse(pkt); return true; } + bool recvTimingResp(PacketPtr pkt) { recvResponse(pkt); return true; } protected: /** A packet queue for outgoing packets. */ - PacketQueue queue; + MasterPacketQueue queue; // Accept and ignore responses. virtual Tick recvResponse(PacketPtr pkt) diff --git a/src/mem/packet_queue.cc b/src/mem/packet_queue.cc index bffae5674..ab50fd567 100644 --- a/src/mem/packet_queue.cc +++ b/src/mem/packet_queue.cc @@ -46,9 +46,8 @@ using namespace std; -PacketQueue::PacketQueue(EventManager& _em, Port& _port, - const std::string _label) - : em(_em), label(_label), sendEvent(this), drainEvent(NULL), port(_port), +PacketQueue::PacketQueue(EventManager& _em, const std::string& _label) + : em(_em), sendEvent(this), drainEvent(NULL), label(_label), waitingOnRetry(false) { } @@ -142,11 +141,10 @@ void PacketQueue::trySendTiming() DeferredPacket dp = transmitList.front(); transmitList.pop_front(); - // attempt to send the packet and remember the outcome - if (!dp.sendAsSnoop) - waitingOnRetry = !port.sendTiming(dp.pkt); - else - waitingOnRetry = !port.sendTimingSnoop(dp.pkt); + // use the appropriate implementation of sendTiming based on the + // type of port associated with the queue, and whether the packet + // is to be sent as a snoop or not + waitingOnRetry = !sendTiming(dp.pkt, dp.sendAsSnoop); if (waitingOnRetry) { // put the packet back at the front of the list (packet should @@ -206,3 +204,33 @@ PacketQueue::drain(Event *de) drainEvent = de; return 1; } + +MasterPacketQueue::MasterPacketQueue(EventManager& _em, MasterPort& _masterPort, + const std::string _label) + : PacketQueue(_em, _label), masterPort(_masterPort) +{ +} + +bool +MasterPacketQueue::sendTiming(PacketPtr pkt, bool send_as_snoop) +{ + // attempt to send the packet and return according to the outcome + if (!send_as_snoop) + return masterPort.sendTimingReq(pkt); + else + return masterPort.sendTimingSnoopResp(pkt); +} + +SlavePacketQueue::SlavePacketQueue(EventManager& _em, SlavePort& _slavePort, + const std::string _label) + : PacketQueue(_em, _label), slavePort(_slavePort) +{ +} + +bool +SlavePacketQueue::sendTiming(PacketPtr pkt, bool send_as_snoop) +{ + // we should never have queued snoop requests + assert(!send_as_snoop); + return slavePort.sendTimingResp(pkt); +} diff --git a/src/mem/packet_queue.hh b/src/mem/packet_queue.hh index fbcd7d449..0171eb9a3 100644 --- a/src/mem/packet_queue.hh +++ b/src/mem/packet_queue.hh @@ -86,9 +86,6 @@ class PacketQueue /** The manager which is used for the event queue */ EventManager& em; - /** Label to use for print request packets label stack. */ - const std::string label; - /** This function attempts to send deferred packets. Scheduled to * be called in the future via SendEvent. */ void processSendEvent(); @@ -104,8 +101,8 @@ class PacketQueue protected: - /** The port used to send the packets. */ - Port& port; + /** Label to use for print request packets label stack. */ + const std::string label; /** Remember whether we're awaiting a retry from the bus. */ bool waitingOnRetry; @@ -135,6 +132,11 @@ class PacketQueue void trySendTiming(); /** + * + */ + virtual bool sendTiming(PacketPtr pkt, bool send_as_snoop) = 0; + + /** * Based on the transmit list, or the provided time, schedule a * send event if there are packets to send. If we are idle and * asked to drain then do so. @@ -152,31 +154,28 @@ class PacketQueue */ virtual void recvRangeChange() { } - public: - /** - * Create a packet queue, linked to an event manager, a port used - * to send the packets, and potentially give it a label that will - * be used for functional print request packets. + * Create a packet queue, linked to an event manager, and a label + * that will be used for functional print request packets. * * @param _em Event manager used for scheduling this queue - * @param _port Port used to send the packets * @param _label Label to push on the label stack for print request packets */ - PacketQueue(EventManager& _em, Port& _port, - const std::string _label = "PacketQueue"); + PacketQueue(EventManager& _em, const std::string& _label); /** * Virtual desctructor since the class may be used as a base class. */ virtual ~PacketQueue(); + public: + /** - * Provide a name to simplify debugging. Base it on the port. + * Provide a name to simplify debugging. * * @return A complete name, appended to module and port */ - const std::string name() const { return port.name() + "-queue"; } + virtual const std::string name() const = 0; /** Check the list of buffered packets against the supplied * functional request. */ @@ -217,4 +216,63 @@ class PacketQueue unsigned int drain(Event *de); }; +class MasterPacketQueue : public PacketQueue +{ + + protected: + + MasterPort& masterPort; + + public: + + /** + * Create a master packet queue, linked to an event manager, a + * master port, and a label that will be used for functional print + * request packets. + * + * @param _em Event manager used for scheduling this queue + * @param _masterPort Master port used to send the packets + * @param _label Label to push on the label stack for print request packets + */ + MasterPacketQueue(EventManager& _em, MasterPort& _masterPort, + const std::string _label = "MasterPacketQueue"); + + virtual ~MasterPacketQueue() { } + + const std::string name() const + { return masterPort.name() + "-" + label; } + + bool sendTiming(PacketPtr pkt, bool send_as_snoop); +}; + +class SlavePacketQueue : public PacketQueue +{ + + protected: + + SlavePort& slavePort; + + public: + + /** + * Create a slave packet queue, linked to an event manager, a + * slave port, and a label that will be used for functional print + * request packets. + * + * @param _em Event manager used for scheduling this queue + * @param _slavePort Slave port used to send the packets + * @param _label Label to push on the label stack for print request packets + */ + SlavePacketQueue(EventManager& _em, SlavePort& _slavePort, + const std::string _label = "SlavePacketQueue"); + + virtual ~SlavePacketQueue() { } + + const std::string name() const + { return slavePort.name() + "-" + label; } + + bool sendTiming(PacketPtr pkt, bool send_as_snoop); + +}; + #endif // __MEM_PACKET_QUEUE_HH__ diff --git a/src/mem/port.cc b/src/mem/port.cc index fc3a42c02..9cebd5897 100644 --- a/src/mem/port.cc +++ b/src/mem/port.cc @@ -107,15 +107,31 @@ MasterPort::peerBlockSize() const Tick MasterPort::sendAtomic(PacketPtr pkt) { + assert(pkt->isRequest()); return _slavePort->recvAtomic(pkt); } void MasterPort::sendFunctional(PacketPtr pkt) { + assert(pkt->isRequest()); return _slavePort->recvFunctional(pkt); } +bool +MasterPort::sendTimingReq(PacketPtr pkt) +{ + assert(pkt->isRequest()); + return _slavePort->recvTimingReq(pkt); +} + +bool +MasterPort::sendTimingSnoopResp(PacketPtr pkt) +{ + assert(pkt->isResponse()); + return _slavePort->recvTimingSnoopResp(pkt); +} + void MasterPort::printAddr(Addr a) { @@ -171,11 +187,27 @@ SlavePort::isConnected() const Tick SlavePort::sendAtomicSnoop(PacketPtr pkt) { + assert(pkt->isRequest()); return _masterPort->recvAtomicSnoop(pkt); } void SlavePort::sendFunctionalSnoop(PacketPtr pkt) { + assert(pkt->isRequest()); return _masterPort->recvFunctionalSnoop(pkt); } + +bool +SlavePort::sendTimingResp(PacketPtr pkt) +{ + assert(pkt->isResponse()); + return _masterPort->recvTimingResp(pkt); +} + +void +SlavePort::sendTimingSnoopReq(PacketPtr pkt) +{ + assert(pkt->isRequest()); + _masterPort->recvTimingSnoopReq(pkt); +} diff --git a/src/mem/port.hh b/src/mem/port.hh index e1f643e8e..840952354 100644 --- a/src/mem/port.hh +++ b/src/mem/port.hh @@ -73,8 +73,7 @@ class MemObject; * opposite role. * * Each port has a name and an owner, and enables three basic types of - * accesses to the peer port: sendFunctional, sendAtomic and - * sendTiming. + * accesses to the peer port: functional, atomic and timing. */ class Port { @@ -130,61 +129,18 @@ class Port protected: - /** These functions are protected because they should only be - * called by a peer port, never directly by any outside object. */ - - /** - * Receive a timing request or response packet from the peer port. - */ - virtual bool recvTiming(PacketPtr pkt) = 0; - - /** - * Receive a timing snoop request or snoop response packet from - * the peer port. - */ - virtual bool recvTimingSnoop(PacketPtr pkt) - { - panic("%s was not expecting a timing snoop\n", name()); - return false; - } - /** - * Called by a peer port if sendTiming or sendTimingSnoop was - * unsuccesful, and had to wait. + * Called by a peer port if sendTimingReq, sendTimingResp or + * sendTimingSnoopResp was unsuccesful, and had to wait. */ virtual void recvRetry() = 0; public: /** - * Attempt to send a timing request or response packet to the peer - * port by calling its receive function. If the send does not - * succeed, as indicated by the return value, then the sender must - * wait for a recvRetry at which point it can re-issue a - * sendTiming. - * - * @param pkt Packet to send. - * - * @return If the send was succesful or not. - */ - bool sendTiming(PacketPtr pkt) { return peer->recvTiming(pkt); } - - /** - * Attempt to send a timing snoop request or snoop response packet - * to the peer port by calling its receive function. If the send - * does not succeed, as indicated by the return value, then the - * sender must wait for a recvRetry at which point it can re-issue - * a sendTimingSnoop. - * - * @param pkt Packet to send. - * - * @return If the send was succesful or not. - */ - bool sendTimingSnoop(PacketPtr pkt) { return peer->recvTimingSnoop(pkt); } - - /** * Send a retry to a peer port that previously attempted a - * sendTiming or sendTimingSnoop which was unsuccessful. + * sendTimingReq, sendTimingResp or sendTimingSnoopResp which was + * unsuccessful. */ void sendRetry() { return peer->recvRetry(); } @@ -202,6 +158,8 @@ class SlavePort; class MasterPort : public Port { + friend class SlavePort; + private: SlavePort* _slavePort; @@ -237,30 +195,28 @@ class MasterPort : public Port void sendFunctional(PacketPtr pkt); /** - * Receive an atomic snoop request packet from the slave port. - */ - virtual Tick recvAtomicSnoop(PacketPtr pkt) - { - panic("%s was not expecting an atomic snoop\n", name()); - return 0; - } - - /** - * Receive a functional snoop request packet from the slave port. - */ - virtual void recvFunctionalSnoop(PacketPtr pkt) - { - panic("%s was not expecting a functional snoop\n", name()); - } + * Attempt to send a timing request to the slave port by calling + * its corresponding receive function. If the send does not + * succeed, as indicated by the return value, then the sender must + * wait for a recvRetry at which point it can re-issue a + * sendTimingReq. + * + * @param pkt Packet to send. + * + * @return If the send was succesful or not. + */ + bool sendTimingReq(PacketPtr pkt); /** - * Called to receive an address range change from the peer slave - * port. the default implementation ignored the change and does - * nothing. Override this function in a derived class if the owner - * needs to be aware of he laesddress ranges, e.g. in an - * interconnect component like a bus. + * Attempt to send a timing snoop response packet to the slave + * port by calling its corresponding receive function. If the send + * does not succeed, as indicated by the return value, then the + * sender must wait for a recvRetry at which point it can re-issue + * a sendTimingSnoopResp. + * + * @param pkt Packet to send. */ - virtual void recvRangeChange() { } + bool sendTimingSnoopResp(PacketPtr pkt); /** * Determine if this master port is snooping or not. The default @@ -288,6 +244,47 @@ class MasterPort : public Port * that address throughout the memory system. For debugging. */ void printAddr(Addr a); + + protected: + + /** + * Receive an atomic snoop request packet from the slave port. + */ + virtual Tick recvAtomicSnoop(PacketPtr pkt) + { + panic("%s was not expecting an atomic snoop request\n", name()); + return 0; + } + + /** + * Receive a functional snoop request packet from the slave port. + */ + virtual void recvFunctionalSnoop(PacketPtr pkt) + { + panic("%s was not expecting a functional snoop request\n", name()); + } + + /** + * Receive a timing response from the slave port. + */ + virtual bool recvTimingResp(PacketPtr pkt) = 0; + + /** + * Receive a timing snoop request from the slave port. + */ + virtual void recvTimingSnoopReq(PacketPtr pkt) + { + panic("%s was not expecting a timing snoop request\n", name()); + } + + /** + * Called to receive an address range change from the peer slave + * port. the default implementation ignored the change and does + * nothing. Override this function in a derived class if the owner + * needs to be aware of he laesddress ranges, e.g. in an + * interconnect component like a bus. + */ + virtual void recvRangeChange() { } }; /** @@ -299,6 +296,8 @@ class MasterPort : public Port class SlavePort : public Port { + friend class MasterPort; + private: MasterPort* _masterPort; @@ -334,14 +333,26 @@ class SlavePort : public Port void sendFunctionalSnoop(PacketPtr pkt); /** - * Receive an atomic request packet from the master port. - */ - virtual Tick recvAtomic(PacketPtr pkt) = 0; + * Attempt to send a timing response to the master port by calling + * its corresponding receive function. If the send does not + * succeed, as indicated by the return value, then the sender must + * wait for a recvRetry at which point it can re-issue a + * sendTimingResp. + * + * @param pkt Packet to send. + * + * @return If the send was succesful or not. + */ + bool sendTimingResp(PacketPtr pkt); /** - * Receive a functional request packet from the master port. + * Attempt to send a timing snoop request packet to the master port + * by calling its corresponding receive function. Snoop requests + * always succeed and hence no return value is needed. + * + * @param pkt Packet to send. */ - virtual void recvFunctional(PacketPtr pkt) = 0; + void sendTimingSnoopReq(PacketPtr pkt); /** * Called by a peer port in order to determine the block size of @@ -367,6 +378,32 @@ class SlavePort : public Port * @return a list of ranges responded to */ virtual AddrRangeList getAddrRanges() = 0; + + protected: + + /** + * Receive an atomic request packet from the master port. + */ + virtual Tick recvAtomic(PacketPtr pkt) = 0; + + /** + * Receive a functional request packet from the master port. + */ + virtual void recvFunctional(PacketPtr pkt) = 0; + + /** + * Receive a timing request from the master port. + */ + virtual bool recvTimingReq(PacketPtr pkt) = 0; + + /** + * Receive a timing snoop response from the master port. + */ + virtual bool recvTimingSnoopResp(PacketPtr pkt) + { + panic("%s was not expecting a timing snoop response\n", name()); + } + }; #endif //__MEM_PORT_HH__ diff --git a/src/mem/qport.hh b/src/mem/qport.hh index 6ee71a572..1d0544dfa 100644 --- a/src/mem/qport.hh +++ b/src/mem/qport.hh @@ -62,7 +62,7 @@ class QueuedSlavePort : public SlavePort protected: /** Packet queue used to store outgoing requests and responses. */ - PacketQueue &queue; + SlavePacketQueue &queue; /** This function is notification that the device should attempt to send a * packet again. */ @@ -78,7 +78,7 @@ class QueuedSlavePort : public SlavePort * QueuePort constructor. */ QueuedSlavePort(const std::string& name, MemObject* owner, - PacketQueue &queue) : + SlavePacketQueue &queue) : SlavePort(name, owner), queue(queue) { } @@ -103,7 +103,7 @@ class QueuedMasterPort : public MasterPort protected: /** Packet queue used to store outgoing requests and responses. */ - PacketQueue &queue; + MasterPacketQueue &queue; /** This function is notification that the device should attempt to send a * packet again. */ @@ -119,7 +119,7 @@ class QueuedMasterPort : public MasterPort * QueuePort constructor. */ QueuedMasterPort(const std::string& name, MemObject* owner, - PacketQueue &queue) : + MasterPacketQueue &queue) : MasterPort(name, owner), queue(queue) { } diff --git a/src/mem/ruby/system/RubyPort.cc b/src/mem/ruby/system/RubyPort.cc index ef9f59645..53b6e8e6d 100644 --- a/src/mem/ruby/system/RubyPort.cc +++ b/src/mem/ruby/system/RubyPort.cc @@ -141,14 +141,12 @@ RubyPort::M5Port::recvAtomic(PacketPtr pkt) bool -RubyPort::PioPort::recvTiming(PacketPtr pkt) +RubyPort::PioPort::recvTimingResp(PacketPtr pkt) { // In FS mode, ruby memory will receive pio responses from devices // and it must forward these responses back to the particular CPU. DPRINTF(RubyPort, "Pio response for address %#x\n", pkt->getAddr()); - assert(pkt->isResponse()); - // First we must retrieve the request port from the sender State RubyPort::SenderState *senderState = safe_cast<RubyPort::SenderState *>(pkt->senderState); @@ -159,24 +157,23 @@ RubyPort::PioPort::recvTiming(PacketPtr pkt) pkt->senderState = senderState->saved; delete senderState; - port->sendTiming(pkt); + port->sendTimingResp(pkt); return true; } bool -RubyPort::M5Port::recvTiming(PacketPtr pkt) +RubyPort::M5Port::recvTimingReq(PacketPtr pkt) { DPRINTF(RubyPort, "Timing access caught for address %#x\n", pkt->getAddr()); - //dsm: based on SimpleTimingPort::recvTiming(pkt); + //dsm: based on SimpleTimingPort::recvTimingReq(pkt); // The received packets should only be M5 requests, which should never // get nacked. There used to be code to hanldle nacks here, but // I'm pretty sure it didn't work correctly with the drain code, // so that would need to be fixed if we ever added it back. - assert(pkt->isRequest()); if (pkt->memInhibitAsserted()) { warn("memInhibitAsserted???"); diff --git a/src/mem/ruby/system/RubyPort.hh b/src/mem/ruby/system/RubyPort.hh index f41c98f55..8833efb6e 100644 --- a/src/mem/ruby/system/RubyPort.hh +++ b/src/mem/ruby/system/RubyPort.hh @@ -62,7 +62,7 @@ class RubyPort : public MemObject { private: - PacketQueue queue; + SlavePacketQueue queue; RubyPort *ruby_port; RubySystem* ruby_system; bool _onRetryList; @@ -83,7 +83,7 @@ class RubyPort : public MemObject { _onRetryList = newVal; } protected: - virtual bool recvTiming(PacketPtr pkt); + virtual bool recvTimingReq(PacketPtr pkt); virtual Tick recvAtomic(PacketPtr pkt); virtual void recvFunctional(PacketPtr pkt); virtual AddrRangeList getAddrRanges(); @@ -100,7 +100,7 @@ class RubyPort : public MemObject { private: - PacketQueue queue; + MasterPacketQueue queue; RubyPort *ruby_port; @@ -109,7 +109,7 @@ class RubyPort : public MemObject bool sendNextCycle(PacketPtr pkt); protected: - virtual bool recvTiming(PacketPtr pkt); + virtual bool recvTimingResp(PacketPtr pkt); }; friend class PioPort; diff --git a/src/mem/tport.cc b/src/mem/tport.cc index db2c72bbc..c071ef18c 100644 --- a/src/mem/tport.cc +++ b/src/mem/tport.cc @@ -53,7 +53,6 @@ SimpleTimingPort::SimpleTimingPort(const std::string& _name, void SimpleTimingPort::recvFunctional(PacketPtr pkt) { - assert(pkt->isRequest()); if (!queue.checkFunctional(pkt)) { // do an atomic access and throw away the returned latency recvAtomic(pkt); @@ -61,11 +60,8 @@ SimpleTimingPort::recvFunctional(PacketPtr pkt) } bool -SimpleTimingPort::recvTiming(PacketPtr pkt) +SimpleTimingPort::recvTimingReq(PacketPtr pkt) { - // the port is a slave and should hence only get timing requests - assert(pkt->isRequest()); - if (pkt->memInhibitAsserted()) { // snooper will supply based on copy of packet // still target's responsibility to delete packet diff --git a/src/mem/tport.hh b/src/mem/tport.hh index 91706fbe9..db5a074fb 100644 --- a/src/mem/tport.hh +++ b/src/mem/tport.hh @@ -54,7 +54,7 @@ /** * The simple timing port uses a queued port to implement - * recvFunctional and recvTiming through recvAtomic. It is always a + * recvFunctional and recvTimingReq through recvAtomic. It is always a * slave port. */ class SimpleTimingPort : public QueuedSlavePort @@ -63,13 +63,13 @@ class SimpleTimingPort : public QueuedSlavePort protected: /** The packet queue used to store outgoing responses. */ - PacketQueue queue; + SlavePacketQueue queue; /** Implemented using recvAtomic(). */ void recvFunctional(PacketPtr pkt); /** Implemented using recvAtomic(). */ - bool recvTiming(PacketPtr pkt); + bool recvTimingReq(PacketPtr pkt); virtual Tick recvAtomic(PacketPtr pkt) = 0; @@ -77,7 +77,7 @@ class SimpleTimingPort : public QueuedSlavePort /** * Create a new SimpleTimingPort that relies on a packet queue to - * hold responses, and implements recvTiming and recvFunctional + * hold responses, and implements recvTimingReq and recvFunctional * through calls to recvAtomic. Once a request arrives, it is * passed to recvAtomic, and in the case of a timing access any * response is scheduled to be sent after the delay of the atomic |