etherlink.cc revision 10469
11376Sbinkertn@umich.edu/* 21376Sbinkertn@umich.edu * Copyright (c) 2002-2005 The Regents of The University of Michigan 31376Sbinkertn@umich.edu * All rights reserved. 41376Sbinkertn@umich.edu * 51376Sbinkertn@umich.edu * Redistribution and use in source and binary forms, with or without 61376Sbinkertn@umich.edu * modification, are permitted provided that the following conditions are 71376Sbinkertn@umich.edu * met: redistributions of source code must retain the above copyright 81376Sbinkertn@umich.edu * notice, this list of conditions and the following disclaimer; 91376Sbinkertn@umich.edu * redistributions in binary form must reproduce the above copyright 101376Sbinkertn@umich.edu * notice, this list of conditions and the following disclaimer in the 111376Sbinkertn@umich.edu * documentation and/or other materials provided with the distribution; 121376Sbinkertn@umich.edu * neither the name of the copyright holders nor the names of its 131376Sbinkertn@umich.edu * contributors may be used to endorse or promote products derived from 141376Sbinkertn@umich.edu * this software without specific prior written permission. 151376Sbinkertn@umich.edu * 161376Sbinkertn@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 171376Sbinkertn@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 181376Sbinkertn@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 191376Sbinkertn@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 201376Sbinkertn@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 211376Sbinkertn@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 221376Sbinkertn@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 231376Sbinkertn@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 241376Sbinkertn@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 251376Sbinkertn@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 261376Sbinkertn@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 271376Sbinkertn@umich.edu * 281376Sbinkertn@umich.edu * Authors: Nathan Binkert 291376Sbinkertn@umich.edu * Ron Dreslinski 301376Sbinkertn@umich.edu */ 311385Sbinkertn@umich.edu 321376Sbinkertn@umich.edu/* @file 331376Sbinkertn@umich.edu * Device module for modelling a fixed bandwidth full duplex ethernet link 341376Sbinkertn@umich.edu */ 351376Sbinkertn@umich.edu 361376Sbinkertn@umich.edu#include <cmath> 371385Sbinkertn@umich.edu#include <deque> 381385Sbinkertn@umich.edu#include <string> 391385Sbinkertn@umich.edu#include <vector> 401385Sbinkertn@umich.edu 411385Sbinkertn@umich.edu#include "base/random.hh" 421385Sbinkertn@umich.edu#include "base/trace.hh" 431385Sbinkertn@umich.edu#include "debug/Ethernet.hh" 441385Sbinkertn@umich.edu#include "debug/EthernetData.hh" 451376Sbinkertn@umich.edu#include "dev/etherdump.hh" 461376Sbinkertn@umich.edu#include "dev/etherint.hh" 471376Sbinkertn@umich.edu#include "dev/etherlink.hh" 481376Sbinkertn@umich.edu#include "dev/etherpkt.hh" 491376Sbinkertn@umich.edu#include "params/EtherLink.hh" 501376Sbinkertn@umich.edu#include "sim/core.hh" 511376Sbinkertn@umich.edu#include "sim/serialize.hh" 521376Sbinkertn@umich.edu#include "sim/system.hh" 531376Sbinkertn@umich.edu 541376Sbinkertn@umich.eduusing namespace std; 551376Sbinkertn@umich.edu 561376Sbinkertn@umich.eduEtherLink::EtherLink(const Params *p) 571376Sbinkertn@umich.edu : EtherObject(p) 581376Sbinkertn@umich.edu{ 591376Sbinkertn@umich.edu link[0] = new Link(name() + ".link0", this, 0, p->speed, 601376Sbinkertn@umich.edu p->delay, p->delay_var, p->dump); 611376Sbinkertn@umich.edu link[1] = new Link(name() + ".link1", this, 1, p->speed, 621376Sbinkertn@umich.edu p->delay, p->delay_var, p->dump); 631376Sbinkertn@umich.edu 641376Sbinkertn@umich.edu interface[0] = new Interface(name() + ".int0", link[0], link[1]); 651381Sbinkertn@umich.edu interface[1] = new Interface(name() + ".int1", link[1], link[0]); 661376Sbinkertn@umich.edu} 671376Sbinkertn@umich.edu 681376Sbinkertn@umich.edu 691376Sbinkertn@umich.eduEtherLink::~EtherLink() 701376Sbinkertn@umich.edu{ 711376Sbinkertn@umich.edu delete link[0]; 721376Sbinkertn@umich.edu delete link[1]; 731376Sbinkertn@umich.edu 741376Sbinkertn@umich.edu delete interface[0]; 751376Sbinkertn@umich.edu delete interface[1]; 761385Sbinkertn@umich.edu} 771381Sbinkertn@umich.edu 781381Sbinkertn@umich.eduEtherInt* 791376Sbinkertn@umich.eduEtherLink::getEthPort(const std::string &if_name, int idx) 801381Sbinkertn@umich.edu{ 811381Sbinkertn@umich.edu Interface *i; 821381Sbinkertn@umich.edu if (if_name == "int0") 831376Sbinkertn@umich.edu i = interface[0]; 841381Sbinkertn@umich.edu else if (if_name == "int1") 851376Sbinkertn@umich.edu i = interface[1]; 861381Sbinkertn@umich.edu else 871376Sbinkertn@umich.edu return NULL; 881376Sbinkertn@umich.edu if (i->getPeer()) 891381Sbinkertn@umich.edu panic("interface already connected to\n"); 901376Sbinkertn@umich.edu 911381Sbinkertn@umich.edu return i; 921381Sbinkertn@umich.edu} 931381Sbinkertn@umich.edu 941376Sbinkertn@umich.edu 951376Sbinkertn@umich.eduEtherLink::Interface::Interface(const string &name, Link *tx, Link *rx) 961381Sbinkertn@umich.edu : EtherInt(name), txlink(tx) 971381Sbinkertn@umich.edu{ 981381Sbinkertn@umich.edu tx->setTxInt(this); 991376Sbinkertn@umich.edu rx->setRxInt(this); 1001376Sbinkertn@umich.edu} 1011376Sbinkertn@umich.edu 1021381Sbinkertn@umich.eduEtherLink::Link::Link(const string &name, EtherLink *p, int num, 1031385Sbinkertn@umich.edu double rate, Tick delay, Tick delay_var, EtherDump *d) 1041385Sbinkertn@umich.edu : objName(name), parent(p), number(num), txint(NULL), rxint(NULL), 1051381Sbinkertn@umich.edu ticksPerByte(rate), linkDelay(delay), delayVar(delay_var), dump(d), 1061376Sbinkertn@umich.edu doneEvent(this) 1071381Sbinkertn@umich.edu{ } 1081381Sbinkertn@umich.edu 1091376Sbinkertn@umich.eduvoid 1101376Sbinkertn@umich.eduEtherLink::serialize(ostream &os) 1111381Sbinkertn@umich.edu{ 1121376Sbinkertn@umich.edu link[0]->serialize("link0", os); 1131381Sbinkertn@umich.edu link[1]->serialize("link1", os); 1141376Sbinkertn@umich.edu} 1151376Sbinkertn@umich.edu 1161376Sbinkertn@umich.eduvoid 1171376Sbinkertn@umich.eduEtherLink::unserialize(Checkpoint *cp, const string §ion) 1181381Sbinkertn@umich.edu{ 1191376Sbinkertn@umich.edu link[0]->unserialize("link0", cp, section); 1201376Sbinkertn@umich.edu link[1]->unserialize("link1", cp, section); 1211376Sbinkertn@umich.edu} 1221376Sbinkertn@umich.edu 1231376Sbinkertn@umich.eduvoid 1241376Sbinkertn@umich.eduEtherLink::Link::txComplete(EthPacketPtr packet) 1251376Sbinkertn@umich.edu{ 1261376Sbinkertn@umich.edu DPRINTF(Ethernet, "packet received: len=%d\n", packet->length); 1271376Sbinkertn@umich.edu DDUMP(EthernetData, packet->data, packet->length); 1281376Sbinkertn@umich.edu rxint->sendPacket(packet); 1291376Sbinkertn@umich.edu} 1301376Sbinkertn@umich.edu 1311376Sbinkertn@umich.educlass LinkDelayEvent : public Event 1321376Sbinkertn@umich.edu{ 1331376Sbinkertn@umich.edu protected: 1341376Sbinkertn@umich.edu EtherLink::Link *link; 1351376Sbinkertn@umich.edu EthPacketPtr packet; 1361376Sbinkertn@umich.edu 1371376Sbinkertn@umich.edu public: 1381376Sbinkertn@umich.edu // non-scheduling version for createForUnserialize() 1391376Sbinkertn@umich.edu LinkDelayEvent(); 1401376Sbinkertn@umich.edu LinkDelayEvent(EtherLink::Link *link, EthPacketPtr pkt); 1411376Sbinkertn@umich.edu 1421376Sbinkertn@umich.edu void process(); 1431383Sbinkertn@umich.edu 1441376Sbinkertn@umich.edu virtual void serialize(ostream &os); 1451376Sbinkertn@umich.edu void unserialize(Checkpoint *cp, const string §ion) {} 1461383Sbinkertn@umich.edu void unserialize(Checkpoint *cp, const string §ion, 1471376Sbinkertn@umich.edu EventQueue *eventq); 1481376Sbinkertn@umich.edu static Serializable *createForUnserialize(Checkpoint *cp, 1491383Sbinkertn@umich.edu const string §ion); 1501383Sbinkertn@umich.edu}; 1511376Sbinkertn@umich.edu 1521376Sbinkertn@umich.eduvoid 1531376Sbinkertn@umich.eduEtherLink::Link::txDone() 1541376Sbinkertn@umich.edu{ 1551376Sbinkertn@umich.edu if (dump) 1561383Sbinkertn@umich.edu dump->dump(packet); 1571376Sbinkertn@umich.edu 1581383Sbinkertn@umich.edu if (linkDelay > 0) { 1591376Sbinkertn@umich.edu DPRINTF(Ethernet, "packet delayed: delay=%d\n", linkDelay); 1601376Sbinkertn@umich.edu Event *event = new LinkDelayEvent(this, packet); 1611376Sbinkertn@umich.edu parent->schedule(event, curTick() + linkDelay); 1621376Sbinkertn@umich.edu } else { 1631376Sbinkertn@umich.edu txComplete(packet); 1641376Sbinkertn@umich.edu } 1651376Sbinkertn@umich.edu 1661376Sbinkertn@umich.edu packet = 0; 1671376Sbinkertn@umich.edu assert(!busy()); 1681385Sbinkertn@umich.edu 1691385Sbinkertn@umich.edu txint->sendDone(); 1701376Sbinkertn@umich.edu} 1711376Sbinkertn@umich.edu 1721376Sbinkertn@umich.edubool 1731376Sbinkertn@umich.eduEtherLink::Link::transmit(EthPacketPtr pkt) 1741376Sbinkertn@umich.edu{ 1751376Sbinkertn@umich.edu if (busy()) { 1761376Sbinkertn@umich.edu DPRINTF(Ethernet, "packet not sent, link busy\n"); 1771376Sbinkertn@umich.edu return false; 1781376Sbinkertn@umich.edu } 1791376Sbinkertn@umich.edu 1801385Sbinkertn@umich.edu DPRINTF(Ethernet, "packet sent: len=%d\n", pkt->length); 1811376Sbinkertn@umich.edu DDUMP(EthernetData, pkt->data, pkt->length); 1821385Sbinkertn@umich.edu 1831385Sbinkertn@umich.edu packet = pkt; 1841385Sbinkertn@umich.edu Tick delay = (Tick)ceil(((double)pkt->length * ticksPerByte) + 1.0); 1851385Sbinkertn@umich.edu if (delayVar != 0) 1861385Sbinkertn@umich.edu delay += random_mt.random<Tick>(0, delayVar); 1871385Sbinkertn@umich.edu 1881385Sbinkertn@umich.edu DPRINTF(Ethernet, "scheduling packet: delay=%d, (rate=%f)\n", 1891385Sbinkertn@umich.edu delay, ticksPerByte); 1901385Sbinkertn@umich.edu parent->schedule(doneEvent, curTick() + delay); 191 192 return true; 193} 194 195void 196EtherLink::Link::serialize(const string &base, ostream &os) 197{ 198 bool packet_exists = packet != nullptr; 199 paramOut(os, base + ".packet_exists", packet_exists); 200 if (packet_exists) 201 packet->serialize(base + ".packet", os); 202 203 bool event_scheduled = doneEvent.scheduled(); 204 paramOut(os, base + ".event_scheduled", event_scheduled); 205 if (event_scheduled) { 206 Tick event_time = doneEvent.when(); 207 paramOut(os, base + ".event_time", event_time); 208 } 209 210} 211 212void 213EtherLink::Link::unserialize(const string &base, Checkpoint *cp, 214 const string §ion) 215{ 216 bool packet_exists; 217 paramIn(cp, section, base + ".packet_exists", packet_exists); 218 if (packet_exists) { 219 packet = make_shared<EthPacketData>(16384); 220 packet->unserialize(base + ".packet", cp, section); 221 } 222 223 bool event_scheduled; 224 paramIn(cp, section, base + ".event_scheduled", event_scheduled); 225 if (event_scheduled) { 226 Tick event_time; 227 paramIn(cp, section, base + ".event_time", event_time); 228 parent->schedule(doneEvent, event_time); 229 } 230} 231 232LinkDelayEvent::LinkDelayEvent() 233 : Event(Default_Pri, AutoSerialize | AutoDelete), link(NULL) 234{ 235} 236 237LinkDelayEvent::LinkDelayEvent(EtherLink::Link *l, EthPacketPtr p) 238 : Event(Default_Pri, AutoSerialize | AutoDelete), link(l), packet(p) 239{ 240} 241 242void 243LinkDelayEvent::process() 244{ 245 link->txComplete(packet); 246} 247 248void 249LinkDelayEvent::serialize(ostream &os) 250{ 251 paramOut(os, "type", string("LinkDelayEvent")); 252 Event::serialize(os); 253 254 EtherLink *parent = link->parent; 255 bool number = link->number; 256 SERIALIZE_OBJPTR(parent); 257 SERIALIZE_SCALAR(number); 258 259 packet->serialize("packet", os); 260} 261 262 263void 264LinkDelayEvent::unserialize(Checkpoint *cp, const string §ion, 265 EventQueue *eventq) 266{ 267 Event::unserialize(cp, section, eventq); 268 269 EtherLink *parent; 270 bool number; 271 UNSERIALIZE_OBJPTR(parent); 272 UNSERIALIZE_SCALAR(number); 273 274 link = parent->link[number]; 275 276 packet = make_shared<EthPacketData>(16384); 277 packet->unserialize("packet", cp, section); 278} 279 280 281Serializable * 282LinkDelayEvent::createForUnserialize(Checkpoint *cp, const string §ion) 283{ 284 return new LinkDelayEvent(); 285} 286 287REGISTER_SERIALIZEABLE("LinkDelayEvent", LinkDelayEvent) 288 289EtherLink * 290EtherLinkParams::create() 291{ 292 return new EtherLink(this); 293} 294