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