111185Serfan.azarkhish@unibo.it/*
211185Serfan.azarkhish@unibo.it * Copyright (c) 2011-2013 ARM Limited
311185Serfan.azarkhish@unibo.it * All rights reserved
411185Serfan.azarkhish@unibo.it *
511185Serfan.azarkhish@unibo.it * The license below extends only to copyright in the software and shall
611185Serfan.azarkhish@unibo.it * not be construed as granting a license to any other intellectual
711185Serfan.azarkhish@unibo.it * property including but not limited to intellectual property relating
811185Serfan.azarkhish@unibo.it * to a hardware implementation of the functionality of the software
911185Serfan.azarkhish@unibo.it * licensed hereunder.  You may use the software subject to the license
1011185Serfan.azarkhish@unibo.it * terms below provided that you ensure that this notice is replicated
1111185Serfan.azarkhish@unibo.it * unmodified and in its entirety in all distributions of the software,
1211185Serfan.azarkhish@unibo.it * modified or unmodified, in source code or in binary form.
1311185Serfan.azarkhish@unibo.it *
1411185Serfan.azarkhish@unibo.it * Copyright (c) 2006 The Regents of The University of Michigan
1511185Serfan.azarkhish@unibo.it * Copyright (c) 2015 The University of Bologna
1611185Serfan.azarkhish@unibo.it * All rights reserved.
1711185Serfan.azarkhish@unibo.it *
1811185Serfan.azarkhish@unibo.it * Redistribution and use in source and binary forms, with or without
1911185Serfan.azarkhish@unibo.it * modification, are permitted provided that the following conditions are
2011185Serfan.azarkhish@unibo.it * met: redistributions of source code must retain the above copyright
2111185Serfan.azarkhish@unibo.it * notice, this list of conditions and the following disclaimer;
2211185Serfan.azarkhish@unibo.it * redistributions in binary form must reproduce the above copyright
2311185Serfan.azarkhish@unibo.it * notice, this list of conditions and the following disclaimer in the
2411185Serfan.azarkhish@unibo.it * documentation and/or other materials provided with the distribution;
2511185Serfan.azarkhish@unibo.it * neither the name of the copyright holders nor the names of its
2611185Serfan.azarkhish@unibo.it * contributors may be used to endorse or promote products derived from
2711185Serfan.azarkhish@unibo.it * this software without specific prior written permission.
2811185Serfan.azarkhish@unibo.it *
2911185Serfan.azarkhish@unibo.it * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3011185Serfan.azarkhish@unibo.it * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3111185Serfan.azarkhish@unibo.it * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
3211185Serfan.azarkhish@unibo.it * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3311185Serfan.azarkhish@unibo.it * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3411185Serfan.azarkhish@unibo.it * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3511185Serfan.azarkhish@unibo.it * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3611185Serfan.azarkhish@unibo.it * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3711185Serfan.azarkhish@unibo.it * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3811185Serfan.azarkhish@unibo.it * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3911185Serfan.azarkhish@unibo.it * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4011185Serfan.azarkhish@unibo.it *
4111185Serfan.azarkhish@unibo.it * Authors: Ali Saidi
4211185Serfan.azarkhish@unibo.it *          Steve Reinhardt
4311185Serfan.azarkhish@unibo.it *          Andreas Hansson
4411185Serfan.azarkhish@unibo.it *          Erfan Azarkhish
4511185Serfan.azarkhish@unibo.it */
4611185Serfan.azarkhish@unibo.it
4711185Serfan.azarkhish@unibo.it/**
4811185Serfan.azarkhish@unibo.it * @file
4911185Serfan.azarkhish@unibo.it * Implementation of the SerialLink Class, modeling Hybrid-Memory-Cube's
5011185Serfan.azarkhish@unibo.it * serial interface.
5111185Serfan.azarkhish@unibo.it */
5211185Serfan.azarkhish@unibo.it
5311185Serfan.azarkhish@unibo.it#include "mem/serial_link.hh"
5411185Serfan.azarkhish@unibo.it
5511185Serfan.azarkhish@unibo.it#include "base/trace.hh"
5611185Serfan.azarkhish@unibo.it#include "debug/SerialLink.hh"
5711185Serfan.azarkhish@unibo.it#include "params/SerialLink.hh"
5811185Serfan.azarkhish@unibo.it
5911185Serfan.azarkhish@unibo.itSerialLink::SerialLinkSlavePort::SerialLinkSlavePort(const std::string& _name,
6011185Serfan.azarkhish@unibo.it                                         SerialLink& _serial_link,
6111185Serfan.azarkhish@unibo.it                                         SerialLinkMasterPort& _masterPort,
6211185Serfan.azarkhish@unibo.it                                         Cycles _delay, int _resp_limit,
6311185Serfan.azarkhish@unibo.it                                         const std::vector<AddrRange>&
6411185Serfan.azarkhish@unibo.it                                         _ranges)
6511185Serfan.azarkhish@unibo.it    : SlavePort(_name, &_serial_link), serial_link(_serial_link),
6611185Serfan.azarkhish@unibo.it      masterPort(_masterPort), delay(_delay),
6711185Serfan.azarkhish@unibo.it      ranges(_ranges.begin(), _ranges.end()),
6811185Serfan.azarkhish@unibo.it      outstandingResponses(0), retryReq(false),
6912084Sspwilson2@wisc.edu      respQueueLimit(_resp_limit),
7012084Sspwilson2@wisc.edu      sendEvent([this]{ trySendTiming(); }, _name)
7111185Serfan.azarkhish@unibo.it{
7211185Serfan.azarkhish@unibo.it}
7311185Serfan.azarkhish@unibo.it
7411185Serfan.azarkhish@unibo.itSerialLink::SerialLinkMasterPort::SerialLinkMasterPort(const std::string&
7511185Serfan.azarkhish@unibo.it                                           _name, SerialLink& _serial_link,
7611185Serfan.azarkhish@unibo.it                                           SerialLinkSlavePort& _slavePort,
7711185Serfan.azarkhish@unibo.it                                           Cycles _delay, int _req_limit)
7811185Serfan.azarkhish@unibo.it    : MasterPort(_name, &_serial_link), serial_link(_serial_link),
7911185Serfan.azarkhish@unibo.it      slavePort(_slavePort), delay(_delay), reqQueueLimit(_req_limit),
8012084Sspwilson2@wisc.edu      sendEvent([this]{ trySendTiming(); }, _name)
8111185Serfan.azarkhish@unibo.it{
8211185Serfan.azarkhish@unibo.it}
8311185Serfan.azarkhish@unibo.it
8411185Serfan.azarkhish@unibo.itSerialLink::SerialLink(SerialLinkParams *p)
8513892Sgabeblack@google.com    : ClockedObject(p),
8611185Serfan.azarkhish@unibo.it      slavePort(p->name + ".slave", *this, masterPort,
8711185Serfan.azarkhish@unibo.it                ticksToCycles(p->delay), p->resp_size, p->ranges),
8811185Serfan.azarkhish@unibo.it      masterPort(p->name + ".master", *this, slavePort,
8911185Serfan.azarkhish@unibo.it                 ticksToCycles(p->delay), p->req_size),
9011551Sabdul.mutaal@gmail.com      num_lanes(p->num_lanes),
9111551Sabdul.mutaal@gmail.com      link_speed(p->link_speed)
9211551Sabdul.mutaal@gmail.com
9311185Serfan.azarkhish@unibo.it{
9411185Serfan.azarkhish@unibo.it}
9511185Serfan.azarkhish@unibo.it
9613784Sgabeblack@google.comPort&
9713784Sgabeblack@google.comSerialLink::getPort(const std::string &if_name, PortID idx)
9811185Serfan.azarkhish@unibo.it{
9911185Serfan.azarkhish@unibo.it    if (if_name == "master")
10011185Serfan.azarkhish@unibo.it        return masterPort;
10113784Sgabeblack@google.com    else if (if_name == "slave")
10211185Serfan.azarkhish@unibo.it        return slavePort;
10311185Serfan.azarkhish@unibo.it    else
10411185Serfan.azarkhish@unibo.it        // pass it along to our super class
10513892Sgabeblack@google.com        return ClockedObject::getPort(if_name, idx);
10611185Serfan.azarkhish@unibo.it}
10711185Serfan.azarkhish@unibo.it
10811185Serfan.azarkhish@unibo.itvoid
10911185Serfan.azarkhish@unibo.itSerialLink::init()
11011185Serfan.azarkhish@unibo.it{
11111185Serfan.azarkhish@unibo.it    // make sure both sides are connected and have the same block size
11211185Serfan.azarkhish@unibo.it    if (!slavePort.isConnected() || !masterPort.isConnected())
11311185Serfan.azarkhish@unibo.it        fatal("Both ports of a serial_link must be connected.\n");
11411185Serfan.azarkhish@unibo.it
11511185Serfan.azarkhish@unibo.it    // notify the master side  of our address ranges
11611185Serfan.azarkhish@unibo.it    slavePort.sendRangeChange();
11711185Serfan.azarkhish@unibo.it}
11811185Serfan.azarkhish@unibo.it
11911185Serfan.azarkhish@unibo.itbool
12011185Serfan.azarkhish@unibo.itSerialLink::SerialLinkSlavePort::respQueueFull() const
12111185Serfan.azarkhish@unibo.it{
12211185Serfan.azarkhish@unibo.it    return outstandingResponses == respQueueLimit;
12311185Serfan.azarkhish@unibo.it}
12411185Serfan.azarkhish@unibo.it
12511185Serfan.azarkhish@unibo.itbool
12611185Serfan.azarkhish@unibo.itSerialLink::SerialLinkMasterPort::reqQueueFull() const
12711185Serfan.azarkhish@unibo.it{
12811185Serfan.azarkhish@unibo.it    return transmitList.size() == reqQueueLimit;
12911185Serfan.azarkhish@unibo.it}
13011185Serfan.azarkhish@unibo.it
13111185Serfan.azarkhish@unibo.itbool
13211185Serfan.azarkhish@unibo.itSerialLink::SerialLinkMasterPort::recvTimingResp(PacketPtr pkt)
13311185Serfan.azarkhish@unibo.it{
13411185Serfan.azarkhish@unibo.it    // all checks are done when the request is accepted on the slave
13511185Serfan.azarkhish@unibo.it    // side, so we are guaranteed to have space for the response
13611185Serfan.azarkhish@unibo.it    DPRINTF(SerialLink, "recvTimingResp: %s addr 0x%x\n",
13711185Serfan.azarkhish@unibo.it            pkt->cmdString(), pkt->getAddr());
13811185Serfan.azarkhish@unibo.it
13911185Serfan.azarkhish@unibo.it    DPRINTF(SerialLink, "Request queue size: %d\n", transmitList.size());
14011185Serfan.azarkhish@unibo.it
14111185Serfan.azarkhish@unibo.it    // @todo: We need to pay for this and not just zero it out
14211185Serfan.azarkhish@unibo.it    pkt->headerDelay = pkt->payloadDelay = 0;
14311185Serfan.azarkhish@unibo.it
14411185Serfan.azarkhish@unibo.it    // This is similar to what happens for the request packets:
14511185Serfan.azarkhish@unibo.it    // The serializer will start serialization as soon as it receives the
14611185Serfan.azarkhish@unibo.it    // first flit, but the deserializer (at the host side in this case), will
14711185Serfan.azarkhish@unibo.it    // have to wait to receive the whole packet. So we only account for the
14811185Serfan.azarkhish@unibo.it    // deserialization latency.
14911185Serfan.azarkhish@unibo.it    Cycles cycles = delay;
15011551Sabdul.mutaal@gmail.com    cycles += Cycles(divCeil(pkt->getSize() * 8, serial_link.num_lanes
15111551Sabdul.mutaal@gmail.com                * serial_link.link_speed));
15211551Sabdul.mutaal@gmail.com     Tick t = serial_link.clockEdge(cycles);
15311185Serfan.azarkhish@unibo.it
15411185Serfan.azarkhish@unibo.it    //@todo: If the processor sends two uncached requests towards HMC and the
15511185Serfan.azarkhish@unibo.it    // second one is smaller than the first one. It may happen that the second
15611185Serfan.azarkhish@unibo.it    // one crosses this link faster than the first one (because the packet
15711185Serfan.azarkhish@unibo.it    // waits in the link based on its size). This can reorder the received
15811185Serfan.azarkhish@unibo.it    // response.
15911185Serfan.azarkhish@unibo.it    slavePort.schedTimingResp(pkt, t);
16011185Serfan.azarkhish@unibo.it
16111185Serfan.azarkhish@unibo.it    return true;
16211185Serfan.azarkhish@unibo.it}
16311185Serfan.azarkhish@unibo.it
16411185Serfan.azarkhish@unibo.itbool
16511185Serfan.azarkhish@unibo.itSerialLink::SerialLinkSlavePort::recvTimingReq(PacketPtr pkt)
16611185Serfan.azarkhish@unibo.it{
16711185Serfan.azarkhish@unibo.it    DPRINTF(SerialLink, "recvTimingReq: %s addr 0x%x\n",
16811185Serfan.azarkhish@unibo.it            pkt->cmdString(), pkt->getAddr());
16911185Serfan.azarkhish@unibo.it
17011185Serfan.azarkhish@unibo.it    // we should not see a timing request if we are already in a retry
17111185Serfan.azarkhish@unibo.it    assert(!retryReq);
17211185Serfan.azarkhish@unibo.it
17311185Serfan.azarkhish@unibo.it    DPRINTF(SerialLink, "Response queue size: %d outresp: %d\n",
17411185Serfan.azarkhish@unibo.it            transmitList.size(), outstandingResponses);
17511185Serfan.azarkhish@unibo.it
17611185Serfan.azarkhish@unibo.it    // if the request queue is full then there is no hope
17711185Serfan.azarkhish@unibo.it    if (masterPort.reqQueueFull()) {
17811185Serfan.azarkhish@unibo.it        DPRINTF(SerialLink, "Request queue full\n");
17911185Serfan.azarkhish@unibo.it        retryReq = true;
18011185Serfan.azarkhish@unibo.it    } else if ( !retryReq ) {
18111185Serfan.azarkhish@unibo.it        // look at the response queue if we expect to see a response
18211185Serfan.azarkhish@unibo.it        bool expects_response = pkt->needsResponse() &&
18311284Sandreas.hansson@arm.com            !pkt->cacheResponding();
18411185Serfan.azarkhish@unibo.it        if (expects_response) {
18511185Serfan.azarkhish@unibo.it            if (respQueueFull()) {
18611185Serfan.azarkhish@unibo.it                DPRINTF(SerialLink, "Response queue full\n");
18711185Serfan.azarkhish@unibo.it                retryReq = true;
18811185Serfan.azarkhish@unibo.it            } else {
18911185Serfan.azarkhish@unibo.it                // ok to send the request with space for the response
19011185Serfan.azarkhish@unibo.it                DPRINTF(SerialLink, "Reserving space for response\n");
19111185Serfan.azarkhish@unibo.it                assert(outstandingResponses != respQueueLimit);
19211185Serfan.azarkhish@unibo.it                ++outstandingResponses;
19311185Serfan.azarkhish@unibo.it
19411185Serfan.azarkhish@unibo.it                // no need to set retryReq to false as this is already the
19511185Serfan.azarkhish@unibo.it                // case
19611185Serfan.azarkhish@unibo.it            }
19711185Serfan.azarkhish@unibo.it        }
19811185Serfan.azarkhish@unibo.it
19911185Serfan.azarkhish@unibo.it        if (!retryReq) {
20011185Serfan.azarkhish@unibo.it            // @todo: We need to pay for this and not just zero it out
20111185Serfan.azarkhish@unibo.it            pkt->headerDelay = pkt->payloadDelay = 0;
20211185Serfan.azarkhish@unibo.it
20311185Serfan.azarkhish@unibo.it            // We assume that the serializer component at the transmitter side
20411185Serfan.azarkhish@unibo.it            // does not need to receive the whole packet to start the
20511185Serfan.azarkhish@unibo.it            // serialization (this assumption is consistent with the HMC
20611185Serfan.azarkhish@unibo.it            // standard). But the deserializer waits for the complete packet
20711185Serfan.azarkhish@unibo.it            // to check its integrity first. So everytime a packet crosses a
20811185Serfan.azarkhish@unibo.it            // serial link, we should account for its deserialization latency
20911185Serfan.azarkhish@unibo.it            // only.
21011185Serfan.azarkhish@unibo.it            Cycles cycles = delay;
21111185Serfan.azarkhish@unibo.it            cycles += Cycles(divCeil(pkt->getSize() * 8,
21211551Sabdul.mutaal@gmail.com                    serial_link.num_lanes * serial_link.link_speed));
21311185Serfan.azarkhish@unibo.it            Tick t = serial_link.clockEdge(cycles);
21411185Serfan.azarkhish@unibo.it
21511185Serfan.azarkhish@unibo.it            //@todo: If the processor sends two uncached requests towards HMC
21611185Serfan.azarkhish@unibo.it            // and the second one is smaller than the first one. It may happen
21711185Serfan.azarkhish@unibo.it            // that the second one crosses this link faster than the first one
21811185Serfan.azarkhish@unibo.it            // (because the packet waits in the link based on its size).
21911185Serfan.azarkhish@unibo.it            // This can reorder the received response.
22011185Serfan.azarkhish@unibo.it            masterPort.schedTimingReq(pkt, t);
22111185Serfan.azarkhish@unibo.it        }
22211185Serfan.azarkhish@unibo.it    }
22311185Serfan.azarkhish@unibo.it
22411185Serfan.azarkhish@unibo.it    // remember that we are now stalling a packet and that we have to
22511185Serfan.azarkhish@unibo.it    // tell the sending master to retry once space becomes available,
22611185Serfan.azarkhish@unibo.it    // we make no distinction whether the stalling is due to the
22711185Serfan.azarkhish@unibo.it    // request queue or response queue being full
22811185Serfan.azarkhish@unibo.it    return !retryReq;
22911185Serfan.azarkhish@unibo.it}
23011185Serfan.azarkhish@unibo.it
23111185Serfan.azarkhish@unibo.itvoid
23211185Serfan.azarkhish@unibo.itSerialLink::SerialLinkSlavePort::retryStalledReq()
23311185Serfan.azarkhish@unibo.it{
23411185Serfan.azarkhish@unibo.it    if (retryReq) {
23511185Serfan.azarkhish@unibo.it        DPRINTF(SerialLink, "Request waiting for retry, now retrying\n");
23611185Serfan.azarkhish@unibo.it        retryReq = false;
23711185Serfan.azarkhish@unibo.it        sendRetryReq();
23811185Serfan.azarkhish@unibo.it    }
23911185Serfan.azarkhish@unibo.it}
24011185Serfan.azarkhish@unibo.it
24111185Serfan.azarkhish@unibo.itvoid
24211185Serfan.azarkhish@unibo.itSerialLink::SerialLinkMasterPort::schedTimingReq(PacketPtr pkt, Tick when)
24311185Serfan.azarkhish@unibo.it{
24411185Serfan.azarkhish@unibo.it    // If we're about to put this packet at the head of the queue, we
24511185Serfan.azarkhish@unibo.it    // need to schedule an event to do the transmit.  Otherwise there
24611185Serfan.azarkhish@unibo.it    // should already be an event scheduled for sending the head
24711185Serfan.azarkhish@unibo.it    // packet.
24811185Serfan.azarkhish@unibo.it    if (transmitList.empty()) {
24911185Serfan.azarkhish@unibo.it        serial_link.schedule(sendEvent, when);
25011185Serfan.azarkhish@unibo.it    }
25111185Serfan.azarkhish@unibo.it
25211185Serfan.azarkhish@unibo.it    assert(transmitList.size() != reqQueueLimit);
25311185Serfan.azarkhish@unibo.it
25411185Serfan.azarkhish@unibo.it    transmitList.emplace_back(DeferredPacket(pkt, when));
25511185Serfan.azarkhish@unibo.it}
25611185Serfan.azarkhish@unibo.it
25711185Serfan.azarkhish@unibo.it
25811185Serfan.azarkhish@unibo.itvoid
25911185Serfan.azarkhish@unibo.itSerialLink::SerialLinkSlavePort::schedTimingResp(PacketPtr pkt, Tick when)
26011185Serfan.azarkhish@unibo.it{
26111185Serfan.azarkhish@unibo.it    // If we're about to put this packet at the head of the queue, we
26211185Serfan.azarkhish@unibo.it    // need to schedule an event to do the transmit.  Otherwise there
26311185Serfan.azarkhish@unibo.it    // should already be an event scheduled for sending the head
26411185Serfan.azarkhish@unibo.it    // packet.
26511185Serfan.azarkhish@unibo.it    if (transmitList.empty()) {
26611185Serfan.azarkhish@unibo.it        serial_link.schedule(sendEvent, when);
26711185Serfan.azarkhish@unibo.it    }
26811185Serfan.azarkhish@unibo.it
26911185Serfan.azarkhish@unibo.it    transmitList.emplace_back(DeferredPacket(pkt, when));
27011185Serfan.azarkhish@unibo.it}
27111185Serfan.azarkhish@unibo.it
27211185Serfan.azarkhish@unibo.itvoid
27311185Serfan.azarkhish@unibo.itSerialLink::SerialLinkMasterPort::trySendTiming()
27411185Serfan.azarkhish@unibo.it{
27511185Serfan.azarkhish@unibo.it    assert(!transmitList.empty());
27611185Serfan.azarkhish@unibo.it
27711185Serfan.azarkhish@unibo.it    DeferredPacket req = transmitList.front();
27811185Serfan.azarkhish@unibo.it
27911185Serfan.azarkhish@unibo.it    assert(req.tick <= curTick());
28011185Serfan.azarkhish@unibo.it
28111185Serfan.azarkhish@unibo.it    PacketPtr pkt = req.pkt;
28211185Serfan.azarkhish@unibo.it
28311185Serfan.azarkhish@unibo.it    DPRINTF(SerialLink, "trySend request addr 0x%x, queue size %d\n",
28411185Serfan.azarkhish@unibo.it            pkt->getAddr(), transmitList.size());
28511185Serfan.azarkhish@unibo.it
28611185Serfan.azarkhish@unibo.it    if (sendTimingReq(pkt)) {
28711185Serfan.azarkhish@unibo.it        // send successful
28811185Serfan.azarkhish@unibo.it        transmitList.pop_front();
28911185Serfan.azarkhish@unibo.it
29011185Serfan.azarkhish@unibo.it        DPRINTF(SerialLink, "trySend request successful\n");
29111185Serfan.azarkhish@unibo.it
29211185Serfan.azarkhish@unibo.it        // If there are more packets to send, schedule event to try again.
29311185Serfan.azarkhish@unibo.it        if (!transmitList.empty()) {
29411185Serfan.azarkhish@unibo.it            DeferredPacket next_req = transmitList.front();
29511185Serfan.azarkhish@unibo.it            DPRINTF(SerialLink, "Scheduling next send\n");
29611185Serfan.azarkhish@unibo.it
29711185Serfan.azarkhish@unibo.it            // Make sure bandwidth limitation is met
29811185Serfan.azarkhish@unibo.it            Cycles cycles = Cycles(divCeil(pkt->getSize() * 8,
29911551Sabdul.mutaal@gmail.com                serial_link.num_lanes * serial_link.link_speed));
30011185Serfan.azarkhish@unibo.it            Tick t = serial_link.clockEdge(cycles);
30111185Serfan.azarkhish@unibo.it            serial_link.schedule(sendEvent, std::max(next_req.tick, t));
30211185Serfan.azarkhish@unibo.it        }
30311185Serfan.azarkhish@unibo.it
30411185Serfan.azarkhish@unibo.it        // if we have stalled a request due to a full request queue,
30511185Serfan.azarkhish@unibo.it        // then send a retry at this point, also note that if the
30611185Serfan.azarkhish@unibo.it        // request we stalled was waiting for the response queue
30711185Serfan.azarkhish@unibo.it        // rather than the request queue we might stall it again
30811185Serfan.azarkhish@unibo.it        slavePort.retryStalledReq();
30911185Serfan.azarkhish@unibo.it    }
31011185Serfan.azarkhish@unibo.it
31111185Serfan.azarkhish@unibo.it    // if the send failed, then we try again once we receive a retry,
31211185Serfan.azarkhish@unibo.it    // and therefore there is no need to take any action
31311185Serfan.azarkhish@unibo.it}
31411185Serfan.azarkhish@unibo.it
31511185Serfan.azarkhish@unibo.itvoid
31611185Serfan.azarkhish@unibo.itSerialLink::SerialLinkSlavePort::trySendTiming()
31711185Serfan.azarkhish@unibo.it{
31811185Serfan.azarkhish@unibo.it    assert(!transmitList.empty());
31911185Serfan.azarkhish@unibo.it
32011185Serfan.azarkhish@unibo.it    DeferredPacket resp = transmitList.front();
32111185Serfan.azarkhish@unibo.it
32211185Serfan.azarkhish@unibo.it    assert(resp.tick <= curTick());
32311185Serfan.azarkhish@unibo.it
32411185Serfan.azarkhish@unibo.it    PacketPtr pkt = resp.pkt;
32511185Serfan.azarkhish@unibo.it
32611185Serfan.azarkhish@unibo.it    DPRINTF(SerialLink, "trySend response addr 0x%x, outstanding %d\n",
32711185Serfan.azarkhish@unibo.it            pkt->getAddr(), outstandingResponses);
32811185Serfan.azarkhish@unibo.it
32911185Serfan.azarkhish@unibo.it    if (sendTimingResp(pkt)) {
33011185Serfan.azarkhish@unibo.it        // send successful
33111185Serfan.azarkhish@unibo.it        transmitList.pop_front();
33211185Serfan.azarkhish@unibo.it        DPRINTF(SerialLink, "trySend response successful\n");
33311185Serfan.azarkhish@unibo.it
33411185Serfan.azarkhish@unibo.it        assert(outstandingResponses != 0);
33511185Serfan.azarkhish@unibo.it        --outstandingResponses;
33611185Serfan.azarkhish@unibo.it
33711185Serfan.azarkhish@unibo.it        // If there are more packets to send, schedule event to try again.
33811185Serfan.azarkhish@unibo.it        if (!transmitList.empty()) {
33911185Serfan.azarkhish@unibo.it            DeferredPacket next_resp = transmitList.front();
34011185Serfan.azarkhish@unibo.it            DPRINTF(SerialLink, "Scheduling next send\n");
34111185Serfan.azarkhish@unibo.it
34211185Serfan.azarkhish@unibo.it            // Make sure bandwidth limitation is met
34311185Serfan.azarkhish@unibo.it            Cycles cycles = Cycles(divCeil(pkt->getSize() * 8,
34411551Sabdul.mutaal@gmail.com                serial_link.num_lanes * serial_link.link_speed));
34511185Serfan.azarkhish@unibo.it            Tick t = serial_link.clockEdge(cycles);
34611185Serfan.azarkhish@unibo.it            serial_link.schedule(sendEvent, std::max(next_resp.tick, t));
34711185Serfan.azarkhish@unibo.it        }
34811185Serfan.azarkhish@unibo.it
34911185Serfan.azarkhish@unibo.it        // if there is space in the request queue and we were stalling
35011185Serfan.azarkhish@unibo.it        // a request, it will definitely be possible to accept it now
35111185Serfan.azarkhish@unibo.it        // since there is guaranteed space in the response queue
35211185Serfan.azarkhish@unibo.it        if (!masterPort.reqQueueFull() && retryReq) {
35311185Serfan.azarkhish@unibo.it            DPRINTF(SerialLink, "Request waiting for retry, now retrying\n");
35411185Serfan.azarkhish@unibo.it            retryReq = false;
35511185Serfan.azarkhish@unibo.it            sendRetryReq();
35611185Serfan.azarkhish@unibo.it        }
35711185Serfan.azarkhish@unibo.it    }
35811185Serfan.azarkhish@unibo.it
35911185Serfan.azarkhish@unibo.it    // if the send failed, then we try again once we receive a retry,
36011185Serfan.azarkhish@unibo.it    // and therefore there is no need to take any action
36111185Serfan.azarkhish@unibo.it}
36211185Serfan.azarkhish@unibo.it
36311185Serfan.azarkhish@unibo.itvoid
36411185Serfan.azarkhish@unibo.itSerialLink::SerialLinkMasterPort::recvReqRetry()
36511185Serfan.azarkhish@unibo.it{
36611185Serfan.azarkhish@unibo.it    trySendTiming();
36711185Serfan.azarkhish@unibo.it}
36811185Serfan.azarkhish@unibo.it
36911185Serfan.azarkhish@unibo.itvoid
37011185Serfan.azarkhish@unibo.itSerialLink::SerialLinkSlavePort::recvRespRetry()
37111185Serfan.azarkhish@unibo.it{
37211185Serfan.azarkhish@unibo.it    trySendTiming();
37311185Serfan.azarkhish@unibo.it}
37411185Serfan.azarkhish@unibo.it
37511185Serfan.azarkhish@unibo.itTick
37611185Serfan.azarkhish@unibo.itSerialLink::SerialLinkSlavePort::recvAtomic(PacketPtr pkt)
37711185Serfan.azarkhish@unibo.it{
37811185Serfan.azarkhish@unibo.it    return delay * serial_link.clockPeriod() + masterPort.sendAtomic(pkt);
37911185Serfan.azarkhish@unibo.it}
38011185Serfan.azarkhish@unibo.it
38111185Serfan.azarkhish@unibo.itvoid
38211185Serfan.azarkhish@unibo.itSerialLink::SerialLinkSlavePort::recvFunctional(PacketPtr pkt)
38311185Serfan.azarkhish@unibo.it{
38411185Serfan.azarkhish@unibo.it    pkt->pushLabel(name());
38511185Serfan.azarkhish@unibo.it
38611185Serfan.azarkhish@unibo.it    // check the response queue
38711185Serfan.azarkhish@unibo.it    for (auto i = transmitList.begin();  i != transmitList.end(); ++i) {
38812823Srmk35@cl.cam.ac.uk        if (pkt->trySatisfyFunctional((*i).pkt)) {
38911185Serfan.azarkhish@unibo.it            pkt->makeResponse();
39011185Serfan.azarkhish@unibo.it            return;
39111185Serfan.azarkhish@unibo.it        }
39211185Serfan.azarkhish@unibo.it    }
39311185Serfan.azarkhish@unibo.it
39411185Serfan.azarkhish@unibo.it    // also check the master port's request queue
39512823Srmk35@cl.cam.ac.uk    if (masterPort.trySatisfyFunctional(pkt)) {
39611185Serfan.azarkhish@unibo.it        return;
39711185Serfan.azarkhish@unibo.it    }
39811185Serfan.azarkhish@unibo.it
39911185Serfan.azarkhish@unibo.it    pkt->popLabel();
40011185Serfan.azarkhish@unibo.it
40111185Serfan.azarkhish@unibo.it    // fall through if pkt still not satisfied
40211185Serfan.azarkhish@unibo.it    masterPort.sendFunctional(pkt);
40311185Serfan.azarkhish@unibo.it}
40411185Serfan.azarkhish@unibo.it
40511185Serfan.azarkhish@unibo.itbool
40612823Srmk35@cl.cam.ac.ukSerialLink::SerialLinkMasterPort::trySatisfyFunctional(PacketPtr pkt)
40711185Serfan.azarkhish@unibo.it{
40811185Serfan.azarkhish@unibo.it    bool found = false;
40911185Serfan.azarkhish@unibo.it    auto i = transmitList.begin();
41011185Serfan.azarkhish@unibo.it
41111321Ssteve.reinhardt@amd.com    while (i != transmitList.end() && !found) {
41212823Srmk35@cl.cam.ac.uk        if (pkt->trySatisfyFunctional((*i).pkt)) {
41311185Serfan.azarkhish@unibo.it            pkt->makeResponse();
41411185Serfan.azarkhish@unibo.it            found = true;
41511185Serfan.azarkhish@unibo.it        }
41611185Serfan.azarkhish@unibo.it        ++i;
41711185Serfan.azarkhish@unibo.it    }
41811185Serfan.azarkhish@unibo.it
41911185Serfan.azarkhish@unibo.it    return found;
42011185Serfan.azarkhish@unibo.it}
42111185Serfan.azarkhish@unibo.it
42211185Serfan.azarkhish@unibo.itAddrRangeList
42311185Serfan.azarkhish@unibo.itSerialLink::SerialLinkSlavePort::getAddrRanges() const
42411185Serfan.azarkhish@unibo.it{
42511185Serfan.azarkhish@unibo.it    return ranges;
42611185Serfan.azarkhish@unibo.it}
42711185Serfan.azarkhish@unibo.it
42811185Serfan.azarkhish@unibo.itSerialLink *
42911185Serfan.azarkhish@unibo.itSerialLinkParams::create()
43011185Serfan.azarkhish@unibo.it{
43111185Serfan.azarkhish@unibo.it    return new SerialLink(this);
43211185Serfan.azarkhish@unibo.it}
433