etherlink.cc revision 1078
111986Sandreas.sandberg@arm.com/*
211986Sandreas.sandberg@arm.com * Copyright (c) 2002-2004 The Regents of The University of Michigan
311986Sandreas.sandberg@arm.com * All rights reserved.
411986Sandreas.sandberg@arm.com *
511986Sandreas.sandberg@arm.com * Redistribution and use in source and binary forms, with or without
611986Sandreas.sandberg@arm.com * modification, are permitted provided that the following conditions are
711986Sandreas.sandberg@arm.com * met: redistributions of source code must retain the above copyright
811986Sandreas.sandberg@arm.com * notice, this list of conditions and the following disclaimer;
911986Sandreas.sandberg@arm.com * redistributions in binary form must reproduce the above copyright
1011986Sandreas.sandberg@arm.com * notice, this list of conditions and the following disclaimer in the
1111986Sandreas.sandberg@arm.com * documentation and/or other materials provided with the distribution;
1211986Sandreas.sandberg@arm.com * neither the name of the copyright holders nor the names of its
1311986Sandreas.sandberg@arm.com * contributors may be used to endorse or promote products derived from
1411986Sandreas.sandberg@arm.com * this software without specific prior written permission.
1511986Sandreas.sandberg@arm.com *
1611986Sandreas.sandberg@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1711986Sandreas.sandberg@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1811986Sandreas.sandberg@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1911986Sandreas.sandberg@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2011986Sandreas.sandberg@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2111986Sandreas.sandberg@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2211986Sandreas.sandberg@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2311986Sandreas.sandberg@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2411986Sandreas.sandberg@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2511986Sandreas.sandberg@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2611986Sandreas.sandberg@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2712037Sandreas.sandberg@arm.com */
2811986Sandreas.sandberg@arm.com
2911986Sandreas.sandberg@arm.com/* @file
3011986Sandreas.sandberg@arm.com * Device module for modelling a fixed bandwidth full duplex ethernet link
3111986Sandreas.sandberg@arm.com */
3211986Sandreas.sandberg@arm.com
3311986Sandreas.sandberg@arm.com#include <cmath>
3411986Sandreas.sandberg@arm.com#include <deque>
3511986Sandreas.sandberg@arm.com#include <string>
3611986Sandreas.sandberg@arm.com#include <vector>
3711986Sandreas.sandberg@arm.com
3811986Sandreas.sandberg@arm.com#include "base/trace.hh"
3911986Sandreas.sandberg@arm.com#include "dev/etherdump.hh"
4011986Sandreas.sandberg@arm.com#include "dev/etherint.hh"
4111986Sandreas.sandberg@arm.com#include "dev/etherlink.hh"
4211986Sandreas.sandberg@arm.com#include "dev/etherpkt.hh"
4311986Sandreas.sandberg@arm.com#include "sim/builder.hh"
4412037Sandreas.sandberg@arm.com#include "sim/serialize.hh"
4511986Sandreas.sandberg@arm.com#include "sim/system.hh"
4611986Sandreas.sandberg@arm.com#include "sim/universe.hh"
4711986Sandreas.sandberg@arm.com
4811986Sandreas.sandberg@arm.comusing namespace std;
4911986Sandreas.sandberg@arm.com
5011986Sandreas.sandberg@arm.comEtherLink::EtherLink(const string &name, EtherInt *i1, EtherInt *i2,
5111986Sandreas.sandberg@arm.com                     Tick speed, Tick dly, EtherDump *dump)
5211986Sandreas.sandberg@arm.com    : SimObject(name)
5311986Sandreas.sandberg@arm.com{
5411986Sandreas.sandberg@arm.com    double rate = ((double)ticksPerSecond * 8.0) / (double)speed;
5511986Sandreas.sandberg@arm.com    Tick delay = US2Ticks(dly);
5611986Sandreas.sandberg@arm.com
5711986Sandreas.sandberg@arm.com    link1 = new Link(name + ".link1", rate, delay, dump);
5811986Sandreas.sandberg@arm.com    link2 = new Link(name + ".link2", rate, delay, dump);
5911986Sandreas.sandberg@arm.com
6011986Sandreas.sandberg@arm.com    int1 = new Interface(name + ".int1", link1, link2);
6111986Sandreas.sandberg@arm.com    int2 = new Interface(name + ".int2", link2, link1);
6211986Sandreas.sandberg@arm.com
6311986Sandreas.sandberg@arm.com    int1->setPeer(i1);
6411986Sandreas.sandberg@arm.com    i1->setPeer(int1);
6511986Sandreas.sandberg@arm.com    int2->setPeer(i2);
6611986Sandreas.sandberg@arm.com    i2->setPeer(int2);
6711986Sandreas.sandberg@arm.com}
6811986Sandreas.sandberg@arm.com
6911986Sandreas.sandberg@arm.comEtherLink::~EtherLink()
7011986Sandreas.sandberg@arm.com{
7111986Sandreas.sandberg@arm.com    delete link1;
7211986Sandreas.sandberg@arm.com    delete link2;
7311986Sandreas.sandberg@arm.com
7411986Sandreas.sandberg@arm.com    delete int1;
7511986Sandreas.sandberg@arm.com    delete int2;
7611986Sandreas.sandberg@arm.com}
7711986Sandreas.sandberg@arm.com
7811986Sandreas.sandberg@arm.comEtherLink::Interface::Interface(const string &name, Link *tx, Link *rx)
7911986Sandreas.sandberg@arm.com    : EtherInt(name), txlink(tx)
8011986Sandreas.sandberg@arm.com{
8111986Sandreas.sandberg@arm.com    tx->setTxInt(this);
8211986Sandreas.sandberg@arm.com    rx->setRxInt(this);
8311986Sandreas.sandberg@arm.com}
8411986Sandreas.sandberg@arm.com
8511986Sandreas.sandberg@arm.comEtherLink::Link::Link(const string &name, double rate, Tick delay,
8611986Sandreas.sandberg@arm.com                      EtherDump *d)
8711986Sandreas.sandberg@arm.com    : objName(name), txint(NULL), rxint(NULL), ticksPerByte(rate),
8812037Sandreas.sandberg@arm.com      linkDelay(delay), dump(d), doneEvent(this)
8911986Sandreas.sandberg@arm.com{}
9011986Sandreas.sandberg@arm.com
9111986Sandreas.sandberg@arm.comvoid
9211986Sandreas.sandberg@arm.comEtherLink::serialize(ostream &os)
9312037Sandreas.sandberg@arm.com{
9411986Sandreas.sandberg@arm.com    nameOut(os, name() + ".link1");
9511986Sandreas.sandberg@arm.com    link1->serialize(os);
9611986Sandreas.sandberg@arm.com    nameOut(os, name() + ".link2");
9711986Sandreas.sandberg@arm.com    link2->serialize(os);
9812037Sandreas.sandberg@arm.com}
9911986Sandreas.sandberg@arm.com
10011986Sandreas.sandberg@arm.comvoid
10112037Sandreas.sandberg@arm.comEtherLink::unserialize(Checkpoint *cp, const string &section)
10212037Sandreas.sandberg@arm.com{
10311986Sandreas.sandberg@arm.com    link1->unserialize(cp, section + ".link1");
10411986Sandreas.sandberg@arm.com    link2->unserialize(cp, section + ".link2");
10512037Sandreas.sandberg@arm.com}
10612037Sandreas.sandberg@arm.com
10712037Sandreas.sandberg@arm.comvoid
10812037Sandreas.sandberg@arm.comEtherLink::Link::txComplete(PacketPtr &packet)
10912037Sandreas.sandberg@arm.com{
11012037Sandreas.sandberg@arm.com    DPRINTF(Ethernet, "packet received: len=%d\n", packet->length);
11112037Sandreas.sandberg@arm.com    DDUMP(EthernetData, packet->data, packet->length);
11212037Sandreas.sandberg@arm.com    rxint->sendPacket(packet);
11312037Sandreas.sandberg@arm.com}
11412037Sandreas.sandberg@arm.com
11512037Sandreas.sandberg@arm.comclass LinkDelayEvent : public Event
11612037Sandreas.sandberg@arm.com{
11712037Sandreas.sandberg@arm.com  protected:
11812037Sandreas.sandberg@arm.com    EtherLink::Link *link;
11912037Sandreas.sandberg@arm.com    PacketPtr packet;
12012037Sandreas.sandberg@arm.com
12112037Sandreas.sandberg@arm.com    // non-scheduling version for createForUnserialize()
12212037Sandreas.sandberg@arm.com    LinkDelayEvent(EtherLink::Link *link);
12312037Sandreas.sandberg@arm.com
12412037Sandreas.sandberg@arm.com  public:
12511986Sandreas.sandberg@arm.com    LinkDelayEvent(EtherLink::Link *link, PacketPtr &pkt, Tick when);
12611986Sandreas.sandberg@arm.com
12711986Sandreas.sandberg@arm.com    void process();
12812037Sandreas.sandberg@arm.com
12911986Sandreas.sandberg@arm.com    virtual void serialize(ostream &os);
13012037Sandreas.sandberg@arm.com    virtual void unserialize(Checkpoint *cp, const string &section);
13112037Sandreas.sandberg@arm.com    static Serializable *createForUnserialize(Checkpoint *cp,
13212037Sandreas.sandberg@arm.com                                              const string &section);
13311986Sandreas.sandberg@arm.com};
13411986Sandreas.sandberg@arm.com
13511986Sandreas.sandberg@arm.com
13611986Sandreas.sandberg@arm.comvoid
13711986Sandreas.sandberg@arm.comEtherLink::Link::txDone()
13811986Sandreas.sandberg@arm.com{
13911986Sandreas.sandberg@arm.com    if (dump)
14011986Sandreas.sandberg@arm.com        dump->dump(packet);
14111986Sandreas.sandberg@arm.com
14211986Sandreas.sandberg@arm.com    if (linkDelay > 0) {
14311986Sandreas.sandberg@arm.com        DPRINTF(Ethernet, "packet delayed: delay=%d\n", linkDelay);
14411986Sandreas.sandberg@arm.com        new LinkDelayEvent(this, packet, curTick + linkDelay);
14511986Sandreas.sandberg@arm.com    } else {
14611986Sandreas.sandberg@arm.com        txComplete(packet);
14711986Sandreas.sandberg@arm.com    }
14811986Sandreas.sandberg@arm.com
14911986Sandreas.sandberg@arm.com    packet = 0;
15011986Sandreas.sandberg@arm.com    assert(!busy());
15111986Sandreas.sandberg@arm.com
15211986Sandreas.sandberg@arm.com    txint->sendDone();
15311986Sandreas.sandberg@arm.com}
15411986Sandreas.sandberg@arm.com
15511986Sandreas.sandberg@arm.combool
15611986Sandreas.sandberg@arm.comEtherLink::Link::transmit(PacketPtr &pkt)
15711986Sandreas.sandberg@arm.com{
15811986Sandreas.sandberg@arm.com    if (busy()) {
15911986Sandreas.sandberg@arm.com        DPRINTF(Ethernet, "packet not sent, link busy\n");
16011986Sandreas.sandberg@arm.com        return false;
16112037Sandreas.sandberg@arm.com    }
16212037Sandreas.sandberg@arm.com
16312037Sandreas.sandberg@arm.com    DPRINTF(Ethernet, "packet sent: len=%d\n", pkt->length);
16411986Sandreas.sandberg@arm.com    DDUMP(EthernetData, pkt->data, pkt->length);
16511986Sandreas.sandberg@arm.com
16611986Sandreas.sandberg@arm.com    packet = pkt;
16711986Sandreas.sandberg@arm.com    Tick delay = (Tick)ceil(((double)pkt->length * ticksPerByte) + 1.0);
16811986Sandreas.sandberg@arm.com    DPRINTF(Ethernet, "scheduling packet: delay=%d, (rate=%f)\n",
16911986Sandreas.sandberg@arm.com            delay, ticksPerByte);
17011986Sandreas.sandberg@arm.com    doneEvent.schedule(curTick + delay);
17111986Sandreas.sandberg@arm.com
17212391Sjason@lowepower.com    return true;
17311986Sandreas.sandberg@arm.com}
17411986Sandreas.sandberg@arm.com
17511986Sandreas.sandberg@arm.comvoid
17611986Sandreas.sandberg@arm.comEtherLink::Link::serialize(ostream &os)
17711986Sandreas.sandberg@arm.com{
17811986Sandreas.sandberg@arm.com    bool packet_exists = packet;
17911986Sandreas.sandberg@arm.com    SERIALIZE_SCALAR(packet_exists);
18011986Sandreas.sandberg@arm.com
18111986Sandreas.sandberg@arm.com    bool event_scheduled = doneEvent.scheduled();
18211986Sandreas.sandberg@arm.com    SERIALIZE_SCALAR(event_scheduled);
18311986Sandreas.sandberg@arm.com    if (event_scheduled) {
18411986Sandreas.sandberg@arm.com        Tick event_time = doneEvent.when();
18511986Sandreas.sandberg@arm.com        SERIALIZE_SCALAR(event_time);
18611986Sandreas.sandberg@arm.com    }
18711986Sandreas.sandberg@arm.com
18811986Sandreas.sandberg@arm.com    if (packet_exists) {
18911986Sandreas.sandberg@arm.com        nameOut(os, csprintf("%s.packet", name()));
19011986Sandreas.sandberg@arm.com        packet->serialize(os);
19111986Sandreas.sandberg@arm.com    }
19211986Sandreas.sandberg@arm.com}
19311986Sandreas.sandberg@arm.com
19411986Sandreas.sandberg@arm.comvoid
19511986Sandreas.sandberg@arm.comEtherLink::Link::unserialize(Checkpoint *cp, const string &section)
19611986Sandreas.sandberg@arm.com{
19711986Sandreas.sandberg@arm.com    bool packet_exists;
19811986Sandreas.sandberg@arm.com    UNSERIALIZE_SCALAR(packet_exists);
19911986Sandreas.sandberg@arm.com    if (packet_exists) {
20011986Sandreas.sandberg@arm.com        packet = new PacketData;
20111986Sandreas.sandberg@arm.com        packet->unserialize(cp, csprintf("%s.packet", section));
20211986Sandreas.sandberg@arm.com    }
20311986Sandreas.sandberg@arm.com
20411986Sandreas.sandberg@arm.com    bool event_scheduled;
20511986Sandreas.sandberg@arm.com    UNSERIALIZE_SCALAR(event_scheduled);
20611986Sandreas.sandberg@arm.com    if (event_scheduled) {
20711986Sandreas.sandberg@arm.com        Tick event_time;
20811986Sandreas.sandberg@arm.com        UNSERIALIZE_SCALAR(event_time);
20911986Sandreas.sandberg@arm.com        doneEvent.schedule(event_time);
21011986Sandreas.sandberg@arm.com    }
21111986Sandreas.sandberg@arm.com}
21211986Sandreas.sandberg@arm.com
21311986Sandreas.sandberg@arm.comLinkDelayEvent::LinkDelayEvent(EtherLink::Link *l)
21411986Sandreas.sandberg@arm.com    : Event(&mainEventQueue), link(l)
21511986Sandreas.sandberg@arm.com{
21611986Sandreas.sandberg@arm.com    setFlags(AutoSerialize);
21711986Sandreas.sandberg@arm.com    setFlags(AutoDelete);
21811986Sandreas.sandberg@arm.com}
21911986Sandreas.sandberg@arm.com
22011986Sandreas.sandberg@arm.comLinkDelayEvent::LinkDelayEvent(EtherLink::Link *l, PacketPtr &p, Tick when)
22111986Sandreas.sandberg@arm.com    : Event(&mainEventQueue), link(l), packet(p)
22211986Sandreas.sandberg@arm.com{
22311986Sandreas.sandberg@arm.com    setFlags(AutoSerialize);
22411986Sandreas.sandberg@arm.com    setFlags(AutoDelete);
22511986Sandreas.sandberg@arm.com    schedule(when);
22611986Sandreas.sandberg@arm.com}
22711986Sandreas.sandberg@arm.com
22811986Sandreas.sandberg@arm.comvoid
22911986Sandreas.sandberg@arm.comLinkDelayEvent::process()
23011986Sandreas.sandberg@arm.com{
23111986Sandreas.sandberg@arm.com    link->txComplete(packet);
23211986Sandreas.sandberg@arm.com}
23311986Sandreas.sandberg@arm.com
23411986Sandreas.sandberg@arm.comvoid
23511986Sandreas.sandberg@arm.comLinkDelayEvent::serialize(ostream &os)
23611986Sandreas.sandberg@arm.com{
23711986Sandreas.sandberg@arm.com    paramOut(os, "type", string("LinkDelayEvent"));
23811986Sandreas.sandberg@arm.com    Event::serialize(os);
23911986Sandreas.sandberg@arm.com    SERIALIZE_OBJPTR(link);
24011986Sandreas.sandberg@arm.com
24111986Sandreas.sandberg@arm.com    nameOut(os, csprintf("%s.packet", name()));
24211986Sandreas.sandberg@arm.com    packet->serialize(os);
24311986Sandreas.sandberg@arm.com}
24411986Sandreas.sandberg@arm.com
24511986Sandreas.sandberg@arm.com
24611986Sandreas.sandberg@arm.comvoid
24711986Sandreas.sandberg@arm.comLinkDelayEvent::unserialize(Checkpoint *cp, const string &section)
24811986Sandreas.sandberg@arm.com{
24911986Sandreas.sandberg@arm.com    Event::unserialize(cp, section);
25011986Sandreas.sandberg@arm.com    packet = new PacketData;
25111986Sandreas.sandberg@arm.com    packet->unserialize(cp, csprintf("%s.packet", section));
25211986Sandreas.sandberg@arm.com}
25311986Sandreas.sandberg@arm.com
25411986Sandreas.sandberg@arm.com
25511986Sandreas.sandberg@arm.comSerializable *
25611986Sandreas.sandberg@arm.comLinkDelayEvent::createForUnserialize(Checkpoint *cp, const string &section)
25711986Sandreas.sandberg@arm.com{
25811986Sandreas.sandberg@arm.com    EtherLink::Link *link;
25911986Sandreas.sandberg@arm.com    UNSERIALIZE_OBJPTR(link);
26011986Sandreas.sandberg@arm.com    return new LinkDelayEvent(link);
26111986Sandreas.sandberg@arm.com}
26211986Sandreas.sandberg@arm.com
26311986Sandreas.sandberg@arm.comREGISTER_SERIALIZEABLE("LinkDelayEvent", LinkDelayEvent)
26411986Sandreas.sandberg@arm.com
26511986Sandreas.sandberg@arm.comBEGIN_DECLARE_SIM_OBJECT_PARAMS(EtherLink)
26611986Sandreas.sandberg@arm.com
26711986Sandreas.sandberg@arm.com    SimObjectParam<EtherInt *> interface1;
26811986Sandreas.sandberg@arm.com    SimObjectParam<EtherInt *> interface2;
26911986Sandreas.sandberg@arm.com    Param<Tick> link_speed;
27011986Sandreas.sandberg@arm.com    Param<Tick> link_delay;
27111986Sandreas.sandberg@arm.com    SimObjectParam<EtherDump *> packet_dump;
27211986Sandreas.sandberg@arm.com
27311986Sandreas.sandberg@arm.comEND_DECLARE_SIM_OBJECT_PARAMS(EtherLink)
27411986Sandreas.sandberg@arm.com
27511986Sandreas.sandberg@arm.comBEGIN_INIT_SIM_OBJECT_PARAMS(EtherLink)
27611986Sandreas.sandberg@arm.com
277    INIT_PARAM(interface1, "interface 1"),
278    INIT_PARAM(interface2, "interface 2"),
279    INIT_PARAM_DFLT(link_speed, "link speed in bits per second", 100000000),
280    INIT_PARAM_DFLT(link_delay, "transmit delay of packets in us", 0),
281    INIT_PARAM_DFLT(packet_dump, "object to dump network packets to", NULL)
282
283END_INIT_SIM_OBJECT_PARAMS(EtherLink)
284
285CREATE_SIM_OBJECT(EtherLink)
286{
287    return new EtherLink(getInstanceName(), interface1, interface2, link_speed,
288                         link_delay, packet_dump);
289}
290
291REGISTER_SIM_OBJECT("EtherLink", EtherLink)
292