etherlink.cc revision 5034
112697Santhony.gutierrez@amd.com/* 212697Santhony.gutierrez@amd.com * Copyright (c) 2002-2005 The Regents of The University of Michigan 311308Santhony.gutierrez@amd.com * All rights reserved. 412697Santhony.gutierrez@amd.com * 511308Santhony.gutierrez@amd.com * Redistribution and use in source and binary forms, with or without 612697Santhony.gutierrez@amd.com * modification, are permitted provided that the following conditions are 712697Santhony.gutierrez@amd.com * met: redistributions of source code must retain the above copyright 811308Santhony.gutierrez@amd.com * notice, this list of conditions and the following disclaimer; 912697Santhony.gutierrez@amd.com * redistributions in binary form must reproduce the above copyright 1012697Santhony.gutierrez@amd.com * notice, this list of conditions and the following disclaimer in the 1111308Santhony.gutierrez@amd.com * documentation and/or other materials provided with the distribution; 1212697Santhony.gutierrez@amd.com * neither the name of the copyright holders nor the names of its 1312697Santhony.gutierrez@amd.com * contributors may be used to endorse or promote products derived from 1412697Santhony.gutierrez@amd.com * this software without specific prior written permission. 1511308Santhony.gutierrez@amd.com * 1612697Santhony.gutierrez@amd.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1712697Santhony.gutierrez@amd.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1812697Santhony.gutierrez@amd.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1911308Santhony.gutierrez@amd.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2012697Santhony.gutierrez@amd.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2112697Santhony.gutierrez@amd.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2212697Santhony.gutierrez@amd.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2312697Santhony.gutierrez@amd.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2412697Santhony.gutierrez@amd.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2512697Santhony.gutierrez@amd.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2612697Santhony.gutierrez@amd.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2712697Santhony.gutierrez@amd.com * 2812697Santhony.gutierrez@amd.com * Authors: Nathan Binkert 2912697Santhony.gutierrez@amd.com * Ron Dreslinski 3012697Santhony.gutierrez@amd.com */ 3111308Santhony.gutierrez@amd.com 3212697Santhony.gutierrez@amd.com/* @file 3311308Santhony.gutierrez@amd.com * Device module for modelling a fixed bandwidth full duplex ethernet link 3411308Santhony.gutierrez@amd.com */ 3511308Santhony.gutierrez@amd.com 3611308Santhony.gutierrez@amd.com#include <cmath> 3711308Santhony.gutierrez@amd.com#include <deque> 3811308Santhony.gutierrez@amd.com#include <string> 3911308Santhony.gutierrez@amd.com#include <vector> 4011308Santhony.gutierrez@amd.com 4111670Sandreas.hansson@arm.com#include "base/random.hh" 4211670Sandreas.hansson@arm.com#include "base/trace.hh" 4311308Santhony.gutierrez@amd.com#include "dev/etherdump.hh" 4411308Santhony.gutierrez@amd.com#include "dev/etherint.hh" 4511308Santhony.gutierrez@amd.com#include "dev/etherlink.hh" 4611308Santhony.gutierrez@amd.com#include "dev/etherpkt.hh" 4711308Santhony.gutierrez@amd.com#include "params/EtherLink.hh" 4811308Santhony.gutierrez@amd.com#include "sim/serialize.hh" 4911308Santhony.gutierrez@amd.com#include "sim/system.hh" 5011308Santhony.gutierrez@amd.com#include "sim/core.hh" 5111308Santhony.gutierrez@amd.com 5211308Santhony.gutierrez@amd.comusing namespace std; 5311308Santhony.gutierrez@amd.com 5411308Santhony.gutierrez@amd.comEtherLink::EtherLink(const Params *p) 5511308Santhony.gutierrez@amd.com : EtherObject(p) 5611308Santhony.gutierrez@amd.com{ 5711308Santhony.gutierrez@amd.com link[0] = new Link(name() + ".link0", this, 0, p->speed, 5811308Santhony.gutierrez@amd.com p->delay, p->delay_var, p->dump); 5911308Santhony.gutierrez@amd.com link[1] = new Link(name() + ".link1", this, 1, p->speed, 6011308Santhony.gutierrez@amd.com p->delay, p->delay_var, p->dump); 6111308Santhony.gutierrez@amd.com 6211308Santhony.gutierrez@amd.com interface[0] = new Interface(name() + ".int0", link[0], link[1]); 6311308Santhony.gutierrez@amd.com interface[1] = new Interface(name() + ".int1", link[1], link[0]); 6411308Santhony.gutierrez@amd.com} 6511308Santhony.gutierrez@amd.com 6611308Santhony.gutierrez@amd.com 6711308Santhony.gutierrez@amd.comEtherLink::~EtherLink() 6811308Santhony.gutierrez@amd.com{ 6911308Santhony.gutierrez@amd.com delete link[0]; 7011308Santhony.gutierrez@amd.com delete link[1]; 7111308Santhony.gutierrez@amd.com 7211308Santhony.gutierrez@amd.com delete interface[0]; 7311308Santhony.gutierrez@amd.com delete interface[1]; 7411308Santhony.gutierrez@amd.com} 7511308Santhony.gutierrez@amd.com 7611308Santhony.gutierrez@amd.comEtherInt* 7711308Santhony.gutierrez@amd.comEtherLink::getEthPort(const std::string &if_name, int idx) 7811308Santhony.gutierrez@amd.com{ 7911308Santhony.gutierrez@amd.com Interface *i; 8011308Santhony.gutierrez@amd.com if (if_name == "int0") 8111308Santhony.gutierrez@amd.com i = interface[0]; 8211308Santhony.gutierrez@amd.com else if (if_name == "int1") 8311308Santhony.gutierrez@amd.com i = interface[1]; 8411308Santhony.gutierrez@amd.com else 8511308Santhony.gutierrez@amd.com return NULL; 8611308Santhony.gutierrez@amd.com if (i->getPeer()) 8711308Santhony.gutierrez@amd.com panic("interface already connected to\n"); 8811308Santhony.gutierrez@amd.com 8911308Santhony.gutierrez@amd.com return i; 9011308Santhony.gutierrez@amd.com} 9111308Santhony.gutierrez@amd.com 9211308Santhony.gutierrez@amd.com 9311308Santhony.gutierrez@amd.comEtherLink::Interface::Interface(const string &name, Link *tx, Link *rx) 9411308Santhony.gutierrez@amd.com : EtherInt(name), txlink(tx) 9511308Santhony.gutierrez@amd.com{ 9611308Santhony.gutierrez@amd.com tx->setTxInt(this); 9711308Santhony.gutierrez@amd.com rx->setRxInt(this); 9811308Santhony.gutierrez@amd.com} 9911308Santhony.gutierrez@amd.com 10011308Santhony.gutierrez@amd.comEtherLink::Link::Link(const string &name, EtherLink *p, int num, 10111308Santhony.gutierrez@amd.com double rate, Tick delay, Tick delay_var, EtherDump *d) 10211308Santhony.gutierrez@amd.com : objName(name), parent(p), number(num), txint(NULL), rxint(NULL), 10311308Santhony.gutierrez@amd.com ticksPerByte(rate), linkDelay(delay), delayVar(delay_var), dump(d), 10411308Santhony.gutierrez@amd.com doneEvent(this) 10511308Santhony.gutierrez@amd.com{ } 10611308Santhony.gutierrez@amd.com 10711308Santhony.gutierrez@amd.comvoid 10811308Santhony.gutierrez@amd.comEtherLink::serialize(ostream &os) 10911308Santhony.gutierrez@amd.com{ 11011308Santhony.gutierrez@amd.com link[0]->serialize("link0", os); 11111308Santhony.gutierrez@amd.com link[1]->serialize("link1", os); 11211308Santhony.gutierrez@amd.com} 11311308Santhony.gutierrez@amd.com 11411308Santhony.gutierrez@amd.comvoid 11511308Santhony.gutierrez@amd.comEtherLink::unserialize(Checkpoint *cp, const string §ion) 11611308Santhony.gutierrez@amd.com{ 11711308Santhony.gutierrez@amd.com link[0]->unserialize("link0", cp, section); 11811308Santhony.gutierrez@amd.com link[1]->unserialize("link1", cp, section); 11911308Santhony.gutierrez@amd.com} 12011308Santhony.gutierrez@amd.com 12111308Santhony.gutierrez@amd.comvoid 12211308Santhony.gutierrez@amd.comEtherLink::Link::txComplete(EthPacketPtr packet) 12311308Santhony.gutierrez@amd.com{ 12411308Santhony.gutierrez@amd.com DPRINTF(Ethernet, "packet received: len=%d\n", packet->length); 12511308Santhony.gutierrez@amd.com DDUMP(EthernetData, packet->data, packet->length); 12611308Santhony.gutierrez@amd.com rxint->sendPacket(packet); 12711308Santhony.gutierrez@amd.com} 12811308Santhony.gutierrez@amd.com 12911308Santhony.gutierrez@amd.comclass LinkDelayEvent : public Event 13011308Santhony.gutierrez@amd.com{ 13111308Santhony.gutierrez@amd.com protected: 13211308Santhony.gutierrez@amd.com EtherLink::Link *link; 13311308Santhony.gutierrez@amd.com EthPacketPtr packet; 13411308Santhony.gutierrez@amd.com 13511308Santhony.gutierrez@amd.com public: 13611308Santhony.gutierrez@amd.com // non-scheduling version for createForUnserialize() 13711308Santhony.gutierrez@amd.com LinkDelayEvent(); 13811308Santhony.gutierrez@amd.com LinkDelayEvent(EtherLink::Link *link, EthPacketPtr pkt, Tick when); 13911308Santhony.gutierrez@amd.com 14011308Santhony.gutierrez@amd.com void process(); 14111308Santhony.gutierrez@amd.com 14211308Santhony.gutierrez@amd.com virtual void serialize(ostream &os); 14311308Santhony.gutierrez@amd.com virtual void unserialize(Checkpoint *cp, const string §ion); 14411308Santhony.gutierrez@amd.com static Serializable *createForUnserialize(Checkpoint *cp, 14511308Santhony.gutierrez@amd.com const string §ion); 14611308Santhony.gutierrez@amd.com}; 14711308Santhony.gutierrez@amd.com 14811308Santhony.gutierrez@amd.comvoid 14911308Santhony.gutierrez@amd.comEtherLink::Link::txDone() 15011308Santhony.gutierrez@amd.com{ 15111308Santhony.gutierrez@amd.com if (dump) 15211308Santhony.gutierrez@amd.com dump->dump(packet); 15311308Santhony.gutierrez@amd.com 15411308Santhony.gutierrez@amd.com if (linkDelay > 0) { 15511308Santhony.gutierrez@amd.com DPRINTF(Ethernet, "packet delayed: delay=%d\n", linkDelay); 15611308Santhony.gutierrez@amd.com new LinkDelayEvent(this, packet, curTick + linkDelay); 15711308Santhony.gutierrez@amd.com } else { 15811308Santhony.gutierrez@amd.com txComplete(packet); 15911308Santhony.gutierrez@amd.com } 16011308Santhony.gutierrez@amd.com 16111308Santhony.gutierrez@amd.com packet = 0; 16211308Santhony.gutierrez@amd.com assert(!busy()); 16311308Santhony.gutierrez@amd.com 16411308Santhony.gutierrez@amd.com txint->sendDone(); 16511308Santhony.gutierrez@amd.com} 16611308Santhony.gutierrez@amd.com 16711308Santhony.gutierrez@amd.combool 16812065Snikos.nikoleris@arm.comEtherLink::Link::transmit(EthPacketPtr pkt) 16911308Santhony.gutierrez@amd.com{ 17011308Santhony.gutierrez@amd.com if (busy()) { 17111308Santhony.gutierrez@amd.com DPRINTF(Ethernet, "packet not sent, link busy\n"); 17211308Santhony.gutierrez@amd.com return false; 17312065Snikos.nikoleris@arm.com } 17412065Snikos.nikoleris@arm.com 17511308Santhony.gutierrez@amd.com DPRINTF(Ethernet, "packet sent: len=%d\n", pkt->length); 17611308Santhony.gutierrez@amd.com DDUMP(EthernetData, pkt->data, pkt->length); 17711308Santhony.gutierrez@amd.com 17811308Santhony.gutierrez@amd.com packet = pkt; 17911308Santhony.gutierrez@amd.com Tick delay = (Tick)ceil(((double)pkt->length * ticksPerByte) + 1.0); 18011308Santhony.gutierrez@amd.com if (delayVar != 0) { 18111308Santhony.gutierrez@amd.com Random<Tick> var; 18211308Santhony.gutierrez@amd.com delay += var.uniform(0, delayVar); 18311308Santhony.gutierrez@amd.com } 18411308Santhony.gutierrez@amd.com DPRINTF(Ethernet, "scheduling packet: delay=%d, (rate=%f)\n", 18511308Santhony.gutierrez@amd.com delay, ticksPerByte); 18611308Santhony.gutierrez@amd.com doneEvent.schedule(curTick + delay); 18711308Santhony.gutierrez@amd.com 18811308Santhony.gutierrez@amd.com return true; 18911308Santhony.gutierrez@amd.com} 19011308Santhony.gutierrez@amd.com 19111308Santhony.gutierrez@amd.comvoid 19211308Santhony.gutierrez@amd.comEtherLink::Link::serialize(const string &base, ostream &os) 19311308Santhony.gutierrez@amd.com{ 19411308Santhony.gutierrez@amd.com bool packet_exists = packet; 19511308Santhony.gutierrez@amd.com paramOut(os, base + ".packet_exists", packet_exists); 19611308Santhony.gutierrez@amd.com if (packet_exists) 19711308Santhony.gutierrez@amd.com packet->serialize(base + ".packet", os); 19811308Santhony.gutierrez@amd.com 19911308Santhony.gutierrez@amd.com bool event_scheduled = doneEvent.scheduled(); 20011308Santhony.gutierrez@amd.com paramOut(os, base + ".event_scheduled", event_scheduled); 20111308Santhony.gutierrez@amd.com if (event_scheduled) { 20211308Santhony.gutierrez@amd.com Tick event_time = doneEvent.when(); 20311308Santhony.gutierrez@amd.com paramOut(os, base + ".event_time", event_time); 20411308Santhony.gutierrez@amd.com } 20511308Santhony.gutierrez@amd.com 20611308Santhony.gutierrez@amd.com} 20711308Santhony.gutierrez@amd.com 20811308Santhony.gutierrez@amd.comvoid 20911308Santhony.gutierrez@amd.comEtherLink::Link::unserialize(const string &base, Checkpoint *cp, 21012598Snikos.nikoleris@arm.com const string §ion) 21112598Snikos.nikoleris@arm.com{ 21211308Santhony.gutierrez@amd.com bool packet_exists; 21311308Santhony.gutierrez@amd.com paramIn(cp, section, base + ".packet_exists", packet_exists); 21411308Santhony.gutierrez@amd.com if (packet_exists) { 21511308Santhony.gutierrez@amd.com packet = new EthPacketData(16384); 21611308Santhony.gutierrez@amd.com packet->unserialize(base + ".packet", cp, section); 21711308Santhony.gutierrez@amd.com } 21811308Santhony.gutierrez@amd.com 21911308Santhony.gutierrez@amd.com bool event_scheduled; 22011308Santhony.gutierrez@amd.com paramIn(cp, section, base + ".event_scheduled", event_scheduled); 22111308Santhony.gutierrez@amd.com if (event_scheduled) { 22211308Santhony.gutierrez@amd.com Tick event_time; 22311308Santhony.gutierrez@amd.com paramIn(cp, section, base + ".event_time", event_time); 22411308Santhony.gutierrez@amd.com doneEvent.schedule(event_time); 22511308Santhony.gutierrez@amd.com } 22611308Santhony.gutierrez@amd.com} 22711308Santhony.gutierrez@amd.com 22811308Santhony.gutierrez@amd.comLinkDelayEvent::LinkDelayEvent() 22911308Santhony.gutierrez@amd.com : Event(&mainEventQueue), link(NULL) 23011308Santhony.gutierrez@amd.com{ 23111308Santhony.gutierrez@amd.com setFlags(AutoSerialize); 23211308Santhony.gutierrez@amd.com setFlags(AutoDelete); 23311308Santhony.gutierrez@amd.com} 23411308Santhony.gutierrez@amd.com 23511308Santhony.gutierrez@amd.comLinkDelayEvent::LinkDelayEvent(EtherLink::Link *l, EthPacketPtr p, Tick when) 23611308Santhony.gutierrez@amd.com : Event(&mainEventQueue), link(l), packet(p) 23712065Snikos.nikoleris@arm.com{ 23812065Snikos.nikoleris@arm.com setFlags(AutoSerialize); 23912065Snikos.nikoleris@arm.com setFlags(AutoDelete); 24012065Snikos.nikoleris@arm.com schedule(when); 24112065Snikos.nikoleris@arm.com} 24212065Snikos.nikoleris@arm.com 24312065Snikos.nikoleris@arm.comvoid 24412065Snikos.nikoleris@arm.comLinkDelayEvent::process() 24512065Snikos.nikoleris@arm.com{ 24612065Snikos.nikoleris@arm.com link->txComplete(packet); 24712065Snikos.nikoleris@arm.com} 24811308Santhony.gutierrez@amd.com 24912065Snikos.nikoleris@arm.comvoid 25012065Snikos.nikoleris@arm.comLinkDelayEvent::serialize(ostream &os) 25112065Snikos.nikoleris@arm.com{ 25212065Snikos.nikoleris@arm.com paramOut(os, "type", string("LinkDelayEvent")); 25312065Snikos.nikoleris@arm.com Event::serialize(os); 25412065Snikos.nikoleris@arm.com 25512065Snikos.nikoleris@arm.com EtherLink *parent = link->parent; 25612065Snikos.nikoleris@arm.com bool number = link->number; 25711308Santhony.gutierrez@amd.com SERIALIZE_OBJPTR(parent); 25811308Santhony.gutierrez@amd.com SERIALIZE_SCALAR(number); 25912065Snikos.nikoleris@arm.com 26011308Santhony.gutierrez@amd.com packet->serialize("packet", os); 26111308Santhony.gutierrez@amd.com} 26211308Santhony.gutierrez@amd.com 26311308Santhony.gutierrez@amd.com 26411308Santhony.gutierrez@amd.comvoid 26511308Santhony.gutierrez@amd.comLinkDelayEvent::unserialize(Checkpoint *cp, const string §ion) 26611308Santhony.gutierrez@amd.com{ 26711308Santhony.gutierrez@amd.com Event::unserialize(cp, section); 26811308Santhony.gutierrez@amd.com 26911308Santhony.gutierrez@amd.com EtherLink *parent; 27011308Santhony.gutierrez@amd.com bool number; 27111308Santhony.gutierrez@amd.com UNSERIALIZE_OBJPTR(parent); 27211308Santhony.gutierrez@amd.com UNSERIALIZE_SCALAR(number); 27311308Santhony.gutierrez@amd.com 27411308Santhony.gutierrez@amd.com link = parent->link[number]; 27511308Santhony.gutierrez@amd.com 27611308Santhony.gutierrez@amd.com packet = new EthPacketData(16384); 27711308Santhony.gutierrez@amd.com packet->unserialize("packet", cp, section); 27811308Santhony.gutierrez@amd.com} 27911308Santhony.gutierrez@amd.com 28011308Santhony.gutierrez@amd.com 28111308Santhony.gutierrez@amd.comSerializable * 28211308Santhony.gutierrez@amd.comLinkDelayEvent::createForUnserialize(Checkpoint *cp, const string §ion) 28311308Santhony.gutierrez@amd.com{ 28411308Santhony.gutierrez@amd.com return new LinkDelayEvent(); 28511308Santhony.gutierrez@amd.com} 28611308Santhony.gutierrez@amd.com 28711308Santhony.gutierrez@amd.comREGISTER_SERIALIZEABLE("LinkDelayEvent", LinkDelayEvent) 28811308Santhony.gutierrez@amd.com 28911308Santhony.gutierrez@amd.comEtherLink * 29011308Santhony.gutierrez@amd.comEtherLinkParams::create() 29111308Santhony.gutierrez@amd.com{ 29211308Santhony.gutierrez@amd.com return new EtherLink(this); 29311308Santhony.gutierrez@amd.com} 29411308Santhony.gutierrez@amd.com