gem5  v22.1.0.0
NetworkBridge.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020 Advanced Micro Devices, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  *
15  * 3. Neither the name of the copyright holder nor the names of its
16  * contributors may be used to endorse or promote products derived from this
17  * software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 
34 
35 #include <cmath>
36 
37 #include "debug/RubyNetwork.hh"
38 #include "params/GarnetIntLink.hh"
39 
40 namespace gem5
41 {
42 
43 namespace ruby
44 {
45 
46 namespace garnet
47 {
48 
50  :CreditLink(p)
51 {
52  enCdc = true;
53  enSerDes = true;
54  mType = p.vtype;
55 
56  cdcLatency = p.cdc_latency;
57  serDesLatency = p.serdes_latency;
58  lastScheduledAt = 0;
59 
60  nLink = p.link;
61  if (mType == enums::LINK_OBJECT) {
62  nLink->setLinkConsumer(this);
64  } else if (mType == enums::OBJECT_LINK) {
67  } else {
68  // CDC type must be set
69  panic("CDC type must be set");
70  }
71 }
72 
73 void
74 NetworkBridge::setVcsPerVnet(uint32_t consumerVcs)
75 {
76  DPRINTF(RubyNetwork, "VcsPerVnet VC: %d\n", consumerVcs);
77  NetworkLink::setVcsPerVnet(consumerVcs);
78  lenBuffer.resize(consumerVcs * m_virt_nets);
79  sizeSent.resize(consumerVcs * m_virt_nets);
80  flitsSent.resize(consumerVcs * m_virt_nets);
81  extraCredit.resize(consumerVcs * m_virt_nets);
82 
83  nLink->setVcsPerVnet(consumerVcs);
84 }
85 
86 void
87 NetworkBridge::initBridge(NetworkBridge *coBrid, bool cdc_en, bool serdes_en)
88 {
89  coBridge = coBrid;
90  enCdc = cdc_en;
91  enSerDes = serdes_en;
92 }
93 
95 {
96 }
97 
98 void
100 {
101  Cycles totLatency = latency;
102 
103  if (enCdc) {
104  // Add the CDC latency
105  totLatency = latency + cdcLatency;
106  }
107 
108  Tick sendTime = link_consumer->getObject()->clockEdge(totLatency);
109  Tick nextAvailTick = lastScheduledAt + link_consumer->getObject()->\ cyclesToTicks(Cycles(1));
110  sendTime = std::max(nextAvailTick, sendTime);
111  t_flit->set_time(sendTime);
112  lastScheduledAt = sendTime;
113  linkBuffer.insert(t_flit);
115 }
116 
117 void
118 NetworkBridge::neutralize(int vc, int eCredit)
119 {
120  extraCredit[vc].push(eCredit);
121 }
122 
123 void
125 {
126  // Serialize-Deserialize only if it is enabled
127  if (enSerDes) {
128  // Calculate the target-width
129  int target_width = bitWidth;
130  int cur_width = nLink->bitWidth;
131  if (mType == enums::OBJECT_LINK) {
132  target_width = nLink->bitWidth;
133  cur_width = bitWidth;
134  }
135 
136  DPRINTF(RubyNetwork, "Target width: %d Current: %d\n",
137  target_width, cur_width);
138  assert(target_width != cur_width);
139 
140  int vc = t_flit->get_vc();
141 
142  if (target_width > cur_width) {
143  // Deserialize
144  // This deserializer combines flits from the
145  // same message together
146  int num_flits = 0;
147  int flitPossible = 0;
148  if (t_flit->get_type() == CREDIT_) {
149  lenBuffer[vc]++;
150  assert(extraCredit[vc].front());
151  if (lenBuffer[vc] == extraCredit[vc].front()) {
152  flitPossible = 1;
153  extraCredit[vc].pop();
154  lenBuffer[vc] = 0;
155  }
156  } else if (t_flit->get_type() == TAIL_ ||
157  t_flit->get_type() == HEAD_TAIL_) {
158  // If its the end of packet, then send whatever
159  // is available.
160  int sizeAvail = (t_flit->msgSize - sizeSent[vc]);
161  flitPossible = ceil((float)sizeAvail/(float)target_width);
162  assert (flitPossible < 2);
163  num_flits = (t_flit->get_id() + 1) - flitsSent[vc];
164  // Stop tracking the packet.
165  flitsSent[vc] = 0;
166  sizeSent[vc] = 0;
167  } else {
168  // If we are yet to receive the complete packet
169  // track the size recieved and flits deserialized.
170  int sizeAvail =
171  ((t_flit->get_id() + 1)*cur_width) - sizeSent[vc];
172  flitPossible = floor((float)sizeAvail/(float)target_width);
173  assert (flitPossible < 2);
174  num_flits = (t_flit->get_id() + 1) - flitsSent[vc];
175  if (flitPossible) {
176  sizeSent[vc] += target_width;
177  flitsSent[vc] = t_flit->get_id() + 1;
178  }
179  }
180 
181  DPRINTF(RubyNetwork, "Deserialize :%dB -----> %dB "
182  " vc:%d\n", cur_width, target_width, vc);
183 
184  flit *fl = NULL;
185  if (flitPossible) {
186  fl = t_flit->deserialize(lenBuffer[vc], num_flits,
187  target_width);
188  }
189 
190  // Inform the credit serializer about the number
191  // of flits that were generated.
192  if (t_flit->get_type() != CREDIT_ && fl) {
193  coBridge->neutralize(vc, num_flits);
194  }
195 
196  // Schedule only if we are done deserializing
197  if (fl) {
198  DPRINTF(RubyNetwork, "Scheduling a flit\n");
199  lenBuffer[vc] = 0;
201  }
202  // Delete this flit, new flit is sent in any case
203  delete t_flit;
204  } else {
205  // Serialize
206  DPRINTF(RubyNetwork, "Serializing flit :%d -----> %d "
207  "(vc:%d, Original Message Size: %d)\n",
208  cur_width, target_width, vc, t_flit->msgSize);
209 
210  int flitPossible = 0;
211  if (t_flit->get_type() == CREDIT_) {
212  // We store the deserialization ratio and then
213  // access it when serializing credits in the
214  // oppposite direction.
215  assert(extraCredit[vc].front());
216  flitPossible = extraCredit[vc].front();
217  extraCredit[vc].pop();
218  } else if (t_flit->get_type() == HEAD_ ||
219  t_flit->get_type() == BODY_) {
220  int sizeAvail =
221  ((t_flit->get_id() + 1)*cur_width) - sizeSent[vc];
222  flitPossible = floor((float)sizeAvail/(float)target_width);
223  if (flitPossible) {
224  sizeSent[vc] += flitPossible*target_width;
225  flitsSent[vc] += flitPossible;
226  }
227  } else {
228  int sizeAvail = t_flit->msgSize - sizeSent[vc];
229  flitPossible = ceil((float)sizeAvail/(float)target_width);
230  sizeSent[vc] = 0;
231  flitsSent[vc] = 0;
232  }
233  assert(flitPossible > 0);
234 
235  // Schedule all the flits
236  // num_flits could be zero for credits
237  for (int i = 0; i < flitPossible; i++) {
238  // Ignore neutralized credits
239  flit *fl = t_flit->serialize(i, flitPossible, target_width);
241  DPRINTF(RubyNetwork, "Serialized to flit[%d of %d parts]:"
242  " %s\n", i+1, flitPossible, *fl);
243  }
244 
245  if (t_flit->get_type() != CREDIT_) {
246  coBridge->neutralize(vc, flitPossible);
247  }
248  // Delete this flit, new flit is sent in any case
249  delete t_flit;
250  }
251  return;
252  }
253 
254  // If only CDC is enabled schedule it
255  scheduleFlit(t_flit, Cycles(0));
256 }
257 void
259 {
260  flit *t_flit;
261 
262  if (link_srcQueue->isReady(curTick())) {
263  t_flit = link_srcQueue->getTopFlit();
264  DPRINTF(RubyNetwork, "Recieved flit %s\n", *t_flit);
265  flitisizeAndSend(t_flit);
266  }
267 
268  // Reschedule in case there is a waiting flit.
269  if (!link_srcQueue->isEmpty()) {
270  scheduleEvent(Cycles(1));
271  }
272 }
273 
274 } // namespace garnet
275 } // namespace ruby
276 } // namespace gem5
277 
#define DPRINTF(x,...)
Definition: trace.hh:186
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...
Cycles is a wrapper class for representing cycle counts, i.e.
Definition: types.hh:79
void scheduleEventAbsolute(Tick timeAbs)
Definition: Consumer.cc:63
void scheduleEvent(Cycles timeDelta)
Definition: Consumer.cc:56
ClockedObject * getObject()
Definition: Consumer.hh:82
void setVcsPerVnet(uint32_t consumerVcs)
std::vector< std::queue< int > > extraCredit
void scheduleFlit(flit *t_flit, Cycles latency)
void neutralize(int vc, int eCredit)
void initBridge(NetworkBridge *coBrid, bool cdc_en, bool serdes_en)
bool isReady(Tick curTime)
Definition: flitBuffer.cc:60
void set_time(Tick time)
Definition: flit.hh:75
virtual flit * serialize(int ser_id, int parts, uint32_t bWidth)
Definition: flit.cc:77
virtual flit * deserialize(int des_id, int num_flits, uint32_t bWidth)
Definition: flit.cc:94
flit_type get_type()
Definition: flit.hh:70
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:178
Bitfield< 7 > i
Definition: misc_types.hh:67
Bitfield< 54 > p
Definition: pagetable.hh:70
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
Tick curTick()
The universal simulation clock.
Definition: cur_tick.hh:46
uint64_t Tick
Tick count type.
Definition: types.hh:58

Generated on Wed Dec 21 2022 10:22:38 for gem5 by doxygen 1.9.1