Line data Source code
1 : #include "Tools/Builder/Pipeline_builder.hpp"
2 : #include "Runtime/Pipeline/Pipeline.hpp"
3 :
4 : using namespace spu;
5 : using namespace spu::tools;
6 :
7 : Pipeline_builder&
8 1 : Pipeline_builder::set_tasks_for_checking(const std::vector<runtime::Task*> tasks)
9 : {
10 1 : this->tasks_for_checking.assign(tasks.begin(), tasks.end());
11 1 : return *this;
12 : }
13 :
14 : Pipeline_builder&
15 10 : Pipeline_builder::add_task_for_checking(runtime::Task* task)
16 : {
17 10 : if (std::find(this->tasks_for_checking.begin(), this->tasks_for_checking.end(), task) !=
18 20 : this->tasks_for_checking.end())
19 : {
20 0 : throw invalid_argument(__FILE__, __LINE__, __func__, "The task is already added in tasks for checking.");
21 : }
22 :
23 10 : this->tasks_for_checking.push_back(task);
24 :
25 10 : return *this;
26 : }
27 :
28 : Pipeline_builder&
29 10 : Pipeline_builder::add_task_for_checking(runtime::Task& task)
30 : {
31 10 : return this->add_task_for_checking(&task);
32 : }
33 :
34 : Pipeline_builder&
35 0 : Pipeline_builder::remove_task_for_checking(const runtime::Task* task)
36 : {
37 0 : this->tasks_for_checking.erase(std::remove(this->tasks_for_checking.begin(), this->tasks_for_checking.end(), task),
38 0 : this->tasks_for_checking.end());
39 :
40 0 : return *this;
41 : }
42 :
43 : const std::vector<runtime::Task*>
44 10 : Pipeline_builder::get_tasks_for_checking()
45 : {
46 10 : return this->tasks_for_checking;
47 : }
48 :
49 : Pipeline_builder&
50 35 : Pipeline_builder::add_stage(Stage_builder& stage)
51 : {
52 35 : if (std::find(this->stages.begin(), this->stages.end(), &stage) != this->stages.end())
53 : {
54 0 : throw invalid_argument(__FILE__, __LINE__, __func__, "The stage is already added.");
55 : }
56 :
57 35 : this->stages.push_back(&stage);
58 :
59 35 : return *this;
60 : }
61 :
62 : Pipeline_builder&
63 4 : Pipeline_builder::remove_stage(const Stage_builder& stage)
64 : {
65 4 : this->stages.erase(std::remove(this->stages.begin(), this->stages.end(), &stage), this->stages.end());
66 :
67 4 : return *this;
68 : }
69 :
70 : Pipeline_builder&
71 0 : Pipeline_builder::remove_stage(const size_t stage_id)
72 : {
73 0 : if (stage_id >= this->stages.size())
74 : {
75 0 : throw length_error(__FILE__, __LINE__, __func__, "No stage of index 'stage_id' exists.");
76 : }
77 :
78 0 : this->stages.erase(std::remove(this->stages.begin(), this->stages.end(), this->stages[stage_id]),
79 0 : this->stages.end());
80 :
81 0 : return *this;
82 : }
83 :
84 : Pipeline_builder::Stage_builder&
85 13 : Pipeline_builder::get_stage(const size_t stage_id)
86 : {
87 13 : if (stage_id >= this->stages.size())
88 : {
89 0 : throw length_error(__FILE__, __LINE__, __func__, "No stage of index 'stage_id' exists.");
90 : }
91 :
92 13 : return *this->stages[stage_id];
93 : }
94 :
95 : Pipeline_builder&
96 18 : Pipeline_builder::configure_interstage_synchro(Synchro_builder& synchro)
97 : {
98 18 : if (std::find(this->synchros.begin(), this->synchros.end(), &synchro) != this->synchros.end())
99 : {
100 0 : throw invalid_argument(__FILE__, __LINE__, __func__, "The interstage synchronization is already added.");
101 : }
102 :
103 18 : this->synchros.push_back(&synchro);
104 :
105 18 : return *this;
106 : }
107 :
108 : Pipeline_builder::Synchro_builder&
109 0 : Pipeline_builder::get_interstage_synchro(const size_t synchro_id)
110 : {
111 0 : if (synchro_id >= this->synchros.size())
112 : {
113 0 : throw length_error(__FILE__, __LINE__, __func__, "No interstage synchronization of index 'synchro_id' exists.");
114 : }
115 :
116 0 : return *this->synchros[synchro_id];
117 : }
118 :
119 : spu::tools::Pipeline_builder::pipeline_construct_t
120 10 : Pipeline_builder::_build()
121 : {
122 10 : spu::tools::Pipeline_builder::pipeline_construct_t pipc;
123 :
124 : // Build stages
125 41 : for (auto it = this->stages.begin(); it != this->stages.end(); it++)
126 : {
127 31 : Stage_builder* stage = *it;
128 :
129 31 : pipc.built_stages.push_back(std::make_tuple<std::vector<spu::runtime::Task*>,
130 : std::vector<spu::runtime::Task*>,
131 62 : std::vector<spu::runtime::Task*>>(
132 62 : std::vector<spu::runtime::Task*>(stage->get_first_tasks()),
133 62 : std::vector<spu::runtime::Task*>(stage->get_last_tasks()),
134 62 : std::vector<spu::runtime::Task*>(stage->get_excluded_tasks())));
135 :
136 31 : pipc.threads.push_back(stage->get_n_threads());
137 31 : pipc.pinning.push_back(stage->is_pinning());
138 31 : pipc.pinning_policy += stage->get_pinning_policy();
139 31 : if (it < this->stages.end() - 1) pipc.pinning_policy += "|";
140 : }
141 :
142 : // Build synchronization between stages
143 10 : Synchro_builder synchro_default;
144 31 : for (size_t stage_id = 0; stage_id < this->stages.size() - 1; stage_id++)
145 : {
146 21 : if (stage_id < this->synchros.size())
147 : {
148 18 : pipc.buffer_sizes.push_back(this->synchros[stage_id]->get_buffer_size());
149 18 : pipc.waitings.push_back(this->synchros[stage_id]->is_active_waiting());
150 : }
151 : else
152 : {
153 3 : pipc.buffer_sizes.push_back(synchro_default.get_buffer_size());
154 3 : pipc.waitings.push_back(synchro_default.is_active_waiting());
155 : }
156 : }
157 :
158 20 : return pipc;
159 0 : }
160 :
161 : runtime::Pipeline
162 10 : Pipeline_builder::build()
163 : {
164 10 : pipeline_construct_t pipc = _build();
165 20 : return runtime::Pipeline(this->get_tasks_for_checking(),
166 : pipc.built_stages,
167 : pipc.threads,
168 : pipc.buffer_sizes,
169 : pipc.waitings,
170 : pipc.pinning,
171 20 : pipc.pinning_policy);
172 10 : }
173 :
174 : runtime::Pipeline*
175 0 : Pipeline_builder::build_ptr()
176 : {
177 0 : pipeline_construct_t pipc = _build();
178 0 : return new runtime::Pipeline(this->get_tasks_for_checking(),
179 : pipc.built_stages,
180 : pipc.threads,
181 : pipc.buffer_sizes,
182 : pipc.waitings,
183 : pipc.pinning,
184 0 : pipc.pinning_policy);
185 0 : }
186 :
187 : size_t
188 0 : spu::tools::Pipeline_builder::get_n_stages()
189 : {
190 0 : return stages.size();
191 : }
192 :
193 : Pipeline_builder::Stage_builder&
194 28 : Pipeline_builder::Stage_builder::set_n_threads(const size_t n)
195 : {
196 28 : this->n_threads = n;
197 28 : return *this;
198 : }
199 :
200 : size_t
201 31 : Pipeline_builder::Stage_builder::get_n_threads()
202 : {
203 31 : return this->n_threads;
204 : }
205 :
206 : Pipeline_builder::Stage_builder&
207 1 : Pipeline_builder::Stage_builder::enable_threads_pinning()
208 : {
209 1 : this->pinning = true;
210 1 : return *this;
211 : }
212 :
213 : Pipeline_builder::Stage_builder&
214 1 : Pipeline_builder::Stage_builder::disable_threads_pinning()
215 : {
216 1 : this->pinning = false;
217 1 : return *this;
218 : }
219 :
220 : Pipeline_builder::Stage_builder&
221 2 : Pipeline_builder::Stage_builder::set_threads_pinning(bool pinning)
222 : {
223 2 : return (pinning) ? this->enable_threads_pinning() : this->disable_threads_pinning();
224 : }
225 :
226 : bool
227 31 : Pipeline_builder::Stage_builder::is_pinning()
228 : {
229 31 : return this->pinning;
230 : }
231 :
232 : Pipeline_builder::Stage_builder&
233 1 : Pipeline_builder::Stage_builder::set_pinning_policy(const std::string pinning_policy)
234 : {
235 1 : this->pinning_policy = pinning_policy;
236 1 : return *this;
237 : }
238 :
239 : const std::string
240 31 : Pipeline_builder::Stage_builder::get_pinning_policy()
241 : {
242 31 : return this->pinning_policy;
243 : }
244 :
245 : Pipeline_builder::Stage_builder&
246 1 : Pipeline_builder::Stage_builder::set_first_tasks(const std::vector<runtime::Task*> first)
247 : {
248 1 : this->first_tasks.assign(first.begin(), first.end());
249 1 : return *this;
250 : }
251 :
252 : Pipeline_builder::Stage_builder&
253 35 : Pipeline_builder::Stage_builder::add_first_task(runtime::Task* first)
254 : {
255 35 : if (std::find(this->first_tasks.begin(), this->first_tasks.end(), first) != this->first_tasks.end())
256 : {
257 0 : throw invalid_argument(__FILE__, __LINE__, __func__, "The task is already added in first tasks.");
258 : }
259 :
260 35 : this->first_tasks.push_back(first);
261 35 : return *this;
262 : }
263 :
264 : Pipeline_builder::Stage_builder&
265 35 : Pipeline_builder::Stage_builder::add_first_task(runtime::Task& first)
266 : {
267 35 : return this->add_first_task(&first);
268 : }
269 :
270 : Pipeline_builder::Stage_builder&
271 0 : Pipeline_builder::Stage_builder::remove_first_task(const runtime::Task* first)
272 : {
273 0 : this->first_tasks.erase(std::remove(this->first_tasks.begin(), this->first_tasks.end(), first),
274 0 : this->first_tasks.end());
275 :
276 0 : return *this;
277 : }
278 :
279 : Pipeline_builder::Stage_builder&
280 0 : Pipeline_builder::Stage_builder::remove_first_task(const runtime::Task& first)
281 : {
282 0 : return this->remove_first_task(&first);
283 : }
284 :
285 : const std::vector<runtime::Task*>
286 39 : Pipeline_builder::Stage_builder::get_first_tasks()
287 : {
288 39 : return this->first_tasks;
289 : }
290 :
291 : Pipeline_builder::Stage_builder&
292 1 : Pipeline_builder::Stage_builder::set_last_tasks(const std::vector<runtime::Task*> last)
293 : {
294 1 : this->last_tasks.assign(last.begin(), last.end());
295 1 : return *this;
296 : }
297 :
298 : Pipeline_builder::Stage_builder&
299 26 : Pipeline_builder::Stage_builder::add_last_task(runtime::Task* last)
300 : {
301 26 : if (std::find(this->last_tasks.begin(), this->last_tasks.end(), last) != this->last_tasks.end())
302 : {
303 0 : throw invalid_argument(__FILE__, __LINE__, __func__, "The task is already added in last tasks.");
304 : }
305 :
306 26 : this->last_tasks.push_back(last);
307 26 : return *this;
308 : }
309 :
310 : Pipeline_builder::Stage_builder&
311 26 : Pipeline_builder::Stage_builder::add_last_task(runtime::Task& last)
312 : {
313 26 : return this->add_last_task(&last);
314 : }
315 :
316 : Pipeline_builder::Stage_builder&
317 0 : Pipeline_builder::Stage_builder::remove_last_task(const runtime::Task* last)
318 : {
319 0 : this->last_tasks.erase(std::remove(this->last_tasks.begin(), this->last_tasks.end(), last), this->last_tasks.end());
320 :
321 0 : return *this;
322 : }
323 :
324 : Pipeline_builder::Stage_builder&
325 0 : Pipeline_builder::Stage_builder::remove_last_task(const runtime::Task& last)
326 : {
327 0 : return this->remove_last_task(&last);
328 : }
329 :
330 : const std::vector<runtime::Task*>
331 39 : Pipeline_builder::Stage_builder::get_last_tasks()
332 : {
333 39 : return this->last_tasks;
334 : }
335 :
336 : Pipeline_builder::Stage_builder&
337 1 : Pipeline_builder::Stage_builder::set_excluded_tasks(const std::vector<runtime::Task*> excluded)
338 : {
339 1 : this->excluded_tasks.assign(excluded.begin(), excluded.end());
340 1 : return *this;
341 : }
342 :
343 : Pipeline_builder::Stage_builder&
344 1 : Pipeline_builder::Stage_builder::add_excluded_task(runtime::Task* excluded)
345 : {
346 1 : if (std::find(this->excluded_tasks.begin(), this->excluded_tasks.end(), excluded) != this->excluded_tasks.end())
347 : {
348 0 : throw invalid_argument(__FILE__, __LINE__, __func__, "The task is already added in excluded tasks.");
349 : }
350 :
351 1 : this->excluded_tasks.push_back(excluded);
352 1 : return *this;
353 : }
354 :
355 : Pipeline_builder::Stage_builder&
356 1 : Pipeline_builder::Stage_builder::add_excluded_task(runtime::Task& excluded)
357 : {
358 1 : return this->add_excluded_task(&excluded);
359 : }
360 :
361 : Pipeline_builder::Stage_builder&
362 0 : Pipeline_builder::Stage_builder::remove_excluded_task(const runtime::Task* excluded)
363 : {
364 0 : this->excluded_tasks.erase(std::remove(this->excluded_tasks.begin(), this->excluded_tasks.end(), excluded),
365 0 : this->excluded_tasks.end());
366 :
367 0 : return *this;
368 : }
369 :
370 : Pipeline_builder::Stage_builder&
371 0 : Pipeline_builder::Stage_builder::remove_excluded_task(const runtime::Task& excluded)
372 : {
373 0 : return this->remove_excluded_task(&excluded);
374 : }
375 :
376 : const std::vector<runtime::Task*>
377 31 : Pipeline_builder::Stage_builder::get_excluded_tasks()
378 : {
379 31 : return this->excluded_tasks;
380 : }
381 :
382 : Pipeline_builder::Synchro_builder&
383 3 : Pipeline_builder::Synchro_builder::enable_active_waiting()
384 : {
385 3 : this->active_waiting = true;
386 3 : return *this;
387 : }
388 :
389 : Pipeline_builder::Synchro_builder&
390 16 : Pipeline_builder::Synchro_builder::disable_active_waiting()
391 : {
392 16 : this->active_waiting = false;
393 16 : return *this;
394 : }
395 :
396 : Pipeline_builder::Synchro_builder&
397 19 : Pipeline_builder::Synchro_builder::set_active_waiting(bool waiting)
398 : {
399 19 : return (waiting) ? this->enable_active_waiting() : this->disable_active_waiting();
400 : }
401 :
402 : bool
403 21 : Pipeline_builder::Synchro_builder::is_active_waiting()
404 : {
405 21 : return this->active_waiting;
406 : }
407 :
408 : Pipeline_builder::Synchro_builder&
409 19 : Pipeline_builder::Synchro_builder::set_buffer_size(size_t buffer_size)
410 : {
411 19 : this->buffer_size = buffer_size;
412 19 : return *this;
413 : }
414 :
415 : size_t
416 21 : Pipeline_builder::Synchro_builder::get_buffer_size()
417 : {
418 21 : return this->buffer_size;
419 : }
|