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