bool
Bus::recvTiming(PacketPtr pkt)
{
- Port *port;
- DPRINTF(Bus, "recvTiming: packet src %d dest %d addr 0x%x cmd %s result %d\n",
- pkt->getSrc(), pkt->getDest(), pkt->getAddr(), pkt->cmdString(),
- pkt->result);
+ int port_id;
+ DPRINTF(Bus, "recvTiming: packet src %d dest %d addr 0x%x cmd %s\n",
+ pkt->getSrc(), pkt->getDest(), pkt->getAddr(), pkt->cmdString());
BusPort *pktPort;
if (pkt->getSrc() == defaultId)
// Make sure to clear the snoop commit flag so it doesn't think an
// access has been handled twice.
if (dest == Packet::Broadcast) {
- port = findPort(pkt->getAddr(), pkt->getSrc());
- timingSnoop(pkt, port ? port : interfaces[pkt->getSrc()]);
+ port_id = findPort(pkt->getAddr());
+ timingSnoop(pkt, interfaces[port_id]);
if (pkt->memInhibitAsserted()) {
//Cache-Cache transfer occuring
} else {
assert(dest >= 0 && dest < maxId);
assert(dest != pkt->getSrc()); // catch infinite loops
- port = interfaces[dest];
+ port_id = dest;
}
occupyBus(pkt);
- if (port) {
- if (port->sendTiming(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) {
void
Bus::recvRetry(int id)
{
- DPRINTF(Bus, "Received a retry from %s\n", id == -1 ? "self" : interfaces[id]->getPeer()->name());
// If there's anything waiting, and the bus isn't busy...
if (retryList.size() && curTick >= tickNextIdle) {
//retryingPort = retryList.front();
}
}
-Port *
-Bus::findPort(Addr addr, int id)
+int
+Bus::findPort(Addr addr)
{
/* An interval tree would be a better way to do this. --ali. */
int dest_id = -1;
iter != defaultRange.end(); iter++) {
if (*iter == addr) {
DPRINTF(Bus, " found addr %#llx on default\n", addr);
- return defaultPort;
+ return defaultId;
}
}
DPRINTF(Bus, "Unable to find destination for addr: %#llx, will use "
"default port", addr);
- return defaultPort;
+ return defaultId;
}
}
-
- // we shouldn't be sending this back to where it came from
- // do the snoop access and then we should terminate
- // the cyclical call.
- if (dest_id == id)
- return 0;
-
- return interfaces[dest_id];
+ return dest_id;
}
void
// 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++) {
if (p != responder && p->getId() != src_id) {
p->sendFunctional(pkt);
}
- if (pkt->result == Packet::Success) {
+ if (pkt->isResponse()) {
break;
}
pkt->setSrc(src_id);
DPRINTF(Bus, "recvAtomic: packet src %d dest %d addr 0x%x cmd %s\n",
pkt->getSrc(), pkt->getDest(), pkt->getAddr(), pkt->cmdString());
assert(pkt->getDest() == Packet::Broadcast);
+ assert(pkt->isRequest());
// Variables for recording original command and snoop response (if
// any)... if a snooper respondes, we will need to restore
// original command so that additional snoops can take place
// properly
MemCmd orig_cmd = pkt->cmd;
- Packet::Result response_result = Packet::Unknown;
- MemCmd response_cmd = MemCmd::InvalidCmd;
+ MemCmd snoop_response_cmd = MemCmd::InvalidCmd;
+ Tick snoop_response_latency = 0;
+ int orig_src = pkt->getSrc();
- Port *target_port = findPort(pkt->getAddr(), pkt->getSrc());
+ int target_port_id = findPort(pkt->getAddr());
+ Port *target_port = interfaces[target_port_id];
SnoopIter s_end = snoopPorts.end();
for (SnoopIter s_iter = snoopPorts.begin(); s_iter != s_end; s_iter++) {
// same port should not have both target addresses and snooping
assert(p != target_port);
if (p->getId() != pkt->getSrc()) {
- p->sendAtomic(pkt);
- if (pkt->result != Packet::Unknown) {
+ Tick latency = p->sendAtomic(pkt);
+ if (pkt->isResponse()) {
// response from snoop agent
assert(pkt->cmd != orig_cmd);
assert(pkt->memInhibitAsserted());
- assert(pkt->isResponse());
// should only happen once
- assert(response_result == Packet::Unknown);
- assert(response_cmd == MemCmd::InvalidCmd);
+ assert(snoop_response_cmd == MemCmd::InvalidCmd);
// save response state
- response_result = pkt->result;
- response_cmd = pkt->cmd;
+ snoop_response_cmd = pkt->cmd;
+ snoop_response_latency = latency;
// restore original packet state for remaining snoopers
pkt->cmd = orig_cmd;
- pkt->result = Packet::Unknown;
+ pkt->setSrc(orig_src);
+ pkt->setDest(Packet::Broadcast);
}
}
}
- Tick response_time = target_port->sendAtomic(pkt);
+ Tick response_latency = 0;
+
+ // we can get requests sent up from the memory side of the bus for
+ // snooping... don't send them back down!
+ if (target_port_id != pkt->getSrc()) {
+ response_latency = target_port->sendAtomic(pkt);
+ }
// if we got a response from a snooper, restore it here
- if (response_result != Packet::Unknown) {
- assert(response_cmd != MemCmd::InvalidCmd);
+ if (snoop_response_cmd != MemCmd::InvalidCmd) {
// no one else should have responded
- assert(pkt->result == Packet::Unknown);
+ assert(!pkt->isResponse());
assert(pkt->cmd == orig_cmd);
- pkt->cmd = response_cmd;
- pkt->result = response_result;
+ pkt->cmd = snoop_response_cmd;
+ response_latency = snoop_response_latency;
}
// why do we have this packet field and the return value both???
- pkt->finishTime = std::max(response_time, curTick + clock);
- return pkt->finishTime;
+ pkt->finishTime = curTick + response_latency;
+ return response_latency;
}
/** Function called by the port when the bus is receiving a Functional
pkt->getSrc(), pkt->getDest(), pkt->getAddr(), pkt->cmdString());
assert(pkt->getDest() == Packet::Broadcast);
- Port* port = findPort(pkt->getAddr(), pkt->getSrc());
- functionalSnoop(pkt, port ? port : interfaces[pkt->getSrc()]);
+ int port_id = findPort(pkt->getAddr());
+ Port *port = interfaces[port_id];
+ functionalSnoop(pkt, port);
- // If the snooping found what we were looking for, we're done.
- if (pkt->result != Packet::Success && port) {
+ // If the snooping hasn't found what we were looking for, keep going.
+ if (!pkt->isResponse() && port_id != pkt->getSrc()) {
port->sendFunctional(pkt);
}
}