serial_link.cc revision 13892
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