144a145,148
> bool is_inhibited = pkt->memInhibitAsserted();
> // for normal requests, going downstream, the express snoop flag
> // and the inhibited flag should always be the same
> assert(is_express_snoop == is_inhibited);
166,168d169
< // set the source port for routing of the response
< pkt->setSrc(slave_port_id);
<
190,194c191,194
< // 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 = !is_express_snoop && pkt->needsResponse();
---
> // remember if the packet will generate a snoop response
> const bool expect_snoop_resp = !is_inhibited && pkt->memInhibitAsserted();
> const bool expect_response = pkt->needsResponse() &&
> !pkt->memInhibitAsserted();
196,205d195
< // 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);
< }
<
227,230c217,232
< // if this is an express snoop, we are done at this point
< if (is_express_snoop) {
< assert(success);
< snoops++;
---
> // check if we were successful in sending the packet onwards
> if (!success) {
> // express snoops and inhibited packets should never be forced
> // to retry
> assert(!is_express_snoop);
> assert(!pkt->memInhibitAsserted());
>
> // undo the calculation so we can check for 0 again
> pkt->firstWordDelay = pkt->lastWordDelay = 0;
>
> DPRINTF(CoherentXBar, "recvTimingReq: src %s %s 0x%x RETRY\n",
> src_port->name(), pkt->cmdString(), pkt->getAddr());
>
> // update the layer state and schedule an idle event
> reqLayers[master_port_id]->failedTiming(src_port,
> clockEdge(headerCycles));
232,235c234,242
< // for normal requests, check if successful
< if (!success) {
< // inhibited packets should never be forced to retry
< assert(!pkt->memInhibitAsserted());
---
> // express snoops currently bypass the crossbar state entirely
> if (!is_express_snoop) {
> // if this particular request will generate a snoop
> // response
> if (expect_snoop_resp) {
> // we should never have an exsiting request outstanding
> assert(outstandingSnoop.find(pkt->req) ==
> outstandingSnoop.end());
> outstandingSnoop.insert(pkt->req);
237,240c244,247
< // if it was added as outstanding and the send failed, then
< // erase it again
< if (add_outstanding)
< outstandingReq.erase(pkt->req);
---
> // basic sanity check on the outstanding snoops
> panic_if(outstandingSnoop.size() > 512,
> "Outstanding snoop requests exceeded 512\n");
> }
242,243c249,252
< // undo the calculation so we can check for 0 again
< pkt->firstWordDelay = pkt->lastWordDelay = 0;
---
> // remember where to route the normal response to
> if (expect_response || expect_snoop_resp) {
> assert(routeTo.find(pkt->req) == routeTo.end());
> routeTo[pkt->req] = slave_port_id;
245,246c254,256
< DPRINTF(CoherentXBar, "recvTimingReq: src %s %s 0x%x RETRY\n",
< src_port->name(), pkt->cmdString(), pkt->getAddr());
---
> panic_if(routeTo.size() > 512,
> "Routing table exceeds 512 packets\n");
> }
249,252d258
< reqLayers[master_port_id]->failedTiming(src_port,
< clockEdge(headerCycles));
< } else {
< // update the layer state and schedule an idle event
255d260
< }
257,258c262
< // stats updates only consider packets that were successfully sent
< if (success) {
---
> // stats updates only consider packets that were successfully sent
261a266,268
>
> if (is_express_snoop)
> snoops++;
273,274c280,283
< // determine the destination based on what is stored in the packet
< PortID slave_port_id = pkt->getDest();
---
> // determine the destination
> const auto route_lookup = routeTo.find(pkt->req);
> assert(route_lookup != routeTo.end());
> const PortID slave_port_id = route_lookup->second;
297,300d305
< // the packet is a normal response to a request that we should
< // have seen passing through the crossbar
< assert(outstandingReq.find(pkt->req) != outstandingReq.end());
<
306,308d310
< // remove it as outstanding
< outstandingReq.erase(pkt->req);
<
315a318,320
> // remove the request from the routing table
> routeTo.erase(route_lookup);
>
340,341c345,346
< // set the source port for routing of the response
< pkt->setSrc(master_port_id);
---
> // remeber if the packet is inhibited so we can see if it changes
> const bool is_inhibited = pkt->memInhibitAsserted();
357a363,368
> // if we can expect a response, remember how to route it
> if (!is_inhibited && pkt->memInhibitAsserted()) {
> assert(routeTo.find(pkt->req) == routeTo.end());
> routeTo[pkt->req] = master_port_id;
> }
>
372,373c383,386
< // get the destination from the packet
< PortID dest_port_id = pkt->getDest();
---
> // get the destination
> const auto route_lookup = routeTo.find(pkt->req);
> assert(route_lookup != routeTo.end());
> const PortID dest_port_id = route_lookup->second;
378c391
< // should be in the outstandingReq), or if we merely forwarded
---
> // should be in the outstandingSnoop), or if we merely forwarded
380,381c393,394
< bool forwardAsSnoop = outstandingReq.find(pkt->req) ==
< outstandingReq.end();
---
> const bool forwardAsSnoop = outstandingSnoop.find(pkt->req) ==
> outstandingSnoop.end();
443c456
< outstandingReq.erase(pkt->req);
---
> outstandingSnoop.erase(pkt->req);
445,449c458,460
< // this is a snoop response from a coherent master, with a
< // destination field set on its way through the crossbar as
< // request, hence it should never go back to where the snoop
< // response came from, but instead to where the original
< // request came from
---
> // this is a snoop response from a coherent master, hence it
> // should never go back to where the snoop response came from,
> // but instead to where the original request came from
478a490,492
> // remove the request from the routing table
> routeTo.erase(route_lookup);
>