etherlink.cc revision 1762
11689SN/A/*
27944SGiacomo.Gabrielli@arm.com * Copyright (c) 2002-2005 The Regents of The University of Michigan
37944SGiacomo.Gabrielli@arm.com * All rights reserved.
47944SGiacomo.Gabrielli@arm.com *
57944SGiacomo.Gabrielli@arm.com * Redistribution and use in source and binary forms, with or without
67944SGiacomo.Gabrielli@arm.com * modification, are permitted provided that the following conditions are
77944SGiacomo.Gabrielli@arm.com * met: redistributions of source code must retain the above copyright
87944SGiacomo.Gabrielli@arm.com * notice, this list of conditions and the following disclaimer;
97944SGiacomo.Gabrielli@arm.com * redistributions in binary form must reproduce the above copyright
107944SGiacomo.Gabrielli@arm.com * notice, this list of conditions and the following disclaimer in the
117944SGiacomo.Gabrielli@arm.com * documentation and/or other materials provided with the distribution;
127944SGiacomo.Gabrielli@arm.com * neither the name of the copyright holders nor the names of its
137944SGiacomo.Gabrielli@arm.com * contributors may be used to endorse or promote products derived from
142326SN/A * this software without specific prior written permission.
151689SN/A *
161689SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
171689SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
181689SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
191689SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
201689SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
211689SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
221689SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
231689SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
241689SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
251689SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
261689SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
271689SN/A */
281689SN/A
291689SN/A/* @file
301689SN/A * Device module for modelling a fixed bandwidth full duplex ethernet link
311689SN/A */
321689SN/A
331689SN/A#include <cmath>
341689SN/A#include <deque>
351689SN/A#include <string>
361689SN/A#include <vector>
371689SN/A
381689SN/A#include "base/trace.hh"
392665Ssaidi@eecs.umich.edu#include "dev/etherdump.hh"
402665Ssaidi@eecs.umich.edu#include "dev/etherint.hh"
412831Sksewell@umich.edu#include "dev/etherlink.hh"
421689SN/A#include "dev/etherpkt.hh"
431689SN/A#include "sim/builder.hh"
442064SN/A#include "sim/serialize.hh"
451060SN/A#include "sim/system.hh"
461060SN/A#include "sim/root.hh"
472292SN/A
481717SN/Ausing namespace std;
494762Snate@binkert.org
506221Snate@binkert.orgEtherLink::EtherLink(const string &name, EtherInt *peer0, EtherInt *peer1,
514762Snate@binkert.org                     double rate, Tick delay, EtherDump *dump)
521060SN/A    : SimObject(name)
536221Snate@binkert.org{
545529Snate@binkert.org    link[0] = new Link(name + ".link0", this, 0, rate, delay, dump);
551061SN/A    link[1] = new Link(name + ".link1", this, 1, rate, delay, dump);
562292SN/A
575606Snate@binkert.org    interface[0] = new Interface(name + ".int0", link[0], link[1]);
585606Snate@binkert.org    interface[1] = new Interface(name + ".int1", link[1], link[0]);
595606Snate@binkert.org
601060SN/A    interface[0]->setPeer(peer0);
612292SN/A    peer0->setPeer(interface[0]);
622292SN/A    interface[1]->setPeer(peer1);
632292SN/A    peer1->setPeer(interface[1]);
642292SN/A}
652292SN/A
662292SN/AEtherLink::~EtherLink()
672292SN/A{
682326SN/A    delete link[0];
692292SN/A    delete link[1];
702292SN/A
712292SN/A    delete interface[0];
722292SN/A    delete interface[1];
732292SN/A}
742292SN/A
755336Shines@cs.fsu.eduEtherLink::Interface::Interface(const string &name, Link *tx, Link *rx)
762292SN/A    : EtherInt(name), txlink(tx)
774873Sstever@eecs.umich.edu{
782292SN/A    tx->setTxInt(this);
792292SN/A    rx->setRxInt(this);
802292SN/A}
814329Sktlim@umich.edu
825529Snate@binkert.orgEtherLink::Link::Link(const string &name, EtherLink *p, int num,
834329Sktlim@umich.edu                      double rate, Tick delay, EtherDump *d)
844329Sktlim@umich.edu    : objName(name), parent(p), number(num), txint(NULL), rxint(NULL),
854329Sktlim@umich.edu      ticksPerByte(rate), linkDelay(delay), dump(d),
862292SN/A      doneEvent(this)
872292SN/A{ }
882292SN/A
892292SN/Avoid
902292SN/AEtherLink::serialize(ostream &os)
912292SN/A{
922292SN/A    link[0]->serialize("link0", os);
932292SN/A    link[1]->serialize("link1", os);
942307SN/A}
952307SN/A
965529Snate@binkert.orgvoid
971060SN/AEtherLink::unserialize(Checkpoint *cp, const string &section)
981060SN/A{
991060SN/A    link[0]->unserialize("link0", cp, section);
1001060SN/A    link[1]->unserialize("link1", cp, section);
1011060SN/A}
1021060SN/A
1032326SN/Avoid
1041060SN/AEtherLink::Link::txComplete(PacketPtr packet)
1051060SN/A{
1061060SN/A    DPRINTF(Ethernet, "packet received: len=%d\n", packet->length);
1071060SN/A    DDUMP(EthernetData, packet->data, packet->length);
1082292SN/A    rxint->sendPacket(packet);
1096221Snate@binkert.org}
1106221Snate@binkert.org
1116221Snate@binkert.orgclass LinkDelayEvent : public Event
1121060SN/A{
1131060SN/A  protected:
1142307SN/A    EtherLink::Link *link;
1152292SN/A    PacketPtr packet;
1162980Sgblack@eecs.umich.edu
1172292SN/A  public:
1182292SN/A    // non-scheduling version for createForUnserialize()
1192292SN/A    LinkDelayEvent();
1202292SN/A    LinkDelayEvent(EtherLink::Link *link, PacketPtr pkt, Tick when);
1212292SN/A
1222292SN/A    void process();
1232292SN/A
1242292SN/A    virtual void serialize(ostream &os);
1252292SN/A    virtual void unserialize(Checkpoint *cp, const string &section);
1262292SN/A    static Serializable *createForUnserialize(Checkpoint *cp,
1276221Snate@binkert.org                                              const string &section);
1286221Snate@binkert.org};
1292292SN/A
1302292SN/Avoid
1312292SN/AEtherLink::Link::txDone()
1322292SN/A{
1332292SN/A    if (dump)
1342292SN/A        dump->dump(packet);
1352292SN/A
1362292SN/A    if (linkDelay > 0) {
1372292SN/A        DPRINTF(Ethernet, "packet delayed: delay=%d\n", linkDelay);
1386221Snate@binkert.org        new LinkDelayEvent(this, packet, curTick + linkDelay);
1396221Snate@binkert.org    } else {
1402292SN/A        txComplete(packet);
1412292SN/A    }
1422831Sksewell@umich.edu
1432292SN/A    packet = 0;
1442292SN/A    assert(!busy());
1452292SN/A
1462292SN/A    txint->sendDone();
1472292SN/A}
1482292SN/A
1492292SN/Abool
1502292SN/AEtherLink::Link::transmit(PacketPtr pkt)
1512292SN/A{
1526221Snate@binkert.org    if (busy()) {
1536221Snate@binkert.org        DPRINTF(Ethernet, "packet not sent, link busy\n");
1542292SN/A        return false;
1552292SN/A    }
1562831Sksewell@umich.edu
1572292SN/A    DPRINTF(Ethernet, "packet sent: len=%d\n", pkt->length);
1582292SN/A    DDUMP(EthernetData, pkt->data, pkt->length);
1592292SN/A
1602292SN/A    packet = pkt;
1612292SN/A    Tick delay = (Tick)ceil(((double)pkt->length * ticksPerByte) + 1.0);
1622292SN/A    DPRINTF(Ethernet, "scheduling packet: delay=%d, (rate=%f)\n",
1632292SN/A            delay, ticksPerByte);
1642292SN/A    doneEvent.schedule(curTick + delay);
1652292SN/A
1662292SN/A    return true;
1672326SN/A}
1682348SN/A
1692326SN/Avoid
1702326SN/AEtherLink::Link::serialize(const string &base, ostream &os)
1712348SN/A{
1722292SN/A    bool packet_exists = packet;
1732292SN/A    paramOut(os, base + ".packet_exists", packet_exists);
1742292SN/A    if (packet_exists)
1752292SN/A        packet->serialize(base + ".packet", os);
1762292SN/A
1772292SN/A    bool event_scheduled = doneEvent.scheduled();
1782292SN/A    paramOut(os, base + ".event_scheduled", event_scheduled);
1791060SN/A    if (event_scheduled) {
1801060SN/A        Tick event_time = doneEvent.when();
1811061SN/A        paramOut(os, base + ".event_time", event_time);
1821060SN/A    }
1831062SN/A
1841062SN/A}
1852301SN/A
1861062SN/Avoid
1871062SN/AEtherLink::Link::unserialize(const string &base, Checkpoint *cp,
1881062SN/A                             const string &section)
1891062SN/A{
1901062SN/A    bool packet_exists;
1911062SN/A    paramIn(cp, section, base + ".packet_exists", packet_exists);
1921062SN/A    if (packet_exists) {
1931062SN/A        packet = new PacketData(16384);
1941062SN/A        packet->unserialize(base + ".packet", cp, section);
1951062SN/A    }
1962301SN/A
1972301SN/A    bool event_scheduled;
1982301SN/A    paramIn(cp, section, base + ".event_scheduled", event_scheduled);
1992301SN/A    if (event_scheduled) {
2001062SN/A        Tick event_time;
2011062SN/A        paramIn(cp, section, base + ".event_time", event_time);
2021062SN/A        doneEvent.schedule(event_time);
2031062SN/A    }
2041062SN/A}
2051062SN/A
2061062SN/ALinkDelayEvent::LinkDelayEvent()
2071062SN/A    : Event(&mainEventQueue), link(NULL)
2081062SN/A{
2091062SN/A    setFlags(AutoSerialize);
2101062SN/A    setFlags(AutoDelete);
2111062SN/A}
2121062SN/A
2131062SN/ALinkDelayEvent::LinkDelayEvent(EtherLink::Link *l, PacketPtr p, Tick when)
2141062SN/A    : Event(&mainEventQueue), link(l), packet(p)
2151062SN/A{
2161062SN/A    setFlags(AutoSerialize);
2171062SN/A    setFlags(AutoDelete);
2181062SN/A    schedule(when);
2191062SN/A}
2201062SN/A
2211062SN/Avoid
2221062SN/ALinkDelayEvent::process()
2231062SN/A{
2241062SN/A    link->txComplete(packet);
2251062SN/A}
2261062SN/A
2271062SN/Avoid
2281062SN/ALinkDelayEvent::serialize(ostream &os)
2291062SN/A{
2301062SN/A    paramOut(os, "type", string("LinkDelayEvent"));
2311062SN/A    Event::serialize(os);
2321062SN/A
2331062SN/A    EtherLink *parent = link->parent;
2341062SN/A    bool number = link->number;
2351062SN/A    SERIALIZE_OBJPTR(parent);
2361062SN/A    SERIALIZE_SCALAR(number);
2371062SN/A
2381062SN/A    packet->serialize("packet", os);
2391062SN/A}
2401062SN/A
2411062SN/A
2421062SN/Avoid
2431062SN/ALinkDelayEvent::unserialize(Checkpoint *cp, const string &section)
2441062SN/A{
2451062SN/A    Event::unserialize(cp, section);
2461062SN/A
2472361SN/A    EtherLink *parent;
2482326SN/A    bool number;
2492301SN/A    UNSERIALIZE_OBJPTR(parent);
2502301SN/A    UNSERIALIZE_SCALAR(number);
2512301SN/A
2522301SN/A    link = parent->link[number];
2532301SN/A
2542301SN/A    packet = new PacketData(16384);
2552326SN/A    packet->unserialize("packet", cp, section);
2562301SN/A}
2572361SN/A
2582326SN/A
2592307SN/ASerializable *
2602301SN/ALinkDelayEvent::createForUnserialize(Checkpoint *cp, const string &section)
2612301SN/A{
2622307SN/A    return new LinkDelayEvent();
2632301SN/A}
2642301SN/A
2652301SN/AREGISTER_SERIALIZEABLE("LinkDelayEvent", LinkDelayEvent)
2662301SN/A
2672301SN/ABEGIN_DECLARE_SIM_OBJECT_PARAMS(EtherLink)
2682301SN/A
2692301SN/A    SimObjectParam<EtherInt *> int1;
2702301SN/A    SimObjectParam<EtherInt *> int2;
2712301SN/A    Param<double> speed;
2722301SN/A    Param<Tick> delay;
2732301SN/A    SimObjectParam<EtherDump *> dump;
2742301SN/A
2752326SN/AEND_DECLARE_SIM_OBJECT_PARAMS(EtherLink)
2764762Snate@binkert.org
2772301SN/ABEGIN_INIT_SIM_OBJECT_PARAMS(EtherLink)
2782301SN/A
2792301SN/A    INIT_PARAM(int1, "interface 1"),
2802301SN/A    INIT_PARAM(int2, "interface 2"),
2814762Snate@binkert.org    INIT_PARAM(speed, "link speed in bits per second"),
2822301SN/A    INIT_PARAM(delay, "transmit delay of packets in us"),
2832301SN/A    INIT_PARAM(dump, "object to dump network packets to")
2842301SN/A
2852301SN/AEND_INIT_SIM_OBJECT_PARAMS(EtherLink)
2862361SN/A
2872326SN/ACREATE_SIM_OBJECT(EtherLink)
2882301SN/A{
2892301SN/A    return new EtherLink(getInstanceName(), int1, int2, speed, delay, dump);
2902301SN/A}
2912301SN/A
2922301SN/AREGISTER_SIM_OBJECT("EtherLink", EtherLink)
2932301SN/A