diff options
author | Ron Dreslinski <rdreslin@umich.edu> | 2006-08-22 16:08:18 -0400 |
---|---|---|
committer | Ron Dreslinski <rdreslin@umich.edu> | 2006-08-22 16:08:18 -0400 |
commit | 9f18764441831b08b8700a8895ae7316f0ed7508 (patch) | |
tree | 49cc780c401a97a1b2c23172db8fd252b726aec0 /src/mem/bus.cc | |
parent | 3a45e9b8cbbe0b3ec69ebd14385fc1b0caa5a08d (diff) | |
download | gem5-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.cc | 106 |
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; |