summaryrefslogtreecommitdiff
path: root/src/mem/qos/q_policy.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/mem/qos/q_policy.cc')
-rw-r--r--src/mem/qos/q_policy.cc147
1 files changed, 147 insertions, 0 deletions
diff --git a/src/mem/qos/q_policy.cc b/src/mem/qos/q_policy.cc
new file mode 100644
index 000000000..88ce95d0a
--- /dev/null
+++ b/src/mem/qos/q_policy.cc
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2018 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Author: Matteo Andreozzi
+ */
+
+#include "mem/qos/q_policy.hh"
+
+#include <unordered_map>
+#include <utility>
+
+#include "debug/QOS.hh"
+#include "enums/QoSQPolicy.hh"
+#include "mem/qos/mem_ctrl.hh"
+
+namespace QoS {
+
+QueuePolicy*
+QueuePolicy::create(const QoSMemCtrlParams* p)
+{
+ switch (p->qos_q_policy) {
+ case Enums::QoSQPolicy::fifo:
+ return new FifoQueuePolicy(p);
+ case Enums::QoSQPolicy::lrg:
+ return new LrgQueuePolicy(p);
+ case Enums::QoSQPolicy::lifo:
+ default:
+ return new LifoQueuePolicy(p);
+ }
+}
+
+QueuePolicy::PacketQueue::iterator
+LrgQueuePolicy::selectPacket(PacketQueue* q)
+{
+ QueuePolicy::PacketQueue::iterator ret = q->end();
+
+ // Tracks one packet per master in the queue
+ std::unordered_map<MasterID, QueuePolicy::PacketQueue::iterator> track;
+
+ // Cycle queue only once
+ for (auto pkt_it = q->begin(); pkt_it != q->end(); ++pkt_it) {
+
+ const auto& pkt = *pkt_it;
+
+ panic_if(!pkt->req,
+ "QoSQPolicy::lrg detected packet without request");
+
+ // Get Request MasterID
+ MasterID m_id = pkt->req->masterId();
+ DPRINTF(QOS, "QoSQPolicy::lrg checking packet "
+ "from queue with id %d\n", m_id);
+
+ // Check if this is a known master.
+ panic_if(memCtrl->hasMaster(m_id),
+ "%s: Unrecognized Master\n", __func__);
+
+ panic_if(toServe.size() > 0,
+ "%s: toServe list is empty\n", __func__);
+
+ if (toServe.front() == m_id) {
+ DPRINTF(QOS, "QoSQPolicy::lrg matched to served "
+ "master id %d\n", m_id);
+ // This packet matches the MasterID to be served next
+ // move toServe front to back
+ toServe.push_back(m_id);
+ toServe.pop_front();
+
+ return pkt_it;
+ }
+
+ // The master generating the packet is not first in the toServe list
+ // (Doesn't have the highest priority among masters)
+ // Check if this is the first packet seen with its master ID
+ // and remember it. Then keep looping over the remaining packets
+ // in the queue.
+ if (track.find(m_id) == track.end()) {
+ track[m_id] = pkt_it;
+ DPRINTF(QOS, "QoSQPolicy::lrg tracking a packet for "
+ "master id %d\n", m_id);
+ }
+ }
+
+ // If here, the current master to be serviced doesn't have a pending
+ // packet in the queue: look for the next master in the list.
+ for (const auto& masterId : toServe) {
+ DPRINTF(QOS, "QoSQPolicy::lrg evaluating alternative "
+ "master id %d\n", masterId);
+
+ if (track.find(masterId) != track.end()) {
+ ret = track[masterId];
+ DPRINTF(QOS, "QoSQPolicy::lrg master id "
+ "%d selected for service\n", masterId);
+
+ return ret;
+ }
+ }
+
+ DPRINTF(QOS, "QoSQPolicy::lrg no packet was serviced\n");
+
+ // Ret will be : packet to serve if any found or queue begin
+ // (end if queue is empty)
+ return ret;
+}
+
+void
+LrgQueuePolicy::enqueuePacket(PacketPtr pkt)
+{
+ MasterID m_id = pkt->masterId();
+ if (!memCtrl->hasMaster(m_id)) {
+ toServe.push_back(m_id);
+ }
+};
+
+} // namespace QoS