diff options
author | Andreas Hansson <andreas.hansson@arm.com> | 2013-03-26 14:46:47 -0400 |
---|---|---|
committer | Andreas Hansson <andreas.hansson@arm.com> | 2013-03-26 14:46:47 -0400 |
commit | 93a8423dea8f8194d83df85a5b3043f9beaf0a1e (patch) | |
tree | ec1ea615c270a0e8524d4bc3ab442781a0c4f043 /src/mem/coherent_bus.cc | |
parent | 362f6f1a16a68a99c962628bcda00c7c576f935c (diff) | |
download | gem5-93a8423dea8f8194d83df85a5b3043f9beaf0a1e.tar.xz |
mem: Separate waiting for the bus and waiting for a peer
This patch splits the retryList into a list of ports that are waiting
for the bus itself to become available, and a map that tracks the
ports where forwarding failed due to a peer not accepting the
packet. Thus, when a retry reaches the bus, it can be sent to the
appropriate port that initiated that transaction.
As a consequence of this patch, only ports that are really ready to go
will get a retry, thus reducing the amount of redundant failed
attempts. This patch also makes it easier to reason about the order of
servicing requests as the ports waiting for the bus are now clearly
FIFO and much easier to change if desired.
Diffstat (limited to 'src/mem/coherent_bus.cc')
-rw-r--r-- | src/mem/coherent_bus.cc | 37 |
1 files changed, 23 insertions, 14 deletions
diff --git a/src/mem/coherent_bus.cc b/src/mem/coherent_bus.cc index 0166872a7..8bc183fd0 100644 --- a/src/mem/coherent_bus.cc +++ b/src/mem/coherent_bus.cc @@ -55,9 +55,13 @@ #include "sim/system.hh" CoherentBus::CoherentBus(const CoherentBusParams *p) - : BaseBus(p), reqLayer(*this, ".reqLayer"), - respLayer(*this, ".respLayer"), - snoopRespLayer(*this, ".snoopRespLayer"), + : BaseBus(p), + reqLayer(*this, ".reqLayer", p->port_master_connection_count + + p->port_default_connection_count), + respLayer(*this, ".respLayer", p->port_slave_connection_count), + snoopRespLayer(*this, ".snoopRespLayer", + p->port_master_connection_count + + p->port_default_connection_count), system(p->system) { // create the ports based on the size of the master and slave @@ -120,10 +124,13 @@ CoherentBus::recvTimingReq(PacketPtr pkt, PortID slave_port_id) // remember if the packet is an express snoop bool is_express_snoop = pkt->isExpressSnoop(); + // determine the destination based on the address + PortID dest_port_id = findPort(pkt->getAddr()); + // test if the bus should be considered occupied for the current // port, and exclude express snoops from the check - if (!is_express_snoop && !reqLayer.tryTiming(src_port)) { - DPRINTF(CoherentBus, "recvTimingReq: src %s %s 0x%x BUSY\n", + if (!is_express_snoop && !reqLayer.tryTiming(src_port, dest_port_id)) { + DPRINTF(CoherentBus, "recvTimingReq: src %s %s 0x%x BUS BUSY\n", src_port->name(), pkt->cmdString(), pkt->getAddr()); return false; } @@ -161,9 +168,8 @@ CoherentBus::recvTimingReq(PacketPtr pkt, PortID slave_port_id) outstandingReq.insert(pkt->req); } - // 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())]->sendTimingReq(pkt); + // since it is a normal request, attempt to send the packet + bool success = masterPorts[dest_port_id]->sendTimingReq(pkt); // if this is an express snoop, we are done at this point if (is_express_snoop) { @@ -186,7 +192,8 @@ CoherentBus::recvTimingReq(PacketPtr pkt, PortID slave_port_id) src_port->name(), pkt->cmdString(), pkt->getAddr()); // update the bus state and schedule an idle event - reqLayer.failedTiming(src_port, clockEdge(Cycles(headerCycles))); + reqLayer.failedTiming(src_port, dest_port_id, + clockEdge(Cycles(headerCycles))); } else { // update the bus state and schedule an idle event reqLayer.succeededTiming(packetFinishTime); @@ -204,7 +211,7 @@ CoherentBus::recvTimingResp(PacketPtr pkt, PortID master_port_id) // test if the bus should be considered occupied for the current // port - if (!respLayer.tryTiming(src_port)) { + if (!respLayer.tryTiming(src_port, pkt->getDest())) { DPRINTF(CoherentBus, "recvTimingResp: src %s %s 0x%x BUSY\n", src_port->name(), pkt->cmdString(), pkt->getAddr()); return false; @@ -267,8 +274,10 @@ CoherentBus::recvTimingSnoopResp(PacketPtr pkt, PortID slave_port_id) SlavePort* src_port = slavePorts[slave_port_id]; // test if the bus should be considered occupied for the current - // port - if (!snoopRespLayer.tryTiming(src_port)) { + // port, do not use the destination port in the check as we do not + // know yet if it is to be passed on as a snoop response or normal + // response and we never block on either + if (!snoopRespLayer.tryTiming(src_port, InvalidPortID)) { DPRINTF(CoherentBus, "recvTimingSnoopResp: src %s %s 0x%x BUSY\n", src_port->name(), pkt->cmdString(), pkt->getAddr()); return false; @@ -346,12 +355,12 @@ CoherentBus::forwardTiming(PacketPtr pkt, PortID exclude_slave_port_id) } void -CoherentBus::recvRetry() +CoherentBus::recvRetry(PortID master_port_id) { // responses and snoop responses never block on forwarding them, // so the retry will always be coming from a port to which we // tried to forward a request - reqLayer.recvRetry(); + reqLayer.recvRetry(master_port_id); } Tick |