112967Smatteo.andreozzi@arm.com/*
212967Smatteo.andreozzi@arm.com * Copyright (c) 2018 ARM Limited
312967Smatteo.andreozzi@arm.com * All rights reserved
412967Smatteo.andreozzi@arm.com *
512967Smatteo.andreozzi@arm.com * The license below extends only to copyright in the software and shall
612967Smatteo.andreozzi@arm.com * not be construed as granting a license to any other intellectual
712967Smatteo.andreozzi@arm.com * property including but not limited to intellectual property relating
812967Smatteo.andreozzi@arm.com * to a hardware implementation of the functionality of the software
912967Smatteo.andreozzi@arm.com * licensed hereunder.  You may use the software subject to the license
1012967Smatteo.andreozzi@arm.com * terms below provided that you ensure that this notice is replicated
1112967Smatteo.andreozzi@arm.com * unmodified and in its entirety in all distributions of the software,
1212967Smatteo.andreozzi@arm.com * modified or unmodified, in source code or in binary form.
1312967Smatteo.andreozzi@arm.com *
1412967Smatteo.andreozzi@arm.com * Redistribution and use in source and binary forms, with or without
1512967Smatteo.andreozzi@arm.com * modification, are permitted provided that the following conditions are
1612967Smatteo.andreozzi@arm.com * met: redistributions of source code must retain the above copyright
1712967Smatteo.andreozzi@arm.com * notice, this list of conditions and the following disclaimer;
1812967Smatteo.andreozzi@arm.com * redistributions in binary form must reproduce the above copyright
1912967Smatteo.andreozzi@arm.com * notice, this list of conditions and the following disclaimer in the
2012967Smatteo.andreozzi@arm.com * documentation and/or other materials provided with the distribution;
2112967Smatteo.andreozzi@arm.com * neither the name of the copyright holders nor the names of its
2212967Smatteo.andreozzi@arm.com * contributors may be used to endorse or promote products derived from
2312967Smatteo.andreozzi@arm.com * this software without specific prior written permission.
2412967Smatteo.andreozzi@arm.com *
2512967Smatteo.andreozzi@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2612967Smatteo.andreozzi@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2712967Smatteo.andreozzi@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2812967Smatteo.andreozzi@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2912967Smatteo.andreozzi@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3012967Smatteo.andreozzi@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3112967Smatteo.andreozzi@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3212967Smatteo.andreozzi@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3312967Smatteo.andreozzi@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3412967Smatteo.andreozzi@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3512967Smatteo.andreozzi@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3612967Smatteo.andreozzi@arm.com *
3712967Smatteo.andreozzi@arm.com * Author: Matteo Andreozzi
3812967Smatteo.andreozzi@arm.com */
3912967Smatteo.andreozzi@arm.com
4012967Smatteo.andreozzi@arm.com#include "debug/Drain.hh"
4112967Smatteo.andreozzi@arm.com#include "debug/QOS.hh"
4212967Smatteo.andreozzi@arm.com#include "mem_sink.hh"
4312967Smatteo.andreozzi@arm.com#include "sim/system.hh"
4412967Smatteo.andreozzi@arm.com
4512967Smatteo.andreozzi@arm.comnamespace QoS {
4612967Smatteo.andreozzi@arm.com
4712967Smatteo.andreozzi@arm.comMemSinkCtrl::MemSinkCtrl(const QoSMemSinkCtrlParams* p)
4812967Smatteo.andreozzi@arm.com  : MemCtrl(p), requestLatency(p->request_latency),
4912967Smatteo.andreozzi@arm.com    responseLatency(p->response_latency),
5012967Smatteo.andreozzi@arm.com    memoryPacketSize(p->memory_packet_size),
5112967Smatteo.andreozzi@arm.com    readBufferSize(p->read_buffer_size),
5212967Smatteo.andreozzi@arm.com    writeBufferSize(p->write_buffer_size), port(name() + ".port", *this),
5312967Smatteo.andreozzi@arm.com    retryRdReq(false), retryWrReq(false), nextRequest(0), nextReqEvent(this)
5412967Smatteo.andreozzi@arm.com{
5512967Smatteo.andreozzi@arm.com    // Resize read and write queue to allocate space
5612967Smatteo.andreozzi@arm.com    // for configured QoS priorities
5712967Smatteo.andreozzi@arm.com    readQueue.resize(numPriorities());
5812967Smatteo.andreozzi@arm.com    writeQueue.resize(numPriorities());
5912967Smatteo.andreozzi@arm.com}
6012967Smatteo.andreozzi@arm.com
6112967Smatteo.andreozzi@arm.comMemSinkCtrl::~MemSinkCtrl()
6212967Smatteo.andreozzi@arm.com{}
6312967Smatteo.andreozzi@arm.com
6412967Smatteo.andreozzi@arm.comvoid
6512967Smatteo.andreozzi@arm.comMemSinkCtrl::init()
6612967Smatteo.andreozzi@arm.com{
6712967Smatteo.andreozzi@arm.com    MemCtrl::init();
6812967Smatteo.andreozzi@arm.com
6912967Smatteo.andreozzi@arm.com    // Allow unconnected memories as this is used in several ruby
7012967Smatteo.andreozzi@arm.com    // systems at the moment
7112967Smatteo.andreozzi@arm.com    if (port.isConnected()) {
7212967Smatteo.andreozzi@arm.com        port.sendRangeChange();
7312967Smatteo.andreozzi@arm.com    }
7412967Smatteo.andreozzi@arm.com}
7512967Smatteo.andreozzi@arm.com
7612967Smatteo.andreozzi@arm.combool
7712967Smatteo.andreozzi@arm.comMemSinkCtrl::readQueueFull(const uint64_t packets) const
7812967Smatteo.andreozzi@arm.com{
7912967Smatteo.andreozzi@arm.com    return (totalReadQueueSize + packets > readBufferSize);
8012967Smatteo.andreozzi@arm.com}
8112967Smatteo.andreozzi@arm.com
8212967Smatteo.andreozzi@arm.combool
8312967Smatteo.andreozzi@arm.comMemSinkCtrl::writeQueueFull(const uint64_t packets) const
8412967Smatteo.andreozzi@arm.com{
8512967Smatteo.andreozzi@arm.com    return (totalWriteQueueSize + packets > writeBufferSize);
8612967Smatteo.andreozzi@arm.com}
8712967Smatteo.andreozzi@arm.com
8812967Smatteo.andreozzi@arm.comTick
8912967Smatteo.andreozzi@arm.comMemSinkCtrl::recvAtomic(PacketPtr pkt)
9012967Smatteo.andreozzi@arm.com{
9112967Smatteo.andreozzi@arm.com    panic_if(pkt->cacheResponding(),
9212967Smatteo.andreozzi@arm.com             "%s Should not see packets where cache is responding\n",
9312967Smatteo.andreozzi@arm.com             __func__);
9412967Smatteo.andreozzi@arm.com
9512967Smatteo.andreozzi@arm.com    access(pkt);
9612967Smatteo.andreozzi@arm.com    return responseLatency;
9712967Smatteo.andreozzi@arm.com}
9812967Smatteo.andreozzi@arm.com
9912967Smatteo.andreozzi@arm.comvoid
10012967Smatteo.andreozzi@arm.comMemSinkCtrl::recvFunctional(PacketPtr pkt)
10112967Smatteo.andreozzi@arm.com{
10212967Smatteo.andreozzi@arm.com    pkt->pushLabel(name());
10312967Smatteo.andreozzi@arm.com
10412967Smatteo.andreozzi@arm.com    functionalAccess(pkt);
10512967Smatteo.andreozzi@arm.com
10612967Smatteo.andreozzi@arm.com    pkt->popLabel();
10712967Smatteo.andreozzi@arm.com}
10812967Smatteo.andreozzi@arm.com
10913784Sgabeblack@google.comPort &
11013784Sgabeblack@google.comMemSinkCtrl::getPort(const std::string &interface, PortID idx)
11112967Smatteo.andreozzi@arm.com{
11212967Smatteo.andreozzi@arm.com    if (interface != "port") {
11313892Sgabeblack@google.com        return MemCtrl::getPort(interface, idx);
11412967Smatteo.andreozzi@arm.com    } else {
11512967Smatteo.andreozzi@arm.com        return port;
11612967Smatteo.andreozzi@arm.com    }
11712967Smatteo.andreozzi@arm.com}
11812967Smatteo.andreozzi@arm.com
11912967Smatteo.andreozzi@arm.combool
12012967Smatteo.andreozzi@arm.comMemSinkCtrl::recvTimingReq(PacketPtr pkt)
12112967Smatteo.andreozzi@arm.com{
12212967Smatteo.andreozzi@arm.com    // Request accepted
12312967Smatteo.andreozzi@arm.com    bool req_accepted = true;
12412967Smatteo.andreozzi@arm.com
12512967Smatteo.andreozzi@arm.com    panic_if(!(pkt->isRead() || pkt->isWrite()),
12612967Smatteo.andreozzi@arm.com             "%s. Should only see "
12712967Smatteo.andreozzi@arm.com             "read and writes at memory controller\n",
12812967Smatteo.andreozzi@arm.com             __func__);
12912967Smatteo.andreozzi@arm.com
13012967Smatteo.andreozzi@arm.com    panic_if(pkt->cacheResponding(),
13112967Smatteo.andreozzi@arm.com             "%s. Should not see packets where cache is responding\n",
13212967Smatteo.andreozzi@arm.com             __func__);
13312967Smatteo.andreozzi@arm.com
13412967Smatteo.andreozzi@arm.com    DPRINTF(QOS,
13512967Smatteo.andreozzi@arm.com            "%s: MASTER %s request %s addr %lld size %d\n",
13612967Smatteo.andreozzi@arm.com            __func__,
13712967Smatteo.andreozzi@arm.com            _system->getMasterName(pkt->req->masterId()),
13812967Smatteo.andreozzi@arm.com            pkt->cmdString(), pkt->getAddr(), pkt->getSize());
13912967Smatteo.andreozzi@arm.com
14012967Smatteo.andreozzi@arm.com    uint64_t required_entries = divCeil(pkt->getSize(), memoryPacketSize);
14112967Smatteo.andreozzi@arm.com
14212967Smatteo.andreozzi@arm.com    assert(required_entries);
14312967Smatteo.andreozzi@arm.com
14412967Smatteo.andreozzi@arm.com    // Schedule packet
14512967Smatteo.andreozzi@arm.com    uint8_t pkt_priority = qosSchedule({&readQueue, &writeQueue},
14612967Smatteo.andreozzi@arm.com                                       memoryPacketSize, pkt);
14712967Smatteo.andreozzi@arm.com
14812967Smatteo.andreozzi@arm.com    if (pkt->isRead()) {
14912967Smatteo.andreozzi@arm.com        if (readQueueFull(required_entries)) {
15012967Smatteo.andreozzi@arm.com            DPRINTF(QOS,
15112967Smatteo.andreozzi@arm.com                    "%s Read queue full, not accepting\n", __func__);
15212967Smatteo.andreozzi@arm.com            // Remember that we have to retry this port
15312967Smatteo.andreozzi@arm.com            retryRdReq = true;
15412967Smatteo.andreozzi@arm.com            numReadRetries++;
15512967Smatteo.andreozzi@arm.com            req_accepted = false;
15612967Smatteo.andreozzi@arm.com        } else {
15712967Smatteo.andreozzi@arm.com            // Enqueue the incoming packet into corresponding
15812967Smatteo.andreozzi@arm.com            // QoS priority queue
15912967Smatteo.andreozzi@arm.com            readQueue.at(pkt_priority).push_back(pkt);
16012967Smatteo.andreozzi@arm.com            queuePolicy->enqueuePacket(pkt);
16112967Smatteo.andreozzi@arm.com        }
16212967Smatteo.andreozzi@arm.com    } else {
16312967Smatteo.andreozzi@arm.com        if (writeQueueFull(required_entries)) {
16412967Smatteo.andreozzi@arm.com            DPRINTF(QOS,
16512967Smatteo.andreozzi@arm.com                    "%s Write queue full, not accepting\n", __func__);
16612967Smatteo.andreozzi@arm.com            // Remember that we have to retry this port
16712967Smatteo.andreozzi@arm.com            retryWrReq = true;
16812967Smatteo.andreozzi@arm.com            numWriteRetries++;
16912967Smatteo.andreozzi@arm.com            req_accepted = false;
17012967Smatteo.andreozzi@arm.com        } else {
17112967Smatteo.andreozzi@arm.com            // Enqueue the incoming packet into corresponding QoS
17212967Smatteo.andreozzi@arm.com            // priority queue
17312967Smatteo.andreozzi@arm.com            writeQueue.at(pkt_priority).push_back(pkt);
17412967Smatteo.andreozzi@arm.com            queuePolicy->enqueuePacket(pkt);
17512967Smatteo.andreozzi@arm.com        }
17612967Smatteo.andreozzi@arm.com    }
17712967Smatteo.andreozzi@arm.com
17812967Smatteo.andreozzi@arm.com    if (req_accepted) {
17912967Smatteo.andreozzi@arm.com        // The packet is accepted - log it
18012967Smatteo.andreozzi@arm.com        logRequest(pkt->isRead()? READ : WRITE,
18112967Smatteo.andreozzi@arm.com                   pkt->req->masterId(),
18212967Smatteo.andreozzi@arm.com                   pkt->qosValue(),
18312967Smatteo.andreozzi@arm.com                   pkt->getAddr(),
18412967Smatteo.andreozzi@arm.com                   required_entries);
18512967Smatteo.andreozzi@arm.com    }
18612967Smatteo.andreozzi@arm.com
18712967Smatteo.andreozzi@arm.com    // Check if we have to process next request event
18812967Smatteo.andreozzi@arm.com    if (!nextReqEvent.scheduled()) {
18912967Smatteo.andreozzi@arm.com        DPRINTF(QOS,
19012967Smatteo.andreozzi@arm.com                "%s scheduling next request at "
19112967Smatteo.andreozzi@arm.com                "time %d (next is %d)\n", __func__,
19212967Smatteo.andreozzi@arm.com                std::max(curTick(), nextRequest), nextRequest);
19312967Smatteo.andreozzi@arm.com        schedule(nextReqEvent, std::max(curTick(), nextRequest));
19412967Smatteo.andreozzi@arm.com    }
19512967Smatteo.andreozzi@arm.com    return req_accepted;
19612967Smatteo.andreozzi@arm.com}
19712967Smatteo.andreozzi@arm.com
19812967Smatteo.andreozzi@arm.comvoid
19912967Smatteo.andreozzi@arm.comMemSinkCtrl::processNextReqEvent()
20012967Smatteo.andreozzi@arm.com{
20112967Smatteo.andreozzi@arm.com    PacketPtr pkt = nullptr;
20212967Smatteo.andreozzi@arm.com
20312967Smatteo.andreozzi@arm.com    // Evaluate bus direction
20412967Smatteo.andreozzi@arm.com    busStateNext = selectNextBusState();
20512967Smatteo.andreozzi@arm.com
20612967Smatteo.andreozzi@arm.com    // Record turnaround stats and update current state direction
20712967Smatteo.andreozzi@arm.com    recordTurnaroundStats();
20812967Smatteo.andreozzi@arm.com
20912967Smatteo.andreozzi@arm.com    // Set current bus state
21012967Smatteo.andreozzi@arm.com    setCurrentBusState();
21112967Smatteo.andreozzi@arm.com
21212967Smatteo.andreozzi@arm.com    // Access current direction buffer
21312967Smatteo.andreozzi@arm.com    std::vector<PacketQueue>* queue_ptr = (busState == READ ? &readQueue :
21412967Smatteo.andreozzi@arm.com                                                              &writeQueue);
21512967Smatteo.andreozzi@arm.com
21612967Smatteo.andreozzi@arm.com    DPRINTF(QOS,
21712967Smatteo.andreozzi@arm.com            "%s DUMPING %s queues status\n", __func__,
21812967Smatteo.andreozzi@arm.com            (busState == WRITE ? "WRITE" : "READ"));
21912967Smatteo.andreozzi@arm.com
22012967Smatteo.andreozzi@arm.com    if (DTRACE(QOS)) {
22112967Smatteo.andreozzi@arm.com        for (uint8_t i = 0; i < numPriorities(); ++i) {
22212967Smatteo.andreozzi@arm.com            std::string plist = "";
22312967Smatteo.andreozzi@arm.com            for (auto& e : (busState == WRITE ? writeQueue[i]: readQueue[i])) {
22412967Smatteo.andreozzi@arm.com                plist += (std::to_string(e->req->masterId())) + " ";
22512967Smatteo.andreozzi@arm.com            }
22612967Smatteo.andreozzi@arm.com            DPRINTF(QOS,
22712967Smatteo.andreozzi@arm.com                    "%s priority Queue [%i] contains %i elements, "
22812967Smatteo.andreozzi@arm.com                    "packets are: [%s]\n", __func__, i,
22912967Smatteo.andreozzi@arm.com                    busState == WRITE ? writeQueueSizes[i] :
23012967Smatteo.andreozzi@arm.com                                        readQueueSizes[i],
23112967Smatteo.andreozzi@arm.com                    plist);
23212967Smatteo.andreozzi@arm.com        }
23312967Smatteo.andreozzi@arm.com    }
23412967Smatteo.andreozzi@arm.com
23512967Smatteo.andreozzi@arm.com    uint8_t curr_prio = numPriorities();
23612967Smatteo.andreozzi@arm.com
23712967Smatteo.andreozzi@arm.com    for (auto queue = (*queue_ptr).rbegin();
23812967Smatteo.andreozzi@arm.com         queue != (*queue_ptr).rend(); ++queue) {
23912967Smatteo.andreozzi@arm.com
24012967Smatteo.andreozzi@arm.com        curr_prio--;
24112967Smatteo.andreozzi@arm.com
24212967Smatteo.andreozzi@arm.com        DPRINTF(QOS,
24312967Smatteo.andreozzi@arm.com                "%s checking %s queue [%d] priority [%d packets]\n",
24412967Smatteo.andreozzi@arm.com                __func__, (busState == READ? "READ" : "WRITE"),
24512967Smatteo.andreozzi@arm.com                curr_prio, queue->size());
24612967Smatteo.andreozzi@arm.com
24712967Smatteo.andreozzi@arm.com        if (!queue->empty()) {
24812967Smatteo.andreozzi@arm.com            // Call the queue policy to select packet from priority queue
24912967Smatteo.andreozzi@arm.com            auto p_it = queuePolicy->selectPacket(&(*queue));
25012967Smatteo.andreozzi@arm.com            pkt = *p_it;
25112967Smatteo.andreozzi@arm.com            queue->erase(p_it);
25212967Smatteo.andreozzi@arm.com
25312967Smatteo.andreozzi@arm.com            DPRINTF(QOS,
25412967Smatteo.andreozzi@arm.com                    "%s scheduling packet address %d for master %s from "
25512967Smatteo.andreozzi@arm.com                    "priority queue %d\n", __func__, pkt->getAddr(),
25612967Smatteo.andreozzi@arm.com                    _system->getMasterName(pkt->req->masterId()),
25712967Smatteo.andreozzi@arm.com                    curr_prio);
25812967Smatteo.andreozzi@arm.com            break;
25912967Smatteo.andreozzi@arm.com        }
26012967Smatteo.andreozzi@arm.com    }
26112967Smatteo.andreozzi@arm.com
26212967Smatteo.andreozzi@arm.com    assert(pkt);
26312967Smatteo.andreozzi@arm.com
26412967Smatteo.andreozzi@arm.com    // Setup next request service time - do it here as retry request
26512967Smatteo.andreozzi@arm.com    // hands over control to the port
26612967Smatteo.andreozzi@arm.com    nextRequest = curTick() + requestLatency;
26712967Smatteo.andreozzi@arm.com
26812967Smatteo.andreozzi@arm.com    uint64_t removed_entries = divCeil(pkt->getSize(), memoryPacketSize);
26912967Smatteo.andreozzi@arm.com
27012967Smatteo.andreozzi@arm.com    DPRINTF(QOS,
27112967Smatteo.andreozzi@arm.com            "%s scheduled packet address %d for master %s size is %d, "
27212967Smatteo.andreozzi@arm.com            "corresponds to %d memory packets\n", __func__, pkt->getAddr(),
27312967Smatteo.andreozzi@arm.com            _system->getMasterName(pkt->req->masterId()),
27412967Smatteo.andreozzi@arm.com            pkt->getSize(), removed_entries);
27512967Smatteo.andreozzi@arm.com
27612967Smatteo.andreozzi@arm.com    // Schedule response
27712967Smatteo.andreozzi@arm.com    panic_if(!pkt->needsResponse(),
27812967Smatteo.andreozzi@arm.com        "%s response not required\n", __func__);
27912967Smatteo.andreozzi@arm.com
28012967Smatteo.andreozzi@arm.com    // Do the actual memory access which also turns the packet
28112967Smatteo.andreozzi@arm.com    // into a response
28212967Smatteo.andreozzi@arm.com    access(pkt);
28312967Smatteo.andreozzi@arm.com
28412967Smatteo.andreozzi@arm.com    // Log the response
28512967Smatteo.andreozzi@arm.com    logResponse(pkt->isRead()? READ : WRITE,
28612967Smatteo.andreozzi@arm.com                pkt->req->masterId(),
28712967Smatteo.andreozzi@arm.com                pkt->qosValue(),
28812967Smatteo.andreozzi@arm.com                pkt->getAddr(),
28912967Smatteo.andreozzi@arm.com                removed_entries, responseLatency);
29012967Smatteo.andreozzi@arm.com
29112967Smatteo.andreozzi@arm.com    // Schedule the response
29213564Snikos.nikoleris@arm.com    port.schedTimingResp(pkt, curTick() + responseLatency);
29312967Smatteo.andreozzi@arm.com    DPRINTF(QOS,
29412967Smatteo.andreozzi@arm.com            "%s response scheduled at time %d\n",
29512967Smatteo.andreozzi@arm.com            __func__, curTick() + responseLatency);
29612967Smatteo.andreozzi@arm.com
29712967Smatteo.andreozzi@arm.com    // Finally - handle retry requests - this handles control
29812967Smatteo.andreozzi@arm.com    // to the port, so do it last
29912967Smatteo.andreozzi@arm.com    if (busState == READ && retryRdReq) {
30012967Smatteo.andreozzi@arm.com        retryRdReq = false;
30112967Smatteo.andreozzi@arm.com        port.sendRetryReq();
30212967Smatteo.andreozzi@arm.com    } else if (busState == WRITE && retryWrReq) {
30312967Smatteo.andreozzi@arm.com        retryWrReq = false;
30412967Smatteo.andreozzi@arm.com        port.sendRetryReq();
30512967Smatteo.andreozzi@arm.com    }
30612967Smatteo.andreozzi@arm.com
30712967Smatteo.andreozzi@arm.com    // Check if we have to schedule another request event
30812967Smatteo.andreozzi@arm.com    if ((totalReadQueueSize || totalWriteQueueSize) &&
30912967Smatteo.andreozzi@arm.com        !nextReqEvent.scheduled()) {
31012967Smatteo.andreozzi@arm.com
31112967Smatteo.andreozzi@arm.com        schedule(nextReqEvent, curTick() + requestLatency);
31212967Smatteo.andreozzi@arm.com        DPRINTF(QOS,
31312967Smatteo.andreozzi@arm.com                "%s scheduling next request event at tick %d\n",
31412967Smatteo.andreozzi@arm.com                __func__, curTick() + requestLatency);
31512967Smatteo.andreozzi@arm.com    }
31612967Smatteo.andreozzi@arm.com}
31712967Smatteo.andreozzi@arm.com
31812967Smatteo.andreozzi@arm.comDrainState
31912967Smatteo.andreozzi@arm.comMemSinkCtrl::drain()
32012967Smatteo.andreozzi@arm.com{
32112967Smatteo.andreozzi@arm.com    if (totalReadQueueSize || totalWriteQueueSize) {
32212967Smatteo.andreozzi@arm.com        DPRINTF(Drain,
32312967Smatteo.andreozzi@arm.com                "%s queues have requests, waiting to drain\n",
32412967Smatteo.andreozzi@arm.com                __func__);
32512967Smatteo.andreozzi@arm.com        return DrainState::Draining;
32612967Smatteo.andreozzi@arm.com    } else {
32712967Smatteo.andreozzi@arm.com        return DrainState::Drained;
32812967Smatteo.andreozzi@arm.com    }
32912967Smatteo.andreozzi@arm.com}
33012967Smatteo.andreozzi@arm.com
33112967Smatteo.andreozzi@arm.comvoid
33212967Smatteo.andreozzi@arm.comMemSinkCtrl::regStats()
33312967Smatteo.andreozzi@arm.com{
33412967Smatteo.andreozzi@arm.com    MemCtrl::regStats();
33512967Smatteo.andreozzi@arm.com
33612967Smatteo.andreozzi@arm.com    // Initialize all the stats
33712967Smatteo.andreozzi@arm.com    using namespace Stats;
33812967Smatteo.andreozzi@arm.com
33912967Smatteo.andreozzi@arm.com    numReadRetries.name(name() + ".numReadRetries")
34012967Smatteo.andreozzi@arm.com        .desc("Number of read retries");
34112967Smatteo.andreozzi@arm.com    numWriteRetries.name(name() + ".numWriteRetries")
34212967Smatteo.andreozzi@arm.com        .desc("Number of write retries");
34312967Smatteo.andreozzi@arm.com}
34412967Smatteo.andreozzi@arm.com
34512967Smatteo.andreozzi@arm.comMemSinkCtrl::MemoryPort::MemoryPort(const std::string& n,
34612967Smatteo.andreozzi@arm.com                                    MemSinkCtrl& m)
34713564Snikos.nikoleris@arm.com  : QueuedSlavePort(n, &m, queue, true), memory(m), queue(memory, *this, true)
34812967Smatteo.andreozzi@arm.com{}
34912967Smatteo.andreozzi@arm.com
35012967Smatteo.andreozzi@arm.comAddrRangeList
35112967Smatteo.andreozzi@arm.comMemSinkCtrl::MemoryPort::getAddrRanges() const
35212967Smatteo.andreozzi@arm.com{
35312967Smatteo.andreozzi@arm.com    AddrRangeList ranges;
35412967Smatteo.andreozzi@arm.com    ranges.push_back(memory.getAddrRange());
35512967Smatteo.andreozzi@arm.com    return ranges;
35612967Smatteo.andreozzi@arm.com}
35712967Smatteo.andreozzi@arm.com
35812967Smatteo.andreozzi@arm.comTick
35912967Smatteo.andreozzi@arm.comMemSinkCtrl::MemoryPort::recvAtomic(PacketPtr pkt)
36012967Smatteo.andreozzi@arm.com{
36112967Smatteo.andreozzi@arm.com    return memory.recvAtomic(pkt);
36212967Smatteo.andreozzi@arm.com}
36312967Smatteo.andreozzi@arm.com
36412967Smatteo.andreozzi@arm.comvoid
36512967Smatteo.andreozzi@arm.comMemSinkCtrl::MemoryPort::recvFunctional(PacketPtr pkt)
36612967Smatteo.andreozzi@arm.com{
36712967Smatteo.andreozzi@arm.com    pkt->pushLabel(memory.name());
36812967Smatteo.andreozzi@arm.com
36912967Smatteo.andreozzi@arm.com    if (!queue.trySatisfyFunctional(pkt)) {
37012967Smatteo.andreozzi@arm.com        // Default implementation of SimpleTimingPort::recvFunctional()
37112967Smatteo.andreozzi@arm.com        // calls recvAtomic() and throws away the latency; we can save a
37212967Smatteo.andreozzi@arm.com        // little here by just not calculating the latency.
37312967Smatteo.andreozzi@arm.com        memory.recvFunctional(pkt);
37412967Smatteo.andreozzi@arm.com    }
37512967Smatteo.andreozzi@arm.com
37612967Smatteo.andreozzi@arm.com    pkt->popLabel();
37712967Smatteo.andreozzi@arm.com}
37812967Smatteo.andreozzi@arm.com
37912967Smatteo.andreozzi@arm.combool
38012967Smatteo.andreozzi@arm.comMemSinkCtrl::MemoryPort::recvTimingReq(PacketPtr pkt)
38112967Smatteo.andreozzi@arm.com{
38212967Smatteo.andreozzi@arm.com    return memory.recvTimingReq(pkt);
38312967Smatteo.andreozzi@arm.com}
38412967Smatteo.andreozzi@arm.com
38512967Smatteo.andreozzi@arm.com} // namespace QoS
38612967Smatteo.andreozzi@arm.com
38712967Smatteo.andreozzi@arm.comQoS::MemSinkCtrl*
38812967Smatteo.andreozzi@arm.comQoSMemSinkCtrlParams::create()
38912967Smatteo.andreozzi@arm.com{
39012967Smatteo.andreozzi@arm.com    return new QoS::MemSinkCtrl(this);
39112967Smatteo.andreozzi@arm.com}
39212967Smatteo.andreozzi@arm.com
393