gem5 [DEVELOP-FOR-25.1]
Loading...
Searching...
No Matches
NetworkInterface.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2020 Advanced Micro Devices, Inc.
3 * Copyright (c) 2020 Inria
4 * Copyright (c) 2016 Georgia Institute of Technology
5 * Copyright (c) 2008 Princeton University
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are
10 * met: redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer;
12 * redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution;
15 * neither the name of the copyright holders nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32
34
35#include <cassert>
36#include <cmath>
37
38#include "base/cast.hh"
39#include "debug/RubyNetwork.hh"
45
46namespace gem5
47{
48
49namespace ruby
50{
51
52namespace garnet
53{
54
65
66void
68 CreditLink *credit_link)
69{
70 InputPort *newInPort = new InputPort(in_link, credit_link);
71 inPorts.push_back(newInPort);
72 DPRINTF(RubyNetwork, "Adding input port:%s with vnets %s\n",
73 in_link->name(), newInPort->printVnets());
74
75 in_link->setLinkConsumer(this);
76 credit_link->setSourceQueue(newInPort->outCreditQueue(), this);
77 if (m_vc_per_vnet != 0) {
79 credit_link->setVcsPerVnet(m_vc_per_vnet);
80 }
81
82}
83
84void
86 CreditLink *credit_link,
87 SwitchID router_id, uint32_t consumerVcs)
88{
89 OutputPort *newOutPort = new OutputPort(out_link, credit_link, router_id);
90 outPorts.push_back(newOutPort);
91
92 assert(consumerVcs > 0);
93 // We are not allowing different physical links to have different vcs
94 // If it is required that the Network Interface support different VCs
95 // for every physical link connected to it. Then they need to change
96 // the logic within outport and inport.
97 if (niOutVcs.size() == 0) {
98 m_vc_per_vnet = consumerVcs;
99 int m_num_vcs = consumerVcs * m_virtual_networks;
100 niOutVcs.resize(m_num_vcs);
101 outVcState.reserve(m_num_vcs);
102 m_ni_out_vcs_enqueue_time.resize(m_num_vcs);
103 // instantiating the NI flit buffers
104 for (int i = 0; i < m_num_vcs; i++) {
106 outVcState.emplace_back(i, m_net_ptr, consumerVcs);
107 }
108
109 // Reset VC Per VNET for input links already instantiated
110 for (auto &iPort: inPorts) {
111 NetworkLink *inNetLink = iPort->inNetLink();
112 inNetLink->setVcsPerVnet(m_vc_per_vnet);
113 credit_link->setVcsPerVnet(m_vc_per_vnet);
114 }
115 } else {
116 fatal_if(consumerVcs != m_vc_per_vnet,
117 "%s: Connected Physical links have different vc requests: %d and %d\n",
118 name(), consumerVcs, m_vc_per_vnet);
119 }
120
121 DPRINTF(RubyNetwork, "OutputPort:%s Vnet: %s\n",
122 out_link->name(), newOutPort->printVnets());
123
124 out_link->setSourceQueue(newOutPort->outFlitQueue(), this);
125 out_link->setVcsPerVnet(m_vc_per_vnet);
126 credit_link->setLinkConsumer(this);
127 credit_link->setVcsPerVnet(m_vc_per_vnet);
128}
129
130void
133{
134 inNode_ptr = in;
135 outNode_ptr = out;
136
137 for (auto& it : in) {
138 if (it != nullptr) {
139 it->setConsumer(this);
140 }
141 }
142}
143
144void
146{
147 // An output MessageBuffer has dequeued something this cycle and there
148 // is now space to enqueue a stalled message. However, we cannot wake
149 // on the same cycle as the dequeue. Schedule a wake at the soonest
150 // possible time (next cycle).
152}
153
154void
156{
157 int vnet = t_flit->get_vnet();
158
159 // Latency
160 m_net_ptr->increment_received_flits(vnet);
161 Tick network_delay =
162 t_flit->get_dequeue_time() -
163 t_flit->get_enqueue_time() - cyclesToTicks(Cycles(1));
164 Tick src_queueing_delay = t_flit->get_src_delay();
165 Tick dest_queueing_delay = (curTick() - t_flit->get_dequeue_time());
166 Tick queueing_delay = src_queueing_delay + dest_queueing_delay;
167
168 m_net_ptr->increment_flit_network_latency(network_delay, vnet);
169 m_net_ptr->increment_flit_queueing_latency(queueing_delay, vnet);
170
171 if (t_flit->get_type() == TAIL_ || t_flit->get_type() == HEAD_TAIL_) {
172 m_net_ptr->increment_received_packets(vnet);
173 m_net_ptr->increment_packet_network_latency(network_delay, vnet);
174 m_net_ptr->increment_packet_queueing_latency(queueing_delay, vnet);
175 }
176
177 // Hops
178 m_net_ptr->increment_total_hops(t_flit->get_route().hops_traversed);
179}
180
181/*
182 * The NI wakeup checks whether there are any ready messages in the protocol
183 * buffer. If yes, it picks that up, flitisizes it into a number of flits and
184 * puts it into an output buffer and schedules the output link. On a wakeup
185 * it also checks whether there are flits in the input link. If yes, it picks
186 * them up and if the flit is a tail, the NI inserts the corresponding message
187 * into the protocol buffer. It also checks for credits being sent by the
188 * downstream router.
189 */
190
191void
193{
194 std::ostringstream oss;
195 for (auto &oPort: outPorts) {
196 oss << oPort->routerID() << "[" << oPort->printVnets() << "] ";
197 }
198 DPRINTF(RubyNetwork, "Network Interface %d connected to router:%s "
199 "woke up. Period: %ld\n", m_id, oss.str(), clockPeriod());
200
201 assert(curTick() == clockEdge());
202 MsgPtr msg_ptr;
203 Tick curTime = clockEdge();
204
205 // Checking for messages coming from the protocol
206 // can pick up a message/cycle for each virtual net
207 for (int vnet = 0; vnet < inNode_ptr.size(); ++vnet) {
208 MessageBuffer *b = inNode_ptr[vnet];
209 if (b == nullptr) {
210 continue;
211 }
212
213 if (b->isReady(curTime)) { // Is there a message waiting
214 msg_ptr = b->peekMsgPtr();
215 if (flitisizeMessage(msg_ptr, vnet)) {
216 b->dequeue(curTime);
217 }
218 }
219 }
220
222
223 // Check if there are flits stalling a virtual channel. Track if a
224 // message is enqueued to restrict ejection to one message per cycle.
226
227 /*********** Check the incoming flit link **********/
228 DPRINTF(RubyNetwork, "Number of input ports: %d\n", inPorts.size());
229 for (auto &iPort: inPorts) {
230 NetworkLink *inNetLink = iPort->inNetLink();
231 if (inNetLink->isReady(curTick())) {
232 flit *t_flit = inNetLink->consumeLink();
233 DPRINTF(RubyNetwork, "Recieved flit:%s\n", *t_flit);
234 assert(t_flit->m_width == iPort->bitWidth());
235
236 int vnet = t_flit->get_vnet();
237 t_flit->set_dequeue_time(curTick());
238
239 // If a tail flit is received, enqueue into the protocol buffers
240 // if space is available. Otherwise, exchange non-tail flits for
241 // credits.
242 if (t_flit->get_type() == TAIL_ ||
243 t_flit->get_type() == HEAD_TAIL_) {
244 if (!iPort->messageEnqueuedThisCycle &&
245 outNode_ptr[vnet]->areNSlotsAvailable(1, curTime)) {
246 // Space is available. Enqueue to protocol buffer.
247 outNode_ptr[vnet]->enqueue(t_flit->get_msg_ptr(), curTime,
249 m_net_ptr->getRandomization(),
250 m_net_ptr->getWarmupEnabled());
251
252 // Simply send a credit back since we are not buffering
253 // this flit in the NI
254 Credit *cFlit = new Credit(t_flit->get_vc(),
255 true, curTick());
256 iPort->sendCredit(cFlit);
257 // Update stats and delete flit pointer
258 incrementStats(t_flit);
259 delete t_flit;
260 } else {
261 // No space available- Place tail flit in stall queue and
262 // set up a callback for when protocol buffer is dequeued.
263 // Stat update and flit pointer deletion will occur upon
264 // unstall.
265 iPort->m_stall_queue.push_back(t_flit);
266 m_stall_count[vnet]++;
267
268 outNode_ptr[vnet]->registerDequeueCallback([this]() {
269 dequeueCallback(); });
270 }
271 } else {
272 // Non-tail flit. Send back a credit but not VC free signal.
273 Credit *cFlit = new Credit(t_flit->get_vc(), false,
274 curTick());
275 // Simply send a credit back since we are not buffering
276 // this flit in the NI
277 iPort->sendCredit(cFlit);
278
279 // Update stats and delete flit pointer.
280 incrementStats(t_flit);
281 delete t_flit;
282 }
283 }
284 }
285
286 /****************** Check the incoming credit link *******/
287
288 for (auto &oPort: outPorts) {
289 CreditLink *inCreditLink = oPort->inCreditLink();
290 if (inCreditLink->isReady(curTick())) {
291 Credit *t_credit = (Credit*) inCreditLink->consumeLink();
292 outVcState[t_credit->get_vc()].increment_credit();
293 if (t_credit->is_free_signal()) {
294 outVcState[t_credit->get_vc()].setState(IDLE_,
295 curTick());
296 }
297 delete t_credit;
298 }
299 }
300
301
302 // It is possible to enqueue multiple outgoing credit flits if a message
303 // was unstalled in the same cycle as a new message arrives. In this
304 // case, we should schedule another wakeup to ensure the credit is sent
305 // back.
306 for (auto &iPort: inPorts) {
307 if (iPort->outCreditQueue()->getSize() > 0) {
308 DPRINTF(RubyNetwork, "Sending a credit %s via %s at %ld\n",
309 *(iPort->outCreditQueue()->peekTopFlit()),
310 iPort->outCreditLink()->name(), clockEdge(Cycles(1)));
311 iPort->outCreditLink()->
313 }
314 }
316}
317
318void
320{
321 // Check all stall queues.
322 // There is one stall queue for each input link
323 for (auto &iPort: inPorts) {
324 iPort->messageEnqueuedThisCycle = false;
325 Tick curTime = clockEdge();
326
327 if (!iPort->m_stall_queue.empty()) {
328 for (auto stallIter = iPort->m_stall_queue.begin();
329 stallIter != iPort->m_stall_queue.end(); ) {
330 flit *stallFlit = *stallIter;
331 int vnet = stallFlit->get_vnet();
332
333 // If we can now eject to the protocol buffer,
334 // send back credits
335 if (outNode_ptr[vnet]->areNSlotsAvailable(1,
336 curTime)) {
337 outNode_ptr[vnet]->enqueue(stallFlit->get_msg_ptr(),
338 curTime, cyclesToTicks(Cycles(1)),
339 m_net_ptr->getRandomization(),
340 m_net_ptr->getWarmupEnabled());
341
342 // Send back a credit with free signal now that the
343 // VC is no longer stalled.
344 Credit *cFlit = new Credit(stallFlit->get_vc(), true,
345 curTick());
346 iPort->sendCredit(cFlit);
347
348 // Update Stats
349 incrementStats(stallFlit);
350
351 // Flit can now safely be deleted and removed from stall
352 // queue
353 delete stallFlit;
354 iPort->m_stall_queue.erase(stallIter);
355 m_stall_count[vnet]--;
356
357 // If there are no more stalled messages for this vnet, the
358 // callback on it's MessageBuffer is not needed.
359 if (m_stall_count[vnet] == 0)
360 outNode_ptr[vnet]->unregisterDequeueCallback();
361
362 iPort->messageEnqueuedThisCycle = true;
363 break;
364 } else {
365 ++stallIter;
366 }
367 }
368 }
369 }
370}
371
372// Embed the protocol message into flits
373bool
375{
376 Message *net_msg_ptr = msg_ptr.get();
377 NetDest net_msg_dest = net_msg_ptr->getDestination();
378
379 // gets all the destinations associated with this message.
380 std::vector<NodeID> dest_nodes = net_msg_dest.getAllDest();
381
382 // Number of flits is dependent on the link bandwidth available.
383 // This is expressed in terms of bytes/cycle or the flit size
384 OutputPort *oPort = getOutportForVnet(vnet);
385 assert(oPort);
386 int num_flits = (int)divCeil((float) m_net_ptr->MessageSizeType_to_int(
387 net_msg_ptr->getMessageSize()), (float)oPort->bitWidth());
388
389 DPRINTF(RubyNetwork, "Message Size:%d vnet:%d bitWidth:%d\n",
390 m_net_ptr->MessageSizeType_to_int(net_msg_ptr->getMessageSize()),
391 vnet, oPort->bitWidth());
392
393 // loop to convert all multicast messages into unicast messages
394 for (int ctr = 0; ctr < dest_nodes.size(); ctr++) {
395
396 // this will return a free output virtual channel
397 int vc = calculateVC(vnet);
398
399 if (vc == -1) {
400 return false ;
401 }
402 MsgPtr new_msg_ptr = msg_ptr->clone();
403 NodeID destID = dest_nodes[ctr];
404
405 Message *new_net_msg_ptr = new_msg_ptr.get();
406 if (dest_nodes.size() > 1) {
407 NetDest personal_dest(m_net_ptr->getRubySystem());
408 for (int m = 0; m < (int) MachineType_NUM; m++) {
409 if ((destID >= MachineType_base_number((MachineType) m)) &&
410 destID < MachineType_base_number((MachineType) (m+1))) {
411 // calculating the NetDest associated with this destID
412 personal_dest.clear();
414 tempID; // because ISO C++ forbids compound-literals...
415 tempID.type = (MachineType)m;
416 tempID.num =
417 destID - MachineType_base_number((MachineType)m);
418 personal_dest.add(tempID);
419 new_net_msg_ptr->getDestination() = personal_dest;
420 break;
421 }
422 }
423 net_msg_dest.removeNetDest(personal_dest);
424 // removing the destination from the original message to reflect
425 // that a message with this particular destination has been
426 // flitisized and an output vc is acquired
427 net_msg_ptr->getDestination().removeNetDest(personal_dest);
428 }
429
430 // Embed Route into the flits
431 // NetDest format is used by the routing table
432 // Custom routing algorithms just need destID
433
434 RouteInfo route;
435 route.vnet = vnet;
436 route.net_dest = new_net_msg_ptr->getDestination();
437 route.src_ni = m_id;
438 route.src_router = oPort->routerID();
439 route.dest_ni = destID;
440 route.dest_router = m_net_ptr->get_router_id(destID, vnet);
441
442 // initialize hops_traversed to -1
443 // so that the first router increments it to 0
444 route.hops_traversed = -1;
445
446 m_net_ptr->increment_injected_packets(vnet);
447 m_net_ptr->update_traffic_distribution(route);
448 int packet_id = m_net_ptr->getNextPacketID();
449 for (int i = 0; i < num_flits; i++) {
450 m_net_ptr->increment_injected_flits(vnet);
451 flit *fl = new flit(packet_id,
452 i, vc, vnet, route, num_flits, new_msg_ptr,
453 m_net_ptr->MessageSizeType_to_int(
454 net_msg_ptr->getMessageSize()),
455 oPort->bitWidth(), curTick());
456
457 fl->set_src_delay(curTick() - msg_ptr->getTime());
458 niOutVcs[vc].insert(fl);
459 }
460
462 outVcState[vc].setState(ACTIVE_, curTick());
463 }
464 return true ;
465}
466
467// Looking for a free output vc
468int
470{
471 for (int i = 0; i < m_vc_per_vnet; i++) {
472 int delta = m_vc_allocator[vnet];
473 m_vc_allocator[vnet]++;
474 if (m_vc_allocator[vnet] == m_vc_per_vnet)
475 m_vc_allocator[vnet] = 0;
476
477 if (outVcState[(vnet*m_vc_per_vnet) + delta].isInState(
478 IDLE_, curTick())) {
479 vc_busy_counter[vnet] = 0;
480 return ((vnet*m_vc_per_vnet) + delta);
481 }
482 }
483
484 vc_busy_counter[vnet] += 1;
486 "%s: Possible network deadlock in vnet: %d at time: %llu \n",
487 name(), vnet, curTick());
488
489 return -1;
490}
491
492void
494{
495 int vc = oPort->vcRoundRobin();
496
497 for (int i = 0; i < niOutVcs.size(); i++) {
498 vc++;
499 if (vc == niOutVcs.size())
500 vc = 0;
501
502 int t_vnet = get_vnet(vc);
503 if (oPort->isVnetSupported(t_vnet)) {
504 // model buffer backpressure
505 if (niOutVcs[vc].isReady(curTick()) &&
506 outVcState[vc].has_credit()) {
507
508 bool is_candidate_vc = true;
509 int vc_base = t_vnet * m_vc_per_vnet;
510
511 if (m_net_ptr->isVNetOrdered(t_vnet)) {
512 for (int vc_offset = 0; vc_offset < m_vc_per_vnet;
513 vc_offset++) {
514 int t_vc = vc_base + vc_offset;
515 if (niOutVcs[t_vc].isReady(curTick())) {
516 if (m_ni_out_vcs_enqueue_time[t_vc] <
518 is_candidate_vc = false;
519 break;
520 }
521 }
522 }
523 }
524 if (!is_candidate_vc)
525 continue;
526
527 // Update the round robin arbiter
528 oPort->vcRoundRobin(vc);
529
530 outVcState[vc].decrement_credit();
531
532 // Just removing the top flit
533 flit *t_flit = niOutVcs[vc].getTopFlit();
534 t_flit->set_time(clockEdge(Cycles(1)));
535
536 // Scheduling the flit
537 scheduleFlit(t_flit);
538
539 if (t_flit->get_type() == TAIL_ ||
540 t_flit->get_type() == HEAD_TAIL_) {
542 }
543
544 // Done with this port, continue to schedule
545 // other ports
546 return;
547 }
548 }
549 }
550}
551
552
553
559
560void
562{
563 // Schedule each output link
564 for (auto &oPort: outPorts) {
565 scheduleOutputPort(oPort);
566 }
567}
568
571{
572 for (auto &iPort : inPorts) {
573 if (iPort->isVnetSupported(vnet)) {
574 return iPort;
575 }
576 }
577
578 return nullptr;
579}
580
581/*
582 * This function returns the outport which supports the given vnet.
583 * Currently, HeteroGarnet does not support multiple outports to
584 * support same vnet. Thus, this function returns the first-and
585 * only outport which supports the vnet.
586 */
589{
590 for (auto &oPort : outPorts) {
591 if (oPort->isVnetSupported(vnet)) {
592 return oPort;
593 }
594 }
595
596 return nullptr;
597}
598void
600{
601 OutputPort *oPort = getOutportForVnet(t_flit->get_vnet());
602
603 if (oPort) {
604 DPRINTF(RubyNetwork, "Scheduling at %s time:%ld flit:%s Message:%s\n",
605 oPort->outNetLink()->name(), clockEdge(Cycles(1)),
606 *t_flit, *(t_flit->get_msg_ptr()));
607 oPort->outFlitQueue()->insert(t_flit);
609 return;
610 }
611
612 panic("No output port found for vnet:%d\n", t_flit->get_vnet());
613 return;
614}
615
616int
618{
619 for (int i = 0; i < m_virtual_networks; i++) {
620 if (vc >= (i*m_vc_per_vnet) && vc < ((i+1)*m_vc_per_vnet)) {
621 return i;
622 }
623 }
624 fatal("Could not determine vc");
625}
626
627
628// Wakeup the NI in the next cycle if there are waiting
629// messages in the protocol buffer, or waiting flits in the
630// output VC buffer.
631// Also check if we have to reschedule because of a clock period
632// difference.
633void
635{
636 for (const auto& it : inNode_ptr) {
637 if (it == nullptr) {
638 continue;
639 }
640
641 while (it->isReady(clockEdge())) { // Is there a message waiting
643 return;
644 }
645 }
646
647 for (auto& ni_out_vc : niOutVcs) {
648 if (ni_out_vc.isReady(clockEdge(Cycles(1)))) {
650 return;
651 }
652 }
653
654 // Check if any input links have flits to be popped.
655 // This can happen if the links are operating at
656 // a higher frequency.
657 for (auto &iPort : inPorts) {
658 NetworkLink *inNetLink = iPort->inNetLink();
659 if (inNetLink->isReady(curTick())) {
661 return;
662 }
663 }
664
665 for (auto &oPort : outPorts) {
666 CreditLink *inCreditLink = oPort->inCreditLink();
667 if (inCreditLink->isReady(curTick())) {
669 return;
670 }
671 }
672}
673
674void
675NetworkInterface::print(std::ostream& out) const
676{
677 out << "[Network Interface]";
678}
679
680bool
682{
683 bool read = false;
684 for (auto& ni_out_vc : niOutVcs) {
685 if (ni_out_vc.functionalRead(pkt, mask))
686 read = true;
687 }
688
689 for (auto &oPort: outPorts) {
690 if (oPort->outFlitQueue()->functionalRead(pkt, mask))
691 read = true;
692 }
693
694 return read;
695}
696
697uint32_t
699{
700 uint32_t num_functional_writes = 0;
701 for (auto& ni_out_vc : niOutVcs) {
702 num_functional_writes += ni_out_vc.functionalWrite(pkt);
703 }
704
705 for (auto &oPort: outPorts) {
706 num_functional_writes += oPort->outFlitQueue()->functionalWrite(pkt);
707 }
708 return num_functional_writes;
709}
710
711int
713{
714 return m_net_ptr->getRubySystem()->MachineType_base_number(obj);
715}
716
717} // namespace garnet
718} // namespace ruby
719} // namespace gem5
#define INFINITE_
#define DPRINTF(x,...)
Definition trace.hh:209
ClockedObject(const ClockedObjectParams &p)
Tick clockEdge(Cycles cycles=Cycles(0)) const
Determine the tick when a cycle begins, by default the current one, but the argument also enables the...
Tick cyclesToTicks(Cycles c) const
Tick clockPeriod() const
Cycles is a wrapper class for representing cycle counts, i.e.
Definition types.hh:79
virtual std::string name() const
Definition named.hh:60
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition packet.hh:295
void scheduleEventAbsolute(Tick timeAbs)
Definition Consumer.cc:63
Consumer(ClockedObject *em, Event::Priority ev_prio=Event::Default_Pri)
Definition Consumer.cc:49
void scheduleEvent(Cycles timeDelta)
Definition Consumer.cc:56
virtual const NetDest & getDestination() const
Definition Message.hh:115
virtual const MessageSizeType & getMessageSize() const
Definition Message.hh:79
void add(MachineID newElement)
Definition NetDest.cc:52
std::vector< NodeID > getAllDest()
Definition NetDest.cc:128
void removeNetDest(const NetDest &netDest)
Definition NetDest.cc:88
std::vector< OutputPort * > outPorts
bool functionalRead(Packet *pkt, WriteMask &mask)
void addInPort(NetworkLink *in_link, CreditLink *credit_link)
int MachineType_base_number(const MachineType &obj)
void addOutPort(NetworkLink *out_link, CreditLink *credit_link, SwitchID router_id, uint32_t consumerVcs)
void print(std::ostream &out) const
GarnetNetworkInterfaceParams Params
std::vector< MessageBuffer * > outNode_ptr
void addNode(std::vector< MessageBuffer * > &inNode, std::vector< MessageBuffer * > &outNode)
void scheduleOutputPort(OutputPort *oPort)
std::vector< MessageBuffer * > inNode_ptr
bool flitisizeMessage(MsgPtr msg_ptr, int vnet)
void scheduleOutputLink()
This function looks at the NI buffers if some buffer has flits which are ready to traverse the link i...
RouteInfo get_route()
Definition flit.hh:68
void set_time(Tick time)
Definition flit.hh:75
void set_src_delay(Tick delay)
Definition flit.hh:78
MsgPtr & get_msg_ptr()
Definition flit.hh:69
void set_dequeue_time(Tick time)
Definition flit.hh:79
flit_type get_type()
Definition flit.hh:70
STL vector class.
Definition stl.hh:37
static constexpr T divCeil(const T &a, const U &b)
Definition intmath.hh:110
#define panic(...)
This implements a cprintf based panic() function.
Definition logging.hh:220
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
Definition logging.hh:268
#define fatal(...)
This implements a cprintf based fatal() function.
Definition logging.hh:232
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Definition logging.hh:246
Bitfield< 3, 0 > mask
Definition pcstate.hh:63
Bitfield< 7 > b
Bitfield< 7 > i
Definition misc_types.hh:67
Bitfield< 33 > id
Bitfield< 0 > m
Bitfield< 0 > p
std::shared_ptr< Message > MsgPtr
Definition Message.hh:60
unsigned int SwitchID
unsigned int NodeID
Copyright (c) 2024 Arm Limited All rights reserved.
Definition binary32.hh:36
Tick curTick()
The universal simulation clock.
Definition cur_tick.hh:46
uint64_t Tick
Tick count type.
Definition types.hh:58
NodeID num
range: 0 ... number of this machine's components in system - 1
Definition MachineID.hh:64

Generated on Mon Oct 27 2025 04:13:03 for gem5 by doxygen 1.14.0