etherlink.cc revision 2665
12068SN/A/* 22068SN/A * Copyright (c) 2002-2005 The Regents of The University of Michigan 32188SN/A * All rights reserved. 42068SN/A * 52068SN/A * Redistribution and use in source and binary forms, with or without 62068SN/A * modification, are permitted provided that the following conditions are 72068SN/A * met: redistributions of source code must retain the above copyright 82068SN/A * notice, this list of conditions and the following disclaimer; 92068SN/A * redistributions in binary form must reproduce the above copyright 102068SN/A * notice, this list of conditions and the following disclaimer in the 112068SN/A * documentation and/or other materials provided with the distribution; 122068SN/A * neither the name of the copyright holders nor the names of its 132068SN/A * contributors may be used to endorse or promote products derived from 142068SN/A * this software without specific prior written permission. 152068SN/A * 162068SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172068SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182068SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192068SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202068SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212068SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222068SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232068SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242068SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252068SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262068SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272068SN/A * 282665Ssaidi@eecs.umich.edu * Authors: Nathan Binkert 292665Ssaidi@eecs.umich.edu * Ron Dreslinski 302068SN/A */ 312649Ssaidi@eecs.umich.edu 322649Ssaidi@eecs.umich.edu/* @file 332649Ssaidi@eecs.umich.edu * Device module for modelling a fixed bandwidth full duplex ethernet link 342649Ssaidi@eecs.umich.edu */ 352649Ssaidi@eecs.umich.edu 362068SN/A#include <cmath> 372068SN/A#include <deque> 382068SN/A#include <string> 392068SN/A#include <vector> 402068SN/A 412068SN/A#include "base/random.hh" 422068SN/A#include "base/trace.hh" 432068SN/A#include "dev/etherdump.hh" 448588Sgblack@eecs.umich.edu#include "dev/etherint.hh" 458588Sgblack@eecs.umich.edu#include "dev/etherlink.hh" 468588Sgblack@eecs.umich.edu#include "dev/etherpkt.hh" 478588Sgblack@eecs.umich.edu#include "sim/builder.hh" 488588Sgblack@eecs.umich.edu#include "sim/serialize.hh" 498588Sgblack@eecs.umich.edu#include "sim/system.hh" 502068SN/A#include "sim/root.hh" 512068SN/A 522068SN/Ausing namespace std; 538588Sgblack@eecs.umich.edu 548588Sgblack@eecs.umich.eduEtherLink::EtherLink(const string &name, EtherInt *peer0, EtherInt *peer1, 552068SN/A double rate, Tick delay, Tick delayVar, EtherDump *dump) 562068SN/A : SimObject(name) 578588Sgblack@eecs.umich.edu{ 582075SN/A link[0] = new Link(name + ".link0", this, 0, rate, delay, delayVar, dump); 592068SN/A link[1] = new Link(name + ".link1", this, 1, rate, delay, delayVar, dump); 602068SN/A 612068SN/A interface[0] = new Interface(name + ".int0", link[0], link[1]); 628588Sgblack@eecs.umich.edu interface[1] = new Interface(name + ".int1", link[1], link[0]); 638588Sgblack@eecs.umich.edu 648588Sgblack@eecs.umich.edu interface[0]->setPeer(peer0); 658588Sgblack@eecs.umich.edu peer0->setPeer(interface[0]); 668588Sgblack@eecs.umich.edu interface[1]->setPeer(peer1); 678588Sgblack@eecs.umich.edu peer1->setPeer(interface[1]); 688588Sgblack@eecs.umich.edu} 692068SN/A 702068SN/AEtherLink::~EtherLink() 712068SN/A{ 728588Sgblack@eecs.umich.edu delete link[0]; 732068SN/A delete link[1]; 742069SN/A 752068SN/A delete interface[0]; 762068SN/A delete interface[1]; 774027Sstever@eecs.umich.edu} 784027Sstever@eecs.umich.edu 794027Sstever@eecs.umich.eduEtherLink::Interface::Interface(const string &name, Link *tx, Link *rx) 806076Sgblack@eecs.umich.edu : EtherInt(name), txlink(tx) 818588Sgblack@eecs.umich.edu{ 822068SN/A tx->setTxInt(this); 832069SN/A rx->setRxInt(this); 842068SN/A} 852068SN/A 862068SN/AEtherLink::Link::Link(const string &name, EtherLink *p, int num, 872068SN/A double rate, Tick delay, Tick delay_var, EtherDump *d) 882068SN/A : objName(name), parent(p), number(num), txint(NULL), rxint(NULL), 892068SN/A ticksPerByte(rate), linkDelay(delay), delayVar(delay_var), dump(d), 902068SN/A doneEvent(this) 912068SN/A{ } 924027Sstever@eecs.umich.edu 934027Sstever@eecs.umich.eduvoid 944027Sstever@eecs.umich.eduEtherLink::serialize(ostream &os) 954027Sstever@eecs.umich.edu{ 964027Sstever@eecs.umich.edu link[0]->serialize("link0", os); 974027Sstever@eecs.umich.edu link[1]->serialize("link1", os); 986076Sgblack@eecs.umich.edu} 992068SN/A 1002068SN/Avoid 1012068SN/AEtherLink::unserialize(Checkpoint *cp, const string §ion) 1022068SN/A{ 1037799Sgblack@eecs.umich.edu link[0]->unserialize("link0", cp, section); 1042068SN/A link[1]->unserialize("link1", cp, section); 1058588Sgblack@eecs.umich.edu} 1062068SN/A 1078588Sgblack@eecs.umich.eduvoid 1082068SN/AEtherLink::Link::txComplete(EthPacketPtr packet) 1092068SN/A{ 1108588Sgblack@eecs.umich.edu DPRINTF(Ethernet, "packet received: len=%d\n", packet->length); 1112147SN/A DDUMP(EthernetData, packet->data, packet->length); 1128588Sgblack@eecs.umich.edu rxint->sendPacket(packet); 1132068SN/A} 1148588Sgblack@eecs.umich.edu 1158588Sgblack@eecs.umich.educlass LinkDelayEvent : public Event 1162068SN/A{ 1172068SN/A protected: 1182068SN/A EtherLink::Link *link; 1192068SN/A EthPacketPtr packet; 1202068SN/A 1212068SN/A public: 1222068SN/A // non-scheduling version for createForUnserialize() 1232147SN/A LinkDelayEvent(); 1242068SN/A LinkDelayEvent(EtherLink::Link *link, EthPacketPtr pkt, Tick when); 1252068SN/A 1262068SN/A void process(); 1272068SN/A 1282068SN/A virtual void serialize(ostream &os); 1298588Sgblack@eecs.umich.edu virtual void unserialize(Checkpoint *cp, const string §ion); 1302068SN/A static Serializable *createForUnserialize(Checkpoint *cp, 1318588Sgblack@eecs.umich.edu const string §ion); 1322068SN/A}; 1332068SN/A 1342068SN/Avoid 1352068SN/AEtherLink::Link::txDone() 1368588Sgblack@eecs.umich.edu{ 1372147SN/A if (dump) 1388588Sgblack@eecs.umich.edu dump->dump(packet); 1392068SN/A 1408588Sgblack@eecs.umich.edu if (linkDelay > 0) { 1418588Sgblack@eecs.umich.edu DPRINTF(Ethernet, "packet delayed: delay=%d\n", linkDelay); 1422068SN/A new LinkDelayEvent(this, packet, curTick + linkDelay); 1432068SN/A } else { 1442068SN/A txComplete(packet); 1452068SN/A } 1462068SN/A 1472068SN/A packet = 0; 1482068SN/A assert(!busy()); 1492068SN/A 1502068SN/A txint->sendDone(); 1512147SN/A} 1522068SN/A 1532068SN/Abool 1542068SN/AEtherLink::Link::transmit(EthPacketPtr pkt) 1552068SN/A{ 1562068SN/A if (busy()) { 1572068SN/A DPRINTF(Ethernet, "packet not sent, link busy\n"); 1588588Sgblack@eecs.umich.edu return false; 1598588Sgblack@eecs.umich.edu } 1608588Sgblack@eecs.umich.edu 1618588Sgblack@eecs.umich.edu DPRINTF(Ethernet, "packet sent: len=%d\n", pkt->length); 1622068SN/A DDUMP(EthernetData, pkt->data, pkt->length); 1632068SN/A 1642068SN/A packet = pkt; 1652068SN/A Tick delay = (Tick)ceil(((double)pkt->length * ticksPerByte) + 1.0); 1662068SN/A if (delayVar != 0) { 1672068SN/A Random<Tick> var; 1688588Sgblack@eecs.umich.edu delay += var.uniform(0, delayVar); 1692068SN/A } 1702068SN/A DPRINTF(Ethernet, "scheduling packet: delay=%d, (rate=%f)\n", 1712068SN/A delay, ticksPerByte); 1722068SN/A doneEvent.schedule(curTick + delay); 1732068SN/A 1742068SN/A return true; 1752068SN/A} 1767799Sgblack@eecs.umich.edu 1772068SN/Avoid 1782068SN/AEtherLink::Link::serialize(const string &base, ostream &os) 1792068SN/A{ 1802068SN/A bool packet_exists = packet; 1812068SN/A paramOut(os, base + ".packet_exists", packet_exists); 1822068SN/A if (packet_exists) 1832068SN/A packet->serialize(base + ".packet", os); 1842068SN/A 1852068SN/A bool event_scheduled = doneEvent.scheduled(); 1862068SN/A paramOut(os, base + ".event_scheduled", event_scheduled); 1872068SN/A if (event_scheduled) { 1882068SN/A Tick event_time = doneEvent.when(); 1892068SN/A paramOut(os, base + ".event_time", event_time); 1908588Sgblack@eecs.umich.edu } 1918588Sgblack@eecs.umich.edu 1928588Sgblack@eecs.umich.edu} 1938588Sgblack@eecs.umich.edu 1942068SN/Avoid 1952068SN/AEtherLink::Link::unserialize(const string &base, Checkpoint *cp, 1962068SN/A const string §ion) 1972068SN/A{ 1982068SN/A bool packet_exists; 1992068SN/A paramIn(cp, section, base + ".packet_exists", packet_exists); 2002068SN/A if (packet_exists) { 2012068SN/A packet = new EthPacketData(16384); 2022068SN/A packet->unserialize(base + ".packet", cp, section); 2032068SN/A } 2042068SN/A 2052068SN/A bool event_scheduled; 2068560Sgblack@eecs.umich.edu paramIn(cp, section, base + ".event_scheduled", event_scheduled); 2072068SN/A if (event_scheduled) { 2082068SN/A Tick event_time; 2092068SN/A paramIn(cp, section, base + ".event_time", event_time); 2102068SN/A doneEvent.schedule(event_time); 2112068SN/A } 2122068SN/A} 2132068SN/A 2142068SN/ALinkDelayEvent::LinkDelayEvent() 2152068SN/A : Event(&mainEventQueue), link(NULL) 2162068SN/A{ 2178588Sgblack@eecs.umich.edu setFlags(AutoSerialize); 2188588Sgblack@eecs.umich.edu setFlags(AutoDelete); 2192068SN/A} 2202068SN/A 2212068SN/ALinkDelayEvent::LinkDelayEvent(EtherLink::Link *l, EthPacketPtr p, Tick when) 2222068SN/A : Event(&mainEventQueue), link(l), packet(p) 2232068SN/A{ 2242068SN/A setFlags(AutoSerialize); 2252068SN/A setFlags(AutoDelete); 2262068SN/A schedule(when); 2272068SN/A} 2282068SN/A 2292068SN/Avoid 2302068SN/ALinkDelayEvent::process() 2312068SN/A{ 2322068SN/A link->txComplete(packet); 2332068SN/A} 2342068SN/A 2352068SN/Avoid 2362068SN/ALinkDelayEvent::serialize(ostream &os) 2372068SN/A{ 2388588Sgblack@eecs.umich.edu paramOut(os, "type", string("LinkDelayEvent")); 2398588Sgblack@eecs.umich.edu Event::serialize(os); 2408588Sgblack@eecs.umich.edu 2418588Sgblack@eecs.umich.edu EtherLink *parent = link->parent; 2422068SN/A bool number = link->number; 2432068SN/A SERIALIZE_OBJPTR(parent); 2442068SN/A SERIALIZE_SCALAR(number); 2452068SN/A 2462068SN/A packet->serialize("packet", os); 2472068SN/A} 2482068SN/A 2492068SN/A 2502068SN/Avoid 2512068SN/ALinkDelayEvent::unserialize(Checkpoint *cp, const string §ion) 2522068SN/A{ 2532068SN/A Event::unserialize(cp, section); 2542068SN/A 2552068SN/A EtherLink *parent; 2562068SN/A bool number; 2578588Sgblack@eecs.umich.edu UNSERIALIZE_OBJPTR(parent); 2582068SN/A UNSERIALIZE_SCALAR(number); 2592068SN/A 2602068SN/A link = parent->link[number]; 2618588Sgblack@eecs.umich.edu 2622068SN/A packet = new EthPacketData(16384); 2632068SN/A packet->unserialize("packet", cp, section); 2642068SN/A} 2658588Sgblack@eecs.umich.edu 2662068SN/A 2672068SN/ASerializable * 2682068SN/ALinkDelayEvent::createForUnserialize(Checkpoint *cp, const string §ion) 2692068SN/A{ 2702068SN/A return new LinkDelayEvent(); 2712068SN/A} 2722068SN/A 2732068SN/AREGISTER_SERIALIZEABLE("LinkDelayEvent", LinkDelayEvent) 2742068SN/A 2752068SN/ABEGIN_DECLARE_SIM_OBJECT_PARAMS(EtherLink) 2762068SN/A 2772068SN/A SimObjectParam<EtherInt *> int1; 2782068SN/A SimObjectParam<EtherInt *> int2; 2792068SN/A Param<double> speed; 2802068SN/A Param<Tick> delay; 2812068SN/A Param<Tick> delay_var; 2822068SN/A SimObjectParam<EtherDump *> dump; 2832068SN/A 2842068SN/AEND_DECLARE_SIM_OBJECT_PARAMS(EtherLink) 2852068SN/A 2867799Sgblack@eecs.umich.eduBEGIN_INIT_SIM_OBJECT_PARAMS(EtherLink) 2878588Sgblack@eecs.umich.edu 2882068SN/A INIT_PARAM(int1, "interface 1"), 2892068SN/A INIT_PARAM(int2, "interface 2"), 2902068SN/A INIT_PARAM(speed, "link speed in bits per second"), 2912068SN/A INIT_PARAM(delay, "transmit delay of packets in us"), 2922068SN/A INIT_PARAM(delay_var, "Difference in amount of time to traverse wire"), 2932068SN/A INIT_PARAM(dump, "object to dump network packets to") 2942068SN/A 2952068SN/AEND_INIT_SIM_OBJECT_PARAMS(EtherLink) 2968588Sgblack@eecs.umich.edu 2978588Sgblack@eecs.umich.eduCREATE_SIM_OBJECT(EtherLink) 2982068SN/A{ 2992068SN/A return new EtherLink(getInstanceName(), int1, int2, speed, delay, delay_var, 3002068SN/A dump); 3012068SN/A} 3022068SN/A 3032068SN/AREGISTER_SIM_OBJECT("EtherLink", EtherLink) 3042147SN/A