summaryrefslogtreecommitdiff
path: root/src/mem/bus.cc
diff options
context:
space:
mode:
authorRon Dreslinski <rdreslin@umich.edu>2006-08-22 16:08:18 -0400
committerRon Dreslinski <rdreslin@umich.edu>2006-08-22 16:08:18 -0400
commit9f18764441831b08b8700a8895ae7316f0ed7508 (patch)
tree49cc780c401a97a1b2c23172db8fd252b726aec0 /src/mem/bus.cc
parent3a45e9b8cbbe0b3ec69ebd14385fc1b0caa5a08d (diff)
downloadgem5-9f18764441831b08b8700a8895ae7316f0ed7508.tar.xz
Commiting a version of the multi-phase snoop atomic bus so people can see the framework. Doesn't work, but also doesn't break uni-processor systems.
Working on pulling out the changes in the cache so that it remains working. src/mem/bus.cc: Changes for multi-phase snoop Some code for registering snoop ranges (a version that compiles and runs, but does nothing) src/mem/bus.hh: Changes for multi-phase snoop src/mem/packet.hh: Flag for multi-phase snoop src/mem/port.hh: Status for multi-phase snoop --HG-- extra : convert_revision : 4c2e5263bba16e3bcf03aabe36ff45ec36de4720
Diffstat (limited to 'src/mem/bus.cc')
-rw-r--r--src/mem/bus.cc106
1 files changed, 102 insertions, 4 deletions
diff --git a/src/mem/bus.cc b/src/mem/bus.cc
index b945f93b3..bca209cd7 100644
--- a/src/mem/bus.cc
+++ b/src/mem/bus.cc
@@ -79,7 +79,17 @@ Bus::recvTiming(Packet *pkt)
short dest = pkt->getDest();
if (dest == Packet::Broadcast) {
- port = findPort(pkt->getAddr(), pkt->getSrc());
+ if ( timingSnoopPhase1(pkt) )
+ {
+ timingSnoopPhase2(pkt);
+ port = findPort(pkt->getAddr(), pkt->getSrc());
+ }
+ else
+ {
+ //Snoop didn't succeed
+ retryList.push_back(interfaces[pkt->getSrc()]);
+ return false;
+ }
} else {
assert(dest >= 0 && dest < interfaces.size());
assert(dest != pkt->getSrc()); // catch infinite loops
@@ -151,6 +161,77 @@ Bus::findPort(Addr addr, int id)
return interfaces[dest_id];
}
+std::vector<int>
+Bus::findSnoopPorts(Addr addr, int id)
+{
+ int i = 0;
+ AddrRangeIter iter;
+ std::vector<int> ports;
+
+ while (i < portSnoopList.size())
+ {
+ 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);
+ DPRINTF(Bus, " found snoop addr 0x%llx on device%d\n", addr,
+ portSnoopList[i].portId);
+ }
+ i++;
+ }
+ return ports;
+}
+
+void
+Bus::atomicSnoop(Packet *pkt)
+{
+ std::vector<int> ports = findSnoopPorts(pkt->getAddr(), pkt->getSrc());
+
+ while (!ports.empty())
+ {
+ interfaces[ports.back()]->sendAtomic(pkt);
+ ports.pop_back();
+ }
+}
+
+bool
+Bus::timingSnoopPhase1(Packet *pkt)
+{
+ std::vector<int> ports = findSnoopPorts(pkt->getAddr(), pkt->getSrc());
+ bool success = true;
+
+ while (!ports.empty() && success)
+ {
+ snoopCallbacks.push_back(ports.back());
+ success = interfaces[ports.back()]->sendTiming(pkt);
+ ports.pop_back();
+ }
+ if (!success)
+ {
+ while (!snoopCallbacks.empty())
+ {
+ interfaces[snoopCallbacks.back()]->sendStatusChange(Port::SnoopSquash);
+ snoopCallbacks.pop_back();
+ }
+ return false;
+ }
+ return true;
+}
+
+void
+Bus::timingSnoopPhase2(Packet *pkt)
+{
+ bool success;
+ pkt->flags |= SNOOP_COMMIT;
+ while (!snoopCallbacks.empty())
+ {
+ success = interfaces[snoopCallbacks.back()]->sendTiming(pkt);
+ //We should not fail on snoop callbacks
+ assert(success);
+ snoopCallbacks.pop_back();
+ }
+}
+
/** Function called by the port when the bus is receiving a Atomic
* transaction.*/
Tick
@@ -159,6 +240,7 @@ Bus::recvAtomic(Packet *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);
+ atomicSnoop(pkt);
return findPort(pkt->getAddr(), pkt->getSrc())->sendAtomic(pkt);
}
@@ -193,7 +275,7 @@ Bus::recvStatusChange(Port::Status status, int id)
assert(snoops.size() == 0);
for(iter = ranges.begin(); iter != ranges.end(); iter++) {
defaultRange.push_back(*iter);
- DPRINTF(BusAddrRanges, "Adding range %llx - %llx for default\n",
+ DPRINTF(BusAddrRanges, "Adding range %llx - %llx for default range\n",
iter->start, iter->end);
}
} else {
@@ -201,6 +283,7 @@ Bus::recvStatusChange(Port::Status status, int id)
assert((id < interfaces.size() && id >= 0) || id == -1);
Port *port = interfaces[id];
std::vector<DevMap>::iterator portIter;
+ std::vector<DevMap>::iterator snoopIter;
// Clean out any previously existent ids
for (portIter = portList.begin(); portIter != portList.end(); ) {
@@ -210,10 +293,25 @@ Bus::recvStatusChange(Port::Status status, int id)
portIter++;
}
+ for (snoopIter = portSnoopList.begin(); snoopIter != portSnoopList.end(); ) {
+ if (snoopIter->portId == id)
+ snoopIter = portSnoopList.erase(snoopIter);
+ else
+ snoopIter++;
+ }
+
port->getPeerAddressRanges(ranges, snoops);
- // not dealing with snooping yet either
- assert(snoops.size() == 0);
+ for(iter = snoops.begin(); iter != snoops.end(); iter++) {
+ DevMap dm;
+ dm.portId = id;
+ dm.range = *iter;
+
+ DPRINTF(BusAddrRanges, "Adding snoop range %llx - %llx for id %d\n",
+ dm.range.start, dm.range.end, id);
+ portSnoopList.push_back(dm);
+ }
+
for(iter = ranges.begin(); iter != ranges.end(); iter++) {
DevMap dm;
dm.portId = id;