etherlink.cc revision 10469
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 "debug/Ethernet.hh" 44#include "debug/EthernetData.hh" 45#include "dev/etherdump.hh" 46#include "dev/etherint.hh" 47#include "dev/etherlink.hh" 48#include "dev/etherpkt.hh" 49#include "params/EtherLink.hh" 50#include "sim/core.hh" 51#include "sim/serialize.hh" 52#include "sim/system.hh" 53 54using namespace std; 55 56EtherLink::EtherLink(const Params *p) 57 : EtherObject(p) 58{ 59 link[0] = new Link(name() + ".link0", this, 0, p->speed, 60 p->delay, p->delay_var, p->dump); 61 link[1] = new Link(name() + ".link1", this, 1, p->speed, 62 p->delay, p->delay_var, p->dump); 63 64 interface[0] = new Interface(name() + ".int0", link[0], link[1]); 65 interface[1] = new Interface(name() + ".int1", link[1], link[0]); 66} 67 68 69EtherLink::~EtherLink() 70{ 71 delete link[0]; 72 delete link[1]; 73 74 delete interface[0]; 75 delete interface[1]; 76} 77 78EtherInt* 79EtherLink::getEthPort(const std::string &if_name, int idx) 80{ 81 Interface *i; 82 if (if_name == "int0") 83 i = interface[0]; 84 else if (if_name == "int1") 85 i = interface[1]; 86 else 87 return NULL; 88 if (i->getPeer()) 89 panic("interface already connected to\n"); 90 91 return i; 92} 93 94 95EtherLink::Interface::Interface(const string &name, Link *tx, Link *rx) 96 : EtherInt(name), txlink(tx) 97{ 98 tx->setTxInt(this); 99 rx->setRxInt(this); 100} 101 102EtherLink::Link::Link(const string &name, EtherLink *p, int num, 103 double rate, Tick delay, Tick delay_var, EtherDump *d) 104 : objName(name), parent(p), number(num), txint(NULL), rxint(NULL), 105 ticksPerByte(rate), linkDelay(delay), delayVar(delay_var), dump(d), 106 doneEvent(this) 107{ } 108 109void 110EtherLink::serialize(ostream &os) 111{ 112 link[0]->serialize("link0", os); 113 link[1]->serialize("link1", os); 114} 115 116void 117EtherLink::unserialize(Checkpoint *cp, const string §ion) 118{ 119 link[0]->unserialize("link0", cp, section); 120 link[1]->unserialize("link1", cp, section); 121} 122 123void 124EtherLink::Link::txComplete(EthPacketPtr packet) 125{ 126 DPRINTF(Ethernet, "packet received: len=%d\n", packet->length); 127 DDUMP(EthernetData, packet->data, packet->length); 128 rxint->sendPacket(packet); 129} 130 131class LinkDelayEvent : public Event 132{ 133 protected: 134 EtherLink::Link *link; 135 EthPacketPtr packet; 136 137 public: 138 // non-scheduling version for createForUnserialize() 139 LinkDelayEvent(); 140 LinkDelayEvent(EtherLink::Link *link, EthPacketPtr pkt); 141 142 void process(); 143 144 virtual void serialize(ostream &os); 145 void unserialize(Checkpoint *cp, const string §ion) {} 146 void unserialize(Checkpoint *cp, const string §ion, 147 EventQueue *eventq); 148 static Serializable *createForUnserialize(Checkpoint *cp, 149 const string §ion); 150}; 151 152void 153EtherLink::Link::txDone() 154{ 155 if (dump) 156 dump->dump(packet); 157 158 if (linkDelay > 0) { 159 DPRINTF(Ethernet, "packet delayed: delay=%d\n", linkDelay); 160 Event *event = new LinkDelayEvent(this, packet); 161 parent->schedule(event, curTick() + linkDelay); 162 } else { 163 txComplete(packet); 164 } 165 166 packet = 0; 167 assert(!busy()); 168 169 txint->sendDone(); 170} 171 172bool 173EtherLink::Link::transmit(EthPacketPtr pkt) 174{ 175 if (busy()) { 176 DPRINTF(Ethernet, "packet not sent, link busy\n"); 177 return false; 178 } 179 180 DPRINTF(Ethernet, "packet sent: len=%d\n", pkt->length); 181 DDUMP(EthernetData, pkt->data, pkt->length); 182 183 packet = pkt; 184 Tick delay = (Tick)ceil(((double)pkt->length * ticksPerByte) + 1.0); 185 if (delayVar != 0) 186 delay += random_mt.random<Tick>(0, delayVar); 187 188 DPRINTF(Ethernet, "scheduling packet: delay=%d, (rate=%f)\n", 189 delay, ticksPerByte); 190 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