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
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.
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.
33 #include "mem/ruby/network/garnet/Router.hh"
35 #include "debug/RubyNetwork.hh"
36 #include "mem/ruby/network/garnet/CreditLink.hh"
37 #include "mem/ruby/network/garnet/GarnetNetwork.hh"
38 #include "mem/ruby/network/garnet/InputUnit.hh"
39 #include "mem/ruby/network/garnet/NetworkLink.hh"
40 #include "mem/ruby/network/garnet/OutputUnit.hh"
44 Router::Router(const Params
&p
)
45 : BasicRouter(p
), Consumer(this), m_latency(p
.latency
),
46 m_virtual_networks(p
.virt_nets
), m_vc_per_vnet(p
.vcs_per_vnet
),
47 m_num_vcs(m_virtual_networks
* m_vc_per_vnet
), m_bit_width(p
.width
),
48 m_network_ptr(nullptr), routingUnit(this), switchAllocator(this),
52 m_output_unit
.clear();
60 switchAllocator
.init();
61 crossbarSwitch
.init();
67 DPRINTF(RubyNetwork
, "Router %d woke up\n", m_id
);
68 assert(clockEdge() == curTick());
70 // check for incoming flits
71 for (int inport
= 0; inport
< m_input_unit
.size(); inport
++) {
72 m_input_unit
[inport
]->wakeup();
75 // check for incoming credits
76 // Note: the credit update is happening before SA
77 // buffer turnaround time =
78 // credit traversal (1-cycle) + SA (1-cycle) + Link Traversal (1-cycle)
79 // if we want the credit update to take place after SA, this loop should
80 // be moved after the SA request
81 for (int outport
= 0; outport
< m_output_unit
.size(); outport
++) {
82 m_output_unit
[outport
]->wakeup();
86 switchAllocator
.wakeup();
89 crossbarSwitch
.wakeup();
93 Router::addInPort(PortDirection inport_dirn
,
94 NetworkLink
*in_link
, CreditLink
*credit_link
)
96 fatal_if(in_link
->bitWidth
!= m_bit_width
, "Widths of link %s(%d)does"
97 " not match that of Router%d(%d). Consider inserting SerDes "
98 "Units.", in_link
->name(), in_link
->bitWidth
, m_id
, m_bit_width
);
100 int port_num
= m_input_unit
.size();
101 InputUnit
*input_unit
= new InputUnit(port_num
, inport_dirn
, this);
103 input_unit
->set_in_link(in_link
);
104 input_unit
->set_credit_link(credit_link
);
105 in_link
->setLinkConsumer(this);
106 in_link
->setVcsPerVnet(get_vc_per_vnet());
107 credit_link
->setSourceQueue(input_unit
->getCreditQueue(), this);
108 credit_link
->setVcsPerVnet(get_vc_per_vnet());
110 m_input_unit
.push_back(std::shared_ptr
<InputUnit
>(input_unit
));
112 routingUnit
.addInDirection(inport_dirn
, port_num
);
116 Router::addOutPort(PortDirection outport_dirn
,
117 NetworkLink
*out_link
,
118 std::vector
<NetDest
>& routing_table_entry
, int link_weight
,
119 CreditLink
*credit_link
, uint32_t consumerVcs
)
121 fatal_if(out_link
->bitWidth
!= m_bit_width
, "Widths of units do not match."
122 " Consider inserting SerDes Units");
124 int port_num
= m_output_unit
.size();
125 OutputUnit
*output_unit
= new OutputUnit(port_num
, outport_dirn
, this,
128 output_unit
->set_out_link(out_link
);
129 output_unit
->set_credit_link(credit_link
);
130 credit_link
->setLinkConsumer(this);
131 credit_link
->setVcsPerVnet(consumerVcs
);
132 out_link
->setSourceQueue(output_unit
->getOutQueue(), this);
133 out_link
->setVcsPerVnet(consumerVcs
);
135 m_output_unit
.push_back(std::shared_ptr
<OutputUnit
>(output_unit
));
137 routingUnit
.addRoute(routing_table_entry
);
138 routingUnit
.addWeight(link_weight
);
139 routingUnit
.addOutDirection(outport_dirn
, port_num
);
143 Router::getOutportDirection(int outport
)
145 return m_output_unit
[outport
]->get_direction();
149 Router::getInportDirection(int inport
)
151 return m_input_unit
[inport
]->get_direction();
155 Router::route_compute(RouteInfo route
, int inport
, PortDirection inport_dirn
)
157 return routingUnit
.outportCompute(route
, inport
, inport_dirn
);
161 Router::grant_switch(int inport
, flit
*t_flit
)
163 crossbarSwitch
.update_sw_winner(inport
, t_flit
);
167 Router::schedule_wakeup(Cycles time
)
169 // wake up after time cycles
174 Router::getPortDirectionName(PortDirection direction
)
176 // PortDirection is actually a string
177 // If not, then this function should add a switch
178 // statement to convert direction to a string
179 // that can be printed out
186 BasicRouter::regStats();
189 .name(name() + ".buffer_reads")
190 .flags(Stats::nozero
)
194 .name(name() + ".buffer_writes")
195 .flags(Stats::nozero
)
199 .name(name() + ".crossbar_activity")
200 .flags(Stats::nozero
)
203 m_sw_input_arbiter_activity
204 .name(name() + ".sw_input_arbiter_activity")
205 .flags(Stats::nozero
)
208 m_sw_output_arbiter_activity
209 .name(name() + ".sw_output_arbiter_activity")
210 .flags(Stats::nozero
)
215 Router::collateStats()
217 for (int j
= 0; j
< m_virtual_networks
; j
++) {
218 for (int i
= 0; i
< m_input_unit
.size(); i
++) {
219 m_buffer_reads
+= m_input_unit
[i
]->get_buf_read_activity(j
);
220 m_buffer_writes
+= m_input_unit
[i
]->get_buf_write_activity(j
);
224 m_sw_input_arbiter_activity
= switchAllocator
.get_input_arbiter_activity();
225 m_sw_output_arbiter_activity
=
226 switchAllocator
.get_output_arbiter_activity();
227 m_crossbar_activity
= crossbarSwitch
.get_crossbar_activity();
233 for (int i
= 0; i
< m_input_unit
.size(); i
++) {
234 m_input_unit
[i
]->resetStats();
237 crossbarSwitch
.resetStats();
238 switchAllocator
.resetStats();
242 Router::printFaultVector(ostream
& out
)
244 int temperature_celcius
= BASELINE_TEMPERATURE_CELCIUS
;
245 int num_fault_types
= m_network_ptr
->fault_model
->number_of_fault_types
;
246 float fault_vector
[num_fault_types
];
247 get_fault_vector(temperature_celcius
, fault_vector
);
248 out
<< "Router-" << m_id
<< " fault vector: " << endl
;
249 for (int fault_type_index
= 0; fault_type_index
< num_fault_types
;
250 fault_type_index
++) {
251 out
<< " - probability of (";
253 m_network_ptr
->fault_model
->fault_type_to_string(fault_type_index
);
255 out
<< fault_vector
[fault_type_index
] << endl
;
260 Router::printAggregateFaultProbability(std::ostream
& out
)
262 int temperature_celcius
= BASELINE_TEMPERATURE_CELCIUS
;
263 float aggregate_fault_prob
;
264 get_aggregate_fault_probability(temperature_celcius
,
265 &aggregate_fault_prob
);
266 out
<< "Router-" << m_id
<< " fault probability: ";
267 out
<< aggregate_fault_prob
<< endl
;
271 Router::functionalWrite(Packet
*pkt
)
273 uint32_t num_functional_writes
= 0;
274 num_functional_writes
+= crossbarSwitch
.functionalWrite(pkt
);
276 for (uint32_t i
= 0; i
< m_input_unit
.size(); i
++) {
277 num_functional_writes
+= m_input_unit
[i
]->functionalWrite(pkt
);
280 for (uint32_t i
= 0; i
< m_output_unit
.size(); i
++) {
281 num_functional_writes
+= m_output_unit
[i
]->functionalWrite(pkt
);
284 return num_functional_writes
;
288 GarnetRouterParams::create() const
290 return new Router(*this);