etherlink.cc revision 2665
1955SN/A/* 2955SN/A * Copyright (c) 2002-2005 The Regents of The University of Michigan 31762SN/A * All rights reserved. 4955SN/A * 5955SN/A * Redistribution and use in source and binary forms, with or without 6955SN/A * modification, are permitted provided that the following conditions are 7955SN/A * met: redistributions of source code must retain the above copyright 8955SN/A * notice, this list of conditions and the following disclaimer; 9955SN/A * redistributions in binary form must reproduce the above copyright 10955SN/A * notice, this list of conditions and the following disclaimer in the 11955SN/A * documentation and/or other materials provided with the distribution; 12955SN/A * neither the name of the copyright holders nor the names of its 13955SN/A * contributors may be used to endorse or promote products derived from 14955SN/A * this software without specific prior written permission. 15955SN/A * 16955SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17955SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18955SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19955SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20955SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21955SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22955SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23955SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24955SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25955SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26955SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27955SN/A * 282665Ssaidi@eecs.umich.edu * Authors: Nathan Binkert 292665Ssaidi@eecs.umich.edu * Ron Dreslinski 30955SN/A */ 31955SN/A 32955SN/A/* @file 331608SN/A * Device module for modelling a fixed bandwidth full duplex ethernet link 34955SN/A */ 35955SN/A 36955SN/A#include <cmath> 37955SN/A#include <deque> 38955SN/A#include <string> 39955SN/A#include <vector> 40955SN/A 41955SN/A#include "base/random.hh" 42955SN/A#include "base/trace.hh" 43955SN/A#include "dev/etherdump.hh" 44955SN/A#include "dev/etherint.hh" 45955SN/A#include "dev/etherlink.hh" 46955SN/A#include "dev/etherpkt.hh" 47955SN/A#include "sim/builder.hh" 482023SN/A#include "sim/serialize.hh" 49955SN/A#include "sim/system.hh" 50955SN/A#include "sim/root.hh" 51955SN/A 52955SN/Ausing namespace std; 53955SN/A 54955SN/AEtherLink::EtherLink(const string &name, EtherInt *peer0, EtherInt *peer1, 55955SN/A double rate, Tick delay, Tick delayVar, EtherDump *dump) 56955SN/A : SimObject(name) 57955SN/A{ 581031SN/A link[0] = new Link(name + ".link0", this, 0, rate, delay, delayVar, dump); 59955SN/A link[1] = new Link(name + ".link1", this, 1, rate, delay, delayVar, dump); 601388SN/A 61955SN/A interface[0] = new Interface(name + ".int0", link[0], link[1]); 62955SN/A interface[1] = new Interface(name + ".int1", link[1], link[0]); 631296SN/A 64955SN/A interface[0]->setPeer(peer0); 652609SN/A peer0->setPeer(interface[0]); 66955SN/A interface[1]->setPeer(peer1); 67955SN/A peer1->setPeer(interface[1]); 68955SN/A} 69955SN/A 70955SN/AEtherLink::~EtherLink() 71955SN/A{ 72955SN/A delete link[0]; 73955SN/A delete link[1]; 74955SN/A 75955SN/A delete interface[0]; 76955SN/A delete interface[1]; 77955SN/A} 78955SN/A 79955SN/AEtherLink::Interface::Interface(const string &name, Link *tx, Link *rx) 80955SN/A : EtherInt(name), txlink(tx) 81955SN/A{ 82955SN/A tx->setTxInt(this); 83955SN/A rx->setRxInt(this); 842325SN/A} 851717SN/A 862652Ssaidi@eecs.umich.eduEtherLink::Link::Link(const string &name, EtherLink *p, int num, 87955SN/A double rate, Tick delay, Tick delay_var, EtherDump *d) 882736Sktlim@umich.edu : objName(name), parent(p), number(num), txint(NULL), rxint(NULL), 892410SN/A ticksPerByte(rate), linkDelay(delay), delayVar(delay_var), dump(d), 90955SN/A doneEvent(this) 912290SN/A{ } 92955SN/A 931717SN/Avoid 942683Sktlim@umich.eduEtherLink::serialize(ostream &os) 952683Sktlim@umich.edu{ 962669Sktlim@umich.edu link[0]->serialize("link0", os); 972568SN/A link[1]->serialize("link1", os); 982568SN/A} 992499SN/A 1002462SN/Avoid 1012568SN/AEtherLink::unserialize(Checkpoint *cp, const string §ion) 1022395SN/A{ 1032405SN/A link[0]->unserialize("link0", cp, section); 104955SN/A link[1]->unserialize("link1", cp, section); 105955SN/A} 106955SN/A 107955SN/Avoid 108955SN/AEtherLink::Link::txComplete(EthPacketPtr packet) 1092090SN/A{ 110955SN/A DPRINTF(Ethernet, "packet received: len=%d\n", packet->length); 1112667Sstever@eecs.umich.edu DDUMP(EthernetData, packet->data, packet->length); 112955SN/A rxint->sendPacket(packet); 113955SN/A} 1141696SN/A 115955SN/Aclass LinkDelayEvent : public Event 116955SN/A{ 117955SN/A protected: 1181127SN/A EtherLink::Link *link; 119955SN/A EthPacketPtr packet; 120955SN/A 1212379SN/A public: 122955SN/A // non-scheduling version for createForUnserialize() 123955SN/A LinkDelayEvent(); 124955SN/A LinkDelayEvent(EtherLink::Link *link, EthPacketPtr pkt, Tick when); 1252155SN/A 1262155SN/A void process(); 1272155SN/A 1282155SN/A virtual void serialize(ostream &os); 1292155SN/A virtual void unserialize(Checkpoint *cp, const string §ion); 1302155SN/A static Serializable *createForUnserialize(Checkpoint *cp, 1312155SN/A const string §ion); 1322155SN/A}; 1332155SN/A 1342155SN/Avoid 1352155SN/AEtherLink::Link::txDone() 1362155SN/A{ 1372155SN/A if (dump) 1382155SN/A dump->dump(packet); 1392155SN/A 1402155SN/A if (linkDelay > 0) { 1412155SN/A DPRINTF(Ethernet, "packet delayed: delay=%d\n", linkDelay); 1422155SN/A new LinkDelayEvent(this, packet, curTick + linkDelay); 1432155SN/A } else { 1442155SN/A txComplete(packet); 1452155SN/A } 1462155SN/A 1472155SN/A packet = 0; 1482155SN/A assert(!busy()); 1492155SN/A 1502155SN/A txint->sendDone(); 1512155SN/A} 1522155SN/A 1532155SN/Abool 1542155SN/AEtherLink::Link::transmit(EthPacketPtr pkt) 1552155SN/A{ 1562155SN/A if (busy()) { 1572155SN/A DPRINTF(Ethernet, "packet not sent, link busy\n"); 1582155SN/A return false; 1592155SN/A } 1602155SN/A 1612155SN/A DPRINTF(Ethernet, "packet sent: len=%d\n", pkt->length); 1622155SN/A DDUMP(EthernetData, pkt->data, pkt->length); 1632155SN/A 1642422SN/A packet = pkt; 1652422SN/A Tick delay = (Tick)ceil(((double)pkt->length * ticksPerByte) + 1.0); 1662422SN/A if (delayVar != 0) { 1672422SN/A Random<Tick> var; 1682422SN/A delay += var.uniform(0, delayVar); 1692422SN/A } 1702422SN/A DPRINTF(Ethernet, "scheduling packet: delay=%d, (rate=%f)\n", 1712397SN/A delay, ticksPerByte); 1722397SN/A doneEvent.schedule(curTick + delay); 1732422SN/A 1742422SN/A return true; 175955SN/A} 176955SN/A 177955SN/Avoid 178955SN/AEtherLink::Link::serialize(const string &base, ostream &os) 179955SN/A{ 180955SN/A bool packet_exists = packet; 181955SN/A paramOut(os, base + ".packet_exists", packet_exists); 182955SN/A if (packet_exists) 1831078SN/A packet->serialize(base + ".packet", os); 184955SN/A 185955SN/A bool event_scheduled = doneEvent.scheduled(); 186955SN/A paramOut(os, base + ".event_scheduled", event_scheduled); 187955SN/A if (event_scheduled) { 1881917SN/A Tick event_time = doneEvent.when(); 189955SN/A paramOut(os, base + ".event_time", event_time); 190955SN/A } 191955SN/A 192955SN/A} 193974SN/A 194955SN/Avoid 195955SN/AEtherLink::Link::unserialize(const string &base, Checkpoint *cp, 196955SN/A const string §ion) 197955SN/A{ 1982566SN/A bool packet_exists; 1992566SN/A paramIn(cp, section, base + ".packet_exists", packet_exists); 200955SN/A if (packet_exists) { 201955SN/A packet = new EthPacketData(16384); 2022539SN/A packet->unserialize(base + ".packet", cp, section); 203955SN/A } 204955SN/A 205955SN/A bool event_scheduled; 2061817SN/A paramIn(cp, section, base + ".event_scheduled", event_scheduled); 2071154SN/A if (event_scheduled) { 2081840SN/A Tick event_time; 2092522SN/A paramIn(cp, section, base + ".event_time", event_time); 2102522SN/A doneEvent.schedule(event_time); 2112629SN/A } 212955SN/A} 213955SN/A 214955SN/ALinkDelayEvent::LinkDelayEvent() 2152539SN/A : Event(&mainEventQueue), link(NULL) 216955SN/A{ 2172539SN/A setFlags(AutoSerialize); 218955SN/A setFlags(AutoDelete); 2191730SN/A} 220955SN/A 221955SN/ALinkDelayEvent::LinkDelayEvent(EtherLink::Link *l, EthPacketPtr p, Tick when) 222955SN/A : Event(&mainEventQueue), link(l), packet(p) 2232212SN/A{ 224955SN/A setFlags(AutoSerialize); 2251040SN/A setFlags(AutoDelete); 2262507SN/A schedule(when); 2272521SN/A} 2282521SN/A 2292507SN/Avoid 2302507SN/ALinkDelayEvent::process() 2312507SN/A{ 2322521SN/A link->txComplete(packet); 2332507SN/A} 2342507SN/A 235955SN/Avoid 236955SN/ALinkDelayEvent::serialize(ostream &os) 237955SN/A{ 238955SN/A paramOut(os, "type", string("LinkDelayEvent")); 239955SN/A Event::serialize(os); 240955SN/A 2411742SN/A EtherLink *parent = link->parent; 2421742SN/A bool number = link->number; 2431742SN/A SERIALIZE_OBJPTR(parent); 2441742SN/A SERIALIZE_SCALAR(number); 2451742SN/A 2461742SN/A packet->serialize("packet", os); 2471742SN/A} 2481742SN/A 2491742SN/A 2501742SN/Avoid 2511742SN/ALinkDelayEvent::unserialize(Checkpoint *cp, const string §ion) 2521742SN/A{ 2531742SN/A Event::unserialize(cp, section); 2541742SN/A 2551742SN/A EtherLink *parent; 2561742SN/A bool number; 2571742SN/A UNSERIALIZE_OBJPTR(parent); 2581742SN/A UNSERIALIZE_SCALAR(number); 2591742SN/A 2601742SN/A link = parent->link[number]; 261955SN/A 262955SN/A packet = new EthPacketData(16384); 2632520SN/A packet->unserialize("packet", cp, section); 2642517SN/A} 2652253SN/A 2662253SN/A 2672253SN/ASerializable * 2682253SN/ALinkDelayEvent::createForUnserialize(Checkpoint *cp, const string §ion) 2692553SN/A{ 2702553SN/A return new LinkDelayEvent(); 2712553SN/A} 2722553SN/A 2732507SN/AREGISTER_SERIALIZEABLE("LinkDelayEvent", LinkDelayEvent) 2742470SN/A 2751744SN/ABEGIN_DECLARE_SIM_OBJECT_PARAMS(EtherLink) 2761744SN/A 2772470SN/A SimObjectParam<EtherInt *> int1; 2782470SN/A SimObjectParam<EtherInt *> int2; 2792470SN/A Param<double> speed; 2802470SN/A Param<Tick> delay; 2812470SN/A Param<Tick> delay_var; 2822470SN/A SimObjectParam<EtherDump *> dump; 2832400SN/A 2842400SN/AEND_DECLARE_SIM_OBJECT_PARAMS(EtherLink) 285955SN/A 286955SN/ABEGIN_INIT_SIM_OBJECT_PARAMS(EtherLink) 2872667Sstever@eecs.umich.edu 2882667Sstever@eecs.umich.edu INIT_PARAM(int1, "interface 1"), 2892667Sstever@eecs.umich.edu INIT_PARAM(int2, "interface 2"), 2902667Sstever@eecs.umich.edu INIT_PARAM(speed, "link speed in bits per second"), 2912667Sstever@eecs.umich.edu INIT_PARAM(delay, "transmit delay of packets in us"), 2922667Sstever@eecs.umich.edu INIT_PARAM(delay_var, "Difference in amount of time to traverse wire"), 2932037SN/A INIT_PARAM(dump, "object to dump network packets to") 2942037SN/A 2952037SN/AEND_INIT_SIM_OBJECT_PARAMS(EtherLink) 2962667Sstever@eecs.umich.edu 2972139SN/ACREATE_SIM_OBJECT(EtherLink) 2982667Sstever@eecs.umich.edu{ 2992155SN/A return new EtherLink(getInstanceName(), int1, int2, speed, delay, delay_var, 3002155SN/A dump); 3012155SN/A} 3022155SN/A 3032155SN/AREGISTER_SIM_OBJECT("EtherLink", EtherLink) 3042155SN/A