2 * Copyright (c) 2008 Princeton University
3 * Copyright (c) 2016 Georgia Institute of Technology
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met: redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer;
10 * redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution;
13 * neither the name of the copyright holders nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 * Authors: Niket Agarwal
34 #include "mem/ruby/network/garnet2.0/Router.hh"
36 #include "base/stl_helpers.hh"
37 #include "debug/RubyNetwork.hh"
38 #include "mem/ruby/network/garnet2.0/CreditLink.hh"
39 #include "mem/ruby/network/garnet2.0/CrossbarSwitch.hh"
40 #include "mem/ruby/network/garnet2.0/GarnetNetwork.hh"
41 #include "mem/ruby/network/garnet2.0/InputUnit.hh"
42 #include "mem/ruby/network/garnet2.0/NetworkLink.hh"
43 #include "mem/ruby/network/garnet2.0/OutputUnit.hh"
44 #include "mem/ruby/network/garnet2.0/RoutingUnit.hh"
45 #include "mem/ruby/network/garnet2.0/SwitchAllocator.hh"
48 using m5::stl_helpers::deletePointers
;
50 Router::Router(const Params
*p
)
51 : BasicRouter(p
), Consumer(this)
53 m_latency
= p
->latency
;
54 m_virtual_networks
= p
->virt_nets
;
55 m_vc_per_vnet
= p
->vcs_per_vnet
;
56 m_num_vcs
= m_virtual_networks
* m_vc_per_vnet
;
58 m_routing_unit
= new RoutingUnit(this);
59 m_sw_alloc
= new SwitchAllocator(this);
60 m_switch
= new CrossbarSwitch(this);
63 m_output_unit
.clear();
68 deletePointers(m_input_unit
);
69 deletePointers(m_output_unit
);
70 delete m_routing_unit
;
87 DPRINTF(RubyNetwork
, "Router %d woke up\n", m_id
);
89 // check for incoming flits
90 for (int inport
= 0; inport
< m_input_unit
.size(); inport
++) {
91 m_input_unit
[inport
]->wakeup();
94 // check for incoming credits
95 // Note: the credit update is happening before SA
96 // buffer turnaround time =
97 // credit traversal (1-cycle) + SA (1-cycle) + Link Traversal (1-cycle)
98 // if we want the credit update to take place after SA, this loop should
99 // be moved after the SA request
100 for (int outport
= 0; outport
< m_output_unit
.size(); outport
++) {
101 m_output_unit
[outport
]->wakeup();
105 m_sw_alloc
->wakeup();
112 Router::addInPort(PortDirection inport_dirn
,
113 NetworkLink
*in_link
, CreditLink
*credit_link
)
115 int port_num
= m_input_unit
.size();
116 InputUnit
*input_unit
= new InputUnit(port_num
, inport_dirn
, this);
118 input_unit
->set_in_link(in_link
);
119 input_unit
->set_credit_link(credit_link
);
120 in_link
->setLinkConsumer(this);
121 credit_link
->setSourceQueue(input_unit
->getCreditQueue());
123 m_input_unit
.push_back(input_unit
);
125 m_routing_unit
->addInDirection(inport_dirn
, port_num
);
129 Router::addOutPort(PortDirection outport_dirn
,
130 NetworkLink
*out_link
,
131 const NetDest
& routing_table_entry
, int link_weight
,
132 CreditLink
*credit_link
)
134 int port_num
= m_output_unit
.size();
135 OutputUnit
*output_unit
= new OutputUnit(port_num
, outport_dirn
, this);
137 output_unit
->set_out_link(out_link
);
138 output_unit
->set_credit_link(credit_link
);
139 credit_link
->setLinkConsumer(this);
140 out_link
->setSourceQueue(output_unit
->getOutQueue());
142 m_output_unit
.push_back(output_unit
);
144 m_routing_unit
->addRoute(routing_table_entry
);
145 m_routing_unit
->addWeight(link_weight
);
146 m_routing_unit
->addOutDirection(outport_dirn
, port_num
);
150 Router::getOutportDirection(int outport
)
152 return m_output_unit
[outport
]->get_direction();
156 Router::getInportDirection(int inport
)
158 return m_input_unit
[inport
]->get_direction();
162 Router::route_compute(RouteInfo route
, int inport
, PortDirection inport_dirn
)
164 return m_routing_unit
->outportCompute(route
, inport
, inport_dirn
);
168 Router::grant_switch(int inport
, flit
*t_flit
)
170 m_switch
->update_sw_winner(inport
, t_flit
);
174 Router::schedule_wakeup(Cycles time
)
176 // wake up after time cycles
181 Router::getPortDirectionName(PortDirection direction
)
183 // PortDirection is actually a string
184 // If not, then this function should add a switch
185 // statement to convert direction to a string
186 // that can be printed out
193 BasicRouter::regStats();
196 .name(name() + ".buffer_reads")
197 .flags(Stats::nozero
)
201 .name(name() + ".buffer_writes")
202 .flags(Stats::nozero
)
206 .name(name() + ".crossbar_activity")
207 .flags(Stats::nozero
)
210 m_sw_input_arbiter_activity
211 .name(name() + ".sw_input_arbiter_activity")
212 .flags(Stats::nozero
)
215 m_sw_output_arbiter_activity
216 .name(name() + ".sw_output_arbiter_activity")
217 .flags(Stats::nozero
)
222 Router::collateStats()
224 for (int j
= 0; j
< m_virtual_networks
; j
++) {
225 for (int i
= 0; i
< m_input_unit
.size(); i
++) {
226 m_buffer_reads
+= m_input_unit
[i
]->get_buf_read_activity(j
);
227 m_buffer_writes
+= m_input_unit
[i
]->get_buf_write_activity(j
);
231 m_sw_input_arbiter_activity
= m_sw_alloc
->get_input_arbiter_activity();
232 m_sw_output_arbiter_activity
= m_sw_alloc
->get_output_arbiter_activity();
233 m_crossbar_activity
= m_switch
->get_crossbar_activity();
239 for (int j
= 0; j
< m_virtual_networks
; j
++) {
240 for (int i
= 0; i
< m_input_unit
.size(); i
++) {
241 m_input_unit
[i
]->resetStats();
245 m_switch
->resetStats();
246 m_sw_alloc
->resetStats();
250 Router::printFaultVector(ostream
& out
)
252 int temperature_celcius
= BASELINE_TEMPERATURE_CELCIUS
;
253 int num_fault_types
= m_network_ptr
->fault_model
->number_of_fault_types
;
254 float fault_vector
[num_fault_types
];
255 get_fault_vector(temperature_celcius
, fault_vector
);
256 out
<< "Router-" << m_id
<< " fault vector: " << endl
;
257 for (int fault_type_index
= 0; fault_type_index
< num_fault_types
;
258 fault_type_index
++) {
259 out
<< " - probability of (";
261 m_network_ptr
->fault_model
->fault_type_to_string(fault_type_index
);
263 out
<< fault_vector
[fault_type_index
] << endl
;
268 Router::printAggregateFaultProbability(std::ostream
& out
)
270 int temperature_celcius
= BASELINE_TEMPERATURE_CELCIUS
;
271 float aggregate_fault_prob
;
272 get_aggregate_fault_probability(temperature_celcius
,
273 &aggregate_fault_prob
);
274 out
<< "Router-" << m_id
<< " fault probability: ";
275 out
<< aggregate_fault_prob
<< endl
;
279 Router::functionalWrite(Packet
*pkt
)
281 uint32_t num_functional_writes
= 0;
282 num_functional_writes
+= m_switch
->functionalWrite(pkt
);
284 for (uint32_t i
= 0; i
< m_input_unit
.size(); i
++) {
285 num_functional_writes
+= m_input_unit
[i
]->functionalWrite(pkt
);
288 for (uint32_t i
= 0; i
< m_output_unit
.size(); i
++) {
289 num_functional_writes
+= m_output_unit
[i
]->functionalWrite(pkt
);
292 return num_functional_writes
;
296 GarnetRouterParams::create()
298 return new Router(this);