2 * Copyright (c) 2015 ARM Limited
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
14 * Copyright (c) 2002-2005 The Regents of The University of Michigan
15 * All rights reserved.
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are
19 * met: redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer;
21 * redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution;
24 * neither the name of the copyright holders nor the names of its
25 * contributors may be used to endorse or promote products derived from
26 * this software without specific prior written permission.
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 * Authors: Nathan Binkert
45 * Device module for modelling a fixed bandwidth full duplex ethernet link
48 #include "dev/net/etherlink.hh"
55 #include "base/random.hh"
56 #include "base/trace.hh"
57 #include "debug/Ethernet.hh"
58 #include "debug/EthernetData.hh"
59 #include "dev/net/etherdump.hh"
60 #include "dev/net/etherint.hh"
61 #include "dev/net/etherpkt.hh"
62 #include "params/EtherLink.hh"
63 #include "sim/core.hh"
64 #include "sim/serialize.hh"
65 #include "sim/system.hh"
69 EtherLink::EtherLink(const Params
*p
)
72 link
[0] = new Link(name() + ".link0", this, 0, p
->speed
,
73 p
->delay
, p
->delay_var
, p
->dump
);
74 link
[1] = new Link(name() + ".link1", this, 1, p
->speed
,
75 p
->delay
, p
->delay_var
, p
->dump
);
77 interface
[0] = new Interface(name() + ".int0", link
[0], link
[1]);
78 interface
[1] = new Interface(name() + ".int1", link
[1], link
[0]);
82 EtherLink::~EtherLink()
92 EtherLink::getEthPort(const std::string
&if_name
, int idx
)
95 if (if_name
== "int0")
97 else if (if_name
== "int1")
102 panic("interface already connected to\n");
108 EtherLink::Interface::Interface(const string
&name
, Link
*tx
, Link
*rx
)
109 : EtherInt(name
), txlink(tx
)
115 EtherLink::Link::Link(const string
&name
, EtherLink
*p
, int num
,
116 double rate
, Tick delay
, Tick delay_var
, EtherDump
*d
)
117 : objName(name
), parent(p
), number(num
), txint(NULL
), rxint(NULL
),
118 ticksPerByte(rate
), linkDelay(delay
), delayVar(delay_var
), dump(d
),
119 doneEvent([this]{ txDone(); }, name
),
120 txQueueEvent([this]{ processTxQueue(); }, name
)
124 EtherLink::serialize(CheckpointOut
&cp
) const
126 link
[0]->serialize("link0", cp
);
127 link
[1]->serialize("link1", cp
);
131 EtherLink::unserialize(CheckpointIn
&cp
)
133 link
[0]->unserialize("link0", cp
);
134 link
[1]->unserialize("link1", cp
);
138 EtherLink::Link::txComplete(EthPacketPtr packet
)
140 DPRINTF(Ethernet
, "packet received: len=%d\n", packet
->length
);
141 DDUMP(EthernetData
, packet
->data
, packet
->length
);
142 rxint
->sendPacket(packet
);
146 EtherLink::Link::txDone()
152 DPRINTF(Ethernet
, "packet delayed: delay=%d\n", linkDelay
);
153 txQueue
.emplace_back(std::make_pair(curTick() + linkDelay
, packet
));
154 if (!txQueueEvent
.scheduled())
155 parent
->schedule(txQueueEvent
, txQueue
.front().first
);
157 assert(txQueue
.empty());
168 EtherLink::Link::processTxQueue()
170 auto cur(txQueue
.front());
173 // Schedule a new event to process the next packet in the queue.
174 if (!txQueue
.empty()) {
175 auto next(txQueue
.front());
176 assert(next
.first
> curTick());
177 parent
->schedule(txQueueEvent
, next
.first
);
180 assert(cur
.first
== curTick());
181 txComplete(cur
.second
);
185 EtherLink::Link::transmit(EthPacketPtr pkt
)
188 DPRINTF(Ethernet
, "packet not sent, link busy\n");
192 DPRINTF(Ethernet
, "packet sent: len=%d\n", pkt
->length
);
193 DDUMP(EthernetData
, pkt
->data
, pkt
->length
);
196 Tick delay
= (Tick
)ceil(((double)pkt
->simLength
* ticksPerByte
) + 1.0);
198 delay
+= random_mt
.random
<Tick
>(0, delayVar
);
200 DPRINTF(Ethernet
, "scheduling packet: delay=%d, (rate=%f)\n",
201 delay
, ticksPerByte
);
202 parent
->schedule(doneEvent
, curTick() + delay
);
208 EtherLink::Link::serialize(const string
&base
, CheckpointOut
&cp
) const
210 bool packet_exists
= packet
!= nullptr;
211 paramOut(cp
, base
+ ".packet_exists", packet_exists
);
213 packet
->serialize(base
+ ".packet", cp
);
215 bool event_scheduled
= doneEvent
.scheduled();
216 paramOut(cp
, base
+ ".event_scheduled", event_scheduled
);
217 if (event_scheduled
) {
218 Tick event_time
= doneEvent
.when();
219 paramOut(cp
, base
+ ".event_time", event_time
);
222 const size_t tx_queue_size(txQueue
.size());
223 paramOut(cp
, base
+ ".tx_queue_size", tx_queue_size
);
225 for (const auto &pe
: txQueue
) {
226 paramOut(cp
, csprintf("%s.txQueue[%i].tick", base
, idx
), pe
.first
);
227 pe
.second
->serialize(csprintf("%s.txQueue[%i].packet", base
, idx
), cp
);
234 EtherLink::Link::unserialize(const string
&base
, CheckpointIn
&cp
)
237 paramIn(cp
, base
+ ".packet_exists", packet_exists
);
239 packet
= make_shared
<EthPacketData
>();
240 packet
->unserialize(base
+ ".packet", cp
);
243 bool event_scheduled
;
244 paramIn(cp
, base
+ ".event_scheduled", event_scheduled
);
245 if (event_scheduled
) {
247 paramIn(cp
, base
+ ".event_time", event_time
);
248 parent
->schedule(doneEvent
, event_time
);
251 size_t tx_queue_size
;
252 if (optParamIn(cp
, base
+ ".tx_queue_size", tx_queue_size
)) {
253 for (size_t idx
= 0; idx
< tx_queue_size
; ++idx
) {
255 EthPacketPtr delayed_packet
= make_shared
<EthPacketData
>();
257 paramIn(cp
, csprintf("%s.txQueue[%i].tick", base
, idx
), tick
);
258 delayed_packet
->unserialize(
259 csprintf("%s.txQueue[%i].packet", base
, idx
), cp
);
261 fatal_if(!txQueue
.empty() && txQueue
.back().first
> tick
,
262 "Invalid txQueue packet order in EtherLink!\n");
263 txQueue
.emplace_back(std::make_pair(tick
, delayed_packet
));
266 if (!txQueue
.empty())
267 parent
->schedule(txQueueEvent
, txQueue
.front().first
);
269 // We can't reliably convert in-flight packets from old
270 // checkpoints. In fact, gem5 hasn't been able to load these
271 // packets for at least two years before the format change.
272 warn("Old-style EtherLink serialization format detected, "
273 "in-flight packets may have been dropped.\n");
278 EtherLinkParams::create()
280 return new EtherLink(this);