12SN/A/* 211071SN/A * Copyright (c) 2015 ARM Limited 311071SN/A * All rights reserved 411071SN/A * 511071SN/A * The license below extends only to copyright in the software and shall 611071SN/A * not be construed as granting a license to any other intellectual 711071SN/A * property including but not limited to intellectual property relating 811071SN/A * to a hardware implementation of the functionality of the software 911071SN/A * licensed hereunder. You may use the software subject to the license 1011071SN/A * terms below provided that you ensure that this notice is replicated 1111071SN/A * unmodified and in its entirety in all distributions of the software, 1211071SN/A * modified or unmodified, in source code or in binary form. 1311071SN/A * 141762SN/A * Copyright (c) 2002-2005 The Regents of The University of Michigan 152SN/A * All rights reserved. 162SN/A * 172SN/A * Redistribution and use in source and binary forms, with or without 182SN/A * modification, are permitted provided that the following conditions are 192SN/A * met: redistributions of source code must retain the above copyright 202SN/A * notice, this list of conditions and the following disclaimer; 212SN/A * redistributions in binary form must reproduce the above copyright 222SN/A * notice, this list of conditions and the following disclaimer in the 232SN/A * documentation and/or other materials provided with the distribution; 242SN/A * neither the name of the copyright holders nor the names of its 252SN/A * contributors may be used to endorse or promote products derived from 262SN/A * this software without specific prior written permission. 272SN/A * 282SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 292SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 302SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 312SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 322SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 332SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 342SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 352SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 362SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 372SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 382SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 392665SN/A * 402665SN/A * Authors: Nathan Binkert 412665SN/A * Ron Dreslinski 422SN/A */ 432SN/A 442SN/A/* @file 452SN/A * Device module for modelling a fixed bandwidth full duplex ethernet link 462SN/A */ 472SN/A 4811263Sandreas.sandberg@arm.com#include "dev/net/etherlink.hh" 4911263Sandreas.sandberg@arm.com 50146SN/A#include <cmath> 512SN/A#include <deque> 522SN/A#include <string> 532SN/A#include <vector> 542SN/A 551954SN/A#include "base/random.hh" 56146SN/A#include "base/trace.hh" 578232SN/A#include "debug/Ethernet.hh" 588232SN/A#include "debug/EthernetData.hh" 5911263Sandreas.sandberg@arm.com#include "dev/net/etherdump.hh" 6011263Sandreas.sandberg@arm.com#include "dev/net/etherint.hh" 6111263Sandreas.sandberg@arm.com#include "dev/net/etherpkt.hh" 624762SN/A#include "params/EtherLink.hh" 638229SN/A#include "sim/core.hh" 641078SN/A#include "sim/serialize.hh" 651078SN/A#include "sim/system.hh" 662SN/A 672SN/Ausing namespace std; 682SN/A 694981SN/AEtherLink::EtherLink(const Params *p) 7013766Sgabeblack@google.com : SimObject(p) 712SN/A{ 725034SN/A link[0] = new Link(name() + ".link0", this, 0, p->speed, 735034SN/A p->delay, p->delay_var, p->dump); 745034SN/A link[1] = new Link(name() + ".link1", this, 1, p->speed, 755034SN/A p->delay, p->delay_var, p->dump); 762SN/A 774981SN/A interface[0] = new Interface(name() + ".int0", link[0], link[1]); 784981SN/A interface[1] = new Interface(name() + ".int1", link[1], link[0]); 794981SN/A} 802SN/A 812SN/A 822SN/AEtherLink::~EtherLink() 832SN/A{ 841435SN/A delete link[0]; 851435SN/A delete link[1]; 862SN/A 871435SN/A delete interface[0]; 881435SN/A delete interface[1]; 892SN/A} 902SN/A 9113784Sgabeblack@google.comPort & 9213784Sgabeblack@google.comEtherLink::getPort(const std::string &if_name, PortID idx) 934981SN/A{ 944981SN/A if (if_name == "int0") 9513784Sgabeblack@google.com return *interface[0]; 964981SN/A else if (if_name == "int1") 9713784Sgabeblack@google.com return *interface[1]; 9813784Sgabeblack@google.com return SimObject::getPort(if_name, idx); 994981SN/A} 1004981SN/A 1014981SN/A 102633SN/AEtherLink::Interface::Interface(const string &name, Link *tx, Link *rx) 1032SN/A : EtherInt(name), txlink(tx) 1042SN/A{ 1052SN/A tx->setTxInt(this); 1062SN/A rx->setRxInt(this); 1072SN/A} 1082SN/A 1091435SN/AEtherLink::Link::Link(const string &name, EtherLink *p, int num, 1101954SN/A double rate, Tick delay, Tick delay_var, EtherDump *d) 1111435SN/A : objName(name), parent(p), number(num), txint(NULL), rxint(NULL), 1121954SN/A ticksPerByte(rate), linkDelay(delay), delayVar(delay_var), dump(d), 11312087Sspwilson2@wisc.edu doneEvent([this]{ txDone(); }, name), 11412087Sspwilson2@wisc.edu txQueueEvent([this]{ processTxQueue(); }, name) 1151435SN/A{ } 1162SN/A 1172SN/Avoid 11810905SN/AEtherLink::serialize(CheckpointOut &cp) const 119558SN/A{ 12010905SN/A link[0]->serialize("link0", cp); 12110905SN/A link[1]->serialize("link1", cp); 122558SN/A} 123558SN/A 124558SN/Avoid 12510905SN/AEtherLink::unserialize(CheckpointIn &cp) 126558SN/A{ 12710905SN/A link[0]->unserialize("link0", cp); 12810905SN/A link[1]->unserialize("link1", cp); 129558SN/A} 130558SN/A 131558SN/Avoid 1322566SN/AEtherLink::Link::txComplete(EthPacketPtr packet) 133633SN/A{ 134633SN/A DPRINTF(Ethernet, "packet received: len=%d\n", packet->length); 135633SN/A DDUMP(EthernetData, packet->data, packet->length); 136633SN/A rxint->sendPacket(packet); 137633SN/A} 138633SN/A 139633SN/Avoid 1402SN/AEtherLink::Link::txDone() 1412SN/A{ 1422SN/A if (dump) 1432SN/A dump->dump(packet); 1442SN/A 145633SN/A if (linkDelay > 0) { 146633SN/A DPRINTF(Ethernet, "packet delayed: delay=%d\n", linkDelay); 14711071SN/A txQueue.emplace_back(std::make_pair(curTick() + linkDelay, packet)); 14811071SN/A if (!txQueueEvent.scheduled()) 14911071SN/A parent->schedule(txQueueEvent, txQueue.front().first); 150633SN/A } else { 15111071SN/A assert(txQueue.empty()); 152633SN/A txComplete(packet); 153633SN/A } 154195SN/A 1552SN/A packet = 0; 1562SN/A assert(!busy()); 1572SN/A 1582SN/A txint->sendDone(); 1592SN/A} 1602SN/A 16111071SN/Avoid 16211071SN/AEtherLink::Link::processTxQueue() 16311071SN/A{ 16411071SN/A auto cur(txQueue.front()); 16511071SN/A txQueue.pop_front(); 16611071SN/A 16711071SN/A // Schedule a new event to process the next packet in the queue. 16811071SN/A if (!txQueue.empty()) { 16911071SN/A auto next(txQueue.front()); 17011071SN/A assert(next.first > curTick()); 17111071SN/A parent->schedule(txQueueEvent, next.first); 17211071SN/A } 17311071SN/A 17411071SN/A assert(cur.first == curTick()); 17511071SN/A txComplete(cur.second); 17611071SN/A} 17711071SN/A 1782SN/Abool 1792566SN/AEtherLink::Link::transmit(EthPacketPtr pkt) 1802SN/A{ 1812SN/A if (busy()) { 182633SN/A DPRINTF(Ethernet, "packet not sent, link busy\n"); 1832SN/A return false; 1842SN/A } 1852SN/A 186633SN/A DPRINTF(Ethernet, "packet sent: len=%d\n", pkt->length); 1872SN/A DDUMP(EthernetData, pkt->data, pkt->length); 1882SN/A 1892SN/A packet = pkt; 19011701Smichael.lebeane@amd.com Tick delay = (Tick)ceil(((double)pkt->simLength * ticksPerByte) + 1.0); 1915190SN/A if (delayVar != 0) 1925190SN/A delay += random_mt.random<Tick>(0, delayVar); 1935190SN/A 194633SN/A DPRINTF(Ethernet, "scheduling packet: delay=%d, (rate=%f)\n", 195633SN/A delay, ticksPerByte); 1967823SN/A parent->schedule(doneEvent, curTick() + delay); 1972SN/A 1982SN/A return true; 1992SN/A} 2002SN/A 201558SN/Avoid 20210905SN/AEtherLink::Link::serialize(const string &base, CheckpointOut &cp) const 203558SN/A{ 20410469SN/A bool packet_exists = packet != nullptr; 20510905SN/A paramOut(cp, base + ".packet_exists", packet_exists); 2061435SN/A if (packet_exists) 20710905SN/A packet->serialize(base + ".packet", cp); 208558SN/A 209633SN/A bool event_scheduled = doneEvent.scheduled(); 21010905SN/A paramOut(cp, base + ".event_scheduled", event_scheduled); 211558SN/A if (event_scheduled) { 212633SN/A Tick event_time = doneEvent.when(); 21310905SN/A paramOut(cp, base + ".event_time", event_time); 214574SN/A } 215574SN/A 21611071SN/A const size_t tx_queue_size(txQueue.size()); 21711071SN/A paramOut(cp, base + ".tx_queue_size", tx_queue_size); 21811071SN/A unsigned idx(0); 21911071SN/A for (const auto &pe : txQueue) { 22011071SN/A paramOut(cp, csprintf("%s.txQueue[%i].tick", base, idx), pe.first); 22111071SN/A pe.second->serialize(csprintf("%s.txQueue[%i].packet", base, idx), cp); 22211071SN/A 22311071SN/A ++idx; 22411071SN/A } 225558SN/A} 226558SN/A 227558SN/Avoid 22810905SN/AEtherLink::Link::unserialize(const string &base, CheckpointIn &cp) 229558SN/A{ 230574SN/A bool packet_exists; 23110905SN/A paramIn(cp, base + ".packet_exists", packet_exists); 232574SN/A if (packet_exists) { 23311701Smichael.lebeane@amd.com packet = make_shared<EthPacketData>(); 23410905SN/A packet->unserialize(base + ".packet", cp); 235558SN/A } 236558SN/A 237574SN/A bool event_scheduled; 23810905SN/A paramIn(cp, base + ".event_scheduled", event_scheduled); 239558SN/A if (event_scheduled) { 240574SN/A Tick event_time; 24110905SN/A paramIn(cp, base + ".event_time", event_time); 2425606SN/A parent->schedule(doneEvent, event_time); 243558SN/A } 24411071SN/A 24511071SN/A size_t tx_queue_size; 24611071SN/A if (optParamIn(cp, base + ".tx_queue_size", tx_queue_size)) { 24711071SN/A for (size_t idx = 0; idx < tx_queue_size; ++idx) { 24811071SN/A Tick tick; 24911701Smichael.lebeane@amd.com EthPacketPtr delayed_packet = make_shared<EthPacketData>(); 25011071SN/A 25111071SN/A paramIn(cp, csprintf("%s.txQueue[%i].tick", base, idx), tick); 25211071SN/A delayed_packet->unserialize( 25311071SN/A csprintf("%s.txQueue[%i].packet", base, idx), cp); 25411071SN/A 25511071SN/A fatal_if(!txQueue.empty() && txQueue.back().first > tick, 25611071SN/A "Invalid txQueue packet order in EtherLink!\n"); 25711071SN/A txQueue.emplace_back(std::make_pair(tick, delayed_packet)); 25811071SN/A } 25911071SN/A 26011071SN/A if (!txQueue.empty()) 26111071SN/A parent->schedule(txQueueEvent, txQueue.front().first); 26211071SN/A } else { 26311071SN/A // We can't reliably convert in-flight packets from old 26411071SN/A // checkpoints. In fact, gem5 hasn't been able to load these 26511071SN/A // packets for at least two years before the format change. 26611071SN/A warn("Old-style EtherLink serialization format detected, " 26711071SN/A "in-flight packets may have been dropped.\n"); 26811071SN/A } 269558SN/A} 270558SN/A 2714762SN/AEtherLink * 2724762SN/AEtherLinkParams::create() 2732SN/A{ 2744981SN/A return new EtherLink(this); 2752SN/A} 276