mem: Determine if a packet queue forces ordering at construction

A packet queue is typically used to hold on to packets that are
schedules to be sent in the future or when they need to queue behind
younger packets that have been sent out yet. Due to memory order
requirements, some MemObjects need to maintain the order for packet
(mostly responses) that reference the same cache block.

Prior to this patch the ordering requirements where determined when
the packet was scheduled to be sent. This patch moves the parameter to
the constructor.

Change-Id: Ieb4d94e86bc7514f5036b313ec23ea47dd653164
Signed-off-by: Nikos Nikoleris <nikos.nikoleris@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/c/15555
Reviewed-by: Daniel Carvalho <odanrc@yahoo.com.br>
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
Maintainer: Jason Lowe-Power <jason@lowepower.com>
diff --git a/src/mem/cache/base.cc b/src/mem/cache/base.cc
index 08cd09f..6049ca6 100644
--- a/src/mem/cache/base.cc
+++ b/src/mem/cache/base.cc
@@ -69,7 +69,8 @@
 BaseCache::CacheSlavePort::CacheSlavePort(const std::string &_name,
                                           BaseCache *_cache,
                                           const std::string &_label)
-    : QueuedSlavePort(_name, _cache, queue), queue(*_cache, *this, _label),
+    : QueuedSlavePort(_name, _cache, queue),
+      queue(*_cache, *this, true, _label),
       blocked(false), mustSendRetry(false),
       sendRetryEvent([this]{ processSendRetry(); }, _name)
 {
@@ -228,7 +229,7 @@
         // lat, neglecting responseLatency, modelling hit latency
         // just as the value of lat overriden by access(), which calls
         // the calculateAccessLatency() function.
-        cpuSidePort.schedTimingResp(pkt, request_time, true);
+        cpuSidePort.schedTimingResp(pkt, request_time);
     } else {
         DPRINTF(Cache, "%s satisfied %s, no response needed\n", __func__,
                 pkt->print());
@@ -400,7 +401,7 @@
     // Reset the bus additional time as it is now accounted for
     pkt->headerDelay = pkt->payloadDelay = 0;
 
-    cpuSidePort.schedTimingResp(pkt, completion_time, true);
+    cpuSidePort.schedTimingResp(pkt, completion_time);
 }
 
 void
@@ -2400,7 +2401,7 @@
                                     const std::string &_label)
     : CacheMasterPort(_name, _cache, _reqQueue, _snoopRespQueue),
       _reqQueue(*_cache, *this, _snoopRespQueue, _label),
-      _snoopRespQueue(*_cache, *this, _label), cache(_cache)
+      _snoopRespQueue(*_cache, *this, true, _label), cache(_cache)
 {
 }
 
diff --git a/src/mem/cache/cache.cc b/src/mem/cache/cache.cc
index 90c4b9b..e23c4ef 100644
--- a/src/mem/cache/cache.cc
+++ b/src/mem/cache/cache.cc
@@ -391,7 +391,7 @@
 
         // request_time is used here, taking into account lat and the delay
         // charged if the packet comes from the xbar.
-        cpuSidePort.schedTimingResp(pkt, request_time, true);
+        cpuSidePort.schedTimingResp(pkt, request_time);
 
         // If an outstanding request is in progress (we found an
         // MSHR) this is set to null
@@ -802,7 +802,7 @@
             }
             // Reset the bus additional time as it is now accounted for
             tgt_pkt->headerDelay = tgt_pkt->payloadDelay = 0;
-            cpuSidePort.schedTimingResp(tgt_pkt, completion_time, true);
+            cpuSidePort.schedTimingResp(tgt_pkt, completion_time);
             break;
 
           case MSHR::Target::FromPrefetcher:
@@ -932,7 +932,7 @@
     pkt->headerDelay = pkt->payloadDelay = 0;
     DPRINTF(CacheVerbose, "%s: created response: %s tick: %lu\n", __func__,
             pkt->print(), forward_time);
-    memSidePort.schedTimingSnoopResp(pkt, forward_time, true);
+    memSidePort.schedTimingSnoopResp(pkt, forward_time);
 }
 
 uint32_t
diff --git a/src/mem/cache/noncoherent_cache.cc b/src/mem/cache/noncoherent_cache.cc
index ca282a3..08cfdd6 100644
--- a/src/mem/cache/noncoherent_cache.cc
+++ b/src/mem/cache/noncoherent_cache.cc
@@ -288,7 +288,7 @@
 
             // Reset the bus additional time as it is now accounted for
             tgt_pkt->headerDelay = tgt_pkt->payloadDelay = 0;
