summaryrefslogtreecommitdiff
path: root/src/mem/bus.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/mem/bus.cc')
-rw-r--r--src/mem/bus.cc116
1 files changed, 83 insertions, 33 deletions
diff --git a/src/mem/bus.cc b/src/mem/bus.cc
index 8ea67a0e4..6b5b63f50 100644
--- a/src/mem/bus.cc
+++ b/src/mem/bus.cc
@@ -160,11 +160,12 @@ Bus::recvTiming(PacketPtr pkt)
short dest = pkt->getDest();
if (dest == Packet::Broadcast) {
- if (timingSnoop(pkt)) {
+ port = findPort(pkt->getAddr(), pkt->getSrc());
+ if (timingSnoop(pkt, port ? port : interfaces[pkt->getSrc()])) {
bool success;
pkt->flags |= SNOOP_COMMIT;
- success = timingSnoop(pkt);
+ success = timingSnoop(pkt, port ? port : interfaces[pkt->getSrc()]);
assert(success);
if (pkt->flags & SATISFIED) {
@@ -177,7 +178,6 @@ Bus::recvTiming(PacketPtr pkt)
occupyBus(pkt);
return true;
}
- port = findPort(pkt->getAddr(), pkt->getSrc());
} else {
//Snoop didn't succeed
DPRINTF(Bus, "Adding a retry to RETRY list %i\n", pktPort);
@@ -192,22 +192,28 @@ Bus::recvTiming(PacketPtr pkt)
occupyBus(pkt);
- if (port->sendTiming(pkt)) {
- // Packet was successfully sent. Return true.
- // Also take care of retries
- if (inRetry) {
- DPRINTF(Bus, "Remove retry from list %i\n", retryList.front());
- retryList.front()->onRetryList(false);
- retryList.pop_front();
- inRetry = false;
+ if (port) {
+ if (port->sendTiming(pkt)) {
+ // Packet was successfully sent. Return true.
+ // Also take care of retries
+ if (inRetry) {
+ DPRINTF(Bus, "Remove retry from list %i\n", retryList.front());
+ retryList.front()->onRetryList(false);
+ retryList.pop_front();
+ inRetry = false;
+ }
+ return true;
}
+
+ // Packet not successfully sent. Leave or put it on the retry list.
+ DPRINTF(Bus, "Adding a retry to RETRY list %i\n", pktPort);
+ addToRetryList(pktPort);
+ return false;
+ }
+ else {
+ //Forwarding up from responder, just return true;
return true;
}
-
- // Packet not successfully sent. Leave or put it on the retry list.
- DPRINTF(Bus, "Adding a retry to RETRY list %i\n", pktPort);
- addToRetryList(pktPort);
- return false;
}
void
@@ -290,7 +296,10 @@ Bus::findPort(Addr addr, int id)
// we shouldn't be sending this back to where it came from
- assert(dest_id != id);
+ // only on a functional access and then we should terminate
+ // the cyclical call.
+ if (dest_id == id)
+ return 0;
return interfaces[dest_id];
}
@@ -307,7 +316,18 @@ Bus::findSnoopPorts(Addr addr, int id)
if (portSnoopList[i].range == addr && portSnoopList[i].portId != id) {
//Careful to not overlap ranges
//or snoop will be called more than once on the port
- ports.push_back(portSnoopList[i].portId);
+
+ //@todo Fix this hack because ranges are overlapping
+ //need to make sure we dont't create overlapping ranges
+ bool hack_overlap = false;
+ int size = ports.size();
+ for (int j=0; j < size; j++) {
+ if (ports[j] == portSnoopList[i].portId)
+ hack_overlap = true;
+ }
+
+ if (!hack_overlap)
+ ports.push_back(portSnoopList[i].portId);
// DPRINTF(Bus, " found snoop addr %#llx on device%d\n", addr,
// portSnoopList[i].portId);
}
@@ -317,17 +337,19 @@ Bus::findSnoopPorts(Addr addr, int id)
}
Tick
-Bus::atomicSnoop(PacketPtr pkt)
+Bus::atomicSnoop(PacketPtr pkt, Port *responder)
{
std::vector<int> ports = findSnoopPorts(pkt->getAddr(), pkt->getSrc());
Tick response_time = 0;
while (!ports.empty())
{
- Tick response = interfaces[ports.back()]->sendAtomic(pkt);
- if (response) {
- assert(!response_time); //Multiple responders
- response_time = response;
+ if (interfaces[ports.back()] != responder) {
+ Tick response = interfaces[ports.back()]->sendAtomic(pkt);
+ if (response) {
+ assert(!response_time); //Multiple responders
+ response_time = response;
+ }
}
ports.pop_back();
}
@@ -335,26 +357,31 @@ Bus::atomicSnoop(PacketPtr pkt)
}
void
-Bus::functionalSnoop(PacketPtr pkt)
+Bus::functionalSnoop(PacketPtr pkt, Port *responder)
{
std::vector<int> ports = findSnoopPorts(pkt->getAddr(), pkt->getSrc());
+ //The packet may be changed by another bus on snoops, restore the id after each
+ int id = pkt->getSrc();
while (!ports.empty() && pkt->result != Packet::Success)
{
- interfaces[ports.back()]->sendFunctional(pkt);
+ if (interfaces[ports.back()] != responder)
+ interfaces[ports.back()]->sendFunctional(pkt);
ports.pop_back();
+ pkt->setSrc(id);
}
}
bool
-Bus::timingSnoop(PacketPtr pkt)
+Bus::timingSnoop(PacketPtr pkt, Port* responder)
{
std::vector<int> ports = findSnoopPorts(pkt->getAddr(), pkt->getSrc());
bool success = true;
while (!ports.empty() && success)
{
- success = interfaces[ports.back()]->sendTiming(pkt);
+ if (interfaces[ports.back()] != responder) //Don't call if responder also, once will do
+ success = interfaces[ports.back()]->sendTiming(pkt);
ports.pop_back();
}
@@ -370,15 +397,21 @@ Bus::recvAtomic(PacketPtr pkt)
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);
+ pkt->flags |= SNOOP_COMMIT;
// Assume one bus cycle in order to get through. This may have
// some clock skew issues yet again...
pkt->finishTime = curTick + clock;
- Tick snoopTime = atomicSnoop(pkt);
+
+ Port *port = findPort(pkt->getAddr(), pkt->getSrc());
+ Tick snoopTime = atomicSnoop(pkt, port ? port : interfaces[pkt->getSrc()]);
+
if (snoopTime)
return snoopTime; //Snoop satisfies it
+ else if (port)
+ return port->sendAtomic(pkt);
else
- return findPort(pkt->getAddr(), pkt->getSrc())->sendAtomic(pkt);
+ return 0;
}
/** Function called by the port when the bus is receiving a Functional
@@ -389,11 +422,15 @@ Bus::recvFunctional(PacketPtr pkt)
DPRINTF(Bus, "recvFunctional: packet src %d dest %d addr 0x%x cmd %s\n",
pkt->getSrc(), pkt->getDest(), pkt->getAddr(), pkt->cmdString());
assert(pkt->getDest() == Packet::Broadcast);
- functionalSnoop(pkt);
+ pkt->flags |= SNOOP_COMMIT;
+
+ Port* port = findPort(pkt->getAddr(), pkt->getSrc());
+ functionalSnoop(pkt, port ? port : interfaces[pkt->getSrc()]);
// If the snooping found what we were looking for, we're done.
- if (pkt->result != Packet::Success)
- findPort(pkt->getAddr(), pkt->getSrc())->sendFunctional(pkt);
+ if (pkt->result != Packet::Success && port) {
+ port->sendFunctional(pkt);
+ }
}
/** Function called by the port when the bus is receiving a status change.*/
@@ -451,6 +488,7 @@ Bus::recvStatusChange(Port::Status status, int id)
dm.portId = id;
dm.range = *iter;
+ //@todo, make sure we don't overlap ranges
DPRINTF(BusAddrRanges, "Adding snoop range %#llx - %#llx for id %d\n",
dm.range.start, dm.range.end, id);
portSnoopList.push_back(dm);
@@ -493,7 +531,7 @@ Bus::addressRanges(AddrRangeList &resp, AddrRangeList &snoop, int id)
for (dflt_iter = defaultRange.begin(); dflt_iter != defaultRange.end();
dflt_iter++) {
resp.push_back(*dflt_iter);
- DPRINTF(BusAddrRanges, " -- %#llx : %#llx\n",dflt_iter->start,
+ DPRINTF(BusAddrRanges, " -- Dflt: %#llx : %#llx\n",dflt_iter->start,
dflt_iter->end);
}
for (portIter = portList.begin(); portIter != portList.end(); portIter++) {
@@ -519,6 +557,18 @@ Bus::addressRanges(AddrRangeList &resp, AddrRangeList &snoop, int id)
portIter->range.start, portIter->range.end);
}
}
+
+ for (portIter = portSnoopList.begin();
+ portIter != portSnoopList.end(); portIter++)
+ {
+ if (portIter->portId != id) {
+ snoop.push_back(portIter->range);
+ DPRINTF(BusAddrRanges, " -- Snoop: %#llx : %#llx\n",
+ portIter->range.start, portIter->range.end);
+ //@todo We need to properly insert snoop ranges
+ //not overlapping the ranges (multiple)
+ }
+ }
}
unsigned int