PandA-2024.02
cond_expr_restructuring.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) 2015-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 
45 #include "Parameter.hpp"
46 
48 #include "application_manager.hpp"
49 
51 #include "design_flow_graph.hpp"
52 #include "design_flow_manager.hpp"
53 
55 #include "hls.hpp"
56 #include "hls_device.hpp"
57 #include "hls_manager.hpp"
58 #include "hls_step.hpp"
59 
61 #include "fu_binding.hpp"
62 
65 
67 #include "schedule.hpp"
68 
70 #include "token_interface.hpp"
71 
73 #include "dbgPrintHelper.hpp" // for DEBUG_LEVEL_
74 #include "string_manipulation.hpp" // for GET_CLASS
75 #include "tree_basic_block.hpp"
76 #include "tree_helper.hpp"
77 #include "tree_manager.hpp"
78 #include "tree_manipulation.hpp"
79 #include "tree_node.hpp"
80 #include "tree_reindex.hpp"
81 
82 #define EPSILON 0.0001
83 
85  const DesignFlowManagerConstRef _design_flow_manager,
86  const ParameterConstRef _parameters)
87  : FunctionFrontendFlowStep(_AppM, _function_id, COND_EXPR_RESTRUCTURING, _design_flow_manager, _parameters)
88 {
89  debug_level = parameters->get_class_debug_level(GET_CLASS(*this), DEBUG_LEVEL_NONE);
90 }
91 
93 
96 {
98  switch(relationship_type)
99  {
101  {
102  break;
103  }
105  {
108  {
109  if(parameters->getOption<HLSFlowStep_Type>(OPT_scheduling_algorithm) == HLSFlowStep_Type::SDC_SCHEDULING &&
110  GetPointer<const HLS_manager>(AppM) && GetPointerS<const HLS_manager>(AppM)->get_HLS(function_id) and
111  GetPointerS<const HLS_manager>(AppM)->get_HLS(function_id)->Rsch)
112  {
114  const auto update_schedule = design_flow_manager.lock()->GetDesignFlowStep(
115  FunctionFrontendFlowStep::ComputeSignature(FrontendFlowStepType::UPDATE_SCHEDULE, function_id));
116  if(update_schedule)
117  {
118  const auto design_flow_graph = design_flow_manager.lock()->CGetDesignFlowGraph();
119  const auto design_flow_step =
120  design_flow_graph->CGetDesignFlowStepInfo(update_schedule)->design_flow_step;
121  if(GetPointerS<const FunctionFrontendFlowStep>(design_flow_step)->CGetBBVersion() !=
122  function_behavior->GetBBVersion())
123  {
124  relationships.insert(std::make_pair(UPDATE_SCHEDULE, SAME_FUNCTION));
125  break;
126  }
127  }
128  }
129  }
130  break;
131  }
133  {
134  relationships.insert(std::make_pair(COMMUTATIVE_EXPR_RESTRUCTURING, SAME_FUNCTION));
135  relationships.insert(std::make_pair(COMPLETE_BB_GRAPH, SAME_FUNCTION));
136  relationships.insert(std::make_pair(FUNCTION_CALL_OPT, SAME_FUNCTION));
137  relationships.insert(std::make_pair(MULTI_WAY_IF, SAME_FUNCTION));
138  relationships.insert(std::make_pair(SHORT_CIRCUIT_TAF, SAME_FUNCTION));
139  break;
140  }
141  default:
142  {
143  THROW_UNREACHABLE("");
144  }
145  }
146  return relationships;
147 }
148 
150 {
152  {
153  return false;
154  }
155 #if HAVE_ILP_BUILT
156  if(parameters->getOption<HLSFlowStep_Type>(OPT_scheduling_algorithm) == HLSFlowStep_Type::SDC_SCHEDULING &&
157  GetPointer<const HLS_manager>(AppM) && GetPointerS<const HLS_manager>(AppM)->get_HLS(function_id) and
158  GetPointerS<const HLS_manager>(AppM)->get_HLS(function_id)->Rsch)
159  {
161  const auto update_schedule = design_flow_manager.lock()->GetDesignFlowStep(
162  FunctionFrontendFlowStep::ComputeSignature(FrontendFlowStepType::UPDATE_SCHEDULE, function_id));
163  if(update_schedule)
164  {
165  const auto design_flow_graph = design_flow_manager.lock()->CGetDesignFlowGraph();
166  const auto design_flow_step = design_flow_graph->CGetDesignFlowStepInfo(update_schedule)->design_flow_step;
167  if(GetPointerS<const FunctionFrontendFlowStep>(design_flow_step)->CGetBBVersion() !=
168  function_behavior->GetBBVersion())
169  {
170  return false;
171  }
172  else
173  {
174  return true;
175  }
176  }
177  else
178  {
179  return false;
180  }
181  }
182  else
183 #endif
184  {
185  return false;
186  }
187 }
188 
190 {
192  TM = AppM->get_tree_manager();
193  if(GetPointer<HLS_manager>(AppM) && GetPointer<HLS_manager>(AppM)->get_HLS(function_id))
194  {
195  schedule = GetPointer<HLS_manager>(AppM)->get_HLS(function_id)->Rsch;
196  allocation_information = GetPointer<HLS_manager>(AppM)->get_HLS(function_id)->allocation_information;
197  }
198 }
199 
201 {
202  bool modified = false;
203  static size_t counter = 0;
204 
205  THROW_ASSERT(GetPointer<const HLS_manager>(AppM)->get_HLS_device(), "unexpected condition");
206  const auto hls_d = GetPointerS<const HLS_manager>(AppM)->get_HLS_device();
207  THROW_ASSERT(hls_d->has_parameter("max_lut_size"), "unexpected condition");
208  const auto max_lut_size = hls_d->get_parameter<size_t>("max_lut_size");
209 
211  const auto fd = GetPointerS<const function_decl>(TM->CGetTreeNode(function_id));
212  const auto sl = GetPointerS<const statement_list>(GET_CONST_NODE(fd->body));
213  for(const auto& block : sl->list_of_bloc)
214  {
215  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Examining BB" + STR(block.first));
216  const auto& list_of_stmt = block.second->CGetStmtList();
217  for(auto stmt = list_of_stmt.begin(); stmt != list_of_stmt.end(); stmt++)
218  {
219  if(!AppM->ApplyNewTransformation())
220  {
221  break;
222  }
223 
224  std::list<tree_nodeRef> new_tree_nodes;
225 
226  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Examining " + (*stmt)->ToString());
227  auto next_stmt_ptr = std::next(stmt);
228  tree_nodeRef next_stmt = std::next(stmt) != list_of_stmt.end() ? *(std::next(stmt)) : tree_nodeRef();
229  tree_nodeRef first_stmt = *stmt;
230  tree_nodeRef second_stmt = tree_nodeRef();
231  tree_nodeRef third_stmt = tree_nodeRef();
232  if(!IsCondExprGimple(*stmt))
233  {
234  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Not a cond_expr");
235  continue;
236  }
237  bool first_operand_of_first = true;
238  bool first_operand_of_second = true;
239  second_stmt = IsCondExprChain(*stmt, true, false);
240  if(!second_stmt)
241  {
242  second_stmt = IsCondExprChain(*stmt, false, false);
243  first_operand_of_first = false;
244  }
245  if(second_stmt)
246  {
248  "---Chained with a second cond_expr: " + STR(second_stmt));
249  third_stmt = IsCondExprChain(second_stmt, true, true);
250  if(!third_stmt)
251  {
252  third_stmt = IsCondExprChain(second_stmt, false, true);
253  first_operand_of_second = false;
254  }
255  }
256  if(!third_stmt)
257  {
258  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Not chained with two cond_exprs");
259  continue;
260  }
261  const auto first_ga = GetPointer<const gimple_assign>(GET_NODE(*stmt));
262  const auto first_ce = GetPointer<const cond_expr>(GET_NODE(first_ga->op1));
263 
264  const auto second_ga = GetPointer<const gimple_assign>(GET_NODE(second_stmt));
265  const auto second_ce = GetPointer<const cond_expr>(GET_NODE(second_ga->op1));
266 
267  const auto third_ga = GetPointer<const gimple_assign>(GET_NODE(third_stmt));
268  const auto third_ce = GetPointer<const cond_expr>(GET_NODE(third_ga->op1));
269 
270  const double old_time = schedule->GetEndingTime(first_ga->index);
271 
274  double operand_ready_time = 0.0;
275 
276  const auto other_operand_of_first = first_operand_of_first ? first_ce->op2 : first_ce->op1;
277  const auto other_operand_of_second = first_operand_of_second ? second_ce->op2 : second_ce->op1;
279  operands.insert(std::make_pair(other_operand_of_first, *stmt));
280  operands.insert(std::make_pair(other_operand_of_second, second_stmt));
281  operands.insert(std::make_pair(third_ce->op1, third_stmt));
282  operands.insert(std::make_pair(third_ce->op2, third_stmt));
283  operands.insert(std::make_pair(first_ce->op0, *stmt));
284  operands.insert(std::make_pair(second_ce->op0, second_stmt));
285  operands.insert(std::make_pair(third_ce->op0, third_stmt));
286  for(const auto& operand : operands)
287  {
289  "---Analyzing when " + STR(operand.first) + " used in " + STR(operand.second) + " is ready");
290  const auto sn = GetPointer<const ssa_name>(GET_NODE(operand.first));
291  if(sn)
292  {
293  const auto def_operand = GetPointer<const gimple_node>(GET_NODE(sn->CGetDefStmt()));
294  if(def_operand->bb_index == block.first)
295  {
296  const auto def_stmt = sn->CGetDefStmt();
297  const auto ending_time = schedule->GetEndingTime(def_stmt->index);
298  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Ending time is " + STR(ending_time));
299  const auto connection_time = allocation_information->GetConnectionTime(
300  def_stmt->index, operand.second->index, schedule->get_cstep(def_stmt->index));
302  "---Connection time is " + STR(connection_time));
303  const auto current_operand_ready_time = ending_time + connection_time;
304  operand_ready_time = std::max(operand_ready_time, current_operand_ready_time);
306  "---New ready time is " + STR(operand_ready_time));
307  }
308  }
309  }
310 
312  const auto cond_expr_time1 = allocation_information->GetTimeLatency((*stmt)->index, fu_binding::UNKNOWN).first;
314  "---Delay of first operation is " + STR(cond_expr_time1));
315  const auto cond_expr_time2 =
318  "---Delay of second operation is " + STR(cond_expr_time2));
319  const auto cond_expr_time3 =
322  "---Delay of third operation is " + STR(cond_expr_time3));
323  const auto new_ending_time = operand_ready_time + std::max(cond_expr_time1, cond_expr_time3) +
324  cond_expr_time2 +
325  allocation_information->GetConnectionTime(third_ga->index, second_ga->index,
326  schedule->get_cstep(third_ga->index));
328  "---Operand ready time " + STR(operand_ready_time) + " - New ending time " +
329  STR(new_ending_time) + " - Old ending time " + STR(old_time));
330  if(new_ending_time + EPSILON >= old_time)
331  {
332  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Increased execution time");
333  continue;
334  }
335  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Chained with a third cond_expr");
336  THROW_ASSERT(third_stmt && second_stmt, "");
340 
342  const auto type_node = tree_helper::CGetType(*stmt);
343  auto first_value = first_operand_of_second ? second_ce->op2 : second_ce->op1;
344  auto second_value = first_operand_of_first ? first_ce->op2 : first_ce->op1;
345  if(!first_operand_of_first)
346  {
347  std::swap(first_value, second_value);
348  }
349  const auto cond_expr_node = tree_man->create_ternary_operation(type_node, first_ce->op0, first_value,
350  second_value, BUILTIN_SRCP, cond_expr_K);
351 
353  tree_nodeRef var = nullptr;
354  if(GET_CONST_NODE(first_value)->get_kind() == ssa_name_K &&
355  GET_CONST_NODE(second_value)->get_kind() == ssa_name_K)
356  {
357  const auto sn1 = GetPointer<const ssa_name>(GET_CONST_NODE(first_value));
358  const auto sn2 = GetPointer<const ssa_name>(GET_CONST_NODE(second_value));
359  if(sn1->var && sn2->var && sn1->var->index == sn2->var->index)
360  {
361  var = sn1->var;
362  }
363  }
364  const auto first_ga_op0 = GetPointer<const ssa_name>(GET_CONST_NODE(first_ga->op0));
365  const auto ssa_node = tree_man->create_ssa_name(var, type_node, first_ga_op0->min, first_ga_op0->max);
366  GetPointerS<ssa_name>(GET_NODE(ssa_node))->bit_values = first_ga_op0->bit_values;
367 
369  const auto curr_stmt =
370  tree_man->create_gimple_modify_stmt(ssa_node, cond_expr_node, function_id, BUILTIN_SRCP);
373  block.second->PushBefore(curr_stmt, *stmt, AppM);
374  new_tree_nodes.push_back(curr_stmt);
375 
376  tree_nodeRef and_first_cond;
377  if(GET_INDEX_NODE(first_ce->op0) == GET_INDEX_NODE(second_ce->op0))
378  {
380  if(!first_operand_of_first && !first_operand_of_second)
381  {
382  const auto boolType = tree_man->GetBooleanType();
383  tree_nodeRef ga;
384  if(max_lut_size > 0)
385  {
386  const auto DefaultUnsignedLongLongInt = tree_man->GetUnsignedLongLongType();
387  const auto lut_constant_node = TM->CreateUniqueIntegerCst(1, DefaultUnsignedLongLongInt);
388  const auto new_op1 =
389  tree_man->create_lut_expr(boolType, lut_constant_node, first_ce->op0, nullptr, nullptr, nullptr,
390  nullptr, nullptr, nullptr, nullptr, BUILTIN_SRCP);
391  ga = tree_man->CreateGimpleAssign(boolType, TM->CreateUniqueIntegerCst(0, boolType),
392  TM->CreateUniqueIntegerCst(1, boolType), new_op1, function_id,
393  BUILTIN_SRCP);
394  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Created LUT NOT " + STR(ga));
395  }
396  else
397  {
398  const auto not_expr =
399  tree_man->create_unary_operation(boolType, first_ce->op0, BUILTIN_SRCP, truth_not_expr_K);
400  ga = tree_man->CreateGimpleAssign(boolType, TM->CreateUniqueIntegerCst(0, boolType),
401  TM->CreateUniqueIntegerCst(1, boolType), not_expr, function_id,
402  BUILTIN_SRCP);
403  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Created NOT " + STR(ga));
404  }
405  block.second->PushBefore(ga, *stmt, AppM);
406  new_tree_nodes.push_back(ga);
407  and_first_cond = GetPointerS<gimple_assign>(GET_NODE(ga))->op0;
408  }
409  else if(first_operand_of_first && first_operand_of_second)
410  {
411  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Simplified to identity");
412  and_first_cond = first_ce->op0;
413  }
414  else
415  {
416  const auto boolType = tree_man->GetBooleanType();
417  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Simplified to 0");
418  and_first_cond = TM->CreateUniqueIntegerCst(0, boolType);
419  }
420  }
421  else
422  {
423  const auto boolType = tree_man->GetBooleanType();
424  tree_nodeRef ga;
425  if(max_lut_size > 0)
426  {
428  const auto DefaultUnsignedLongLongInt = tree_man->GetUnsignedLongLongType();
429  long long int lut_val;
430  if(!first_operand_of_first && !first_operand_of_second)
431  {
432  lut_val = 1;
433  }
434  else if(!first_operand_of_first && first_operand_of_second)
435  {
436  lut_val = 2;
437  }
438  else if(first_operand_of_first && !first_operand_of_second)
439  {
440  lut_val = 4;
441  }
442  else
443  {
444  lut_val = 8;
445  }
446  const auto lut_constant_node = TM->CreateUniqueIntegerCst(lut_val, DefaultUnsignedLongLongInt);
447  const auto new_op1 =
448  tree_man->create_lut_expr(boolType, lut_constant_node, second_ce->op0, first_ce->op0, nullptr,
449  nullptr, nullptr, nullptr, nullptr, nullptr, BUILTIN_SRCP);
450  ga = tree_man->CreateGimpleAssign(boolType, TM->CreateUniqueIntegerCst(0, boolType),
451  TM->CreateUniqueIntegerCst(1, boolType), new_op1, function_id,
452  BUILTIN_SRCP);
453  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Created LUT STD " + STR(ga));
454  }
455  else
456  {
457  if(!first_operand_of_first && !first_operand_of_second)
458  {
459  const auto not_expr0 =
460  tree_man->create_unary_operation(boolType, second_ce->op0, BUILTIN_SRCP, truth_not_expr_K);
461  const auto op0_not_expr = tree_man->CreateGimpleAssign(
462  boolType, TM->CreateUniqueIntegerCst(0, boolType), TM->CreateUniqueIntegerCst(1, boolType),
463  not_expr0, function_id, BUILTIN_SRCP);
464  block.second->PushBefore(op0_not_expr, *stmt, AppM);
465  new_tree_nodes.push_back(op0_not_expr);
466  const auto not_expr1 =
467  tree_man->create_unary_operation(boolType, first_ce->op0, BUILTIN_SRCP, truth_not_expr_K);
468  const auto op1_not_expr = tree_man->CreateGimpleAssign(
469  boolType, TM->CreateUniqueIntegerCst(0, boolType), TM->CreateUniqueIntegerCst(1, boolType),
470  not_expr1, function_id, BUILTIN_SRCP);
471  block.second->PushBefore(op1_not_expr, *stmt, AppM);
472  new_tree_nodes.push_back(op1_not_expr);
473  const auto and_expr = tree_man->create_binary_operation(
474  boolType, GetPointerS<gimple_assign>(GET_NODE(op0_not_expr))->op0,
475  GetPointerS<gimple_assign>(GET_NODE(op1_not_expr))->op0, BUILTIN_SRCP, truth_and_expr_K);
476  ga = tree_man->CreateGimpleAssign(boolType, TM->CreateUniqueIntegerCst(0, boolType),
477  TM->CreateUniqueIntegerCst(1, boolType), and_expr, function_id,
478  BUILTIN_SRCP);
479  }
480  else if(!first_operand_of_first && first_operand_of_second)
481  {
482  const auto not_expr1 =
483  tree_man->create_unary_operation(boolType, first_ce->op0, BUILTIN_SRCP, truth_not_expr_K);
484  const auto op1_not_expr = tree_man->CreateGimpleAssign(
485  boolType, TM->CreateUniqueIntegerCst(0, boolType), TM->CreateUniqueIntegerCst(1, boolType),
486  not_expr1, function_id, BUILTIN_SRCP);
487  block.second->PushBefore(op1_not_expr, *stmt, AppM);
488  new_tree_nodes.push_back(op1_not_expr);
489  const auto and_expr = tree_man->create_binary_operation(
490  boolType, second_ce->op0, GetPointerS<gimple_assign>(GET_NODE(op1_not_expr))->op0, BUILTIN_SRCP,
491  truth_and_expr_K);
492  ga = tree_man->CreateGimpleAssign(boolType, TM->CreateUniqueIntegerCst(0, boolType),
493  TM->CreateUniqueIntegerCst(1, boolType), and_expr, function_id,
494  BUILTIN_SRCP);
495  }
496  else if(first_operand_of_first && !first_operand_of_second)
497  {
498  const auto not_expr0 =
499  tree_man->create_unary_operation(boolType, second_ce->op0, BUILTIN_SRCP, truth_not_expr_K);
500  const auto op0_not_expr = tree_man->CreateGimpleAssign(
501  boolType, TM->CreateUniqueIntegerCst(0, boolType), TM->CreateUniqueIntegerCst(1, boolType),
502  not_expr0, function_id, BUILTIN_SRCP);
503  block.second->PushBefore(op0_not_expr, *stmt, AppM);
504  new_tree_nodes.push_back(op0_not_expr);
505  const auto and_expr = tree_man->create_binary_operation(
506  boolType, GetPointerS<gimple_assign>(GET_NODE(op0_not_expr))->op0, first_ce->op0, BUILTIN_SRCP,
507  truth_and_expr_K);
508  ga = tree_man->CreateGimpleAssign(boolType, TM->CreateUniqueIntegerCst(0, boolType),
509  TM->CreateUniqueIntegerCst(1, boolType), and_expr, function_id,
510  BUILTIN_SRCP);
511  }
512  else
513  {
514  const auto and_expr = tree_man->create_binary_operation(boolType, second_ce->op0, first_ce->op0,
515  BUILTIN_SRCP, truth_and_expr_K);
516  ga = tree_man->CreateGimpleAssign(boolType, TM->CreateUniqueIntegerCst(0, boolType),
517  TM->CreateUniqueIntegerCst(1, boolType), and_expr, function_id,
518  BUILTIN_SRCP);
519  }
520  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Created AND " + STR(ga));
521  }
522  block.second->PushBefore(ga, *stmt, AppM);
523  new_tree_nodes.push_back(ga);
524  and_first_cond = GetPointerS<gimple_assign>(GET_NODE(ga))->op0;
525  }
526 
528  const auto root_cond_expr = tree_man->create_ternary_operation(
529  type_node, and_first_cond, first_operand_of_second ? second_ce->op1 : second_ce->op2, ssa_node,
530  BUILTIN_SRCP, cond_expr_K);
531 
533  const auto root_gimple_node =
534  tree_man->create_gimple_modify_stmt(first_ga->op0, root_cond_expr, function_id, BUILTIN_SRCP);
536  "---Created " + GET_CONST_NODE(root_gimple_node)->ToString());
537  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Before " + (*stmt)->ToString());
538  block.second->Replace(*stmt, root_gimple_node, true, AppM);
539  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---After " + (*stmt)->ToString());
540  new_tree_nodes.push_back(root_gimple_node);
541  AppM->RegisterTransformation(GetName(), root_gimple_node);
542 
544  THROW_ASSERT(GetPointer<const ssa_name>(GET_CONST_NODE(second_ga->op0))->CGetUseStmts().size() == 0, "");
545 
547  block.second->RemoveStmt(second_stmt, AppM);
548 
549  for(const auto& temp_stmt : list_of_stmt)
550  {
551  schedule->UpdateTime(temp_stmt->index);
552  }
553 
555  (!parameters->IsParameter("print-dot-FF") || parameters->GetParameter<unsigned int>("print-dot-FF")))
556  {
557  WriteBBGraphDot("BB_Inside_" + GetName() + "_" + STR(counter) + ".dot");
559  "---Written BB_Inside_" + GetName() + "_" + STR(counter) + ".dot");
560  counter++;
561  }
562  const double new_time = schedule->GetEndingTime(GET_INDEX_CONST_NODE(root_gimple_node));
563  if(new_time + EPSILON > old_time)
564  {
565  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Error in estimation");
567  for(const auto& to_be_removed : new_tree_nodes)
568  {
569  block.second->RemoveStmt(to_be_removed, AppM);
570  }
571 
573  next_stmt ? block.second->PushBefore(second_stmt, next_stmt, AppM) :
574  block.second->PushBack(second_stmt, AppM);
575  next_stmt ? block.second->PushBefore(first_stmt, next_stmt, AppM) :
576  block.second->PushBack(first_stmt, AppM);
577 
579  for(const auto& temp_stmt : list_of_stmt)
580  {
581  schedule->UpdateTime(temp_stmt->index);
582  }
583 
585  stmt = std::prev(next_stmt_ptr);
586  continue;
587  }
589  modified = true;
591  stmt = list_of_stmt.begin();
592  }
593  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Examined BB" + STR(block.first));
594  }
595 
596  if(modified)
597  {
598  function_behavior->UpdateBBVersion();
599  }
601 }
602 
604 {
605  const auto ga = GetPointer<const gimple_assign>(GET_CONST_NODE(tn));
606  if(!ga)
607  {
608  return false;
609  }
610  return GET_NODE(ga->op1)->get_kind() == cond_expr_K;
611 }
612 
614  bool is_third_node) const
615 {
616  const auto ga = GetPointer<const gimple_assign>(GET_CONST_NODE(tn));
617  const auto ce = GetPointer<const cond_expr>(GET_NODE(ga->op1));
618  const auto operand = first ? GET_NODE(ce->op1) : GET_NODE(ce->op2);
619  const auto other_operand = first ? GET_NODE(ce->op2) : GET_NODE(ce->op1);
620  const auto sn = GetPointer<const ssa_name>(operand);
621  if(tree_helper::is_constant(TM, other_operand->index))
622  {
623  return tree_nodeRef();
624  }
625  if(!sn)
626  {
627  return tree_nodeRef();
628  }
629  if(!is_third_node && sn->CGetNumberUses() > 1)
630  {
631  return tree_nodeRef();
632  }
633  const auto def = GetPointer<const gimple_assign>(GET_NODE(sn->CGetDefStmt()));
634  if(!def)
635  {
636  return tree_nodeRef();
637  }
638  if(def->bb_index != ga->bb_index)
639  {
640  return tree_nodeRef();
641  }
642  const auto chain_ce = GetPointer<const cond_expr>(GET_NODE(def->op1));
643  if(!chain_ce)
644  {
645  return tree_nodeRef();
646  }
647  if(schedule->GetStartingTime(ga->index) == schedule->GetEndingTime(def->index) or
648  (schedule->get_cstep_end(def->index).second + 1) == schedule->get_cstep(ga->index).second)
649  {
650  return sn->CGetDefStmt();
651  }
652  else
653  {
654  return tree_nodeRef();
655  }
656 }
#define GET_NODE(t)
Macro used to hide implementation details when accessing a tree_node from another tree_node...
Definition: tree_node.hpp:343
bool IsCondExprGimple(const tree_nodeConstRef tn) const
Return true if tree node is a gimple_assign with a cond_expr in the right part.
#define DEBUG_LEVEL_VERY_PEDANTIC
extremely verbose debugging print is performed.
Data structure representing the entire HLS information.
#define INDENT_DBG_MEX(dbgLevel, curDbgLevel, mex)
We are producing a debug version of the program, so the message is printed;.
virtual void Initialize()
Initialize the step (i.e., like a constructor, but executed just before exec.
File containing functions and utilities to support the printing of debug messagges.
Step successfully executed.
#define GET_CLASS(obj)
Macro returning the actual type of an object.
Definition of the class representing a generic C application.
void Initialize() override
Initialize the step (i.e., like a constructor, but executed just before exec.
std::string GetName() const override
Return the name of this design step.
RelationshipType
The relationship type.
Source must be executed to satisfy target.
AbsControlStep get_cstep(const vertex &op) const
Returns the clock cycle where the given operation has been scheduled.
Definition: schedule.cpp:270
AllocationInformationRef allocation_information
The allocation information.
AbsControlStep get_cstep_end(const vertex &op) const
Return the last clock cycle in which the operation execute.
Definition: schedule.cpp:302
A simple interface to token object of the raw files.
#define GET_INDEX_NODE(t)
Macro used to hide implementation details when accessing a tree_node from another tree_node...
Definition: tree_node.hpp:361
Data structure describing a basic block at tree level.
std::pair< double, double > GetTimeLatency(const unsigned int operation, const unsigned int functional_unit, const unsigned int stage=0) const
Return the execution time of (a stage of) an operation.
const tree_nodeConstRef CGetTreeNode(const unsigned int i) const
#define STR(s)
Macro which performs a lexical_cast to a string.
Auxiliary methods for manipulating string.
#define max
Definition: backprop.h:17
bool HasToBeExecuted() const override
Check if this step has actually to be executed.
std::string ToString(ActorGraphBackend_Type actor_graph_backend_type)
Header include.
~CondExprRestructuring() override
Destructor.
CondExprRestructuring(const application_managerRef AppM, unsigned int function_id, const DesignFlowManagerConstRef design_flow_manager, const ParameterConstRef parameters)
Constructor.
#define THROW_UNREACHABLE(str_expr)
helper function used to specify that some points should never be reached
Definition: exceptions.hpp:292
void UpdateTime(const unsigned int operation_index, bool update_cs=true)
Compute the starting and the ending time of a statement.
Definition: schedule.cpp:337
Data structure used to store the schedule of the operations.
bool HasToBeExecuted() const override
Check if this step has actually to be executed.
HLSFlowStep_Type
Definition: hls_step.hpp:95
void WriteBBGraphDot(const std::string &filename) const
Write the current version of statement list in dot format.
tree_nodeRef IsCondExprChain(const tree_nodeConstRef tn, const bool first, bool is_third_node) const
Given a gimple_assign with cond_expr in the right part and one of its operand it checks: ...
#define EPSILON
Header include.
const CustomUnorderedSet< std::pair< FrontendFlowStepType, FunctionRelationship > > ComputeFrontendRelationships(const DesignFlowStep::RelationshipType relationship_type) const override
Return the set of analyses in relationship with this design step.
const unsigned int index
Represent the index read from the raw file and the index-1 of the vector of tree_node associated to t...
Definition: tree_node.hpp:146
Classes to describe design flow graph.
tree_nodeRef CreateUniqueIntegerCst(integer_cst_t value, const tree_nodeConstRef &type)
memoization of integer constants
Analysis step restructing tree of cond_expr to reduce critical path delay.
const Wrefcount< const DesignFlowManager > design_flow_manager
The design flow manager.
#define GET_CONST_NODE(t)
Definition: tree_node.hpp:347
DesignFlowStep_Status GetStatus() const
Return the status of this design step.
Classes specification of the tree_node data structures.
const ParameterConstRef parameters
Set of input parameters.
DesignFlowStep_Status
The status of a step.
This package is used by all HLS packages to manage resource constraints and characteristics.
Class defining some useful functions to create tree nodes and to manipulate the tree manager...
#define DEBUG_LEVEL_NONE
no debugging print is performed.
Wrapper of design_flow.
static const unsigned int UNKNOWN
The value used to identified unknown functional unit.
Definition: fu_binding.hpp:178
This struct specifies the block node.
Definition: tree_node.hpp:1820
This file collects some utility functions.
double GetStartingTime(const unsigned int operation) const
Return the starting time of the operation.
Definition: schedule.cpp:1151
refcount< T > lock() const
Definition: refcount.hpp:212
#define BUILTIN_SRCP
const unsigned int function_id
The index of the function to be analyzed.
const application_managerRef AppM
The application manager.
struct definition of the type node structures.
Definition: tree_node.hpp:1318
Class specification of the tree_reindex support class.
tree_managerRef TM
The tree manager.
Data structure used to store the functional-unit binding of the vertexes.
ScheduleRef schedule
The schedule.
Template borrowed from the ANTLR library by Terence Parr (http://www.jGuru.com - Software rights: htt...
Definition: refcount.hpp:94
static tree_nodeConstRef CGetType(const tree_nodeConstRef &node)
Return the treenode of the type of node.
this class is used to manage the command-line or XML options.
double GetConnectionTime(const unsigned int first_operation, const unsigned int second_operation, const AbsControlStep cs) const
Return the connection time for a couple of operations or the phi overhead for a single operation...
refcount< tree_node > tree_nodeRef
RefCount type definition of the tree_node class structure.
Definition: tree_node.hpp:212
unsigned counter[N_THREADS]
Definition: data.c:3
int debug_level
The debug level.
double GetEndingTime(const unsigned int operation) const
Return the starting time of the operation.
Definition: schedule.cpp:1140
DesignFlowStep_Status InternalExec() override
Performs the loops analysis.
#define GET_INDEX_CONST_NODE(t)
Definition: tree_node.hpp:363
static bool is_constant(const tree_managerConstRef &TM, const unsigned int index)
Return if a tree node is a constant object.
Data structure definition for high-level synthesis flow.
This class creates a layer to add nodes and to manipulate the tree_nodes manager. ...
Class specification of the manager of the tree structures extracted from the raw file.
HLS specialization of generic_device.
const FunctionBehaviorRef function_behavior
The function behavior of the function to be analyzed.
int sl
Definition: adpcm.c:105
static const std::string ComputeSignature(const FrontendFlowStepType frontend_flow_step_type, const unsigned int function_id)
Compute the signature of a function frontend flow step.
#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:52 for PandA-2024.02 by doxygen 1.8.13