From ecef1612b8a9a5632c8354ccb000184c2f82ddf3 Mon Sep 17 00:00:00 2001 From: Stephan Diestelhorst Date: Mon, 2 Mar 2015 04:00:49 -0500 Subject: mem: Add option to force in-order insertion in PacketQueue By default, the packet queue is ordered by the ticks of the to-be-sent packages. With the recent modifications of packages sinking their header time when their resposne leaves the caches, there could be cases of MSHR targets being allocated and ordered A, B, but their responses being sent out in the order B,A. This led to inconsistencies in bus traffic, in particular the snoop filter observing first a ReadExResp and later a ReadRespWithInv. Logically, these were ordered the other way around behind the MSHR, but due to the timing adjustments when inserting into the PacketQueue, they were sent out in the wrong order on the bus, confusing the snoop filter. This patch adds a flag (off by default) such that these special cases can request in-order insertion into the packet queue, which might offset timing slighty. This is expected to occur rarely and not affect timing results. --- src/mem/packet_queue.cc | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) (limited to 'src/mem/packet_queue.cc') diff --git a/src/mem/packet_queue.cc b/src/mem/packet_queue.cc index 29f6d2903..1b2c69930 100644 --- a/src/mem/packet_queue.cc +++ b/src/mem/packet_queue.cc @@ -100,10 +100,11 @@ PacketQueue::checkFunctional(PacketPtr pkt) } void -PacketQueue::schedSendTiming(PacketPtr pkt, Tick when) +PacketQueue::schedSendTiming(PacketPtr pkt, Tick when, bool force_order) { - DPRINTF(PacketQueue, "%s for %s address %x size %d\n", __func__, - pkt->cmdString(), pkt->getAddr(), pkt->getSize()); + DPRINTF(PacketQueue, "%s for %s address %x size %d when %lu ord: %i\n", + __func__, pkt->cmdString(), pkt->getAddr(), pkt->getSize(), when, + force_order); // we can still send a packet before the end of this tick assert(when >= curTick()); @@ -118,9 +119,26 @@ PacketQueue::schedSendTiming(PacketPtr pkt, Tick when) name()); } + // if requested, force the timing to be in-order by changing the when + // parameter + if (force_order && !transmitList.empty()) { + Tick back = transmitList.back().tick; + + // fudge timing if required; relies on the code below to do the right + // thing (push_back) with the updated time-stamp + if (when < back) { + DPRINTF(PacketQueue, "%s force_order shifted packet %s address "\ + "%x from %lu to %lu\n", __func__, pkt->cmdString(), + pkt->getAddr(), when, back); + when = back; + } + } + // nothing on the list, or earlier than current front element, // schedule an event if (transmitList.empty() || when < transmitList.front().tick) { + // force_order-ed in here only when list is empty + assert(!force_order || transmitList.empty()); // 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 @@ -143,6 +161,9 @@ PacketQueue::schedSendTiming(PacketPtr pkt, Tick when) return; } + // forced orders never need insertion in the middle + assert(!force_order); + // this belongs in the middle somewhere, insertion sort auto i = transmitList.begin(); ++i; // already checked for insertion at front -- cgit v1.2.3