etherlink.cc revision 13766:4ecebdee8da4
13536SN/A/* 27752SWilliam.Wang@arm.com * Copyright (c) 2015 ARM Limited 37752SWilliam.Wang@arm.com * All rights reserved 47752SWilliam.Wang@arm.com * 57752SWilliam.Wang@arm.com * The license below extends only to copyright in the software and shall 67752SWilliam.Wang@arm.com * not be construed as granting a license to any other intellectual 77752SWilliam.Wang@arm.com * property including but not limited to intellectual property relating 87752SWilliam.Wang@arm.com * to a hardware implementation of the functionality of the software 97752SWilliam.Wang@arm.com * licensed hereunder. You may use the software subject to the license 107752SWilliam.Wang@arm.com * terms below provided that you ensure that this notice is replicated 117752SWilliam.Wang@arm.com * unmodified and in its entirety in all distributions of the software, 127752SWilliam.Wang@arm.com * modified or unmodified, in source code or in binary form. 137752SWilliam.Wang@arm.com * 143536SN/A * Copyright (c) 2002-2005 The Regents of The University of Michigan 153536SN/A * All rights reserved. 163536SN/A * 173536SN/A * Redistribution and use in source and binary forms, with or without 183536SN/A * modification, are permitted provided that the following conditions are 193536SN/A * met: redistributions of source code must retain the above copyright 203536SN/A * notice, this list of conditions and the following disclaimer; 213536SN/A * redistributions in binary form must reproduce the above copyright 223536SN/A * notice, this list of conditions and the following disclaimer in the 233536SN/A * documentation and/or other materials provided with the distribution; 243536SN/A * neither the name of the copyright holders nor the names of its 253536SN/A * contributors may be used to endorse or promote products derived from 263536SN/A * this software without specific prior written permission. 273536SN/A * 283536SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 293536SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 303536SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 313536SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 323536SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 333536SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 343536SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 353536SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 363536SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 373536SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 383536SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 393536SN/A * 403536SN/A * Authors: Nathan Binkert 417752SWilliam.Wang@arm.com * Ron Dreslinski 423536SN/A */ 433536SN/A 443536SN/A/* @file 458332Snate@binkert.org * Device module for modelling a fixed bandwidth full duplex ethernet link 468332Snate@binkert.org */ 473536SN/A 483536SN/A#include "dev/net/etherlink.hh" 493536SN/A 503536SN/A#include <cmath> 513536SN/A#include <deque> 523536SN/A#include <string> 533536SN/A#include <vector> 545543SN/A 555543SN/A#include "base/random.hh" 563536SN/A#include "base/trace.hh" 573536SN/A#include "debug/Ethernet.hh" 583536SN/A#include "debug/EthernetData.hh" 593536SN/A#include "dev/net/etherdump.hh" 603536SN/A#include "dev/net/etherint.hh" 613536SN/A#include "dev/net/etherpkt.hh" 623536SN/A#include "params/EtherLink.hh" 633536SN/A#include "sim/core.hh" 643536SN/A#include "sim/serialize.hh" 653536SN/A#include "sim/system.hh" 663536SN/A 675543SN/Ausing namespace std; 685543SN/A 693536SN/AEtherLink::EtherLink(const Params *p) 703536SN/A : SimObject(p) 713536SN/A{ 723536SN/A link[0] = new Link(name() + ".link0", this, 0, p->speed, 733536SN/A p->delay, p->delay_var, p->dump); 743536SN/A link[1] = new Link(name() + ".link1", this, 1, p->speed, 753536SN/A p->delay, p->delay_var, p->dump); 763536SN/A 773536SN/A interface[0] = new Interface(name() + ".int0", link[0], link[1]); 783536SN/A interface[1] = new Interface(name() + ".int1", link[1], link[0]); 793536SN/A} 803536SN/A 813536SN/A 823536SN/AEtherLink::~EtherLink() 833536SN/A{ 843536SN/A delete link[0]; 855543SN/A delete link[1]; 863536SN/A 873536SN/A delete interface[0]; 883536SN/A delete interface[1]; 893536SN/A} 903536SN/A 913536SN/AEtherInt* 923536SN/AEtherLink::getEthPort(const std::string &if_name, int idx) 933536SN/A{ 943536SN/A Interface *i; 953536SN/A if (if_name == "int0") 963536SN/A i = interface[0]; 973536SN/A else if (if_name == "int1") 983536SN/A i = interface[1]; 993536SN/A else 1003536SN/A return NULL; 1013536SN/A if (i->getPeer()) 1023536SN/A panic("interface already connected to\n"); 1033536SN/A 1043536SN/A return i; 1055543SN/A} 1065543SN/A 1073536SN/A 1083536SN/AEtherLink::Interface::Interface(const string &name, Link *tx, Link *rx) 1093536SN/A : EtherInt(name), txlink(tx) 1103536SN/A{ 1113536SN/A tx->setTxInt(this); 1123536SN/A rx->setRxInt(this); 1133536SN/A} 1143536SN/A 1153536SN/AEtherLink::Link::Link(const string &name, EtherLink *p, int num, 1163536SN/A double rate, Tick delay, Tick delay_var, EtherDump *d) 1173536SN/A : objName(name), parent(p), number(num), txint(NULL), rxint(NULL), 1183536SN/A ticksPerByte(rate), linkDelay(delay), delayVar(delay_var), dump(d), 1193536SN/A doneEvent([this]{ txDone(); }, name), 1203536SN/A txQueueEvent([this]{ processTxQueue(); }, name) 1213536SN/A{ } 1223536SN/A 1233536SN/Avoid 1243536SN/AEtherLink::serialize(CheckpointOut &cp) const 1253536SN/A{ 1263536SN/A link[0]->serialize("link0", cp); 1273536SN/A link[1]->serialize("link1", cp); 1283536SN/A} 1293536SN/A 1303536SN/Avoid 1313536SN/AEtherLink::unserialize(CheckpointIn &cp) 1323536SN/A{ 1335569SN/A link[0]->unserialize("link0", cp); 1343536SN/A link[1]->unserialize("link1", cp); 1353536SN/A} 1363536SN/A 1379020Sgblack@eecs.umich.eduvoid 1388229Snate@binkert.orgEtherLink::Link::txComplete(EthPacketPtr packet) 1398229Snate@binkert.org{ 1408229Snate@binkert.org DPRINTF(Ethernet, "packet received: len=%d\n", packet->length); 1417752SWilliam.Wang@arm.com DDUMP(EthernetData, packet->data, packet->length); 1427752SWilliam.Wang@arm.com rxint->sendPacket(packet); 1433536SN/A} 1443536SN/A 1453536SN/Avoid 1463536SN/AEtherLink::Link::txDone() 1478229Snate@binkert.org{ 1483536SN/A if (dump) 1497752SWilliam.Wang@arm.com dump->dump(packet); 1508232Snate@binkert.org 1518232Snate@binkert.org if (linkDelay > 0) { 1528229Snate@binkert.org DPRINTF(Ethernet, "packet delayed: delay=%d\n", linkDelay); 1533536SN/A txQueue.emplace_back(std::make_pair(curTick() + linkDelay, packet)); 1543536SN/A if (!txQueueEvent.scheduled()) 1558782Sgblack@eecs.umich.edu parent->schedule(txQueueEvent, txQueue.front().first); 1563536SN/A } else { 1573536SN/A assert(txQueue.empty()); 1583536SN/A txComplete(packet); 1597752SWilliam.Wang@arm.com } 1603536SN/A 1615569SN/A packet = 0; 1627752SWilliam.Wang@arm.com assert(!busy()); 1633536SN/A 1643536SN/A txint->sendDone(); 1653536SN/A} 1665569SN/A 1675569SN/Avoid 1685569SN/AEtherLink::Link::processTxQueue() 1693536SN/A{ 1703536SN/A auto cur(txQueue.front()); 1713536SN/A txQueue.pop_front(); 1728782Sgblack@eecs.umich.edu 1738782Sgblack@eecs.umich.edu // Schedule a new event to process the next packet in the queue. 1748782Sgblack@eecs.umich.edu if (!txQueue.empty()) { 1758782Sgblack@eecs.umich.edu auto next(txQueue.front()); 1763536SN/A assert(next.first > curTick()); 1778782Sgblack@eecs.umich.edu parent->schedule(txQueueEvent, next.first); 1788782Sgblack@eecs.umich.edu } 1798782Sgblack@eecs.umich.edu 1808782Sgblack@eecs.umich.edu assert(cur.first == curTick()); 1818782Sgblack@eecs.umich.edu txComplete(cur.second); 1828782Sgblack@eecs.umich.edu} 1838782Sgblack@eecs.umich.edu 1848782Sgblack@eecs.umich.edubool 1858782Sgblack@eecs.umich.eduEtherLink::Link::transmit(EthPacketPtr pkt) 1868782Sgblack@eecs.umich.edu{ 1878782Sgblack@eecs.umich.edu if (busy()) { 1888782Sgblack@eecs.umich.edu DPRINTF(Ethernet, "packet not sent, link busy\n"); 1898782Sgblack@eecs.umich.edu return false; 1908782Sgblack@eecs.umich.edu } 1913536SN/A 1928782Sgblack@eecs.umich.edu DPRINTF(Ethernet, "packet sent: len=%d\n", pkt->length); 1938782Sgblack@eecs.umich.edu DDUMP(EthernetData, pkt->data, pkt->length); 1943536SN/A 1953536SN/A packet = pkt; 1965569SN/A Tick delay = (Tick)ceil(((double)pkt->simLength * ticksPerByte) + 1.0); 1975569SN/A if (delayVar != 0) 1985569SN/A delay += random_mt.random<Tick>(0, delayVar); 1995569SN/A 2003536SN/A DPRINTF(Ethernet, "scheduling packet: delay=%d, (rate=%f)\n", 2013536SN/A delay, ticksPerByte); 2023536SN/A parent->schedule(doneEvent, curTick() + delay); 2037752SWilliam.Wang@arm.com 2047752SWilliam.Wang@arm.com return true; 2053579SN/A} 2063536SN/A 2077752SWilliam.Wang@arm.comvoid 2087752SWilliam.Wang@arm.comEtherLink::Link::serialize(const string &base, CheckpointOut &cp) const 2097752SWilliam.Wang@arm.com{ 2107752SWilliam.Wang@arm.com bool packet_exists = packet != nullptr; 2117752SWilliam.Wang@arm.com paramOut(cp, base + ".packet_exists", packet_exists); 2127752SWilliam.Wang@arm.com if (packet_exists) 2137752SWilliam.Wang@arm.com packet->serialize(base + ".packet", cp); 2147752SWilliam.Wang@arm.com 2157752SWilliam.Wang@arm.com bool event_scheduled = doneEvent.scheduled(); 2167752SWilliam.Wang@arm.com paramOut(cp, base + ".event_scheduled", event_scheduled); 2177752SWilliam.Wang@arm.com if (event_scheduled) { 2187752SWilliam.Wang@arm.com Tick event_time = doneEvent.when(); 2197752SWilliam.Wang@arm.com paramOut(cp, base + ".event_time", event_time); 2207752SWilliam.Wang@arm.com } 2217752SWilliam.Wang@arm.com 2227752SWilliam.Wang@arm.com const size_t tx_queue_size(txQueue.size()); 2237752SWilliam.Wang@arm.com paramOut(cp, base + ".tx_queue_size", tx_queue_size); 2247752SWilliam.Wang@arm.com unsigned idx(0); 2257752SWilliam.Wang@arm.com for (const auto &pe : txQueue) { 2263536SN/A paramOut(cp, csprintf("%s.txQueue[%i].tick", base, idx), pe.first); 2277752SWilliam.Wang@arm.com pe.second->serialize(csprintf("%s.txQueue[%i].packet", base, idx), cp); 2287752SWilliam.Wang@arm.com 2297752SWilliam.Wang@arm.com ++idx; 2307752SWilliam.Wang@arm.com } 2317752SWilliam.Wang@arm.com} 2327752SWilliam.Wang@arm.com 2337752SWilliam.Wang@arm.comvoid 2347752SWilliam.Wang@arm.comEtherLink::Link::unserialize(const string &base, CheckpointIn &cp) 2357752SWilliam.Wang@arm.com{ 2367752SWilliam.Wang@arm.com bool packet_exists; 2377752SWilliam.Wang@arm.com paramIn(cp, base + ".packet_exists", packet_exists); 2387752SWilliam.Wang@arm.com if (packet_exists) { 2397752SWilliam.Wang@arm.com packet = make_shared<EthPacketData>(); 2403536SN/A packet->unserialize(base + ".packet", cp); 2413536SN/A } 2427752SWilliam.Wang@arm.com 2437752SWilliam.Wang@arm.com bool event_scheduled; 2447752SWilliam.Wang@arm.com paramIn(cp, base + ".event_scheduled", event_scheduled); 2457752SWilliam.Wang@arm.com if (event_scheduled) { 2463536SN/A Tick event_time; 2473536SN/A paramIn(cp, base + ".event_time", event_time); 2485569SN/A parent->schedule(doneEvent, event_time); 2495569SN/A } 2505569SN/A 2515569SN/A size_t tx_queue_size; 2523536SN/A if (optParamIn(cp, base + ".tx_queue_size", tx_queue_size)) { 2533536SN/A for (size_t idx = 0; idx < tx_queue_size; ++idx) { 2543536SN/A Tick tick; 2557752SWilliam.Wang@arm.com EthPacketPtr delayed_packet = make_shared<EthPacketData>(); 2567752SWilliam.Wang@arm.com 2577752SWilliam.Wang@arm.com paramIn(cp, csprintf("%s.txQueue[%i].tick", base, idx), tick); 2587752SWilliam.Wang@arm.com delayed_packet->unserialize( 2597752SWilliam.Wang@arm.com csprintf("%s.txQueue[%i].packet", base, idx), cp); 2607752SWilliam.Wang@arm.com 2617752SWilliam.Wang@arm.com fatal_if(!txQueue.empty() && txQueue.back().first > tick, 2627752SWilliam.Wang@arm.com "Invalid txQueue packet order in EtherLink!\n"); 2637752SWilliam.Wang@arm.com txQueue.emplace_back(std::make_pair(tick, delayed_packet)); 2647752SWilliam.Wang@arm.com } 2657752SWilliam.Wang@arm.com 2667752SWilliam.Wang@arm.com if (!txQueue.empty()) 2677752SWilliam.Wang@arm.com parent->schedule(txQueueEvent, txQueue.front().first); 2687752SWilliam.Wang@arm.com } else { 2697752SWilliam.Wang@arm.com // We can't reliably convert in-flight packets from old 2707752SWilliam.Wang@arm.com // checkpoints. In fact, gem5 hasn't been able to load these 2717752SWilliam.Wang@arm.com // packets for at least two years before the format change. 2727752SWilliam.Wang@arm.com warn("Old-style EtherLink serialization format detected, " 2737752SWilliam.Wang@arm.com "in-flight packets may have been dropped.\n"); 2747752SWilliam.Wang@arm.com } 2757752SWilliam.Wang@arm.com} 2767752SWilliam.Wang@arm.com 2777752SWilliam.Wang@arm.comEtherLink * 2787752SWilliam.Wang@arm.comEtherLinkParams::create() 2797752SWilliam.Wang@arm.com{ 2807752SWilliam.Wang@arm.com return new EtherLink(this); 2817752SWilliam.Wang@arm.com} 2827752SWilliam.Wang@arm.com