-            cpuSidePort.schedTimingResp(tgt_pkt, completion_time, true);
+            cpuSidePort.schedTimingResp(tgt_pkt, completion_time);
             break;
 
           case MSHR::Target::FromPrefetcher:
diff --git a/src/mem/dram_ctrl.cc b/src/mem/dram_ctrl.cc
index e7af75b..b6ec465 100644
--- a/src/mem/dram_ctrl.cc
+++ b/src/mem/dram_ctrl.cc
@@ -938,7 +938,7 @@
 
         // queue the packet in the response queue to be sent out after
         // the static latency has passed
-        port.schedTimingResp(pkt, response_time, true);
+        port.schedTimingResp(pkt, response_time);
     } else {
         // @todo the packet is going to be deleted, and the DRAMPacket
         // is still having a pointer to it
@@ -2924,7 +2924,7 @@
 }
 
 DRAMCtrl::MemoryPort::MemoryPort(const std::string& name, DRAMCtrl& _memory)
-    : QueuedSlavePort(name, &_memory, queue), queue(_memory, *this),
+    : QueuedSlavePort(name, &_memory, queue), queue(_memory, *this, true),
       memory(_memory)
 { }
 
diff --git a/src/mem/packet_queue.cc b/src/mem/packet_queue.cc
index 7aa2fc1..45378ae 100644
--- a/src/mem/packet_queue.cc
+++ b/src/mem/packet_queue.cc
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012,2015 ARM Limited
+ * Copyright (c) 2012,2015,2018 ARM Limited
  * All rights reserved.
  *
  * The license below extends only to copyright in the software and shall
@@ -49,9 +49,11 @@
 
 PacketQueue::PacketQueue(EventManager& _em, const std::string& _label,
                          const std::string& _sendEventName,
+                         bool force_order,
                          bool disable_sanity_check)
     : em(_em), sendEvent([this]{ processSendEvent(); }, _sendEventName),
       _disableSanityCheck(disable_sanity_check),
+      forceOrder(force_order),
       label(_label), waitingOnRetry(false)
 {
 }
@@ -102,11 +104,11 @@
 }
 
 void
-PacketQueue::schedSendTiming(PacketPtr pkt, Tick when, bool force_order)
+PacketQueue::schedSendTiming(PacketPtr pkt, Tick when)
 {
     DPRINTF(PacketQueue, "%s for %s address %x size %d when %lu ord: %i\n",
             __func__, pkt->cmdString(), pkt->getAddr(), pkt->getSize(), when,
-            force_order);
+            forceOrder);
 
     // we can still send a packet before the end of this tick
     assert(when >= curTick());
@@ -137,13 +139,13 @@
     // assert(waitingOnRetry || sendEvent.scheduled());
 
     // this belongs in the middle somewhere, so search from the end to
-    // order by tick; however, if force_order is set, also make sure
+    // order by tick; however, if forceOrder 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()))
+           !(forceOrder && i->pkt->getAddr() == pkt->getAddr()))
         --i;
 
     // emplace inserts the element before the position pointed to by
@@ -250,8 +252,9 @@
 
 SnoopRespPacketQueue::SnoopRespPacketQueue(EventManager& _em,
                                            MasterPort& _masterPort,
+                                           bool force_order,
                                            const std::string _label)
-    : PacketQueue(_em, _label, name(_masterPort, _label)),
+    : PacketQueue(_em, _label, name(_masterPort, _label), force_order),
       masterPort(_masterPort)
 {
 }
@@ -263,8 +266,9 @@
 }
 
 RespPacketQueue::RespPacketQueue(EventManager& _em, SlavePort& _slavePort,
+                                 bool force_order,
                                  const std::string _label)
-    : PacketQueue(_em, _label, name(_slavePort, _label)),
+    : PacketQueue(_em, _label, name(_slavePort, _label), force_order),
       slavePort(_slavePort)
 {
 }
diff --git a/src/mem/packet_queue.hh b/src/mem/packet_queue.hh
index 629fca5..4ac4bf3 100644
--- a/src/mem/packet_queue.hh
+++ b/src/mem/packet_queue.hh
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012,2015 ARM Limited
+ * Copyright (c) 2012,2015,2018 ARM Limited
  * All rights reserved.
  *
  * The license below extends only to copyright in the software and shall
@@ -96,6 +96,13 @@
       */
     bool _disableSanityCheck;
 
+    /**
+     * if true, inserted packets have to be unconditionally scheduled
+     * after the last packet in the queue that references the same
+     * address
+     */
+    bool forceOrder;
+
   protected:
 
     /** Label to use for print request packets label stack. */
@@ -130,11 +137,13 @@
      *
      * @param _em Event manager used for scheduling this queue
      * @param _label Label to push on the label stack for print request packets
