serial_link.cc revision 11551
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), 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) { 39611185Serfan.azarkhish@unibo.it if (pkt->checkFunctional((*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 40311185Serfan.azarkhish@unibo.it if (masterPort.checkFunctional(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 41411185Serfan.azarkhish@unibo.itSerialLink::SerialLinkMasterPort::checkFunctional(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) { 42011185Serfan.azarkhish@unibo.it if (pkt->checkFunctional((*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