PandA-2024.02
hls_div_cg_ext.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  */
41 #include "hls_div_cg_ext.hpp"
43 
45 #include "design_flow_graph.hpp"
46 #include "design_flow_manager.hpp"
47 #include "design_flow_step.hpp"
48 
51 
53 #include "application_manager.hpp"
54 #include "behavioral_helper.hpp"
55 #include "call_graph.hpp"
56 #include "call_graph_manager.hpp"
57 #include "function_behavior.hpp"
58 #include "hls_device.hpp"
59 #include "hls_manager.hpp"
60 
62 #include "basic_block.hpp"
64 
66 #include "Parameter.hpp"
67 
69 #include <fstream>
70 
72 #include "custom_map.hpp"
73 #include <string>
74 
76 #include "ext_tree_node.hpp"
77 #include "token_interface.hpp"
78 #include "tree_basic_block.hpp"
79 #include "tree_helper.hpp"
80 #include "tree_manager.hpp"
81 #include "tree_manipulation.hpp"
82 #include "tree_node.hpp"
83 #include "tree_reindex.hpp"
84 
86 #include "dbgPrintHelper.hpp"
87 #include "exceptions.hpp"
88 #include "math_function.hpp"
89 #include "string_manipulation.hpp" // for GET_CLASS
90 
92  unsigned int _function_id, const DesignFlowManagerConstRef _design_flow_manager)
93  : FunctionFrontendFlowStep(_AppM, _function_id, HLS_DIV_CG_EXT, _design_flow_manager, _parameters),
94  TreeM(_AppM->get_tree_manager()),
95  use64bitMul(false),
96  use32bitMul(false)
97 {
98  debug_level = parameters->get_class_debug_level(GET_CLASS(*this), DEBUG_LEVEL_NONE);
99 }
100 
102 
105 {
107  switch(relationship_type)
108  {
110  {
111  relationships.insert(std::make_pair(COMPUTE_IMPLICIT_CALLS, SAME_FUNCTION));
112  relationships.insert(std::make_pair(FIX_STRUCTS_PASSED_BY_VALUE, SAME_FUNCTION));
113  relationships.insert(std::make_pair(FUNCTION_CALL_TYPE_CLEANUP, SAME_FUNCTION));
114  relationships.insert(std::make_pair(IR_LOWERING, SAME_FUNCTION));
115  relationships.insert(std::make_pair(USE_COUNTING, SAME_FUNCTION));
116  break;
117  }
119  {
120  break;
121  }
123  {
125  {
126  relationships.insert(std::make_pair(FUNCTION_CALL_TYPE_CLEANUP, SAME_FUNCTION));
127  }
128  break;
129  }
130  default:
131  {
132  THROW_UNREACHABLE("");
133  }
134  }
135  return relationships;
136 }
137 
139 {
141 
142  const auto curr_tn = TreeM->GetTreeNode(function_id);
143  const auto fname = tree_helper::GetFunctionName(TreeM, curr_tn);
144  const auto fd = GetPointerS<function_decl>(curr_tn);
145  const auto sl = GetPointerS<statement_list>(GET_NODE(fd->body));
146 
147  THROW_ASSERT(GetPointer<const HLS_manager>(AppM)->get_HLS_device(), "unexpected condition");
148  const auto hls_d = GetPointer<const HLS_manager>(AppM)->get_HLS_device();
149  if(fname != "__umul64" && fname != "__mul64")
150  {
151  if((hls_d->has_parameter("use_soft_64_mul") && hls_d->get_parameter<size_t>("use_soft_64_mul")) ||
152  (parameters->isOption(OPT_DSP_fracturing) && parameters->getOption<std::string>(OPT_DSP_fracturing) == "16") ||
153  (parameters->isOption(OPT_DSP_fracturing) && parameters->getOption<std::string>(OPT_DSP_fracturing) == "32"))
154  {
155  use64bitMul = true;
156  }
157  }
158  if(fname != "__umul32" && fname != "__mul32")
159  {
160  if((hls_d->has_parameter("use_soft_32_mul") && hls_d->get_parameter<size_t>("use_soft_32_mul")) ||
161  (parameters->isOption(OPT_DSP_fracturing) && parameters->getOption<std::string>(OPT_DSP_fracturing) == "16"))
162  {
163  use32bitMul = true;
164  }
165  }
166 
167  bool modified = false;
168  for(const auto& idx_bb : sl->list_of_bloc)
169  {
170  const auto& BB = idx_bb.second;
171  for(const auto& stmt : BB->CGetStmtList())
172  {
174  "-->Examine " + STR(GET_INDEX_NODE(stmt)) + " " + GET_NODE(stmt)->ToString());
175  modified |= recursive_examinate(stmt, stmt, tree_man);
177  "<--Examined " + STR(GET_INDEX_NODE(stmt)) + " " + GET_NODE(stmt)->ToString());
178  }
179  }
180 
181  if(modified)
182  {
183  function_behavior->UpdateBBVersion();
185  }
187 }
188 
189 bool hls_div_cg_ext::recursive_examinate(const tree_nodeRef& current_tree_node, const tree_nodeRef& current_statement,
190  const tree_manipulationRef tree_man)
191 {
192  THROW_ASSERT(current_tree_node->get_kind() == tree_reindex_K, "Node is not a tree reindex");
193  bool modified = false;
194  const tree_nodeRef curr_tn = GET_NODE(current_tree_node);
195  const auto get_current_srcp = [curr_tn]() -> std::string {
196  const auto srcp_tn = GetPointer<const srcp>(curr_tn);
197  if(srcp_tn)
198  {
199  return srcp_tn->include_name + ":" + STR(srcp_tn->line_number) + ":" + STR(srcp_tn->column_number);
200  }
201  return "";
202  };
203  switch(curr_tn->get_kind())
204  {
205  case call_expr_K:
206  case aggr_init_expr_K:
207  {
208  break;
209  }
210  case gimple_assign_K:
211  {
212  const auto gm = GetPointerS<gimple_assign>(curr_tn);
213  modified |= recursive_examinate(gm->op0, current_statement, tree_man);
214  modified |= recursive_examinate(gm->op1, current_statement, tree_man);
215  if(gm->predicate)
216  {
217  modified |= recursive_examinate(gm->predicate, current_statement, tree_man);
218  }
219  break;
220  }
221  case tree_list_K:
222  {
223  tree_nodeRef current = current_tree_node;
224  while(current)
225  {
226  modified |=
227  recursive_examinate(GetPointer<tree_list>(GET_NODE(current))->valu, current_statement, tree_man);
228  current = GetPointer<tree_list>(GET_NODE(current))->chan;
229  }
230  break;
231  }
233  {
234  const auto ue = GetPointerS<unary_expr>(curr_tn);
235  modified |= recursive_examinate(ue->op, current_statement, tree_man);
236  break;
237  }
239  {
240  const auto be = GetPointerS<binary_expr>(curr_tn);
241  const auto be_type = be->get_kind();
242  modified |= recursive_examinate(be->op0, current_statement, tree_man);
243  modified |= recursive_examinate(be->op1, current_statement, tree_man);
244 
245  if(be_type == exact_div_expr_K || be_type == trunc_div_expr_K || be_type == trunc_mod_expr_K)
246  {
247  const auto expr_type = tree_helper::CGetType(be->op0);
248  const auto bitsize0 = ceil_pow2(tree_helper::Size(be->op0));
249  const auto bitsize1 = ceil_pow2(tree_helper::Size(be->op1));
250  const auto bitsize = std::max(bitsize0, bitsize1);
251 
252  const auto div_by_constant = [&]() {
253  if(GetPointer<const integer_cst>(GET_CONST_NODE(be->op1)))
254  {
255  const auto cst_val = tree_helper::GetConstValue(be->op1);
256  if((cst_val & (cst_val - 1)) == 0)
257  {
258  return true;
259  }
260  }
261  return false;
262  }();
263 
264  if(!div_by_constant && GET_CONST_NODE(expr_type)->get_kind() == integer_type_K &&
265  (bitsize == 32 || bitsize == 64))
266  {
267  const auto fu_suffix = be_type == trunc_mod_expr_K ? "mod" : "div";
268  const auto bitsize_str = bitsize == 32 ? "s" : "d";
269  const auto unsignedp = tree_helper::IsUnsignedIntegerType(expr_type);
270  const std::string fu_name = "__" + STR(unsignedp ? "u" : "") + fu_suffix + bitsize_str + "i3" +
271  ((bitsize0 == 64 && bitsize1 == 32) ? "6432" : "");
272  const auto called_function = TreeM->GetFunction(fu_name);
273  THROW_ASSERT(called_function, "The library miss this function " + fu_name);
274  THROW_ASSERT(TreeM->get_implementation_node(called_function->index) != 0,
275  "inconsistent behavioral helper");
276  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Adding call to " + fu_name);
277  const std::vector<tree_nodeRef> args = {be->op0, be->op1};
278  const auto ce = tree_man->CreateCallExpr(called_function, args, get_current_srcp());
279  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Replaced " + STR(current_statement));
280  TreeM->ReplaceTreeNode(current_statement, current_tree_node, ce);
282  GET_INDEX_CONST_NODE(current_statement),
284  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "--- -> " + STR(current_statement));
285  modified = true;
286  }
287  }
288  else if(be_type == frem_expr_K)
289  {
290  const auto expr_type = tree_helper::CGetType(be->op0);
291  THROW_ASSERT(GET_CONST_NODE(expr_type)->get_kind() == real_type_K, "unexpected case");
292  const auto bitsize = tree_helper::Size(expr_type);
293  const std::string fu_name = bitsize == 32 ? "fmodf" : "fmod";
294  const auto called_function = TreeM->GetFunction(fu_name);
295  THROW_ASSERT(called_function, "Add option -lm to the command line for frem/fmod");
296  THROW_ASSERT(TreeM->get_implementation_node(called_function->index) != 0, "inconsistent behavioral helper");
297  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Adding call to " + fu_name);
298  const std::vector<tree_nodeRef> args = {be->op0, be->op1};
299  const auto ce = tree_man->CreateCallExpr(called_function, args, get_current_srcp());
300  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Replaced " + STR(current_statement));
301  TreeM->ReplaceTreeNode(current_statement, current_tree_node, ce);
303  GET_INDEX_CONST_NODE(current_statement),
305  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "--- -> " + STR(current_statement));
306  modified = true;
307  }
308  else if(be_type == mult_expr_K)
309  {
310  const auto expr_type = tree_helper::CGetType(be->op0);
311  const auto bitsize0 = ceil_pow2(tree_helper::Size(be->op0));
312  const auto bitsize1 = ceil_pow2(tree_helper::Size(be->op1));
313  const auto bitsize = std::max(bitsize0, bitsize1);
314  auto doTransf = false;
315  std::string fname;
316  if(use64bitMul && GET_CONST_NODE(expr_type)->get_kind() == integer_type_K && bitsize == 64)
317  {
318  const auto unsignedp = tree_helper::IsUnsignedIntegerType(expr_type);
319  fname = unsignedp ? "__umul64" : "__mul64";
320  doTransf = true;
321  }
322  if(use32bitMul && GET_CONST_NODE(expr_type)->get_kind() == integer_type_K && bitsize == 32)
323  {
324  const auto unsignedp = tree_helper::IsUnsignedIntegerType(expr_type);
325  fname = unsignedp ? "__umul32" : "__mul32";
326  doTransf = true;
327  }
328  if(doTransf)
329  {
330  const auto called_function = TreeM->GetFunction(fname);
331  THROW_ASSERT(called_function, "The library miss this function " + fname);
332  THROW_ASSERT(AppM->get_tree_manager()->get_implementation_node(called_function->index) != 0,
333  "inconsistent behavioral helper");
334  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Adding call to " + fname);
335  const std::vector<tree_nodeRef> args = {be->op0, be->op1};
336  const auto ce = tree_man->CreateCallExpr(called_function, args, get_current_srcp());
337  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Replaced " + STR(current_statement));
338  TreeM->ReplaceTreeNode(current_statement, current_tree_node, ce);
340  GET_INDEX_CONST_NODE(current_statement),
342  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "--- -> " + STR(current_statement));
343  modified = true;
344  }
345  }
346  break;
347  }
349  {
350  const ternary_expr* te = GetPointer<ternary_expr>(curr_tn);
351  modified |= recursive_examinate(te->op0, current_statement, tree_man);
352  if(te->op1)
353  {
354  modified |= recursive_examinate(te->op1, current_statement, tree_man);
355  }
356  if(te->op2)
357  {
358  modified |= recursive_examinate(te->op2, current_statement, tree_man);
359  }
360  break;
361  }
363  {
364  const quaternary_expr* qe = GetPointer<quaternary_expr>(curr_tn);
365  modified |= recursive_examinate(qe->op0, current_statement, tree_man);
366  if(qe->op1)
367  {
368  modified |= recursive_examinate(qe->op1, current_statement, tree_man);
369  }
370  if(qe->op2)
371  {
372  modified |= recursive_examinate(qe->op2, current_statement, tree_man);
373  }
374  if(qe->op3)
375  {
376  modified |= recursive_examinate(qe->op3, current_statement, tree_man);
377  }
378  break;
379  }
380  case constructor_K:
381  {
382  const constructor* co = GetPointer<constructor>(curr_tn);
383  for(const auto& iv : co->list_of_idx_valu)
384  {
385  modified |= recursive_examinate(iv.second, current_statement, tree_man);
386  }
387  break;
388  }
389  case gimple_call_K:
390  case gimple_nop_K:
391  case var_decl_K:
392  case parm_decl_K:
393  case ssa_name_K:
394  case lut_expr_K:
395  case gimple_cond_K:
396  case gimple_switch_K:
397  case gimple_multi_way_if_K:
398  case gimple_return_K:
399  case gimple_for_K:
400  case gimple_while_K:
401  case CASE_TYPE_NODES:
402  case type_decl_K:
403  case template_decl_K:
404  case target_mem_ref_K:
405  case target_mem_ref461_K:
406  case real_cst_K:
407  case complex_cst_K:
408  case string_cst_K:
409  case integer_cst_K:
410  case field_decl_K:
411  case function_decl_K:
412  case label_decl_K:
413  case result_decl_K:
414  case vector_cst_K:
415  case void_cst_K:
416  case tree_vec_K:
417  case case_label_expr_K:
418  case gimple_label_K:
419  case gimple_asm_K:
420  case gimple_goto_K:
421  case CASE_PRAGMA_NODES:
422  case gimple_pragma_K:
423  break;
424  case binfo_K:
425  case block_K:
426  case const_decl_K:
427  case CASE_CPP_NODES:
428  case gimple_bind_K:
429  case gimple_phi_K:
430  case gimple_predict_K:
431  case gimple_resx_K:
432  case identifier_node_K:
433  case last_tree_K:
434  case namespace_decl_K:
435  case none_K:
436  case placeholder_expr_K:
437  case statement_list_K:
438  case translation_unit_decl_K:
439  case error_mark_K:
440  case using_decl_K:
441  case tree_reindex_K:
442  case target_expr_K:
443  {
444  THROW_ERROR_CODE(NODE_NOT_YET_SUPPORTED_EC, "Not supported node: " + curr_tn->get_kind_text());
445  break;
446  }
447  default:
448  {
449  THROW_UNREACHABLE("");
450  }
451  }
452  return modified;
453 }
#define GET_NODE(t)
Macro used to hide implementation details when accessing a tree_node from another tree_node...
Definition: tree_node.hpp:343
#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;.
File containing functions and utilities to support the printing of debug messagges.
Step successfully executed.
#define CASE_BINARY_EXPRESSION
This macro collects all case labels for binary_expr objects.
Definition: tree_node.hpp:463
#define GET_CLASS(obj)
Macro returning the actual type of an object.
bool recursive_examinate(const tree_nodeRef &current_tree_node, const tree_nodeRef &current_statement, const tree_manipulationRef tree_man)
Recursive examine tree node.
Definition of the class representing a generic C application.
std::vector< std::pair< tree_nodeRef, tree_nodeRef > > list_of_idx_valu
store the list initializers: <index, value>
Definition: tree_node.hpp:2445
hls_div_cg_ext(const ParameterConstRef _parameters, const application_managerRef AppM, unsigned int _function_id, const DesignFlowManagerConstRef design_flow_manager)
Constructor.
RelationshipType
The relationship type.
Source must be executed to satisfy target.
mathematical utility function not provided by standard libraries
exceptions managed by PandA
tree_nodeRef op2
The third operand of the ternary expression.
Definition: tree_node.hpp:1253
tree_nodeRef op1
The second operand of the Quaternary expression.
Definition: tree_node.hpp:1287
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
struct definition of the ternary node structures.
Definition: tree_node.hpp:1239
This class provides methods to build a basic blocks graph.
Node not yet supported.
Definition: exceptions.hpp:323
Data structure describing a basic block at tree level.
Constructor: return an aggregate value made from specified components.
Definition: tree_node.hpp:2434
redefinition of map to manage ordered/unordered structures
const tree_managerRef TreeM
virtual enum kind get_kind() const =0
Virtual function returning the type of the actual class.
#define STR(s)
Macro which performs a lexical_cast to a string.
Auxiliary methods for manipulating string.
#define max
Definition: backprop.h:17
tree_nodeRef op3
The fourth operand of the Quaternary expression.
Definition: tree_node.hpp:1293
std::string ToString(ActorGraphBackend_Type actor_graph_backend_type)
Header include.
static void addCallPointAndExpand(CustomUnorderedSet< unsigned int > &AV, const application_managerRef AM, unsigned int caller_id, unsigned int called_id, unsigned int call_id, enum FunctionEdgeInfo::CallType call_type, int DL)
static bool IsUnsignedIntegerType(const tree_nodeConstRef &type)
Return true if the treenode is of unsigned integer type.
Step that extends the call graph with the division and modulus function calls where appropriate...
#define THROW_UNREACHABLE(str_expr)
helper function used to specify that some points should never be reached
Definition: exceptions.hpp:292
virtual std::string get_kind_text() const =0
Virtual function returning the name of the actual class.
DesignFlowStep_Status InternalExec() override
Fixes the var_decl duplication.
struct definition of the Quaternary node structures.
Definition: tree_node.hpp:1276
static unsigned long long Size(const tree_nodeConstRef &tn)
Return the size of a tree object.
Base class for step of design flow.
#define CASE_QUATERNARY_EXPRESSION
This macro collects all case labels for quaternary_expr objects.
Definition: tree_node.hpp:574
#define CASE_UNARY_EXPRESSION
This macro collects all case labels for unary_expr objects.
Definition: tree_node.hpp:371
Classes to describe design flow graph.
CustomUnorderedSet< unsigned int > already_visited
Already visited tree node (used to avoid infinite recursion)
#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.
~hls_div_cg_ext() override
Destructor.
Call graph hierarchy.
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.
#define CASE_TYPE_NODES
This macro collects all case labels for type objects.
Definition: tree_node.hpp:581
This file collects some utility functions.
tree_nodeRef CreateCallExpr(const tree_nodeConstRef &called_function, const std::vector< tree_nodeRef > &args, const std::string &srcp) const
Create a call_expr.
const unsigned int function_id
The index of the function to be analyzed.
const application_managerRef AppM
The application manager.
Class specification of the tree_reindex support class.
Class specification of the basic_block structure.
tree_nodeRef op0
The first operand of the Quaternary expression.
Definition: tree_node.hpp:1284
tree_nodeRef op0
The first operand of the ternary expression.
Definition: tree_node.hpp:1247
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.
#define THROW_ERROR_CODE(code, str_expr)
helper function used to throw an error with a code error
Definition: exceptions.hpp:266
Classes specification of the tree_node data structures not present in the gcc.
this class is used to manage the command-line or XML options.
#define CASE_CPP_NODES
This macro collects all case labels for cpp nodes.
Definition: tree_node.hpp:644
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.
static std::string GetFunctionName(const tree_managerConstRef &TM, const tree_nodeConstRef &decl)
Return the name of the function.
Wrapper to call graph.
static integer_cst_t GetConstValue(const tree_nodeConstRef &tn, bool is_signed=true)
Get value from integer constant.
int debug_level
The debug level.
#define GET_INDEX_CONST_NODE(t)
Definition: tree_node.hpp:363
tree_nodeRef op1
The second operand of the ternary expression.
Definition: tree_node.hpp:1250
This class creates a layer to add nodes and to manipulate the tree_nodes manager. ...
This class models the application of a analysis to all the functions of an application.
#define CASE_TERNARY_EXPRESSION
This macro collects all case labels for ternary_expr objects.
Definition: tree_node.hpp:550
tree_nodeRef op2
The third operand of the Quaternary expression.
Definition: tree_node.hpp:1290
Class specification of the manager of the tree structures extracted from the raw file.
HLS specialization of generic_device.
A brief description of the C++ Header File.
const FunctionBehaviorRef function_behavior
The function behavior of the function to be analyzed.
int sl
Definition: adpcm.c:105
#define CASE_PRAGMA_NODES
This macro collects all case labels for pragma objects.
Definition: tree_node.hpp:610
#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