etherlink.cc revision 11263
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) 704981SN/A : EtherObject(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 914981SN/AEtherInt* 924981SN/AEtherLink::getEthPort(const std::string &if_name, int idx) 934981SN/A{ 944981SN/A Interface *i; 954981SN/A if (if_name == "int0") 964981SN/A i = interface[0]; 974981SN/A else if (if_name == "int1") 984981SN/A i = interface[1]; 994981SN/A else 1004981SN/A return NULL; 1014981SN/A if (i->getPeer()) 1024981SN/A panic("interface already connected to\n"); 1034981SN/A 1044981SN/A return i; 1054981SN/A} 1064981SN/A 1074981SN/A 108633SN/AEtherLink::Interface::Interface(const string &name, Link *tx, Link *rx) 1092SN/A : EtherInt(name), txlink(tx) 1102SN/A{ 1112SN/A tx->setTxInt(this); 1122SN/A rx->setRxInt(this); 1132SN/A} 1142SN/A 1151435SN/AEtherLink::Link::Link(const string &name, EtherLink *p, int num, 1161954SN/A double rate, Tick delay, Tick delay_var, EtherDump *d) 1171435SN/A : objName(name), parent(p), number(num), txint(NULL), rxint(NULL), 1181954SN/A ticksPerByte(rate), linkDelay(delay), delayVar(delay_var), dump(d), 11911071SN/A doneEvent(this), txQueueEvent(this) 1201435SN/A{ } 1212SN/A 1222SN/Avoid 12310905SN/AEtherLink::serialize(CheckpointOut &cp) const 124558SN/A{ 12510905SN/A link[0]->serialize("link0", cp); 12610905SN/A link[1]->serialize("link1", cp); 127558SN/A} 128558SN/A 129558SN/Avoid 13010905SN/AEtherLink::unserialize(CheckpointIn &cp) 131558SN/A{ 13210905SN/A link[0]->unserialize("link0", cp); 13310905SN/A link[1]->unserialize("link1", cp); 134558SN/A} 135558SN/A 136558SN/Avoid 1372566SN/AEtherLink::Link::txComplete(EthPacketPtr packet) 138633SN/A{ 139633SN/A DPRINTF(Ethernet, "packet received: len=%d\n", packet->length); 140633SN/A DDUMP(EthernetData, packet->data, packet->length); 141633SN/A rxint->sendPacket(packet); 142633SN/A} 143633SN/A 144633SN/Avoid 1452SN/AEtherLink::Link::txDone() 1462SN/A{ 1472SN/A if (dump) 1482SN/A dump->dump(packet); 1492SN/A 150633SN/A if (linkDelay > 0) { 151633SN/A DPRINTF(Ethernet, "packet delayed: delay=%d\n", linkDelay); 15211071SN/A txQueue.emplace_back(std::make_pair(curTick() + linkDelay, packet)); 15311071SN/A if (!txQueueEvent.scheduled()) 15411071SN/A parent->schedule(txQueueEvent, txQueue.front().first); 155633SN/A } else { 15611071SN/A assert(txQueue.empty()); 157633SN/A txComplete(packet); 158633SN/A } 159195SN/A 1602SN/A packet = 0; 1612SN/A assert(!busy()); 1622SN/A 1632SN/A txint->sendDone(); 1642SN/A} 1652SN/A 16611071SN/Avoid 16711071SN/AEtherLink::Link::processTxQueue() 16811071SN/A{ 16911071SN/A auto cur(txQueue.front()); 17011071SN/A txQueue.pop_front(); 17111071SN/A 17211071SN/A // Schedule a new event to process the next packet in the queue. 17311071SN/A if (!txQueue.empty()) { 17411071SN/A auto next(txQueue.front()); 17511071SN/A assert(next.first > curTick()); 17611071SN/A parent->schedule(txQueueEvent, next.first); 17711071SN/A } 17811071SN/A 17911071SN/A assert(cur.first == curTick()); 18011071SN/A txComplete(cur.second); 18111071SN/A} 18211071SN/A 1832SN/Abool 1842566SN/AEtherLink::Link::transmit(EthPacketPtr pkt) 1852SN/A{ 1862SN/A if (busy()) { 187633SN/A DPRINTF(Ethernet, "packet not sent, link busy\n"); 1882SN/A return false; 1892SN/A } 1902SN/A 191633SN/A DPRINTF(Ethernet, "packet sent: len=%d\n", pkt->length); 1922SN/A DDUMP(EthernetData, pkt->data, pkt->length); 1932SN/A 1942SN/A packet = pkt; 1951961SN/A Tick delay = (Tick)ceil(((double)pkt->length * ticksPerByte) + 1.0); 1965190SN/A if (delayVar != 0) 1975190SN/A delay += random_mt.random<Tick>(0, delayVar); 1985190SN/A 199633SN/A DPRINTF(Ethernet, "scheduling packet: delay=%d, (rate=%f)\n", 200633SN/A delay, ticksPerByte); 2017823SN/A parent->schedule(doneEvent, curTick() + delay); 2022SN/A 2032SN/A return true; 2042SN/A} 2052SN/A 206558SN/Avoid 20710905SN/AEtherLink::Link::serialize(const string &base, CheckpointOut &cp) const 208558SN/A{ 20910469SN/A bool packet_exists = packet != nullptr; 21010905SN/A paramOut(cp, base + ".packet_exists", packet_exists); 2111435SN/A if (packet_exists) 21210905SN/A packet->serialize(base + ".packet", cp); 213558SN/A 214633SN/A bool event_scheduled = doneEvent.scheduled(); 21510905SN/A paramOut(cp, base + ".event_scheduled", event_scheduled); 216558SN/A if (event_scheduled) { 217633SN/A Tick event_time = doneEvent.when(); 21810905SN/A paramOut(cp, base + ".event_time", event_time); 219574SN/A } 220574SN/A 22111071SN/A const size_t tx_queue_size(txQueue.size()); 22211071SN/A paramOut(cp, base + ".tx_queue_size", tx_queue_size); 22311071SN/A unsigned idx(0); 22411071SN/A for (const auto &pe : txQueue) { 22511071SN/A paramOut(cp, csprintf("%s.txQueue[%i].tick", base, idx), pe.first); 22611071SN/A pe.second->serialize(csprintf("%s.txQueue[%i].packet", base, idx), cp); 22711071SN/A 22811071SN/A ++idx; 22911071SN/A } 230558SN/A} 231558SN/A 232558SN/Avoid 23310905SN/AEtherLink::Link::unserialize(const string &base, CheckpointIn &cp) 234558SN/A{ 235574SN/A bool packet_exists; 23610905SN/A paramIn(cp, base + ".packet_exists", packet_exists); 237574SN/A if (packet_exists) { 23810469SN/A packet = make_shared<EthPacketData>(16384); 23910905SN/A packet->unserialize(base + ".packet", cp); 240558SN/A } 241558SN/A 242574SN/A bool event_scheduled; 24310905SN/A paramIn(cp, base + ".event_scheduled", event_scheduled); 244558SN/A if (event_scheduled) { 245574SN/A Tick event_time; 24610905SN/A paramIn(cp, base + ".event_time", event_time); 2475606SN/A parent->schedule(doneEvent, event_time); 248558SN/A } 24911071SN/A 25011071SN/A size_t tx_queue_size; 25111071SN/A if (optParamIn(cp, base + ".tx_queue_size", tx_queue_size)) { 25211071SN/A for (size_t idx = 0; idx < tx_queue_size; ++idx) { 25311071SN/A Tick tick; 25411071SN/A EthPacketPtr delayed_packet = make_shared<EthPacketData>(16384); 25511071SN/A 25611071SN/A paramIn(cp, csprintf("%s.txQueue[%i].tick", base, idx), tick); 25711071SN/A delayed_packet->unserialize( 25811071SN/A csprintf("%s.txQueue[%i].packet", base, idx), cp); 25911071SN/A 26011071SN/A fatal_if(!txQueue.empty() && txQueue.back().first > tick, 26111071SN/A "Invalid txQueue packet order in EtherLink!\n"); 26211071SN/A txQueue.emplace_back(std::make_pair(tick, delayed_packet)); 26311071SN/A } 26411071SN/A 26511071SN/A if (!txQueue.empty()) 26611071SN/A parent->schedule(txQueueEvent, txQueue.front().first); 26711071SN/A } else { 26811071SN/A // We can't reliably convert in-flight packets from old 26911071SN/A // checkpoints. In fact, gem5 hasn't been able to load these 27011071SN/A // packets for at least two years before the format change. 27111071SN/A warn("Old-style EtherLink serialization format detected, " 27211071SN/A "in-flight packets may have been dropped.\n"); 27311071SN/A } 274558SN/A} 275558SN/A 2764762SN/AEtherLink * 2774762SN/AEtherLinkParams::create() 2782SN/A{ 2794981SN/A return new EtherLink(this); 2802SN/A} 281