summaryrefslogtreecommitdiff
path: root/src/mem
diff options
context:
space:
mode:
Diffstat (limited to 'src/mem')
-rw-r--r--src/mem/bridge.cc12
-rw-r--r--src/mem/bus.cc116
-rw-r--r--src/mem/bus.hh6
-rw-r--r--src/mem/cache/base_cache.cc14
-rw-r--r--src/mem/cache/base_cache.hh7
-rw-r--r--src/mem/cache/miss/miss_queue.cc2
-rw-r--r--src/mem/packet.hh2
7 files changed, 108 insertions, 51 deletions
diff --git a/src/mem/bridge.cc b/src/mem/bridge.cc
index 38dcfd2e8..b787f79ca 100644
--- a/src/mem/bridge.cc
+++ b/src/mem/bridge.cc
@@ -91,10 +91,16 @@ Bridge::init()
bool
Bridge::BridgePort::recvTiming(PacketPtr pkt)
{
- DPRINTF(BusBridge, "recvTiming: src %d dest %d addr 0x%x\n",
- pkt->getSrc(), pkt->getDest(), pkt->getAddr());
+ if (pkt->flags & SNOOP_COMMIT) {
+ DPRINTF(BusBridge, "recvTiming: src %d dest %d addr 0x%x\n",
+ pkt->getSrc(), pkt->getDest(), pkt->getAddr());
- return otherPort->queueForSendTiming(pkt);
+ return otherPort->queueForSendTiming(pkt);
+ }
+ else {
+ // Else it's just a snoop, properly return if we are blocking
+ return !queueFull();
+ }
}
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
diff --git a/src/mem/bus.hh b/src/mem/bus.hh
index ff1d2545d..c472b6143 100644
--- a/src/mem/bus.hh
+++ b/src/mem/bus.hh
@@ -109,16 +109,16 @@ class Bus : public MemObject
std::vector<int> findSnoopPorts(Addr addr, int id);
/** Snoop all relevant ports atomicly. */
- Tick atomicSnoop(PacketPtr pkt);
+ Tick atomicSnoop(PacketPtr pkt, Port* responder);
/** Snoop all relevant ports functionally. */
- void functionalSnoop(PacketPtr pkt);
+ 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);
+ bool timingSnoop(PacketPtr pkt, Port *responder);
/** Process address range request.
* @param resp addresses that we can respond to
diff --git a/src/mem/cache/base_cache.cc b/src/mem/cache/base_cache.cc
index c16cb6945..3af61375d 100644
--- a/src/mem/cache/base_cache.cc
+++ b/src/mem/cache/base_cache.cc
@@ -160,11 +160,14 @@ BaseCache::CachePort::recvRetry()
PacketPtr pkt;
assert(waitingOnRetry);
if (!drainList.empty()) {
- DPRINTF(CachePort, "%s attempting to send a retry for response\n", name());
+ DPRINTF(CachePort, "%s attempting to send a retry for response (%i waiting)\n"
+ , name(), drainList.size());
//We have some responses to drain first
- if (sendTiming(drainList.front())) {
- DPRINTF(CachePort, "%s sucessful in sending a retry for response\n", name());
- drainList.pop_front();
+ pkt = drainList.front();
+ drainList.pop_front();
+ if (sendTiming(pkt)) {
+ DPRINTF(CachePort, "%s sucessful in sending a retry for"
+ "response (%i still waiting)\n", name(), drainList.size());
if (!drainList.empty() ||
!isCpuSide && cache->doMasterRequest() ||
isCpuSide && cache->doSlaveRequest()) {
@@ -175,6 +178,9 @@ BaseCache::CachePort::recvRetry()
}
waitingOnRetry = false;
}
+ else {
+ drainList.push_front(pkt);
+ }
// Check if we're done draining once this list is empty
if (drainList.empty())
cache->checkDrain();
diff --git a/src/mem/cache/base_cache.hh b/src/mem/cache/base_cache.hh
index 584c2d5df..ef4955432 100644
--- a/src/mem/cache/base_cache.hh
+++ b/src/mem/cache/base_cache.hh
@@ -144,8 +144,6 @@ class BaseCache : public MemObject
protected:
CachePort *memSidePort;
- bool snoopRangesSent;
-
public:
virtual Port *getPort(const std::string &if_name, int idx = -1);
@@ -171,10 +169,6 @@ class BaseCache : public MemObject
if (status == Port::RangeChange){
if (!isCpuSide) {
cpuSidePort->sendStatusChange(Port::RangeChange);
- if (!snoopRangesSent) {
- snoopRangesSent = true;
- memSidePort->sendStatusChange(Port::RangeChange);
- }
}
else {
memSidePort->sendStatusChange(Port::RangeChange);
@@ -358,7 +352,6 @@ class BaseCache : public MemObject
//Start ports at null if more than one is created we should panic
cpuSidePort = NULL;
memSidePort = NULL;
- snoopRangesSent = false;
}
~BaseCache()
diff --git a/src/mem/cache/miss/miss_queue.cc b/src/mem/cache/miss/miss_queue.cc
index fe467a8ea..3c4586272 100644
--- a/src/mem/cache/miss/miss_queue.cc
+++ b/src/mem/cache/miss/miss_queue.cc
@@ -612,6 +612,8 @@ MissQueue::handleResponse(PacketPtr &pkt, Tick time)
if (mshr->hasTargets()) {
// Didn't satisfy all the targets, need to resend
Packet::Command cmd = mshr->getTarget()->cmd;
+ mshr->pkt->setDest(Packet::Broadcast);
+ mshr->pkt->result = Packet::Unknown;
mq.markPending(mshr, cmd);
mshr->order = order++;
cache->setMasterRequest(Request_MSHR, time);
diff --git a/src/mem/packet.hh b/src/mem/packet.hh
index 2bc51bf12..19251941f 100644
--- a/src/mem/packet.hh
+++ b/src/mem/packet.hh
@@ -301,7 +301,7 @@ class Packet
/** Destructor. */
~Packet()
- { deleteData(); }
+ { if (staticData || dynamicData) deleteData(); }
/** Reinitialize packet address and size from the associated
* Request object, and reset other fields that may have been