etherlink.cc revision 4762
16892SBrad.Beckmann@amd.com/* 26892SBrad.Beckmann@amd.com * Copyright (c) 2002-2005 The Regents of The University of Michigan 36892SBrad.Beckmann@amd.com * All rights reserved. 46892SBrad.Beckmann@amd.com * 56892SBrad.Beckmann@amd.com * Redistribution and use in source and binary forms, with or without 66892SBrad.Beckmann@amd.com * modification, are permitted provided that the following conditions are 76892SBrad.Beckmann@amd.com * met: redistributions of source code must retain the above copyright 86892SBrad.Beckmann@amd.com * notice, this list of conditions and the following disclaimer; 96892SBrad.Beckmann@amd.com * redistributions in binary form must reproduce the above copyright 106892SBrad.Beckmann@amd.com * notice, this list of conditions and the following disclaimer in the 116892SBrad.Beckmann@amd.com * documentation and/or other materials provided with the distribution; 126892SBrad.Beckmann@amd.com * neither the name of the copyright holders nor the names of its 136892SBrad.Beckmann@amd.com * contributors may be used to endorse or promote products derived from 146892SBrad.Beckmann@amd.com * this software without specific prior written permission. 156892SBrad.Beckmann@amd.com * 166892SBrad.Beckmann@amd.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 176892SBrad.Beckmann@amd.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 186892SBrad.Beckmann@amd.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 196892SBrad.Beckmann@amd.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 206892SBrad.Beckmann@amd.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 216892SBrad.Beckmann@amd.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 226892SBrad.Beckmann@amd.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 236892SBrad.Beckmann@amd.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 246892SBrad.Beckmann@amd.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 256892SBrad.Beckmann@amd.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 266892SBrad.Beckmann@amd.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 276892SBrad.Beckmann@amd.com * 286892SBrad.Beckmann@amd.com * Authors: Nathan Binkert 296892SBrad.Beckmann@amd.com * Ron Dreslinski 307563SBrad.Beckmann@amd.com */ 316892SBrad.Beckmann@amd.com 326892SBrad.Beckmann@amd.com/* @file 336892SBrad.Beckmann@amd.com * Device module for modelling a fixed bandwidth full duplex ethernet link 346892SBrad.Beckmann@amd.com */ 357538SBrad.Beckmann@amd.com 367538SBrad.Beckmann@amd.com#include <cmath> 377538SBrad.Beckmann@amd.com#include <deque> 387538SBrad.Beckmann@amd.com#include <string> 397538SBrad.Beckmann@amd.com#include <vector> 407538SBrad.Beckmann@amd.com 417661Snate@binkert.org#include "base/random.hh" 427538SBrad.Beckmann@amd.com#include "base/trace.hh" 437538SBrad.Beckmann@amd.com#include "dev/etherdump.hh" 447538SBrad.Beckmann@amd.com#include "dev/etherint.hh" 457917SBrad.Beckmann@amd.com#include "dev/etherlink.hh" 467563SBrad.Beckmann@amd.com#include "dev/etherpkt.hh" 477563SBrad.Beckmann@amd.com#include "params/EtherLink.hh" 487538SBrad.Beckmann@amd.com#include "sim/serialize.hh" 497538SBrad.Beckmann@amd.com#include "sim/system.hh" 507538SBrad.Beckmann@amd.com#include "sim/core.hh" 517538SBrad.Beckmann@amd.com 527538SBrad.Beckmann@amd.comusing namespace std; 537566SBrad.Beckmann@amd.com 547566SBrad.Beckmann@amd.comEtherLink::EtherLink(const string &name, EtherInt *peer0, EtherInt *peer1, 557809Snilay@cs.wisc.edu double rate, Tick delay, Tick delayVar, EtherDump *dump) 567809Snilay@cs.wisc.edu : SimObject(name) 577809Snilay@cs.wisc.edu{ 587809Snilay@cs.wisc.edu link[0] = new Link(name + ".link0", this, 0, rate, delay, delayVar, dump); 597538SBrad.Beckmann@amd.com link[1] = new Link(name + ".link1", this, 1, rate, delay, delayVar, dump); 607538SBrad.Beckmann@amd.com 617538SBrad.Beckmann@amd.com interface[0] = new Interface(name + ".int0", link[0], link[1]); 627538SBrad.Beckmann@amd.com interface[1] = new Interface(name + ".int1", link[1], link[0]); 637541SBrad.Beckmann@amd.com 646892SBrad.Beckmann@amd.com interface[0]->setPeer(peer0); 657032SBrad.Beckmann@amd.com peer0->setPeer(interface[0]); 667032SBrad.Beckmann@amd.com interface[1]->setPeer(peer1); 676923SBrad.Beckmann@amd.com peer1->setPeer(interface[1]); 686893SBrad.Beckmann@amd.com} 697557SBrad.Beckmann@amd.com 707557SBrad.Beckmann@amd.comEtherLink::~EtherLink() 716923SBrad.Beckmann@amd.com{ 726923SBrad.Beckmann@amd.com delete link[0]; 737557SBrad.Beckmann@amd.com delete link[1]; 748257SBrad.Beckmann@amd.com 758257SBrad.Beckmann@amd.com delete interface[0]; 768257SBrad.Beckmann@amd.com delete interface[1]; 778257SBrad.Beckmann@amd.com} 788257SBrad.Beckmann@amd.com 798257SBrad.Beckmann@amd.comEtherLink::Interface::Interface(const string &name, Link *tx, Link *rx) 808257SBrad.Beckmann@amd.com : EtherInt(name), txlink(tx) 818257SBrad.Beckmann@amd.com{ 828257SBrad.Beckmann@amd.com tx->setTxInt(this); 838257SBrad.Beckmann@amd.com rx->setRxInt(this); 848257SBrad.Beckmann@amd.com} 858257SBrad.Beckmann@amd.com 868257SBrad.Beckmann@amd.comEtherLink::Link::Link(const string &name, EtherLink *p, int num, 878257SBrad.Beckmann@amd.com double rate, Tick delay, Tick delay_var, EtherDump *d) 888257SBrad.Beckmann@amd.com : objName(name), parent(p), number(num), txint(NULL), rxint(NULL), 898257SBrad.Beckmann@amd.com ticksPerByte(rate), linkDelay(delay), delayVar(delay_var), dump(d), 908258SBrad.Beckmann@amd.com doneEvent(this) 918258SBrad.Beckmann@amd.com{ } 928257SBrad.Beckmann@amd.com 938257SBrad.Beckmann@amd.comvoid 946892SBrad.Beckmann@amd.comEtherLink::serialize(ostream &os) 957032SBrad.Beckmann@amd.com{ 967032SBrad.Beckmann@amd.com link[0]->serialize("link0", os); 976892SBrad.Beckmann@amd.com link[1]->serialize("link1", os); 987032SBrad.Beckmann@amd.com} 997032SBrad.Beckmann@amd.com 1008257SBrad.Beckmann@amd.comvoid 1018257SBrad.Beckmann@amd.comEtherLink::unserialize(Checkpoint *cp, const string §ion) 1028257SBrad.Beckmann@amd.com{ 1037557SBrad.Beckmann@amd.com link[0]->unserialize("link0", cp, section); 1047032SBrad.Beckmann@amd.com link[1]->unserialize("link1", cp, section); 1057032SBrad.Beckmann@amd.com} 1067557SBrad.Beckmann@amd.com 1078257SBrad.Beckmann@amd.comvoid 1088257SBrad.Beckmann@amd.comEtherLink::Link::txComplete(EthPacketPtr packet) 1096892SBrad.Beckmann@amd.com{ 1106903SBrad.Beckmann@amd.com DPRINTF(Ethernet, "packet received: len=%d\n", packet->length); 1117563SBrad.Beckmann@amd.com DDUMP(EthernetData, packet->data, packet->length); 1127025SBrad.Beckmann@amd.com rxint->sendPacket(packet); 1137025SBrad.Beckmann@amd.com} 1147025SBrad.Beckmann@amd.com 1157025SBrad.Beckmann@amd.comclass LinkDelayEvent : public Event 1167563SBrad.Beckmann@amd.com{ 1176903SBrad.Beckmann@amd.com protected: 1186903SBrad.Beckmann@amd.com EtherLink::Link *link; 1197563SBrad.Beckmann@amd.com EthPacketPtr packet; 1207563SBrad.Beckmann@amd.com 1217563SBrad.Beckmann@amd.com public: 1227563SBrad.Beckmann@amd.com // non-scheduling version for createForUnserialize() 1237563SBrad.Beckmann@amd.com LinkDelayEvent(); 1247563SBrad.Beckmann@amd.com LinkDelayEvent(EtherLink::Link *link, EthPacketPtr pkt, Tick when); 1257563SBrad.Beckmann@amd.com 1267663SBrad.Beckmann@amd.com void process(); 1277663SBrad.Beckmann@amd.com 1287663SBrad.Beckmann@amd.com virtual void serialize(ostream &os); 1297663SBrad.Beckmann@amd.com virtual void unserialize(Checkpoint *cp, const string §ion); 1307663SBrad.Beckmann@amd.com static Serializable *createForUnserialize(Checkpoint *cp, 1317563SBrad.Beckmann@amd.com const string §ion); 1326903SBrad.Beckmann@amd.com}; 1336903SBrad.Beckmann@amd.com 1347563SBrad.Beckmann@amd.comvoid 1357563SBrad.Beckmann@amd.comEtherLink::Link::txDone() 1367541SBrad.Beckmann@amd.com{ 1377541SBrad.Beckmann@amd.com if (dump) 1386905SBrad.Beckmann@amd.com dump->dump(packet); 1396892SBrad.Beckmann@amd.com 1406897SBrad.Beckmann@amd.com if (linkDelay > 0) { 1416892SBrad.Beckmann@amd.com DPRINTF(Ethernet, "packet delayed: delay=%d\n", linkDelay); 1426893SBrad.Beckmann@amd.com new LinkDelayEvent(this, packet, curTick + linkDelay); 1436892SBrad.Beckmann@amd.com } else { 1446892SBrad.Beckmann@amd.com txComplete(packet); 1456892SBrad.Beckmann@amd.com } 1466903SBrad.Beckmann@amd.com 1476892SBrad.Beckmann@amd.com packet = 0; 1486893SBrad.Beckmann@amd.com assert(!busy()); 1497809Snilay@cs.wisc.edu 1506892SBrad.Beckmann@amd.com txint->sendDone(); 1516892SBrad.Beckmann@amd.com} 152 153bool 154EtherLink::Link::transmit(EthPacketPtr pkt) 155{ 156 if (busy()) { 157 DPRINTF(Ethernet, "packet not sent, link busy\n"); 158 return false; 159 } 160 161 DPRINTF(Ethernet, "packet sent: len=%d\n", pkt->length); 162 DDUMP(EthernetData, pkt->data, pkt->length); 163 164 packet = pkt; 165 Tick delay = (Tick)ceil(((double)pkt->length * ticksPerByte) + 1.0); 166 if (delayVar != 0) { 167 Random<Tick> var; 168 delay += var.uniform(0, delayVar); 169 } 170 DPRINTF(Ethernet, "scheduling packet: delay=%d, (rate=%f)\n", 171 delay, ticksPerByte); 172 doneEvent.schedule(curTick + delay); 173 174 return true; 175} 176 177void 178EtherLink::Link::serialize(const string &base, ostream &os) 179{ 180 bool packet_exists = packet; 181 paramOut(os, base + ".packet_exists", packet_exists); 182 if (packet_exists) 183 packet->serialize(base + ".packet", os); 184 185 bool event_scheduled = doneEvent.scheduled(); 186 paramOut(os, base + ".event_scheduled", event_scheduled); 187 if (event_scheduled) { 188 Tick event_time = doneEvent.when(); 189 paramOut(os, base + ".event_time", event_time); 190 } 191 192} 193 194void 195EtherLink::Link::unserialize(const string &base, Checkpoint *cp, 196 const string §ion) 197{ 198 bool packet_exists; 199 paramIn(cp, section, base + ".packet_exists", packet_exists); 200 if (packet_exists) { 201 packet = new EthPacketData(16384); 202 packet->unserialize(base + ".packet", cp, section); 203 } 204 205 bool event_scheduled; 206 paramIn(cp, section, base + ".event_scheduled", event_scheduled); 207 if (event_scheduled) { 208 Tick event_time; 209 paramIn(cp, section, base + ".event_time", event_time); 210 doneEvent.schedule(event_time); 211 } 212} 213 214LinkDelayEvent::LinkDelayEvent() 215 : Event(&mainEventQueue), link(NULL) 216{ 217 setFlags(AutoSerialize); 218 setFlags(AutoDelete); 219} 220 221LinkDelayEvent::LinkDelayEvent(EtherLink::Link *l, EthPacketPtr p, Tick when) 222 : Event(&mainEventQueue), link(l), packet(p) 223{ 224 setFlags(AutoSerialize); 225 setFlags(AutoDelete); 226 schedule(when); 227} 228 229void 230LinkDelayEvent::process() 231{ 232 link->txComplete(packet); 233} 234 235void 236LinkDelayEvent::serialize(ostream &os) 237{ 238 paramOut(os, "type", string("LinkDelayEvent")); 239 Event::serialize(os); 240 241 EtherLink *parent = link->parent; 242 bool number = link->number; 243 SERIALIZE_OBJPTR(parent); 244 SERIALIZE_SCALAR(number); 245 246 packet->serialize("packet", os); 247} 248 249 250void 251LinkDelayEvent::unserialize(Checkpoint *cp, const string §ion) 252{ 253 Event::unserialize(cp, section); 254 255 EtherLink *parent; 256 bool number; 257 UNSERIALIZE_OBJPTR(parent); 258 UNSERIALIZE_SCALAR(number); 259 260 link = parent->link[number]; 261 262 packet = new EthPacketData(16384); 263 packet->unserialize("packet", cp, section); 264} 265 266 267Serializable * 268LinkDelayEvent::createForUnserialize(Checkpoint *cp, const string §ion) 269{ 270 return new LinkDelayEvent(); 271} 272 273REGISTER_SERIALIZEABLE("LinkDelayEvent", LinkDelayEvent) 274 275EtherLink * 276EtherLinkParams::create() 277{ 278 return new EtherLink(name, int1, int2, speed, delay, delay_var, dump); 279} 280