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.
42 * Device module for modelling a fixed bandwidth full duplex ethernet link
45 #include "dev/net/etherlink.hh"
52 #include "base/random.hh"
53 #include "base/trace.hh"
54 #include "debug/Ethernet.hh"
55 #include "debug/EthernetData.hh"
56 #include "dev/net/etherdump.hh"
57 #include "dev/net/etherint.hh"
58 #include "dev/net/etherpkt.hh"
59 #include "params/EtherLink.hh"
60 #include "sim/core.hh"
61 #include "sim/serialize.hh"
62 #include "sim/system.hh"
66 EtherLink::EtherLink(const Params
&p
)
69 link
[0] = new Link(name() + ".link0", this, 0, p
.speed
,
70 p
.delay
, p
.delay_var
, p
.dump
);
71 link
[1] = new Link(name() + ".link1", this, 1, p
.speed
,
72 p
.delay
, p
.delay_var
, p
.dump
);
74 interface
[0] = new Interface(name() + ".int0", link
[0], link
[1]);
75 interface
[1] = new Interface(name() + ".int1", link
[1], link
[0]);
79 EtherLink::~EtherLink()
89 EtherLink::getPort(const std::string
&if_name
, PortID idx
)
91 if (if_name
== "int0")
93 else if (if_name
== "int1")
95 return SimObject::getPort(if_name
, idx
);
99 EtherLink::Interface::Interface(const string
&name
, Link
*tx
, Link
*rx
)
100 : EtherInt(name
), txlink(tx
)
106 EtherLink::Link::Link(const string
&name
, EtherLink
*p
, int num
,
107 double rate
, Tick delay
, Tick delay_var
, EtherDump
*d
)
108 : objName(name
), parent(p
), number(num
), txint(NULL
), rxint(NULL
),
109 ticksPerByte(rate
), linkDelay(delay
), delayVar(delay_var
), dump(d
),
110 doneEvent([this]{ txDone(); }, name
),
111 txQueueEvent([this]{ processTxQueue(); }, name
)
115 EtherLink::serialize(CheckpointOut
&cp
) const
117 link
[0]->serialize("link0", cp
);
118 link
[1]->serialize("link1", cp
);
122 EtherLink::unserialize(CheckpointIn
&cp
)
124 link
[0]->unserialize("link0", cp
);
125 link
[1]->unserialize("link1", cp
);
129 EtherLink::Link::txComplete(EthPacketPtr packet
)
131 DPRINTF(Ethernet
, "packet received: len=%d\n", packet
->length
);
132 DDUMP(EthernetData
, packet
->data
, packet
->length
);
133 rxint
->sendPacket(packet
);
137 EtherLink::Link::txDone()
143 DPRINTF(Ethernet
, "packet delayed: delay=%d\n", linkDelay
);
144 txQueue
.emplace_back(std::make_pair(curTick() + linkDelay
, packet
));
145 if (!txQueueEvent
.scheduled())
146 parent
->schedule(txQueueEvent
, txQueue
.front().first
);
148 assert(txQueue
.empty());
159 EtherLink::Link::processTxQueue()
161 auto cur(txQueue
.front());
164 // Schedule a new event to process the next packet in the queue.
165 if (!txQueue
.empty()) {
166 auto next(txQueue
.front());
167 assert(next
.first
> curTick());
168 parent
->schedule(txQueueEvent
, next
.first
);
171 assert(cur
.first
== curTick());
172 txComplete(cur
.second
);
176 EtherLink::Link::transmit(EthPacketPtr pkt
)
179 DPRINTF(Ethernet
, "packet not sent, link busy\n");
183 DPRINTF(Ethernet
, "packet sent: len=%d\n", pkt
->length
);
184 DDUMP(EthernetData
, pkt
->data
, pkt
->length
);
187 Tick delay
= (Tick
)ceil(((double)pkt
->simLength
* ticksPerByte
) + 1.0);
189 delay
+= random_mt
.random
<Tick
>(0, delayVar
);
191 DPRINTF(Ethernet
, "scheduling packet: delay=%d, (rate=%f)\n",
192 delay
, ticksPerByte
);
193 parent
->schedule(doneEvent
, curTick() + delay
);
199 EtherLink::Link::serialize(const string
&base
, CheckpointOut
&cp
) const
201 bool packet_exists
= packet
!= nullptr;
202 paramOut(cp
, base
+ ".packet_exists", packet_exists
);
204 packet
->serialize(base
+ ".packet", cp
);
206 bool event_scheduled
= doneEvent
.scheduled();
207 paramOut(cp
, base
+ ".event_scheduled", event_scheduled
);
208 if (event_scheduled
) {
209 Tick event_time
= doneEvent
.when();
210 paramOut(cp
, base
+ ".event_time", event_time
);
213 const size_t tx_queue_size(txQueue
.size());
214 paramOut(cp
, base
+ ".tx_queue_size", tx_queue_size
);
216 for (const auto &pe
: txQueue
) {
217 paramOut(cp
, csprintf("%s.txQueue[%i].tick", base
, idx
), pe
.first
);
218 pe
.second
->serialize(csprintf("%s.txQueue[%i].packet", base
, idx
), cp
);
225 EtherLink::Link::unserialize(const string
&base
, CheckpointIn
&cp
)
228 paramIn(cp
, base
+ ".packet_exists", packet_exists
);
230 packet
= make_shared
<EthPacketData
>();
231 packet
->unserialize(base
+ ".packet", cp
);
234 bool event_scheduled
;
235 paramIn(cp
, base
+ ".event_scheduled", event_scheduled
);
236 if (event_scheduled
) {
238 paramIn(cp
, base
+ ".event_time", event_time
);
239 parent
->schedule(doneEvent
, event_time
);
242 size_t tx_queue_size
= 0;
243 if (optParamIn(cp
, base
+ ".tx_queue_size", tx_queue_size
)) {
244 for (size_t idx
= 0; idx
< tx_queue_size
; ++idx
) {
246 EthPacketPtr delayed_packet
= make_shared
<EthPacketData
>();
248 paramIn(cp
, csprintf("%s.txQueue[%i].tick", base
, idx
), tick
);
249 delayed_packet
->unserialize(
250 csprintf("%s.txQueue[%i].packet", base
, idx
), cp
);
252 fatal_if(!txQueue
.empty() && txQueue
.back().first
> tick
,
253 "Invalid txQueue packet order in EtherLink!\n");
254 txQueue
.emplace_back(std::make_pair(tick
, delayed_packet
));
257 if (!txQueue
.empty())
258 parent
->schedule(txQueueEvent
, txQueue
.front().first
);
260 // We can't reliably convert in-flight packets from old
261 // checkpoints. In fact, gem5 hasn't been able to load these
262 // packets for at least two years before the format change.
263 warn("Old-style EtherLink serialization format detected, "
264 "in-flight packets may have been dropped.\n");
269 EtherLinkParams::create() const
271 return new EtherLink(*this);