mem: Order packet queue only on matching addresses
Instead of conservatively enforcing order for all packets, which may negatively impact the simulated-system performance, this patch updates the packet queue such that it only applies the restriction if there are already packets with the same address in the queue. The basic need for the order enforcement is due to coherency interactions where requests/responses to the same cache line must not over-take each other. We rely on the fact that any packet that needs order enforcement will have a block-aligned address. Thus, there is no need for the queue to know about the cacheline size.
This commit is contained in:
parent
52c8ae5187
commit
c086c20bd2
2 changed files with 15 additions and 39 deletions
|
@ -119,29 +119,8 @@ PacketQueue::schedSendTiming(PacketPtr pkt, Tick when, bool force_order)
|
|||
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
|
||||
// nothing on the list
|
||||
if (transmitList.empty()) {
|
||||
transmitList.emplace_front(when, pkt);
|
||||
schedSendEvent(when);
|
||||
return;
|
||||
|
@ -155,21 +134,19 @@ PacketQueue::schedSendTiming(PacketPtr pkt, Tick when, bool force_order)
|
|||
// ourselves again before we had a chance to update waitingOnRetry
|
||||
// assert(waitingOnRetry || sendEvent.scheduled());
|
||||
|
||||
// list is non-empty and this belongs at the end
|
||||
if (when >= transmitList.back().tick) {
|
||||
transmitList.emplace_back(when, pkt);
|
||||
return;
|
||||
}
|
||||
// this belongs in the middle somewhere, so search from the end to
|
||||
// order by tick; however, if force_order is set, also make sure
|
||||
// not to re-order in front of some existing packet with the same
|
||||
// address
|
||||
auto i = transmitList.end();
|
||||
--i;
|
||||
while (i != transmitList.begin() && when < i->tick &&
|
||||
!(force_order && i->pkt->getAddr() == pkt->getAddr()))
|
||||
--i;
|
||||
|
||||
// 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
|
||||
while (i != transmitList.end() && when >= i->tick)
|
||||
++i;
|
||||
transmitList.emplace(i, when, pkt);
|
||||
// emplace inserts the element before the position pointed to by
|
||||
// the iterator, so advance it one step
|
||||
transmitList.emplace(++i, when, pkt);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -176,8 +176,7 @@ class PacketQueue : public Drainable
|
|||
*
|
||||
* @param pkt Packet to send
|
||||
* @param when Absolute time (in ticks) to send packet
|
||||
* @param force_order Do not reorder packets despite timing, but keep them
|
||||
* in insertion order.
|
||||
* @param force_order Force insertion order for packets with same address
|
||||
*/
|
||||
void schedSendTiming(PacketPtr pkt, Tick when, bool force_order = false);
|
||||
|
||||
|
|
Loading…
Reference in a new issue