etherlink.cc revision 633
12SN/A/* 21762SN/A * Copyright (c) 2003 The Regents of The University of Michigan 32SN/A * All rights reserved. 42SN/A * 52SN/A * Redistribution and use in source and binary forms, with or without 62SN/A * modification, are permitted provided that the following conditions are 72SN/A * met: redistributions of source code must retain the above copyright 82SN/A * notice, this list of conditions and the following disclaimer; 92SN/A * redistributions in binary form must reproduce the above copyright 102SN/A * notice, this list of conditions and the following disclaimer in the 112SN/A * documentation and/or other materials provided with the distribution; 122SN/A * neither the name of the copyright holders nor the names of its 132SN/A * contributors may be used to endorse or promote products derived from 142SN/A * this software without specific prior written permission. 152SN/A * 162SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272665Ssaidi@eecs.umich.edu */ 282665Ssaidi@eecs.umich.edu 292665Ssaidi@eecs.umich.edu/* @file 302SN/A * Device module for modelling a fixed bandwidth full duplex ethernet link 312SN/A */ 324183Sgblack@eecs.umich.edu 332439SN/A#include <cmath> 342680Sktlim@umich.edu#include <deque> 352222SN/A#include <string> 364183Sgblack@eecs.umich.edu#include <vector> 374183Sgblack@eecs.umich.edu 384183Sgblack@eecs.umich.edu#include "base/trace.hh" 392SN/A#include "dev/etherdump.hh" 402201SN/A#include "dev/etherint.hh" 417678Sgblack@eecs.umich.edu#include "dev/etherlink.hh" 422201SN/A#include "dev/etherpkt.hh" 437720Sgblack@eecs.umich.edu#include "sim/builder.hh" 442201SN/A#include "sim/universe.hh" 452222SN/A#include "sim/system.hh" 467678Sgblack@eecs.umich.edu 472222SN/Ausing namespace std; 487720Sgblack@eecs.umich.edu 492680Sktlim@umich.eduEtherLink::EtherLink(const string &name, EtherInt *i1, EtherInt *i2, 502222SN/A Tick speed, Tick dly, EtherDump *dump) 512201SN/A : SimObject(name) 522612SN/A{ 537678Sgblack@eecs.umich.edu double rate = ((double)ticksPerSecond * 8.0) / (double)speed; 542612SN/A Tick delay = US2Ticks(dly); 556815SLisa.Hsu@amd.com 562612SN/A link1 = new Link(name + ".link1", rate, delay, dump); 575004Sgblack@eecs.umich.edu link2 = new Link(name + ".link2", rate, delay, dump); 584184Ssaidi@eecs.umich.edu 597678Sgblack@eecs.umich.edu int1 = new Interface(name + ".int1", link1, link2); 604183Sgblack@eecs.umich.edu int2 = new Interface(name + ".int2", link2, link1); 614183Sgblack@eecs.umich.edu 624183Sgblack@eecs.umich.edu int1->setPeer(i1); 634434Ssaidi@eecs.umich.edu i1->setPeer(int1); 644183Sgblack@eecs.umich.edu int2->setPeer(i2); 654434Ssaidi@eecs.umich.edu i2->setPeer(int2); 664183Sgblack@eecs.umich.edu} 675004Sgblack@eecs.umich.edu 687678Sgblack@eecs.umich.eduEtherLink::~EtherLink() 695004Sgblack@eecs.umich.edu{ 705004Sgblack@eecs.umich.edu delete link1; 715004Sgblack@eecs.umich.edu delete link2; 724184Ssaidi@eecs.umich.edu 73 delete int1; 74 delete int2; 75} 76 77EtherLink::Interface::Interface(const string &name, Link *tx, Link *rx) 78 : EtherInt(name), txlink(tx) 79{ 80 tx->setTxInt(this); 81 rx->setRxInt(this); 82} 83 84EtherLink::Link::Link(const string &name, double rate, Tick delay, 85 EtherDump *d) 86 : objName(name), txint(NULL), rxint(NULL), ticksPerByte(rate), 87 linkDelay(delay), dump(d), doneEvent(this) 88{} 89 90void 91EtherLink::serialize(ostream &os) 92{ 93 nameOut(os, name() + ".link1"); 94 link1->serialize(os); 95 nameOut(os, name() + ".link2"); 96 link2->serialize(os); 97} 98 99void 100EtherLink::unserialize(Checkpoint *cp, const string §ion) 101{ 102 link1->unserialize(cp, section + ".link1"); 103 link2->unserialize(cp, section + ".link2"); 104} 105 106void 107EtherLink::Link::txComplete(PacketPtr &packet) 108{ 109 DPRINTF(Ethernet, "packet received: len=%d\n", packet->length); 110 DDUMP(EthernetData, packet->data, packet->length); 111 rxint->sendPacket(packet); 112} 113 114class LinkDelayEvent : public Event 115{ 116 protected: 117 EtherLink::Link *link; 118 PacketPtr packet; 119 120 // non-scheduling version for createForUnserialize() 121 LinkDelayEvent(EtherLink::Link *link); 122 123 public: 124 LinkDelayEvent(EtherLink::Link *link, PacketPtr &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 134 135void 136EtherLink::Link::txDone() 137{ 138 if (dump) 139 dump->dump(packet); 140 141 if (linkDelay > 0) { 142 DPRINTF(Ethernet, "packet delayed: delay=%d\n", linkDelay); 143 new LinkDelayEvent(this, packet, curTick + linkDelay); 144 } else { 145 txComplete(packet); 146 } 147 148 packet = 0; 149 assert(!busy()); 150 151 txint->sendDone(); 152} 153 154bool 155EtherLink::Link::transmit(PacketPtr &pkt) 156{ 157 if (busy()) { 158 DPRINTF(Ethernet, "packet not sent, link busy\n"); 159 return false; 160 } 161 162 DPRINTF(Ethernet, "packet sent: len=%d\n", pkt->length); 163 DDUMP(EthernetData, pkt->data, pkt->length); 164 165 packet = pkt; 166 Tick delay = (Tick)ceil(((double)pkt->length * ticksPerByte) + 1.0); 167 DPRINTF(Ethernet, "scheduling packet: delay=%d, (rate=%f)\n", 168 delay, ticksPerByte); 169 doneEvent.schedule(curTick + delay); 170 171 return true; 172} 173 174void 175EtherLink::Link::serialize(ostream &os) 176{ 177 bool packet_exists = packet; 178 SERIALIZE_SCALAR(packet_exists); 179 180 bool event_scheduled = doneEvent.scheduled(); 181 SERIALIZE_SCALAR(event_scheduled); 182 if (event_scheduled) { 183 Tick event_time = doneEvent.when(); 184 SERIALIZE_SCALAR(event_time); 185 } 186 187 if (packet_exists) { 188 nameOut(os, csprintf("%s.packet", name())); 189 packet->serialize(os); 190 } 191} 192 193void 194EtherLink::Link::unserialize(Checkpoint *cp, const string §ion) 195{ 196 bool packet_exists; 197 UNSERIALIZE_SCALAR(packet_exists); 198 if (packet_exists) { 199 packet = new EtherPacket; 200 packet->unserialize(cp, csprintf("%s.packet", section)); 201 } 202 203 bool event_scheduled; 204 UNSERIALIZE_SCALAR(event_scheduled); 205 if (event_scheduled) { 206 Tick event_time; 207 UNSERIALIZE_SCALAR(event_time); 208 doneEvent.schedule(event_time); 209 } 210} 211 212LinkDelayEvent::LinkDelayEvent(EtherLink::Link *l) 213 : Event(&mainEventQueue), link(l) 214{ 215 setFlags(AutoSerialize); 216 setFlags(AutoDelete); 217} 218 219LinkDelayEvent::LinkDelayEvent(EtherLink::Link *l, PacketPtr &p, Tick when) 220 : Event(&mainEventQueue), link(l), packet(p) 221{ 222 setFlags(AutoSerialize); 223 setFlags(AutoDelete); 224 schedule(when); 225} 226 227void 228LinkDelayEvent::process() 229{ 230 link->txComplete(packet); 231} 232 233void 234LinkDelayEvent::serialize(ostream &os) 235{ 236 paramOut(os, "type", string("LinkDelayEvent")); 237 Event::serialize(os); 238 SERIALIZE_OBJPTR(link); 239 240 nameOut(os, csprintf("%s.packet", name())); 241 packet->serialize(os); 242} 243 244 245void 246LinkDelayEvent::unserialize(Checkpoint *cp, const string §ion) 247{ 248 Event::unserialize(cp, section); 249 packet = new EtherPacket; 250 packet->unserialize(cp, csprintf("%s.packet", section)); 251} 252 253 254Serializable * 255LinkDelayEvent::createForUnserialize(Checkpoint *cp, const string §ion) 256{ 257 EtherLink::Link *link; 258 UNSERIALIZE_OBJPTR(link); 259 return new LinkDelayEvent(link); 260} 261 262REGISTER_SERIALIZEABLE("LinkDelayEvent", LinkDelayEvent) 263 264BEGIN_DECLARE_SIM_OBJECT_PARAMS(EtherLink) 265 266 SimObjectParam<EtherInt *> interface1; 267 SimObjectParam<EtherInt *> interface2; 268 Param<Tick> link_speed; 269 Param<Tick> link_delay; 270 SimObjectParam<EtherDump *> packet_dump; 271 272END_DECLARE_SIM_OBJECT_PARAMS(EtherLink) 273 274BEGIN_INIT_SIM_OBJECT_PARAMS(EtherLink) 275 276 INIT_PARAM(interface1, "interface 1"), 277 INIT_PARAM(interface2, "interface 2"), 278 INIT_PARAM_DFLT(link_speed, "link speed in bits per second", 100000000), 279 INIT_PARAM_DFLT(link_delay, "transmit delay of packets in us", 0), 280 INIT_PARAM_DFLT(packet_dump, "object to dump network packets to", NULL) 281 282END_INIT_SIM_OBJECT_PARAMS(EtherLink) 283 284CREATE_SIM_OBJECT(EtherLink) 285{ 286 return new EtherLink(getInstanceName(), interface1, interface2, link_speed, 287 link_delay, packet_dump); 288} 289 290REGISTER_SIM_OBJECT("EtherLink", EtherLink) 291