2 * Copyright (c) 2008 Princeton University
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 * Authors: Niket Agarwal
31 #include "mem/ruby/network/garnet/fixed-pipeline/GarnetNetwork_d.hh"
32 #include "mem/ruby/network/garnet/fixed-pipeline/InputUnit_d.hh"
33 #include "mem/ruby/network/garnet/fixed-pipeline/OutputUnit_d.hh"
34 #include "mem/ruby/network/garnet/fixed-pipeline/Router_d.hh"
35 #include "mem/ruby/network/garnet/fixed-pipeline/SWallocator_d.hh"
37 SWallocator_d::SWallocator_d(Router_d
*router
)
41 m_num_vcs
= m_router
->get_num_vcs();
42 m_vc_per_vnet
= m_router
->get_vc_per_vnet();
44 m_local_arbiter_activity
= 0;
45 m_global_arbiter_activity
= 0;
51 m_input_unit
= m_router
->get_inputUnit_ref();
52 m_output_unit
= m_router
->get_outputUnit_ref();
54 m_num_inports
= m_router
->get_num_inports();
55 m_num_outports
= m_router
->get_num_outports();
56 m_round_robin_outport
.resize(m_num_outports
);
57 m_round_robin_inport
.resize(m_num_inports
);
58 m_port_req
.resize(m_num_outports
);
59 m_vc_winners
.resize(m_num_outports
);
61 for (int i
= 0; i
< m_num_inports
; i
++) {
62 m_round_robin_inport
[i
] = 0;
65 for (int i
= 0; i
< m_num_outports
; i
++) {
66 m_port_req
[i
].resize(m_num_inports
);
67 m_vc_winners
[i
].resize(m_num_inports
);
69 m_round_robin_outport
[i
] = 0;
71 for (int j
= 0; j
< m_num_inports
; j
++) {
72 m_port_req
[i
][j
] = false; // [outport][inport]
78 SWallocator_d::wakeup()
80 arbitrate_inports(); // First stage of allocation
81 arbitrate_outports(); // Second stage of allocation
83 clear_request_vector();
85 m_router
->call_switch();
90 SWallocator_d::arbitrate_inports()
92 // First do round robin arbitration on a set of input vc requests
93 for (int inport
= 0; inport
< m_num_inports
; inport
++) {
94 int invc
= m_round_robin_inport
[inport
];
96 // Select next round robin vc candidate within valid vnet
97 int next_round_robin_invc
= invc
;
99 next_round_robin_invc
++;
101 if (next_round_robin_invc
>= m_num_vcs
)
102 next_round_robin_invc
= 0;
103 } while (!((m_router
->get_net_ptr())->validVirtualNetwork(
104 get_vnet(next_round_robin_invc
))));
106 m_round_robin_inport
[inport
] = next_round_robin_invc
;
108 for (int invc_iter
= 0; invc_iter
< m_num_vcs
; invc_iter
++) {
110 if (invc
>= m_num_vcs
)
113 if (!((m_router
->get_net_ptr())->validVirtualNetwork(
117 if (m_input_unit
[inport
]->need_stage(invc
, ACTIVE_
, SA_
,
118 m_router
->curCycle()) &&
119 m_input_unit
[inport
]->has_credits(invc
)) {
121 if (is_candidate_inport(inport
, invc
)) {
122 int outport
= m_input_unit
[inport
]->get_route(invc
);
123 m_local_arbiter_activity
++;
124 m_port_req
[outport
][inport
] = true;
125 m_vc_winners
[outport
][inport
]= invc
;
126 break; // got one vc winner for this port
134 SWallocator_d::is_candidate_inport(int inport
, int invc
)
136 int outport
= m_input_unit
[inport
]->get_route(invc
);
137 Cycles t_enqueue_time
= m_input_unit
[inport
]->get_enqueue_time(invc
);
138 int t_vnet
= get_vnet(invc
);
139 int vc_base
= t_vnet
*m_vc_per_vnet
;
140 if ((m_router
->get_net_ptr())->isVNetOrdered(t_vnet
)) {
141 for (int vc_offset
= 0; vc_offset
< m_vc_per_vnet
; vc_offset
++) {
142 int temp_vc
= vc_base
+ vc_offset
;
143 if (m_input_unit
[inport
]->need_stage(temp_vc
, ACTIVE_
, SA_
,
144 m_router
->curCycle()) &&
145 (m_input_unit
[inport
]->get_route(temp_vc
) == outport
) &&
146 (m_input_unit
[inport
]->get_enqueue_time(temp_vc
) <
158 SWallocator_d::arbitrate_outports()
160 // Now there are a set of input vc requests for output vcs.
161 // Again do round robin arbitration on these requests
162 for (int outport
= 0; outport
< m_num_outports
; outport
++) {
163 int inport
= m_round_robin_outport
[outport
];
164 m_round_robin_outport
[outport
]++;
166 if (m_round_robin_outport
[outport
] >= m_num_outports
)
167 m_round_robin_outport
[outport
] = 0;
169 for (int inport_iter
= 0; inport_iter
< m_num_inports
; inport_iter
++) {
171 if (inport
>= m_num_inports
)
174 // inport has a request this cycle for outport:
175 if (m_port_req
[outport
][inport
]) {
176 m_port_req
[outport
][inport
] = false;
177 int invc
= m_vc_winners
[outport
][inport
];
178 int outvc
= m_input_unit
[inport
]->get_outvc(invc
);
180 // remove flit from Input Unit
181 flit_d
*t_flit
= m_input_unit
[inport
]->getTopFlit(invc
);
182 t_flit
->advance_stage(ST_
, m_router
->curCycle());
183 t_flit
->set_vc(outvc
);
184 t_flit
->set_outport(outport
);
185 t_flit
->set_time(m_router
->curCycle());
187 m_output_unit
[outport
]->decrement_credit(outvc
);
188 m_router
->update_sw_winner(inport
, t_flit
);
189 m_global_arbiter_activity
++;
191 if ((t_flit
->get_type() == TAIL_
) ||
192 t_flit
->get_type() == HEAD_TAIL_
) {
194 // Send a credit back
195 // along with the information that this VC is now idle
196 m_input_unit
[inport
]->increment_credit(invc
, true,
197 m_router
->curCycle());
199 // This Input VC should now be empty
200 assert(m_input_unit
[inport
]->isReady(invc
,
201 m_router
->curCycle()) == false);
203 m_input_unit
[inport
]->set_vc_state(IDLE_
, invc
,
204 m_router
->curCycle());
205 m_input_unit
[inport
]->set_enqueue_time(invc
,
208 // Send a credit back
209 // but do not indicate that the VC is idle
210 m_input_unit
[inport
]->increment_credit(invc
, false,
211 m_router
->curCycle());
213 break; // got a in request for this outport
220 SWallocator_d::check_for_wakeup()
222 Cycles nextCycle
= m_router
->curCycle() + Cycles(1);
224 for (int i
= 0; i
< m_num_inports
; i
++) {
225 for (int j
= 0; j
< m_num_vcs
; j
++) {
226 if (m_input_unit
[i
]->need_stage(j
, ACTIVE_
, SA_
, nextCycle
)) {
227 m_router
->vcarb_req();
235 SWallocator_d::get_vnet(int invc
)
237 int vnet
= invc
/m_vc_per_vnet
;
238 assert(vnet
< m_router
->get_num_vnets());
243 SWallocator_d::clear_request_vector()
245 for (int i
= 0; i
< m_num_outports
; i
++) {
246 for (int j
= 0; j
< m_num_inports
; j
++) {
247 m_port_req
[i
][j
] = false;