etherlink.cc revision 11071
11689SN/A/* 27598Sminkyu.jeong@arm.com * Copyright (c) 2015 ARM Limited 37598Sminkyu.jeong@arm.com * All rights reserved 47598Sminkyu.jeong@arm.com * 57598Sminkyu.jeong@arm.com * The license below extends only to copyright in the software and shall 67598Sminkyu.jeong@arm.com * not be construed as granting a license to any other intellectual 77598Sminkyu.jeong@arm.com * property including but not limited to intellectual property relating 87598Sminkyu.jeong@arm.com * to a hardware implementation of the functionality of the software 97598Sminkyu.jeong@arm.com * licensed hereunder. You may use the software subject to the license 107598Sminkyu.jeong@arm.com * terms below provided that you ensure that this notice is replicated 117598Sminkyu.jeong@arm.com * unmodified and in its entirety in all distributions of the software, 127598Sminkyu.jeong@arm.com * modified or unmodified, in source code or in binary form. 137598Sminkyu.jeong@arm.com * 142326SN/A * Copyright (c) 2002-2005 The Regents of The University of Michigan 151689SN/A * All rights reserved. 161689SN/A * 171689SN/A * Redistribution and use in source and binary forms, with or without 181689SN/A * modification, are permitted provided that the following conditions are 191689SN/A * met: redistributions of source code must retain the above copyright 201689SN/A * notice, this list of conditions and the following disclaimer; 211689SN/A * redistributions in binary form must reproduce the above copyright 221689SN/A * notice, this list of conditions and the following disclaimer in the 231689SN/A * documentation and/or other materials provided with the distribution; 241689SN/A * neither the name of the copyright holders nor the names of its 251689SN/A * contributors may be used to endorse or promote products derived from 261689SN/A * this software without specific prior written permission. 271689SN/A * 281689SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 291689SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 301689SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 311689SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 321689SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 331689SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 341689SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 351689SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 361689SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 371689SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 381689SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 392665Ssaidi@eecs.umich.edu * 402665Ssaidi@eecs.umich.edu * Authors: Nathan Binkert 411689SN/A * Ron Dreslinski 421689SN/A */ 431060SN/A 441060SN/A/* @file 451689SN/A * Device module for modelling a fixed bandwidth full duplex ethernet link 461060SN/A */ 471060SN/A 481060SN/A#include <cmath> 498230Snate@binkert.org#include <deque> 506658Snate@binkert.org#include <string> 512292SN/A#include <vector> 521717SN/A 538229Snate@binkert.org#include "base/random.hh" 548232Snate@binkert.org#include "base/trace.hh" 558232Snate@binkert.org#include "debug/Ethernet.hh" 568232Snate@binkert.org#include "debug/EthernetData.hh" 575529Snate@binkert.org#include "dev/etherdump.hh" 581060SN/A#include "dev/etherint.hh" 596221Snate@binkert.org#include "dev/etherlink.hh" 606221Snate@binkert.org#include "dev/etherpkt.hh" 611681SN/A#include "params/EtherLink.hh" 625529Snate@binkert.org#include "sim/core.hh" 632873Sktlim@umich.edu#include "sim/serialize.hh" 644329Sktlim@umich.edu#include "sim/system.hh" 654329Sktlim@umich.edu 664329Sktlim@umich.eduusing namespace std; 672292SN/A 682292SN/AEtherLink::EtherLink(const Params *p) 692292SN/A : EtherObject(p) 702292SN/A{ 712820Sktlim@umich.edu link[0] = new Link(name() + ".link0", this, 0, p->speed, 722292SN/A p->delay, p->delay_var, p->dump); 732820Sktlim@umich.edu link[1] = new Link(name() + ".link1", this, 1, p->speed, 742820Sktlim@umich.edu p->delay, p->delay_var, p->dump); 755529Snate@binkert.org 762307SN/A interface[0] = new Interface(name() + ".int0", link[0], link[1]); 771060SN/A interface[1] = new Interface(name() + ".int1", link[1], link[0]); 782292SN/A} 792292SN/A 802292SN/A 811060SN/AEtherLink::~EtherLink() 821060SN/A{ 831060SN/A delete link[0]; 841060SN/A delete link[1]; 851060SN/A 861060SN/A delete interface[0]; 871681SN/A delete interface[1]; 886221Snate@binkert.org} 896221Snate@binkert.org 906221Snate@binkert.orgEtherInt* 916221Snate@binkert.orgEtherLink::getEthPort(const std::string &if_name, int idx) 922292SN/A{ 932292SN/A Interface *i; 942820Sktlim@umich.edu if (if_name == "int0") 952820Sktlim@umich.edu i = interface[0]; 962292SN/A else if (if_name == "int1") 972292SN/A i = interface[1]; 982820Sktlim@umich.edu else 992820Sktlim@umich.edu return NULL; 1002292SN/A if (i->getPeer()) 1012292SN/A panic("interface already connected to\n"); 1022292SN/A 1032292SN/A return i; 1042292SN/A} 1052292SN/A 1062292SN/A 1072292SN/AEtherLink::Interface::Interface(const string &name, Link *tx, Link *rx) 1081060SN/A : EtherInt(name), txlink(tx) 1091060SN/A{ 1101681SN/A tx->setTxInt(this); 1111062SN/A rx->setRxInt(this); 1122292SN/A} 1131062SN/A 1142301SN/AEtherLink::Link::Link(const string &name, EtherLink *p, int num, 1152301SN/A double rate, Tick delay, Tick delay_var, EtherDump *d) 1161062SN/A : objName(name), parent(p), number(num), txint(NULL), rxint(NULL), 1172727Sktlim@umich.edu ticksPerByte(rate), linkDelay(delay), delayVar(delay_var), dump(d), 1181062SN/A doneEvent(this), txQueueEvent(this) 1191062SN/A{ } 1201062SN/A 1211062SN/Avoid 1221062SN/AEtherLink::serialize(CheckpointOut &cp) const 1231062SN/A{ 1241062SN/A link[0]->serialize("link0", cp); 1251062SN/A link[1]->serialize("link1", cp); 1261062SN/A} 1271062SN/A 1281062SN/Avoid 1291062SN/AEtherLink::unserialize(CheckpointIn &cp) 1301062SN/A{ 1311062SN/A link[0]->unserialize("link0", cp); 1321062SN/A link[1]->unserialize("link1", cp); 1331062SN/A} 1341062SN/A 1351062SN/Avoid 1361062SN/AEtherLink::Link::txComplete(EthPacketPtr packet) 1371062SN/A{ 1381062SN/A DPRINTF(Ethernet, "packet received: len=%d\n", packet->length); 1391062SN/A DDUMP(EthernetData, packet->data, packet->length); 1401062SN/A rxint->sendPacket(packet); 1411062SN/A} 1421062SN/A 1431062SN/Avoid 1441062SN/AEtherLink::Link::txDone() 1451062SN/A{ 1461062SN/A if (dump) 1471062SN/A dump->dump(packet); 1481062SN/A 1491062SN/A if (linkDelay > 0) { 1501062SN/A DPRINTF(Ethernet, "packet delayed: delay=%d\n", linkDelay); 1511062SN/A txQueue.emplace_back(std::make_pair(curTick() + linkDelay, packet)); 1521062SN/A if (!txQueueEvent.scheduled()) 1531062SN/A parent->schedule(txQueueEvent, txQueue.front().first); 1541062SN/A } else { 1551062SN/A assert(txQueue.empty()); 1561062SN/A txComplete(packet); 1571062SN/A } 1581062SN/A 1592292SN/A packet = 0; 1602292SN/A assert(!busy()); 1612292SN/A 1622292SN/A txint->sendDone(); 1631062SN/A} 1641062SN/A 1651062SN/Avoid 1661062SN/AEtherLink::Link::processTxQueue() 1671062SN/A{ 1681062SN/A auto cur(txQueue.front()); 1691062SN/A txQueue.pop_front(); 1702292SN/A 1712292SN/A // Schedule a new event to process the next packet in the queue. 1722292SN/A if (!txQueue.empty()) { 1732292SN/A auto next(txQueue.front()); 1742292SN/A assert(next.first > curTick()); 1752292SN/A parent->schedule(txQueueEvent, next.first); 1762292SN/A } 1772292SN/A 1782292SN/A assert(cur.first == curTick()); 1792292SN/A txComplete(cur.second); 1802301SN/A} 1812727Sktlim@umich.edu 1822353SN/Abool 1832727Sktlim@umich.eduEtherLink::Link::transmit(EthPacketPtr pkt) 1842727Sktlim@umich.edu{ 1852727Sktlim@umich.edu if (busy()) { 1866221Snate@binkert.org DPRINTF(Ethernet, "packet not sent, link busy\n"); 1872353SN/A return false; 1882727Sktlim@umich.edu } 1892727Sktlim@umich.edu 1902727Sktlim@umich.edu DPRINTF(Ethernet, "packet sent: len=%d\n", pkt->length); 1912727Sktlim@umich.edu DDUMP(EthernetData, pkt->data, pkt->length); 1922353SN/A 1932727Sktlim@umich.edu packet = pkt; 1942727Sktlim@umich.edu Tick delay = (Tick)ceil(((double)pkt->length * ticksPerByte) + 1.0); 1952727Sktlim@umich.edu if (delayVar != 0) 1966221Snate@binkert.org delay += random_mt.random<Tick>(0, delayVar); 1972301SN/A 1982301SN/A DPRINTF(Ethernet, "scheduling packet: delay=%d, (rate=%f)\n", 1992727Sktlim@umich.edu delay, ticksPerByte); 2002301SN/A parent->schedule(doneEvent, curTick() + delay); 2012727Sktlim@umich.edu 2026221Snate@binkert.org return true; 2032301SN/A} 2042301SN/A 2052727Sktlim@umich.eduvoid 2062301SN/AEtherLink::Link::serialize(const string &base, CheckpointOut &cp) const 2072727Sktlim@umich.edu{ 2086221Snate@binkert.org bool packet_exists = packet != nullptr; 2092301SN/A paramOut(cp, base + ".packet_exists", packet_exists); 2102301SN/A if (packet_exists) 2112727Sktlim@umich.edu packet->serialize(base + ".packet", cp); 2122301SN/A 2132727Sktlim@umich.edu bool event_scheduled = doneEvent.scheduled(); 2146221Snate@binkert.org paramOut(cp, base + ".event_scheduled", event_scheduled); 2152301SN/A if (event_scheduled) { 2162301SN/A Tick event_time = doneEvent.when(); 2172727Sktlim@umich.edu paramOut(cp, base + ".event_time", event_time); 2182301SN/A } 2192301SN/A 2202301SN/A const size_t tx_queue_size(txQueue.size()); 2212301SN/A paramOut(cp, base + ".tx_queue_size", tx_queue_size); 2222727Sktlim@umich.edu unsigned idx(0); 2232727Sktlim@umich.edu for (const auto &pe : txQueue) { 2242727Sktlim@umich.edu paramOut(cp, csprintf("%s.txQueue[%i].tick", base, idx), pe.first); 2252727Sktlim@umich.edu pe.second->serialize(csprintf("%s.txQueue[%i].packet", base, idx), cp); 2262727Sktlim@umich.edu 2272727Sktlim@umich.edu ++idx; 2282727Sktlim@umich.edu } 2292727Sktlim@umich.edu} 2302727Sktlim@umich.edu 2312301SN/Avoid 2322301SN/AEtherLink::Link::unserialize(const string &base, CheckpointIn &cp) 2336221Snate@binkert.org{ 2342301SN/A bool packet_exists; 2352301SN/A paramIn(cp, base + ".packet_exists", packet_exists); 2362727Sktlim@umich.edu if (packet_exists) { 2372301SN/A packet = make_shared<EthPacketData>(16384); 2382326SN/A packet->unserialize(base + ".packet", cp); 2396221Snate@binkert.org } 2402301SN/A 2412301SN/A bool event_scheduled; 2422727Sktlim@umich.edu paramIn(cp, base + ".event_scheduled", event_scheduled); 2432301SN/A if (event_scheduled) { 2442326SN/A Tick event_time; 2456221Snate@binkert.org paramIn(cp, base + ".event_time", event_time); 2462301SN/A parent->schedule(doneEvent, event_time); 2472301SN/A } 2482727Sktlim@umich.edu 2492301SN/A size_t tx_queue_size; 2502326SN/A if (optParamIn(cp, base + ".tx_queue_size", tx_queue_size)) { 2516221Snate@binkert.org for (size_t idx = 0; idx < tx_queue_size; ++idx) { 2522301SN/A Tick tick; 2532301SN/A EthPacketPtr delayed_packet = make_shared<EthPacketData>(16384); 2542727Sktlim@umich.edu 2552301SN/A paramIn(cp, csprintf("%s.txQueue[%i].tick", base, idx), tick); 2562326SN/A delayed_packet->unserialize( 2576221Snate@binkert.org csprintf("%s.txQueue[%i].packet", base, idx), cp); 2582301SN/A 2592301SN/A fatal_if(!txQueue.empty() && txQueue.back().first > tick, 2602727Sktlim@umich.edu "Invalid txQueue packet order in EtherLink!\n"); 2612301SN/A txQueue.emplace_back(std::make_pair(tick, delayed_packet)); 2622326SN/A } 2632301SN/A 2642301SN/A if (!txQueue.empty()) 2652727Sktlim@umich.edu parent->schedule(txQueueEvent, txQueue.front().first); 2662301SN/A } else { 2672326SN/A // We can't reliably convert in-flight packets from old 2682301SN/A // checkpoints. In fact, gem5 hasn't been able to load these 2692326SN/A // packets for at least two years before the format change. 2702301SN/A warn("Old-style EtherLink serialization format detected, " 2712301SN/A "in-flight packets may have been dropped.\n"); 2722727Sktlim@umich.edu } 2732301SN/A} 2742326SN/A 2752301SN/AEtherLink * 2762326SN/AEtherLinkParams::create() 2772301SN/A{ 2782301SN/A return new EtherLink(this); 2792727Sktlim@umich.edu} 2802326SN/A