112966SMatteo.Andreozzi@arm.com/* 212966SMatteo.Andreozzi@arm.com * Copyright (c) 2018 ARM Limited 312966SMatteo.Andreozzi@arm.com * All rights reserved 412966SMatteo.Andreozzi@arm.com * 512966SMatteo.Andreozzi@arm.com * The license below extends only to copyright in the software and shall 612966SMatteo.Andreozzi@arm.com * not be construed as granting a license to any other intellectual 712966SMatteo.Andreozzi@arm.com * property including but not limited to intellectual property relating 812966SMatteo.Andreozzi@arm.com * to a hardware implementation of the functionality of the software 912966SMatteo.Andreozzi@arm.com * licensed hereunder. You may use the software subject to the license 1012966SMatteo.Andreozzi@arm.com * terms below provided that you ensure that this notice is replicated 1112966SMatteo.Andreozzi@arm.com * unmodified and in its entirety in all distributions of the software, 1212966SMatteo.Andreozzi@arm.com * modified or unmodified, in source code or in binary form. 1312966SMatteo.Andreozzi@arm.com * 1412966SMatteo.Andreozzi@arm.com * Redistribution and use in source and binary forms, with or without 1512966SMatteo.Andreozzi@arm.com * modification, are permitted provided that the following conditions are 1612966SMatteo.Andreozzi@arm.com * met: redistributions of source code must retain the above copyright 1712966SMatteo.Andreozzi@arm.com * notice, this list of conditions and the following disclaimer; 1812966SMatteo.Andreozzi@arm.com * redistributions in binary form must reproduce the above copyright 1912966SMatteo.Andreozzi@arm.com * notice, this list of conditions and the following disclaimer in the 2012966SMatteo.Andreozzi@arm.com * documentation and/or other materials provided with the distribution; 2112966SMatteo.Andreozzi@arm.com * neither the name of the copyright holders nor the names of its 2212966SMatteo.Andreozzi@arm.com * contributors may be used to endorse or promote products derived from 2312966SMatteo.Andreozzi@arm.com * this software without specific prior written permission. 2412966SMatteo.Andreozzi@arm.com * 2512966SMatteo.Andreozzi@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2612966SMatteo.Andreozzi@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2712966SMatteo.Andreozzi@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2812966SMatteo.Andreozzi@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2912966SMatteo.Andreozzi@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 3012966SMatteo.Andreozzi@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 3112966SMatteo.Andreozzi@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3212966SMatteo.Andreozzi@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3312966SMatteo.Andreozzi@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3412966SMatteo.Andreozzi@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3512966SMatteo.Andreozzi@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3612966SMatteo.Andreozzi@arm.com * 3712966SMatteo.Andreozzi@arm.com * Author: Matteo Andreozzi 3812966SMatteo.Andreozzi@arm.com */ 3912966SMatteo.Andreozzi@arm.com 4012966SMatteo.Andreozzi@arm.com#include "mem/qos/q_policy.hh" 4112966SMatteo.Andreozzi@arm.com 4212966SMatteo.Andreozzi@arm.com#include <unordered_map> 4312966SMatteo.Andreozzi@arm.com#include <utility> 4412966SMatteo.Andreozzi@arm.com 4512966SMatteo.Andreozzi@arm.com#include "debug/QOS.hh" 4612966SMatteo.Andreozzi@arm.com#include "enums/QoSQPolicy.hh" 4712966SMatteo.Andreozzi@arm.com#include "mem/qos/mem_ctrl.hh" 4812966SMatteo.Andreozzi@arm.com 4912966SMatteo.Andreozzi@arm.comnamespace QoS { 5012966SMatteo.Andreozzi@arm.com 5112966SMatteo.Andreozzi@arm.comQueuePolicy* 5212966SMatteo.Andreozzi@arm.comQueuePolicy::create(const QoSMemCtrlParams* p) 5312966SMatteo.Andreozzi@arm.com{ 5412966SMatteo.Andreozzi@arm.com switch (p->qos_q_policy) { 5512966SMatteo.Andreozzi@arm.com case Enums::QoSQPolicy::fifo: 5612966SMatteo.Andreozzi@arm.com return new FifoQueuePolicy(p); 5712966SMatteo.Andreozzi@arm.com case Enums::QoSQPolicy::lrg: 5812966SMatteo.Andreozzi@arm.com return new LrgQueuePolicy(p); 5912966SMatteo.Andreozzi@arm.com case Enums::QoSQPolicy::lifo: 6012966SMatteo.Andreozzi@arm.com default: 6112966SMatteo.Andreozzi@arm.com return new LifoQueuePolicy(p); 6212966SMatteo.Andreozzi@arm.com } 6312966SMatteo.Andreozzi@arm.com} 6412966SMatteo.Andreozzi@arm.com 6512966SMatteo.Andreozzi@arm.comQueuePolicy::PacketQueue::iterator 6612966SMatteo.Andreozzi@arm.comLrgQueuePolicy::selectPacket(PacketQueue* q) 6712966SMatteo.Andreozzi@arm.com{ 6812966SMatteo.Andreozzi@arm.com QueuePolicy::PacketQueue::iterator ret = q->end(); 6912966SMatteo.Andreozzi@arm.com 7012966SMatteo.Andreozzi@arm.com // Tracks one packet per master in the queue 7112966SMatteo.Andreozzi@arm.com std::unordered_map<MasterID, QueuePolicy::PacketQueue::iterator> track; 7212966SMatteo.Andreozzi@arm.com 7312966SMatteo.Andreozzi@arm.com // Cycle queue only once 7412966SMatteo.Andreozzi@arm.com for (auto pkt_it = q->begin(); pkt_it != q->end(); ++pkt_it) { 7512966SMatteo.Andreozzi@arm.com 7612966SMatteo.Andreozzi@arm.com const auto& pkt = *pkt_it; 7712966SMatteo.Andreozzi@arm.com 7812966SMatteo.Andreozzi@arm.com panic_if(!pkt->req, 7912966SMatteo.Andreozzi@arm.com "QoSQPolicy::lrg detected packet without request"); 8012966SMatteo.Andreozzi@arm.com 8112966SMatteo.Andreozzi@arm.com // Get Request MasterID 8212966SMatteo.Andreozzi@arm.com MasterID m_id = pkt->req->masterId(); 8312966SMatteo.Andreozzi@arm.com DPRINTF(QOS, "QoSQPolicy::lrg checking packet " 8412966SMatteo.Andreozzi@arm.com "from queue with id %d\n", m_id); 8512966SMatteo.Andreozzi@arm.com 8612966SMatteo.Andreozzi@arm.com // Check if this is a known master. 8712966SMatteo.Andreozzi@arm.com panic_if(memCtrl->hasMaster(m_id), 8812966SMatteo.Andreozzi@arm.com "%s: Unrecognized Master\n", __func__); 8912966SMatteo.Andreozzi@arm.com 9012966SMatteo.Andreozzi@arm.com panic_if(toServe.size() > 0, 9112966SMatteo.Andreozzi@arm.com "%s: toServe list is empty\n", __func__); 9212966SMatteo.Andreozzi@arm.com 9312966SMatteo.Andreozzi@arm.com if (toServe.front() == m_id) { 9412966SMatteo.Andreozzi@arm.com DPRINTF(QOS, "QoSQPolicy::lrg matched to served " 9512966SMatteo.Andreozzi@arm.com "master id %d\n", m_id); 9612966SMatteo.Andreozzi@arm.com // This packet matches the MasterID to be served next 9712966SMatteo.Andreozzi@arm.com // move toServe front to back 9812966SMatteo.Andreozzi@arm.com toServe.push_back(m_id); 9912966SMatteo.Andreozzi@arm.com toServe.pop_front(); 10012966SMatteo.Andreozzi@arm.com 10112966SMatteo.Andreozzi@arm.com return pkt_it; 10212966SMatteo.Andreozzi@arm.com } 10312966SMatteo.Andreozzi@arm.com 10412966SMatteo.Andreozzi@arm.com // The master generating the packet is not first in the toServe list 10512966SMatteo.Andreozzi@arm.com // (Doesn't have the highest priority among masters) 10612966SMatteo.Andreozzi@arm.com // Check if this is the first packet seen with its master ID 10712966SMatteo.Andreozzi@arm.com // and remember it. Then keep looping over the remaining packets 10812966SMatteo.Andreozzi@arm.com // in the queue. 10912966SMatteo.Andreozzi@arm.com if (track.find(m_id) == track.end()) { 11012966SMatteo.Andreozzi@arm.com track[m_id] = pkt_it; 11112966SMatteo.Andreozzi@arm.com DPRINTF(QOS, "QoSQPolicy::lrg tracking a packet for " 11212966SMatteo.Andreozzi@arm.com "master id %d\n", m_id); 11312966SMatteo.Andreozzi@arm.com } 11412966SMatteo.Andreozzi@arm.com } 11512966SMatteo.Andreozzi@arm.com 11612966SMatteo.Andreozzi@arm.com // If here, the current master to be serviced doesn't have a pending 11712966SMatteo.Andreozzi@arm.com // packet in the queue: look for the next master in the list. 11812966SMatteo.Andreozzi@arm.com for (const auto& masterId : toServe) { 11912966SMatteo.Andreozzi@arm.com DPRINTF(QOS, "QoSQPolicy::lrg evaluating alternative " 12012966SMatteo.Andreozzi@arm.com "master id %d\n", masterId); 12112966SMatteo.Andreozzi@arm.com 12212966SMatteo.Andreozzi@arm.com if (track.find(masterId) != track.end()) { 12312966SMatteo.Andreozzi@arm.com ret = track[masterId]; 12412966SMatteo.Andreozzi@arm.com DPRINTF(QOS, "QoSQPolicy::lrg master id " 12512966SMatteo.Andreozzi@arm.com "%d selected for service\n", masterId); 12612966SMatteo.Andreozzi@arm.com 12712966SMatteo.Andreozzi@arm.com return ret; 12812966SMatteo.Andreozzi@arm.com } 12912966SMatteo.Andreozzi@arm.com } 13012966SMatteo.Andreozzi@arm.com 13112966SMatteo.Andreozzi@arm.com DPRINTF(QOS, "QoSQPolicy::lrg no packet was serviced\n"); 13212966SMatteo.Andreozzi@arm.com 13312966SMatteo.Andreozzi@arm.com // Ret will be : packet to serve if any found or queue begin 13412966SMatteo.Andreozzi@arm.com // (end if queue is empty) 13512966SMatteo.Andreozzi@arm.com return ret; 13612966SMatteo.Andreozzi@arm.com} 13712966SMatteo.Andreozzi@arm.com 13812966SMatteo.Andreozzi@arm.comvoid 13912966SMatteo.Andreozzi@arm.comLrgQueuePolicy::enqueuePacket(PacketPtr pkt) 14012966SMatteo.Andreozzi@arm.com{ 14112966SMatteo.Andreozzi@arm.com MasterID m_id = pkt->masterId(); 14212966SMatteo.Andreozzi@arm.com if (!memCtrl->hasMaster(m_id)) { 14312966SMatteo.Andreozzi@arm.com toServe.push_back(m_id); 14412966SMatteo.Andreozzi@arm.com } 14512966SMatteo.Andreozzi@arm.com}; 14612966SMatteo.Andreozzi@arm.com 14712966SMatteo.Andreozzi@arm.com} // namespace QoS 148