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