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 &section)
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 &section);
1302068SN/A    static Serializable *createForUnserialize(Checkpoint *cp,
1318588Sgblack@eecs.umich.edu                                              const string &section);
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 &section)
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 &section)
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 &section)
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