serial_link.cc revision 12823
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)
8511185Serfan.azarkhish@unibo.it    : MemObject(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
9611185Serfan.azarkhish@unibo.itBaseMasterPort&
9711185Serfan.azarkhish@unibo.itSerialLink::getMasterPort(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;
10111185Serfan.azarkhish@unibo.it    else
10211185Serfan.azarkhish@unibo.it        // pass it along to our super class
10311185Serfan.azarkhish@unibo.it        return MemObject::getMasterPort(if_name, idx);
10411185Serfan.azarkhish@unibo.it}
10511185Serfan.azarkhish@unibo.it
10611185Serfan.azarkhish@unibo.itBaseSlavePort&
10711185Serfan.azarkhish@unibo.itSerialLink::getSlavePort(const std::string &if_name, PortID idx)
10811185Serfan.azarkhish@unibo.it{
10911185Serfan.azarkhish@unibo.it    if (if_name == "slave")
11011185Serfan.azarkhish@unibo.it        return slavePort;
11111185Serfan.azarkhish@unibo.it    else
11211185Serfan.azarkhish@unibo.it        // pass it along to our super class
11311185Serfan.azarkhish@unibo.it        return MemObject::getSlavePort(if_name, idx);
11411185Serfan.azarkhish@unibo.it}
11511185Serfan.azarkhish@unibo.it
11611185Serfan.azarkhish@unibo.itvoid
11711185Serfan.azarkhish@unibo.itSerialLink::init()
11811185Serfan.azarkhish@unibo.it{
11911185Serfan.azarkhish@unibo.it    // make sure both sides are connected and have the same block size
12011185Serfan.azarkhish@unibo.it    if (!slavePort.isConnected() || !masterPort.isConnected())
12111185Serfan.azarkhish@unibo.it        fatal("Both ports of a serial_link must be connected.\n");
12211185Serfan.azarkhish@unibo.it
12311185Serfan.azarkhish@unibo.it    // notify the master side  of our address ranges
12411185Serfan.azarkhish@unibo.it    slavePort.sendRangeChange();
12511185Serfan.azarkhish@unibo.it}
12611185Serfan.azarkhish@unibo.it
12711185Serfan.azarkhish@unibo.itbool
12811185Serfan.azarkhish@unibo.itSerialLink::SerialLinkSlavePort::respQueueFull() const
12911185Serfan.azarkhish@unibo.it{
13011185Serfan.azarkhish@unibo.it    return outstandingResponses == respQueueLimit;
13111185Serfan.azarkhish@unibo.it}
13211185Serfan.azarkhish@unibo.it
13311185Serfan.azarkhish@unibo.itbool
13411185Serfan.azarkhish@unibo.itSerialLink::SerialLinkMasterPort::reqQueueFull() const
13511185Serfan.azarkhish@unibo.it{
13611185Serfan.azarkhish@unibo.it    return transmitList.size() == reqQueueLimit;
13711185Serfan.azarkhish@unibo.it}
13811185Serfan.azarkhish@unibo.it
13911185Serfan.azarkhish@unibo.itbool
14011185Serfan.azarkhish@unibo.itSerialLink::SerialLinkMasterPort::recvTimingResp(PacketPtr pkt)
14111185Serfan.azarkhish@unibo.it{
14211185Serfan.azarkhish@unibo.it    // all checks are done when the request is accepted on the slave
14311185Serfan.azarkhish@unibo.it    // side, so we are guaranteed to have space for the response
14411185Serfan.azarkhish@unibo.it    DPRINTF(SerialLink, "recvTimingResp: %s addr 0x%x\n",
14511185Serfan.azarkhish@unibo.it            pkt->cmdString(), pkt->getAddr());
14611185Serfan.azarkhish@unibo.it
14711185Serfan.azarkhish@unibo.it    DPRINTF(SerialLink, "Request queue size: %d\n", transmitList.size());
14811185Serfan.azarkhish@unibo.it
14911185Serfan.azarkhish@unibo.it    // @todo: We need to pay for this and not just zero it out
15011185Serfan.azarkhish@unibo.it    pkt->headerDelay = pkt->payloadDelay = 0;
15111185Serfan.azarkhish@unibo.it
15211185Serfan.azarkhish@unibo.it    // This is similar to what happens for the request packets:
15311185Serfan.azarkhish@unibo.it    // The serializer will start serialization as soon as it receives the
15411185Serfan.azarkhish@unibo.it    // first flit, but the deserializer (at the host side in this case), will
15511185Serfan.azarkhish@unibo.it    // have to wait to receive the whole packet. So we only account for the
15611185Serfan.azarkhish@unibo.it    // deserialization latency.
15711185Serfan.azarkhish@unibo.it    Cycles cycles = delay;
15811551Sabdul.mutaal@gmail.com    cycles += Cycles(divCeil(pkt->getSize() * 8, serial_link.num_lanes
15911551Sabdul.mutaal@gmail.com                * serial_link.link_speed));
16011551Sabdul.mutaal@gmail.com     Tick t = serial_link.clockEdge(cycles);
16111185Serfan.azarkhish@unibo.it
16211185Serfan.azarkhish@unibo.it    //@todo: If the processor sends two uncached requests towards HMC and the
16311185Serfan.azarkhish@unibo.it    // second one is smaller than the first one. It may happen that the second
16411185Serfan.azarkhish@unibo.it    // one crosses this link faster than the first one (because the packet
16511185Serfan.azarkhish@unibo.it    // waits in the link based on its size). This can reorder the received
16611185Serfan.azarkhish@unibo.it    // response.
16711185Serfan.azarkhish@unibo.it    slavePort.schedTimingResp(pkt, t);
16811185Serfan.azarkhish@unibo.it
16911185Serfan.azarkhish@unibo.it    return true;
17011185Serfan.azarkhish@unibo.it}
17111185Serfan.azarkhish@unibo.it
17211185Serfan.azarkhish@unibo.itbool
17311185Serfan.azarkhish@unibo.itSerialLink::SerialLinkSlavePort::recvTimingReq(PacketPtr pkt)
17411185Serfan.azarkhish@unibo.it{
17511185Serfan.azarkhish@unibo.it    DPRINTF(SerialLink, "recvTimingReq: %s addr 0x%x\n",
17611185Serfan.azarkhish@unibo.it            pkt->cmdString(), pkt->getAddr());
17711185Serfan.azarkhish@unibo.it
17811185Serfan.azarkhish@unibo.it    // we should not see a timing request if we are already in a retry
17911185Serfan.azarkhish@unibo.it    assert(!retryReq);
18011185Serfan.azarkhish@unibo.it
18111185Serfan.azarkhish@unibo.it    DPRINTF(SerialLink, "Response queue size: %d outresp: %d\n",
18211185Serfan.azarkhish@unibo.it            transmitList.size(), outstandingResponses);
18311185Serfan.azarkhish@unibo.it
18411185Serfan.azarkhish@unibo.it    // if the request queue is full then there is no hope
18511185Serfan.azarkhish@unibo.it    if (masterPort.reqQueueFull()) {
18611185Serfan.azarkhish@unibo.it        DPRINTF(SerialLink, "Request queue full\n");
18711185Serfan.azarkhish@unibo.it        retryReq = true;
18811185Serfan.azarkhish@unibo.it    } else if ( !retryReq ) {
18911185Serfan.azarkhish@unibo.it        // look at the response queue if we expect to see a response
19011185Serfan.azarkhish@unibo.it        bool expects_response = pkt->needsResponse() &&
19111284Sandreas.hansson@arm.com            !pkt->cacheResponding();
19211185Serfan.azarkhish@unibo.it        if (expects_response) {
19311185Serfan.azarkhish@unibo.it            if (respQueueFull()) {
19411185Serfan.azarkhish@unibo.it                DPRINTF(SerialLink, "Response queue full\n");
19511185Serfan.azarkhish@unibo.it                retryReq = true;
19611185Serfan.azarkhish@unibo.it            } else {
19711185Serfan.azarkhish@unibo.it                // ok to send the request with space for the response
19811185Serfan.azarkhish@unibo.it                DPRINTF(SerialLink, "Reserving space for response\n");
19911185Serfan.azarkhish@unibo.it                assert(outstandingResponses != respQueueLimit);
20011185Serfan.azarkhish@unibo.it                ++outstandingResponses;
20111185Serfan.azarkhish@unibo.it
20211185Serfan.azarkhish@unibo.it                // no need to set retryReq to false as this is already the
20311185Serfan.azarkhish@unibo.it                // case
20411185Serfan.azarkhish@unibo.it            }
20511185Serfan.azarkhish@unibo.it        }
20611185Serfan.azarkhish@unibo.it
20711185Serfan.azarkhish@unibo.it        if (!retryReq) {
20811185Serfan.azarkhish@unibo.it            // @todo: We need to pay for this and not just zero it out
20911185Serfan.azarkhish@unibo.it            pkt->headerDelay = pkt->payloadDelay = 0;
21011185Serfan.azarkhish@unibo.it
21111185Serfan.azarkhish@unibo.it            // We assume that the serializer component at the transmitter side
21211185Serfan.azarkhish@unibo.it            // does not need to receive the whole packet to start the
21311185Serfan.azarkhish@unibo.it            // serialization (this assumption is consistent with the HMC
21411185Serfan.azarkhish@unibo.it            // standard). But the deserializer waits for the complete packet
21511185Serfan.azarkhish@unibo.it            // to check its integrity first. So everytime a packet crosses a
21611185Serfan.azarkhish@unibo.it            // serial link, we should account for its deserialization latency
21711185Serfan.azarkhish@unibo.it            // only.
21811185Serfan.azarkhish@unibo.it            Cycles cycles = delay;
21911185Serfan.azarkhish@unibo.it            cycles += Cycles(divCeil(pkt->getSize() * 8,
22011551Sabdul.mutaal@gmail.com                    serial_link.num_lanes * serial_link.link_speed));
22111185Serfan.azarkhish@unibo.it            Tick t = serial_link.clockEdge(cycles);
22211185Serfan.azarkhish@unibo.it
22311185Serfan.azarkhish@unibo.it            //@todo: If the processor sends two uncached requests towards HMC
22411185Serfan.azarkhish@unibo.it            // and the second one is smaller than the first one. It may happen
22511185Serfan.azarkhish@unibo.it            // that the second one crosses this link faster than the first one
22611185Serfan.azarkhish@unibo.it            // (because the packet waits in the link based on its size).
22711185Serfan.azarkhish@unibo.it            // This can reorder the received response.
22811185Serfan.azarkhish@unibo.it            masterPort.schedTimingReq(pkt, t);
22911185Serfan.azarkhish@unibo.it        }
23011185Serfan.azarkhish@unibo.it    }
23111185Serfan.azarkhish@unibo.it
23211185Serfan.azarkhish@unibo.it    // remember that we are now stalling a packet and that we have to
23311185Serfan.azarkhish@unibo.it    // tell the sending master to retry once space becomes available,
23411185Serfan.azarkhish@unibo.it    // we make no distinction whether the stalling is due to the
23511185Serfan.azarkhish@unibo.it    // request queue or response queue being full
23611185Serfan.azarkhish@unibo.it    return !retryReq;
23711185Serfan.azarkhish@unibo.it}
23811185Serfan.azarkhish@unibo.it
23911185Serfan.azarkhish@unibo.itvoid
24011185Serfan.azarkhish@unibo.itSerialLink::SerialLinkSlavePort::retryStalledReq()
24111185Serfan.azarkhish@unibo.it{
24211185Serfan.azarkhish@unibo.it    if (retryReq) {
24311185Serfan.azarkhish@unibo.it        DPRINTF(SerialLink, "Request waiting for retry, now retrying\n");
24411185Serfan.azarkhish@unibo.it        retryReq = false;
24511185Serfan.azarkhish@unibo.it        sendRetryReq();
24611185Serfan.azarkhish@unibo.it    }
24711185Serfan.azarkhish@unibo.it}
24811185Serfan.azarkhish@unibo.it
24911185Serfan.azarkhish@unibo.itvoid
25011185Serfan.azarkhish@unibo.itSerialLink::SerialLinkMasterPort::schedTimingReq(PacketPtr pkt, Tick when)
25111185Serfan.azarkhish@unibo.it{
25211185Serfan.azarkhish@unibo.it    // If we're about to put this packet at the head of the queue, we
25311185Serfan.azarkhish@unibo.it    // need to schedule an event to do the transmit.  Otherwise there
25411185Serfan.azarkhish@unibo.it    // should already be an event scheduled for sending the head
25511185Serfan.azarkhish@unibo.it    // packet.
25611185Serfan.azarkhish@unibo.it    if (transmitList.empty()) {
25711185Serfan.azarkhish@unibo.it        serial_link.schedule(sendEvent, when);
25811185Serfan.azarkhish@unibo.it    }
25911185Serfan.azarkhish@unibo.it
26011185Serfan.azarkhish@unibo.it    assert(transmitList.size() != reqQueueLimit);
26111185Serfan.azarkhish@unibo.it
26211185Serfan.azarkhish@unibo.it    transmitList.emplace_back(DeferredPacket(pkt, when));
26311185Serfan.azarkhish@unibo.it}
26411185Serfan.azarkhish@unibo.it
26511185Serfan.azarkhish@unibo.it
26611185Serfan.azarkhish@unibo.itvoid
26711185Serfan.azarkhish@unibo.itSerialLink::SerialLinkSlavePort::schedTimingResp(PacketPtr pkt, Tick when)
26811185Serfan.azarkhish@unibo.it{
26911185Serfan.azarkhish@unibo.it    // If we're about to put this packet at the head of the queue, we
27011185Serfan.azarkhish@unibo.it    // need to schedule an event to do the transmit.  Otherwise there
27111185Serfan.azarkhish@unibo.it    // should already be an event scheduled for sending the head
27211185Serfan.azarkhish@unibo.it    // packet.
27311185Serfan.azarkhish@unibo.it    if (transmitList.empty()) {
27411185Serfan.azarkhish@unibo.it        serial_link.schedule(sendEvent, when);
27511185Serfan.azarkhish@unibo.it    }
27611185Serfan.azarkhish@unibo.it
27711185Serfan.azarkhish@unibo.it    transmitList.emplace_back(DeferredPacket(pkt, when));
27811185Serfan.azarkhish@unibo.it}
27911185Serfan.azarkhish@unibo.it
28011185Serfan.azarkhish@unibo.itvoid
28111185Serfan.azarkhish@unibo.itSerialLink::SerialLinkMasterPort::trySendTiming()
28211185Serfan.azarkhish@unibo.it{
28311185Serfan.azarkhish@unibo.it    assert(!transmitList.empty());
28411185Serfan.azarkhish@unibo.it
28511185Serfan.azarkhish@unibo.it    DeferredPacket req = transmitList.front();
28611185Serfan.azarkhish@unibo.it
28711185Serfan.azarkhish@unibo.it    assert(req.tick <= curTick());
28811185Serfan.azarkhish@unibo.it
28911185Serfan.azarkhish@unibo.it    PacketPtr pkt = req.pkt;
29011185Serfan.azarkhish@unibo.it
29111185Serfan.azarkhish@unibo.it    DPRINTF(SerialLink, "trySend request addr 0x%x, queue size %d\n",
29211185Serfan.azarkhish@unibo.it            pkt->getAddr(), transmitList.size());
29311185Serfan.azarkhish@unibo.it
29411185Serfan.azarkhish@unibo.it    if (sendTimingReq(pkt)) {
29511185Serfan.azarkhish@unibo.it        // send successful
29611185Serfan.azarkhish@unibo.it        transmitList.pop_front();
29711185Serfan.azarkhish@unibo.it
29811185Serfan.azarkhish@unibo.it        DPRINTF(SerialLink, "trySend request successful\n");
29911185Serfan.azarkhish@unibo.it
30011185Serfan.azarkhish@unibo.it        // If there are more packets to send, schedule event to try again.
30111185Serfan.azarkhish@unibo.it        if (!transmitList.empty()) {
30211185Serfan.azarkhish@unibo.it            DeferredPacket next_req = transmitList.front();
30311185Serfan.azarkhish@unibo.it            DPRINTF(SerialLink, "Scheduling next send\n");
30411185Serfan.azarkhish@unibo.it
30511185Serfan.azarkhish@unibo.it            // Make sure bandwidth limitation is met
30611185Serfan.azarkhish@unibo.it            Cycles cycles = Cycles(divCeil(pkt->getSize() * 8,
30711551Sabdul.mutaal@gmail.com                serial_link.num_lanes * serial_link.link_speed));
30811185Serfan.azarkhish@unibo.it            Tick t = serial_link.clockEdge(cycles);
30911185Serfan.azarkhish@unibo.it            serial_link.schedule(sendEvent, std::max(next_req.tick, t));
31011185Serfan.azarkhish@unibo.it        }
31111185Serfan.azarkhish@unibo.it
31211185Serfan.azarkhish@unibo.it        // if we have stalled a request due to a full request queue,
31311185Serfan.azarkhish@unibo.it        // then send a retry at this point, also note that if the
31411185Serfan.azarkhish@unibo.it        // request we stalled was waiting for the response queue
31511185Serfan.azarkhish@unibo.it        // rather than the request queue we might stall it again
31611185Serfan.azarkhish@unibo.it        slavePort.retryStalledReq();
31711185Serfan.azarkhish@unibo.it    }
31811185Serfan.azarkhish@unibo.it
31911185Serfan.azarkhish@unibo.it    // if the send failed, then we try again once we receive a retry,
32011185Serfan.azarkhish@unibo.it    // and therefore there is no need to take any action
32111185Serfan.azarkhish@unibo.it}
32211185Serfan.azarkhish@unibo.it
32311185Serfan.azarkhish@unibo.itvoid
32411185Serfan.azarkhish@unibo.itSerialLink::SerialLinkSlavePort::trySendTiming()
32511185Serfan.azarkhish@unibo.it{
32611185Serfan.azarkhish@unibo.it    assert(!transmitList.empty());
32711185Serfan.azarkhish@unibo.it
32811185Serfan.azarkhish@unibo.it    DeferredPacket resp = transmitList.front();
32911185Serfan.azarkhish@unibo.it
33011185Serfan.azarkhish@unibo.it    assert(resp.tick <= curTick());
33111185Serfan.azarkhish@unibo.it
33211185Serfan.azarkhish@unibo.it    PacketPtr pkt = resp.pkt;
33311185Serfan.azarkhish@unibo.it
33411185Serfan.azarkhish@unibo.it    DPRINTF(SerialLink, "trySend response addr 0x%x, outstanding %d\n",
33511185Serfan.azarkhish@unibo.it            pkt->getAddr(), outstandingResponses);
33611185Serfan.azarkhish@unibo.it
33711185Serfan.azarkhish@unibo.it    if (sendTimingResp(pkt)) {
33811185Serfan.azarkhish@unibo.it        // send successful
33911185Serfan.azarkhish@unibo.it        transmitList.pop_front();
34011185Serfan.azarkhish@unibo.it        DPRINTF(SerialLink, "trySend response successful\n");
34111185Serfan.azarkhish@unibo.it
34211185Serfan.azarkhish@unibo.it        assert(outstandingResponses != 0);
34311185Serfan.azarkhish@unibo.it        --outstandingResponses;
34411185Serfan.azarkhish@unibo.it
34511185Serfan.azarkhish@unibo.it        // If there are more packets to send, schedule event to try again.
34611185Serfan.azarkhish@unibo.it        if (!transmitList.empty()) {
34711185Serfan.azarkhish@unibo.it            DeferredPacket next_resp = transmitList.front();
34811185Serfan.azarkhish@unibo.it            DPRINTF(SerialLink, "Scheduling next send\n");
34911185Serfan.azarkhish@unibo.it
35011185Serfan.azarkhish@unibo.it            // Make sure bandwidth limitation is met
35111185Serfan.azarkhish@unibo.it            Cycles cycles = Cycles(divCeil(pkt->getSize() * 8,
35211551Sabdul.mutaal@gmail.com                serial_link.num_lanes * serial_link.link_speed));
35311185Serfan.azarkhish@unibo.it            Tick t = serial_link.clockEdge(cycles);
35411185Serfan.azarkhish@unibo.it            serial_link.schedule(sendEvent, std::max(next_resp.tick, t));
35511185Serfan.azarkhish@unibo.it        }
35611185Serfan.azarkhish@unibo.it
35711185Serfan.azarkhish@unibo.it        // if there is space in the request queue and we were stalling
35811185Serfan.azarkhish@unibo.it        // a request, it will definitely be possible to accept it now
35911185Serfan.azarkhish@unibo.it        // since there is guaranteed space in the response queue
36011185Serfan.azarkhish@unibo.it        if (!masterPort.reqQueueFull() && retryReq) {
36111185Serfan.azarkhish@unibo.it            DPRINTF(SerialLink, "Request waiting for retry, now retrying\n");
36211185Serfan.azarkhish@unibo.it            retryReq = false;
36311185Serfan.azarkhish@unibo.it            sendRetryReq();
36411185Serfan.azarkhish@unibo.it        }
36511185Serfan.azarkhish@unibo.it    }
36611185Serfan.azarkhish@unibo.it
36711185Serfan.azarkhish@unibo.it    // if the send failed, then we try again once we receive a retry,
36811185Serfan.azarkhish@unibo.it    // and therefore there is no need to take any action
36911185Serfan.azarkhish@unibo.it}
37011185Serfan.azarkhish@unibo.it
37111185Serfan.azarkhish@unibo.itvoid
37211185Serfan.azarkhish@unibo.itSerialLink::SerialLinkMasterPort::recvReqRetry()
37311185Serfan.azarkhish@unibo.it{
37411185Serfan.azarkhish@unibo.it    trySendTiming();
37511185Serfan.azarkhish@unibo.it}
37611185Serfan.azarkhish@unibo.it
37711185Serfan.azarkhish@unibo.itvoid
37811185Serfan.azarkhish@unibo.itSerialLink::SerialLinkSlavePort::recvRespRetry()
37911185Serfan.azarkhish@unibo.it{
38011185Serfan.azarkhish@unibo.it    trySendTiming();
38111185Serfan.azarkhish@unibo.it}
38211185Serfan.azarkhish@unibo.it
38311185Serfan.azarkhish@unibo.itTick
38411185Serfan.azarkhish@unibo.itSerialLink::SerialLinkSlavePort::recvAtomic(PacketPtr pkt)
38511185Serfan.azarkhish@unibo.it{
38611185Serfan.azarkhish@unibo.it    return delay * serial_link.clockPeriod() + masterPort.sendAtomic(pkt);
38711185Serfan.azarkhish@unibo.it}
38811185Serfan.azarkhish@unibo.it
38911185Serfan.azarkhish@unibo.itvoid
39011185Serfan.azarkhish@unibo.itSerialLink::SerialLinkSlavePort::recvFunctional(PacketPtr pkt)
39111185Serfan.azarkhish@unibo.it{
39211185Serfan.azarkhish@unibo.it    pkt->pushLabel(name());
39311185Serfan.azarkhish@unibo.it
39411185Serfan.azarkhish@unibo.it    // check the response queue
39511185Serfan.azarkhish@unibo.it    for (auto i = transmitList.begin();  i != transmitList.end(); ++i) {
39612823Srmk35@cl.cam.ac.uk        if (pkt->trySatisfyFunctional((*i).pkt)) {
39711185Serfan.azarkhish@unibo.it            pkt->makeResponse();
39811185Serfan.azarkhish@unibo.it            return;
39911185Serfan.azarkhish@unibo.it        }
40011185Serfan.azarkhish@unibo.it    }
40111185Serfan.azarkhish@unibo.it
40211185Serfan.azarkhish@unibo.it    // also check the master port's request queue
40312823Srmk35@cl.cam.ac.uk    if (masterPort.trySatisfyFunctional(pkt)) {
40411185Serfan.azarkhish@unibo.it        return;
40511185Serfan.azarkhish@unibo.it    }
40611185Serfan.azarkhish@unibo.it
40711185Serfan.azarkhish@unibo.it    pkt->popLabel();
40811185Serfan.azarkhish@unibo.it
40911185Serfan.azarkhish@unibo.it    // fall through if pkt still not satisfied
41011185Serfan.azarkhish@unibo.it    masterPort.sendFunctional(pkt);
41111185Serfan.azarkhish@unibo.it}
41211185Serfan.azarkhish@unibo.it
41311185Serfan.azarkhish@unibo.itbool
41412823Srmk35@cl.cam.ac.ukSerialLink::SerialLinkMasterPort::trySatisfyFunctional(PacketPtr pkt)
41511185Serfan.azarkhish@unibo.it{
41611185Serfan.azarkhish@unibo.it    bool found = false;
41711185Serfan.azarkhish@unibo.it    auto i = transmitList.begin();
41811185Serfan.azarkhish@unibo.it
41911321Ssteve.reinhardt@amd.com    while (i != transmitList.end() && !found) {
42012823Srmk35@cl.cam.ac.uk        if (pkt->trySatisfyFunctional((*i).pkt)) {
42111185Serfan.azarkhish@unibo.it            pkt->makeResponse();
42211185Serfan.azarkhish@unibo.it            found = true;
42311185Serfan.azarkhish@unibo.it        }
42411185Serfan.azarkhish@unibo.it        ++i;
42511185Serfan.azarkhish@unibo.it    }
42611185Serfan.azarkhish@unibo.it
42711185Serfan.azarkhish@unibo.it    return found;
42811185Serfan.azarkhish@unibo.it}
42911185Serfan.azarkhish@unibo.it
43011185Serfan.azarkhish@unibo.itAddrRangeList
43111185Serfan.azarkhish@unibo.itSerialLink::SerialLinkSlavePort::getAddrRanges() const
43211185Serfan.azarkhish@unibo.it{
43311185Serfan.azarkhish@unibo.it    return ranges;
43411185Serfan.azarkhish@unibo.it}
43511185Serfan.azarkhish@unibo.it
43611185Serfan.azarkhish@unibo.itSerialLink *
43711185Serfan.azarkhish@unibo.itSerialLinkParams::create()
43811185Serfan.azarkhish@unibo.it{
43911185Serfan.azarkhish@unibo.it    return new SerialLink(this);
44011185Serfan.azarkhish@unibo.it}
441