+     * @param force_order Force insertion order for packets with same address
      * @param disable_sanity_check Flag used to disable the sanity check
      *        on the size of the transmitList. The check is enabled by default.
      */
     PacketQueue(EventManager& _em, const std::string& _label,
                 const std::string& _sendEventName,
+                bool force_order = false,
                 bool disable_sanity_check = false);
 
     /**
@@ -187,9 +196,8 @@
      *
      * @param pkt Packet to send
      * @param when Absolute time (in ticks) to send packet
-     * @param force_order Force insertion order for packets with same address
      */
-    void schedSendTiming(PacketPtr pkt, Tick when, bool force_order = false);
+    void schedSendTiming(PacketPtr pkt, Tick when);
 
     /**
      * Retry sending a packet from the queue. Note that this is not
@@ -267,9 +275,11 @@
      *
      * @param _em Event manager used for scheduling this queue
      * @param _masterPort Master port used to send the packets
+     * @param force_order Force insertion order for packets with same address
      * @param _label Label to push on the label stack for print request packets
      */
     SnoopRespPacketQueue(EventManager& _em, MasterPort& _masterPort,
+                         bool force_order = false,
                          const std::string _label = "SnoopRespPacketQueue");
 
     virtual ~SnoopRespPacketQueue() { }
@@ -303,10 +313,12 @@
      *
      * @param _em Event manager used for scheduling this queue
      * @param _slavePort Slave port used to send the packets
+     * @param force_order Force insertion order for packets with same address
      * @param _label Label to push on the label stack for print request packets
      */
     RespPacketQueue(EventManager& _em, SlavePort& _slavePort,
-                     const std::string _label = "RespPacketQueue");
+                    bool force_order = false,
+                    const std::string _label = "RespPacketQueue");
 
     virtual ~RespPacketQueue() { }
 
diff --git a/src/mem/qos/mem_sink.cc b/src/mem/qos/mem_sink.cc
index a951dae..77cfbaf 100644
--- a/src/mem/qos/mem_sink.cc
+++ b/src/mem/qos/mem_sink.cc
@@ -289,7 +289,7 @@
                 removed_entries, responseLatency);
 
     // Schedule the response
-    port.schedTimingResp(pkt, curTick() + responseLatency, true);
+    port.schedTimingResp(pkt, curTick() + responseLatency);
     DPRINTF(QOS,
             "%s response scheduled at time %d\n",
             __func__, curTick() + responseLatency);
@@ -344,7 +344,7 @@
 
 MemSinkCtrl::MemoryPort::MemoryPort(const std::string& n,
                                     MemSinkCtrl& m)
-  : QueuedSlavePort(n, &m, queue), memory(m), queue(memory, *this)
+  : QueuedSlavePort(n, &m, queue, true), memory(m), queue(memory, *this, true)
 {}
 
 AddrRangeList
diff --git a/src/mem/qport.hh b/src/mem/qport.hh
index 708347a..77d8dfa 100644
--- a/src/mem/qport.hh
+++ b/src/mem/qport.hh
@@ -88,8 +88,8 @@
      * @param pkt Packet to send
      * @param when Absolute time (in ticks) to send packet
      */
-    void schedTimingResp(PacketPtr pkt, Tick when, bool force_order = false)
-    { respQueue.schedSendTiming(pkt, when, force_order); }
+    void schedTimingResp(PacketPtr pkt, Tick when)
+    { respQueue.schedSendTiming(pkt, when); }
 
     /** Check the list of buffered packets against the supplied
      * functional request. */
@@ -153,9 +153,8 @@
      * @param pkt Packet to send
      * @param when Absolute time (in ticks) to send packet
      */
-    void schedTimingSnoopResp(PacketPtr pkt, Tick when, bool force_order =
-                              false)
-    { snoopRespQueue.schedSendTiming(pkt, when, force_order); }
+    void schedTimingSnoopResp(PacketPtr pkt, Tick when)
+    { snoopRespQueue.schedSendTiming(pkt, when); }
 
     /** Check the list of buffered packets against the supplied
      * functional request. */
diff --git a/src/mem/ruby/slicc_interface/AbstractController.cc b/src/mem/ruby/slicc_interface/AbstractController.cc
index 101a4ce..1327ecc 100644
--- a/src/mem/ruby/slicc_interface/AbstractController.cc
+++ b/src/mem/ruby/slicc_interface/AbstractController.cc
@@ -382,7 +382,7 @@
                                            const std::string &_label)
     : QueuedMasterPort(_name, _controller, reqQueue, snoopRespQueue),
       reqQueue(*_controller, *this, _label),
-      snoopRespQueue(*_controller, *this, _label),
+      snoopRespQueue(*_controller, *this, false, _label),
       controller(_controller)
 {
 }