/* * 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 #include #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 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