etherlink.cc revision 8232
1712SN/A/* 21762SN/A * Copyright (c) 2002-2005 The Regents of The University of Michigan 3712SN/A * All rights reserved. 4712SN/A * 5712SN/A * Redistribution and use in source and binary forms, with or without 6712SN/A * modification, are permitted provided that the following conditions are 7712SN/A * met: redistributions of source code must retain the above copyright 8712SN/A * notice, this list of conditions and the following disclaimer; 9712SN/A * redistributions in binary form must reproduce the above copyright 10712SN/A * notice, this list of conditions and the following disclaimer in the 11712SN/A * documentation and/or other materials provided with the distribution; 12712SN/A * neither the name of the copyright holders nor the names of its 13712SN/A * contributors may be used to endorse or promote products derived from 14712SN/A * this software without specific prior written permission. 15712SN/A * 16712SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17712SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18712SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19712SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20712SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21712SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22712SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23712SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24712SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25712SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26712SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272665Ssaidi@eecs.umich.edu * 282665Ssaidi@eecs.umich.edu * Authors: Nathan Binkert 29712SN/A * Ron Dreslinski 30712SN/A */ 311354SN/A 321354SN/A/* @file 33712SN/A * Device module for modelling a fixed bandwidth full duplex ethernet link 348706Sandreas.hansson@arm.com */ 35712SN/A 362680Sktlim@umich.edu#include <cmath> 37712SN/A#include <deque> 38712SN/A#include <string> 39712SN/A#include <vector> 40712SN/A 41712SN/A#include "base/random.hh" 42712SN/A#include "base/trace.hh" 43712SN/A#include "debug/Ethernet.hh" 445191Ssaidi@eecs.umich.edu#include "debug/EthernetData.hh" 452680Sktlim@umich.edu#include "dev/etherdump.hh" 46712SN/A#include "dev/etherint.hh" 475191Ssaidi@eecs.umich.edu#include "dev/etherlink.hh" 48712SN/A#include "dev/etherpkt.hh" 49712SN/A#include "params/EtherLink.hh" 505191Ssaidi@eecs.umich.edu#include "sim/core.hh" 515191Ssaidi@eecs.umich.edu#include "sim/serialize.hh" 525191Ssaidi@eecs.umich.edu#include "sim/system.hh" 535191Ssaidi@eecs.umich.edu 545191Ssaidi@eecs.umich.eduusing namespace std; 55712SN/A 56712SN/AEtherLink::EtherLink(const Params *p) 575191Ssaidi@eecs.umich.edu : EtherObject(p) 585191Ssaidi@eecs.umich.edu{ 595191Ssaidi@eecs.umich.edu link[0] = new Link(name() + ".link0", this, 0, p->speed, 605191Ssaidi@eecs.umich.edu p->delay, p->delay_var, p->dump); 615191Ssaidi@eecs.umich.edu link[1] = new Link(name() + ".link1", this, 1, p->speed, 62712SN/A p->delay, p->delay_var, p->dump); 635191Ssaidi@eecs.umich.edu 645191Ssaidi@eecs.umich.edu interface[0] = new Interface(name() + ".int0", link[0], link[1]); 655191Ssaidi@eecs.umich.edu interface[1] = new Interface(name() + ".int1", link[1], link[0]); 665191Ssaidi@eecs.umich.edu} 675191Ssaidi@eecs.umich.edu 685191Ssaidi@eecs.umich.edu 695191Ssaidi@eecs.umich.eduEtherLink::~EtherLink() 705191Ssaidi@eecs.umich.edu{ 715191Ssaidi@eecs.umich.edu delete link[0]; 7214020Sgabeblack@google.com delete link[1]; 738852Sandreas.hansson@arm.com 745191Ssaidi@eecs.umich.edu delete interface[0]; 755191Ssaidi@eecs.umich.edu delete interface[1]; 765191Ssaidi@eecs.umich.edu} 775191Ssaidi@eecs.umich.edu 78712SN/AEtherInt* 79712SN/AEtherLink::getEthPort(const std::string &if_name, int idx) 80712SN/A{ 81712SN/A Interface *i; 825191Ssaidi@eecs.umich.edu if (if_name == "int0") 835191Ssaidi@eecs.umich.edu i = interface[0]; 84712SN/A else if (if_name == "int1") 855191Ssaidi@eecs.umich.edu i = interface[1]; 86712SN/A else 87712SN/A return NULL; 885191Ssaidi@eecs.umich.edu if (i->getPeer()) 895191Ssaidi@eecs.umich.edu panic("interface already connected to\n"); 90712SN/A 91712SN/A return i; 925191Ssaidi@eecs.umich.edu} 93712SN/A 94712SN/A 95712SN/AEtherLink::Interface::Interface(const string &name, Link *tx, Link *rx) 96712SN/A : EtherInt(name), txlink(tx) 975191Ssaidi@eecs.umich.edu{ 985191Ssaidi@eecs.umich.edu tx->setTxInt(this); 99712SN/A rx->setRxInt(this); 100712SN/A} 1015191Ssaidi@eecs.umich.edu 102712SN/AEtherLink::Link::Link(const string &name, EtherLink *p, int num, 103712SN/A double rate, Tick delay, Tick delay_var, EtherDump *d) 104712SN/A : objName(name), parent(p), number(num), txint(NULL), rxint(NULL), 105712SN/A ticksPerByte(rate), linkDelay(delay), delayVar(delay_var), dump(d), 106712SN/A doneEvent(this) 1075191Ssaidi@eecs.umich.edu{ } 1085191Ssaidi@eecs.umich.edu 109712SN/Avoid 1105191Ssaidi@eecs.umich.eduEtherLink::serialize(ostream &os) 1115191Ssaidi@eecs.umich.edu{ 1125191Ssaidi@eecs.umich.edu link[0]->serialize("link0", os); 113712SN/A link[1]->serialize("link1", os); 114712SN/A} 115712SN/A 116712SN/Avoid 117712SN/AEtherLink::unserialize(Checkpoint *cp, const string §ion) 118712SN/A{ 1195191Ssaidi@eecs.umich.edu link[0]->unserialize("link0", cp, section); 120712SN/A link[1]->unserialize("link1", cp, section); 121712SN/A} 1225191Ssaidi@eecs.umich.edu 1235191Ssaidi@eecs.umich.eduvoid 124712SN/AEtherLink::Link::txComplete(EthPacketPtr packet) 1255191Ssaidi@eecs.umich.edu{ 126712SN/A DPRINTF(Ethernet, "packet received: len=%d\n", packet->length); 127712SN/A DDUMP(EthernetData, packet->data, packet->length); 1285191Ssaidi@eecs.umich.edu rxint->sendPacket(packet); 1295191Ssaidi@eecs.umich.edu} 130712SN/A 1315191Ssaidi@eecs.umich.educlass LinkDelayEvent : public Event 132712SN/A{ 133712SN/A protected: 134712SN/A EtherLink::Link *link; 1351354SN/A 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 virtual void unserialize(Checkpoint *cp, const string §ion); 146 static Serializable *createForUnserialize(Checkpoint *cp, 147 const string §ion); 148}; 149 150void 151EtherLink::Link::txDone() 152{ 153 if (dump) 154 dump->dump(packet); 155 156 if (linkDelay > 0) { 157 DPRINTF(Ethernet, "packet delayed: delay=%d\n", linkDelay); 158 Event *event = new LinkDelayEvent(this, packet); 159 parent->schedule(event, curTick() + linkDelay); 160 } else { 161 txComplete(packet); 162 } 163 164 packet = 0; 165 assert(!busy()); 166 167 txint->sendDone(); 168} 169 170bool 171EtherLink::Link::transmit(EthPacketPtr pkt) 172{ 173 if (busy()) { 174 DPRINTF(Ethernet, "packet not sent, link busy\n"); 175 return false; 176 } 177 178 DPRINTF(Ethernet, "packet sent: len=%d\n", pkt->length); 179 DDUMP(EthernetData, pkt->data, pkt->length); 180 181 packet = pkt; 182 Tick delay = (Tick)ceil(((double)pkt->length * ticksPerByte) + 1.0); 183 if (delayVar != 0) 184 delay += random_mt.random<Tick>(0, delayVar); 185 186 DPRINTF(Ethernet, "scheduling packet: delay=%d, (rate=%f)\n", 187 delay, ticksPerByte); 188 parent->schedule(doneEvent, curTick() + delay); 189 190 return true; 191} 192 193void 194EtherLink::Link::serialize(const string &base, ostream &os) 195{ 196 bool packet_exists = packet; 197 paramOut(os, base + ".packet_exists", packet_exists); 198 if (packet_exists) 199 packet->serialize(base + ".packet", os); 200 201 bool event_scheduled = doneEvent.scheduled(); 202 paramOut(os, base + ".event_scheduled", event_scheduled); 203 if (event_scheduled) { 204 Tick event_time = doneEvent.when(); 205 paramOut(os, base + ".event_time", event_time); 206 } 207 208} 209 210void 211EtherLink::Link::unserialize(const string &base, Checkpoint *cp, 212 const string §ion) 213{ 214 bool packet_exists; 215 paramIn(cp, section, base + ".packet_exists", packet_exists); 216 if (packet_exists) { 217 packet = new EthPacketData(16384); 218 packet->unserialize(base + ".packet", cp, section); 219 } 220 221 bool event_scheduled; 222 paramIn(cp, section, base + ".event_scheduled", event_scheduled); 223 if (event_scheduled) { 224 Tick event_time; 225 paramIn(cp, section, base + ".event_time", event_time); 226 parent->schedule(doneEvent, event_time); 227 } 228} 229 230LinkDelayEvent::LinkDelayEvent() 231 : link(NULL) 232{ 233 setFlags(AutoSerialize); 234 setFlags(AutoDelete); 235} 236 237LinkDelayEvent::LinkDelayEvent(EtherLink::Link *l, EthPacketPtr p) 238 : link(l), packet(p) 239{ 240 setFlags(AutoSerialize); 241 setFlags(AutoDelete); 242} 243 244void 245LinkDelayEvent::process() 246{ 247 link->txComplete(packet); 248} 249 250void 251LinkDelayEvent::serialize(ostream &os) 252{ 253 paramOut(os, "type", string("LinkDelayEvent")); 254 Event::serialize(os); 255 256 EtherLink *parent = link->parent; 257 bool number = link->number; 258 SERIALIZE_OBJPTR(parent); 259 SERIALIZE_SCALAR(number); 260 261 packet->serialize("packet", os); 262} 263 264 265void 266LinkDelayEvent::unserialize(Checkpoint *cp, const string §ion) 267{ 268 Event::unserialize(cp, section); 269 270 EtherLink *parent; 271 bool number; 272 UNSERIALIZE_OBJPTR(parent); 273 UNSERIALIZE_SCALAR(number); 274 275 link = parent->link[number]; 276 277 packet = new EthPacketData(16384); 278 packet->unserialize("packet", cp, section); 279} 280 281 282Serializable * 283LinkDelayEvent::createForUnserialize(Checkpoint *cp, const string §ion) 284{ 285 return new LinkDelayEvent(); 286} 287 288REGISTER_SERIALIZEABLE("LinkDelayEvent", LinkDelayEvent) 289 290EtherLink * 291EtherLinkParams::create() 292{ 293 return new EtherLink(this); 294} 295