Integrate snoop loop functions into their respective call sites.
Also some additional cleanup of Bus::recvTiming(). --HG-- extra : convert_revision : 156814119f75d04c2e954aec2d7ed6fdc186c26f
This commit is contained in:
parent
d094f9cf27
commit
de52eebd3b
156
src/mem/bus.cc
156
src/mem/bus.cc
|
@ -172,78 +172,79 @@ void Bus::occupyBus(PacketPtr pkt)
|
|||
bool
|
||||
Bus::recvTiming(PacketPtr pkt)
|
||||
{
|
||||
int port_id;
|
||||
short src = pkt->getSrc();
|
||||
DPRINTF(Bus, "recvTiming: packet src %d dest %d addr 0x%x cmd %s\n",
|
||||
pkt->getSrc(), pkt->getDest(), pkt->getAddr(), pkt->cmdString());
|
||||
src, pkt->getDest(), pkt->getAddr(), pkt->cmdString());
|
||||
|
||||
BusPort *pktPort;
|
||||
if (pkt->getSrc() == defaultId)
|
||||
pktPort = defaultPort;
|
||||
else pktPort = interfaces[pkt->getSrc()];
|
||||
BusPort *src_port = (src == defaultId) ? defaultPort : interfaces[src];
|
||||
|
||||
// If the bus is busy, or other devices are in line ahead of the current
|
||||
// one, put this device on the retry list.
|
||||
if (!(pkt->isResponse() || pkt->isExpressSnoop()) &&
|
||||
(tickNextIdle > curTick ||
|
||||
(retryList.size() && (!inRetry || pktPort != retryList.front()))))
|
||||
(retryList.size() && (!inRetry || src_port != retryList.front()))))
|
||||
{
|
||||
addToRetryList(pktPort);
|
||||
addToRetryList(src_port);
|
||||
DPRINTF(Bus, "recvTiming: Bus is busy, returning false\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
occupyBus(pkt);
|
||||
|
||||
short dest = pkt->getDest();
|
||||
int dest_port_id;
|
||||
Port *dest_port;
|
||||
|
||||
if (dest == Packet::Broadcast) {
|
||||
port_id = findPort(pkt->getAddr());
|
||||
timingSnoop(pkt, interfaces[port_id]);
|
||||
|
||||
if (pkt->memInhibitAsserted()) {
|
||||
//Cache-Cache transfer occuring
|
||||
if (inRetry) {
|
||||
retryList.front()->onRetryList(false);
|
||||
retryList.pop_front();
|
||||
inRetry = false;
|
||||
dest_port_id = findPort(pkt->getAddr());
|
||||
dest_port = interfaces[dest_port_id];
|
||||
for (SnoopIter s_iter = snoopPorts.begin();
|
||||
s_iter != snoopPorts.end();
|
||||
s_iter++) {
|
||||
BusPort *p = *s_iter;
|
||||
if (p != dest_port && p != src_port) {
|
||||
#ifndef NDEBUG
|
||||
// cache is not allowed to refuse snoop
|
||||
bool success = p->sendTiming(pkt);
|
||||
assert(success);
|
||||
#else
|
||||
// avoid unused variable warning
|
||||
p->sendTiming(pkt);
|
||||
#endif
|
||||
}
|
||||
occupyBus(pkt);
|
||||
DPRINTF(Bus, "recvTiming: Packet sucessfully sent\n");
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
assert(dest >= 0 && dest < maxId);
|
||||
assert(dest != pkt->getSrc()); // catch infinite loops
|
||||
port_id = dest;
|
||||
assert(dest != src); // catch infinite loops
|
||||
dest_port_id = dest;
|
||||
dest_port = interfaces[dest_port_id];
|
||||
}
|
||||
|
||||
occupyBus(pkt);
|
||||
|
||||
if (port_id != pkt->getSrc()) {
|
||||
if (interfaces[port_id]->sendTiming(pkt)) {
|
||||
// Packet was successfully sent. Return true.
|
||||
// Also take care of retries
|
||||
if (inRetry) {
|
||||
DPRINTF(Bus, "Remove retry from list %d\n",
|
||||
retryList.front()->getId());
|
||||
retryList.front()->onRetryList(false);
|
||||
retryList.pop_front();
|
||||
inRetry = false;
|
||||
}
|
||||
return true;
|
||||
if (dest_port_id == src) {
|
||||
// Must be forwarded snoop up from below...
|
||||
assert(dest == Packet::Broadcast);
|
||||
} else {
|
||||
// send to actual target
|
||||
if (!dest_port->sendTiming(pkt)) {
|
||||
// Packet not successfully sent. Leave or put it on the retry list.
|
||||
// illegal to block responses... can lead to deadlock
|
||||
assert(!pkt->isResponse());
|
||||
DPRINTF(Bus, "Adding2 a retry to RETRY list %d\n", src);
|
||||
addToRetryList(src_port);
|
||||
return false;
|
||||
}
|
||||
// send OK, fall through
|
||||
}
|
||||
|
||||
// Packet not successfully sent. Leave or put it on the retry list.
|
||||
// illegal to block responses... can lead to deadlock
|
||||
assert(!pkt->isResponse());
|
||||
DPRINTF(Bus, "Adding2 a retry to RETRY list %d\n",
|
||||
pktPort->getId());
|
||||
addToRetryList(pktPort);
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
//Forwarding up from responder, just return true;
|
||||
DPRINTF(Bus, "recvTiming: can we be here?\n");
|
||||
return true;
|
||||
// Packet was successfully sent.
|
||||
// Also take care of retries
|
||||
if (inRetry) {
|
||||
DPRINTF(Bus, "Remove retry from list %d\n", src);
|
||||
retryList.front()->onRetryList(false);
|
||||
retryList.pop_front();
|
||||
inRetry = false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -314,46 +315,6 @@ Bus::findPort(Addr addr)
|
|||
return dest_id;
|
||||
}
|
||||
|
||||
void
|
||||
Bus::functionalSnoop(PacketPtr pkt, Port *responder)
|
||||
{
|
||||
// The packet may be changed by another bus on snoops, restore the
|
||||
// id after each
|
||||
int src_id = pkt->getSrc();
|
||||
|
||||
assert(pkt->isRequest()); // hasn't already been satisfied
|
||||
|
||||
for (SnoopIter s_iter = snoopPorts.begin();
|
||||
s_iter != snoopPorts.end();
|
||||
s_iter++) {
|
||||
BusPort *p = *s_iter;
|
||||
if (p != responder && p->getId() != src_id) {
|
||||
p->sendFunctional(pkt);
|
||||
}
|
||||
if (pkt->isResponse()) {
|
||||
break;
|
||||
}
|
||||
pkt->setSrc(src_id);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
Bus::timingSnoop(PacketPtr pkt, Port* responder)
|
||||
{
|
||||
for (SnoopIter s_iter = snoopPorts.begin();
|
||||
s_iter != snoopPorts.end();
|
||||
s_iter++) {
|
||||
BusPort *p = *s_iter;
|
||||
if (p != responder && p->getId() != pkt->getSrc()) {
|
||||
bool success = p->sendTiming(pkt);
|
||||
if (!success)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/** Function called by the port when the bus is receiving a Atomic
|
||||
* transaction.*/
|
||||
|
@ -434,7 +395,24 @@ Bus::recvFunctional(PacketPtr pkt)
|
|||
|
||||
int port_id = findPort(pkt->getAddr());
|
||||
Port *port = interfaces[port_id];
|
||||
functionalSnoop(pkt, port);
|
||||
// The packet may be changed by another bus on snoops, restore the
|
||||
// id after each
|
||||
int src_id = pkt->getSrc();
|
||||
|
||||
assert(pkt->isRequest()); // hasn't already been satisfied
|
||||
|
||||
for (SnoopIter s_iter = snoopPorts.begin();
|
||||
s_iter != snoopPorts.end();
|
||||
s_iter++) {
|
||||
BusPort *p = *s_iter;
|
||||
if (p != port && p->getId() != src_id) {
|
||||
p->sendFunctional(pkt);
|
||||
}
|
||||
if (pkt->isResponse()) {
|
||||
break;
|
||||
}
|
||||
pkt->setSrc(src_id);
|
||||
}
|
||||
|
||||
// If the snooping hasn't found what we were looking for, keep going.
|
||||
if (!pkt->isResponse() && port_id != pkt->getSrc()) {
|
||||
|
|
|
@ -180,15 +180,6 @@ class Bus : public MemObject
|
|||
*/
|
||||
int findPort(Addr addr);
|
||||
|
||||
/** Snoop all relevant ports functionally. */
|
||||
void functionalSnoop(PacketPtr pkt, Port *responder);
|
||||
|
||||
/** Call snoop on caches, be sure to set SNOOP_COMMIT bit if you want
|
||||
* the snoop to happen
|
||||
* @return True if succeds.
|
||||
*/
|
||||
bool timingSnoop(PacketPtr pkt, Port *responder);
|
||||
|
||||
/** Process address range request.
|
||||
* @param resp addresses that we can respond to
|
||||
* @param snoop addresses that we would like to snoop
|
||||
|
|
Loading…
Reference in a new issue