diff options
Diffstat (limited to 'src/mem')
-rw-r--r-- | src/mem/bridge.cc | 19 | ||||
-rw-r--r-- | src/mem/bridge.hh | 8 | ||||
-rw-r--r-- | src/mem/bus.cc | 502 | ||||
-rw-r--r-- | src/mem/bus.hh | 135 | ||||
-rw-r--r-- | src/mem/cache/base.hh | 2 | ||||
-rw-r--r-- | src/mem/cache/cache.hh | 8 | ||||
-rw-r--r-- | src/mem/cache/cache_impl.hh | 60 | ||||
-rw-r--r-- | src/mem/mport.cc | 14 | ||||
-rw-r--r-- | src/mem/mport.hh | 6 | ||||
-rw-r--r-- | src/mem/packet_queue.cc | 13 | ||||
-rw-r--r-- | src/mem/packet_queue.hh | 10 | ||||
-rw-r--r-- | src/mem/port.cc | 26 | ||||
-rw-r--r-- | src/mem/port.hh | 127 | ||||
-rw-r--r-- | src/mem/ruby/system/RubyPort.cc | 15 | ||||
-rw-r--r-- | src/mem/ruby/system/RubyPort.hh | 4 |
15 files changed, 619 insertions, 330 deletions
diff --git a/src/mem/bridge.cc b/src/mem/bridge.cc index ebb37e792..4dcb2a537 100644 --- a/src/mem/bridge.cc +++ b/src/mem/bridge.cc @@ -412,31 +412,12 @@ Bridge::BridgeSlavePort::recvRetry() } Tick -Bridge::BridgeMasterPort::recvAtomic(PacketPtr pkt) -{ - // master port should never receive any atomic access (panic only - // works once the other side, i.e. the busses, respects this) - // - //panic("Master port on %s got a recvAtomic\n", bridge->name()); - return 0; -} - -Tick Bridge::BridgeSlavePort::recvAtomic(PacketPtr pkt) { return delay + masterPort.sendAtomic(pkt); } void -Bridge::BridgeMasterPort::recvFunctional(PacketPtr pkt) -{ - // master port should never receive any functional access (panic - // only works once the other side, i.e. the busses, respect this) - - // panic("Master port on %s got a recvFunctional\n", bridge->name()); -} - -void Bridge::BridgeSlavePort::recvFunctional(PacketPtr pkt) { std::list<PacketBuffer*>::iterator i; diff --git a/src/mem/bridge.hh b/src/mem/bridge.hh index e7dbc0a28..87b327ca3 100644 --- a/src/mem/bridge.hh +++ b/src/mem/bridge.hh @@ -358,14 +358,6 @@ class Bridge : public MemObject /** When receiving a retry request from the peer port, pass it to the bridge. */ virtual void recvRetry(); - - /** When receiving a Atomic requestfrom the peer port, - pass it to the bridge. */ - virtual Tick recvAtomic(PacketPtr pkt); - - /** When receiving a Functional request from the peer port, - pass it to the bridge. */ - virtual void recvFunctional(PacketPtr pkt); }; /** Slave port of the bridge. */ diff --git a/src/mem/bus.cc b/src/mem/bus.cc index c89455f02..eb26e268b 100644 --- a/src/mem/bus.cc +++ b/src/mem/bus.cc @@ -57,7 +57,6 @@ Bus::Bus(const BusParams *p) : MemObject(p), clock(p->clock), headerCycles(p->header_cycles), width(p->width), tickNextIdle(0), drainEvent(NULL), busIdleEvent(this), inRetry(false), - nbrMasterPorts(p->port_master_connection_count), defaultPortId(INVALID_PORT_ID), useDefaultRange(p->use_default_range), defaultBlockSize(p->block_size), cachedBlockSize(0), cachedBlockSizeValid(false) @@ -71,40 +70,28 @@ Bus::Bus(const BusParams *p) fatal("Number of header cycles must be positive\n"); // create the ports based on the size of the master and slave - // vector ports, and the presence of the default master - - // id used to index into master and slave ports, that currently - // has holes to be able to use the id to index into either - int id = 0; + // vector ports, and the presence of the default port, the ports + // are enumerated starting from zero for (int i = 0; i < p->port_master_connection_count; ++i) { - std::string portName = csprintf("%s-p%d", name(), id); - BusMasterPort* bp = new BusMasterPort(portName, this, id); + std::string portName = csprintf("%s-p%d", name(), i); + BusMasterPort* bp = new BusMasterPort(portName, this, i); masterPorts.push_back(bp); - slavePorts.push_back(NULL); - ++id; } - // see if we have a default master connected and if so add the - // port + // see if we have a default slave device connected and if so add + // our corresponding master port if (p->port_default_connection_count) { - defaultPortId = id; + defaultPortId = masterPorts.size(); std::string portName = csprintf("%s-default", name()); - BusMasterPort* bp = new BusMasterPort(portName, this, id); + BusMasterPort* bp = new BusMasterPort(portName, this, defaultPortId); masterPorts.push_back(bp); - slavePorts.push_back(NULL); - ++id; - // this is an additional master port - ++nbrMasterPorts; } - // note that the first slave port is now stored on index - // nbrMasterPorts in the vector + // create the slave ports, once again starting at zero for (int i = 0; i < p->port_slave_connection_count; ++i) { - std::string portName = csprintf("%s-p%d", name(), id); - BusSlavePort* bp = new BusSlavePort(portName, this, id); - masterPorts.push_back(NULL); + std::string portName = csprintf("%s-p%d", name(), i); + BusSlavePort* bp = new BusSlavePort(portName, this, i); slavePorts.push_back(bp); - ++id; } clearPortCache(); @@ -113,9 +100,8 @@ Bus::Bus(const BusParams *p) MasterPort & Bus::getMasterPort(const std::string &if_name, int idx) { - if (if_name == "master") { - // the master index translates directly to the interfaces - // vector as they are stored first + if (if_name == "master" && idx < masterPorts.size()) { + // the master port index translates directly to the vector position return *masterPorts[idx]; } else if (if_name == "default") { return *masterPorts[defaultPortId]; @@ -127,8 +113,9 @@ Bus::getMasterPort(const std::string &if_name, int idx) SlavePort & Bus::getSlavePort(const std::string &if_name, int idx) { - if (if_name == "slave") { - return *slavePorts[nbrMasterPorts + idx]; + if (if_name == "slave" && idx < slavePorts.size()) { + // the slave port index translates directly to the vector position + return *slavePorts[idx]; } else { return MemObject::getSlavePort(if_name, idx); } @@ -137,19 +124,15 @@ Bus::getSlavePort(const std::string &if_name, int idx) void Bus::init() { - std::vector<BusSlavePort*>::iterator intIter; - - // iterate over our interfaces and determine which of our neighbours - // are snooping and add them as snoopers - for (intIter = slavePorts.begin(); intIter != slavePorts.end(); - intIter++) { - // since there are holes in the vector, check for NULL - if (*intIter != NULL) { - if ((*intIter)->getMasterPort().isSnooping()) { - DPRINTF(BusAddrRanges, "Adding snooping neighbour %s\n", - (*intIter)->getMasterPort().name()); - snoopPorts.push_back(*intIter); - } + std::vector<BusSlavePort*>::iterator p; + + // iterate over our slave ports and determine which of our + // neighbouring master ports are snooping and add them as snoopers + for (p = slavePorts.begin(); p != slavePorts.end(); ++p) { + if ((*p)->getMasterPort().isSnooping()) { + DPRINTF(BusAddrRanges, "Adding snooping neighbour %s\n", + (*p)->getMasterPort().name()); + snoopPorts.push_back(*p); } } } @@ -200,27 +183,36 @@ void Bus::occupyBus(Tick until) curTick(), tickNextIdle); } -/** Function called by the port when the bus is receiving a Timing - * transaction.*/ bool -Bus::recvTiming(PacketPtr pkt) +Bus::isOccupied(PacketPtr pkt, Port* port) { - // called for both requests and responses + // first we see if the next idle tick is in the future, next the + // bus is considered occupied if there are ports on the retry list + // and we are not in a retry with the current port + if (tickNextIdle > curTick() || + (!retryList.empty() && !(inRetry && port == retryList.front()))) { + addToRetryList(port); + return true; + } + return false; +} - // get the source id and port +bool +Bus::recvTiming(PacketPtr pkt) +{ + // get the source id Packet::NodeID src_id = pkt->getSrc(); - // determine the source port based on the id - Port *src_port = slavePorts[src_id] ? - (Port*) slavePorts[src_id] : (Port*) masterPorts[src_id]; - - // If the bus is busy, or other devices are in line ahead of the current - // one, put this device on the retry list. - if (!pkt->isExpressSnoop() && - (tickNextIdle > curTick() || - (!retryList.empty() && (!inRetry || src_port != retryList.front())))) - { - addToRetryList(src_port); + // determine the source port based on the id and direction + Port *src_port = NULL; + if (pkt->isRequest()) + src_port = slavePorts[src_id]; + else + src_port = masterPorts[src_id]; + + // test if the bus should be considered occupied for the current + // packet, and exclude express snoops from the check + if (!pkt->isExpressSnoop() && isOccupied(pkt, src_port)) { DPRINTF(Bus, "recvTiming: src %d dst %d %s 0x%x BUSY\n", src_id, pkt->getDest(), pkt->cmdString(), pkt->getAddr()); return false; @@ -232,89 +224,196 @@ Bus::recvTiming(PacketPtr pkt) Tick headerFinishTime = pkt->isExpressSnoop() ? 0 : calcPacketTiming(pkt); Tick packetFinishTime = pkt->isExpressSnoop() ? 0 : pkt->finishTime; - Packet::NodeID dest = pkt->getDest(); - int dest_id; - Port *dest_port; - + // decide what to do based on the direction if (pkt->isRequest()) { // the packet is a memory-mapped request and should be broadcasted to // our snoopers - assert(dest == Packet::Broadcast); - - SnoopIter s_end = snoopPorts.end(); - for (SnoopIter s_iter = snoopPorts.begin(); s_iter != s_end; s_iter++) { - BusSlavePort *p = *s_iter; - // we got this request from a snooping master - // (corresponding to our own slave port that is also in - // snoopPorts) and should not send it back to where it - // came from - if (p->getId() != src_id) { - // cache is not allowed to refuse snoop - bool success M5_VAR_USED = p->sendTiming(pkt); - assert(success); - } + assert(pkt->getDest() == Packet::Broadcast); + + // forward to all snoopers but the source + forwardTiming(pkt, src_id); + + // remember if we add an outstanding req so we can undo it if + // necessary, if the packet needs a response, we should add it + // as outstanding and express snoops never fail so there is + // not need to worry about them + bool add_outstanding = !pkt->isExpressSnoop() && pkt->needsResponse(); + + // keep track that we have an outstanding request packet + // matching this request, this is used by the coherency + // mechanism in determining what to do with snoop responses + // (in recvTimingSnoop) + if (add_outstanding) { + // we should never have an exsiting request outstanding + assert(outstandingReq.find(pkt->req) == outstandingReq.end()); + outstandingReq.insert(pkt->req); } - // since it is a request, similar to functional and atomic, - // determine the destination based on the address and forward - // through the corresponding master port - dest_id = findPort(pkt->getAddr()); - dest_port = masterPorts[dest_id]; - } else { - // the packet is a response, and it should always go back to - // the port determined by the destination field - dest_id = dest; - assert(dest_id != src_id); // catch infinite loops - dest_port = slavePorts[dest_id] ? - (Port*) slavePorts[dest_id] : (Port*) masterPorts[dest_id]; - - // a normal response from the memory system (i.e. from a - // connected slave) should always go back to the master - // that issued it through one of our slave ports, however - // if this is a snoop response it could go either way, for - // example, it could be coming from a slave port - // connecting an L1 with a coherent master and another L1 - // coherent master (one of our slave ports), or coming - // from the L1 and going to the L2 slave port (through one - // of our master ports) - } - - assert(dest_port != NULL); - - // if this is a snoop from a slave (corresponding to our own - // master), i.e. the memory side of the bus, then do not send it - // back to where it came from - if (dest_id != src_id) { - // send to actual target - if (!dest_port->sendTiming(pkt)) { - // Packet not successfully sent. Leave or put it on the retry list. - // illegal to block responses... can lead to deadlock - assert(!pkt->isResponse()); - // It's also illegal to force a transaction to retry after - // someone else has committed to respond. + // since it is a normal request, determine the destination + // based on the address and attempt to send the packet + bool success = masterPorts[findPort(pkt->getAddr())]->sendTiming(pkt); + + if (!success) { + // inhibited packets should never be forced to retry assert(!pkt->memInhibitAsserted()); - DPRINTF(Bus, "recvTiming: src %d dst %d %s 0x%x TGT RETRY\n", + + // if it was added as outstanding and the send failed, then + // erase it again + if (add_outstanding) + outstandingReq.erase(pkt->req); + + DPRINTF(Bus, "recvTiming: src %d dst %d %s 0x%x RETRY\n", src_id, pkt->getDest(), pkt->cmdString(), pkt->getAddr()); + addToRetryList(src_port); occupyBus(headerFinishTime); + return false; } - // send OK, fall through... pkt may have been deleted by - // target at this point, so it should *not* be referenced - // again. We'll set it to NULL here just to be safe. - pkt = NULL; + } else { + // the packet is a normal response to a request that we should + // have seen passing through the bus + assert(outstandingReq.find(pkt->req) != outstandingReq.end()); + + // remove it as outstanding + outstandingReq.erase(pkt->req); + + // send the packet to the destination through one of our slave + // ports, as determined by the destination field + bool success M5_VAR_USED = slavePorts[pkt->getDest()]->sendTiming(pkt); + + // currently it is illegal to block responses... can lead to + // deadlock + assert(success); } - occupyBus(packetFinishTime); + succeededTiming(packetFinishTime); + + return true; +} + +bool +Bus::recvTimingSnoop(PacketPtr pkt) +{ + // get the source id + Packet::NodeID src_id = pkt->getSrc(); + + if (pkt->isRequest()) { + DPRINTF(Bus, "recvTimingSnoop: src %d dst %d %s 0x%x\n", + src_id, pkt->getDest(), pkt->cmdString(), pkt->getAddr()); + + // the packet is an express snoop request and should be + // broadcasted to our snoopers + assert(pkt->getDest() == Packet::Broadcast); + assert(pkt->isExpressSnoop()); + + // forward to all snoopers + forwardTiming(pkt, INVALID_PORT_ID); + + // a snoop request came from a connected slave device (one of + // our master ports), and if it is not coming from the slave + // device responsible for the address range something is + // wrong, hence there is nothing further to do as the packet + // would be going back to where it came from + assert(src_id == findPort(pkt->getAddr())); + + // this is an express snoop and is never forced to retry + assert(!inRetry); + + return true; + } else { + // determine the source port based on the id + SlavePort* src_port = slavePorts[src_id]; - // Packet was successfully sent. - // Also take care of retries + if (isOccupied(pkt, src_port)) { + DPRINTF(Bus, "recvTimingSnoop: src %d dst %d %s 0x%x BUSY\n", + src_id, pkt->getDest(), pkt->cmdString(), pkt->getAddr()); + return false; + } + + DPRINTF(Bus, "recvTimingSnoop: src %d dst %d %s 0x%x\n", + src_id, pkt->getDest(), pkt->cmdString(), pkt->getAddr()); + + // get the destination from the packet + Packet::NodeID dest = pkt->getDest(); + + // responses are never express snoops + assert(!pkt->isExpressSnoop()); + + calcPacketTiming(pkt); + Tick packetFinishTime = pkt->finishTime; + + // determine if the response is from a snoop request we + // created as the result of a normal request (in which case it + // should be in the outstandingReq), or if we merely forwarded + // someone else's snoop request + if (outstandingReq.find(pkt->req) == outstandingReq.end()) { + // this is a snoop response to a snoop request we + // forwarded, e.g. coming from the L1 and going to the L2 + // this should be forwarded as a snoop response + bool success M5_VAR_USED = masterPorts[dest]->sendTimingSnoop(pkt); + assert(success); + } else { + // we got a snoop response on one of our slave ports, + // i.e. from a coherent master connected to the bus, and + // since we created the snoop request as part of + // recvTiming, this should now be a normal response again + outstandingReq.erase(pkt->req); + + // this is a snoop response from a coherent master, with a + // destination field set on its way through the bus as + // request, hence it should never go back to where the + // snoop response came from, but instead to where the + // original request came from + assert(src_id != dest); + + // as a normal response, it should go back to a master + // through one of our slave ports + bool success M5_VAR_USED = slavePorts[dest]->sendTiming(pkt); + + // currently it is illegal to block responses... can lead + // to deadlock + assert(success); + } + + succeededTiming(packetFinishTime); + + return true; + } +} + +void +Bus::succeededTiming(Tick busy_time) +{ + // occupy the bus accordingly + occupyBus(busy_time); + + // if a retrying port succeeded, also take it off the retry list if (inRetry) { - DPRINTF(Bus, "Remove retry from list %d\n", src_id); + DPRINTF(Bus, "Remove retry from list %s\n", + retryList.front()->name()); retryList.pop_front(); inRetry = false; } - return true; +} + +void +Bus::forwardTiming(PacketPtr pkt, int exclude_slave_port_id) +{ + SnoopIter s_end = snoopPorts.end(); + for (SnoopIter s_iter = snoopPorts.begin(); s_iter != s_end; s_iter++) { + BusSlavePort *p = *s_iter; + // we could have gotten this request from a snooping master + // (corresponding to our own slave port that is also in + // snoopPorts) and should not send it back to where it came + // from + if (exclude_slave_port_id == INVALID_PORT_ID || + p->getId() != exclude_slave_port_id) { + // cache is not allowed to refuse snoop + bool success M5_VAR_USED = p->sendTimingSnoop(pkt); + assert(success); + } + } } void @@ -430,9 +529,6 @@ Bus::findPort(Addr addr) name()); } - -/** Function called by the port when the bus is receiving a Atomic - * transaction.*/ Tick Bus::recvAtomic(PacketPtr pkt) { @@ -443,12 +539,59 @@ Bus::recvAtomic(PacketPtr pkt) assert(pkt->getDest() == Packet::Broadcast); assert(pkt->isRequest()); - // the packet may be changed by another bus on snoops, record the - // source id here - Packet::NodeID src_id = pkt->getSrc(); + // forward to all snoopers but the source + std::pair<MemCmd, Tick> snoop_result = forwardAtomic(pkt, pkt->getSrc()); + MemCmd snoop_response_cmd = snoop_result.first; + Tick snoop_response_latency = snoop_result.second; - // record the original command to enable us to restore it between - // snoops so that additional snoops can take place properly + // even if we had a snoop response, we must continue and also + // perform the actual request at the destination + int dest_id = findPort(pkt->getAddr()); + + // forward the request to the appropriate destination + Tick response_latency = masterPorts[dest_id]->sendAtomic(pkt); + + // if we got a response from a snooper, restore it here + if (snoop_response_cmd != MemCmd::InvalidCmd) { + // no one else should have responded + assert(!pkt->isResponse()); + pkt->cmd = snoop_response_cmd; + response_latency = snoop_response_latency; + } + + pkt->finishTime = curTick() + response_latency; + return response_latency; +} + +Tick +Bus::recvAtomicSnoop(PacketPtr pkt) +{ + DPRINTF(Bus, "recvAtomicSnoop: packet src %d dest %d addr 0x%x cmd %s\n", + pkt->getSrc(), pkt->getDest(), pkt->getAddr(), pkt->cmdString()); + + // we should always see a request routed based on the address + assert(pkt->getDest() == Packet::Broadcast); + assert(pkt->isRequest()); + + // forward to all snoopers + std::pair<MemCmd, Tick> snoop_result = forwardAtomic(pkt, INVALID_PORT_ID); + MemCmd snoop_response_cmd = snoop_result.first; + Tick snoop_response_latency = snoop_result.second; + + if (snoop_response_cmd != MemCmd::InvalidCmd) + pkt->cmd = snoop_response_cmd; + + pkt->finishTime = curTick() + snoop_response_latency; + return snoop_response_latency; +} + +std::pair<MemCmd, Tick> +Bus::forwardAtomic(PacketPtr pkt, int exclude_slave_port_id) +{ + // the packet may be changed on snoops, record the original source + // and command to enable us to restore it between snoops so that + // additional snoops can take place properly + Packet::NodeID orig_src_id = pkt->getSrc(); MemCmd orig_cmd = pkt->cmd; MemCmd snoop_response_cmd = MemCmd::InvalidCmd; Tick snoop_response_latency = 0; @@ -460,8 +603,9 @@ Bus::recvAtomic(PacketPtr pkt) // (corresponding to our own slave port that is also in // snoopPorts) and should not send it back to where it came // from - if (p->getId() != src_id) { - Tick latency = p->sendAtomic(pkt); + if (exclude_slave_port_id == INVALID_PORT_ID || + p->getId() != exclude_slave_port_id) { + Tick latency = p->sendAtomicSnoop(pkt); // in contrast to a functional access, we have to keep on // going as all snoopers must be updated even if we get a // response @@ -476,48 +620,51 @@ Bus::recvAtomic(PacketPtr pkt) snoop_response_latency = latency; // restore original packet state for remaining snoopers pkt->cmd = orig_cmd; - pkt->setSrc(src_id); + pkt->setSrc(orig_src_id); pkt->setDest(Packet::Broadcast); } } } - // even if we had a snoop response, we must continue and also - // perform the actual request at the destination - int dest_id = findPort(pkt->getAddr()); - - Tick response_latency = 0; + // the packet is restored as part of the loop and any potential + // snoop response is part of the returned pair + return std::make_pair(snoop_response_cmd, snoop_response_latency); +} - // if this is a snoop from a slave (corresponding to our own - // master), i.e. the memory side of the bus, then do not send it - // back to where it came from - if (dest_id != src_id) { - response_latency = masterPorts[dest_id]->sendAtomic(pkt); +void +Bus::recvFunctional(PacketPtr pkt) +{ + if (!pkt->isPrint()) { + // don't do DPRINTFs on PrintReq as it clutters up the output + DPRINTF(Bus, + "recvFunctional: packet src %d dest %d addr 0x%x cmd %s\n", + pkt->getSrc(), pkt->getDest(), pkt->getAddr(), + pkt->cmdString()); } - // if we got a response from a snooper, restore it here - if (snoop_response_cmd != MemCmd::InvalidCmd) { - // no one else should have responded - assert(!pkt->isResponse()); - assert(pkt->cmd == orig_cmd); - pkt->cmd = snoop_response_cmd; - response_latency = snoop_response_latency; - } + // we should always see a request routed based on the address + assert(pkt->getDest() == Packet::Broadcast); + assert(pkt->isRequest()); - // why do we have this packet field and the return value both??? - pkt->finishTime = curTick() + response_latency; - return response_latency; + // forward to all snoopers but the source + forwardFunctional(pkt, pkt->getSrc()); + + // there is no need to continue if the snooping has found what we + // were looking for and the packet is already a response + if (!pkt->isResponse()) { + int dest_id = findPort(pkt->getAddr()); + + masterPorts[dest_id]->sendFunctional(pkt); + } } -/** Function called by the port when the bus is receiving a Functional - * transaction.*/ void -Bus::recvFunctional(PacketPtr pkt) +Bus::recvFunctionalSnoop(PacketPtr pkt) { if (!pkt->isPrint()) { // don't do DPRINTFs on PrintReq as it clutters up the output DPRINTF(Bus, - "recvFunctional: packet src %d dest %d addr 0x%x cmd %s\n", + "recvFunctionalSnoop: packet src %d dest %d addr 0x%x cmd %s\n", pkt->getSrc(), pkt->getDest(), pkt->getAddr(), pkt->cmdString()); } @@ -526,10 +673,13 @@ Bus::recvFunctional(PacketPtr pkt) assert(pkt->getDest() == Packet::Broadcast); assert(pkt->isRequest()); - // the packet may be changed by another bus on snoops, record the - // source id here - Packet::NodeID src_id = pkt->getSrc(); + // forward to all snoopers + forwardFunctional(pkt, INVALID_PORT_ID); +} +void +Bus::forwardFunctional(PacketPtr pkt, int exclude_slave_port_id) +{ SnoopIter s_end = snoopPorts.end(); for (SnoopIter s_iter = snoopPorts.begin(); s_iter != s_end; s_iter++) { BusSlavePort *p = *s_iter; @@ -537,26 +687,13 @@ Bus::recvFunctional(PacketPtr pkt) // (corresponding to our own slave port that is also in // snoopPorts) and should not send it back to where it came // from - if (p->getId() != src_id) { - p->sendFunctional(pkt); - - // if we get a response we are done - if (pkt->isResponse()) { - break; - } - } - } - - // there is no need to continue if the snooping has found what we - // were looking for and the packet is already a response - if (!pkt->isResponse()) { - int dest_id = findPort(pkt->getAddr()); + if (exclude_slave_port_id == INVALID_PORT_ID || + p->getId() != exclude_slave_port_id) + p->sendFunctionalSnoop(pkt); - // if this is a snoop from a slave (corresponding to our own - // master), i.e. the memory side of the bus, then do not send - // it back to where it came from, - if (dest_id != src_id) { - masterPorts[dest_id]->sendFunctional(pkt); + // if we get a response we are done + if (pkt->isResponse()) { + break; } } } @@ -621,8 +758,7 @@ Bus::recvRangeChange(int id) std::vector<BusSlavePort*>::const_iterator intIter; for (intIter = slavePorts.begin(); intIter != slavePorts.end(); intIter++) - if (*intIter != NULL && (*intIter)->getId() != id) - (*intIter)->sendRangeChange(); + (*intIter)->sendRangeChange(); inRecvRangeChange.erase(id); } diff --git a/src/mem/bus.hh b/src/mem/bus.hh index e79e9df9e..8a0676353 100644 --- a/src/mem/bus.hh +++ b/src/mem/bus.hh @@ -91,25 +91,35 @@ class Bus : public MemObject protected: - /** When reciving a timing request from the peer port (at id), - pass it to the bus. */ + /** + * When receiving a timing request, pass it to the bus. + */ virtual bool recvTiming(PacketPtr pkt) { pkt->setSrc(id); return bus->recvTiming(pkt); } - /** When reciving a Atomic requestfrom the peer port (at id), - pass it to the bus. */ + /** + * When receiving a timing snoop response, pass it to the bus. + */ + virtual bool recvTimingSnoop(PacketPtr pkt) + { pkt->setSrc(id); return bus->recvTimingSnoop(pkt); } + + /** + * When receiving an atomic request, pass it to the bus. + */ virtual Tick recvAtomic(PacketPtr pkt) { pkt->setSrc(id); return bus->recvAtomic(pkt); } - /** When reciving a Functional requestfrom the peer port (at id), - pass it to the bus. */ + /** + * When receiving a functional request, pass it to the bus. + */ virtual void recvFunctional(PacketPtr pkt) { pkt->setSrc(id); bus->recvFunctional(pkt); } - /** When reciving a retry from the peer port (at id), - pass it to the bus. */ + /** + * When receiving a retry, pass it to the bus. + */ virtual void recvRetry() - { bus->recvRetry(id); } + { panic("Bus slave ports always succeed and should never retry.\n"); } // This should return all the 'owned' addresses that are // downstream from this bus, yes? That is, the union of all @@ -160,20 +170,29 @@ class Bus : public MemObject protected: - /** When reciving a timing request from the peer port (at id), - pass it to the bus. */ + /** + * When receiving a timing response, pass it to the bus. + */ virtual bool recvTiming(PacketPtr pkt) { pkt->setSrc(id); return bus->recvTiming(pkt); } - /** When reciving a Atomic requestfrom the peer port (at id), - pass it to the bus. */ - virtual Tick recvAtomic(PacketPtr pkt) - { pkt->setSrc(id); return bus->recvAtomic(pkt); } + /** + * When receiving a timing snoop request, pass it to the bus. + */ + virtual bool recvTimingSnoop(PacketPtr pkt) + { pkt->setSrc(id); return bus->recvTimingSnoop(pkt); } - /** When reciving a Functional requestfrom the peer port (at id), - pass it to the bus. */ - virtual void recvFunctional(PacketPtr pkt) - { pkt->setSrc(id); bus->recvFunctional(pkt); } + /** + * When receiving an atomic snoop request, pass it to the bus. + */ + virtual Tick recvAtomicSnoop(PacketPtr pkt) + { pkt->setSrc(id); return bus->recvAtomicSnoop(pkt); } + + /** + * When receiving a functional snoop request, pass it to the bus. + */ + virtual void recvFunctionalSnoop(PacketPtr pkt) + { pkt->setSrc(id); bus->recvFunctionalSnoop(pkt); } /** When reciving a range change from the peer port (at id), pass it to the bus. */ @@ -212,18 +231,91 @@ class Bus : public MemObject typedef std::vector<BusSlavePort*>::iterator SnoopIter; std::vector<BusSlavePort*> snoopPorts; + /** + * Store the outstanding requests so we can determine which ones + * we generated and which ones were merely forwarded. This is used + * in the coherent bus when coherency responses come back. + */ + std::set<RequestPtr> outstandingReq; + /** Function called by the port when the bus is recieving a Timing transaction.*/ bool recvTiming(PacketPtr pkt); + /** Function called by the port when the bus is recieving a timing + snoop transaction.*/ + bool recvTimingSnoop(PacketPtr pkt); + + /** + * Forward a timing packet to our snoopers, potentially excluding + * one of the connected coherent masters to avoid sending a packet + * back to where it came from. + * + * @param pkt Packet to forward + * @param exclude_slave_port_id Id of slave port to exclude + */ + void forwardTiming(PacketPtr pkt, int exclude_slave_port_id); + + /** + * Determine if the bus is to be considered occupied when being + * presented with a packet from a specific port. If so, the port + * in question is also added to the retry list. + * + * @param pkt Incoming packet + * @param port Source port on the bus presenting the packet + * + * @return True if the bus is to be considered occupied + */ + bool isOccupied(PacketPtr pkt, Port* port); + + /** + * Deal with a destination port accepting a packet by potentially + * removing the source port from the retry list (if retrying) and + * occupying the bus accordingly. + * + * @param busy_time Time to spend as a result of a successful send + */ + void succeededTiming(Tick busy_time); + /** Function called by the port when the bus is recieving a Atomic transaction.*/ Tick recvAtomic(PacketPtr pkt); + /** Function called by the port when the bus is recieving an + atomic snoop transaction.*/ + Tick recvAtomicSnoop(PacketPtr pkt); + + /** + * Forward an atomic packet to our snoopers, potentially excluding + * one of the connected coherent masters to avoid sending a packet + * back to where it came from. + * + * @param pkt Packet to forward + * @param exclude_slave_port_id Id of slave port to exclude + * + * @return a pair containing the snoop response and snoop latency + */ + std::pair<MemCmd, Tick> forwardAtomic(PacketPtr pkt, + int exclude_slave_port_id); + /** Function called by the port when the bus is recieving a Functional transaction.*/ void recvFunctional(PacketPtr pkt); + /** Function called by the port when the bus is recieving a functional + snoop transaction.*/ + void recvFunctionalSnoop(PacketPtr pkt); + + /** + * Forward a functional packet to our snoopers, potentially + * excluding one of the connected coherent masters to avoid + * sending a packet back to where it came from. + * + * @param pkt Packet to forward + * @param exclude_slave_port_id Id of slave port to exclude + */ + void forwardFunctional(PacketPtr pkt, int exclude_slave_port_id); + /** Timing function called by port when it is once again able to process * requests. */ void recvRetry(int id); @@ -345,11 +437,6 @@ class Bus : public MemObject bool inRetry; std::set<int> inRecvRangeChange; - // keep track of the number of master ports (not counting the - // default master) since we need this as an offset into the - // interfaces vector - unsigned int nbrMasterPorts; - /** The master and slave ports of the bus */ std::vector<BusSlavePort*> slavePorts; std::vector<BusMasterPort*> masterPorts; diff --git a/src/mem/cache/base.hh b/src/mem/cache/base.hh index 47cbaf7a0..b24e595b7 100644 --- a/src/mem/cache/base.hh +++ b/src/mem/cache/base.hh @@ -142,7 +142,7 @@ class BaseCache : public MemObject * @param when time to send the response */ void respond(PacketPtr pkt, Tick time) { - queue.schedSendTiming(pkt, time); + queue.schedSendTiming(pkt, time, true); } protected: diff --git a/src/mem/cache/cache.hh b/src/mem/cache/cache.hh index e745529a7..a774a356c 100644 --- a/src/mem/cache/cache.hh +++ b/src/mem/cache/cache.hh @@ -90,6 +90,8 @@ class Cache : public BaseCache protected: + virtual bool recvTimingSnoop(PacketPtr pkt); + virtual bool recvTiming(PacketPtr pkt); virtual Tick recvAtomic(PacketPtr pkt); @@ -152,11 +154,13 @@ class Cache : public BaseCache protected: + virtual bool recvTimingSnoop(PacketPtr pkt); + virtual bool recvTiming(PacketPtr pkt); - virtual Tick recvAtomic(PacketPtr pkt); + virtual Tick recvAtomicSnoop(PacketPtr pkt); - virtual void recvFunctional(PacketPtr pkt); + virtual void recvFunctionalSnoop(PacketPtr pkt); virtual unsigned deviceBlockSize() const { return cache->getBlockSize(); } diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh index 3525e0777..fa6f6c860 100644 --- a/src/mem/cache/cache_impl.hh +++ b/src/mem/cache/cache_impl.hh @@ -785,7 +785,7 @@ Cache<TagStore>::functionalAccess(PacketPtr pkt, bool fromCpuSide) } else if (forwardSnoops && cpuSidePort->getMasterPort().isSnooping()) { // if it came from the memory side, it must be a snoop request // and we should only forward it if we are forwarding snoops - cpuSidePort->sendFunctional(pkt); + cpuSidePort->sendFunctionalSnoop(pkt); } } } @@ -1178,24 +1178,23 @@ Cache<TagStore>::handleSnoop(PacketPtr pkt, BlkType *blk, // rewritten to be relative to cpu-side bus (if any) bool alreadyResponded = pkt->memInhibitAsserted(); if (is_timing) { - Packet *snoopPkt = new Packet(pkt, true); // clear flags - snoopPkt->setExpressSnoop(); - snoopPkt->senderState = new ForwardResponseRecord(pkt, this); - cpuSidePort->sendTiming(snoopPkt); - if (snoopPkt->memInhibitAsserted()) { + Packet snoopPkt(pkt, true); // clear flags + snoopPkt.setExpressSnoop(); + snoopPkt.senderState = new ForwardResponseRecord(pkt, this); + cpuSidePort->sendTimingSnoop(&snoopPkt); + if (snoopPkt.memInhibitAsserted()) { // cache-to-cache response from some upper cache assert(!alreadyResponded); pkt->assertMemInhibit(); } else { - delete snoopPkt->senderState; + delete snoopPkt.senderState; } - if (snoopPkt->sharedAsserted()) { + if (snoopPkt.sharedAsserted()) { pkt->assertShared(); } - delete snoopPkt; } else { - int origSrc = pkt->getSrc(); - cpuSidePort->sendAtomic(pkt); + Packet::NodeID origSrc = pkt->getSrc(); + cpuSidePort->sendAtomicSnoop(pkt); if (!alreadyResponded && pkt->memInhibitAsserted()) { // cache-to-cache response from some upper cache: // forward response to original requester @@ -1335,6 +1334,16 @@ Cache<TagStore>::snoopTiming(PacketPtr pkt) handleSnoop(pkt, blk, true, false, false); } +template<class TagStore> +bool +Cache<TagStore>::CpuSidePort::recvTimingSnoop(PacketPtr pkt) +{ + // Express snoop responses from master to slave, e.g., from L1 to L2 + assert(pkt->isResponse()); + + cache->timingAccess(pkt); + return true; +} template<class TagStore> Tick @@ -1483,7 +1492,7 @@ Cache<TagStore>::getTimingPacket() PacketPtr snoop_pkt = new Packet(tgt_pkt, true); snoop_pkt->setExpressSnoop(); snoop_pkt->senderState = mshr; - cpuSidePort->sendTiming(snoop_pkt); + cpuSidePort->sendTimingSnoop(snoop_pkt); if (snoop_pkt->memInhibitAsserted()) { markInService(mshr, snoop_pkt); @@ -1550,8 +1559,9 @@ template<class TagStore> bool Cache<TagStore>::CpuSidePort::recvTiming(PacketPtr pkt) { - // illegal to block responses... can lead to deadlock - if (pkt->isRequest() && !pkt->memInhibitAsserted() && blocked) { + assert(pkt->isRequest()); + // always let inhibited requests through even if blocked + if (!pkt->memInhibitAsserted() && blocked) { DPRINTF(Cache,"Scheduling a retry while blocked\n"); mustSendRetry = true; return false; @@ -1603,17 +1613,25 @@ Cache<TagStore>::MemSidePort::recvTiming(PacketPtr pkt) if (pkt->wasNacked()) panic("Need to implement cache resending nacked packets!\n"); - if (pkt->isResponse()) { - cache->handleResponse(pkt); - } else { - cache->snoopTiming(pkt); - } + assert(pkt->isResponse()); + cache->handleResponse(pkt); + return true; +} + +// Express snooping requests to memside port +template<class TagStore> +bool +Cache<TagStore>::MemSidePort::recvTimingSnoop(PacketPtr pkt) +{ + // handle snooping requests + assert(pkt->isRequest()); + cache->snoopTiming(pkt); return true; } template<class TagStore> Tick -Cache<TagStore>::MemSidePort::recvAtomic(PacketPtr pkt) +Cache<TagStore>::MemSidePort::recvAtomicSnoop(PacketPtr pkt) { assert(pkt->isRequest()); // atomic snoop @@ -1622,7 +1640,7 @@ Cache<TagStore>::MemSidePort::recvAtomic(PacketPtr pkt) template<class TagStore> void -Cache<TagStore>::MemSidePort::recvFunctional(PacketPtr pkt) +Cache<TagStore>::MemSidePort::recvFunctionalSnoop(PacketPtr pkt) { assert(pkt->isRequest()); // functional snoop (note that in contrast to atomic we don't have diff --git a/src/mem/mport.cc b/src/mem/mport.cc index 9af394d27..5678f87d7 100644 --- a/src/mem/mport.cc +++ b/src/mem/mport.cc @@ -52,17 +52,3 @@ MessageSlavePort::recvAtomic(PacketPtr pkt) name(), pkt->cmd.toString(), getMasterPort().name()); } } - -Tick -MessageMasterPort::recvAtomic(PacketPtr pkt) -{ - if (pkt->cmd == MemCmd::MessageResp) { - // normally we would never see responses in recvAtomic, but - // since the timing port uses recvAtomic to implement - // recvTiming we have to deal with them here - return recvResponse(pkt); - } else { - panic("%s received unexpected atomic command %s from %s.\n", - name(), pkt->cmd.toString(), getSlavePort().name()); - } -} diff --git a/src/mem/mport.hh b/src/mem/mport.hh index 664acc559..7f9e8f4e0 100644 --- a/src/mem/mport.hh +++ b/src/mem/mport.hh @@ -82,11 +82,7 @@ class MessageMasterPort : public QueuedMasterPort virtual ~MessageMasterPort() {} - void recvFunctional(PacketPtr pkt) { assert(false); } - - Tick recvAtomic(PacketPtr pkt); - - bool recvTiming(PacketPtr pkt) { recvAtomic(pkt); return true; } + bool recvTiming(PacketPtr pkt) { recvResponse(pkt); return true; } protected: diff --git a/src/mem/packet_queue.cc b/src/mem/packet_queue.cc index 29914bea2..bffae5674 100644 --- a/src/mem/packet_queue.cc +++ b/src/mem/packet_queue.cc @@ -104,7 +104,7 @@ PacketQueue::schedSendEvent(Tick when) } void -PacketQueue::schedSendTiming(PacketPtr pkt, Tick when) +PacketQueue::schedSendTiming(PacketPtr pkt, Tick when, bool send_as_snoop) { assert(when > curTick()); @@ -114,14 +114,14 @@ PacketQueue::schedSendTiming(PacketPtr pkt, Tick when) // note that currently we ignore a potentially outstanding retry // and could in theory put a new packet at the head of the // transmit list before retrying the existing packet - transmitList.push_front(DeferredPacket(when, pkt)); + transmitList.push_front(DeferredPacket(when, pkt, send_as_snoop)); schedSendEvent(when); return; } // list is non-empty and this belongs at the end if (when >= transmitList.back().tick) { - transmitList.push_back(DeferredPacket(when, pkt)); + transmitList.push_back(DeferredPacket(when, pkt, send_as_snoop)); return; } @@ -130,7 +130,7 @@ PacketQueue::schedSendTiming(PacketPtr pkt, Tick when) ++i; // already checked for insertion at front while (i != transmitList.end() && when >= i->tick) ++i; - transmitList.insert(i, DeferredPacket(when, pkt)); + transmitList.insert(i, DeferredPacket(when, pkt, send_as_snoop)); } void PacketQueue::trySendTiming() @@ -143,7 +143,10 @@ void PacketQueue::trySendTiming() transmitList.pop_front(); // attempt to send the packet and remember the outcome - waitingOnRetry = !port.sendTiming(dp.pkt); + if (!dp.sendAsSnoop) + waitingOnRetry = !port.sendTiming(dp.pkt); + else + waitingOnRetry = !port.sendTimingSnoop(dp.pkt); if (waitingOnRetry) { // put the packet back at the front of the list (packet should diff --git a/src/mem/packet_queue.hh b/src/mem/packet_queue.hh index ac868802b..fbcd7d449 100644 --- a/src/mem/packet_queue.hh +++ b/src/mem/packet_queue.hh @@ -70,8 +70,9 @@ class PacketQueue public: Tick tick; ///< The tick when the packet is ready to transmit PacketPtr pkt; ///< Pointer to the packet to transmit - DeferredPacket(Tick t, PacketPtr p) - : tick(t), pkt(p) + bool sendAsSnoop; ///< Should it be sent as a snoop or not + DeferredPacket(Tick t, PacketPtr p, bool send_as_snoop) + : tick(t), pkt(p), sendAsSnoop(send_as_snoop) {} }; @@ -196,8 +197,9 @@ class PacketQueue * * @param pkt Packet to send * @param when Absolute time (in ticks) to send packet + * @param send_as_snoop Send the packet as a snoop or not */ - void schedSendTiming(PacketPtr pkt, Tick when); + void schedSendTiming(PacketPtr pkt, Tick when, bool send_as_snoop = false); /** * Used by a port to notify the queue that a retry was received @@ -215,4 +217,4 @@ class PacketQueue unsigned int drain(Event *de); }; -#endif // __MEM_TPORT_HH__ +#endif // __MEM_PACKET_QUEUE_HH__ diff --git a/src/mem/port.cc b/src/mem/port.cc index 3305541c7..92c6aaab8 100644 --- a/src/mem/port.cc +++ b/src/mem/port.cc @@ -104,7 +104,19 @@ MasterPort::peerBlockSize() const return _slavePort->deviceBlockSize(); } - void +Tick +MasterPort::sendAtomic(PacketPtr pkt) +{ + return _slavePort->recvAtomic(pkt); +} + +void +MasterPort::sendFunctional(PacketPtr pkt) +{ + return _slavePort->recvFunctional(pkt); +} + +void MasterPort::printAddr(Addr a) { Request req(a, 1, 0, Request::funcMasterId); @@ -155,3 +167,15 @@ SlavePort::isConnected() const { return _masterPort != NULL; } + +Tick +SlavePort::sendAtomicSnoop(PacketPtr pkt) +{ + return _masterPort->recvAtomicSnoop(pkt); +} + +void +SlavePort::sendFunctionalSnoop(PacketPtr pkt) +{ + return _masterPort->recvFunctionalSnoop(pkt); +} diff --git a/src/mem/port.hh b/src/mem/port.hh index 80bb3b085..61c92d8e4 100644 --- a/src/mem/port.hh +++ b/src/mem/port.hh @@ -115,28 +115,35 @@ class Port /** These functions are protected because they should only be * called by a peer port, never directly by any outside object. */ - /** Called to recive a timing call from the peer port. */ + /** + * Receive a timing request or response packet from the peer port. + */ virtual bool recvTiming(PacketPtr pkt) = 0; - /** Called to recive a atomic call from the peer port. */ - virtual Tick recvAtomic(PacketPtr pkt) = 0; - - /** Called to recive a functional call from the peer port. */ - virtual void recvFunctional(PacketPtr pkt) = 0; + /** + * Receive a timing snoop request or snoop response packet from + * the peer port. + */ + virtual bool recvTimingSnoop(PacketPtr pkt) + { + panic("%s was not expecting a timing snoop\n", name()); + return false; + } /** - * Called by a peer port if sendTiming was unsuccesful, and had to - * wait. + * Called by a peer port if sendTiming or sendTimingSnoop was + * unsuccesful, and had to wait. */ virtual void recvRetry() = 0; public: /** - * Attempt to send a timing packet to the peer port by calling its - * receive function. If the send does not succeed, as indicated by - * the return value, then the sender must wait for a recvRetry at - * which point it can re-issue a sendTiming. + * Attempt to send a timing request or response packet to the peer + * port by calling its receive function. If the send does not + * succeed, as indicated by the return value, then the sender must + * wait for a recvRetry at which point it can re-issue a + * sendTiming. * * @param pkt Packet to send. * @@ -145,30 +152,23 @@ class Port bool sendTiming(PacketPtr pkt) { return peer->recvTiming(pkt); } /** - * Send a retry to a peer port that previously attempted a sendTiming - * which was unsuccessful. - */ - void sendRetry() { return peer->recvRetry(); } - - /** - * Send an atomic packet, where the data is moved and the state - * is updated in zero time, without interleaving with other - * memory accesses. + * Attempt to send a timing snoop request or snoop response packet + * to the peer port by calling its receive function. If the send + * does not succeed, as indicated by the return value, then the + * sender must wait for a recvRetry at which point it can re-issue + * a sendTimingSnoop. * * @param pkt Packet to send. * - * @return Estimated latency of access. - */ - Tick sendAtomic(PacketPtr pkt) { return peer->recvAtomic(pkt); } + * @return If the send was succesful or not. + */ + bool sendTimingSnoop(PacketPtr pkt) { return peer->recvTimingSnoop(pkt); } /** - * Send a functional packet, where the data is instantly updated - * everywhere in the memory system, without affecting the current - * state of any block or moving the block. - * - * @param pkt Packet to send. + * Send a retry to a peer port that previously attempted a + * sendTiming or sendTimingSnoop which was unsuccessful. */ - void sendFunctional(PacketPtr pkt) { return peer->recvFunctional(pkt); } + void sendRetry() { return peer->recvRetry(); } }; @@ -198,6 +198,43 @@ class MasterPort : public Port bool isConnected() const; /** + * Send an atomic request packet, where the data is moved and the + * state is updated in zero time, without interleaving with other + * memory accesses. + * + * @param pkt Packet to send. + * + * @return Estimated latency of access. + */ + Tick sendAtomic(PacketPtr pkt); + + /** + * Send a functional request packet, where the data is instantly + * updated everywhere in the memory system, without affecting the + * current state of any block or moving the block. + * + * @param pkt Packet to send. + */ + void sendFunctional(PacketPtr pkt); + + /** + * Receive an atomic snoop request packet from the slave port. + */ + virtual Tick recvAtomicSnoop(PacketPtr pkt) + { + panic("%s was not expecting an atomic snoop\n", name()); + return 0; + } + + /** + * Receive a functional snoop request packet from the slave port. + */ + virtual void recvFunctionalSnoop(PacketPtr pkt) + { + panic("%s was not expecting a functional snoop\n", name()); + } + + /** * Called to receive an address range change from the peer slave * port. the default implementation ignored the change and does * nothing. Override this function in a derived class if the owner @@ -257,6 +294,36 @@ class SlavePort : public Port bool isConnected() const; /** + * Send an atomic snoop request packet, where the data is moved + * and the state is updated in zero time, without interleaving + * with other memory accesses. + * + * @param pkt Snoop packet to send. + * + * @return Estimated latency of access. + */ + Tick sendAtomicSnoop(PacketPtr pkt); + + /** + * Send a functional snoop request packet, where the data is + * instantly updated everywhere in the memory system, without + * affecting the current state of any block or moving the block. + * + * @param pkt Snoop packet to send. + */ + void sendFunctionalSnoop(PacketPtr pkt); + + /** + * Receive an atomic request packet from the master port. + */ + virtual Tick recvAtomic(PacketPtr pkt) = 0; + + /** + * Receive a functional request packet from the master port. + */ + virtual void recvFunctional(PacketPtr pkt) = 0; + + /** * Called by a peer port in order to determine the block size of * the owner of this port. */ diff --git a/src/mem/ruby/system/RubyPort.cc b/src/mem/ruby/system/RubyPort.cc index 0cdb919b1..74a60f863 100644 --- a/src/mem/ruby/system/RubyPort.cc +++ b/src/mem/ruby/system/RubyPort.cc @@ -133,13 +133,6 @@ RubyPort::M5Port::M5Port(const std::string &_name, RubyPort *_port, } Tick -RubyPort::PioPort::recvAtomic(PacketPtr pkt) -{ - panic("RubyPort::PioPort::recvAtomic() not implemented!\n"); - return 0; -} - -Tick RubyPort::M5Port::recvAtomic(PacketPtr pkt) { panic("RubyPort::M5Port::recvAtomic() not implemented!\n"); @@ -662,10 +655,11 @@ RubyPort::M5Port::hitCallback(PacketPtr pkt) } bool -RubyPort::M5Port::sendNextCycle(PacketPtr pkt) +RubyPort::M5Port::sendNextCycle(PacketPtr pkt, bool send_as_snoop) { //minimum latency, must be > 0 - queue.schedSendTiming(pkt, curTick() + (1 * g_eventQueue_ptr->getClock())); + queue.schedSendTiming(pkt, curTick() + (1 * g_eventQueue_ptr->getClock()), + send_as_snoop); return true; } @@ -706,7 +700,8 @@ RubyPort::ruby_eviction_callback(const Address& address) for (CpuPortIter p = slave_ports.begin(); p != slave_ports.end(); ++p) { if ((*p)->getMasterPort().isSnooping()) { Packet *pkt = new Packet(&req, MemCmd::InvalidationReq, -1); - (*p)->sendNextCycle(pkt); + // send as a snoop request + (*p)->sendNextCycle(pkt, true); } } } diff --git a/src/mem/ruby/system/RubyPort.hh b/src/mem/ruby/system/RubyPort.hh index 553614021..f41c98f55 100644 --- a/src/mem/ruby/system/RubyPort.hh +++ b/src/mem/ruby/system/RubyPort.hh @@ -71,7 +71,7 @@ class RubyPort : public MemObject public: M5Port(const std::string &_name, RubyPort *_port, RubySystem*_system, bool _access_phys_mem); - bool sendNextCycle(PacketPtr pkt); + bool sendNextCycle(PacketPtr pkt, bool send_as_snoop = false); void hitCallback(PacketPtr pkt); void evictionCallback(const Address& address); unsigned deviceBlockSize() const; @@ -110,8 +110,6 @@ class RubyPort : public MemObject protected: virtual bool recvTiming(PacketPtr pkt); - virtual Tick recvAtomic(PacketPtr pkt); - virtual void recvFunctional(PacketPtr pkt) { } }; friend class PioPort; |