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