PandA-2024.02
design_flow_manager.cpp
Go to the documentation of this file.
1 /*
2  *
3  * _/_/_/ _/_/ _/ _/ _/_/_/ _/_/
4  * _/ _/ _/ _/ _/_/ _/ _/ _/ _/ _/
5  * _/_/_/ _/_/_/_/ _/ _/_/ _/ _/ _/_/_/_/
6  * _/ _/ _/ _/ _/ _/ _/ _/ _/
7  * _/ _/ _/ _/ _/ _/_/_/ _/ _/
8  *
9  * ***********************************************
10  * PandA Project
11  * URL: http://panda.dei.polimi.it
12  * Politecnico di Milano - DEIB
13  * System Architectures Group
14  * ***********************************************
15  * Copyright (C) 2004-2024 Politecnico di Milano
16  *
17  * This file is part of the PandA framework.
18  *
19  * The PandA framework is free software; you can redistribute it and/or modify
20  * it under the terms of the GNU General Public License as published by
21  * the Free Software Foundation; either version 3 of the License, or
22  * (at your option) any later version.
23  *
24  * This program is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27  * GNU General Public License for more details.
28  *
29  * You should have received a copy of the GNU General Public License
30  * along with this program. If not, see <http://www.gnu.org/licenses/>.
31  *
32  */
43 #include "design_flow_manager.hpp"
44 
45 #include "config_HAVE_ASSERTS.hpp" // for HAVE_ASSERTS
46 #include "config_HAVE_UNORDERED.hpp" // for HAVE_UNORDERED
47 
48 #include <boost/graph/adjacency_list.hpp> // for adjacency_list, source
49 #include <boost/graph/filtered_graph.hpp> // for in_edges, num_vertices
50 #include <boost/iterator/filter_iterator.hpp> // for filter_iterator
51 #include <boost/iterator/iterator_facade.hpp> // for operator!=, operator++
52 #include <boost/tuple/tuple.hpp> // for tie
53 #include <iterator> // for advance
54 #include <list> // for list
55 #if !HAVE_UNORDERED
56 #ifndef NDEBUG
57 #include <random> // for uniform_int_distrib...
58 #endif
59 #endif
60 #include "Parameter.hpp" // for Parameter, OPT_test...
61 #include "cpu_stats.hpp" // for PrintVirtualDataMem...
62 #include "cpu_time.hpp" // for START_TIME, STOP_TIME
63 #include "custom_set.hpp"
64 #include "dbgPrintHelper.hpp" // for DEBUG_LEVEL_VERY_PE...
65 #include "design_flow_aux_step.hpp" // for AuxDesignFlowStep
66 #include "design_flow_graph.hpp" // for DesignFlowGraph
67 #include "design_flow_step.hpp" // for DesignFlowStep_Status
68 #include "design_flow_step_factory.hpp" // for DesignFlowStepRef
69 #include "exceptions.hpp" // for THROW_UNREACHABLE
70 #include "string_manipulation.hpp" // for STR GET_CLASS
71 #include <utility> // for pair
72 
74  : design_flow_graph(_design_flow_graph)
75 {
76 }
77 
79 {
80  const DesignFlowStepInfoConstRef x_info = design_flow_graph->CGetDesignFlowStepInfo(x);
81  const DesignFlowStepInfoConstRef y_info = design_flow_graph->CGetDesignFlowStepInfo(y);
82  const bool x_composed = x_info->design_flow_step->IsComposed();
83  const bool y_composed = y_info->design_flow_step->IsComposed();
84  const bool x_unnecessary =
85  x_info->status == DesignFlowStep_Status::SKIPPED or x_info->status == DesignFlowStep_Status::UNNECESSARY;
86  const bool y_unnecessary =
87  y_info->status == DesignFlowStep_Status::SKIPPED or y_info->status == DesignFlowStep_Status::UNNECESSARY;
88  if(x_composed and not y_composed)
89  {
90  return true;
91  }
92  else if(not x_composed and y_composed)
93  {
94  return false;
95  }
96  else if(x_unnecessary and not y_unnecessary)
97  {
98  return false;
99  }
100  else if(not x_unnecessary and y_unnecessary)
101  {
102  return true;
103  }
104  else
105  {
106 #if HAVE_UNORDERED
107  return x < y;
108 #else
109  return x_info->design_flow_step->GetName() < y_info->design_flow_step->GetName();
110 #endif
111  }
112 }
113 
115  : design_flow_graphs_collection(new DesignFlowGraphsCollection(_parameters)),
116  design_flow_graph(new DesignFlowGraph(design_flow_graphs_collection, DesignFlowGraph::DEPENDENCE_SELECTOR |
117  DesignFlowGraph::PRECEDENCE_SELECTOR |
118  DesignFlowGraph::AUX_SELECTOR)),
119  feedback_design_flow_graph(
120  new DesignFlowGraph(design_flow_graphs_collection,
121  DesignFlowGraph::DEPENDENCE_SELECTOR | DesignFlowGraph::PRECEDENCE_SELECTOR |
122  DesignFlowGraph::AUX_SELECTOR | DesignFlowGraph::DEPENDENCE_FEEDBACK_SELECTOR)),
124  parameters(_parameters),
125  output_level(_parameters->getOption<int>(OPT_output_level))
126 {
127  debug_level = parameters->get_class_debug_level(GET_CLASS(*this));
128  const DesignFlowGraphInfoRef design_flow_graph_info = design_flow_graph->GetDesignFlowGraphInfo();
129  null_deleter nullDel;
130  design_flow_graph_info->entry = design_flow_graphs_collection->AddDesignFlowStep(
132  new AuxDesignFlowStep("Entry", DESIGN_FLOW_ENTRY, DesignFlowManagerConstRef(this, nullDel), parameters)),
133  false);
134 #ifndef NDEBUG
135  if(debug_level >= DEBUG_LEVEL_PARANOIC or parameters->IsParameter("profile_steps"))
136  {
137  step_names[design_flow_graph_info->entry] = "Entry";
138  }
139 #endif
140  const DesignFlowStepInfoRef entry_info = design_flow_graph->GetDesignFlowStepInfo(design_flow_graph_info->entry);
141  entry_info->status = DesignFlowStep_Status::EMPTY;
142  design_flow_graph_info->exit = design_flow_graphs_collection->AddDesignFlowStep(
144  new AuxDesignFlowStep("Exit", DESIGN_FLOW_EXIT, DesignFlowManagerConstRef(this, nullDel), parameters)),
145  false);
146 #ifndef NDEBUG
147  if(debug_level >= DEBUG_LEVEL_PARANOIC or parameters->IsParameter("profile_steps"))
148  {
149  step_names[design_flow_graph_info->exit] = "Exit";
150  }
151 #endif
152 }
153 
155 
157 
159 {
160  DesignFlowStepSet steps;
161  steps.insert(step);
162  RecursivelyAddSteps(steps, false);
163 }
164 
166 {
167  RecursivelyAddSteps(steps, false);
168 }
169 
170 void DesignFlowManager::RecursivelyAddSteps(const DesignFlowStepSet& steps, const bool unnecessary)
171 {
172  static size_t temp_counter = 0;
173  const DesignFlowGraphInfoRef design_flow_graph_info = design_flow_graph->GetDesignFlowGraphInfo();
174  for(const auto& design_flow_step : steps)
175  {
176  const std::string signature = design_flow_step->GetSignature();
178  "-->Adding design flow step " + design_flow_step->GetName() + " - Signature " + signature);
179 
181  vertex step_vertex = GetDesignFlowStep(signature);
183  if(step_vertex)
184  {
185  if(unnecessary)
186  {
189  INDENT_DBG_MEX(DEBUG_LEVEL_PARANOIC, debug_level, "<--This step already exist (unnecessary)");
190  continue;
191  }
192  else
193  {
194  const DesignFlowStepInfoRef design_flow_step_info = design_flow_graph->GetDesignFlowStepInfo(step_vertex);
195  if(design_flow_step_info->status == DesignFlowStep_Status::UNNECESSARY)
196  {
201  bool it_belongs = possibly_ready.find(step_vertex) != possibly_ready.end();
202  possibly_ready.erase(step_vertex);
203  if(it_belongs)
204  {
205  design_flow_step_info->status = DesignFlowStep_Status::UNEXECUTED;
206  possibly_ready.insert(step_vertex);
207  }
208  else
209  {
210  design_flow_step_info->status = DesignFlowStep_Status::UNEXECUTED;
211  }
213  "---This step already exist but was unnecessary. Now it becomes necessary");
214  }
215  else
216  {
217  THROW_ASSERT(design_flow_step_info->status != DesignFlowStep_Status::SKIPPED,
218  "Switching to necessary " + design_flow_step_info->design_flow_step->GetName() +
219  " which has already skipped");
221  INDENT_DBG_MEX(DEBUG_LEVEL_PARANOIC, debug_level, "<--This step already exist");
222  continue;
223  }
224  }
225  }
226  else
227  {
228  INDENT_DBG_MEX(DEBUG_LEVEL_PARANOIC, debug_level, "---This step does not exist");
229  step_vertex = design_flow_graphs_collection->AddDesignFlowStep(design_flow_step, unnecessary);
230 #ifndef NDEBUG
231  if(debug_level >= DEBUG_LEVEL_PARANOIC or parameters->IsParameter("profile_steps"))
232  {
233  step_names[step_vertex] = design_flow_step->GetName();
234  }
235 #endif
236  }
237 
238  DesignFlowStepSet relationships;
239 
241  INDENT_DBG_MEX(DEBUG_LEVEL_PARANOIC, debug_level, "-->Adding dependencies of " + design_flow_step->GetName());
242  design_flow_step->ComputeRelationships(relationships, DesignFlowStep::DEPENDENCE_RELATIONSHIP);
243  RecursivelyAddSteps(relationships, unnecessary);
244  for(const auto& relationship : relationships)
245  {
246  const std::string relationship_signature = relationship->GetSignature();
247  vertex relationship_vertex = GetDesignFlowStep(relationship_signature);
248  design_flow_graphs_collection->AddDesignFlowDependence(relationship_vertex, step_vertex,
250 #ifndef NDEBUG
251  if(parameters->IsParameter("DebugDFM") and parameters->GetParameter<bool>("DebugDFM"))
252  {
253  try
254  {
255  std::list<vertex> vertices;
256  design_flow_graph->TopologicalSort(vertices);
257  }
258  catch(...)
259  {
260  WriteLoopDot();
261  feedback_design_flow_graph->WriteDot("Design_Flow_Error");
262  THROW_UNREACHABLE("Design flow graph is not anymore acyclic");
263  }
264  }
265 #endif
266  }
267  INDENT_DBG_MEX(DEBUG_LEVEL_PARANOIC, debug_level, "<--Added dependencies of " + design_flow_step->GetName());
268 
270  INDENT_DBG_MEX(DEBUG_LEVEL_PARANOIC, debug_level, "-->Adding precedences of " + design_flow_step->GetName());
271  relationships.clear();
272  design_flow_step->ComputeRelationships(relationships, DesignFlowStep::PRECEDENCE_RELATIONSHIP);
273  RecursivelyAddSteps(relationships, true);
274  for(const auto& relationship : relationships)
275  {
276  const std::string relationship_signature = relationship->GetSignature();
277  vertex relationship_vertex = GetDesignFlowStep(relationship_signature);
278  design_flow_graphs_collection->AddDesignFlowDependence(relationship_vertex, step_vertex,
280 #ifndef NDEBUG
281  if(parameters->IsParameter("DebugDFM") and parameters->GetParameter<bool>("DebugDFM"))
282  {
283  try
284  {
285  std::list<vertex> vertices;
286  design_flow_graph->TopologicalSort(vertices);
287  }
288  catch(...)
289  {
290  WriteLoopDot();
291  feedback_design_flow_graph->WriteDot("Design_Flow_Error");
292  THROW_UNREACHABLE("Design flow graph is not anymore acyclic");
293  }
294  }
295 #endif
296  }
297  INDENT_DBG_MEX(DEBUG_LEVEL_PARANOIC, debug_level, "<--Added precedences of " + design_flow_step->GetName());
298 
300  bool current_ready = true;
301  InEdgeIterator ie, ie_end;
302  for(boost::tie(ie, ie_end) = boost::in_edges(step_vertex, *design_flow_graph); ie != ie_end; ie++)
303  {
304  vertex pre_dependence_vertex = boost::source(*ie, *design_flow_graph);
305  const DesignFlowStepInfoRef pre_info = design_flow_graph->GetDesignFlowStepInfo(pre_dependence_vertex);
306  switch(pre_info->status)
307  {
313  {
314  break;
315  }
318  {
319  current_ready = false;
320  break;
321  }
323  {
324  THROW_UNREACHABLE("Step with nonexitent status");
325  break;
326  }
327  default:
328  {
329  THROW_UNREACHABLE("");
330  }
331  }
332  }
333  if(current_ready)
334  {
336  "---Adding " + design_flow_step->GetName() + " to list of ready steps");
337  possibly_ready.insert(step_vertex);
338  }
340  {
341  feedback_design_flow_graph->WriteDot("Design_Flow_" + STR(step_counter) + "_" + STR(temp_counter));
342  temp_counter++;
343  }
344  if(boost::in_degree(step_vertex, *design_flow_graph) == 0)
345  {
346  design_flow_graphs_collection->AddDesignFlowDependence(design_flow_graph_info->entry, step_vertex,
348  }
349  for(boost::tie(ie, ie_end) = boost::in_edges(step_vertex, *design_flow_graph); ie != ie_end; ie++)
350  {
351  const auto source = boost::source(*ie, *design_flow_graph);
352  if(design_flow_graph->ExistsEdge(source, design_flow_graph_info->exit))
353  {
354  design_flow_graphs_collection->RemoveSelector(source, design_flow_graph_info->exit,
356  }
357  }
358  if(boost::out_degree(step_vertex, *design_flow_graph) == 0)
359  {
360  design_flow_graphs_collection->AddDesignFlowDependence(step_vertex, design_flow_graph_info->exit,
362  }
364  "<--Added design flow step " + design_flow_step->GetName() + " - Signature " + signature);
365  }
366 }
367 
369 {
370  return design_flow_graph;
371 }
372 
374 {
375 #if !HAVE_UNORDERED
376 #ifndef NDEBUG
378  "---Seed for design flow manager: " +
379  STR(parameters->isOption(OPT_test_single_non_deterministic_flow) ?
380  parameters->getOption<size_t>(OPT_test_single_non_deterministic_flow) :
381  0));
382  auto generator = std::bind(std::uniform_int_distribution<size_t>(0, 10000),
383  std::mt19937(parameters->isOption(OPT_test_single_non_deterministic_flow) ?
384  parameters->getOption<size_t>(OPT_test_single_non_deterministic_flow) :
385  0));
386 #endif
387 #endif
388 
389  INDENT_DBG_MEX(DEBUG_LEVEL_PARANOIC, debug_level, "-->Started execution of design flow");
391  {
392  INDENT_DBG_MEX(DEBUG_LEVEL_PARANOIC, debug_level, "---Writing initial design flow graph");
393  feedback_design_flow_graph->WriteDot("Design_Flow_" + STR(step_counter));
394  }
395  size_t executed_passes = 0;
396  size_t skipped_passes = 0;
397  size_t graph_changes = 0;
398  long design_flow_manager_time = 0;
399  while(possibly_ready.size())
400  {
401  const size_t initial_number_vertices = boost::num_vertices(*feedback_design_flow_graph);
402  const size_t initial_number_edges = boost::num_vertices(*feedback_design_flow_graph);
403  long before_time = 0;
404  if(parameters->IsParameter("dfm_statistics"))
405  {
406  START_TIME(before_time);
407  }
408  step_counter++;
409  INDENT_DBG_MEX(DEBUG_LEVEL_PARANOIC, debug_level, "-->Ready steps are");
410 #ifndef NDEBUG
411  for(const auto ready_step : possibly_ready)
412  {
414  "---" + design_flow_graph->CGetDesignFlowStepInfo(ready_step)->design_flow_step->GetName());
415  }
416 #endif
418  const vertex next = [&]() -> vertex {
419 #if !HAVE_UNORDERED
420 #ifndef NDEBUG
421  if(parameters->isOption(OPT_test_single_non_deterministic_flow))
422  {
423  const size_t random = generator();
424  const size_t offset = random % possibly_ready.size();
426  "---Random is " + STR(random) + " - Offset is " + STR(offset) + " (Size is " +
427  STR(possibly_ready.size()) + ")");
428  auto begin = possibly_ready.begin();
429  std::advance(begin, offset);
430  return *begin;
431  }
432 #endif
433 #endif
434  return *(possibly_ready.begin());
435  }();
436 #if HAVE_ASSERTS
437  const auto erased_elements =
438 #endif
439  possibly_ready.erase(next);
440  const DesignFlowStepInfoRef design_flow_step_info = design_flow_graph->GetDesignFlowStepInfo(next);
441  const DesignFlowStepRef step = design_flow_step_info->design_flow_step;
443  "-->Beginning iteration number " + STR(step_counter) + " - Considering step " + step->GetName());
444  INDENT_DBG_MEX(DEBUG_LEVEL_PARANOIC, debug_level, "-->Other ready steps are");
445 #ifndef NDEBUG
446  for(const auto ready_step : possibly_ready)
447  {
449  "---" + design_flow_graph->CGetDesignFlowStepInfo(ready_step)->design_flow_step->GetName());
450  }
451 #endif
453  THROW_ASSERT(erased_elements == 1, "Number of erased elements is " + STR(erased_elements));
454 
457  INDENT_DBG_MEX(DEBUG_LEVEL_PARANOIC, debug_level, "-->Recomputing dependences");
458  DesignFlowStepSet pre_dependence_steps, pre_precedence_steps;
459  step->ComputeRelationships(pre_dependence_steps, DesignFlowStep::DEPENDENCE_RELATIONSHIP);
460  RecursivelyAddSteps(pre_dependence_steps, design_flow_step_info->status == DesignFlowStep_Status::UNNECESSARY);
461  INDENT_DBG_MEX(DEBUG_LEVEL_PARANOIC, debug_level, "<--Recomputed dependences");
462  INDENT_DBG_MEX(DEBUG_LEVEL_PARANOIC, debug_level, "-->Recomputing precedences");
463  step->ComputeRelationships(pre_precedence_steps, DesignFlowStep::PRECEDENCE_RELATIONSHIP);
464  RecursivelyAddSteps(pre_precedence_steps, true);
465  INDENT_DBG_MEX(DEBUG_LEVEL_PARANOIC, debug_level, "<--Recomputed precedences");
466  bool current_ready = true;
467  DesignFlowStepSet::const_iterator pre_dependence_step, pre_dependence_step_end = pre_dependence_steps.end();
468  for(pre_dependence_step = pre_dependence_steps.begin(); pre_dependence_step != pre_dependence_step_end;
469  ++pre_dependence_step)
470  {
471  const vertex pre_dependence_vertex =
472  design_flow_graph->GetDesignFlowStep((*pre_dependence_step)->GetSignature());
473  design_flow_graphs_collection->AddDesignFlowDependence(pre_dependence_vertex, next,
475  const DesignFlowStepInfoRef pre_info = design_flow_graph->GetDesignFlowStepInfo(pre_dependence_vertex);
476  switch(pre_info->status)
477  {
483  {
484  break;
485  }
488  {
489  current_ready = false;
490  break;
491  }
493  {
494  THROW_UNREACHABLE("Step with nonexitent status");
495  break;
496  }
497  default:
498  {
499  THROW_UNREACHABLE("");
500  }
501  }
502  }
504  for(const auto& pre_precedence_step : pre_precedence_steps)
505  {
506  const vertex pre_precedence_vertex =
507  design_flow_graph->GetDesignFlowStep((pre_precedence_step)->GetSignature());
508  design_flow_graphs_collection->AddDesignFlowDependence(pre_precedence_vertex, next,
510  const DesignFlowStepInfoRef pre_info = design_flow_graph->GetDesignFlowStepInfo(pre_precedence_vertex);
511  switch(pre_info->status)
512  {
518  {
519  break;
520  }
523  {
524  current_ready = false;
525  break;
526  }
528  {
529  THROW_UNREACHABLE("Step with nonexitent status");
530  break;
531  }
532  default:
533  {
534  THROW_UNREACHABLE("");
535  }
536  }
537  }
538  if(not current_ready)
539  {
541  {
542  feedback_design_flow_graph->WriteDot("Design_Flow_" + STR(step_counter));
543  INDENT_DBG_MEX(DEBUG_LEVEL_PARANOIC, debug_level, "---Writing Design_Flow_" + STR(step_counter));
544  }
545 #ifndef NDEBUG
547  {
549  VertexIterator temp_step, temp_step_end;
550  for(boost::tie(temp_step, temp_step_end) = boost::vertices(*design_flow_graph); temp_step != temp_step_end;
551  temp_step++)
552  {
553  const DesignFlowStepInfoConstRef temp_design_flow_step_info =
554  design_flow_graph->CGetDesignFlowStepInfo(*temp_step);
555  vertex_history[step_counter][*temp_step] = temp_design_flow_step_info->status;
556  }
557  EdgeIterator edge, edge_end;
558  for(boost::tie(edge, edge_end) = boost::edges(*design_flow_graph); edge != edge_end; edge++)
559  {
560  edge_history[step_counter][*edge] = design_flow_graph->GetSelector(*edge);
561  }
562  }
563 #endif
564  INDENT_DBG_MEX(DEBUG_LEVEL_PARANOIC, debug_level, "<--Ended iteration number " + STR(step_counter));
565  const size_t final_number_vertices = boost::num_vertices(*feedback_design_flow_graph);
566  const size_t final_number_edges = boost::num_vertices(*feedback_design_flow_graph);
567  if(final_number_vertices > initial_number_vertices or final_number_edges > initial_number_edges)
568  {
569  graph_changes++;
570  }
571  continue;
572  }
573  if(parameters->IsParameter("dfm_statistics"))
574  {
575  STOP_TIME(before_time);
576  design_flow_manager_time += before_time;
577  }
578  if(design_flow_step_info->status == DesignFlowStep_Status::UNNECESSARY)
579  {
581  "---Skipping execution of " + step->GetName() + " since unnecessary");
582  design_flow_step_info->status = DesignFlowStep_Status::SKIPPED;
583  }
584  else if(step->HasToBeExecuted())
585  {
586 #ifndef NDEBUG
587  size_t indentation_before = indentation;
588 #endif
589  INDENT_OUT_MEX(OUTPUT_LEVEL_VERY_PEDANTIC, output_level, "-->Starting execution of " + step->GetName());
590  long step_execution_time = 0;
591  if(OUTPUT_LEVEL_VERY_PEDANTIC <= output_level || parameters->IsParameter("profile_steps"))
592  {
593  START_TIME(step_execution_time);
594  }
595  step->Initialize();
596  if(step->CGetDebugLevel() >= DEBUG_LEVEL_VERY_PEDANTIC)
597  {
598  step->PrintInitialIR();
599  }
600  design_flow_step_info->status = step->Exec();
601  executed_passes++;
602  if(step->CGetDebugLevel() >= DEBUG_LEVEL_VERY_PEDANTIC)
603  {
604  step->PrintFinalIR();
605  }
606  if(OUTPUT_LEVEL_VERY_PEDANTIC <= output_level || parameters->IsParameter("profile_steps"))
607  {
608  STOP_TIME(step_execution_time);
609  }
610  const std::string memory_usage =
611 #ifndef NDEBUG
612  std::string(" - Virtual Memory: ") + PrintVirtualDataMemoryUsage()
613 #else
614  ""
615 #endif
616  ;
617 #ifndef NDEBUG
618  if(parameters->IsParameter("profile_steps"))
619  {
620  accumulated_execution_time[next] += step_execution_time;
621  if(design_flow_step_info->status == DesignFlowStep_Status::SUCCESS)
622  {
623  success_executions[next]++;
624  }
625  else if(design_flow_step_info->status == DesignFlowStep_Status::UNCHANGED)
626  {
627  unchanged_executions[next]++;
628  }
629  }
630 #endif
632  "<--Ended execution of " + step->GetName() +
633  (design_flow_step_info->status == DesignFlowStep_Status::UNCHANGED ?
634  ":=" :
635  (design_flow_step_info->status == DesignFlowStep_Status::SUCCESS ? ":+" : "")) +
636  " in " + print_cpu_time(step_execution_time) + " seconds" + memory_usage);
637 #ifndef NDEBUG
638  THROW_ASSERT(indentation_before == indentation, "Not closed indentation");
639 #endif
640  }
641  else
642  {
643  INDENT_OUT_MEX(DEBUG_LEVEL_PARANOIC, debug_level, "---Skipping execution of " + step->GetName());
644  design_flow_step_info->status = DesignFlowStep_Status::UNCHANGED;
645  skipped_passes++;
646 #ifndef NDEBUG
647  if(parameters->IsParameter("profile_steps"))
648  {
649  skipped_executions[next]++;
650  }
651 #endif
652  }
653  long after_time = 0;
654  if(parameters->IsParameter("dfm_statistics"))
655  {
656  START_TIME(after_time);
657  }
658  bool invalidations = false;
659  if(not parameters->IsParameter("disable-invalidations"))
660  {
662  INDENT_DBG_MEX(DEBUG_LEVEL_PARANOIC, debug_level, "-->Adding post-dependencies of " + step->GetName());
663  DesignFlowStepSet relationships;
664  step->ComputeRelationships(relationships, DesignFlowStep::INVALIDATION_RELATIONSHIP);
666  invalidations = not relationships.empty();
667  DesignFlowStepSet::const_iterator relationship, relationship_end = relationships.end();
668  for(relationship = relationships.begin(); relationship != relationship_end; ++relationship)
669  {
670  const std::string relationship_signature = (*relationship)->GetSignature();
671  vertex relationship_vertex = GetDesignFlowStep(relationship_signature);
672  THROW_ASSERT(relationship_vertex, "Missing vertex " + relationship_signature);
673  if(design_flow_graph->IsReachable(relationship_vertex, next))
674  {
675  design_flow_graphs_collection->AddDesignFlowDependence(next, relationship_vertex,
677  DeExecute(relationship_vertex, true);
678  }
679  else
680  {
681  feedback_design_flow_graph->WriteDot("Design_Flow_Error");
683  "Invalidating " +
684  design_flow_graph->CGetDesignFlowStepInfo(relationship_vertex)->design_flow_step->GetName() +
685  " which is not before the current one");
686  }
687  }
688  INDENT_DBG_MEX(DEBUG_LEVEL_PARANOIC, debug_level, "<--Added post-dependencies of " + step->GetName());
689  }
690  OutEdgeIterator oe, oe_end;
691  INDENT_DBG_MEX(DEBUG_LEVEL_PARANOIC, debug_level, "-->Starting checking of new ready steps");
692  for(boost::tie(oe, oe_end) = boost::out_edges(next, *design_flow_graph); oe != oe_end; oe++)
693  {
695  DesignFlowStepInfoRef target_info = design_flow_graph->GetDesignFlowStepInfo(target);
696  switch(target_info->status)
697  {
703  {
706  continue;
707  }
710  {
711  break;
712  }
714  {
715  THROW_UNREACHABLE("Step with nonexitent status");
716  break;
717  }
718  default:
719  {
720  THROW_UNREACHABLE("");
721  }
722  }
724  "-->Examining successor " +
725  design_flow_graph->GetDesignFlowStepInfo(target)->design_flow_step->GetName());
726  bool target_ready = true;
727  InEdgeIterator ie, ie_end;
728  for(boost::tie(ie, ie_end) = boost::in_edges(target, *design_flow_graph); ie != ie_end; ie++)
729  {
730  const vertex source = boost::source(*ie, *design_flow_graph);
731  const DesignFlowStepInfoRef source_info = design_flow_graph->GetDesignFlowStepInfo(source);
733  "-->Examining predecessor " + source_info->design_flow_step->GetName());
734  switch(source_info->status)
735  {
741  {
742  break;
743  }
745  {
746  target_ready = false;
747  break;
748  }
750  {
751  target_ready = false;
752  break;
753  }
755  {
756  THROW_UNREACHABLE("Step with nonexitent status");
757  break;
758  }
759  default:
760  {
761  THROW_UNREACHABLE("");
762  }
763  }
764  if(not target_ready)
765  {
767  break;
768  }
770  }
771  if(target_ready)
772  {
774  "---Adding " +
775  design_flow_graph->CGetDesignFlowStepInfo(target)->design_flow_step->GetName() +
776  " to list of ready steps");
777  possibly_ready.insert(target);
778  }
780  }
781  INDENT_DBG_MEX(DEBUG_LEVEL_PARANOIC, debug_level, "<--Checked new ready steps");
782  CustomOrderedSet<EdgeDescriptor> to_be_removeds;
783  InEdgeIterator ie, ie_end;
784  for(boost::tie(ie, ie_end) =
785  boost::in_edges(design_flow_graph->CGetDesignFlowGraphInfo()->exit, *design_flow_graph);
786  ie != ie_end; ie++)
787  {
788  const auto source = boost::source(*ie, *design_flow_graph);
789  if(boost::out_degree(source, *design_flow_graph) > 1)
790  {
791  to_be_removeds.insert(*ie);
792  }
793  }
794  for(const auto& to_be_removed : to_be_removeds)
795  {
796  design_flow_graphs_collection->RemoveSelector(to_be_removed, DesignFlowGraph::AUX_SELECTOR);
797  }
799  {
800  INDENT_DBG_MEX(DEBUG_LEVEL_PARANOIC, debug_level, "---Writing Design_Flow_" + STR(step_counter));
801  feedback_design_flow_graph->WriteDot("Design_Flow_" + STR(step_counter));
802 
803 #ifndef NDEBUG
804  VertexIterator temp_step, temp_step_end;
806  for(boost::tie(temp_step, temp_step_end) = boost::vertices(*design_flow_graph); temp_step != temp_step_end;
807  temp_step++)
808  {
809  const DesignFlowStepInfoConstRef temp_design_flow_step_info =
810  design_flow_graph->CGetDesignFlowStepInfo(*temp_step);
811  vertex_history[step_counter][*temp_step] = temp_design_flow_step_info->status;
812  }
813  EdgeIterator edge, edge_end;
814  for(boost::tie(edge, edge_end) = boost::edges(*design_flow_graph); edge != edge_end; edge++)
815  {
816  edge_history[step_counter][*edge] = design_flow_graph->GetSelector(*edge);
817  }
818 #endif
819  }
820  if(parameters->IsParameter("dfm_statistics"))
821  {
822  STOP_TIME(after_time);
823  design_flow_manager_time += after_time;
824  }
826  "<--Ended iteration number " + STR(step_counter) + " - Step " + step->GetName());
827  const size_t final_number_vertices = boost::num_vertices(*feedback_design_flow_graph);
828  const size_t final_number_edges = boost::num_vertices(*feedback_design_flow_graph);
829  if(parameters->IsParameter("dfm_statistics"))
830  {
831  if(final_number_vertices > initial_number_vertices or final_number_edges > initial_number_edges or
832  invalidations)
833  {
834  graph_changes++;
835  }
836  if(parameters->GetParameter<size_t>("dfm_statistics") > 1)
837  {
838  VertexIterator v_stat, v_stat_end;
839  size_t executed_vertices = 0;
840  static size_t previous_executed_vertices = 0;
841  for(boost::tie(v_stat, v_stat_end) = boost::vertices(*design_flow_graph); v_stat != v_stat_end; v_stat++)
842  {
843  const DesignFlowStepInfoRef local_design_flow_step_info =
844  design_flow_graph->GetDesignFlowStepInfo(*v_stat);
845  switch(local_design_flow_step_info->status)
846  {
852  {
853  executed_vertices++;
854  break;
855  }
858  {
859  break;
860  }
862  {
863  THROW_UNREACHABLE("Step with nonexitent status");
864  break;
865  }
866  default:
867  {
868  THROW_UNREACHABLE("");
869  }
870  }
871  }
872  if(previous_executed_vertices > executed_vertices)
873  {
875  "dfm_statistics - number of invalidated vertices by " + step->GetName() + ": " +
876  STR(previous_executed_vertices - executed_vertices));
877  }
879  "dfm_statistics - number of vertices at the end of iteration " + STR(step_counter) + ": " +
880  STR(executed_vertices) + " / " + STR(final_number_vertices));
882  "dfm_statistics - number of edges at the end of iteration " + STR(step_counter) + ": " +
883  STR(final_number_edges));
884  previous_executed_vertices = executed_vertices;
885  }
886  }
887  }
888 #ifndef NDEBUG
890  {
891  for(size_t writing_step_counter = 0; writing_step_counter < step_counter; writing_step_counter++)
892  {
893  if(edge_history.find(writing_step_counter) != edge_history.end())
894  {
896  "-->Writing Design_Flow_History_" + STR(writing_step_counter));
897  feedback_design_flow_graph->WriteDot("Design_Flow_History_" + STR(writing_step_counter), vertex_history,
898  edge_history, step_names, writing_step_counter);
900  "<--Written Design_Flow_History_" + STR(writing_step_counter));
901  }
902  }
903  }
904 #endif
905  if(design_flow_graph->CGetDesignFlowStepInfo(design_flow_graph->CGetDesignFlowGraphInfo()->exit)->status !=
907  {
908 #ifndef NDEBUG
909  WriteLoopDot();
910 #endif
911  feedback_design_flow_graph->WriteDot("Design_Flow_Error");
912  THROW_UNREACHABLE("Design flow didn't end");
913  }
914  if(parameters->IsParameter("dfm_statistics"))
915  {
917  "dfm_statistics - number of vertices in final graph: " +
918  STR(boost::num_vertices(*design_flow_graph)));
920  "dfm_statistics - number of edges in final graph: " + STR(boost::num_edges(*design_flow_graph)));
922  "dfm_statistics - number of executed passes: " + STR(executed_passes));
924  "dfm_statistics - number of skipped passes: " + STR(skipped_passes));
926  "dfm_statistics - number of graph changes: " + STR(graph_changes));
928  "dfm_statistics - design flow manager time: " + print_cpu_time(design_flow_manager_time) +
929  " seconds");
930  }
931 #ifndef NDEBUG
932  if(parameters->IsParameter("profile_steps"))
933  {
934  INDENT_OUT_MEX(OUTPUT_LEVEL_NONE, output_level, "-->Steps execution statistics");
935  for(const auto step : accumulated_execution_time)
936  {
938  "---" + step_names.at(step.first) + ": " + print_cpu_time(step.second) +
939  " seconds - Successes: " + STR(success_executions[step.first]) +
940  " - Unchanged: " + STR(unchanged_executions[step.first]) +
941  " - Skipped: " + STR(skipped_executions[step.first]));
942  }
944  }
945 #endif
946  INDENT_DBG_MEX(DEBUG_LEVEL_PARANOIC, debug_level, "---Total number of iterations: " + STR(step_counter));
947  INDENT_DBG_MEX(DEBUG_LEVEL_PARANOIC, debug_level, "<--Ended execution of design flow");
948 }
949 
950 vertex DesignFlowManager::GetDesignFlowStep(const std::string& signature) const
951 {
952  return design_flow_graphs_collection->GetDesignFlowStep(signature);
953 }
954 
955 DesignFlowStepFactoryConstRef DesignFlowManager::CGetDesignFlowStepFactory(const std::string& prefix) const
956 {
958  "No factory to create steps with prefix " + prefix + " found");
959  return design_flow_step_factories.find(prefix)->second;
960 }
961 
962 void DesignFlowManager::RegisterFactory(const DesignFlowStepFactoryConstRef factory)
963 {
964  design_flow_step_factories[factory->GetPrefix()] = factory;
965 }
966 
967 void DesignFlowManager::DeExecute(const vertex starting_vertex, const bool force_execution)
968 {
970  const DesignFlowStepInfoRef design_flow_step_info = design_flow_graph->GetDesignFlowStepInfo(starting_vertex);
972  "---DeExecuting " + design_flow_step_info->design_flow_step->GetName());
973  switch(design_flow_step_info->status)
974  {
976  {
977  design_flow_step_info->status = DesignFlowStep_Status::UNEXECUTED;
978  break;
979  }
983  {
984  design_flow_step_info->status = DesignFlowStep_Status::UNEXECUTED;
985  break;
986  }
988  {
989  if(force_execution)
990  {
991  design_flow_step_info->status = DesignFlowStep_Status::UNEXECUTED;
992  }
993  else
994  {
995  design_flow_step_info->status = DesignFlowStep_Status::UNNECESSARY;
996  }
997  break;
998  }
1001  {
1002  break;
1003  }
1005  {
1006  THROW_UNREACHABLE("Step with nonexitent status");
1007  break;
1008  }
1009  default:
1010  {
1011  THROW_UNREACHABLE("");
1012  }
1013  }
1014 
1016  bool current_ready = true;
1017  InEdgeIterator ie, ie_end;
1018  for(boost::tie(ie, ie_end) = boost::in_edges(starting_vertex, *design_flow_graph); ie != ie_end; ie++)
1019  {
1020  vertex pre_dependence_vertex = boost::source(*ie, *design_flow_graph);
1021  const DesignFlowStepInfoRef pre_info = design_flow_graph->GetDesignFlowStepInfo(pre_dependence_vertex);
1022  switch(pre_info->status)
1023  {
1029  {
1030  break;
1031  }
1034  {
1035  current_ready = false;
1036  break;
1037  }
1039  {
1040  THROW_UNREACHABLE("Step with nonexitent status");
1041  break;
1042  }
1043  default:
1044  {
1045  THROW_UNREACHABLE("");
1046  }
1047  }
1048  }
1049  if(current_ready)
1050  {
1051  possibly_ready.insert(starting_vertex);
1052  }
1053 
1055  OutEdgeIterator oe, oe_end;
1056  for(boost::tie(oe, oe_end) = boost::out_edges(starting_vertex, *design_flow_graph); oe != oe_end; oe++)
1057  {
1059  const DesignFlowStepInfoRef target_info = design_flow_graph->GetDesignFlowStepInfo(target);
1060  switch(target_info->status)
1061  {
1067  {
1068  DeExecute(target, false);
1069  break;
1070  }
1073  {
1074  break;
1075  }
1077  {
1078  THROW_UNREACHABLE("Step with nonexitent status");
1079  break;
1080  }
1081  default:
1082  {
1083  THROW_UNREACHABLE("");
1084  }
1085  }
1086  }
1087 }
1088 
1089 DesignFlowStep_Status DesignFlowManager::GetStatus(const std::string& signature) const
1090 {
1091  const vertex step = GetDesignFlowStep(signature);
1092  if(step == NULL_VERTEX)
1093  {
1095  }
1096  else
1097  {
1098  return design_flow_graph->CGetDesignFlowStepInfo(step)->status;
1099  }
1100 }
1101 
1102 const DesignFlowStepRef DesignFlowManager::CreateFlowStep(const std::string& signature) const
1103 {
1104  THROW_ASSERT(signature.find("::") != std::string::npos, signature);
1105  const auto prefix = signature.substr(0, signature.find("::"));
1106  return CGetDesignFlowStepFactory(prefix)->CreateFlowStep(signature);
1107 }
1108 
1109 #ifndef NDEBUG
1111 {
1112  std::map<size_t, UnorderedSetStdStable<vertex>> sccs;
1113  feedback_design_flow_graph->GetStronglyConnectedComponents(sccs);
1114  for(const auto& id_scc : sccs)
1115  {
1116  const auto& scc_id = id_scc.first;
1117  const auto& scc = id_scc.second;
1118  if(scc.size() > 1)
1119  {
1120  CustomUnorderedSet<vertex> vertices;
1121  for(const auto v : scc)
1122  {
1123  vertices.insert(v);
1124  }
1128  vertices)
1129  .WriteDot("DesignFlowLoop_" + STR(scc_id) + ".dot");
1130  }
1131  }
1132 }
1133 #endif
void DeExecute(const vertex starting_vertex, bool force_execution)
Recursively remove executed flag starting from a vertex.
const DesignFlowStepRef CreateFlowStep(const std::string &signature) const
Create a design flow step.
The key comparison functor for design flow step; it puts necessary steps before unnecessary ones; in ...
void WriteDot(const std::string &file_name, const int detail_level=0) const
Write this graph in dot format.
#define DEBUG_LEVEL_VERY_PEDANTIC
extremely verbose debugging print is performed.
void RecursivelyAddSteps(const DesignFlowStepSet &steps, const bool unnecessary)
Recursively add steps and corresponding dependencies to the design flow.
Step does not exits.
#define INDENT_DBG_MEX(dbgLevel, curDbgLevel, mex)
We are producing a debug version of the program, so the message is printed;.
void AddStep(const DesignFlowStepRef step)
Add step and corresponding dependencies to the design flow.
boost::graph_traits< graph >::out_edge_iterator OutEdgeIterator
out_edge_iterator definition.
Definition: graph.hpp:1312
File containing functions and utilities to support the printing of debug messagges.
const DesignFlowGraphRef design_flow_graph
The graph of steps composing the design flow.
void AddSteps(const DesignFlowStepSet &steps)
Add steps and corresponding dependencies to the design flow.
Class for describing auxiliary steps in design flow.
#define OUTPUT_LEVEL_NONE
no output print is performed.
Step successfully executed.
void RegisterFactory(const DesignFlowStepFactoryConstRef factory)
Register a design flow step factory.
string target
Definition: lenet_tvm.py:16
DesignFlowStepNecessitySorter(const DesignFlowGraphConstRef _design_flow_graph)
Constructor.
#define GET_CLASS(obj)
Macro returning the actual type of an object.
const DesignFlowGraphConstRef design_flow_graph
The design flow graph.
CustomMap< size_t, CustomUnorderedMapStable< EdgeDescriptor, int > > edge_history
This structure stores "history of design flow graph manager - edges" First key is the iteration Secon...
virtual ~DesignFlowManager()
Destructor.
Step successfully executed but without any IR change.
std::set< vertex, DesignFlowStepNecessitySorter > possibly_ready
The set of potentially ready steps; when a step is added to set is ready to be executed, but it can become unready because of new added vertices.
Source must be executed to satisfy target.
#define INDENT_OUT_MEX(outLevel, curOutLevel, mex)
static size_t step_counter
NOTE: static should be removed when all the design flow managers will be merged Counter of current it...
static const int DEPENDENCE_SELECTOR
The dependence selector.
boost::graph_traits< graph >::in_edge_iterator InEdgeIterator
in_edge_iterator definition.
Definition: graph.hpp:1310
exceptions managed by PandA
DesignFlowStep_Status GetStatus(const std::string &signature) const
Return the status of a design step (if it does not exist return NONEXISTENT)
Definition of hash function for EdgeDescriptor.
Definition: graph.hpp:1321
CustomUnorderedMap< std::string, DesignFlowStepFactoryConstRef > design_flow_step_factories
The registered factories.
vertex GetDesignFlowStep(const std::string &signature) const
Return the vertex associated with a design step if exists, NULL_VERTEX otherwise. ...
static const int DEPENDENCE_FEEDBACK_SELECTOR
The dependence feedback selector.
Include a set of utilities used to manage CPU time measures.
#define STR(s)
Macro which performs a lexical_cast to a string.
Auxiliary methods for manipulating string.
DesignFlowManager(const ParameterConstRef parameters)
Constructor.
boost::graph_traits< graph >::edge_iterator EdgeIterator
edge_iterator definition.
Definition: graph.hpp:1314
Pure virtual base class for all the design flow step factory.
#define START_TIME(time_var)
Macro used to store the start time into time_var.
Definition: cpu_time.hpp:133
#define THROW_UNREACHABLE(str_expr)
helper function used to specify that some points should never be reached
Definition: exceptions.hpp:292
unsigned edges[4545]
Definition: graph.h:25
Base class for step of design flow.
const DesignFlowGraphConstRef feedback_design_flow_graph
The design flow graph with feedback edges.
CustomMap< vertex, std::string > step_names
The name of each vertex (we have to store since it is possible that it cannot be recomputed at the en...
int debug_level
The debug level.
Classes to describe design flow graph.
CustomMap< vertex, size_t > unchanged_executions
The number of times each step is executed with unchanged exit.
redefinition of set to manage ordered/unordered structures
#define STOP_TIME(time_var)
Macro used to store the elapsed time into time_var.
Definition: cpu_time.hpp:136
const ParameterConstRef parameters
The set of input parameters.
boost::graph_traits< graph >::vertex_descriptor vertex
vertex definition.
Definition: graph.hpp:1303
unsigned offset[NUM_VERTICES+1]
Definition: graph.h:3
static const int PRECEDENCE_SELECTOR
The condition selector.
CustomMap< size_t, CustomMap< vertex, DesignFlowStep_Status > > vertex_history
This structure stores "history of design flow graph manager - vertices" First key is the iteration Se...
boost::graph_traits< graph >::vertex_iterator VertexIterator
vertex_iterator definition.
Definition: graph.hpp:1307
DesignFlowStep_Status
The status of a step.
std::string PrintVirtualDataMemoryUsage()
Definition: cpu_stats.cpp:59
virtual void Exec() final
Execute the design flow.
const DesignFlowGraphsCollectionRef design_flow_graphs_collection
The bulk graph of steps composing the design flow.
Wrapper of design_flow.
null deleter
Definition: refcount.hpp:51
std::string print_cpu_time(long int t)
massage a long which represents a time interval in milliseconds, into a string suitable for output ...
Definition: cpu_time.hpp:110
refcount< DesignFlowStep > DesignFlowStepRef
Class describing auxiliary steps in design flow.
#define OUTPUT_LEVEL_VERY_PEDANTIC
verbose debugging print is performed.
const int output_level
The output level.
CustomMap< vertex, long > accumulated_execution_time
The accumulated times of each step.
size_t indentation
The current indentation for debug messages.
Template borrowed from the ANTLR library by Terence Parr (http://www.jGuru.com - Software rights: htt...
Definition: refcount.hpp:94
#define DEBUG_LEVEL_PARANOIC
paranoid level debugging print is performed.
this class is used to manage the command-line or XML options.
CustomMap< vertex, size_t > skipped_executions
The number of times the execution of a step is skipped.
DesignFlowStepFactoryConstRef CGetDesignFlowStepFactory(const std::string &prefix) const
Return the factory which can create design flow step with signature beginning with prefix...
x
Return the smallest n such that 2^n >= _x.
Utility managing CPU statistics.
static const int AUX_SELECTOR
The auxiliary selector.
bool operator()(const vertex x, const vertex y) const
Compare position of two vertices.
CustomMap< vertex, size_t > success_executions
The number of times each step is executed with success.
Step is symbolic and it has already been marked.
#define NULL_VERTEX
null vertex definition
Definition: graph.hpp:1305
const DesignFlowGraphConstRef CGetDesignFlowGraph() const
Return the design flow graph.
Step not yet executed.
#define THROW_ASSERT(cond, str_expr)
helper function used to check an assert and if needed to throw an error in a standard way ...
Definition: exceptions.hpp:289

Generated on Mon Feb 12 2024 13:02:51 for PandA-2024.02 by doxygen 1.8.13