etherlink.cc revision 8229
11689SN/A/*
29444SAndreas.Sandberg@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 * Authors: Nathan Binkert
291689SN/A *          Ron Dreslinski
301689SN/A */
311689SN/A
321689SN/A/* @file
331689SN/A * Device module for modelling a fixed bandwidth full duplex ethernet link
341689SN/A */
351689SN/A
361689SN/A#include <cmath>
371689SN/A#include <deque>
381689SN/A#include <string>
392665Ssaidi@eecs.umich.edu#include <vector>
402665Ssaidi@eecs.umich.edu
412831Sksewell@umich.edu#include "base/random.hh"
421689SN/A#include "base/trace.hh"
431689SN/A#include "dev/etherdump.hh"
442064SN/A#include "dev/etherint.hh"
451060SN/A#include "dev/etherlink.hh"
461060SN/A#include "dev/etherpkt.hh"
472292SN/A#include "params/EtherLink.hh"
481717SN/A#include "sim/core.hh"
498232Snate@binkert.org#include "sim/serialize.hh"
504762Snate@binkert.org#include "sim/system.hh"
516221Snate@binkert.org
524762Snate@binkert.orgusing namespace std;
531060SN/A
548737Skoansin.tan@gmail.comEtherLink::EtherLink(const Params *p)
558737Skoansin.tan@gmail.com    : EtherObject(p)
568737Skoansin.tan@gmail.com{
575529Snate@binkert.org    link[0] = new Link(name() + ".link0", this, 0, p->speed,
581061SN/A                       p->delay, p->delay_var, p->dump);
592292SN/A    link[1] = new Link(name() + ".link1", this, 1, p->speed,
605606Snate@binkert.org                       p->delay, p->delay_var, p->dump);
618581Ssteve.reinhardt@amd.com
628581Ssteve.reinhardt@amd.com    interface[0] = new Interface(name() + ".int0", link[0], link[1]);
631060SN/A    interface[1] = new Interface(name() + ".int1", link[1], link[0]);
642292SN/A}
652292SN/A
662292SN/A
672292SN/AEtherLink::~EtherLink()
682292SN/A{
692292SN/A    delete link[0];
702326SN/A    delete link[1];
712292SN/A
722292SN/A    delete interface[0];
732292SN/A    delete interface[1];
742292SN/A}
752292SN/A
762292SN/AEtherInt*
775336Shines@cs.fsu.eduEtherLink::getEthPort(const std::string &if_name, int idx)
782292SN/A{
794873Sstever@eecs.umich.edu    Interface *i;
802292SN/A    if (if_name == "int0")
812292SN/A        i = interface[0];
822292SN/A    else if (if_name == "int1")
834329Sktlim@umich.edu        i = interface[1];
845529Snate@binkert.org    else
854329Sktlim@umich.edu        return NULL;
864329Sktlim@umich.edu    if (i->getPeer())
874329Sktlim@umich.edu        panic("interface already connected to\n");
882292SN/A
892292SN/A    return i;
902292SN/A}
912292SN/A
922292SN/A
932292SN/AEtherLink::Interface::Interface(const string &name, Link *tx, Link *rx)
942292SN/A    : EtherInt(name), txlink(tx)
952292SN/A{
965529Snate@binkert.org    tx->setTxInt(this);
971060SN/A    rx->setRxInt(this);
981060SN/A}
991060SN/A
1001060SN/AEtherLink::Link::Link(const string &name, EtherLink *p, int num,
1011060SN/A                      double rate, Tick delay, Tick delay_var, EtherDump *d)
1021060SN/A    : objName(name), parent(p), number(num), txint(NULL), rxint(NULL),
1032326SN/A      ticksPerByte(rate), linkDelay(delay), delayVar(delay_var), dump(d),
1041060SN/A      doneEvent(this)
1051060SN/A{ }
1061060SN/A
1071060SN/Avoid
1082292SN/AEtherLink::serialize(ostream &os)
1096221Snate@binkert.org{
1106221Snate@binkert.org    link[0]->serialize("link0", os);
1116221Snate@binkert.org    link[1]->serialize("link1", os);
1121060SN/A}
1131060SN/A
1142307SN/Avoid
1152292SN/AEtherLink::unserialize(Checkpoint *cp, const string &section)
1162980Sgblack@eecs.umich.edu{
1172292SN/A    link[0]->unserialize("link0", cp, section);
1182292SN/A    link[1]->unserialize("link1", cp, section);
1192292SN/A}
1202292SN/A
1212292SN/Avoid
1222292SN/AEtherLink::Link::txComplete(EthPacketPtr packet)
1232292SN/A{
1242292SN/A    DPRINTF(Ethernet, "packet received: len=%d\n", packet->length);
1252292SN/A    DDUMP(EthernetData, packet->data, packet->length);
1262292SN/A    rxint->sendPacket(packet);
1276221Snate@binkert.org}
1286221Snate@binkert.org
1292292SN/Aclass LinkDelayEvent : public Event
1302292SN/A{
1312292SN/A  protected:
1322292SN/A    EtherLink::Link *link;
1332292SN/A    EthPacketPtr packet;
1342292SN/A
1352292SN/A  public:
1362292SN/A    // non-scheduling version for createForUnserialize()
1372292SN/A    LinkDelayEvent();
1386221Snate@binkert.org    LinkDelayEvent(EtherLink::Link *link, EthPacketPtr pkt);
1396221Snate@binkert.org
1402292SN/A    void process();
1412292SN/A
1422831Sksewell@umich.edu    virtual void serialize(ostream &os);
1432292SN/A    virtual void unserialize(Checkpoint *cp, const string &section);
1442292SN/A    static Serializable *createForUnserialize(Checkpoint *cp,
1452292SN/A                                              const string &section);
1462292SN/A};
1472292SN/A
1482292SN/Avoid
1492292SN/AEtherLink::Link::txDone()
1502292SN/A{
1512292SN/A    if (dump)
1526221Snate@binkert.org        dump->dump(packet);
1536221Snate@binkert.org
1542292SN/A    if (linkDelay > 0) {
1552292SN/A        DPRINTF(Ethernet, "packet delayed: delay=%d\n", linkDelay);
1562831Sksewell@umich.edu        Event *event = new LinkDelayEvent(this, packet);
1572292SN/A        parent->schedule(event, curTick() + linkDelay);
1582292SN/A    } else {
1592292SN/A        txComplete(packet);
1602292SN/A    }
1612292SN/A
1622292SN/A    packet = 0;
1632292SN/A    assert(!busy());
1642292SN/A
1652292SN/A    txint->sendDone();
1662292SN/A}
1672326SN/A
1682348SN/Abool
1692326SN/AEtherLink::Link::transmit(EthPacketPtr pkt)
1702326SN/A{
1712348SN/A    if (busy()) {
1722292SN/A        DPRINTF(Ethernet, "packet not sent, link busy\n");
1732292SN/A        return false;
1742292SN/A    }
1752292SN/A
1762292SN/A    DPRINTF(Ethernet, "packet sent: len=%d\n", pkt->length);
1772292SN/A    DDUMP(EthernetData, pkt->data, pkt->length);
1782292SN/A
1791060SN/A    packet = pkt;
1801060SN/A    Tick delay = (Tick)ceil(((double)pkt->length * ticksPerByte) + 1.0);
1811061SN/A    if (delayVar != 0)
1821060SN/A        delay += random_mt.random<Tick>(0, delayVar);
1831062SN/A
1841062SN/A    DPRINTF(Ethernet, "scheduling packet: delay=%d, (rate=%f)\n",
1852301SN/A            delay, ticksPerByte);
1861062SN/A    parent->schedule(doneEvent, curTick() + delay);
1871062SN/A
1881062SN/A    return true;
1891062SN/A}
1901062SN/A
1911062SN/Avoid
1921062SN/AEtherLink::Link::serialize(const string &base, ostream &os)
1931062SN/A{
1941062SN/A    bool packet_exists = packet;
1951062SN/A    paramOut(os, base + ".packet_exists", packet_exists);
1962301SN/A    if (packet_exists)
1972301SN/A        packet->serialize(base + ".packet", os);
1982301SN/A
1992301SN/A    bool event_scheduled = doneEvent.scheduled();
2001062SN/A    paramOut(os, base + ".event_scheduled", event_scheduled);
2011062SN/A    if (event_scheduled) {
2021062SN/A        Tick event_time = doneEvent.when();
2031062SN/A        paramOut(os, base + ".event_time", event_time);
2041062SN/A    }
2051062SN/A
2061062SN/A}
2071062SN/A
2081062SN/Avoid
2091062SN/AEtherLink::Link::unserialize(const string &base, Checkpoint *cp,
2101062SN/A                             const string &section)
2111062SN/A{
2121062SN/A    bool packet_exists;
2131062SN/A    paramIn(cp, section, base + ".packet_exists", packet_exists);
2141062SN/A    if (packet_exists) {
2151062SN/A        packet = new EthPacketData(16384);
2161062SN/A        packet->unserialize(base + ".packet", cp, section);
2171062SN/A    }
2181062SN/A
2191062SN/A    bool event_scheduled;
2201062SN/A    paramIn(cp, section, base + ".event_scheduled", event_scheduled);
2211062SN/A    if (event_scheduled) {
2221062SN/A        Tick event_time;
2231062SN/A        paramIn(cp, section, base + ".event_time", event_time);
2241062SN/A        parent->schedule(doneEvent, event_time);
2251062SN/A    }
2261062SN/A}
2271062SN/A
2281062SN/ALinkDelayEvent::LinkDelayEvent()
2291062SN/A    : link(NULL)
2301062SN/A{
2311062SN/A    setFlags(AutoSerialize);
2321062SN/A    setFlags(AutoDelete);
2331062SN/A}
2341062SN/A
2351062SN/ALinkDelayEvent::LinkDelayEvent(EtherLink::Link *l, EthPacketPtr p)
2361062SN/A    : link(l), packet(p)
2371062SN/A{
2381062SN/A    setFlags(AutoSerialize);
2391062SN/A    setFlags(AutoDelete);
2401062SN/A}
2411062SN/A
2421062SN/Avoid
2431062SN/ALinkDelayEvent::process()
2441062SN/A{
2451062SN/A    link->txComplete(packet);
2461062SN/A}
2472361SN/A
2482326SN/Avoid
2492301SN/ALinkDelayEvent::serialize(ostream &os)
2502301SN/A{
2512301SN/A    paramOut(os, "type", string("LinkDelayEvent"));
2522301SN/A    Event::serialize(os);
2532301SN/A
2542301SN/A    EtherLink *parent = link->parent;
2552326SN/A    bool number = link->number;
2562301SN/A    SERIALIZE_OBJPTR(parent);
2572361SN/A    SERIALIZE_SCALAR(number);
2582326SN/A
2592307SN/A    packet->serialize("packet", os);
2608240Snate@binkert.org}
2612301SN/A
2622307SN/A
2632301SN/Avoid
2642301SN/ALinkDelayEvent::unserialize(Checkpoint *cp, const string &section)
2652301SN/A{
2662301SN/A    Event::unserialize(cp, section);
2678240Snate@binkert.org
2682301SN/A    EtherLink *parent;
2692301SN/A    bool number;
2702301SN/A    UNSERIALIZE_OBJPTR(parent);
2712301SN/A    UNSERIALIZE_SCALAR(number);
2722301SN/A
2732301SN/A    link = parent->link[number];
2742301SN/A
2752326SN/A    packet = new EthPacketData(16384);
2764762Snate@binkert.org    packet->unserialize("packet", cp, section);
2778240Snate@binkert.org}
2782301SN/A
2792301SN/A
2802301SN/ASerializable *
2814762Snate@binkert.orgLinkDelayEvent::createForUnserialize(Checkpoint *cp, const string &section)
2822301SN/A{
2832301SN/A    return new LinkDelayEvent();
2842301SN/A}
2852301SN/A
2862361SN/AREGISTER_SERIALIZEABLE("LinkDelayEvent", LinkDelayEvent)
2872326SN/A
2882301SN/AEtherLink *
2898240Snate@binkert.orgEtherLinkParams::create()
2902301SN/A{
2912301SN/A    return new EtherLink(this);
2922301SN/A}
2932301SN/A