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
;
98 next_round_robin_invc
++;
99 if (next_round_robin_invc
>= m_num_vcs
)
100 next_round_robin_invc
= 0;
101 m_round_robin_inport
[inport
] = next_round_robin_invc
;
103 for (int invc_iter
= 0; invc_iter
< m_num_vcs
; invc_iter
++) {
105 if (invc
>= m_num_vcs
)
108 if (m_input_unit
[inport
]->need_stage(invc
, ACTIVE_
, SA_
,
109 m_router
->curCycle()) &&
110 m_input_unit
[inport
]->has_credits(invc
)) {
112 if (is_candidate_inport(inport
, invc
)) {
113 int outport
= m_input_unit
[inport
]->get_route(invc
);
114 m_local_arbiter_activity
++;
115 m_port_req
[outport
][inport
] = true;
116 m_vc_winners
[outport
][inport
]= invc
;
117 break; // got one vc winner for this port
125 SWallocator_d::is_candidate_inport(int inport
, int invc
)
127 int outport
= m_input_unit
[inport
]->get_route(invc
);
128 Cycles t_enqueue_time
= m_input_unit
[inport
]->get_enqueue_time(invc
);
129 int t_vnet
= get_vnet(invc
);
130 int vc_base
= t_vnet
*m_vc_per_vnet
;
131 if ((m_router
->get_net_ptr())->isVNetOrdered(t_vnet
)) {
132 for (int vc_offset
= 0; vc_offset
< m_vc_per_vnet
; vc_offset
++) {
133 int temp_vc
= vc_base
+ vc_offset
;
134 if (m_input_unit
[inport
]->need_stage(temp_vc
, ACTIVE_
, SA_
,
135 m_router
->curCycle()) &&
136 (m_input_unit
[inport
]->get_route(temp_vc
) == outport
) &&
137 (m_input_unit
[inport
]->get_enqueue_time(temp_vc
) <
149 SWallocator_d::arbitrate_outports()
151 // Now there are a set of input vc requests for output vcs.
152 // Again do round robin arbitration on these requests
153 for (int outport
= 0; outport
< m_num_outports
; outport
++) {
154 int inport
= m_round_robin_outport
[outport
];
155 m_round_robin_outport
[outport
]++;
157 if (m_round_robin_outport
[outport
] >= m_num_outports
)
158 m_round_robin_outport
[outport
] = 0;
160 for (int inport_iter
= 0; inport_iter
< m_num_inports
; inport_iter
++) {
162 if (inport
>= m_num_inports
)
165 // inport has a request this cycle for outport:
166 if (m_port_req
[outport
][inport
]) {
167 m_port_req
[outport
][inport
] = false;
168 int invc
= m_vc_winners
[outport
][inport
];
169 int outvc
= m_input_unit
[inport
]->get_outvc(invc
);
171 // remove flit from Input Unit
172 flit_d
*t_flit
= m_input_unit
[inport
]->getTopFlit(invc
);
173 t_flit
->advance_stage(ST_
, m_router
->curCycle());
174 t_flit
->set_vc(outvc
);
175 t_flit
->set_outport(outport
);
176 t_flit
->set_time(m_router
->curCycle());
178 m_output_unit
[outport
]->decrement_credit(outvc
);
179 m_router
->update_sw_winner(inport
, t_flit
);
180 m_global_arbiter_activity
++;
182 if ((t_flit
->get_type() == TAIL_
) ||
183 t_flit
->get_type() == HEAD_TAIL_
) {
185 // Send a credit back
186 // along with the information that this VC is now idle
187 m_input_unit
[inport
]->increment_credit(invc
, true,
188 m_router
->curCycle());
190 // This Input VC should now be empty
191 assert(m_input_unit
[inport
]->isReady(invc
,
192 m_router
->curCycle()) == false);
194 m_input_unit
[inport
]->set_vc_state(IDLE_
, invc
,
195 m_router
->curCycle());
196 m_input_unit
[inport
]->set_enqueue_time(invc
,
199 // Send a credit back
200 // but do not indicate that the VC is idle
201 m_input_unit
[inport
]->increment_credit(invc
, false,
202 m_router
->curCycle());
204 break; // got a in request for this outport
211 SWallocator_d::check_for_wakeup()
213 Cycles nextCycle
= m_router
->curCycle() + Cycles(1);
215 for (int i
= 0; i
< m_num_inports
; i
++) {
216 for (int j
= 0; j
< m_num_vcs
; j
++) {
217 if (m_input_unit
[i
]->need_stage(j
, ACTIVE_
, SA_
, nextCycle
)) {
218 m_router
->vcarb_req();
226 SWallocator_d::get_vnet(int invc
)
228 int vnet
= invc
/m_vc_per_vnet
;
229 assert(vnet
< m_router
->get_num_vnets());
234 SWallocator_d::clear_request_vector()
236 for (int i
= 0; i
< m_num_outports
; i
++) {
237 for (int j
= 0; j
< m_num_inports
; j
++) {
238 m_port_req
[i
][j
] = false;