etherlink.cc revision 11263:8dcc6b40f164
14876Sstever@eecs.umich.edu/* 23646Srdreslin@umich.edu * Copyright (c) 2015 ARM Limited 33646Srdreslin@umich.edu * All rights reserved 43646Srdreslin@umich.edu * 53646Srdreslin@umich.edu * The license below extends only to copyright in the software and shall 63646Srdreslin@umich.edu * not be construed as granting a license to any other intellectual 73646Srdreslin@umich.edu * property including but not limited to intellectual property relating 83646Srdreslin@umich.edu * to a hardware implementation of the functionality of the software 93646Srdreslin@umich.edu * licensed hereunder. You may use the software subject to the license 103646Srdreslin@umich.edu * terms below provided that you ensure that this notice is replicated 113646Srdreslin@umich.edu * unmodified and in its entirety in all distributions of the software, 123646Srdreslin@umich.edu * modified or unmodified, in source code or in binary form. 133646Srdreslin@umich.edu * 143646Srdreslin@umich.edu * Copyright (c) 2002-2005 The Regents of The University of Michigan 153646Srdreslin@umich.edu * All rights reserved. 163646Srdreslin@umich.edu * 173646Srdreslin@umich.edu * Redistribution and use in source and binary forms, with or without 183646Srdreslin@umich.edu * modification, are permitted provided that the following conditions are 193646Srdreslin@umich.edu * met: redistributions of source code must retain the above copyright 203646Srdreslin@umich.edu * notice, this list of conditions and the following disclaimer; 213646Srdreslin@umich.edu * redistributions in binary form must reproduce the above copyright 223646Srdreslin@umich.edu * notice, this list of conditions and the following disclaimer in the 233646Srdreslin@umich.edu * documentation and/or other materials provided with the distribution; 243646Srdreslin@umich.edu * neither the name of the copyright holders nor the names of its 253646Srdreslin@umich.edu * contributors may be used to endorse or promote products derived from 263646Srdreslin@umich.edu * this software without specific prior written permission. 273646Srdreslin@umich.edu * 283646Srdreslin@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 293646Srdreslin@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 303646Srdreslin@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 313646Srdreslin@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 323646Srdreslin@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 3312564Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 3412564Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 356654Snate@binkert.org * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 366654Snate@binkert.org * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 376654Snate@binkert.org * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 386654Snate@binkert.org * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 393646Srdreslin@umich.edu * 403646Srdreslin@umich.edu * Authors: Nathan Binkert 416654Snate@binkert.org * Ron Dreslinski 423646Srdreslin@umich.edu */ 433646Srdreslin@umich.edu 443646Srdreslin@umich.edu/* @file 453646Srdreslin@umich.edu * Device module for modelling a fixed bandwidth full duplex ethernet link 463646Srdreslin@umich.edu */ 473646Srdreslin@umich.edu 483646Srdreslin@umich.edu#include "dev/net/etherlink.hh" 493646Srdreslin@umich.edu 503646Srdreslin@umich.edu#include <cmath> 513646Srdreslin@umich.edu#include <deque> 523646Srdreslin@umich.edu#include <string> 533646Srdreslin@umich.edu#include <vector> 543646Srdreslin@umich.edu 553646Srdreslin@umich.edu#include "base/random.hh" 563646Srdreslin@umich.edu#include "base/trace.hh" 573646Srdreslin@umich.edu#include "debug/Ethernet.hh" 583646Srdreslin@umich.edu#include "debug/EthernetData.hh" 593646Srdreslin@umich.edu#include "dev/net/etherdump.hh" 603646Srdreslin@umich.edu#include "dev/net/etherint.hh" 613646Srdreslin@umich.edu#include "dev/net/etherpkt.hh" 623646Srdreslin@umich.edu#include "params/EtherLink.hh" 633646Srdreslin@umich.edu#include "sim/core.hh" 643646Srdreslin@umich.edu#include "sim/serialize.hh" 653646Srdreslin@umich.edu#include "sim/system.hh" 663646Srdreslin@umich.edu 673646Srdreslin@umich.eduusing namespace std; 683646Srdreslin@umich.edu 693646Srdreslin@umich.eduEtherLink::EtherLink(const Params *p) 703646Srdreslin@umich.edu : EtherObject(p) 713646Srdreslin@umich.edu{ 723646Srdreslin@umich.edu link[0] = new Link(name() + ".link0", this, 0, p->speed, 733646Srdreslin@umich.edu p->delay, p->delay_var, p->dump); 743646Srdreslin@umich.edu link[1] = new Link(name() + ".link1", this, 1, p->speed, 7512564Sgabeblack@google.com p->delay, p->delay_var, p->dump); 763646Srdreslin@umich.edu 773646Srdreslin@umich.edu interface[0] = new Interface(name() + ".int0", link[0], link[1]); 783646Srdreslin@umich.edu interface[1] = new Interface(name() + ".int1", link[1], link[0]); 793646Srdreslin@umich.edu} 803646Srdreslin@umich.edu 8111851Sbrandon.potter@amd.com 823646Srdreslin@umich.eduEtherLink::~EtherLink() 833646Srdreslin@umich.edu{ 843646Srdreslin@umich.edu delete link[0]; 853646Srdreslin@umich.edu delete link[1]; 8611851Sbrandon.potter@amd.com 873646Srdreslin@umich.edu delete interface[0]; 883646Srdreslin@umich.edu delete interface[1]; 893646Srdreslin@umich.edu} 9011851Sbrandon.potter@amd.com 913646Srdreslin@umich.eduEtherInt* 923646Srdreslin@umich.eduEtherLink::getEthPort(const std::string &if_name, int idx) 933646Srdreslin@umich.edu{ 9411851Sbrandon.potter@amd.com Interface *i; 953646Srdreslin@umich.edu if (if_name == "int0") 963646Srdreslin@umich.edu i = interface[0]; 973646Srdreslin@umich.edu else if (if_name == "int1") 9811851Sbrandon.potter@amd.com i = interface[1]; 993646Srdreslin@umich.edu else 1003646Srdreslin@umich.edu return NULL; 1013646Srdreslin@umich.edu if (i->getPeer()) 10211851Sbrandon.potter@amd.com panic("interface already connected to\n"); 1033646Srdreslin@umich.edu 1043646Srdreslin@umich.edu return i; 1053646Srdreslin@umich.edu} 1063646Srdreslin@umich.edu 10711851Sbrandon.potter@amd.com 1083646Srdreslin@umich.eduEtherLink::Interface::Interface(const string &name, Link *tx, Link *rx) 1093646Srdreslin@umich.edu : EtherInt(name), txlink(tx) 1103646Srdreslin@umich.edu{ 1113646Srdreslin@umich.edu tx->setTxInt(this); 11211851Sbrandon.potter@amd.com rx->setRxInt(this); 1133646Srdreslin@umich.edu} 1143646Srdreslin@umich.edu 1153646Srdreslin@umich.eduEtherLink::Link::Link(const string &name, EtherLink *p, int num, 11611851Sbrandon.potter@amd.com double rate, Tick delay, Tick delay_var, EtherDump *d) 1173646Srdreslin@umich.edu : objName(name), parent(p), number(num), txint(NULL), rxint(NULL), 1183646Srdreslin@umich.edu ticksPerByte(rate), linkDelay(delay), delayVar(delay_var), dump(d), 1193646Srdreslin@umich.edu doneEvent(this), txQueueEvent(this) 12011851Sbrandon.potter@amd.com{ } 1213646Srdreslin@umich.edu 1223646Srdreslin@umich.eduvoid 1233646Srdreslin@umich.eduEtherLink::serialize(CheckpointOut &cp) const 1243646Srdreslin@umich.edu{ 12511851Sbrandon.potter@amd.com link[0]->serialize("link0", cp); 1263646Srdreslin@umich.edu link[1]->serialize("link1", cp); 1273646Srdreslin@umich.edu} 1283646Srdreslin@umich.edu 1293646Srdreslin@umich.eduvoid 13011851Sbrandon.potter@amd.comEtherLink::unserialize(CheckpointIn &cp) 1313646Srdreslin@umich.edu{ 1323646Srdreslin@umich.edu link[0]->unserialize("link0", cp); 1333646Srdreslin@umich.edu link[1]->unserialize("link1", cp); 1343646Srdreslin@umich.edu} 1353646Srdreslin@umich.edu 1363646Srdreslin@umich.eduvoid 1373646Srdreslin@umich.eduEtherLink::Link::txComplete(EthPacketPtr packet) 1383646Srdreslin@umich.edu{ 1393646Srdreslin@umich.edu DPRINTF(Ethernet, "packet received: len=%d\n", packet->length); 14011053Sandreas.hansson@arm.com DDUMP(EthernetData, packet->data, packet->length); 1413646Srdreslin@umich.edu rxint->sendPacket(packet); 1423646Srdreslin@umich.edu} 1433646Srdreslin@umich.edu 1443646Srdreslin@umich.eduvoid 1453646Srdreslin@umich.eduEtherLink::Link::txDone() 1463646Srdreslin@umich.edu{ 1473646Srdreslin@umich.edu if (dump) 1483646Srdreslin@umich.edu dump->dump(packet); 14911053Sandreas.hansson@arm.com 1503646Srdreslin@umich.edu if (linkDelay > 0) { 1513646Srdreslin@umich.edu DPRINTF(Ethernet, "packet delayed: delay=%d\n", linkDelay); 1523646Srdreslin@umich.edu txQueue.emplace_back(std::make_pair(curTick() + linkDelay, packet)); 1533646Srdreslin@umich.edu if (!txQueueEvent.scheduled()) 1543646Srdreslin@umich.edu parent->schedule(txQueueEvent, txQueue.front().first); 1553646Srdreslin@umich.edu } else { 1563646Srdreslin@umich.edu assert(txQueue.empty()); 1573646Srdreslin@umich.edu txComplete(packet); 1583646Srdreslin@umich.edu } 1593646Srdreslin@umich.edu 1603646Srdreslin@umich.edu packet = 0; 1613646Srdreslin@umich.edu assert(!busy()); 1623646Srdreslin@umich.edu 1633646Srdreslin@umich.edu txint->sendDone(); 1643646Srdreslin@umich.edu} 1653646Srdreslin@umich.edu 1663646Srdreslin@umich.eduvoid 1673646Srdreslin@umich.eduEtherLink::Link::processTxQueue() 1683646Srdreslin@umich.edu{ 1693646Srdreslin@umich.edu auto cur(txQueue.front()); 1703646Srdreslin@umich.edu txQueue.pop_front(); 1713646Srdreslin@umich.edu 1723646Srdreslin@umich.edu // Schedule a new event to process the next packet in the queue. 1733646Srdreslin@umich.edu if (!txQueue.empty()) { 17410720Sandreas.hansson@arm.com auto next(txQueue.front()); 1753646Srdreslin@umich.edu assert(next.first > curTick()); 1763646Srdreslin@umich.edu parent->schedule(txQueueEvent, next.first); 1773646Srdreslin@umich.edu } 1783646Srdreslin@umich.edu 1793646Srdreslin@umich.edu assert(cur.first == curTick()); 1803646Srdreslin@umich.edu txComplete(cur.second); 1813646Srdreslin@umich.edu} 1823646Srdreslin@umich.edu 1833646Srdreslin@umich.edubool 1843646Srdreslin@umich.eduEtherLink::Link::transmit(EthPacketPtr pkt) 1853646Srdreslin@umich.edu{ 1863646Srdreslin@umich.edu if (busy()) { 18710720Sandreas.hansson@arm.com DPRINTF(Ethernet, "packet not sent, link busy\n"); 1883646Srdreslin@umich.edu return false; 1893646Srdreslin@umich.edu } 1903646Srdreslin@umich.edu 1913646Srdreslin@umich.edu DPRINTF(Ethernet, "packet sent: len=%d\n", pkt->length); 1923646Srdreslin@umich.edu DDUMP(EthernetData, pkt->data, pkt->length); 1933646Srdreslin@umich.edu 1943646Srdreslin@umich.edu packet = pkt; 1953646Srdreslin@umich.edu Tick delay = (Tick)ceil(((double)pkt->length * ticksPerByte) + 1.0); 1963646Srdreslin@umich.edu if (delayVar != 0) 1973646Srdreslin@umich.edu delay += random_mt.random<Tick>(0, delayVar); 1983646Srdreslin@umich.edu 1993646Srdreslin@umich.edu DPRINTF(Ethernet, "scheduling packet: delay=%d, (rate=%f)\n", 20010720Sandreas.hansson@arm.com delay, ticksPerByte); 2013646Srdreslin@umich.edu parent->schedule(doneEvent, curTick() + delay); 2023646Srdreslin@umich.edu 2033646Srdreslin@umich.edu return true; 2043646Srdreslin@umich.edu} 2053646Srdreslin@umich.edu 2063646Srdreslin@umich.eduvoid 2073646Srdreslin@umich.eduEtherLink::Link::serialize(const string &base, CheckpointOut &cp) const 2083646Srdreslin@umich.edu{ 2093646Srdreslin@umich.edu bool packet_exists = packet != nullptr; 2103646Srdreslin@umich.edu paramOut(cp, base + ".packet_exists", packet_exists); 2113646Srdreslin@umich.edu if (packet_exists) 2128931Sandreas.hansson@arm.com packet->serialize(base + ".packet", cp); 2139036Sandreas.hansson@arm.com 21410720Sandreas.hansson@arm.com bool event_scheduled = doneEvent.scheduled(); 2159790Sakash.bagdia@arm.com paramOut(cp, base + ".event_scheduled", event_scheduled); 2163646Srdreslin@umich.edu if (event_scheduled) { 21710720Sandreas.hansson@arm.com Tick event_time = doneEvent.when(); 2183646Srdreslin@umich.edu paramOut(cp, base + ".event_time", event_time); 2193646Srdreslin@umich.edu } 2203646Srdreslin@umich.edu 2213646Srdreslin@umich.edu const size_t tx_queue_size(txQueue.size()); 2223646Srdreslin@umich.edu paramOut(cp, base + ".tx_queue_size", tx_queue_size); 2233646Srdreslin@umich.edu unsigned idx(0); 2248847Sandreas.hansson@arm.com for (const auto &pe : txQueue) { 2258847Sandreas.hansson@arm.com paramOut(cp, csprintf("%s.txQueue[%i].tick", base, idx), pe.first); 2268847Sandreas.hansson@arm.com pe.second->serialize(csprintf("%s.txQueue[%i].packet", base, idx), cp); 2273646Srdreslin@umich.edu 2283646Srdreslin@umich.edu ++idx; 2293646Srdreslin@umich.edu } 2303646Srdreslin@umich.edu} 2313646Srdreslin@umich.edu 2328847Sandreas.hansson@arm.comvoid 2338847Sandreas.hansson@arm.comEtherLink::Link::unserialize(const string &base, CheckpointIn &cp) 2343646Srdreslin@umich.edu{ 2358847Sandreas.hansson@arm.com bool packet_exists; 2368847Sandreas.hansson@arm.com paramIn(cp, base + ".packet_exists", packet_exists); 2373646Srdreslin@umich.edu if (packet_exists) { 2383646Srdreslin@umich.edu packet = make_shared<EthPacketData>(16384); 2393646Srdreslin@umich.edu packet->unserialize(base + ".packet", cp); 2403646Srdreslin@umich.edu } 2413646Srdreslin@umich.edu 2428801Sgblack@eecs.umich.edu bool event_scheduled; 2433646Srdreslin@umich.edu paramIn(cp, base + ".event_scheduled", event_scheduled); 2443646Srdreslin@umich.edu if (event_scheduled) { 2453646Srdreslin@umich.edu Tick event_time; 2463646Srdreslin@umich.edu paramIn(cp, base + ".event_time", event_time); 2473646Srdreslin@umich.edu parent->schedule(doneEvent, event_time); 2483646Srdreslin@umich.edu } 2493646Srdreslin@umich.edu 2503646Srdreslin@umich.edu size_t tx_queue_size; 2513646Srdreslin@umich.edu if (optParamIn(cp, base + ".tx_queue_size", tx_queue_size)) { 2523646Srdreslin@umich.edu for (size_t idx = 0; idx < tx_queue_size; ++idx) { 2533646Srdreslin@umich.edu Tick tick; 2543646Srdreslin@umich.edu EthPacketPtr delayed_packet = make_shared<EthPacketData>(16384); 2553646Srdreslin@umich.edu 2563646Srdreslin@umich.edu paramIn(cp, csprintf("%s.txQueue[%i].tick", base, idx), tick); 2573646Srdreslin@umich.edu delayed_packet->unserialize( 2583646Srdreslin@umich.edu csprintf("%s.txQueue[%i].packet", base, idx), cp); 2593646Srdreslin@umich.edu 2603646Srdreslin@umich.edu fatal_if(!txQueue.empty() && txQueue.back().first > tick, 2613646Srdreslin@umich.edu "Invalid txQueue packet order in EtherLink!\n"); 2623646Srdreslin@umich.edu txQueue.emplace_back(std::make_pair(tick, delayed_packet)); 2633646Srdreslin@umich.edu } 2643646Srdreslin@umich.edu 2653646Srdreslin@umich.edu if (!txQueue.empty()) 2663646Srdreslin@umich.edu parent->schedule(txQueueEvent, txQueue.front().first); 2673646Srdreslin@umich.edu } else { 2683646Srdreslin@umich.edu // We can't reliably convert in-flight packets from old 2693646Srdreslin@umich.edu // checkpoints. In fact, gem5 hasn't been able to load these 2703646Srdreslin@umich.edu // packets for at least two years before the format change. 2713646Srdreslin@umich.edu warn("Old-style EtherLink serialization format detected, " 2726654Snate@binkert.org "in-flight packets may have been dropped.\n"); 2736654Snate@binkert.org } 2746654Snate@binkert.org} 2756654Snate@binkert.org 2766654Snate@binkert.orgEtherLink * 2773646Srdreslin@umich.eduEtherLinkParams::create() 2783646Srdreslin@umich.edu{ 2793646Srdreslin@umich.edu return new EtherLink(this); 2803646Srdreslin@umich.edu} 2813646Srdreslin@umich.edu