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 &section)
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 &section);
1302155SN/A    static Serializable *createForUnserialize(Checkpoint *cp,
1312155SN/A                                              const string &section);
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 &section)
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 &section)
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 &section)
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