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