etherlink.cc revision 5034
19164Sandreas.hansson@arm.com/* 29164Sandreas.hansson@arm.com * Copyright (c) 2002-2005 The Regents of The University of Michigan 39164Sandreas.hansson@arm.com * All rights reserved. 49164Sandreas.hansson@arm.com * 59164Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without 69164Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions are 79164Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright 89164Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer; 99164Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright 109164Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the 119164Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution; 129164Sandreas.hansson@arm.com * neither the name of the copyright holders nor the names of its 134486Sbinkertn@umich.edu * contributors may be used to endorse or promote products derived from 144486Sbinkertn@umich.edu * this software without specific prior written permission. 154486Sbinkertn@umich.edu * 164486Sbinkertn@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 174486Sbinkertn@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 184486Sbinkertn@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 194486Sbinkertn@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 204486Sbinkertn@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 214486Sbinkertn@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 224486Sbinkertn@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 234486Sbinkertn@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 244486Sbinkertn@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 254486Sbinkertn@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 264486Sbinkertn@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 274486Sbinkertn@umich.edu * 284486Sbinkertn@umich.edu * Authors: Nathan Binkert 294486Sbinkertn@umich.edu * Ron Dreslinski 304486Sbinkertn@umich.edu */ 314486Sbinkertn@umich.edu 324486Sbinkertn@umich.edu/* @file 334486Sbinkertn@umich.edu * Device module for modelling a fixed bandwidth full duplex ethernet link 344486Sbinkertn@umich.edu */ 354486Sbinkertn@umich.edu 364486Sbinkertn@umich.edu#include <cmath> 374486Sbinkertn@umich.edu#include <deque> 384486Sbinkertn@umich.edu#include <string> 394486Sbinkertn@umich.edu#include <vector> 409164Sandreas.hansson@arm.com 414486Sbinkertn@umich.edu#include "base/random.hh" 423102SN/A#include "base/trace.hh" 432568SN/A#include "dev/etherdump.hh" 442568SN/A#include "dev/etherint.hh" 452568SN/A#include "dev/etherlink.hh" 462568SN/A#include "dev/etherpkt.hh" 478839Sandreas.hansson@arm.com#include "params/EtherLink.hh" 488839Sandreas.hansson@arm.com#include "sim/serialize.hh" 498713Sandreas.hansson@arm.com#include "sim/system.hh" 509164Sandreas.hansson@arm.com#include "sim/core.hh" 512568SN/A 528713Sandreas.hansson@arm.comusing namespace std; 538713Sandreas.hansson@arm.com 54EtherLink::EtherLink(const Params *p) 55 : EtherObject(p) 56{ 57 link[0] = new Link(name() + ".link0", this, 0, p->speed, 58 p->delay, p->delay_var, p->dump); 59 link[1] = new Link(name() + ".link1", this, 1, p->speed, 60 p->delay, p->delay_var, p->dump); 61 62 interface[0] = new Interface(name() + ".int0", link[0], link[1]); 63 interface[1] = new Interface(name() + ".int1", link[1], link[0]); 64} 65 66 67EtherLink::~EtherLink() 68{ 69 delete link[0]; 70 delete link[1]; 71 72 delete interface[0]; 73 delete interface[1]; 74} 75 76EtherInt* 77EtherLink::getEthPort(const std::string &if_name, int idx) 78{ 79 Interface *i; 80 if (if_name == "int0") 81 i = interface[0]; 82 else if (if_name == "int1") 83 i = interface[1]; 84 else 85 return NULL; 86 if (i->getPeer()) 87 panic("interface already connected to\n"); 88 89 return i; 90} 91 92 93EtherLink::Interface::Interface(const string &name, Link *tx, Link *rx) 94 : EtherInt(name), txlink(tx) 95{ 96 tx->setTxInt(this); 97 rx->setRxInt(this); 98} 99 100EtherLink::Link::Link(const string &name, EtherLink *p, int num, 101 double rate, Tick delay, Tick delay_var, EtherDump *d) 102 : objName(name), parent(p), number(num), txint(NULL), rxint(NULL), 103 ticksPerByte(rate), linkDelay(delay), delayVar(delay_var), dump(d), 104 doneEvent(this) 105{ } 106 107void 108EtherLink::serialize(ostream &os) 109{ 110 link[0]->serialize("link0", os); 111 link[1]->serialize("link1", os); 112} 113 114void 115EtherLink::unserialize(Checkpoint *cp, const string §ion) 116{ 117 link[0]->unserialize("link0", cp, section); 118 link[1]->unserialize("link1", cp, section); 119} 120 121void 122EtherLink::Link::txComplete(EthPacketPtr packet) 123{ 124 DPRINTF(Ethernet, "packet received: len=%d\n", packet->length); 125 DDUMP(EthernetData, packet->data, packet->length); 126 rxint->sendPacket(packet); 127} 128 129class LinkDelayEvent : public Event 130{ 131 protected: 132 EtherLink::Link *link; 133 EthPacketPtr packet; 134 135 public: 136 // non-scheduling version for createForUnserialize() 137 LinkDelayEvent(); 138 LinkDelayEvent(EtherLink::Link *link, EthPacketPtr pkt, Tick when); 139 140 void process(); 141 142 virtual void serialize(ostream &os); 143 virtual void unserialize(Checkpoint *cp, const string §ion); 144 static Serializable *createForUnserialize(Checkpoint *cp, 145 const string §ion); 146}; 147 148void 149EtherLink::Link::txDone() 150{ 151 if (dump) 152 dump->dump(packet); 153 154 if (linkDelay > 0) { 155 DPRINTF(Ethernet, "packet delayed: delay=%d\n", linkDelay); 156 new LinkDelayEvent(this, packet, curTick + linkDelay); 157 } else { 158 txComplete(packet); 159 } 160 161 packet = 0; 162 assert(!busy()); 163 164 txint->sendDone(); 165} 166 167bool 168EtherLink::Link::transmit(EthPacketPtr pkt) 169{ 170 if (busy()) { 171 DPRINTF(Ethernet, "packet not sent, link busy\n"); 172 return false; 173 } 174 175 DPRINTF(Ethernet, "packet sent: len=%d\n", pkt->length); 176 DDUMP(EthernetData, pkt->data, pkt->length); 177 178 packet = pkt; 179 Tick delay = (Tick)ceil(((double)pkt->length * ticksPerByte) + 1.0); 180 if (delayVar != 0) { 181 Random<Tick> var; 182 delay += var.uniform(0, delayVar); 183 } 184 DPRINTF(Ethernet, "scheduling packet: delay=%d, (rate=%f)\n", 185 delay, ticksPerByte); 186 doneEvent.schedule(curTick + delay); 187 188 return true; 189} 190 191void 192EtherLink::Link::serialize(const string &base, ostream &os) 193{ 194 bool packet_exists = packet; 195 paramOut(os, base + ".packet_exists", packet_exists); 196 if (packet_exists) 197 packet->serialize(base + ".packet", os); 198 199 bool event_scheduled = doneEvent.scheduled(); 200 paramOut(os, base + ".event_scheduled", event_scheduled); 201 if (event_scheduled) { 202 Tick event_time = doneEvent.when(); 203 paramOut(os, base + ".event_time", event_time); 204 } 205 206} 207 208void 209EtherLink::Link::unserialize(const string &base, Checkpoint *cp, 210 const string §ion) 211{ 212 bool packet_exists; 213 paramIn(cp, section, base + ".packet_exists", packet_exists); 214 if (packet_exists) { 215 packet = new EthPacketData(16384); 216 packet->unserialize(base + ".packet", cp, section); 217 } 218 219 bool event_scheduled; 220 paramIn(cp, section, base + ".event_scheduled", event_scheduled); 221 if (event_scheduled) { 222 Tick event_time; 223 paramIn(cp, section, base + ".event_time", event_time); 224 doneEvent.schedule(event_time); 225 } 226} 227 228LinkDelayEvent::LinkDelayEvent() 229 : Event(&mainEventQueue), link(NULL) 230{ 231 setFlags(AutoSerialize); 232 setFlags(AutoDelete); 233} 234 235LinkDelayEvent::LinkDelayEvent(EtherLink::Link *l, EthPacketPtr p, Tick when) 236 : Event(&mainEventQueue), link(l), packet(p) 237{ 238 setFlags(AutoSerialize); 239 setFlags(AutoDelete); 240 schedule(when); 241} 242 243void 244LinkDelayEvent::process() 245{ 246 link->txComplete(packet); 247} 248 249void 250LinkDelayEvent::serialize(ostream &os) 251{ 252 paramOut(os, "type", string("LinkDelayEvent")); 253 Event::serialize(os); 254 255 EtherLink *parent = link->parent; 256 bool number = link->number; 257 SERIALIZE_OBJPTR(parent); 258 SERIALIZE_SCALAR(number); 259 260 packet->serialize("packet", os); 261} 262 263 264void 265LinkDelayEvent::unserialize(Checkpoint *cp, const string §ion) 266{ 267 Event::unserialize(cp, section); 268 269 EtherLink *parent; 270 bool number; 271 UNSERIALIZE_OBJPTR(parent); 272 UNSERIALIZE_SCALAR(number); 273 274 link = parent->link[number]; 275 276 packet = new 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