etherlink.cc revision 4762
1/* 2 * Copyright (c) 2002-2005 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Nathan Binkert 29 * Ron Dreslinski 30 */ 31 32/* @file 33 * Device module for modelling a fixed bandwidth full duplex ethernet link 34 */ 35 36#include <cmath> 37#include <deque> 38#include <string> 39#include <vector> 40 41#include "base/random.hh" 42#include "base/trace.hh" 43#include "dev/etherdump.hh" 44#include "dev/etherint.hh" 45#include "dev/etherlink.hh" 46#include "dev/etherpkt.hh" 47#include "params/EtherLink.hh" 48#include "sim/serialize.hh" 49#include "sim/system.hh" 50#include "sim/core.hh" 51 52using namespace std; 53 54EtherLink::EtherLink(const string &name, EtherInt *peer0, EtherInt *peer1, 55 double rate, Tick delay, Tick delayVar, EtherDump *dump) 56 : SimObject(name) 57{ 58 link[0] = new Link(name + ".link0", this, 0, rate, delay, delayVar, dump); 59 link[1] = new Link(name + ".link1", this, 1, rate, delay, delayVar, dump); 60 61 interface[0] = new Interface(name + ".int0", link[0], link[1]); 62 interface[1] = new Interface(name + ".int1", link[1], link[0]); 63 64 interface[0]->setPeer(peer0); 65 peer0->setPeer(interface[0]); 66 interface[1]->setPeer(peer1); 67 peer1->setPeer(interface[1]); 68} 69 70EtherLink::~EtherLink() 71{ 72 delete link[0]; 73 delete link[1]; 74 75 delete interface[0]; 76 delete interface[1]; 77} 78 79EtherLink::Interface::Interface(const string &name, Link *tx, Link *rx) 80 : EtherInt(name), txlink(tx) 81{ 82 tx->setTxInt(this); 83 rx->setRxInt(this); 84} 85 86EtherLink::Link::Link(const string &name, EtherLink *p, int num, 87 double rate, Tick delay, Tick delay_var, EtherDump *d) 88 : objName(name), parent(p), number(num), txint(NULL), rxint(NULL), 89 ticksPerByte(rate), linkDelay(delay), delayVar(delay_var), dump(d), 90 doneEvent(this) 91{ } 92 93void 94EtherLink::serialize(ostream &os) 95{ 96 link[0]->serialize("link0", os); 97 link[1]->serialize("link1", os); 98} 99 100void 101EtherLink::unserialize(Checkpoint *cp, const string §ion) 102{ 103 link[0]->unserialize("link0", cp, section); 104 link[1]->unserialize("link1", cp, section); 105} 106 107void 108EtherLink::Link::txComplete(EthPacketPtr packet) 109{ 110 DPRINTF(Ethernet, "packet received: len=%d\n", packet->length); 111 DDUMP(EthernetData, packet->data, packet->length); 112 rxint->sendPacket(packet); 113} 114 115class LinkDelayEvent : public Event 116{ 117 protected: 118 EtherLink::Link *link; 119 EthPacketPtr packet; 120 121 public: 122 // non-scheduling version for createForUnserialize() 123 LinkDelayEvent(); 124 LinkDelayEvent(EtherLink::Link *link, EthPacketPtr pkt, Tick when); 125 126 void process(); 127 128 virtual void serialize(ostream &os); 129 virtual void unserialize(Checkpoint *cp, const string §ion); 130 static Serializable *createForUnserialize(Checkpoint *cp, 131 const string §ion); 132}; 133 134void 135EtherLink::Link::txDone() 136{ 137 if (dump) 138 dump->dump(packet); 139 140 if (linkDelay > 0) { 141 DPRINTF(Ethernet, "packet delayed: delay=%d\n", linkDelay); 142 new LinkDelayEvent(this, packet, curTick + linkDelay); 143 } else { 144 txComplete(packet); 145 } 146 147 packet = 0; 148 assert(!busy()); 149 150 txint->sendDone(); 151} 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