PandA-2024.02
mux_connection_binding.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  */
48 
49 #include "Parameter.hpp"
50 #include "adder_conn_obj.hpp"
51 #include "allocation.hpp"
53 #include "behavioral_helper.hpp"
54 #include "commandport_obj.hpp"
55 #include "conn_binding.hpp"
56 #include "connection_obj.hpp"
57 #include "conv_conn_obj.hpp"
58 #include "cpu_time.hpp"
59 #include "dbgPrintHelper.hpp"
60 #include "direct_conn.hpp"
61 #include "fu_binding.hpp"
62 #include "function_behavior.hpp"
63 #include "funit_obj.hpp"
64 #include "graph.hpp"
65 #include "hls.hpp"
66 #include "hls_manager.hpp"
67 #include "liveness.hpp"
68 #include "memory.hpp"
69 #include "memory_symbol.hpp"
70 #include "multi_unbounded_obj.hpp"
71 #include "mux_conn.hpp"
72 #include "mux_obj.hpp"
73 #include "op_graph.hpp"
75 #include "reg_binding.hpp"
76 #include "register_obj.hpp"
80 #include "string_manipulation.hpp"
81 #include "technology_node.hpp"
82 #include "tree_helper.hpp"
83 #include "tree_manager.hpp"
84 #include "tree_reindex.hpp"
85 #include "utility.hpp"
86 
87 #define USE_ALIGNMENT_INFO 1
88 static unsigned int align_to_trimmed_bits(unsigned int algn)
89 {
90  if(algn == 8)
91  {
92  return 0;
93  }
94  else if(algn == 16)
95  {
96  return 1;
97  }
98  else if(algn == 32)
99  {
100  return 2;
101  }
102  else if(algn == 64)
103  {
104  return 3;
105  }
106  else if(algn == 128)
107  {
108  return 4;
109  }
110  else if(algn == 256)
111  {
112  return 5;
113  }
114  else
115  {
116  return 0;
117  }
118 }
119 
121  unsigned int _funId,
122  const DesignFlowManagerConstRef _design_flow_manager)
123  : conn_binding_creator(_parameters, _HLSMgr, _funId, _design_flow_manager,
125  id(0),
126  cur_phi_tree_var(0),
127  is_PC(false)
128 {
129  debug_level = _parameters->get_class_debug_level(GET_CLASS(*this));
130 }
131 
133 
135 {
138  regs_in.clear();
139  chained_in.clear();
140  module_in.clear();
141  swap_computed_table.clear();
142  noswap_computed_table.clear();
143  id = 0;
144  cur_phi_tree_var = 0;
145 }
146 
150 {
151  connCache.clear();
152  long step_time = 0;
154  {
155  START_TIME(step_time);
156  }
157 
159  auto mux = mux_interconnection();
160 
162  {
163  STOP_TIME(step_time);
164  }
165  if(mux)
166  {
168  {
170  }
172  "-->Connection Binding Information for function " +
173  HLSMgr->CGetFunctionBehavior(funId)->CGetBehavioralHelper()->get_function_name() + ":");
175  "---Number of allocated multiplexers (2-to-1 equivalent): " + std::to_string(mux));
177  "---Total number of bit-level multiplexers: " + STR(HLS->Rconn->determine_bit_level_mux()));
178 
180  {
182  "Time to perform interconnection binding: " + print_cpu_time(step_time) + " seconds");
183  }
184  else
185  {
186  HLS->Rconn->print();
187  }
190  {
192  }
193  }
194  connCache.clear();
197 }
198 
200  generic_objRef fu_obj, unsigned int port_num, unsigned int port_index,
201  unsigned int tree_var, unsigned int precision, bool is_not_a_phi)
202 {
203  const CustomOrderedSet<vertex>& running_states = HLS->Rliv->get_state_where_run(op);
204  for(const auto state : running_states)
205  {
206  if(GetPointer<register_obj>(fu_obj) && !is_not_a_phi)
207  {
208  const StateInfoConstRef state_info = is_PC ? StateInfoConstRef() : HLS->STG->GetStg()->CGetStateInfo(state);
209  if(state_info && state_info->is_duplicated && !state_info->all_paths)
210  {
211  bool found_branch = false;
212  const tree_managerRef TreeM = HLSMgr->get_tree_manager();
213  const auto gp =
214  GetPointer<const gimple_phi>(TreeM->get_tree_node_const(data->CGetOpNodeInfo(op)->GetNodeId()));
215  for(const auto& def_edge : gp->CGetDefEdgesList())
216  {
217  auto bbID = def_edge.second;
218  if(!state_info->isOriginalState && bbID != state_info->sourceBb)
219  {
220  continue;
221  }
222  else if(state_info->isOriginalState && bbID == state_info->sourceBb)
223  {
224  continue;
225  }
226  else if(state_info->moved_op_def_set.find(cur_phi_tree_var) != state_info->moved_op_def_set.end())
227  {
228  continue;
229  }
230  else if(def_edge.first->index != cur_phi_tree_var)
231  {
232  continue;
233  }
234  found_branch = true;
235  break;
236  }
237  if(!found_branch)
238  {
239  continue;
240  }
241  }
244  THROW_ASSERT(HLS->Rliv->has_state_in(state, op, cur_phi_tree_var), " no state in for @" + STR(tree_var));
245  const CustomOrderedSet<vertex>& states_in = HLS->Rliv->get_state_in(state, op, cur_phi_tree_var);
246  for(const auto stateIn : states_in)
247  {
248  HLS->Rconn->add_data_transfer(fu_obj_src, fu_obj, port_num, port_index,
249  data_transfer(tree_var, precision, stateIn, state, op));
252  " - add data transfer from "
253  << fu_obj_src->get_string() << " to " << fu_obj->get_string() << " port "
254  << std::to_string(port_num) << ":" << std::to_string(port_index) << " from state "
255  << HLS->Rliv->get_name(stateIn) + " to state " + HLS->Rliv->get_name(state) +
256  (tree_var ?
257  (" for " +
258  HLSMgr->CGetFunctionBehavior(funId)->CGetBehavioralHelper()->PrintVariable(tree_var)) :
259  ""));
260  generic_objRef enable_obj = GetPointer<register_obj>(fu_obj)->get_wr_enable();
261  GetPointer<commandport_obj>(enable_obj)
262  ->add_activation(commandport_obj::transition(
264  GetPointer<commandport_obj>(enable_obj)->set_phi_write_enable();
266  " - write enable for " + fu_obj->get_string() + " from state "
267  << HLS->Rliv->get_name(stateIn) + " to state " + HLS->Rliv->get_name(state));
268  }
269  }
270  else
271  {
272  HLS->Rconn->add_data_transfer(fu_obj_src, fu_obj, port_num, port_index,
273  data_transfer(tree_var, precision, state, NULL_VERTEX, op));
276  " - add data transfer from "
277  << fu_obj_src->get_string() << " to " << fu_obj->get_string() << " port " << std::to_string(port_num)
278  << ":" << std::to_string(port_index) << " in state "
279  << HLS->Rliv->get_name(state) +
280  (tree_var ?
281  (" for " +
282  HLSMgr->CGetFunctionBehavior(funId)->CGetBehavioralHelper()->PrintVariable(tree_var)) :
283  ""));
284  }
285  }
286 }
287 
288 unsigned int mux_connection_binding::address_precision(unsigned int precision, const vertex& op,
289  const OpGraphConstRef data, const tree_managerRef TreeM)
290 {
291  auto fu_type = HLS->Rfu->get_assign(op);
292  auto node_id = data->CGetOpNodeInfo(op)->GetNodeId();
293  const auto node = TreeM->CGetTreeNode(node_id);
294  const auto gm = GetPointer<const gimple_assign>(node);
295  bool right_addr_expr = false;
296  if(gm && GetPointer<const addr_expr>(GET_CONST_NODE(gm->op1)))
297  {
298  right_addr_expr = true;
299  }
300  bool is_load_store = GET_TYPE(data, op) & (TYPE_LOAD | TYPE_STORE);
301  if(!right_addr_expr && is_load_store && HLS->allocation_information->is_direct_access_memory_unit(fu_type))
302  {
303  unsigned var = HLS->allocation_information->is_memory_unit(fu_type) ?
306  if(var && HLSMgr->Rmem->is_private_memory(var))
307  {
308  unsigned long long int max_addr =
309  HLSMgr->Rmem->get_base_address(var, HLS->functionId) + tree_helper::Size(TreeM->CGetTreeReindex(var)) / 8;
310  unsigned int address_bitsize;
311  for(address_bitsize = 1; max_addr > (1ull << address_bitsize); ++address_bitsize)
312  {
313  ;
314  }
315  return address_bitsize;
316  }
317  }
318  return precision;
319 }
320 
321 bool mux_connection_binding::isConstantObj(unsigned int tree_index, const tree_managerRef TreeM)
322 {
323  if(tree_index == 0)
324  {
325  return true;
326  }
327  tree_nodeRef tn = TreeM->get_tree_node_const(tree_index);
328  if(GetPointer<integer_cst>(tn))
329  {
330  return true;
331  }
332  else
333  {
334  return false;
335  }
336 }
337 
339  generic_objRef fu_obj, unsigned int port_num, unsigned int port_index,
340  const OpGraphConstRef data, unsigned int precision,
341  unsigned int alignment)
342 {
343  bool is_not_a_phi = (GET_TYPE(data, op) & TYPE_PHI) == 0;
344  auto tree_var = std::get<0>(_var);
345  unsigned long long int constant_value = std::get<1>(_var);
346  auto bus_addr_bitsize = HLSMgr->get_address_bitsize();
347  bus_addr_bitsize = std::min(precision, bus_addr_bitsize);
348  memory_symbolRef m_sym;
349  const FunctionBehaviorConstRef FB = HLSMgr->CGetFunctionBehavior(funId);
350 
351  if(tree_var)
352  {
353  const tree_managerRef TreeM = HLSMgr->get_tree_manager();
354  tree_nodeRef tn = TreeM->GetTreeNode(tree_var);
355  switch(tn->get_kind())
356  {
357  case addr_expr_K:
358  {
359  auto* ae = GetPointer<addr_expr>(tn);
360  auto node_id = data->CGetOpNodeInfo(op)->GetNodeId();
361  const auto node = TreeM->CGetTreeNode(node_id);
362  auto* gm = GetPointer<const gimple_assign>(node);
363  const auto type = tree_helper::CGetType(ae->op);
364  if(type && GetPointer<const type_node>(GET_CONST_NODE(type)))
365  {
366 #if USE_ALIGNMENT_INFO
367  if(alignment)
368  {
369  alignment = std::min(alignment, GetPointer<const type_node>(GET_CONST_NODE(type))->algn);
370  }
371  else
372  {
373  alignment = GetPointer<const type_node>(GET_CONST_NODE(type))->algn;
374  }
375 #endif
376  }
377  if(gm && gm->temporary_address)
378  {
379  const auto ref_var = tree_helper::GetBaseVariable(gm->op0);
380  auto local_precision = bus_addr_bitsize;
381  if(FB->is_variable_mem(GET_INDEX_CONST_NODE(ref_var)))
382  {
383  unsigned long long int max_addr =
384  HLSMgr->Rmem->get_base_address(GET_INDEX_CONST_NODE(ref_var), HLS->functionId) +
385  tree_helper::Size(ref_var) / 8;
386  for(local_precision = 1; max_addr > (1ull << local_precision); ++local_precision)
387  {
388  ;
389  }
390  }
391  determine_connection(op, HLS_manager::io_binding_type(GET_INDEX_NODE(ae->op), 0), fu_obj, port_num,
392  port_index, data, local_precision, alignment);
393  }
394  else
395  {
396  determine_connection(op, HLS_manager::io_binding_type(GET_INDEX_NODE(ae->op), 0), fu_obj, port_num,
397  port_index, data, precision, alignment);
398  }
399  return;
400  }
401  case mem_ref_K:
402  {
403  auto* mr = GetPointer<mem_ref>(tn);
404  auto base_index = GET_INDEX_NODE(mr->op0);
407  "");
408  auto offset = static_cast<long long>(tree_helper::GetConstValue(mr->op1));
409  auto offset_index = offset ? GET_INDEX_NODE(mr->op1) : 0;
410  generic_objRef current_operand;
411  auto local_precision = address_precision(precision, op, data, TreeM);
412  if(offset_index)
413  {
414 #if USE_ALIGNMENT_INFO
415  const auto cost_val = offset;
416  alignment = std::min(static_cast<unsigned int>(8 * (cost_val & -cost_val)), alignment);
417 #endif
418  current_operand = generic_objRef(new adder_conn_obj("adder_conn_obj_" + STR(id++)));
419  GetPointer<adder_conn_obj>(current_operand)->add_bitsize(local_precision);
420  if(alignment)
421  {
422  GetPointer<adder_conn_obj>(current_operand)->set_trimmed_bits(align_to_trimmed_bits(alignment));
423  }
424  HLS->Rconn->add_sparse_logic(current_operand);
425  determine_connection(op, HLS_manager::io_binding_type(base_index, 0), current_operand, 0, 0, data,
426  local_precision, alignment);
427  determine_connection(op, HLS_manager::io_binding_type(offset_index, 0), current_operand, 1, 0, data,
428  local_precision, alignment);
429 
430  create_single_conn(data, op, current_operand, fu_obj, port_num, port_index, 0, local_precision,
431  is_not_a_phi);
432  }
433  else
434  {
435  determine_connection(op, HLS_manager::io_binding_type(base_index, 0), fu_obj, port_num, port_index, data,
436  local_precision, alignment);
437  }
438  return;
439  }
440  case string_cst_K:
441  case integer_cst_K:
442  case real_cst_K:
443  case vector_cst_K:
444  case void_cst_K:
445  case complex_cst_K:
446  case ssa_name_K:
447  case var_decl_K:
448  {
449  if(HLSMgr->Rmem->has_base_address(tree_var))
450  {
451  m_sym = HLSMgr->Rmem->get_symbol(tree_var, HLS->functionId);
452  constant_value = HLSMgr->Rmem->get_base_address(tree_var, HLS->functionId);
453  tree_var = 0;
454  precision = bus_addr_bitsize;
455  }
456  // else a direct connection is considered
457  break;
458  }
459  case function_decl_K:
460  {
461  m_sym = HLSMgr->Rmem->get_symbol(tree_var, tree_var);
462  constant_value = HLSMgr->Rmem->get_base_address(tree_var, tree_var);
463  tree_var = 0;
464  precision = bus_addr_bitsize;
465  break;
466  }
467  case indirect_ref_K:
468  case realpart_expr_K:
469  case imagpart_expr_K:
470  case parm_decl_K:
471  case view_convert_expr_K:
472  case bit_field_ref_K:
473  case constructor_K:
474  case misaligned_indirect_ref_K:
475  case abs_expr_K:
476  case alignof_expr_K:
477  case array_ref_K:
478  case arrow_expr_K:
479  case bit_not_expr_K:
480  case buffer_ref_K:
481  case card_expr_K:
482  case cleanup_point_expr_K:
483  case conj_expr_K:
484  case component_ref_K:
485  case convert_expr_K:
486  case exit_expr_K:
487  case fix_ceil_expr_K:
488  case fix_floor_expr_K:
489  case fix_round_expr_K:
490  case fix_trunc_expr_K:
491  case float_expr_K:
492  case loop_expr_K:
493  case lut_expr_K:
494  case negate_expr_K:
495  case non_lvalue_expr_K:
496  case nop_expr_K:
497  case reference_expr_K:
498  case reinterpret_cast_expr_K:
499  case sizeof_expr_K:
500  case static_cast_expr_K:
501  case throw_expr_K:
502  case truth_not_expr_K:
503  case unsave_expr_K:
504  case va_arg_expr_K:
505  case reduc_max_expr_K:
506  case reduc_min_expr_K:
507  case reduc_plus_expr_K:
508  case vec_unpack_hi_expr_K:
509  case vec_unpack_lo_expr_K:
510  case vec_unpack_float_hi_expr_K:
511  case vec_unpack_float_lo_expr_K:
512  case assert_expr_K:
513  case bit_and_expr_K:
514  case bit_ior_expr_K:
515  case bit_xor_expr_K:
516  case catch_expr_K:
517  case ceil_div_expr_K:
518  case ceil_mod_expr_K:
519  case complex_expr_K:
520  case compound_expr_K:
521  case eh_filter_expr_K:
522  case eq_expr_K:
523  case exact_div_expr_K:
524  case fdesc_expr_K:
525  case floor_div_expr_K:
526  case floor_mod_expr_K:
527  case ge_expr_K:
528  case gt_expr_K:
529  case goto_subroutine_K:
530  case in_expr_K:
531  case init_expr_K:
532  case le_expr_K:
533  case lrotate_expr_K:
534  case lshift_expr_K:
535  case lt_expr_K:
536  case max_expr_K:
537  case min_expr_K:
538  case minus_expr_K:
539  case modify_expr_K:
540  case mult_expr_K:
541  case mult_highpart_expr_K:
542  case ne_expr_K:
543  case ordered_expr_K:
544  case paren_expr_K:
545  case plus_expr_K:
546  case pointer_plus_expr_K:
547  case postdecrement_expr_K:
548  case postincrement_expr_K:
549  case predecrement_expr_K:
550  case preincrement_expr_K:
551  case range_expr_K:
552  case rdiv_expr_K:
553  case round_div_expr_K:
554  case round_mod_expr_K:
555  case rrotate_expr_K:
556  case rshift_expr_K:
557  case set_le_expr_K:
558  case target_mem_ref_K:
559  case target_mem_ref461_K:
560  case trunc_div_expr_K:
561  case trunc_mod_expr_K:
562  case truth_and_expr_K:
563  case truth_andif_expr_K:
564  case truth_or_expr_K:
565  case truth_orif_expr_K:
566  case truth_xor_expr_K:
567  case try_catch_expr_K:
568  case try_finally_K:
569  case uneq_expr_K:
570  case ltgt_expr_K:
571  case unge_expr_K:
572  case ungt_expr_K:
573  case unle_expr_K:
574  case unlt_expr_K:
575  case unordered_expr_K:
576  case widen_sum_expr_K:
577  case widen_mult_expr_K:
578  case with_size_expr_K:
579  case vec_lshift_expr_K:
580  case vec_rshift_expr_K:
581  case widen_mult_hi_expr_K:
582  case widen_mult_lo_expr_K:
583  case vec_cond_expr_K:
584  case vec_pack_trunc_expr_K:
585  case vec_pack_sat_expr_K:
586  case vec_pack_fix_trunc_expr_K:
587  case vec_perm_expr_K:
588  case vec_extracteven_expr_K:
589  case vec_extractodd_expr_K:
590  case vec_interleavehigh_expr_K:
591  case vec_interleavelow_expr_K:
592  case CASE_CPP_NODES:
593  case const_decl_K:
594  case field_decl_K:
595  case label_decl_K:
596  case namespace_decl_K:
597  case result_decl_K:
598  case translation_unit_decl_K:
599  case error_mark_K:
600  case using_decl_K:
601  case type_decl_K:
602  case template_decl_K:
603  case CASE_GIMPLE_NODES:
604  case call_expr_K:
605  case aggr_init_expr_K:
606  case case_label_expr_K:
607  case CASE_FAKE_NODES:
608  case CASE_PRAGMA_NODES:
609  case binfo_K:
610  case block_K:
611  case identifier_node_K:
612  case statement_list_K:
613  case tree_list_K:
614  case tree_vec_K:
615  case array_range_ref_K:
616  case target_expr_K:
617  case cond_expr_K:
618  case dot_prod_expr_K:
619  case ternary_plus_expr_K:
620  case ternary_pm_expr_K:
621  case ternary_mp_expr_K:
622  case ternary_mm_expr_K:
623  case fshl_expr_K:
624  case fshr_expr_K:
625  case bit_ior_concat_expr_K:
626  case obj_type_ref_K:
627  case save_expr_K:
628  case vtable_ref_K:
629  case with_cleanup_expr_K:
630  case extract_bit_expr_K:
631  case sat_plus_expr_K:
632  case sat_minus_expr_K:
633  case extractvalue_expr_K:
634  case insertvalue_expr_K:
635  case extractelement_expr_K:
636  case insertelement_expr_K:
637  case frem_expr_K:
638  case CASE_TYPE_NODES:
639  default:
640  THROW_ERROR("determine_connection pattern not supported: " + tn->get_kind_text() + " @" + STR(tree_var));
641  }
642  }
643  if(tree_var == 0)
644  {
646  THROW_ASSERT(precision, "a precision greater than 0 is expected");
647  auto string_value = convert_to_binary(constant_value, precision);
648  PRINT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, " - Constant value: " + STR(constant_value));
649  PRINT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, " - " + string_value);
650  std::string param_name;
651  if(m_sym)
652  {
653  param_name = m_sym->get_symbol_name();
654  PRINT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, " - param: " + param_name);
655  string_value = STR(m_sym->get_address());
656  }
657  const auto C_obj = HLS->Rconn->get_constant_obj(string_value, param_name, precision);
658  create_single_conn(data, op, C_obj, fu_obj, port_num, port_index, 0, precision, is_not_a_phi);
659  return;
660  }
661  const auto BH = FB->CGetBehavioralHelper();
662  if(BH->is_a_constant(tree_var))
663  {
664  THROW_ASSERT(precision, "a precision greater than 0 is expected: " + STR(precision));
665  const auto C_value = HLSMgr->get_constant_string(tree_var, precision);
666  const auto C_obj = HLS->Rconn->get_constant_obj(C_value, "", precision);
667  PRINT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, " - Tree constant value: " + BH->PrintVariable(tree_var));
669  create_single_conn(data, op, C_obj, fu_obj, port_num, port_index, tree_var, precision, is_not_a_phi);
670  return;
671  }
672  connect_to_registers(op, data, fu_obj, port_num, port_index, tree_var, precision, is_not_a_phi);
673 }
674 
675 unsigned int mux_connection_binding::extract_parm_decl(unsigned int tree_var, const tree_managerRef TreeM)
676 {
677  unsigned int base_index;
678  tree_nodeRef node = TreeM->get_tree_node_const(tree_var);
679  if(GetPointer<parm_decl>(node))
680  {
681  base_index = tree_var;
682  }
683  else
684  {
685  auto* sn = GetPointer<ssa_name>(node);
686  base_index = GET_INDEX_NODE(sn->var);
687  }
688  return base_index;
689 }
690 
692  unsigned int port_num, unsigned int port_index, unsigned int tree_var,
693  unsigned long long precision, const bool is_not_a_phi)
694 {
695  THROW_ASSERT(tree_var, "a non-null tree var is expected");
696  const tree_managerRef TreeM = HLSMgr->get_tree_manager();
697  const CustomOrderedSet<vertex>& running_states = HLS->Rliv->get_state_where_run(op);
698  last_intermediate_state fetch_previous(HLS->STG->GetStg(),
699  HLSMgr->CGetFunctionBehavior(funId)->is_simple_pipeline());
700  next_unique_state get_next(HLS->STG->GetStg());
701  for(const auto state : running_states)
702  {
703  unsigned int tree_var_state_in;
704  if(!is_not_a_phi)
705  {
706  THROW_ASSERT(not HLSMgr->GetFunctionBehavior(HLS->functionId)->is_simple_pipeline(),
707  "A pipelined function should not contain any phi operations");
708  const StateInfoConstRef state_info = is_PC ? StateInfoConstRef() : HLS->STG->GetStg()->CGetStateInfo(state);
709  if(state_info && state_info->is_duplicated && !state_info->all_paths)
710  {
711  bool found_branch = false;
712  const auto gp =
713  GetPointer<const gimple_phi>(TreeM->get_tree_node_const(data->CGetOpNodeInfo(op)->GetNodeId()));
714  for(const auto& def_edge : gp->CGetDefEdgesList())
715  {
716  auto bbID = def_edge.second;
717  if(!state_info->isOriginalState && bbID != state_info->sourceBb)
718  {
719  continue;
720  }
721  else if(state_info->isOriginalState && bbID == state_info->sourceBb)
722  {
723  continue;
724  }
725  else if(state_info->moved_op_def_set.find(cur_phi_tree_var) != state_info->moved_op_def_set.end())
726  {
727  continue;
728  }
729  else if(state_info->moved_op_use_set.find(gp->res->index) != state_info->moved_op_use_set.end())
730  {
731  continue;
732  }
733  else if(def_edge.first->index != cur_phi_tree_var)
734  {
735  continue;
736  }
737  found_branch = true;
738  break;
739  }
740  if(!found_branch)
741  {
742  continue;
743  }
744  }
745  tree_var_state_in = cur_phi_tree_var;
746  }
747  else
748  {
749  tree_var_state_in = tree_var;
750  }
751  THROW_ASSERT(HLS->Rliv->has_state_in(state, op, tree_var_state_in),
752  " no state in for @" + STR(tree_var_state_in) + " - " + (is_not_a_phi ? " not a phi" : "phi") +
753  " - " + HLS->Rliv->get_name(state) + " for op " + GET_NAME(data, op));
754  const CustomOrderedSet<vertex>& states_in = HLS->Rliv->get_state_in(state, op, tree_var_state_in);
755  for(const auto stateIn : states_in)
756  {
757  generic_objRef reg_obj;
758 
759  if(!is_not_a_phi)
760  {
761  THROW_ASSERT(not HLSMgr->GetFunctionBehavior(HLS->functionId)->is_simple_pipeline(),
762  "A pipelined function should not contain any phi operations");
763  vertex srcState = stateIn;
764  vertex lstate = state;
765  if(srcState == NULL_VERTEX)
766  {
767  std::swap(srcState, lstate);
768  }
769  if(tree_helper::is_parameter(TreeM, tree_var))
770  {
771  auto base_index = extract_parm_decl(tree_var, TreeM);
772  const generic_objRef fu_src_obj = input_ports[base_index];
773  THROW_ASSERT(fu_src_obj, "unexpected condition");
774  HLS->Rconn->add_data_transfer(fu_src_obj, fu_obj, port_num, port_index,
775  data_transfer(tree_var, precision, srcState, lstate, op));
778  " - add data transfer from primary input "
779  << fu_src_obj->get_string() << " to " << fu_obj->get_string() << " port "
780  << std::to_string(port_num) << ":" << std::to_string(port_index) << " from state "
781  << HLS->Rliv->get_name(srcState) + " to state " + HLS->Rliv->get_name(lstate) + " for " +
782  HLSMgr->CGetFunctionBehavior(funId)->CGetBehavioralHelper()->PrintVariable(tree_var));
783  }
784  else
785  {
786  vertex def_op = HLS->Rliv->get_op_where_defined(tree_var);
787  const CustomOrderedSet<vertex>& def_op_ending_states = HLS->Rliv->get_state_where_end(def_op);
788  if((GET_TYPE(data, def_op) & TYPE_PHI) == 0)
789  {
790  if(def_op_ending_states.find(srcState) != def_op_ending_states.end())
791  {
792  const generic_objRef fu_src_obj = HLS->Rfu->get(def_op);
793  HLS->Rconn->add_data_transfer(fu_src_obj, fu_obj, port_num, port_index,
794  data_transfer(tree_var, precision, srcState, lstate, op));
797  " - add data transfer from "
798  << fu_src_obj->get_string() << " to " << fu_obj->get_string() << " port "
799  << std::to_string(port_num) << ":" << std::to_string(port_index) << " from state "
800  << HLS->Rliv->get_name(srcState) + " to state " + HLS->Rliv->get_name(lstate) + " for " +
801  HLSMgr->CGetFunctionBehavior(funId)->CGetBehavioralHelper()->PrintVariable(
802  tree_var));
803  }
804  else if(HLS->storage_value_information->is_a_storage_value(fetch_previous(srcState, lstate),
805  tree_var))
806  {
808  fetch_previous(srcState, lstate), tree_var);
809  auto r_index = HLS->Rreg->get_register(storage_value);
812  " - register: "
813  << r_index << " from "
814  << HLS->Rliv->get_name(srcState) + " to state " + HLS->Rliv->get_name(lstate) + " for " +
815  HLSMgr->CGetFunctionBehavior(funId)->CGetBehavioralHelper()->PrintVariable(
816  tree_var));
817  reg_obj = HLS->Rreg->get(r_index);
818  if(reg_obj != fu_obj)
819  {
820  HLS->Rconn->add_data_transfer(reg_obj, fu_obj, port_num, port_index,
821  data_transfer(tree_var, precision, srcState, lstate, op));
824  " - add data transfer from "
825  << reg_obj->get_string() << " to " << fu_obj->get_string() << " port "
826  << std::to_string(port_num) << ":" << std::to_string(port_index) << " from state "
827  << HLS->Rliv->get_name(srcState) + " to state " + HLS->Rliv->get_name(lstate) +
828  " for " +
829  HLSMgr->CGetFunctionBehavior(funId)->CGetBehavioralHelper()->PrintVariable(
830  tree_var));
831  }
832  }
833  else
834  {
835  THROW_ERROR("not expected from " + HLS->Rliv->get_name(srcState) + " to " +
836  HLS->Rliv->get_name(lstate) + " " +
837  HLSMgr->CGetFunctionBehavior(funId)->CGetBehavioralHelper()->PrintVariable(tree_var));
838  }
839  }
840  else
841  {
842  THROW_ASSERT(
843  HLS->storage_value_information->is_a_storage_value(fetch_previous(srcState, lstate), tree_var),
844  "it has to be a register");
846  fetch_previous(srcState, lstate), tree_var);
847  auto r_index = HLS->Rreg->get_register(storage_value);
850  " - register: "
851  << r_index << " from "
852  << HLS->Rliv->get_name(srcState) + " to state " + HLS->Rliv->get_name(lstate) + " for " +
853  HLSMgr->CGetFunctionBehavior(funId)->CGetBehavioralHelper()->PrintVariable(tree_var));
854  reg_obj = HLS->Rreg->get(r_index);
855  if(reg_obj != fu_obj)
856  {
857  HLS->Rconn->add_data_transfer(reg_obj, fu_obj, port_num, port_index,
858  data_transfer(tree_var, precision, srcState, lstate, op));
861  " - add data transfer from "
862  << reg_obj->get_string() << " to " << fu_obj->get_string() << " port "
863  << std::to_string(port_num) << ":" << std::to_string(port_index) << " from state "
864  << HLS->Rliv->get_name(srcState) + " to state " + HLS->Rliv->get_name(lstate) + " for " +
865  HLSMgr->CGetFunctionBehavior(funId)->CGetBehavioralHelper()->PrintVariable(
866  tree_var));
867  }
868  }
869  }
870  if(GetPointer<register_obj>(fu_obj) && reg_obj != fu_obj)
871  {
872  generic_objRef enable_obj = GetPointer<register_obj>(fu_obj)->get_wr_enable();
873  GetPointer<commandport_obj>(enable_obj)
874  ->add_activation(
875  commandport_obj::transition(fetch_previous(srcState, lstate), lstate,
876  commandport_obj::data_operation_pair(tree_var_state_in, op)));
877  GetPointer<commandport_obj>(enable_obj)->set_phi_write_enable();
879  " - write enable for " + fu_obj->get_string() + " from state "
880  << HLS->Rliv->get_name(srcState) + " to state " + HLS->Rliv->get_name(lstate));
881  }
882  }
883  else
884  {
885  vertex tgt_state = stateIn;
886  if(tree_helper::is_parameter(TreeM, tree_var) &&
887  not HLSMgr->GetFunctionBehavior(HLS->functionId)->is_simple_pipeline())
888  {
889  auto base_index = extract_parm_decl(tree_var, TreeM);
890  const generic_objRef fu_src_obj = input_ports[base_index];
891  THROW_ASSERT(fu_src_obj, "unexpected condition");
892  HLS->Rconn->add_data_transfer(fu_src_obj, fu_obj, port_num, port_index,
893  data_transfer(tree_var, precision, state, tgt_state, op));
896  " - add data transfer from primary input "
897  << fu_src_obj->get_string() << " to " << fu_obj->get_string() << " port "
898  << std::to_string(port_num) << ":" << std::to_string(port_index) << " from state "
899  << HLS->Rliv->get_name(state) + " to state " + HLS->Rliv->get_name(tgt_state) + " for " +
900  HLSMgr->CGetFunctionBehavior(funId)->CGetBehavioralHelper()->PrintVariable(tree_var));
901  }
902  else if(tree_helper::is_parameter(TreeM, tree_var))
903  {
904  // Primary inputs need a dedicated register per each state if we
905  // want to preserve their values along pipeline steps
906  unsigned int storage_value;
907  unsigned int r_index;
908  auto tgt_port = port_num;
909  auto tgt_index = port_index;
910  vertex previous = fetch_previous(HLS->STG->get_entry_state(), tgt_state);
911  generic_objRef tgt_obj = fu_obj;
912  if(tgt_state != get_next(HLS->STG->get_entry_state()))
913  {
914  while(previous != get_next(HLS->STG->get_entry_state()))
915  {
917  "The chain of registers propagating a primary input is broken");
918  storage_value = HLS->storage_value_information->get_storage_value_index(previous, tree_var);
919  r_index = HLS->Rreg->get_register(storage_value);
920  reg_obj = HLS->Rreg->get(r_index);
921  HLS->Rconn->add_data_transfer(reg_obj, tgt_obj, tgt_port, tgt_index,
922  data_transfer(tree_var, precision, previous, tgt_state, op));
925  " - add data transfer from "
926  << reg_obj->get_string() << " to " << tgt_obj->get_string() << " port "
927  << std::to_string(tgt_port) << ":" << std::to_string(tgt_index) << " from state "
928  << HLS->Rliv->get_name(previous) + " to state " + HLS->Rliv->get_name(tgt_state) +
929  " for " +
930  HLSMgr->CGetFunctionBehavior(funId)->CGetBehavioralHelper()->PrintVariable(
931  tree_var));
932  THROW_ASSERT(reg_obj != tgt_obj, "There is a loop in the propagation chain");
933  tgt_state = previous;
934  previous = fetch_previous(HLS->STG->get_entry_state(), tgt_state);
935  tgt_obj = reg_obj;
936  tgt_port = 0;
937  tgt_index = 0;
938  }
939  }
940  auto base_index = extract_parm_decl(tree_var, TreeM);
941  const generic_objRef fu_src_obj = input_ports[base_index];
942  THROW_ASSERT(fu_src_obj, "unexpected condition");
943  HLS->Rconn->add_data_transfer(fu_src_obj, tgt_obj, tgt_port, port_index,
944  data_transfer(tree_var, precision, previous, tgt_state, op));
947  " - add data transfer from primary input "
948  << fu_src_obj->get_string() << " to " << tgt_obj->get_string() << " port "
949  << std::to_string(tgt_port) << ":" << std::to_string(port_index) << " from state "
950  << HLS->Rliv->get_name(previous) + " to state " + HLS->Rliv->get_name(tgt_state) + " for " +
951  HLSMgr->CGetFunctionBehavior(funId)->CGetBehavioralHelper()->PrintVariable(tree_var));
952  }
953  else
954  {
955  vertex def_op = HLS->Rliv->get_op_where_defined(tree_var);
956  const CustomOrderedSet<vertex>& def_op_ending_states = HLS->Rliv->get_state_where_end(def_op);
957  const StateInfoConstRef state_info =
958  is_PC ? StateInfoConstRef() : HLS->STG->GetStg()->CGetStateInfo(state);
959  if((GET_TYPE(data, def_op) & TYPE_PHI) == 0)
960  {
961  if(def_op_ending_states.find(state) != def_op_ending_states.end())
962  {
963  const generic_objRef fu_src_obj = HLS->Rfu->get(def_op);
964  HLS->Rconn->add_data_transfer(fu_src_obj, fu_obj, port_num, port_index,
965  data_transfer(tree_var, precision, state, tgt_state, op));
968  " - add data transfer from "
969  << fu_src_obj->get_string() << " to " << fu_obj->get_string() << " port "
970  << std::to_string(port_num) << ":" << std::to_string(port_index) << " from state "
971  << HLS->Rliv->get_name(state) + " to state " + HLS->Rliv->get_name(tgt_state) + " for " +
972  HLSMgr->CGetFunctionBehavior(funId)->CGetBehavioralHelper()->PrintVariable(
973  tree_var));
974  }
975  else if(HLS->storage_value_information->is_a_storage_value(fetch_previous(state, tgt_state),
976  tree_var))
977  {
979  fetch_previous(state, tgt_state), tree_var);
980  auto r_index = HLS->Rreg->get_register(storage_value);
983  " - register: "
984  << r_index << " from "
985  << HLS->Rliv->get_name(state) + " to state " + HLS->Rliv->get_name(tgt_state) + " for " +
986  HLSMgr->CGetFunctionBehavior(funId)->CGetBehavioralHelper()->PrintVariable(
987  tree_var));
988  reg_obj = HLS->Rreg->get(r_index);
989  THROW_ASSERT(
990  not(reg_obj == fu_obj && HLSMgr->GetFunctionBehavior(HLS->functionId)->is_simple_pipeline()),
991  "There can be no direct forwarding in pipelining");
992  if(reg_obj != fu_obj)
993  {
994  HLS->Rconn->add_data_transfer(reg_obj, fu_obj, port_num, port_index,
995  data_transfer(tree_var, precision, state, tgt_state, op));
998  " - add data transfer from "
999  << reg_obj->get_string() << " to " << fu_obj->get_string() << " port "
1000  << std::to_string(port_num) << ":" << std::to_string(port_index) << " from state "
1001  << HLS->Rliv->get_name(state) + " to state " + HLS->Rliv->get_name(tgt_state) +
1002  " for " +
1003  HLSMgr->CGetFunctionBehavior(funId)->CGetBehavioralHelper()->PrintVariable(
1004  tree_var));
1005  }
1006  }
1007  else
1008  {
1009  THROW_UNREACHABLE("not expected from " + HLS->Rliv->get_name(state) + " to " +
1010  HLS->Rliv->get_name(tgt_state) + " " +
1011  HLSMgr->get_tree_manager()->get_tree_node_const(tree_var)->ToString());
1012  }
1013  }
1014  else if(state_info && state_info->is_duplicated && state_info->clonedState != NULL_VERTEX &&
1015  !state_info->all_paths && def_op_ending_states.find(state) != def_op_ending_states.end() &&
1016  std::find(state_info->moved_exec_op.begin(), state_info->moved_exec_op.end(), op) ==
1017  state_info->moved_exec_op.end())
1018  {
1019  const auto gp = GetPointer<const gimple_phi>(
1020  TreeM->get_tree_node_const(data->CGetOpNodeInfo(def_op)->GetNodeId()));
1021  bool phi_postponed = false;
1022  unsigned int tree_temp = 0;
1023  for(const auto& def_edge : gp->CGetDefEdgesList())
1024  {
1025  auto bbID = def_edge.second;
1026  tree_temp = def_edge.first->index;
1027  if(bbID != state_info->sourceBb)
1028  {
1029  continue;
1030  }
1031  else if(state_info->moved_op_def_set.find(tree_temp) != state_info->moved_op_def_set.end())
1032  {
1033  phi_postponed = true;
1034  break;
1035  }
1036  else if(state_info->moved_op_use_set.find(tree_var) != state_info->moved_op_use_set.end())
1037  {
1038  phi_postponed = true;
1039  break;
1040  }
1041  else
1042  {
1043  break;
1044  }
1045  }
1047  "Is phi postponed? " + (phi_postponed ? std::string("YES") : std::string("NO")));
1048  if(phi_postponed)
1049  {
1050  // std::cerr << "phi postponed 0" << std::endl;
1051  generic_objRef fu_src_obj;
1052  if(state_info->moved_op_use_set.find(tree_var) != state_info->moved_op_use_set.end() &&
1053  state_info->moved_op_def_set.find(tree_temp) == state_info->moved_op_def_set.end())
1054  {
1055  auto src_storage_value = HLS->storage_value_information->get_storage_value_index(
1056  fetch_previous(state, tgt_state), tree_temp);
1057  auto src_r_index = HLS->Rreg->get_register(src_storage_value);
1058  fu_src_obj = HLS->Rreg->get(src_r_index);
1059  }
1060  else
1061  {
1062  vertex src_def_op = HLS->Rliv->get_op_where_defined(tree_temp);
1063  fu_src_obj = HLS->Rfu->get(src_def_op);
1064  }
1065  HLS->Rconn->add_data_transfer(fu_src_obj, fu_obj, port_num, port_index,
1066  data_transfer(tree_temp, precision, state, tgt_state, op));
1067  PRINT_DBG_MEX(
1069  " - add data transfer from "
1070  << fu_src_obj->get_string() << " to " << fu_obj->get_string() << " port "
1071  << std::to_string(port_num) << ":" << std::to_string(port_index) << " from state "
1072  << HLS->Rliv->get_name(state) + " to state " + HLS->Rliv->get_name(tgt_state) + " for " +
1073  HLSMgr->CGetFunctionBehavior(funId)->CGetBehavioralHelper()->PrintVariable(
1074  tree_temp));
1075  }
1076  else
1077  {
1078  THROW_ASSERT(
1079  HLS->storage_value_information->is_a_storage_value(fetch_previous(state, tgt_state), tree_var),
1080  "it has to be a register");
1081  auto storage_value = HLS->storage_value_information->get_storage_value_index(
1082  fetch_previous(state, tgt_state), tree_var);
1083  auto r_index = HLS->Rreg->get_register(storage_value);
1084  PRINT_DBG_MEX(
1086  " - register: "
1087  << r_index << " from "
1088  << HLS->Rliv->get_name(state) + " to state " + HLS->Rliv->get_name(tgt_state) + " for " +
1089  HLSMgr->CGetFunctionBehavior(funId)->CGetBehavioralHelper()->PrintVariable(
1090  tree_var));
1091  reg_obj = HLS->Rreg->get(r_index);
1092  if(reg_obj != fu_obj)
1093  {
1094  HLS->Rconn->add_data_transfer(reg_obj, fu_obj, port_num, port_index,
1095  data_transfer(tree_var, precision, state, tgt_state, op));
1096  PRINT_DBG_MEX(
1098  " - add data transfer from "
1099  << reg_obj->get_string() << " to " << fu_obj->get_string() << " port "
1100  << std::to_string(port_num) << ":" << std::to_string(port_index) << " from state "
1101  << HLS->Rliv->get_name(state) + " to state " + HLS->Rliv->get_name(tgt_state) +
1102  " for " +
1103  HLSMgr->CGetFunctionBehavior(funId)->CGetBehavioralHelper()->PrintVariable(
1104  tree_var));
1105  }
1106  }
1107  }
1108  else
1109  {
1110  THROW_ASSERT(
1111  HLS->storage_value_information->is_a_storage_value(fetch_previous(state, tgt_state), tree_var),
1112  "it has to be a register");
1113  auto storage_value = HLS->storage_value_information->get_storage_value_index(
1114  fetch_previous(state, tgt_state), tree_var);
1115  auto r_index = HLS->Rreg->get_register(storage_value);
1116  PRINT_DBG_MEX(
1118  " - register: "
1119  << r_index << " from "
1120  << HLS->Rliv->get_name(state) + " to state " + HLS->Rliv->get_name(tgt_state) + " for " +
1121  HLSMgr->CGetFunctionBehavior(funId)->CGetBehavioralHelper()->PrintVariable(tree_var));
1122  reg_obj = HLS->Rreg->get(r_index);
1123  if(reg_obj != fu_obj)
1124  {
1125  HLS->Rconn->add_data_transfer(reg_obj, fu_obj, port_num, port_index,
1126  data_transfer(tree_var, precision, state, tgt_state, op));
1127  PRINT_DBG_MEX(
1129  " - add data transfer from "
1130  << reg_obj->get_string() << " to " << fu_obj->get_string() << " port "
1131  << std::to_string(port_num) << ":" << std::to_string(port_index) << " from state "
1132  << HLS->Rliv->get_name(state) + " to state " + HLS->Rliv->get_name(tgt_state) + " for " +
1133  HLSMgr->CGetFunctionBehavior(funId)->CGetBehavioralHelper()->PrintVariable(
1134  tree_var));
1135  }
1136  }
1137  }
1138  }
1139  }
1140  if(HLSMgr->CGetFunctionBehavior(funId)->is_simple_pipeline())
1141  {
1142  vertex target;
1143  vertex previous;
1144  vertex def_op;
1145  vertex top;
1146  unsigned int origin_idx;
1147  unsigned int target_idx;
1148  unsigned int origin_reg_idx;
1149  unsigned int target_reg_idx;
1150  generic_objRef origin_reg;
1151  generic_objRef target_reg;
1153  for(auto& var : in_vars)
1154  {
1155  target = state;
1156  previous = fetch_previous(HLS->STG->get_entry_state(), target);
1157  def_op = HLS->Rliv->get_op_where_defined(var);
1158  THROW_ASSERT(HLS->Rliv->get_state_where_end(def_op).size() == 1,
1159  "A pipelined operation has more than one ending state");
1160  top = *HLS->Rliv->get_state_where_end(def_op).begin();
1161  THROW_ASSERT(target != top, "State defining a variable cannot have it as a live in variable");
1163  "There is a live in variable without any register");
1164  while(previous != top)
1165  {
1167  "There is a live in variable without any register");
1168  THROW_ASSERT(HLS->Rliv->get_live_in(previous).find(var) != HLS->Rliv->get_live_in(previous).end(),
1169  "The variable is not in live-in");
1170  THROW_ASSERT(HLS->Rliv->get_live_out(previous).find(var) != HLS->Rliv->get_live_out(previous).end(),
1171  "The variable is not in live-out");
1172  origin_idx = HLS->storage_value_information->get_storage_value_index(previous, var);
1173  target_idx = HLS->storage_value_information->get_storage_value_index(target, var);
1174  origin_reg_idx = HLS->Rreg->get_register(origin_idx);
1175  target_reg_idx = HLS->Rreg->get_register(target_idx);
1176  origin_reg = HLS->Rreg->get(origin_reg_idx);
1177  target_reg = HLS->Rreg->get(target_reg_idx);
1178  // Always add a data transfer on port 0 since it's always an input to reg_STD
1179  HLS->Rconn->add_data_transfer(origin_reg, target_reg, 0, 0,
1180  data_transfer(var, precision, previous, target, op));
1181  PRINT_DBG_MEX(
1183  " - add data transfer from "
1184  << origin_reg->get_string() << " to " << target_reg->get_string() << " port "
1185  << std::to_string(0) << ":" << std::to_string(0) << " from state "
1186  << HLS->Rliv->get_name(previous) + " to state " + HLS->Rliv->get_name(target) + " for " +
1187  HLSMgr->CGetFunctionBehavior(funId)->CGetBehavioralHelper()->PrintVariable(tree_var));
1188  target = previous;
1189  previous = fetch_previous(HLS->STG->get_entry_state(), target);
1190  }
1191  }
1192  }
1193  }
1194 }
1195 
1196 void mux_connection_binding::add_conversion(unsigned int num, vertex op, unsigned int form_par_type,
1197  unsigned long long form_par_bitsize, unsigned int port_index,
1198  const generic_objRef fu_obj, const OpGraphConstRef data,
1199  const tree_managerRef TreeM, unsigned int tree_var)
1200 {
1201  const HLS_manager::io_binding_type& varObj = HLS_manager::io_binding_type(tree_var, 0);
1202  const auto var = TreeM->CGetTreeReindex(tree_var);
1203  const auto parm = TreeM->CGetTreeReindex(form_par_type);
1204  const auto size_tree_var = tree_helper::Size(var);
1205  const auto inIP = tree_helper::IsSignedIntegerType(var);
1206  const auto inUP =
1208  const auto outIP = tree_helper::IsSignedIntegerType(parm);
1209  const auto outUP =
1211  THROW_ASSERT(((inIP || inUP) && (outIP || outUP)) || (!inIP && !inUP && !outIP && !outUP), "unexpected conversion");
1212  if(((inIP || inUP) && (outIP || outUP)) && (form_par_bitsize != size_tree_var))
1213  {
1214  generic_objRef conv_port;
1215  HLS_manager::check_bitwidth(form_par_bitsize);
1216  auto out_bitsize = static_cast<unsigned>(form_par_bitsize);
1217  auto ctype = uu_conv;
1218  if(inIP && outUP)
1219  {
1220  ctype = iu_conv;
1221  }
1222  else if(inIP && outIP)
1223  {
1224  ctype = ii_conv;
1225  }
1226  else if(inUP && outIP)
1227  {
1228  ctype = ui_conv;
1229  }
1230  auto key = std::make_tuple(out_bitsize, ctype, varObj);
1231  if(connCache.find(key) == connCache.end())
1232  {
1233  if(inIP && outUP)
1234  {
1235  conv_port = generic_objRef(new iu_conv_conn_obj("iu_conv_conn_obj_" + STR(id++)));
1236  GetPointer<iu_conv_conn_obj>(conv_port)->add_bitsize(out_bitsize);
1237  }
1238  else if(inIP && outIP)
1239  {
1240  conv_port = generic_objRef(new ii_conv_conn_obj("ii_conv_conn_obj_" + STR(id++)));
1241  GetPointer<ii_conv_conn_obj>(conv_port)->add_bitsize(out_bitsize);
1242  }
1243  else if(inUP && outUP)
1244  {
1245  conv_port = generic_objRef(new uu_conv_conn_obj("uu_conv_conn_obj_" + STR(id++)));
1246  GetPointer<uu_conv_conn_obj>(conv_port)->add_bitsize(out_bitsize);
1247  }
1248  else if(inUP && outIP)
1249  {
1250  conv_port = generic_objRef(new ui_conv_conn_obj("ui_conv_conn_obj_" + STR(id++)));
1251  GetPointer<ui_conv_conn_obj>(conv_port)->add_bitsize(out_bitsize);
1252  }
1253  else
1254  {
1255  THROW_ERROR("unexpected");
1256  }
1257  if(isConstantObj(std::get<0>(varObj), TreeM))
1258  {
1259  connCache[key] = conv_port;
1260  }
1261  HLS->Rconn->add_sparse_logic(conv_port);
1262  HLS_manager::check_bitwidth(size_tree_var);
1263  determine_connection(op, varObj, conv_port, 0, 0, data, static_cast<unsigned>(size_tree_var));
1264  }
1265  else
1266  {
1267  conv_port = connCache.find(key)->second;
1268  }
1269  auto is_not_a_phi = (GET_TYPE(data, op) & TYPE_PHI) == 0;
1270  create_single_conn(data, op, conv_port, fu_obj, num, port_index, tree_var, out_bitsize, is_not_a_phi);
1271  }
1272  else if(form_par_bitsize != size_tree_var)
1273  {
1274  generic_objRef conv_port = generic_objRef(new ff_conv_conn_obj("ff_conv_conn_obj_" + STR(id++)));
1275  if(parameters->isOption(OPT_soft_float) && parameters->getOption<bool>(OPT_soft_float))
1276  {
1277  technology_nodeRef current_fu;
1278  AllocationInformation::extract_bambu_provided_name(size_tree_var, form_par_bitsize, HLSMgr, current_fu);
1279  }
1280  HLS->Rconn->add_sparse_logic(conv_port);
1281  HLS_manager::check_bitwidth(form_par_bitsize);
1282  auto out_bitsize = static_cast<unsigned>(form_par_bitsize);
1283  HLS_manager::check_bitwidth(size_tree_var);
1284  GetPointer<ff_conv_conn_obj>(conv_port)->add_bitsize_in(static_cast<unsigned>(size_tree_var));
1285  GetPointer<ff_conv_conn_obj>(conv_port)->add_bitsize_out(out_bitsize);
1286  determine_connection(op, varObj, conv_port, 0, 0, data, static_cast<unsigned>(size_tree_var));
1287  auto is_not_a_phi = (GET_TYPE(data, op) & TYPE_PHI) == 0;
1288  create_single_conn(data, op, conv_port, fu_obj, num, port_index, tree_var, out_bitsize, is_not_a_phi);
1289  }
1290  else
1291  {
1292  HLS_manager::check_bitwidth(size_tree_var);
1293  determine_connection(op, varObj, fu_obj, num, port_index, data, static_cast<unsigned>(size_tree_var));
1294  }
1295 }
1296 
1298 {
1299  const auto TreeM = HLSMgr->get_tree_manager();
1300  const auto FB = HLSMgr->CGetFunctionBehavior(funId);
1301  const auto BH = FB->CGetBehavioralHelper();
1302  const auto data = FB->CGetOpGraph(FunctionBehavior::FDFG);
1303  const auto bus_addr_bitsize = HLSMgr->get_address_bitsize();
1304  const auto astg = HLS->STG->CGetAstg();
1305  if(parameters->getOption<int>(OPT_memory_banks_number) > 1 && !parameters->isOption(OPT_context_switch))
1306  {
1308  }
1309  else
1310  {
1312  }
1313 
1314  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "-->Starting execution of interconnection binding");
1315 
1316  for(const auto& state2mu : HLS->STG->get_mu_ctrls())
1317  {
1318  const auto& mu = state2mu.second;
1319  const auto mu_mod = mu->get_structural_obj();
1320  const auto mut = GetPointer<multi_unbounded_obj>(mu);
1321  const auto en_port =
1322  HLS->Rconn->bind_selector_port(conn_binding::IN, commandport_obj::MULTI_UNBOUNDED_ENABLE, mu, 0);
1323  mut->set_mu_enable(en_port);
1324  }
1325 
1326  const auto num_regs = HLS->Rreg->get_used_regs();
1327  for(auto r = 0U; r < num_regs; r++)
1328  {
1329  const auto reg_obj = HLS->Rreg->get(r);
1330  const auto sel_port = HLS->Rconn->bind_selector_port(conn_binding::IN, commandport_obj::WRENABLE, reg_obj, r);
1331  GetPointer<register_obj>(reg_obj)->set_wr_enable(sel_port);
1332  }
1333  for(const auto i : HLS->Rfu->get_allocation_list())
1334  {
1335  // number of instance functional unit i
1336  const auto num = HLS->Rfu->get_number(i);
1337  for(unsigned int fu_num = 0; fu_num < num; fu_num++)
1338  {
1339  // get the functional unit object associated to i and fu_num (id and index)
1340  const auto tmp_Fu = HLS->Rfu->get(i, fu_num);
1341  std::vector<technology_nodeRef> tmp_ops_node =
1342  GetPointer<functional_unit>(HLS->allocation_information->get_fu(i))->get_operations();
1343 
1344  if(tmp_ops_node.size() > 1)
1345  {
1346  // check all operations associated to functional unit tmp_Fu
1347  for(unsigned int oper = 0; oper < tmp_ops_node.size(); oper++)
1348  {
1349  const auto sel_port =
1350  HLS->Rconn->bind_selector_port(conn_binding::IN, commandport_obj::SELECTOR, tmp_Fu, oper);
1351  GetPointer<funit_obj>(tmp_Fu)->add_selector_op(sel_port, tmp_ops_node.at(oper)->get_name());
1352  }
1353  }
1354  }
1355  }
1356 
1359 
1360  BOOST_FOREACH(vertex op, boost::vertices(*data))
1361  {
1363  if(GET_TYPE(data, op) & TYPE_VPHI)
1364  {
1365  continue;
1366  }
1367  auto fu = HLS->Rfu->get_assign(op);
1368  auto idx = HLS->Rfu->get_index(op);
1369  auto n_channels = HLS->allocation_information->get_number_channels(fu);
1370  if((GET_TYPE(data, op) & TYPE_PHI) == 0)
1371  {
1372  unsigned int port_index = n_channels < 2 ? 0 : idx % n_channels;
1374  " * Operation: " + GET_NAME(data, op) << " " + data->CGetOpNodeInfo(op)->GetOperation());
1375  HLS->Rconn->bind_command_port(op, conn_binding::IN, commandport_obj::OPERATION, data);
1376 
1378  " - FU: " + HLS->allocation_information->get_fu_name(fu).first);
1380  const auto tmp_ops_node_size =
1381  GetPointer<functional_unit>(HLS->allocation_information->get_fu(fu))->get_operations().size();
1382  if(tmp_ops_node_size > 1U)
1383  {
1384  if(!GetPointer<funit_obj>(HLS->Rfu->get(fu, idx)))
1385  {
1386  THROW_ERROR("Functional unit " + HLS->allocation_information->get_string_name(fu) +
1387  " does not have an instance " + STR(idx));
1388  }
1389  const auto selector_obj =
1390  GetPointer<funit_obj>(HLS->Rfu->get(fu, idx))->GetSelector_op(data->CGetOpNodeInfo(op)->GetOperation());
1391  if(!selector_obj)
1392  {
1393  THROW_ERROR("Functional unit " + HLS->allocation_information->get_string_name(fu) +
1394  " does not have selector " + data->CGetOpNodeInfo(op)->GetOperation() + "(" + STR(idx) +
1395  ") Operation: " + STR(data->CGetOpNodeInfo(op)->GetNodeId()));
1396  }
1397  const CustomOrderedSet<vertex>& running_states = HLS->Rliv->get_state_where_run(op);
1398  for(const auto state : running_states)
1399  {
1400  bool is_starting_operation = std::find(astg->CGetStateInfo(state)->starting_operations.begin(),
1401  astg->CGetStateInfo(state)->starting_operations.end(),
1402  op) != astg->CGetStateInfo(state)->starting_operations.end();
1403  if(!(GET_TYPE(data, op) & (TYPE_LOAD | TYPE_STORE)) || is_starting_operation)
1404  {
1405  GetPointer<commandport_obj>(selector_obj)
1406  ->add_activation(
1409  " - add activation for " + selector_obj->get_string() + " in state "
1410  << HLS->Rliv->get_name(state));
1411  }
1412  }
1413  }
1414 
1415  const generic_objRef fu_obj = HLS->Rfu->get(op);
1416  std::vector<HLS_manager::io_binding_type> var_read = HLSMgr->get_required_values(HLS->functionId, op);
1417 #ifndef NDEBUG
1418  unsigned int index = 0;
1419 #endif
1420  for(auto& num : var_read)
1421  {
1422  if(std::get<0>(num) == 0)
1423  {
1425  " - " << index << ". Read: " + STR(std::get<1>(num)));
1426  }
1427  else
1428  {
1430  " - " << index << ". Read: " + BH->PrintVariable(std::get<0>(num)));
1431  }
1432 #ifndef NDEBUG
1433  ++index;
1434 #endif
1435  }
1436  if(GET_TYPE(data, op) & (TYPE_LOAD | TYPE_STORE))
1437  {
1438  auto node_id = data->CGetOpNodeInfo(op)->GetNodeId();
1439  const tree_nodeRef node = TreeM->get_tree_node_const(node_id);
1440  auto* gm = GetPointer<gimple_assign>(node);
1441  THROW_ASSERT(gm, "only gimple_assign's are allowed as memory operations");
1442 
1445  {
1446  unsigned int alignment = 0;
1447  tree_nodeRef var_node;
1448  unsigned int size_var;
1449  tree_nodeConstRef tn;
1450  unsigned int var_node_idx;
1451  unsigned long long Prec = 0;
1452  const auto type = tree_helper::CGetType(gm->op0);
1453  if(type && (GET_CONST_NODE(type)->get_kind() == integer_type_K))
1454  {
1455  Prec = GetPointerS<const integer_type>(GET_CONST_NODE(type))->prec;
1456  }
1457  else if(type && (GET_CONST_NODE(type)->get_kind() == boolean_type_K))
1458  {
1459  Prec = 8;
1460  }
1461  else if(type && (GET_CONST_NODE(type)->get_kind() == enumeral_type_K))
1462  {
1463  Prec = GetPointerS<const enumeral_type>(GET_CONST_NODE(type))->prec;
1464  }
1465  unsigned int algn = 0;
1466  if(type && (GET_CONST_NODE(type)->get_kind() == integer_type_K))
1467  {
1468  algn = GetPointerS<const integer_type>(GET_CONST_NODE(type))->algn;
1469  }
1470  else if(type && (GET_CONST_NODE(type)->get_kind() == boolean_type_K))
1471  {
1472  algn = 8;
1473  }
1474 #if USE_ALIGNMENT_INFO
1475  if(type && GetPointer<const type_node>(GET_CONST_NODE(type)))
1476  {
1477  algn = alignment = GetPointerS<const type_node>(GET_CONST_NODE(type))->algn;
1478  }
1479 #endif
1480  if(GET_TYPE(data, op) & TYPE_STORE)
1481  {
1482  size_var = std::get<0>(var_read[0]);
1483  tn = tree_helper::CGetType(TreeM->CGetTreeReindex(size_var));
1484  var_node = GET_NODE(gm->op0);
1485  var_node_idx = GET_INDEX_NODE(gm->op0);
1486 
1487  if(size_var)
1488  {
1489  THROW_ASSERT(
1490  tree_helper::GetConstValue(GetPointerS<const type_node>(GET_CONST_NODE(tn))->size) >= 0, "");
1491  const auto IR_var_bitsize = static_cast<unsigned int>(
1492  tree_helper::GetConstValue(GetPointerS<const type_node>(GET_CONST_NODE(tn))->size));
1493  unsigned int var_bitsize;
1494  if(Prec != algn && Prec % algn)
1495  {
1497  var_bitsize = static_cast<unsigned int>(Prec);
1498  }
1499  else
1500  {
1501  HLS_manager::check_bitwidth(IR_var_bitsize);
1502  var_bitsize = IR_var_bitsize;
1503  }
1504  generic_objRef conv_port;
1505  auto varObj = var_read[0];
1506  if(tree_helper::is_int(TreeM, size_var))
1507  {
1508  auto key = std::make_tuple(var_bitsize, iu_conv, varObj);
1509  if(connCache.find(key) == connCache.end())
1510  {
1511  conv_port = generic_objRef(new iu_conv_conn_obj("iu_conv_conn_obj_" + STR(id++)));
1512  if(isConstantObj(std::get<0>(varObj), TreeM))
1513  {
1514  connCache[key] = conv_port;
1515  }
1516  HLS->Rconn->add_sparse_logic(conv_port);
1517  GetPointer<iu_conv_conn_obj>(conv_port)->add_bitsize(var_bitsize);
1518  determine_connection(op, varObj, conv_port, 0, 0, data, var_bitsize);
1519  }
1520  else
1521  {
1522  conv_port = connCache.find(key)->second;
1523  }
1524  }
1525  else
1526  {
1527  auto key = std::make_tuple(var_bitsize, uu_conv, varObj);
1528  if(connCache.find(key) == connCache.end())
1529  {
1530  conv_port = generic_objRef(new uu_conv_conn_obj("uu_conv_conn_obj_" + STR(id++)));
1531  if(isConstantObj(std::get<0>(varObj), TreeM))
1532  {
1533  connCache[key] = conv_port;
1534  }
1535  HLS->Rconn->add_sparse_logic(conv_port);
1536  GetPointer<uu_conv_conn_obj>(conv_port)->add_bitsize(var_bitsize);
1537  determine_connection(op, varObj, conv_port, 0, 0, data, var_bitsize);
1538  }
1539  else
1540  {
1541  conv_port = connCache.find(key)->second;
1542  }
1543  }
1544  create_single_conn(data, op, conv_port, fu_obj, 0, port_index, size_var, var_bitsize, true);
1545  }
1546  else
1547  {
1548  auto prec = object_bitsize(TreeM, var_read[0]);
1550  determine_connection(op, var_read[0], fu_obj, 0, port_index, data, static_cast<unsigned>(prec));
1551  }
1552  }
1553  else
1554  {
1555  size_var = HLSMgr->get_produced_value(HLS->functionId, op);
1556  tn = tree_helper::CGetType(TreeM->CGetTreeReindex(size_var));
1557  var_node = GET_NODE(gm->op1);
1558  var_node_idx = GET_INDEX_NODE(gm->op1);
1559  }
1560 #ifndef NDEBUG
1561  if(var_node->get_kind() == ssa_name_K)
1562  {
1563  THROW_ASSERT(GET_CONST_NODE(tree_helper::CGetType(var_node))->get_kind() == complex_type_K,
1564  "only complex objects are considered");
1565  }
1566 #endif
1567  auto is_dual = HLS->allocation_information->is_dual_port_memory(fu);
1568  auto port_offset = [&](unsigned pi) -> unsigned int {
1569  if(is_dual)
1570  {
1571  return (GET_TYPE(data, op) & TYPE_LOAD) ? pi * 2 - 1 : pi * 2;
1572  }
1573  else
1574  {
1575  return pi;
1576  }
1577  };
1578 
1579  THROW_ASSERT(!gm->predicate || tree_helper::Size(gm->predicate) == 1, STR(gm->predicate));
1580  auto var = gm->predicate ? HLS_manager::io_binding_type(gm->predicate->index, 0) :
1583  determine_connection(op, var, fu_obj, port_offset(3), port_index, data, 1);
1584 
1585  THROW_ASSERT(var_node->get_kind() == mem_ref_K, "MEMORY REFERENCE/LOAD-STORE type not supported: " +
1586  var_node->get_kind_text() + " " + STR(node_id));
1587 
1589  determine_connection(op, HLS_manager::io_binding_type(var_node_idx, 0), fu_obj, port_offset(1),
1590  port_index, data, bus_addr_bitsize, alignment);
1592  if(Prec != algn && Prec % algn)
1593  {
1596  op, HLS_manager::io_binding_type(0, Prec), fu_obj, port_offset(2), port_index, data,
1597  static_cast<unsigned>(object_bitsize(TreeM, HLS_manager::io_binding_type(0, Prec))));
1598  }
1599  else
1600  {
1601  const auto IR_var_bitsize = Prec != 0 ? Prec : tree_helper::Size(tn);
1602  HLS_manager::check_bitwidth(IR_var_bitsize);
1603  unsigned int var_bitsize;
1604  var_bitsize = static_cast<unsigned int>(IR_var_bitsize);
1606  op, HLS_manager::io_binding_type(0, var_bitsize), fu_obj, port_offset(2), port_index, data,
1607  static_cast<unsigned>(object_bitsize(TreeM, HLS_manager::io_binding_type(0, var_bitsize))));
1608  }
1609  }
1610  else
1611  {
1612  THROW_ERROR("Unit " + HLS->allocation_information->get_fu_name(fu).first + " not supported");
1613  }
1614  }
1615  else if(data->CGetOpNodeInfo(op)->GetOperation() == MULTI_READ_COND)
1616  {
1617  PRINT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, " - " << var_read.size() << " reads");
1618  for(unsigned int num = 0; num < var_read.size(); num++)
1619  {
1620  auto prec = object_bitsize(TreeM, var_read[num]);
1622  determine_connection(op, var_read[num], fu_obj, 0, num, data, static_cast<unsigned>(prec));
1623  }
1624  }
1625  else
1626  {
1627  PRINT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, " - " << var_read.size() << " reads");
1628  tree_nodeConstRef first_valid;
1629  if(HLS->Rfu->get_ports_are_swapped(op))
1630  {
1631  THROW_ASSERT(var_read.size() == 2, "unexpected condition");
1632  std::swap(var_read[0], var_read[1]);
1633  }
1634  for(unsigned int port_num = 0; port_num < var_read.size(); port_num++)
1635  {
1636  const auto tree_var = std::get<0>(var_read[port_num]);
1637  const auto tree_var_node = tree_var == 0 ? nullptr : TreeM->CGetTreeReindex(tree_var);
1638  const auto& node = data->CGetOpNodeInfo(op)->node;
1639  const auto form_par_type = tree_helper::GetFormalIth(node, port_num);
1640  auto size_form_par = form_par_type ? tree_helper::Size(form_par_type) : 0;
1641  const auto OperationType = data->CGetOpNodeInfo(op)->GetOperation();
1642  if(tree_var && !first_valid)
1643  {
1644  first_valid = tree_var_node;
1645  }
1646  if((OperationType == "cond_expr" || OperationType == "vec_cond_expr") && port_num != 0 && tree_var)
1647  {
1648  first_valid = tree_var_node;
1649  }
1650 
1651  if(tree_var == 0)
1652  {
1654  " - " << port_num << ". Read: " + STR(std::get<1>(var_read[port_num])));
1655  }
1656  else
1657  {
1659  " - " << port_num << ". Read: " + BH->PrintVariable(tree_var));
1661  " * " + GET_CONST_NODE(tree_var_node)->get_kind_text());
1663  " * bitsize " + STR(object_bitsize(TreeM, var_read[port_num])));
1664  }
1665  if(tree_var && HLSMgr->Rmem->is_actual_parm_loaded(tree_var))
1666  {
1667  THROW_ERROR("LOADING of actual parameter not yet implemented");
1668  }
1669  else if(form_par_type && tree_var &&
1670  ((tree_helper::IsSignedIntegerType(tree_var_node) &&
1671  (tree_helper::IsUnsignedIntegerType(form_par_type) ||
1672  tree_helper::IsBooleanType(form_par_type))) ||
1673  ((tree_helper::IsUnsignedIntegerType(tree_var_node) ||
1674  (tree_helper::IsBooleanType(form_par_type))) &&
1675  tree_helper::IsSignedIntegerType(form_par_type)) ||
1676  (tree_helper::IsRealType(tree_var_node) && tree_helper::IsRealType(form_par_type))))
1677  {
1678  add_conversion(port_num, op, form_par_type->index, size_form_par, port_index, fu_obj, data, TreeM,
1679  tree_var);
1680  }
1681  else if(first_valid && tree_var && first_valid->index != tree_var_node->index && !form_par_type &&
1682  OperationType != "rshift_expr" && OperationType != "lshift_expr" &&
1683  OperationType != "extract_bit_expr" && OperationType != "rrotate_expr" &&
1684  OperationType != "lrotate_expr" &&
1685  ((tree_helper::IsSignedIntegerType(tree_var_node) &&
1686  tree_helper::IsUnsignedIntegerType(first_valid)) ||
1687  (tree_helper::IsUnsignedIntegerType(tree_var_node) &&
1688  tree_helper::IsSignedIntegerType(first_valid))))
1689  {
1690  // we only need type conversion and not size conversion, so we pass the same size for both
1691  size_form_par = tree_helper::Size(tree_var_node);
1692  add_conversion(port_num, op, first_valid->index, size_form_par, port_index, fu_obj, data, TreeM,
1693  tree_var);
1694  }
1695  else
1696  {
1697  auto prec = object_bitsize(TreeM, var_read[port_num]);
1699  determine_connection(op, var_read[port_num], fu_obj, port_num, port_index, data,
1700  static_cast<unsigned>(prec));
1701  }
1702  }
1703  }
1704  }
1705 
1706  if(GET_TYPE(data, op) & TYPE_PHI)
1707  {
1709  auto var_written = HLSMgr->get_produced_value(HLS->functionId, op);
1710  CustomOrderedSet<unsigned int> source_already_analyzed;
1711  const CustomOrderedSet<vertex>& ending_states = HLS->Rliv->get_state_where_end(op);
1712  THROW_ASSERT(ending_states.size() == 1 || is_PC ||
1713  HLS->STG->GetStg()->CGetStateInfo(*ending_states.begin())->is_duplicated,
1714  "phis cannot run in more than one state");
1715  for(const auto estate : ending_states)
1716  {
1717  const StateInfoConstRef state_info =
1718  is_PC ? StateInfoConstRef() : HLS->STG->GetStg()->CGetStateInfo(estate);
1719  const auto gp =
1720  GetPointer<const gimple_phi>(TreeM->get_tree_node_const(data->CGetOpNodeInfo(op)->GetNodeId()));
1721  for(const auto& def_edge : gp->CGetDefEdgesList())
1722  {
1723  auto tree_temp = def_edge.first->index;
1725  "Pre-Managing phi operation " + GET_NAME(data, op) + " ending in state " +
1726  HLS->Rliv->get_name(estate) +
1727  (tree_temp ? " for variable " + def_edge.first->ToString() : ""));
1728  bool phi_postponed = false;
1729  if(state_info && state_info->is_duplicated && !state_info->all_paths)
1730  {
1731  auto bbID = def_edge.second;
1732  if(!state_info->isOriginalState && bbID != state_info->sourceBb)
1733  {
1734  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Not original state and not source BB");
1735  continue;
1736  }
1737  else if(state_info->isOriginalState && bbID == state_info->sourceBb)
1738  {
1739  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Original state and source BB");
1740  continue;
1741  }
1742  else if(state_info->moved_op_def_set.find(tree_temp) != state_info->moved_op_def_set.end())
1743  {
1744  phi_postponed = true;
1745  }
1746  else if(state_info->moved_op_use_set.find(var_written) != state_info->moved_op_use_set.end())
1747  {
1748  phi_postponed = true;
1749  }
1750  }
1752  "Is phi postponed? " + (phi_postponed ? std::string("YES") : std::string("NO")));
1753  if(!phi_postponed)
1754  {
1755  if(source_already_analyzed.find(tree_temp) == source_already_analyzed.end())
1756  {
1757  source_already_analyzed.insert(tree_temp);
1758  }
1759  else
1760  {
1761  continue;
1762  }
1763  }
1764  cur_phi_tree_var = tree_temp;
1766  "Pre-Managing phi operation2 " + GET_NAME(data, op) + " ending in state " +
1767  HLS->Rliv->get_name(estate) +
1768  (cur_phi_tree_var ? " for variable " + BH->PrintVariable(cur_phi_tree_var) : ""));
1769  THROW_ASSERT(cur_phi_tree_var, "something wrong happened");
1770  THROW_ASSERT(!HLSMgr->Rmem->has_base_address(tree_temp),
1771  "phi cannot manage memory objects: @" + STR(tree_temp));
1772  THROW_ASSERT(!HLSMgr->Rmem->has_base_address(var_written),
1773  "phi cannot manage memory objects: @" + STR(var_written));
1774  THROW_ASSERT(TreeM->CGetTreeNode(tree_temp)->get_kind() != array_ref_K, "unexpected phi use");
1775  THROW_ASSERT(TreeM->CGetTreeNode(tree_temp)->get_kind() != indirect_ref_K, "unexpected phi use");
1776  THROW_ASSERT(TreeM->CGetTreeNode(tree_temp)->get_kind() != misaligned_indirect_ref_K,
1777  "unexpected phi use");
1778 
1780  "Managing phi operation " + GET_NAME(data, op) + " ending in state " +
1781  HLS->Rliv->get_name(estate) +
1782  (cur_phi_tree_var ? " for variable " + BH->PrintVariable(cur_phi_tree_var) : ""));
1783  if(HLS->storage_value_information->is_a_storage_value(estate, var_written))
1784  {
1785  auto storage_value = HLS->storage_value_information->get_storage_value_index(estate, var_written);
1786  auto r_index = HLS->Rreg->get_register(storage_value);
1787  auto in_bitsize = object_bitsize(TreeM, HLS_manager::io_binding_type(tree_temp, 0));
1788  HLS_manager::check_bitwidth(in_bitsize);
1789  auto out_bitsize = object_bitsize(TreeM, HLS_manager::io_binding_type(var_written, 0));
1790  HLS_manager::check_bitwidth(out_bitsize);
1791  generic_objRef tgt_reg_obj = HLS->Rreg->get(r_index);
1792  THROW_ASSERT(
1793  tree_helper::IsSameType(TreeM->CGetTreeNode(tree_temp), TreeM->CGetTreeNode(var_written)),
1794  "conversion required");
1795  if(phi_postponed)
1796  {
1797  if(HLS->Rliv->has_state_out(estate, op, var_written))
1798  {
1799  if(in_bitsize != out_bitsize)
1800  {
1801  if(tree_helper::is_unsigned(TreeM, var_written) ||
1802  tree_helper::is_a_pointer(TreeM, var_written) || tree_helper::is_bool(TreeM, var_written))
1803  {
1804  generic_objRef conv_port =
1805  generic_objRef(new u_assign_conn_obj("u_assign_conn_obj_" + STR(id++)));
1806  HLS->Rconn->add_sparse_logic(conv_port);
1807  GetPointer<u_assign_conn_obj>(conv_port)->add_bitsize(static_cast<unsigned>(in_bitsize));
1808  generic_objRef fu_src_obj;
1809  if(state_info &&
1810  state_info->moved_op_use_set.find(var_written) != state_info->moved_op_use_set.end() &&
1811  state_info->moved_op_def_set.find(cur_phi_tree_var) ==
1812  state_info->moved_op_def_set.end())
1813  {
1814  auto src_storage_value =
1816  auto src_r_index = HLS->Rreg->get_register(src_storage_value);
1817  fu_src_obj = HLS->Rreg->get(src_r_index);
1818  }
1819  else
1820  {
1822  fu_src_obj = HLS->Rfu->get(src_def_op);
1823  }
1824  const CustomOrderedSet<vertex>& states_out =
1825  HLS->Rliv->get_state_out(estate, op, var_written);
1826  for(const auto state_out : states_out)
1827  {
1828  HLS->Rconn->add_data_transfer(fu_src_obj, conv_port, 0, 0,
1830  static_cast<unsigned>(in_bitsize), estate,
1831  state_out, op));
1832  HLS->Rconn->add_data_transfer(conv_port, tgt_reg_obj, 0, 0,
1834  static_cast<unsigned>(in_bitsize), estate,
1835  state_out, op));
1837  " - add data transfer from "
1838  << fu_src_obj->get_string() << " to " << conv_port->get_string()
1839  << " port 0:0 from state "
1840  << HLS->Rliv->get_name(estate) + " to state " +
1841  HLS->Rliv->get_name(state_out) + " for " +
1842  HLSMgr->CGetFunctionBehavior(funId)
1843  ->CGetBehavioralHelper()
1844  ->PrintVariable(cur_phi_tree_var));
1845  generic_objRef enable_obj = GetPointer<register_obj>(tgt_reg_obj)->get_wr_enable();
1846  GetPointer<commandport_obj>(enable_obj)
1847  ->add_activation(commandport_obj::transition(
1848  estate, state_out,
1851  " - write enable for " + tgt_reg_obj->get_string() + " from "
1852  << HLS->Rliv->get_name(estate) + " to state " +
1853  HLS->Rliv->get_name(state_out));
1854  }
1855  }
1856  else if(tree_helper::is_int(TreeM, var_written))
1857  {
1858  generic_objRef conv_port =
1859  generic_objRef(new i_assign_conn_obj("i_assign_conn_obj_phi" + STR(id++)));
1860  HLS->Rconn->add_sparse_logic(conv_port);
1861  GetPointer<i_assign_conn_obj>(conv_port)->add_bitsize(static_cast<unsigned>(in_bitsize));
1862  generic_objRef fu_src_obj;
1863  if(state_info &&
1864  state_info->moved_op_use_set.find(var_written) != state_info->moved_op_use_set.end() &&
1865  state_info->moved_op_def_set.find(cur_phi_tree_var) ==
1866  state_info->moved_op_def_set.end())
1867  {
1868  auto src_storage_value =
1870  auto src_r_index = HLS->Rreg->get_register(src_storage_value);
1871  fu_src_obj = HLS->Rreg->get(src_r_index);
1872  }
1873  else
1874  {
1876  fu_src_obj = HLS->Rfu->get(src_def_op);
1877  }
1878 
1879  const CustomOrderedSet<vertex>& states_out =
1880  HLS->Rliv->get_state_out(estate, op, var_written);
1881  const CustomOrderedSet<vertex>::const_iterator s_out_it_end = states_out.end();
1882  for(auto s_out_it = states_out.begin(); s_out_it != s_out_it_end; ++s_out_it)
1883  {
1884  HLS->Rconn->add_data_transfer(fu_src_obj, conv_port, 0, 0,
1886  static_cast<unsigned>(in_bitsize), estate,
1887  *s_out_it, op));
1888  HLS->Rconn->add_data_transfer(conv_port, tgt_reg_obj, 0, 0,
1890  static_cast<unsigned>(in_bitsize), estate,
1891  *s_out_it, op));
1893  " - add data transfer from "
1894  << fu_src_obj->get_string() << " to " << conv_port->get_string()
1895  << " port 0:0 from state "
1896  << HLS->Rliv->get_name(estate) + " to state " +
1897  HLS->Rliv->get_name(*s_out_it) + " for " +
1898  HLSMgr->CGetFunctionBehavior(funId)
1899  ->CGetBehavioralHelper()
1900  ->PrintVariable(cur_phi_tree_var));
1901  generic_objRef enable_obj = GetPointer<register_obj>(tgt_reg_obj)->get_wr_enable();
1902  GetPointer<commandport_obj>(enable_obj)
1903  ->add_activation(commandport_obj::transition(
1904  estate, *s_out_it,
1907  " - write enable for " + tgt_reg_obj->get_string() + " from "
1908  << HLS->Rliv->get_name(estate) + " to state " +
1909  HLS->Rliv->get_name(*s_out_it));
1910  }
1911  }
1912  else if(tree_helper::is_real(TreeM, var_written))
1913  {
1914  generic_objRef conv_port =
1915  generic_objRef(new f_assign_conn_obj("f_assign_conn_obj_" + STR(id++)));
1916  HLS->Rconn->add_sparse_logic(conv_port);
1917  GetPointer<f_assign_conn_obj>(conv_port)->add_bitsize(static_cast<unsigned>(in_bitsize));
1918  generic_objRef fu_src_obj;
1919  if(state_info &&
1920  state_info->moved_op_use_set.find(var_written) != state_info->moved_op_use_set.end() &&
1921  state_info->moved_op_def_set.find(cur_phi_tree_var) ==
1922  state_info->moved_op_def_set.end())
1923  {
1924  auto src_storage_value =
1926  auto src_r_index = HLS->Rreg->get_register(src_storage_value);
1927  fu_src_obj = HLS->Rreg->get(src_r_index);
1928  }
1929  else
1930  {
1932  fu_src_obj = HLS->Rfu->get(src_def_op);
1933  }
1934 
1935  const CustomOrderedSet<vertex>& states_out =
1936  HLS->Rliv->get_state_out(estate, op, var_written);
1937  const CustomOrderedSet<vertex>::const_iterator s_out_it_end = states_out.end();
1938  for(auto s_out_it = states_out.begin(); s_out_it != s_out_it_end; ++s_out_it)
1939  {
1940  HLS->Rconn->add_data_transfer(fu_src_obj, conv_port, 0, 0,
1942  static_cast<unsigned>(in_bitsize), estate,
1943  *s_out_it, op));
1944  HLS->Rconn->add_data_transfer(conv_port, tgt_reg_obj, 0, 0,
1946  static_cast<unsigned>(in_bitsize), estate,
1947  *s_out_it, op));
1949  " - add data transfer from "
1950  << fu_src_obj->get_string() << " to " << conv_port->get_string()
1951  << " port 0:0 from state "
1952  << HLS->Rliv->get_name(estate) + " to state " +
1953  HLS->Rliv->get_name(*s_out_it) + " for " +
1954  HLSMgr->CGetFunctionBehavior(funId)
1955  ->CGetBehavioralHelper()
1956  ->PrintVariable(cur_phi_tree_var));
1957  generic_objRef enable_obj = GetPointer<register_obj>(tgt_reg_obj)->get_wr_enable();
1958  GetPointer<commandport_obj>(enable_obj)
1959  ->add_activation(commandport_obj::transition(
1960  estate, *s_out_it,
1963  " - write enable for " + tgt_reg_obj->get_string() + " from "
1964  << HLS->Rliv->get_name(estate) + " to state " +
1965  HLS->Rliv->get_name(*s_out_it));
1966  }
1967  }
1968  else
1969  {
1970  THROW_ERROR(
1971  "not expected conversion " + STR(cur_phi_tree_var) + " " + STR(in_bitsize) + " " +
1972  STR(out_bitsize) + " " +
1973  TreeM->get_tree_node_const(data->CGetOpNodeInfo(op)->GetNodeId())->ToString());
1974  }
1975  }
1976  else
1977  {
1978  generic_objRef fu_src_obj;
1979  if(state_info &&
1980  state_info->moved_op_use_set.find(var_written) != state_info->moved_op_use_set.end() &&
1981  state_info->moved_op_def_set.find(cur_phi_tree_var) == state_info->moved_op_def_set.end())
1982  {
1983  auto src_storage_value =
1985  auto src_r_index = HLS->Rreg->get_register(src_storage_value);
1986  fu_src_obj = HLS->Rreg->get(src_r_index);
1987  }
1988  else
1989  {
1991  fu_src_obj = HLS->Rfu->get(src_def_op);
1992  }
1993  const CustomOrderedSet<vertex>& states_out =
1994  HLS->Rliv->get_state_out(estate, op, var_written);
1995  const CustomOrderedSet<vertex>::const_iterator s_out_it_end = states_out.end();
1996  for(auto s_out_it = states_out.begin(); s_out_it != s_out_it_end; ++s_out_it)
1997  {
1998  HLS->Rconn->add_data_transfer(fu_src_obj, tgt_reg_obj, 0, 0,
2000  static_cast<unsigned>(in_bitsize), estate,
2001  *s_out_it, op));
2002  PRINT_DBG_MEX(
2004  " - add data transfer from "
2005  << fu_src_obj->get_string() << " to " << tgt_reg_obj->get_string()
2006  << " port 0:0 from state "
2007  << HLS->Rliv->get_name(estate) + " to state " + HLS->Rliv->get_name(*s_out_it) +
2008  " for " +
2009  HLSMgr->CGetFunctionBehavior(funId)->CGetBehavioralHelper()->PrintVariable(
2010  cur_phi_tree_var));
2011  generic_objRef enable_obj = GetPointer<register_obj>(tgt_reg_obj)->get_wr_enable();
2012  GetPointer<commandport_obj>(enable_obj)
2013  ->add_activation(commandport_obj::transition(
2014  estate, *s_out_it, commandport_obj::data_operation_pair(cur_phi_tree_var, op)));
2016  " - write enable for " + tgt_reg_obj->get_string() + " from "
2017  << HLS->Rliv->get_name(estate) + " to state " +
2018  HLS->Rliv->get_name(*s_out_it));
2019  }
2020  }
2021  }
2022  }
2023  else
2024  {
2025  if(in_bitsize != out_bitsize)
2026  {
2027  add_conversion(0, op, tree_helper::CGetType(TreeM->CGetTreeNode(var_written))->index,
2028  out_bitsize, 0, tgt_reg_obj, data, TreeM, tree_temp);
2029  }
2030  else
2031  {
2032  determine_connection(op, HLS_manager::io_binding_type(tree_temp, 0), tgt_reg_obj, 0, 0, data,
2033  static_cast<unsigned>(in_bitsize));
2034  }
2035  }
2036  }
2037  cur_phi_tree_var = 0;
2038  }
2039  }
2040  }
2041  else
2042  {
2043  PRINT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, " * Ending Operation: " + GET_NAME(data, op));
2044  HLS->Rconn->bind_command_port(op, conn_binding::IN, commandport_obj::OPERATION, data);
2045 
2047  " - FU: " + HLS->allocation_information->get_fu_name(HLS->Rfu->get_assign(op)).first);
2048  const generic_objRef fu_obj = HLS->Rfu->get(op);
2049  const auto var_written = HLSMgr->get_produced_value(HLS->functionId, op);
2050  if((GET_TYPE(data, op) & TYPE_MULTIIF) != 0)
2051  {
2052  PRINT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, " - Write: (multi-way if value)");
2053  auto node_id = data->CGetOpNodeInfo(op)->GetNodeId();
2054  std::vector<HLS_manager::io_binding_type> var_read = HLSMgr->get_required_values(HLS->functionId, op);
2055  generic_objRef TargetPort =
2056  HLS->Rconn->bind_selector_port(conn_binding::OUT, commandport_obj::MULTIIF, op, data);
2057  const CustomOrderedSet<vertex>& ending_states = HLS->Rliv->get_state_where_end(op);
2058  for(const auto estate : ending_states)
2059  {
2060  HLS->Rconn->add_data_transfer(fu_obj, TargetPort, 0, 0,
2061  data_transfer(node_id, var_read.size(), estate, NULL_VERTEX, op));
2063  " - add data transfer from "
2064  << fu_obj->get_string() << " to " << TargetPort->get_string() << " in state "
2065  << HLS->Rliv->get_name(estate) + " for " + STR(node_id));
2066  GetPointer<commandport_obj>(TargetPort)
2067  ->add_activation(commandport_obj::transition(estate, NULL_VERTEX,
2068  commandport_obj::data_operation_pair(node_id, op)));
2070  " - add activation for " + TargetPort->get_string() + " in state "
2071  << HLS->Rliv->get_name(estate));
2072  }
2073  }
2074  else if(var_written == 0)
2075  {
2076  PRINT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, " - Write: (no value produced)");
2077  }
2078  else if((GET_TYPE(data, op) & TYPE_IF) != 0)
2079  {
2080  PRINT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, " - Write: (boolean value)");
2081  generic_objRef TargetPort =
2082  HLS->Rconn->bind_selector_port(conn_binding::OUT, commandport_obj::CONDITION, op, data);
2083  const CustomOrderedSet<vertex>& ending_states = HLS->Rliv->get_state_where_end(op);
2084  for(const auto estate : ending_states)
2085  {
2086  HLS->Rconn->add_data_transfer(fu_obj, TargetPort, 0, 0,
2087  data_transfer(var_written,
2088  tree_helper::Size(TreeM->CGetTreeReindex(var_written)),
2089  estate, NULL_VERTEX, op));
2091  " - add data transfer from " << fu_obj->get_string() << " to "
2092  << TargetPort->get_string() << " in state "
2093  << HLS->Rliv->get_name(estate) + "for condition");
2094  GetPointer<commandport_obj>(TargetPort)
2095  ->add_activation(commandport_obj::transition(estate, NULL_VERTEX,
2096  commandport_obj::data_operation_pair(var_written, op)));
2098  " - add activation for " + TargetPort->get_string() + " in state "
2099  << HLS->Rliv->get_name(estate));
2100  }
2101  }
2102  else if((GET_TYPE(data, op) & TYPE_SWITCH) != 0)
2103  {
2104  PRINT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, " - Write: (switch value)");
2105  generic_objRef TargetPort =
2106  HLS->Rconn->bind_selector_port(conn_binding::OUT, commandport_obj::SWITCH, op, data);
2107  const CustomOrderedSet<vertex>& ending_states = HLS->Rliv->get_state_where_end(op);
2108  for(const auto estate : ending_states)
2109  {
2110  HLS->Rconn->add_data_transfer(fu_obj, TargetPort, 0, 0,
2111  data_transfer(var_written,
2112  tree_helper::Size(TreeM->CGetTreeReindex(var_written)),
2113  estate, NULL_VERTEX, op));
2114  PRINT_DBG_MEX(
2116  " - add data transfer from "
2117  << fu_obj->get_string() << " to " << TargetPort->get_string() << " in state "
2118  << HLS->Rliv->get_name(estate) + " for " +
2119  HLSMgr->CGetFunctionBehavior(funId)->CGetBehavioralHelper()->PrintVariable(var_written));
2120  GetPointer<commandport_obj>(TargetPort)
2121  ->add_activation(commandport_obj::transition(estate, NULL_VERTEX,
2122  commandport_obj::data_operation_pair(var_written, op)));
2124  " - add activation for " + TargetPort->get_string() + " in state "
2125  << HLS->Rliv->get_name(estate));
2126  }
2127  }
2128  else
2129  {
2130  PRINT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, " - Write: " + BH->PrintVariable(var_written));
2131  const CustomOrderedSet<vertex>& ending_states = HLS->Rliv->get_state_where_end(op);
2132  for(const auto estate : ending_states)
2133  {
2134  if(HLS->Rliv->has_state_out(estate, op, var_written))
2135  {
2136  const CustomOrderedSet<vertex>& states_out = HLS->Rliv->get_state_out(estate, op, var_written);
2137  const CustomOrderedSet<vertex>::const_iterator s_out_it_end = states_out.end();
2138  for(auto s_out_it = states_out.begin(); s_out_it != s_out_it_end; ++s_out_it)
2139  {
2140  auto storage_value =
2141  HLS->storage_value_information->get_storage_value_index(*s_out_it, var_written);
2142  auto r_index = HLS->Rreg->get_register(storage_value);
2143  generic_objRef tgt_reg_obj = HLS->Rreg->get(r_index);
2144  HLS->Rconn->add_data_transfer(fu_obj, tgt_reg_obj, 0, 0,
2145  data_transfer(var_written,
2146  tree_helper::Size(TreeM->CGetTreeReindex(var_written)),
2147  estate, *s_out_it, op));
2148  PRINT_DBG_MEX(
2150  " - add data transfer from "
2151  << fu_obj->get_string() << " to " << tgt_reg_obj->get_string() << " from state "
2152  << HLS->Rliv->get_name(estate) + " to state " + HLS->Rliv->get_name(*s_out_it) + " for " +
2153  HLSMgr->CGetFunctionBehavior(funId)->CGetBehavioralHelper()->PrintVariable(
2154  var_written));
2155  generic_objRef enable_obj = GetPointer<register_obj>(tgt_reg_obj)->get_wr_enable();
2156  GetPointer<commandport_obj>(enable_obj)
2157  ->add_activation(commandport_obj::transition(
2158  estate, *s_out_it, commandport_obj::data_operation_pair(var_written, op)));
2160  " - write enable for " + tgt_reg_obj->get_string() + " from "
2161  << HLS->Rliv->get_name(estate) + " to state " + HLS->Rliv->get_name(*s_out_it));
2162  }
2163  }
2164  else
2165  {
2168  PRINT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, " - write in a data_transfer");
2169  }
2170  }
2171  }
2172  }
2173  }
2174 
2175  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "<--Ended execution of interconnection binding");
2176 }
2177 
2179 {
2180  PRINT_DBG_MEX(DEBUG_LEVEL_VERBOSE, debug_level, "Starting datapath interconnection based on mux architecture");
2181 
2182  unsigned int allocated_mux = 0;
2183  unsigned int iteration = 0;
2184 
2185  for(const auto& connection : HLS->Rconn->get_data_transfers())
2186  {
2187  const generic_objRef unit = std::get<0>(connection.first);
2188  auto operand = std::get<1>(connection.first);
2189  auto port_index = std::get<2>(connection.first);
2191  "Unit: " + unit->get_string() + "(" + std::to_string(operand) + ":" + std::to_string(port_index) +
2192  "): " + std::to_string(connection.second.size()) + " connections");
2193  allocated_mux += input_logic(connection.second, unit, operand, port_index, iteration);
2194  ++iteration;
2195  }
2196 
2197  return allocated_mux;
2198 }
2199 
2201  unsigned int op, unsigned int port_index, unsigned int iteration)
2202 {
2203  static unsigned int used_mux = 0;
2204  unsigned int starting_value = used_mux;
2205 
2207  if(srcs.size() == 1)
2208  {
2209  generic_objRef op1 = srcs.begin()->first;
2210  THROW_ASSERT(op1, "Target \"" + tgt->get_string() + "\" connected with an undefined source");
2211  connection_objRef conn_obj = connection_objRef(new direct_conn(srcs.begin()->second));
2212  HLS->Rconn->AddConnectionCB(op1, tgt, op, port_index, conn_obj);
2214  " - Direct connection between " + op1->get_string() + " and " + tgt->get_string() + "(" + STR(op) +
2215  ":" + STR(port_index) + ")");
2216  return 0;
2217  }
2218 
2220  std::map<generic_objRef, std::vector<std::pair<generic_objRef, unsigned int>>> src_mux_tree;
2221 
2223  std::map<data_transfer, generic_objRef> var2obj;
2225  std::map<generic_objRef, std::list<data_transfer>> obj2var;
2227  std::map<data_transfer, generic_objRef> var2src;
2228 
2229 #ifndef NDEBUG
2230  std::map<std::pair<vertex, vertex>, generic_objRef> check_sources;
2231 #endif
2232 
2233  std::list<generic_objRef> to_allocate;
2234  PRINT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, " - Connection from: ");
2235  for(const auto& src : srcs)
2236  {
2237  PRINT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, " * Source: " + src.first->get_string() + " ");
2238  const CustomOrderedSet<data_transfer>& vars = src.second;
2239  THROW_ASSERT(vars.size(), "A connection should contain at least one data-transfer");
2240  for(const auto& var : vars)
2241  {
2242  if(std::get<0>(var) == INFINITE_UINT)
2243  {
2245  " - var: (bool) from. " + HLS->Rliv->get_name(std::get<2>(var)) + " to " +
2246  HLS->Rliv->get_name(std::get<3>(var)));
2247  }
2248  else if(std::get<0>(var) != 0)
2249  {
2250  PRINT_DBG_MEX(
2252  " - var: " +
2253  HLSMgr->CGetFunctionBehavior(funId)->CGetBehavioralHelper()->PrintVariable(std::get<0>(var)) +
2254  " of size " + STR(std::get<1>(var)) + " from. " + HLS->Rliv->get_name(std::get<2>(var)) + " to " +
2255  HLS->Rliv->get_name(std::get<3>(var)));
2256  }
2257  else
2258  {
2260  " - size: " + STR(std::get<1>(var)) + " from. " +
2261  HLS->Rliv->get_name(std::get<2>(var)) + " to " + HLS->Rliv->get_name(std::get<3>(var)));
2262  }
2263 
2264  var2obj[var] = src.first;
2265  var2src[var] = src.first;
2266  obj2var[src.first].push_back(var);
2267 #ifndef NDEBUG
2268  if(check_sources.find(std::make_pair(std::get<2>(var), std::get<3>(var))) != check_sources.end() &&
2269  check_sources.find(std::make_pair(std::get<2>(var), std::get<3>(var)))->second != src.first)
2270  {
2271  THROW_ERROR("two different sources for the same transition: from. " +
2272  HLS->Rliv->get_name(std::get<2>(var)) + " to " + HLS->Rliv->get_name(std::get<3>(var)) +
2273  " source 1 " + src.first->get_string() + " source 2 " +
2274  check_sources.find(std::make_pair(std::get<2>(var), std::get<3>(var)))->second->get_string());
2275  }
2276  else if(check_sources.find(std::make_pair(std::get<2>(var), std::get<3>(var))) == check_sources.end())
2277  {
2278  check_sources[std::make_pair(std::get<2>(var), std::get<3>(var))] = src.first;
2279  }
2280 #endif
2281  }
2282  if(src.first->get_type() != generic_obj::REGISTER)
2283  {
2284  to_allocate.push_back(src.first);
2285  }
2286  else
2287  {
2288  to_allocate.push_front(src.first);
2289  }
2290  }
2291 
2292  std::string tgt_string = tgt->get_string() + "_" + STR(op);
2293  if(to_allocate.size() > 1)
2294  {
2295  unsigned int level = 0;
2296  std::map<unsigned int, unsigned int> level_map;
2297  do
2298  {
2300  generic_objRef first = to_allocate.front();
2301  to_allocate.pop_front();
2302  generic_objRef second = to_allocate.front();
2303  to_allocate.pop_front();
2304 
2305  if(GetPointer<mux_obj>(first))
2306  {
2307  level = GetPointer<mux_obj>(first)->get_level() + 1;
2308  }
2309 
2310  std::string mux_name =
2311  "MUX_" + STR(iteration) + "_" + tgt_string + "_" + STR(level) + "_" + STR(level_map[level]++);
2312  generic_objRef mux = generic_objRef(new mux_obj(first, second, level, mux_name, tgt));
2313  ++used_mux;
2314  PRINT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, GetPointer<mux_obj>(mux)->get_string());
2315 
2316  generic_objRef sel_port = HLS->Rconn->bind_selector_port(conn_binding::IN, commandport_obj::SELECTOR, mux, 0);
2317  GetPointer<mux_obj>(mux)->set_selector(sel_port);
2318 
2319  to_allocate.push_back(mux);
2320 
2321  std::list<data_transfer>::iterator v;
2322 
2324  for(v = obj2var[first].begin(); v != obj2var[first].end(); ++v)
2325  {
2326  if(GetPointer<mux_obj>(var2obj[*v]))
2327  {
2328  GetPointer<mux_obj>(var2obj[*v])->set_target(mux);
2329  }
2330 
2331  var2obj[*v] = mux;
2332  obj2var[mux].push_back(*v);
2333 
2334  if(std::find(src_mux_tree[var2src[*v]].begin(), src_mux_tree[var2src[*v]].end(),
2335  std::make_pair(mux, T_COND)) == src_mux_tree[var2src[*v]].end())
2336  {
2337  src_mux_tree[var2src[*v]].push_back(std::make_pair(mux, T_COND));
2338  }
2339 
2340  GetPointer<mux_obj>(mux)->add_bitsize(std::get<1>(*v));
2341 
2342  GetPointer<commandport_obj>(sel_port)->add_activation(
2343  commandport_obj::transition(std::get<2>(*v), std::get<3>(*v),
2344  commandport_obj::data_operation_pair(std::get<0>(*v), std::get<4>(*v))));
2346  " - add mux activation for " + sel_port->get_string() + " from state "
2347  << HLS->Rliv->get_name(std::get<2>(*v)) + " to state " +
2348  HLS->Rliv->get_name(std::get<3>(*v)));
2349  }
2351  for(v = obj2var[second].begin(); v != obj2var[second].end(); ++v)
2352  {
2353  if(GetPointer<mux_obj>(var2obj[*v]))
2354  {
2355  GetPointer<mux_obj>(var2obj[*v])->set_target(mux);
2356  }
2357 
2358  var2obj[*v] = mux;
2359  obj2var[mux].push_back(*v);
2360 
2361  if(std::find(src_mux_tree[var2src[*v]].begin(), src_mux_tree[var2src[*v]].end(),
2362  std::make_pair(mux, F_COND)) == src_mux_tree[var2src[*v]].end())
2363  {
2364  src_mux_tree[var2src[*v]].push_back(std::make_pair(mux, F_COND));
2365  }
2366 
2367  GetPointer<mux_obj>(mux)->add_bitsize(std::get<1>(*v));
2369  " - FALSE input for " + sel_port->get_string() + " from state "
2370  << HLS->Rliv->get_name(std::get<2>(*v)) + " to state " +
2371  HLS->Rliv->get_name(std::get<3>(*v)));
2372  }
2373  } while(to_allocate.size() > 1);
2374 
2376  for(const auto& src : srcs)
2377  {
2378  connection_objRef conn_obj = connection_objRef(new mux_conn(src.second, src_mux_tree[src.first]));
2379  HLS->Rconn->AddConnectionCB(src.first, tgt, op, port_index, conn_obj);
2380  }
2381  }
2382  else
2383  {
2384  THROW_ERROR("no mux to_allocate" + STR(to_allocate.size()));
2385  }
2386 
2388  return used_mux - starting_value;
2389 }
2390 
2392  const HLS_manager::io_binding_type& obj) const
2393 {
2394  const auto first = std::get<0>(obj);
2395  const auto second = std::get<1>(obj);
2396  if(first)
2397  {
2398  const auto type = tree_helper::CGetType(TreeM->CGetTreeReindex(first));
2399  const auto bus_addr_bitsize = HLSMgr->get_address_bitsize();
2400 
2402  tree_helper::IsUnionType(type) /*|| tree_helper::IsComplexType(type)*/)
2403  {
2404  return bus_addr_bitsize;
2405  }
2406  else
2407  {
2408  return tree_helper::Size(TreeM->CGetTreeReindex(first));
2409  }
2410  }
2411  else
2412  {
2413  if(second)
2414  {
2415  unsigned int count;
2416  for(count = 1; second >= (1u << count); ++count)
2417  {
2418  ;
2419  }
2420  return count + 1;
2421  }
2422  else
2423  {
2424  return 1;
2425  }
2426  }
2427 }
#define GET_NODE(t)
Macro used to hide implementation details when accessing a tree_node from another tree_node...
Definition: tree_node.hpp:343
static bool IsSameType(const tree_nodeConstRef &tn0, const tree_nodeConstRef &tn1)
Given two nodes tells if they have same base type (const is not considered: const double == double) ...
#define TYPE_SWITCH
constant identifying the node type of a SWITCH operation.
Definition: op_graph.hpp:105
void Initialize() override
Initialize the step (i.e., like a constructor, but executed just before exec.
Class specification to contain liveness information.
Generic class managing interconnection binding algorithms.
void pi(UINT64 *A)
Definition: Keccak.c:102
static tree_nodeConstRef GetFormalIth(const tree_nodeConstRef &obj, unsigned int parm_index)
Return the type of the ith formal parameter in case index_obj is a call_expr.
unsigned int get_register(unsigned int sv) const
return the register index where the storage value is stored
This class is used to specify the type of a connection object: UINT.
#define DEBUG_LEVEL_VERY_PEDANTIC
extremely verbose debugging print is performed.
static bool IsUnionType(const tree_nodeConstRef &type)
Return if treenode is an union.
const HLS_managerRef HLSMgr
information about all the HLS synthesis
Definition: hls_step.hpp:205
Data structure representing the entire HLS information.
std::pair< unsigned int, vertex > data_operation_pair
#define INDENT_DBG_MEX(dbgLevel, curDbgLevel, mex)
We are producing a debug version of the program, so the message is printed;.
Class implementation of the connection module converting the type and the size of connection objects...
void * top(node_stack *head)
Definition: tree.c:75
#define GET_TYPE(data, vertex_index)
Helper macro returning the type associated with a node.
File containing functions and utilities to support the printing of debug messagges.
Base class for all unbounded objects added to datapath.
#define PRINT_DBG_MEX(dbgLevel, curDbgLevel, mex)
We are producing a debug version of the program, so the message is printed;.
generic_objRef get(const vertex v) const
Returns reference to funit object associated with this vertex.
static bool is_int(const tree_managerConstRef &TM, const unsigned int index)
Return true if the treenode is of integer type.
#define DEBUG_LEVEL_PEDANTIC
very verbose debugging print is performed.
This file contains the structures needed to manage a graph that will represent the state transition g...
const CustomOrderedSet< vertex > & get_state_where_end(vertex op) const
return in which support vertex the operation is ending
Definition: liveness.cpp:235
bool is_direct_access_memory_unit(unsigned int fu_type) const
return true in case fu type is a memory unit with direct access channels
Base class for all command ports into datapath.
#define TYPE_MULTIIF
constant identifying the a multi-way if
Definition: op_graph.hpp:202
#define TYPE_VPHI
constant string identifying an operation node of type virtual phi-nodes
Definition: op_graph.hpp:162
string target
Definition: lenet_tvm.py:16
const tree_nodeRef CGetTreeReindex(const unsigned int i) const
Return a tree_reindex wrapping the i-th tree_node.
#define GET_CLASS(obj)
Macro returning the actual type of an object.
CustomOrderedSet< vertex > noswap_computed_table
store the operations for which a port swapping is not beneficial
void AddConnectionCB(const generic_objRef op1, const generic_objRef op2, unsigned int operand, unsigned int port_index, connection_objRef conn)
Creates a connection between two objects.
static bool is_unsigned(const tree_managerConstRef &TM, const unsigned int index)
Return true if the treenode is of unsigned integer type.
This class is used to represent a connection through multiplexers.
Definition: mux_conn.hpp:61
#define TYPE_IF
constant identifying the node type of an IF operation.
Definition: op_graph.hpp:100
const int output_level
The output level.
vertex get_entry_state() const
Gets vertex that represents state that contains entry node.
generic_objRef bind_selector_port(direction_type dir, unsigned int mode, const vertex &cond, const OpGraphConstRef data)
This class is used to specify the type of a connection object: REAL.
bool get_ports_are_swapped(vertex v) const
Check if vertex v has its ports swapped or not.
Definition: fu_binding.hpp:359
static bool is_real(const tree_managerConstRef &TM, const unsigned int index)
Return true if the treenode is of real type.
std::map< resource_id_type, std::map< unsigned int, CustomOrderedSet< unsigned int > > > regs_in
store the registers for each resource and for each port
unsigned long long object_bitsize(const tree_managerRef TreeM, const HLS_manager::io_binding_type &obj) const
Compute the bitsize given a io_binding type.
Datastructure to represent a memory symbol in HLS.
#define INDENT_OUT_MEX(outLevel, curOutLevel, mex)
unsigned int get_assign(const vertex &v) const
Returns the functional unit assigned to the vertex.
Definition: fu_binding.cpp:242
const unsigned int funId
identifier of the function to be processed (0 means that it is a global step)
#define GET_NAME(data, vertex_index)
Helper macro returning the name associated with a node.
Class specification of the graph structures.
std::pair< std::string, std::string > get_fu_name(unsigned int id) const
Returns the name of the functional unit, associated with the name of the library, given the correspon...
static bool is_parameter(const tree_managerConstRef &TM, const unsigned int index)
return true in case the index corresponds to a parameter in ssa form or not
AllocationInformationRef allocation_information
Store the technology information.
Definition: hls.hpp:115
Class adopted to represent direct connections inside the datapath.
unsigned int extract_parm_decl(unsigned int tree_var, const tree_managerRef TreeM)
unsigned long long determine_bit_level_mux() const
Returns the number of bit-level multiplexers.
DesignFlowStep_Status InternalExec() override
Execute the step.
const CustomOrderedSet< vertex > & get_state_in(vertex state, vertex op, unsigned int var) const
given a variable and a state it returns the set of states from which the variable may come ...
Definition: liveness.cpp:166
virtual void print() const
Function that prints the interconnection binding.
#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
std::map< std::tuple< unsigned int, cacheType, const HLS_manager::io_binding_type >, generic_objRef > connCache
connection cache
#define min(x, y)
bool has_state_out(vertex state, vertex op, unsigned int var) const
return true in case the variable for a given op and a given state has a state out ...
Definition: liveness.cpp:212
void determine_connection(const vertex &op, const HLS_manager::io_binding_type &var, generic_objRef fu_obj, unsigned int port_num, unsigned int port_index, const OpGraphConstRef data, unsigned int precision, unsigned int alignment=0)
Determine the actual interconnection.
This class is used to convert unsigned into unsigned int.
static std::string extract_bambu_provided_name(unsigned long long prec_in, unsigned long long prec_out, const HLS_managerConstRef hls_manager, technology_nodeRef &current_fu)
static technology_nodeRef get_fu(const std::string &fu_name, const HLS_managerConstRef hls_manager)
Returns the technology_node associated with the given operation.
This class is used to convert unsigned into signed int.
refcount< conn_binding > conn_bindingRef
Refcount definition of the class.
bool isConstantObj(unsigned int tree_index, const tree_managerRef TreeM)
virtual bool is_a_storage_value(vertex curr_vertex, unsigned int var_index)=0
return true in case a storage value exist for the pair vertex variable
#define OUTPUT_LEVEL_MINIMUM
minimum debugging print is performed.
This class is used to convert signed into signed int.
generic_objRef get_constant_obj(const std::string &value, const std::string &param, unsigned int precision)
Class adopt to represent a mux connection.
std::tuple< unsigned int, unsigned int > io_binding_type
tuple set used to represent the required values or the constant default value associated with the inp...
Include a set of utilities used to manage CPU time measures.
#define TYPE_LOAD
Constant string identifying a memory load operation.
Definition: op_graph.hpp:172
const tree_nodeConstRef CGetTreeNode(const unsigned int i) const
#define TYPE_PHI
constant string identifying an operation node of type PHI
Definition: op_graph.hpp:135
void add_data_transfer(const generic_objRef op1, const generic_objRef op2, unsigned int operand, unsigned int port_index, data_transfer data)
Adds a data transfer between two objects.
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.
int key[32]
Definition: aes.h:67
#define max
Definition: backprop.h:17
std::string ToString(ActorGraphBackend_Type actor_graph_backend_type)
Header include.
static bool IsUnsignedIntegerType(const tree_nodeConstRef &type)
Return true if the treenode is of unsigned integer type.
const tree_nodeRef get_tree_node_const(unsigned int i) const
Return the reference to the i-th tree_node Constant version of get_tree_node.
static bool IsSignedIntegerType(const tree_nodeConstRef &type)
Return true if the treenode is of integer type.
const OpNodeInfoConstRef CGetOpNodeInfo(const vertex node) const
Returns the info associated with a node.
Definition: op_graph.hpp:843
static bool IsArrayType(const tree_nodeConstRef &type)
Return true if treenode is an array.
std::string convert_to_binary(G _value, unsigned long long precision)
Definition: utility.hpp:110
void create_connections()
Creates the connections inside the architecture.
#define THROW_UNREACHABLE(str_expr)
helper function used to specify that some points should never be reached
Definition: exceptions.hpp:292
#define START_TIME(time_var)
Macro used to store the start time into time_var.
Definition: cpu_time.hpp:133
fu_bindingRef Rfu
Store the refcounted functional unit binding of the operations.
Definition: hls.hpp:121
virtual std::string get_kind_text() const =0
Virtual function returning the name of the actual class.
const std::string get_string() const
Returns the name associated with the element.
This class is used to convert signed into unsigned int.
refcount< connection_obj > connection_objRef
RefCount definition for connection_obj class.
Data structure used to store the register binding of variables.
static unsigned long long Size(const tree_nodeConstRef &tn)
Return the size of a tree object.
StorageValueInformationRef storage_value_information
data-structure for storage values
Definition: hls.hpp:130
unsigned int get_proxy_memory_var(const unsigned int fu_name) const
return the var associated with the proxy unit
Base class for multiplexer into datapath.
static bool IsBooleanType(const tree_nodeConstRef &type)
Return true if the treenode is of bool type.
unsigned int get_number(unsigned int unit) const
Returns number of functional unit allocated.
Definition: fu_binding.hpp:249
Data structure used to store the interconnection binding of datapath elements.
refcount< const StateInfo > StateInfoConstRef
a functional resource
Definition: generic_obj.hpp:73
HLSFlowStep_Type
Definition: hls_step.hpp:95
std::map< unsigned int, generic_objRef > input_ports
map between input port variable and generic object
Class specification of the data structures used to manage technology information. ...
unsigned int address_precision(unsigned int precision, const vertex &op, const OpGraphConstRef data, const tree_managerRef TreeM)
generic_objRef get(const unsigned int &r) const
Returns reference to register object associated to a given index.
std::tuple< unsigned int, unsigned int, vertex, vertex, vertex > data_transfer
definition of the data transfer (tree_node, precision, from, to, data_transferred, current_op).
#define index(x, y)
Definition: Keccak.c:74
#define STOP_TIME(time_var)
Macro used to store the elapsed time into time_var.
Definition: cpu_time.hpp:136
const std::map< vertex, generic_objRef > & get_mu_ctrls() const
#define TYPE_STORE
Constant string identifying a memory store operation.
Definition: op_graph.hpp:177
boost::graph_traits< graph >::vertex_descriptor vertex
vertex definition.
Definition: graph.hpp:1303
Base class for all register into datapath.
unsigned offset[NUM_VERTICES+1]
Definition: graph.h:3
#define T_COND
constant used to represent control edges representing a true edge of a conditional statement...
This file contains the structures needed to manage a graph that will represent the state transition g...
#define GET_CONST_NODE(t)
Definition: tree_node.hpp:347
const CustomOrderedSet< unsigned int > & get_live_out(const vertex &v) const
Get the set of variables live at the output of a vertex.
Definition: liveness.cpp:142
const BehavioralHelperConstRef CGetBehavioralHelper() const
Returns the helper associated with the function.
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.
This file collects some utility functions and macros.
std::map< resource_id_type, std::map< unsigned int, CustomOrderedSet< unsigned int > > > chained_in
store the chained storage values for each resource and for each port
static bool is_a_pointer(const tree_managerConstRef &TM, const unsigned int index)
Return if treenode index is a pointer.
reg_bindingRef Rreg
Store the refcounted register binding of the variables.
Definition: hls.hpp:133
std::list< unsigned int > get_allocation_list() const
Returns the set of allocated unit.
Definition: fu_binding.cpp:221
static conn_bindingRef create_conn_binding(const HLS_managerRef _HLSMgr, const hlsRef _HLS, const BehavioralHelperConstRef _BH, const ParameterConstRef _parameters)
factory method to create the right conn_binding depending on the flow
#define THROW_ERROR(str_expr)
helper function used to throw an error in a standard way
Definition: exceptions.hpp:263
This class is used to specify the type of a connection object: INT.
This package is used to define the storage value scheme adopted by the register allocation algorithms...
const StateTransitionGraphConstRef CGetAstg() const
Returns pointer to state transition graph created.
livenessRef Rliv
data-structure containing the variable liveness
Definition: hls.hpp:127
static void check_bitwidth(unsigned long long prec)
check if the maximum bitwidth used for registers, busses, muxes, etc. is compatible with prec ...
#define CASE_TYPE_NODES
This macro collects all case labels for type objects.
Definition: tree_node.hpp:581
This file collects some utility functions.
std::map< generic_objRef, CustomOrderedSet< data_transfer >, GenericObjSorter > ConnectionSources
definition of sources of a connection
tree_nodeRef GetTreeNode(const unsigned int index) const
Return the index-th tree_node (modifiable version)
Data structure used to store the interconnection binding of datapath elements when parallel memory co...
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
Class implementation of the adder connection module.
void create_single_conn(const OpGraphConstRef data, const vertex &op, generic_objRef fu_obj_src, generic_objRef fu_obj, unsigned int port_num, unsigned int port_index, unsigned int tree_var, unsigned int precision, const bool is_not_a_phi)
create the connection object and update the unique table
CustomOrderedSet< vertex > swap_computed_table
store the operations for which a port swapping is beneficial
const CustomOrderedSet< vertex > & get_state_out(vertex state, vertex op, unsigned int var) const
given a variable and a state it returns the set of destination states where the variable may be used ...
Definition: liveness.cpp:200
void add_conversion(unsigned int num, vertex op, unsigned int form_par_type, unsigned long long form_par_bitsize, unsigned int port_index, const generic_objRef fu_obj, const OpGraphConstRef data, const tree_managerRef TreeM, unsigned int tree_var)
static tree_nodeConstRef GetBaseVariable(const tree_nodeConstRef &mem)
Retrun the base variable of a memory access.
bool has_state_in(vertex state, vertex op, unsigned int var) const
return true in case the variable for a given op and a given state has a state in
Definition: liveness.cpp:177
#define OUTPUT_LEVEL_PEDANTIC
verbose debugging print is performed.
bool is_dual_port_memory(unsigned int fu_type) const
return true in case the memory has decoupled addresses for writing and reading
Data flow graph with feedback.
Class to represent direct connections.
Definition: direct_conn.hpp:55
Class specification of the tree_reindex support class.
#define CASE_FAKE_NODES
This macro collects all case labels for fake or empty nodes.
Definition: tree_node.hpp:635
unsigned int get_number_channels(unsigned int fu_name) const
return the number of channels available for the functional unit
std::string get_string_name(unsigned int fu_name) const
Returns the name of the functional for debug purpose.
Data structure used to store the functional-unit binding of the vertexes.
#define INFINITE_UINT
UNSIGNED INT representing infinite.
Definition: utility.hpp:70
bool is_variable_mem(unsigned int node_id) const
Checks if a variable has been allocated in memory.
unsigned int get_memory_var(const unsigned int fu_name) const
Returns the base address of the functional unit.
const CustomOrderedSet< vertex > & get_state_where_run(vertex op) const
return in which support vertex the operation is running
Definition: liveness.cpp:241
hlsRef HLS
HLS data structure of the function to be analyzed.
std::map< resource_id_type, std::map< unsigned int, CustomOrderedSet< resource_id_type > > > module_in
store the resource in IN for each resource and for each port
virtual unsigned int get_storage_value_index(vertex curr_vertex, unsigned int var_index)=0
Returns the index of the storage value associated with the variable in a given vertex.
const std::map< ConnectionTarget, ConnectionSources > & get_data_transfers() const
Returns the map containing all the data transfers.
void Initialize() override
Initialize the step (i.e., like a constructor, but executed just before exec.
Data structures used in operations graph.
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 convert real into real.
static bool IsStructType(const tree_nodeConstRef &type)
Return true if treenode is a record.
unsigned int get_used_regs() const
returns number of used register
int level
Definition: main.c:98
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
static bool is_bool(const tree_managerConstRef &TM, const unsigned int index)
Return true if the treenode is of bool type.
static unsigned int align_to_trimmed_bits(unsigned int algn)
#define F_COND
constant used to represent control edges representing a false edge of a conditional statement...
StateTransitionGraphRef GetStg()
Returns pointer to state transition graph created.
unsigned int functionId
this is the identifier of the function to be implemented
Definition: hls.hpp:87
std::tuple< vertex, vertex, data_operation_pair > transition
describe a transition from a source state to the target state plus the tree_node of the data transfer...
bool is_memory_unit(const unsigned int fu_name) const
Returns true if the fu_name is a memory unit.
bool is_indirect_access_memory_unit(unsigned int fu) const
return true in case fu type is a resource unit performing an indirect access to memory ...
StateTransitionGraphManagerRef STG
Store the refcounted state transition graph.
Definition: hls.hpp:124
Class to manage mux-based interconnections based on the FSM controller.
#define CASE_GIMPLE_NODES
This macro collects all cases labels for gimple nodes.
Definition: tree_node.hpp:700
static integer_cst_t GetConstValue(const tree_nodeConstRef &tn, bool is_signed=true)
Get value from integer constant.
int debug_level
The debug level.
This package is used by all HLS packages to manage resource constraints and characteristics.
generic_objRef bind_command_port(const vertex &ver, direction_type dir, unsigned int mode, const OpGraphConstRef g)
Bind vertex to a command port object.
mux_connection_binding(const ParameterConstRef _parameters, const HLS_managerRef HLSMgr, unsigned int funId, const DesignFlowManagerConstRef design_flow_manager)
Main constructor.
#define GET_INDEX_CONST_NODE(t)
Definition: tree_node.hpp:363
vertex get_op_where_defined(unsigned int var) const
return which operation defines the variable
Definition: liveness.cpp:154
Base class for all register into datapath.
void connect_to_registers(vertex op, const OpGraphConstRef data, generic_objRef fu_obj, unsigned int port_num, unsigned int port_index, unsigned int tree_var, unsigned long long precision, const bool is_not_a_phi)
connect the fu_obj with the associated registers.
#define DEBUG_LEVEL_VERBOSE
verbose debugging print is performed.
static bool IsPointerType(const tree_nodeConstRef &type)
Return true if treenode index is a pointer.
Data structure definition for high-level synthesis flow.
conn_bindingRef Rconn
Store the refcounted interconnection of datapath elements.
Definition: hls.hpp:139
void add_sparse_logic(const generic_objRef so)
#define NULL_VERTEX
null vertex definition
Definition: graph.hpp:1305
unsigned int cur_phi_tree_var
store the current phi use. Used during the analysis of phi nodes
Datastructure to represent memory information in high-level synthesis.
const std::string & get_name(vertex v) const
return the name of the given state
Definition: liveness.cpp:247
#define MULTI_READ_COND
constant string identifying the operation performed by a MULTI_READ_COND.
Definition: op_graph.hpp:260
unsigned int get_index(const vertex &v) const
Returns the index of functional unit assigned to the vertex.
Definition: fu_binding.cpp:261
Class specification of the manager of the tree structures extracted from the raw file.
refcount< generic_obj > generic_objRef
RefCount definition for generic_obj class.
A brief description of the C++ Header File.
unsigned int input_logic(const conn_binding::ConnectionSources &src, const generic_objRef tgt, unsigned int op, unsigned int port_index, unsigned int iteration)
Computes logic for inputs.
This class is used when pointers arithmetic is implicitly performed.
static bool IsRealType(const tree_nodeConstRef &type)
Return true if the treenode is of real type.
const CustomOrderedSet< unsigned int > & get_live_in(const vertex &v) const
Get the set of variables live at the input of a vertex.
Definition: liveness.cpp:109
void cleanInternals()
This class is a specialization of generic_obj class to represent a multiplexer into the datapath...
Definition: mux_obj.hpp:57
~mux_connection_binding() override
Destructor.
#define CASE_PRAGMA_NODES
This macro collects all case labels for pragma objects.
Definition: tree_node.hpp:610
void add_parameter_ports()
Add ports representing parameter values.
#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
unsigned int mux_interconnection()
Performs specialization of interconnections using mux architecture.

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