etherlink.cc revision 4762
111406Sandreas.sandberg@arm.com/*
211406Sandreas.sandberg@arm.com * Copyright (c) 2002-2005 The Regents of The University of Michigan
311406Sandreas.sandberg@arm.com * All rights reserved.
411406Sandreas.sandberg@arm.com *
511406Sandreas.sandberg@arm.com * Redistribution and use in source and binary forms, with or without
611406Sandreas.sandberg@arm.com * modification, are permitted provided that the following conditions are
711406Sandreas.sandberg@arm.com * met: redistributions of source code must retain the above copyright
811406Sandreas.sandberg@arm.com * notice, this list of conditions and the following disclaimer;
911406Sandreas.sandberg@arm.com * redistributions in binary form must reproduce the above copyright
1011406Sandreas.sandberg@arm.com * notice, this list of conditions and the following disclaimer in the
1111406Sandreas.sandberg@arm.com * documentation and/or other materials provided with the distribution;
1211406Sandreas.sandberg@arm.com * neither the name of the copyright holders nor the names of its
1311406Sandreas.sandberg@arm.com * contributors may be used to endorse or promote products derived from
1411406Sandreas.sandberg@arm.com * this software without specific prior written permission.
1511406Sandreas.sandberg@arm.com *
1611406Sandreas.sandberg@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1711406Sandreas.sandberg@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1811406Sandreas.sandberg@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1911406Sandreas.sandberg@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2011406Sandreas.sandberg@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2111406Sandreas.sandberg@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2211406Sandreas.sandberg@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2311406Sandreas.sandberg@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2411406Sandreas.sandberg@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2511406Sandreas.sandberg@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2611406Sandreas.sandberg@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2711406Sandreas.sandberg@arm.com *
2811406Sandreas.sandberg@arm.com * Authors: Nathan Binkert
2911406Sandreas.sandberg@arm.com *          Ron Dreslinski
3011406Sandreas.sandberg@arm.com */
3111406Sandreas.sandberg@arm.com
3211406Sandreas.sandberg@arm.com/* @file
3311406Sandreas.sandberg@arm.com * Device module for modelling a fixed bandwidth full duplex ethernet link
3411406Sandreas.sandberg@arm.com */
3511406Sandreas.sandberg@arm.com
3611406Sandreas.sandberg@arm.com#include <cmath>
3711406Sandreas.sandberg@arm.com#include <deque>
3811406Sandreas.sandberg@arm.com#include <string>
3911406Sandreas.sandberg@arm.com#include <vector>
4011406Sandreas.sandberg@arm.com
4111406Sandreas.sandberg@arm.com#include "base/random.hh"
4211406Sandreas.sandberg@arm.com#include "base/trace.hh"
4311406Sandreas.sandberg@arm.com#include "dev/etherdump.hh"
4411406Sandreas.sandberg@arm.com#include "dev/etherint.hh"
4511406Sandreas.sandberg@arm.com#include "dev/etherlink.hh"
4611406Sandreas.sandberg@arm.com#include "dev/etherpkt.hh"
4711406Sandreas.sandberg@arm.com#include "params/EtherLink.hh"
4811406Sandreas.sandberg@arm.com#include "sim/serialize.hh"
4911406Sandreas.sandberg@arm.com#include "sim/system.hh"
5011406Sandreas.sandberg@arm.com#include "sim/core.hh"
5111406Sandreas.sandberg@arm.com
5211406Sandreas.sandberg@arm.comusing namespace std;
5311406Sandreas.sandberg@arm.com
5411406Sandreas.sandberg@arm.comEtherLink::EtherLink(const string &name, EtherInt *peer0, EtherInt *peer1,
5511406Sandreas.sandberg@arm.com                     double rate, Tick delay, Tick delayVar, EtherDump *dump)
5611406Sandreas.sandberg@arm.com    : SimObject(name)
5711406Sandreas.sandberg@arm.com{
5811406Sandreas.sandberg@arm.com    link[0] = new Link(name + ".link0", this, 0, rate, delay, delayVar, dump);
5911406Sandreas.sandberg@arm.com    link[1] = new Link(name + ".link1", this, 1, rate, delay, delayVar, dump);
6011406Sandreas.sandberg@arm.com
6111406Sandreas.sandberg@arm.com    interface[0] = new Interface(name + ".int0", link[0], link[1]);
6211406Sandreas.sandberg@arm.com    interface[1] = new Interface(name + ".int1", link[1], link[0]);
6311406Sandreas.sandberg@arm.com
6411406Sandreas.sandberg@arm.com    interface[0]->setPeer(peer0);
6511406Sandreas.sandberg@arm.com    peer0->setPeer(interface[0]);
6611406Sandreas.sandberg@arm.com    interface[1]->setPeer(peer1);
6711406Sandreas.sandberg@arm.com    peer1->setPeer(interface[1]);
6811406Sandreas.sandberg@arm.com}
6911406Sandreas.sandberg@arm.com
7011406Sandreas.sandberg@arm.comEtherLink::~EtherLink()
7111406Sandreas.sandberg@arm.com{
7211406Sandreas.sandberg@arm.com    delete link[0];
7311406Sandreas.sandberg@arm.com    delete link[1];
7411406Sandreas.sandberg@arm.com
7511406Sandreas.sandberg@arm.com    delete interface[0];
7611406Sandreas.sandberg@arm.com    delete interface[1];
7711406Sandreas.sandberg@arm.com}
7811406Sandreas.sandberg@arm.com
7911406Sandreas.sandberg@arm.comEtherLink::Interface::Interface(const string &name, Link *tx, Link *rx)
8011406Sandreas.sandberg@arm.com    : EtherInt(name), txlink(tx)
8111406Sandreas.sandberg@arm.com{
8211406Sandreas.sandberg@arm.com    tx->setTxInt(this);
8311406Sandreas.sandberg@arm.com    rx->setRxInt(this);
8411406Sandreas.sandberg@arm.com}
8511406Sandreas.sandberg@arm.com
8611406Sandreas.sandberg@arm.comEtherLink::Link::Link(const string &name, EtherLink *p, int num,
8711406Sandreas.sandberg@arm.com                      double rate, Tick delay, Tick delay_var, EtherDump *d)
8811406Sandreas.sandberg@arm.com    : objName(name), parent(p), number(num), txint(NULL), rxint(NULL),
8911406Sandreas.sandberg@arm.com      ticksPerByte(rate), linkDelay(delay), delayVar(delay_var), dump(d),
9011406Sandreas.sandberg@arm.com      doneEvent(this)
9111406Sandreas.sandberg@arm.com{ }
9211406Sandreas.sandberg@arm.com
9311406Sandreas.sandberg@arm.comvoid
9411406Sandreas.sandberg@arm.comEtherLink::serialize(ostream &os)
9511406Sandreas.sandberg@arm.com{
9611406Sandreas.sandberg@arm.com    link[0]->serialize("link0", os);
9711406Sandreas.sandberg@arm.com    link[1]->serialize("link1", os);
9811406Sandreas.sandberg@arm.com}
9911406Sandreas.sandberg@arm.com
10011406Sandreas.sandberg@arm.comvoid
10111406Sandreas.sandberg@arm.comEtherLink::unserialize(Checkpoint *cp, const string &section)
10211406Sandreas.sandberg@arm.com{
10311406Sandreas.sandberg@arm.com    link[0]->unserialize("link0", cp, section);
10411406Sandreas.sandberg@arm.com    link[1]->unserialize("link1", cp, section);
10511406Sandreas.sandberg@arm.com}
10611406Sandreas.sandberg@arm.com
10711406Sandreas.sandberg@arm.comvoid
10811406Sandreas.sandberg@arm.comEtherLink::Link::txComplete(EthPacketPtr packet)
10911406Sandreas.sandberg@arm.com{
11011406Sandreas.sandberg@arm.com    DPRINTF(Ethernet, "packet received: len=%d\n", packet->length);
11111406Sandreas.sandberg@arm.com    DDUMP(EthernetData, packet->data, packet->length);
11211406Sandreas.sandberg@arm.com    rxint->sendPacket(packet);
11311406Sandreas.sandberg@arm.com}
11411406Sandreas.sandberg@arm.com
11511406Sandreas.sandberg@arm.comclass LinkDelayEvent : public Event
11611406Sandreas.sandberg@arm.com{
11711406Sandreas.sandberg@arm.com  protected:
11811406Sandreas.sandberg@arm.com    EtherLink::Link *link;
11911406Sandreas.sandberg@arm.com    EthPacketPtr packet;
12011406Sandreas.sandberg@arm.com
12111406Sandreas.sandberg@arm.com  public:
12211406Sandreas.sandberg@arm.com    // non-scheduling version for createForUnserialize()
12311406Sandreas.sandberg@arm.com    LinkDelayEvent();
12411406Sandreas.sandberg@arm.com    LinkDelayEvent(EtherLink::Link *link, EthPacketPtr pkt, Tick when);
12511406Sandreas.sandberg@arm.com
12611406Sandreas.sandberg@arm.com    void process();
12711406Sandreas.sandberg@arm.com
12811406Sandreas.sandberg@arm.com    virtual void serialize(ostream &os);
12911406Sandreas.sandberg@arm.com    virtual void unserialize(Checkpoint *cp, const string &section);
13011406Sandreas.sandberg@arm.com    static Serializable *createForUnserialize(Checkpoint *cp,
13111406Sandreas.sandberg@arm.com                                              const string &section);
13211406Sandreas.sandberg@arm.com};
13311406Sandreas.sandberg@arm.com
13411406Sandreas.sandberg@arm.comvoid
13511406Sandreas.sandberg@arm.comEtherLink::Link::txDone()
13611406Sandreas.sandberg@arm.com{
13711406Sandreas.sandberg@arm.com    if (dump)
13811406Sandreas.sandberg@arm.com        dump->dump(packet);
13911406Sandreas.sandberg@arm.com
14011406Sandreas.sandberg@arm.com    if (linkDelay > 0) {
14111406Sandreas.sandberg@arm.com        DPRINTF(Ethernet, "packet delayed: delay=%d\n", linkDelay);
14211406Sandreas.sandberg@arm.com        new LinkDelayEvent(this, packet, curTick + linkDelay);
14311406Sandreas.sandberg@arm.com    } else {
14411406Sandreas.sandberg@arm.com        txComplete(packet);
14511406Sandreas.sandberg@arm.com    }
14611406Sandreas.sandberg@arm.com
14711406Sandreas.sandberg@arm.com    packet = 0;
14811406Sandreas.sandberg@arm.com    assert(!busy());
14911406Sandreas.sandberg@arm.com
15011406Sandreas.sandberg@arm.com    txint->sendDone();
15111406Sandreas.sandberg@arm.com}
15211406Sandreas.sandberg@arm.com
15311406Sandreas.sandberg@arm.combool
15411406Sandreas.sandberg@arm.comEtherLink::Link::transmit(EthPacketPtr pkt)
15511406Sandreas.sandberg@arm.com{
15611406Sandreas.sandberg@arm.com    if (busy()) {
15711406Sandreas.sandberg@arm.com        DPRINTF(Ethernet, "packet not sent, link busy\n");
15811406Sandreas.sandberg@arm.com        return false;
15911406Sandreas.sandberg@arm.com    }
16011406Sandreas.sandberg@arm.com
16111406Sandreas.sandberg@arm.com    DPRINTF(Ethernet, "packet sent: len=%d\n", pkt->length);
16211406Sandreas.sandberg@arm.com    DDUMP(EthernetData, pkt->data, pkt->length);
16311406Sandreas.sandberg@arm.com
16411406Sandreas.sandberg@arm.com    packet = pkt;
16511406Sandreas.sandberg@arm.com    Tick delay = (Tick)ceil(((double)pkt->length * ticksPerByte) + 1.0);
16611406Sandreas.sandberg@arm.com    if (delayVar != 0) {
16711406Sandreas.sandberg@arm.com        Random<Tick> var;
16811406Sandreas.sandberg@arm.com        delay +=  var.uniform(0, delayVar);
16911406Sandreas.sandberg@arm.com    }
17011406Sandreas.sandberg@arm.com    DPRINTF(Ethernet, "scheduling packet: delay=%d, (rate=%f)\n",
17111406Sandreas.sandberg@arm.com            delay, ticksPerByte);
17211406Sandreas.sandberg@arm.com    doneEvent.schedule(curTick + delay);
17311406Sandreas.sandberg@arm.com
17411406Sandreas.sandberg@arm.com    return true;
17511406Sandreas.sandberg@arm.com}
17611406Sandreas.sandberg@arm.com
17711406Sandreas.sandberg@arm.comvoid
17811406Sandreas.sandberg@arm.comEtherLink::Link::serialize(const string &base, ostream &os)
17911406Sandreas.sandberg@arm.com{
18011406Sandreas.sandberg@arm.com    bool packet_exists = packet;
18111406Sandreas.sandberg@arm.com    paramOut(os, base + ".packet_exists", packet_exists);
18211406Sandreas.sandberg@arm.com    if (packet_exists)
18311406Sandreas.sandberg@arm.com        packet->serialize(base + ".packet", os);
18411406Sandreas.sandberg@arm.com
18511406Sandreas.sandberg@arm.com    bool event_scheduled = doneEvent.scheduled();
18611406Sandreas.sandberg@arm.com    paramOut(os, base + ".event_scheduled", event_scheduled);
18711406Sandreas.sandberg@arm.com    if (event_scheduled) {
18811406Sandreas.sandberg@arm.com        Tick event_time = doneEvent.when();
18911406Sandreas.sandberg@arm.com        paramOut(os, base + ".event_time", event_time);
19011406Sandreas.sandberg@arm.com    }
19111406Sandreas.sandberg@arm.com
19211406Sandreas.sandberg@arm.com}
19311406Sandreas.sandberg@arm.com
19411406Sandreas.sandberg@arm.comvoid
19511406Sandreas.sandberg@arm.comEtherLink::Link::unserialize(const string &base, Checkpoint *cp,
19611406Sandreas.sandberg@arm.com                             const string &section)
19711406Sandreas.sandberg@arm.com{
19811406Sandreas.sandberg@arm.com    bool packet_exists;
19911406Sandreas.sandberg@arm.com    paramIn(cp, section, base + ".packet_exists", packet_exists);
20011406Sandreas.sandberg@arm.com    if (packet_exists) {
20111406Sandreas.sandberg@arm.com        packet = new EthPacketData(16384);
20211406Sandreas.sandberg@arm.com        packet->unserialize(base + ".packet", cp, section);
20311406Sandreas.sandberg@arm.com    }
20411406Sandreas.sandberg@arm.com
20511406Sandreas.sandberg@arm.com    bool event_scheduled;
20611406Sandreas.sandberg@arm.com    paramIn(cp, section, base + ".event_scheduled", event_scheduled);
20711406Sandreas.sandberg@arm.com    if (event_scheduled) {
20811406Sandreas.sandberg@arm.com        Tick event_time;
20911406Sandreas.sandberg@arm.com        paramIn(cp, section, base + ".event_time", event_time);
21011406Sandreas.sandberg@arm.com        doneEvent.schedule(event_time);
21111406Sandreas.sandberg@arm.com    }
21211406Sandreas.sandberg@arm.com}
21311406Sandreas.sandberg@arm.com
21411406Sandreas.sandberg@arm.comLinkDelayEvent::LinkDelayEvent()
21511406Sandreas.sandberg@arm.com    : Event(&mainEventQueue), link(NULL)
21611406Sandreas.sandberg@arm.com{
21711406Sandreas.sandberg@arm.com    setFlags(AutoSerialize);
21811406Sandreas.sandberg@arm.com    setFlags(AutoDelete);
21911406Sandreas.sandberg@arm.com}
22011406Sandreas.sandberg@arm.com
22111406Sandreas.sandberg@arm.comLinkDelayEvent::LinkDelayEvent(EtherLink::Link *l, EthPacketPtr p, Tick when)
22211406Sandreas.sandberg@arm.com    : Event(&mainEventQueue), link(l), packet(p)
22311406Sandreas.sandberg@arm.com{
22411406Sandreas.sandberg@arm.com    setFlags(AutoSerialize);
22511406Sandreas.sandberg@arm.com    setFlags(AutoDelete);
22611406Sandreas.sandberg@arm.com    schedule(when);
22711406Sandreas.sandberg@arm.com}
22811406Sandreas.sandberg@arm.com
22911406Sandreas.sandberg@arm.comvoid
23011406Sandreas.sandberg@arm.comLinkDelayEvent::process()
23111406Sandreas.sandberg@arm.com{
23211406Sandreas.sandberg@arm.com    link->txComplete(packet);
23311406Sandreas.sandberg@arm.com}
23411406Sandreas.sandberg@arm.com
23511406Sandreas.sandberg@arm.comvoid
23611406Sandreas.sandberg@arm.comLinkDelayEvent::serialize(ostream &os)
23711406Sandreas.sandberg@arm.com{
23811406Sandreas.sandberg@arm.com    paramOut(os, "type", string("LinkDelayEvent"));
23911406Sandreas.sandberg@arm.com    Event::serialize(os);
24011406Sandreas.sandberg@arm.com
24111406Sandreas.sandberg@arm.com    EtherLink *parent = link->parent;
24211406Sandreas.sandberg@arm.com    bool number = link->number;
24311406Sandreas.sandberg@arm.com    SERIALIZE_OBJPTR(parent);
24411406Sandreas.sandberg@arm.com    SERIALIZE_SCALAR(number);
24511406Sandreas.sandberg@arm.com
24611406Sandreas.sandberg@arm.com    packet->serialize("packet", os);
24711406Sandreas.sandberg@arm.com}
24811406Sandreas.sandberg@arm.com
24911406Sandreas.sandberg@arm.com
25011406Sandreas.sandberg@arm.comvoid
25111406Sandreas.sandberg@arm.comLinkDelayEvent::unserialize(Checkpoint *cp, const string &section)
25211406Sandreas.sandberg@arm.com{
25311406Sandreas.sandberg@arm.com    Event::unserialize(cp, section);
25411406Sandreas.sandberg@arm.com
25511406Sandreas.sandberg@arm.com    EtherLink *parent;
25611406Sandreas.sandberg@arm.com    bool number;
25711406Sandreas.sandberg@arm.com    UNSERIALIZE_OBJPTR(parent);
25811406Sandreas.sandberg@arm.com    UNSERIALIZE_SCALAR(number);
25911406Sandreas.sandberg@arm.com
26011406Sandreas.sandberg@arm.com    link = parent->link[number];
26111406Sandreas.sandberg@arm.com
26211406Sandreas.sandberg@arm.com    packet = new EthPacketData(16384);
26311406Sandreas.sandberg@arm.com    packet->unserialize("packet", cp, section);
26411406Sandreas.sandberg@arm.com}
26511406Sandreas.sandberg@arm.com
26611406Sandreas.sandberg@arm.com
26711406Sandreas.sandberg@arm.comSerializable *
26811406Sandreas.sandberg@arm.comLinkDelayEvent::createForUnserialize(Checkpoint *cp, const string &section)
26911406Sandreas.sandberg@arm.com{
27011406Sandreas.sandberg@arm.com    return new LinkDelayEvent();
27111406Sandreas.sandberg@arm.com}
27211406Sandreas.sandberg@arm.com
27311406Sandreas.sandberg@arm.comREGISTER_SERIALIZEABLE("LinkDelayEvent", LinkDelayEvent)
27411406Sandreas.sandberg@arm.com
27511406Sandreas.sandberg@arm.comEtherLink *
27611406Sandreas.sandberg@arm.comEtherLinkParams::create()
27711406Sandreas.sandberg@arm.com{
278    return new EtherLink(name, int1, int2, speed, delay, delay_var, dump);
279}
280