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 §ion) 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 §ion); 13011406Sandreas.sandberg@arm.com static Serializable *createForUnserialize(Checkpoint *cp, 13111406Sandreas.sandberg@arm.com const string §ion); 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 §ion) 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 §ion) 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 §ion) 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