PandA-2024.02
InterfaceInfer.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) 2022-2024 Politecnico di Milano
16  *
17  * This file is part of the PandA framework.
18  *
19  * The PandA framework is free software; you can redistribute it and/or modify
20  * it under the terms of the GNU General Public License as published by
21  * the Free Software Foundation; either version 3 of the License, or
22  * (at your option) any later version.
23  *
24  * This program is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27  * GNU General Public License for more details.
28  *
29  * You should have received a copy of the GNU General Public License
30  * along with this program. If not, see <http://www.gnu.org/licenses/>.
31  *
32  */
41 #include "InterfaceInfer.hpp"
42 
43 #include "config_PANDA_DATA_INSTALLDIR.hpp"
44 
45 #include "Parameter.hpp"
46 #include "application_manager.hpp"
47 #include "area_info.hpp"
48 #include "behavioral_helper.hpp"
49 #include "call_graph.hpp"
50 #include "call_graph_manager.hpp"
51 #include "compiler_wrapper.hpp"
52 #include "constant_strings.hpp"
53 #include "copyrights_strings.hpp"
54 #include "dbgPrintHelper.hpp"
55 #include "design_flow_graph.hpp"
56 #include "design_flow_manager.hpp"
57 #include "function_behavior.hpp"
58 #include "hls_device.hpp"
59 #include "hls_manager.hpp"
60 #include "hls_step.hpp"
61 #include "language_writer.hpp"
62 #include "library_manager.hpp"
63 #include "math_function.hpp"
64 #include "string_manipulation.hpp"
65 #include "structural_manager.hpp"
66 #include "structural_objects.hpp"
67 #include "technology_flow_step.hpp"
69 #include "technology_manager.hpp"
70 #include "technology_node.hpp"
71 #include "time_info.hpp"
72 #include "token_interface.hpp"
73 #include "tree_basic_block.hpp"
74 #include "tree_helper.hpp"
75 #include "tree_manager.hpp"
76 #include "tree_manipulation.hpp"
77 #include "tree_node.hpp"
78 #include "tree_reindex.hpp"
79 #include "var_pp_functor.hpp"
80 
81 #include <regex>
82 
83 #define EPSILON 0.000000001
84 #define ENCODE_FDNAME(arg_name, MODE, interface_type) \
85  ((arg_name) + STR_CST_interface_parameter_keyword + (MODE) + (interface_type))
86 
88 {
89  none,
90  direct,
91  axi_slave
92 };
93 
95 {
96  generic,
97  ac_type
98 };
99 
101 {
103 
104  public:
105  std::string name;
106  const std::string arg_id;
107  const std::string interface_fname;
108  unsigned alignment;
109  unsigned long long bitwidth;
110  unsigned long long factor;
112 
115 
116  interface_info(const std::string& _arg_id, const std::string& _interface_fname, bool fixed_size,
118  : _fixed_size(fixed_size),
119  name(""),
120  arg_id(_arg_id),
121  interface_fname(_interface_fname),
122  alignment(1U),
123  bitwidth(0ULL),
124  factor(1ULL),
125  type(datatype::generic),
126  parm_attrs(_parm_attrs),
127  iface_attrs(_iface_attrs)
128  {
129  }
130 
131  void update(const tree_nodeRef& tn, const std::string& _type_name, ParameterConstRef parameters)
132  {
133  if(type != datatype::ac_type)
134  {
135  bool is_signed, is_fixed;
136  const auto type_name =
137  std::regex_replace(_type_name, std::regex("(ac_channel|stream|hls::stream)<(.*)>"), "$2");
138  const auto ac_bitwidth = ac_type_bitwidth(type_name, is_signed, is_fixed);
139  auto _type = ac_bitwidth != 0ULL ? datatype::ac_type : datatype::generic;
140  unsigned long long _bitwidth = 0;
141  if(_type == datatype::ac_type)
142  {
143  _bitwidth = ac_bitwidth;
144  type = datatype::ac_type;
145  alignment = static_cast<unsigned>(get_aligned_ac_bitsize(_bitwidth) >> 3);
146  }
147  else if(_type_name.empty())
148  {
149  const auto ptd_type = tree_helper::CGetType(tn);
150  if(tree_helper::IsArrayEquivType(ptd_type))
151  {
152  if(tree_helper::IsStructType(ptd_type))
153  {
154  _bitwidth = tree_helper::Size(tree_helper::CGetArrayBaseType(ptd_type));
155  }
156  else
157  {
158  const auto elt_type = tree_helper::CGetArrayBaseType(ptd_type);
159  if(tree_helper::IsStructType(elt_type))
160  {
161  if(!tree_helper::IsArrayEquivType(elt_type))
162  {
163  THROW_ERROR("Struct type not supported for interfacing: " + STR(elt_type));
164  }
165  _bitwidth = tree_helper::Size(tree_helper::CGetArrayBaseType(elt_type));
166  }
167  else
168  {
169  _bitwidth = tree_helper::Size(elt_type);
170  }
171  }
172  }
173  else if(tree_helper::IsPointerType(ptd_type) || tree_helper::IsStructType(ptd_type))
174  {
175  _bitwidth = static_cast<unsigned long long>(CompilerWrapper::CGetPointerSize(parameters));
176  }
177  else
178  {
179  _bitwidth = tree_helper::Size(ptd_type);
180  }
181  const auto _alignment = static_cast<unsigned>(get_aligned_bitsize(_bitwidth) >> 3);
182  alignment = std::max(alignment, _alignment);
183  }
184 
185  if(_fixed_size && bitwidth && bitwidth != _bitwidth)
186  {
187  THROW_ERROR("Unaligned access not allowed for required interface!");
188  }
189  bitwidth = std::max(bitwidth, _bitwidth);
190  }
191  }
192 };
193 
194 static const std::regex signature_param_typename("((?:\\w+\\s*)+(?:<[^>]*>)?\\s*[\\*&\\/]*\\s*)");
195 
196 static std::string get_decl_name(tree_nodeRef tn)
197 {
198  const auto dn = GetPointer<const decl_node>(GET_CONST_NODE(tn));
199  THROW_ASSERT(dn, "Expected decl_node.");
200  THROW_ASSERT(dn->name, "Expected declaration name.");
201  return GetPointer<const identifier_node>(GET_CONST_NODE(dn->name))->strg;
202 }
203 
204 static std::vector<unsigned int> GetSortedRoots(const CallGraphManagerConstRef& CGM)
205 {
206  std::vector<unsigned int> sorted_roots;
207 
208  const auto CG = CGM->CGetCallGraph();
209  std::vector<vertex> sorted_cg;
210  sorted_cg.reserve(boost::num_vertices(*CG));
211  boost::topological_sort(*CG, std::back_inserter(sorted_cg));
212  auto root_fid = CGM->GetRootFunctions();
213  for(auto v : sorted_cg)
214  {
215  const auto fid = CGM->get_function(v);
216  auto r_it = root_fid.find(fid);
217  if(r_it != root_fid.end())
218  {
219  root_fid.erase(r_it);
220  sorted_roots.push_back(fid);
221  }
222  }
223 
224  return sorted_roots;
225 }
226 
227 static std::tuple<unsigned int, unsigned int> GetCallStmt(const CallGraphManagerConstRef& CGM, unsigned int fid)
228 {
229  const auto fv = CGM->GetVertex(fid);
230  const auto CG = CGM->CGetCallGraph();
231  const auto [calls, calls_end] = boost::in_edges(fv, *CG);
232  if(std::distance(calls, calls_end) == 1)
233  {
234  const auto edge_info = CG->CGetFunctionEdgeInfo(*calls);
235  if(edge_info->direct_call_points.size() == 1)
236  {
237  const auto call_id = *edge_info->direct_call_points.begin();
238  return {CGM->get_function(boost::source(*calls, *CG)), call_id};
239  }
240  }
241  return {0, 0};
242 }
243 
244 static std::vector<tree_nodeRef> GetCallArgs(tree_nodeRef stmt)
245 {
246  if(const auto ga = GetPointer<const gimple_assign>(GET_CONST_NODE(stmt)))
247  {
248  const auto ce = GetPointer<const call_expr>(GET_CONST_NODE(ga->op1));
249  return ce->args;
250  }
251  else if(const auto gc = GetPointer<const gimple_call>(GET_CONST_NODE(stmt)))
252  {
253  return gc->args;
254  }
255  THROW_UNREACHABLE("Unexpected call statement.");
256  return std::vector<tree_nodeRef>();
257 }
258 
260  const tree_nodeConstRef& var, unsigned int fid)
261 {
262  const auto base_var = tree_helper::GetBaseVariable(var);
263  if(const auto pd = GetPointer<const parm_decl>(GET_CONST_NODE(base_var)))
264  {
265  const auto [caller_id, call_id] = GetCallStmt(CGM, fid);
266  if(caller_id)
267  {
268  const auto fd = GetPointer<const function_decl>(TM->CGetTreeNode(fid));
269  const auto parm_idx = static_cast<size_t>(
270  std::distance(fd->list_of_args.begin(),
271  std::find_if(fd->list_of_args.begin(), fd->list_of_args.end(), [&](const auto& tn) {
272  return GET_INDEX_CONST_NODE(tn) == GET_INDEX_CONST_NODE(base_var);
273  })));
274  THROW_ASSERT(parm_idx < fd->list_of_args.size(), "Parameter not found.");
275  const auto call_args = GetCallArgs(TM->CGetTreeReindex(call_id));
276  THROW_ASSERT(call_args.size() == fd->list_of_args.size(),
277  "Expected formal and actual parameters' count match.");
278  return ResolvePointerAlias(CGM, TM, call_args.at(parm_idx), caller_id);
279  }
280  }
281  return base_var;
282 }
283 
284 InterfaceInfer::InterfaceInfer(const application_managerRef _AppM, const DesignFlowManagerConstRef _design_flow_manager,
285  const ParameterConstRef _parameters)
286  : ApplicationFrontendFlowStep(_AppM, INTERFACE_INFER, _design_flow_manager, _parameters), already_executed(false)
287 {
288  debug_level = parameters->get_class_debug_level(GET_CLASS(*this));
289 }
290 
292 
295 {
297  switch(relationship_type)
298  {
300  {
301  relationships.insert(std::make_pair(DATAFLOW_CG_EXT, ALL_FUNCTIONS));
302  relationships.insert(std::make_pair(FUNCTION_ANALYSIS, WHOLE_APPLICATION));
303  relationships.insert(std::make_pair(IR_LOWERING, ALL_FUNCTIONS));
304  relationships.insert(std::make_pair(PARM2SSA, ALL_FUNCTIONS));
305  relationships.insert(std::make_pair(USE_COUNTING, ALL_FUNCTIONS));
306  break;
307  }
309  {
310  break;
311  }
313  {
314  break;
315  }
316  default:
317  {
318  THROW_UNREACHABLE("");
319  }
320  }
321  return relationships;
322 }
323 
325  const DesignFlowStep::RelationshipType relationship_type)
326 {
327  switch(relationship_type)
328  {
330  {
331  break;
332  }
334  {
335  const auto design_flow_graph = design_flow_manager.lock()->CGetDesignFlowGraph();
336  const auto technology_flow_step_factory = GetPointer<const TechnologyFlowStepFactory>(
337  design_flow_manager.lock()->CGetDesignFlowStepFactory("Technology"));
338  const auto technology_flow_signature =
340  const auto technology_flow_step = design_flow_manager.lock()->GetDesignFlowStep(technology_flow_signature);
341  const auto technology_design_flow_step =
342  technology_flow_step ?
343  design_flow_graph->CGetDesignFlowStepInfo(technology_flow_step)->design_flow_step :
344  technology_flow_step_factory->CreateTechnologyFlowStep(TechnologyFlowStep_Type::LOAD_TECHNOLOGY);
345  relationship.insert(technology_design_flow_step);
346  break;
347  }
349  {
350  break;
351  }
352  default:
353  THROW_UNREACHABLE("");
354  }
355  ApplicationFrontendFlowStep::ComputeRelationships(relationship, relationship_type);
356 }
357 
359 {
360  return !already_executed;
361 }
362 
364 {
365  const auto HLSMgr = GetPointer<HLS_manager>(AppM);
366  THROW_ASSERT(HLSMgr, "");
367  const auto TM = AppM->get_tree_manager();
368  const auto CGM = AppM->CGetCallGraphManager();
369  const auto CG = CGM->CGetCallGraph();
370  const auto sorted_roots = GetSortedRoots(CGM);
371 
372  std::set<unsigned int> modified;
373  const auto add_to_modified = [&](const tree_nodeRef& tn) {
374  modified.insert(GET_INDEX_CONST_NODE(GetPointer<gimple_node>(GET_CONST_NODE(tn))->scpe));
375  };
376 
377  for(const auto root_id : sorted_roots)
378  {
379  const auto fnode = TM->CGetTreeReindex(root_id);
380  const auto fd = GetPointer<const function_decl>(GET_CONST_NODE(fnode));
381  const auto fsymbol = tree_helper::GetMangledFunctionName(fd);
382  INDENT_OUT_MEX(OUTPUT_LEVEL_MINIMUM, output_level, "-->Analyzing function " + fsymbol);
383 
384  /* Check if there is a typename corresponding to fname */
385  auto func_arch = HLSMgr->module_arch->GetArchitecture(fsymbol);
386  if(!func_arch)
387  {
389 
390  const auto fsign = [&]() {
391  const auto cxa_fname = cxa_demangle(fsymbol);
392  if(cxa_fname.empty())
393  {
394  return tree_helper::PrintType(TM, fd->type, false, true);
395  }
396  return cxa_fname;
397  }();
398  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Extracting interface from signature " + fsymbol);
399  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Demangled as " + fsign);
400  size_t parm_index = 0;
401  std::sregex_token_iterator typename_it(fsign.begin(), fsign.end(), signature_param_typename, 0), end;
402  func_arch->attrs[FunctionArchitecture::func_symbol] = fsymbol;
403  func_arch->attrs[FunctionArchitecture::func_name] = tree_helper::GetFunctionName(TM, fnode);
404  ++typename_it; // First match is the function name/pointer type
405  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Iterating arguments:");
406  for(const auto& arg : fd->list_of_args)
407  {
408  THROW_ASSERT(typename_it != end, "");
409  const auto parm_name = [&]() {
410  std::stringstream ss;
411  ss << arg;
412  return ss.str();
413  }();
414  auto& iface_attrs = func_arch->ifaces[parm_name];
415  iface_attrs[FunctionArchitecture::iface_name] = parm_name;
416  iface_attrs[FunctionArchitecture::iface_mode] = "default";
417  auto& parm_attrs = func_arch->parms[parm_name];
418  const std::string tname(*typename_it);
419  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Argument " + parm_name + " : " + tname);
420  parm_attrs[FunctionArchitecture::parm_port] = parm_name;
421  parm_attrs[FunctionArchitecture::parm_typename] = parm_attrs[FunctionArchitecture::parm_original_typename] =
422  tname;
423  parm_attrs[FunctionArchitecture::parm_index] = std::to_string(parm_index);
424  parm_attrs[FunctionArchitecture::parm_bundle] = parm_name;
425  if(tname.find("_fixed<") != std::string::npos)
426  {
427  parm_attrs[FunctionArchitecture::parm_includes] +=
428  STR(";" PANDA_DATA_INSTALLDIR "/panda/ac_types/include/" + tname.substr(0, 2) + "_fixed.h");
429  }
430  if(tname.find("_int<") != std::string::npos)
431  {
432  parm_attrs[FunctionArchitecture::parm_includes] +=
433  STR(";" PANDA_DATA_INSTALLDIR "/panda/ac_types/include/" + tname.substr(0, 2) + "_int.h");
434  }
435  if(tname.find("ac_channel<") != std::string::npos)
436  {
437  parm_attrs[FunctionArchitecture::parm_includes] +=
438  STR(";" PANDA_DATA_INSTALLDIR "/panda/ac_types/include/ac_channel.h");
439  }
440  ++typename_it;
441  ++parm_index;
442  }
444  HLSMgr->module_arch->AddArchitecture(fsymbol, func_arch);
446  }
447 
448  const tree_manipulationRef tree_man(new tree_manipulation(TM, parameters, AppM));
449  const auto is_dataflow_module =
450  func_arch->attrs.find(FunctionArchitecture::func_dataflow) != func_arch->attrs.end() &&
451  func_arch->attrs.find(FunctionArchitecture::func_dataflow)->second == "module";
452  if(is_dataflow_module)
453  {
454  const auto [caller_id, call_id] = GetCallStmt(CGM, root_id);
455  THROW_ASSERT(call_id, "Expected unique call point for dataflow module " + fsymbol + ".");
456  const auto call_stmt = TM->CGetTreeReindex(call_id);
457  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Call point " + STR(call_stmt));
458  const auto& args = GetCallArgs(call_stmt);
459 
460  size_t idx = 0;
461  for(const auto& arg : args)
462  {
464  {
465  const auto base_var = ResolvePointerAlias(CGM, TM, arg, caller_id);
466  const auto parm_attr = std::find_if(func_arch->parms.begin(), func_arch->parms.end(), [&](auto& it) {
467  return it.second.at(FunctionArchitecture::parm_index) == std::to_string(idx);
468  });
469  THROW_ASSERT(parm_attr != func_arch->parms.end(), "Expected parameter index " + std::to_string(idx));
470  auto& current_bundle = parm_attr->second.at(FunctionArchitecture::parm_bundle);
471  std::string bundle_name;
472  if(GET_CONST_NODE(base_var)->get_kind() == parm_decl_K)
473  {
474  func_arch->ifaces[current_bundle].at(FunctionArchitecture::iface_mode) = "default";
476  "---Parameter " + parm_attr->second.at(FunctionArchitecture::parm_port) +
477  " forwarded from caller function");
478  ++idx;
479  continue;
480  }
481  else if(GetPointer<const cst_node>(GET_CONST_NODE(base_var)))
482  {
484  "---Parameter " + parm_attr->second.at(FunctionArchitecture::parm_port) +
485  " is constant at this call point");
486  ++idx;
487  continue;
488  }
489  else if(const auto dn = GetPointer<const decl_node>(GET_CONST_NODE(base_var)))
490  {
491  bundle_name = "DF_bambu_" + std::to_string(GET_INDEX_CONST_NODE(base_var));
492  }
493  else
494  {
495  THROW_UNREACHABLE("Unexpected declaration.");
496  }
497  func_arch->ifaces[bundle_name] = func_arch->ifaces.at(current_bundle);
498  func_arch->ifaces[bundle_name].at(FunctionArchitecture::iface_name) = bundle_name;
499  func_arch->ifaces.erase(current_bundle);
500  current_bundle = bundle_name;
501  THROW_ASSERT(fd->list_of_args.size() > idx, "Unexpected function parameters count");
502  auto pd = GetPointerS<parm_decl>(GET_NODE(fd->list_of_args.at(idx)));
503  pd->name = tree_man->create_identifier_node(bundle_name);
505  "---Parameter " + parm_attr->second.at(FunctionArchitecture::parm_port) +
506  " renamed and bound to internal interface " + STR(base_var) + " - " + bundle_name);
507  parm_attr->second.at(FunctionArchitecture::parm_port) = bundle_name;
508  func_arch->parms[bundle_name] = parm_attr->second;
509  func_arch->parms.erase(parm_attr);
510  }
511  ++idx;
512  }
514 
515  INDENT_OUT_MEX(OUTPUT_LEVEL_MINIMUM, output_level, "---Generating control flow loop for dataflow module");
517  const auto sl = GetPointer<statement_list>(GET_NODE(fd->body));
518  THROW_ASSERT(sl->list_of_bloc.count(BB_ENTRY) && sl->list_of_bloc.count(BB_EXIT),
519  "Expected entry and exit basic blocks for function " + fsymbol);
520  const auto& bb_entry = sl->list_of_bloc.at(BB_ENTRY);
521  THROW_ASSERT(bb_entry->list_of_succ.size() == 1, "Expected single entry basic block for function " + fsymbol);
522  const auto& bb_first = sl->list_of_bloc.at(bb_entry->list_of_succ.front());
523  for(auto& [bbi, bb] : sl->list_of_bloc)
524  {
525  if(std::find(bb->list_of_succ.begin(), bb->list_of_succ.end(), BB_EXIT) != bb->list_of_succ.end())
526  {
528  "---BB" + std::to_string(bbi) + " loop-back to entry BB" +
529  std::to_string(bb_first->number));
530  bb->list_of_succ.clear();
531  bb->list_of_succ.push_back(bb_first->number);
532  bb_first->list_of_pred.push_back(bbi);
533  const auto return_stmt = bb->CGetStmtList().back();
534  THROW_ASSERT(GetPointer<const gimple_return>(GET_CONST_NODE(return_stmt)),
535  "Expected return statement as last statement");
536  bb->RemoveStmt(return_stmt, AppM);
537  }
538  }
540  }
541 
542  std::map<std::string, TreeNodeSet> bundle_vdefs;
543  for(const auto& arg : fd->list_of_args)
544  {
545  const auto arg_id = GET_INDEX_NODE(arg);
546  const auto arg_name = get_decl_name(arg);
547  const auto arg_type = tree_helper::CGetType(arg);
548  INDENT_OUT_MEX(OUTPUT_LEVEL_MINIMUM, output_level, "---Parameter @" + STR(arg_id) + " " + arg_name);
549  THROW_ASSERT(func_arch->parms.find(arg_name) != func_arch->parms.end(),
550  "Not matched parameter name: " + arg_name);
551  auto& parm_attrs = func_arch->parms.at(arg_name);
552  THROW_ASSERT(parm_attrs.find(FunctionArchitecture::parm_bundle) != parm_attrs.end(),
553  "Missing parameter bundle name");
554  parm_attrs.emplace(FunctionArchitecture::parm_offset, "off");
555  if(tree_helper::IsPointerType(arg_type))
556  {
557  const auto ptd_type = tree_helper::CGetPointedType(arg_type);
558  const auto array_size =
559  tree_helper::IsArrayType(ptd_type) ? tree_helper::GetArrayTotalSize(ptd_type) : 1ULL;
560  parm_attrs.emplace(FunctionArchitecture::parm_size_in_bytes,
561  std::to_string(array_size * (get_aligned_bitsize(tree_helper::Size(arg_type)) >> 3)));
562  }
563  THROW_ASSERT(func_arch->ifaces.find(parm_attrs.at(FunctionArchitecture::parm_bundle)) !=
564  func_arch->ifaces.end(),
565  "Missing parameter bundle: " + parm_attrs.at(FunctionArchitecture::parm_bundle));
566  auto& iface_attrs = func_arch->ifaces.at(parm_attrs.at(FunctionArchitecture::parm_bundle));
567  iface_attrs[FunctionArchitecture::iface_direction] = port_o::GetString(port_o::IN);
568  iface_attrs[FunctionArchitecture::iface_bitwidth] = STR(tree_helper::Size(arg_type));
569  iface_attrs[FunctionArchitecture::iface_alignment] =
570  std::to_string(get_aligned_bitsize(tree_helper::Size(arg_type)) >> 3);
571  auto& interface_type = iface_attrs[FunctionArchitecture::iface_mode];
572  THROW_ASSERT(parameters->getOption<HLSFlowStep_Type>(OPT_interface_type) !=
574  interface_type.size(),
575  "Expected interface type for parameter '" + arg_name + "'");
576  if(parameters->getOption<HLSFlowStep_Type>(OPT_interface_type) !=
578  interface_type == "bus")
579  {
580  interface_type = "default";
581  }
582  else if(interface_type != "default")
583  {
584  const auto arg_ssa_id = AppM->getSSAFromParm(root_id, arg_id);
585  const auto arg_ssa = TM->GetTreeReindex(arg_ssa_id);
586  THROW_ASSERT(GET_CONST_NODE(arg_ssa)->get_kind() == ssa_name_K, "");
587  if(GetPointerS<const ssa_name>(GET_CONST_NODE(arg_ssa))->CGetUseStmts().empty())
588  {
589  THROW_WARNING("Parameter '" + arg_name + "' not used by any statement");
590  if(tree_helper::IsPointerType(arg_type))
591  {
592  // BEAWARE: none is used here in place of default to avoid memory allocation to consider this as
593  // an active pointer parameter
594  interface_type = "none";
595  }
596  else
597  {
598  THROW_ERROR("parameter not used: specified interface does not make sense - " + interface_type);
599  }
600  continue;
601  }
602  if(tree_helper::IsPointerType(arg_type))
603  {
604  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "---Is a pointer type");
605  interface_info info(arg_name, fsymbol, interface_type != "m_axi", parm_attrs, iface_attrs);
606  info.update(arg_ssa, parm_attrs.at(FunctionArchitecture::parm_typename), parameters);
607 
608  std::list<tree_nodeRef> writeStmt;
609  std::list<tree_nodeRef> readStmt;
610  ChasePointerInterface(arg_ssa, writeStmt, readStmt, info);
611  const auto isRead = !readStmt.empty();
612  const auto isWrite = !writeStmt.empty();
613 
614  if(!isRead && !isWrite)
615  {
616  if(interface_type == "m_axi")
617  {
618  continue;
619  }
620  THROW_ERROR("Parameter '" + arg_name + "' cannot have interface type '" + interface_type +
621  "' since no load/store is associated with it");
622  }
623 
624  info.factor = std::max(
625  info.type == datatype::generic ?
626  (8ULL * std::stoull(parm_attrs.at(FunctionArchitecture::parm_size_in_bytes))) / info.bitwidth :
627  1ULL,
628  1ULL);
629  info.name = [&]() -> std::string {
630  if(isRead && isWrite)
631  {
632  iface_attrs[FunctionArchitecture::iface_direction] = port_o::GetString(port_o::IO);
633  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "---I/O interface");
634  if(interface_type == "array")
635  {
636  if(info.factor > 1)
637  {
638  parm_attrs[FunctionArchitecture::parm_elem_count] = STR(info.factor);
639  }
640  return "array";
641  }
642  else if(interface_type == "ptrdefault")
643  {
644  if(info.factor > 1)
645  {
646  parm_attrs[FunctionArchitecture::parm_elem_count] = STR(info.factor);
647  return "array";
648  }
649  else if(parameters->IsParameter("none-ptrdefault") &&
650  parameters->GetParameter<int>("none-ptrdefault") == 1)
651  {
652  return "none";
653  }
654  else if(parameters->IsParameter("none-registered-ptrdefault") &&
655  parameters->GetParameter<int>("none-registered-ptrdefault") == 1)
656  {
657  iface_attrs[FunctionArchitecture::iface_register] = "";
658  return "none";
659  }
660  return "ovalid";
661  }
662  else if(interface_type == "fifo" || interface_type == "axis")
663  {
664  THROW_ERROR("parameter " + arg_name + " cannot have interface " + interface_type +
665  " because it cannot be read and written at the same time");
666  }
667  }
668  else if(isRead)
669  {
670  iface_attrs[FunctionArchitecture::iface_direction] = port_o::GetString(port_o::IN);
671  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "---Read-only interface");
672  if(interface_type == "array")
673  {
674  if(info.factor > 1)
675  {
676  parm_attrs[FunctionArchitecture::parm_elem_count] = STR(info.factor);
677  }
678  return "array";
679  }
680  else if(interface_type == "ptrdefault")
681  {
682  if(info.factor > 1)
683  {
684  parm_attrs[FunctionArchitecture::parm_elem_count] = STR(info.factor);
685  return "array";
686  }
687  return "none";
688  }
689  else if(interface_type == "ovalid")
690  {
691  THROW_ERROR("parameter " + arg_name + " cannot have interface " + interface_type +
692  " because it is read only");
693  }
694  }
695  else if(isWrite)
696  {
697  iface_attrs[FunctionArchitecture::iface_direction] = port_o::GetString(port_o::OUT);
698  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "---Write-only interface");
699  if(interface_type == "array")
700  {
701  if(info.factor > 1)
702  {
703  parm_attrs[FunctionArchitecture::parm_elem_count] = std::to_string(info.factor);
704  }
705  return "array";
706  }
707  else if(interface_type == "ptrdefault")
708  {
709  if(info.factor > 1)
710  {
711  parm_attrs[FunctionArchitecture::parm_elem_count] = std::to_string(info.factor);
712  return "array";
713  }
714  else if(parameters->IsParameter("none-ptrdefault") &&
715  parameters->GetParameter<int>("none-ptrdefault") == 1)
716  {
717  return "none";
718  }
719  else if(parameters->IsParameter("none-registered-ptrdefault") &&
720  parameters->GetParameter<int>("none-registered-ptrdefault") == 1)
721  {
722  iface_attrs[FunctionArchitecture::iface_register] = "";
723  return "none";
724  }
725  return "valid";
726  }
727  }
728  return interface_type;
729  }();
730  iface_attrs[FunctionArchitecture::iface_bitwidth] = std::to_string(info.bitwidth);
731  iface_attrs[FunctionArchitecture::iface_alignment] = std::to_string(info.alignment);
732  if(interface_type == "fifo" || interface_type == "axis")
733  {
734  iface_attrs.emplace(FunctionArchitecture::iface_depth, "0");
735  }
736  interface_type = info.name;
737 
738  THROW_ASSERT(info.bitwidth, "Expected non-zero bitwidth");
739 
740  std::set<std::string> operationsR, operationsW;
741  const auto interface_datatype = tree_man->GetCustomIntegerType(info.bitwidth, true);
742  const auto commonRWSignature = interface_type == "array" || interface_type == "m_axi";
743  const auto& bundle_name = iface_attrs.at(FunctionArchitecture::iface_name);
744  const auto require_flush =
745  interface_type == "m_axi" &&
746  iface_attrs.find(FunctionArchitecture::iface_cache_line_count) != iface_attrs.end();
747  const auto store_vdef = [&](const tree_nodeRef& stmt) {
748  if(require_flush)
749  {
750  const auto& vdef = GetPointerS<const gimple_node>(GET_CONST_NODE(stmt))->vdef;
751  if(vdef)
752  {
753  bundle_vdefs[bundle_name].insert(vdef);
754  }
755  }
756  };
757  for(const auto& stmt : readStmt)
758  {
759  setReadInterface(stmt, bundle_name, operationsR, commonRWSignature, interface_datatype, tree_man, TM);
760  add_to_modified(stmt);
761  store_vdef(stmt);
762  }
763  for(const auto& stmt : writeStmt)
764  {
765  setWriteInterface(stmt, bundle_name, operationsW, commonRWSignature, interface_datatype, tree_man,
766  TM);
767  add_to_modified(stmt);
768  store_vdef(stmt);
769  }
770  create_resource(operationsR, operationsW, info, func_arch);
771  }
772  else if(interface_type == "none")
773  {
774  THROW_ERROR("Interface type '" + interface_type + "' for parameter '" + arg_name + "' unexpected");
775  }
776  else
777  {
778  THROW_ERROR("Interface type '" + interface_type + "' for parameter '" + arg_name + "' is not supported");
779  }
780  }
781  INDENT_OUT_MEX(OUTPUT_LEVEL_MINIMUM, output_level, "-->Interface specification:");
782  INDENT_OUT_MEX(OUTPUT_LEVEL_MINIMUM, output_level, "---Parameter : " + arg_name);
783  INDENT_OUT_MEX(OUTPUT_LEVEL_MINIMUM, output_level, "---Protocol : " + interface_type);
785  "---Direction : " + iface_attrs.at(FunctionArchitecture::iface_direction));
787  "---Bundle : " + parm_attrs.at(FunctionArchitecture::parm_bundle));
789  "---Bitwidth : " + iface_attrs.at(FunctionArchitecture::iface_bitwidth));
790  if(parm_attrs.find(FunctionArchitecture::parm_elem_count) != parm_attrs.end())
791  {
793  "---Size : " + parm_attrs.at(FunctionArchitecture::parm_elem_count));
794  }
796  "---Alignment : " + iface_attrs.at(FunctionArchitecture::iface_alignment));
798  }
799  /* Add cache flush operation */
800  for(const auto& bundle_vdef : bundle_vdefs)
801  {
802  const auto& bundle_name = bundle_vdef.first;
803  const auto& vdefs = bundle_vdef.second;
804  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Interface finalizer for bundle " + bundle_name);
805  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Virtuals count: " + STR(vdefs.size()));
806  const auto generate_fini_call = [&]() {
807  const auto fini_fname = ENCODE_FDNAME(bundle_name, "_Flush_", "m_axi");
808  std::vector<tree_nodeConstRef> argsT;
809  argsT.push_back(tree_man->GetBooleanType());
810  argsT.push_back(tree_man->GetUnsignedIntegerType());
811  const auto fini_fd = tree_man->create_function_decl(fini_fname, fd->scpe, argsT, tree_man->GetVoidType(),
812  BUILTIN_SRCP, false);
813 
814  // Cache flush is indicated by a write of size 0.
815  std::vector<tree_nodeRef> args;
816  args.push_back(TM->CreateUniqueIntegerCst(1, argsT.at(0)));
817  args.push_back(TM->CreateUniqueIntegerCst(0, argsT.at(1)));
818  const auto fini_call = tree_man->create_gimple_call(fini_fd, args, GET_INDEX_NODE(fd->scpe), BUILTIN_SRCP);
819  const auto fini_node = GetPointerS<gimple_node>(GET_CONST_NODE(fini_call));
820  for(const auto& vdef : vdefs)
821  {
822  fini_node->AddVuse(vdef);
823  }
824  return fini_call;
825  };
826 
827  const auto sl = GetPointerS<const statement_list>(GET_CONST_NODE(fd->body));
828  for(const auto& bbi_bb : sl->list_of_bloc)
829  {
830  const auto& bb = bbi_bb.second;
831  const auto is_last = std::count(bb->list_of_succ.cbegin(), bb->list_of_succ.cend(), BB_EXIT);
832  if(bb->number != BB_ENTRY && is_last)
833  {
834  const auto fini_call = generate_fini_call();
835  THROW_ASSERT(bb->CGetStmtList().size(), "BB" + STR(bb->number) + " should not be empty");
836  const auto last_stmt = bb->CGetStmtList().back();
837  if(GetPointer<const gimple_return>(GET_CONST_NODE(last_stmt)))
838  {
839  bb->PushBefore(fini_call, last_stmt, AppM);
840  }
841  else
842  {
843  bb->PushBack(fini_call, AppM);
844  }
846  "---Added function call " + STR(fini_call) + " to BB" + STR(bb->number));
847  }
848  }
850  }
851 
852  INDENT_OUT_MEX(OUTPUT_LEVEL_MINIMUM, output_level, "<--Analyzed function " + fsymbol);
853  }
854 
855  // Remove interface information for non interfaced functions to avoid issues with aggressive IR optimizations
856  // (signature modification, SROA, ...)
857  for(auto it = HLSMgr->module_arch->cbegin(); it != HLSMgr->module_arch->cend();)
858  {
859  const auto fnode = TM->GetFunction(it->first);
860  if(!fnode || (it->second->attrs.size() <= 2 && std::find(sorted_roots.begin(), sorted_roots.end(),
861  GET_INDEX_CONST_NODE(fnode)) == sorted_roots.end()))
862  {
864  "Erase function architecture for function " + it->first);
865  it = HLSMgr->module_arch->erase(it);
866  }
867  else
868  {
869  ++it;
870  }
871  }
872 
873  already_executed = true;
874  if(modified.size())
875  {
876  for(const auto& f_id : modified)
877  {
878  AppM->GetFunctionBehavior(f_id)->UpdateBBVersion();
879  }
881  }
883 }
884 
886  std::list<tree_nodeRef>& writeStmt, std::list<tree_nodeRef>& readStmt,
887  interface_info& info)
888 {
889  const auto TM = AppM->get_tree_manager();
890  enum call_type
891  {
892  ct_forward,
893  ct_read,
894  ct_write
895  };
896  const auto propagate_arg_use = [&](tree_nodeRef arg_var, size_t use_count, tree_nodeRef fd_node,
897  const std::vector<tree_nodeRef>& call_args, tree_nodeRef& ssa_var) -> call_type {
898  THROW_ASSERT(arg_var && fd_node, "unexpected condition");
899  ssa_var = arg_var;
900  const auto call_fd = [&]() {
901  const auto fd_kind = GET_CONST_NODE(fd_node)->get_kind();
902  auto& fn = fd_node;
903  if(fd_kind == addr_expr_K)
904  {
905  fn = GetPointerS<const addr_expr>(GET_CONST_NODE(fd_node))->op;
906  }
907  THROW_ASSERT(GET_CONST_NODE(fn)->get_kind() == function_decl_K,
908  "unexpected condition: " + GET_CONST_NODE(fn)->get_kind_text());
909  return GetPointerS<const function_decl>(GET_CONST_NODE(fn));
910  }();
911  if(!call_fd->body)
912  {
913  const auto called_fname = [&]() {
914  const auto fname = tree_helper::print_function_name(TM, call_fd);
915  const auto demangled = cxa_demangle(fname);
916  return demangled.size() ? demangled : fname;
917  }();
918  if(called_fname.find(STR_CST_interface_parameter_keyword) != std::string::npos)
919  {
920  const auto arg_id = called_fname.substr(0, called_fname.find(STR_CST_interface_parameter_keyword));
921  if(arg_id != info.arg_id)
922  {
923  const auto func_arch = GetPointer<HLS_manager>(AppM)->module_arch->GetArchitecture(info.interface_fname);
924  THROW_ASSERT(func_arch, "Expected initialized architecture for function " + info.interface_fname);
925  const auto bundle_id = func_arch->parms.at(arg_id).at(FunctionArchitecture::parm_bundle);
926  const auto info_bundle_id = func_arch->parms.at(info.arg_id).at(FunctionArchitecture::parm_bundle);
927  if(bundle_id != info_bundle_id)
928  {
929  THROW_ERROR("Pattern not supported with required I/O interface: parameters '" + arg_id + "' and '" +
930  info.arg_id + "' share a memory operation");
931  }
932  }
933  return call_type::ct_forward;
934  }
935  else if(called_fname.find("ac_channel") != std::string::npos)
936  {
937  if(called_fname.find("::_read") != std::string::npos)
938  {
939  if(call_fd->list_of_args.size() >= 1 && call_fd->list_of_args.size() <= 3)
940  {
941  auto ret_type = GET_CONST_NODE(call_fd->type);
942  if(ret_type->get_kind() == function_type_K || ret_type->get_kind() == method_type_K)
943  {
944  const auto ft = GetPointerS<const function_type>(ret_type);
945  if(GET_CONST_NODE(ft->retn)->get_kind() != void_type_K)
946  {
947  ssa_var = ft->retn;
948  }
949  else
950  {
951  THROW_ASSERT(call_fd->list_of_args.size() >= 2, "unexpected condition");
952  THROW_ASSERT(call_args.size() >= 2, "unexpected condition");
953  auto first_arg = call_args.at(0);
954  THROW_ASSERT(tree_helper::IsPointerType(first_arg), "unexpected condition");
955  ssa_var = TM->CGetTreeReindex(tree_helper::GetBaseVariable(first_arg)->index);
956  THROW_ASSERT(ssa_var != first_arg, "unexpected condition");
957  }
958  }
959  else
960  {
961  THROW_ERROR("unexpected condition");
962  }
963  }
964  else
965  {
966  THROW_ERROR("unexpected condition");
967  }
968  return call_type::ct_read;
969  }
970  else if(called_fname.find("::_write") != std::string::npos)
971  {
972  if(call_fd->list_of_args.size() == 2)
973  {
974  auto ret_type = GET_CONST_NODE(call_fd->type);
975  if(ret_type->get_kind() == void_type_K)
976  {
977  THROW_ERROR("unexpected condition");
978  }
979  if(tree_helper::IsPointerType(call_fd->list_of_args.at(1)))
980  {
981  auto second_arg = call_args.at(1);
982  ssa_var = TM->CGetTreeReindex(tree_helper::GetBaseVariable(second_arg)->index);
983  THROW_ASSERT(ssa_var != second_arg, "unexpected condition");
984  }
985  else
986  {
987  ssa_var = call_fd->list_of_args.at(1);
988  }
989  }
990  else
991  {
992  THROW_ERROR("unexpected condition");
993  }
994  return call_type::ct_write;
995  }
996  THROW_UNREACHABLE("AC channel method not supported: " + called_fname);
997  }
998  THROW_UNREACHABLE("Hardware function " + called_fname + " interfacing not supported.");
999  }
1000 
1001  size_t par_index = 0U;
1002  for(auto use_idx = 0U; use_idx < use_count; ++use_idx, ++par_index)
1003  {
1004  // look for the actual vs formal parameter binding
1005  par_index = [&](size_t start_idx) {
1006  for(auto idx = start_idx; idx < call_args.size(); ++idx)
1007  {
1008  if(GET_INDEX_CONST_NODE(call_args[idx]) == GET_INDEX_CONST_NODE(arg_var))
1009  {
1010  return idx;
1011  }
1012  }
1013  THROW_ERROR("Use of " + arg_var->ToString() + " not found.");
1014  return static_cast<size_t>(-1);
1015  }(par_index);
1016  THROW_ASSERT(call_fd->list_of_args.size() > par_index, "unexpected condition");
1017  const auto called_param = call_fd->list_of_args.at(par_index);
1018 
1019  const auto call_arg_ssa_id = AppM->getSSAFromParm(call_fd->index, GET_INDEX_CONST_NODE(called_param));
1020  const auto call_arg_ssa = TM->CGetTreeReindex(call_arg_ssa_id);
1021  THROW_ASSERT(GET_CONST_NODE(call_arg_ssa)->get_kind() == ssa_name_K, "");
1022  if(GetPointerS<const ssa_name>(GET_CONST_NODE(call_arg_ssa))->CGetUseStmts().size())
1023  {
1024  forwardInterface(fd_node, called_param, info);
1025 
1028  "-->Pointer forwarded as function argument " + STR(par_index));
1029  ChasePointerInterfaceRecurse(Visited, call_arg_ssa, writeStmt, readStmt, info);
1030  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "<--Sub-function done");
1031  }
1032  }
1033  return call_type::ct_forward;
1034  };
1035  const auto push_stmt = [&](tree_nodeRef stmt, call_type ct, tree_nodeRef val) {
1036  if(ct == call_type::ct_forward)
1037  {
1038  return;
1039  }
1040  if(ct == call_type::ct_read)
1041  {
1042  readStmt.push_back(stmt);
1043  info.update(val, "", parameters);
1044  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "--- LOAD OPERATION");
1045  }
1046  else if(ct == call_type::ct_write)
1047  {
1048  writeStmt.push_back(stmt);
1049  info.update(val, "", parameters);
1050  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "--- STORE OPERATION");
1051  }
1052  };
1053  if(!Visited.insert(GET_INDEX_CONST_NODE(ssa_node)).second)
1054  {
1056  "---SKIPPED FUNCTION: already visited through argument " + ssa_node->ToString());
1057  return;
1058  }
1059 
1060  std::queue<tree_nodeRef> chase_ssa;
1061  chase_ssa.push(ssa_node);
1062  while(chase_ssa.size())
1063  {
1064  ssa_node = chase_ssa.front();
1065  const auto ssa_var = GetPointer<const ssa_name>(GET_CONST_NODE(ssa_node));
1066  chase_ssa.pop();
1068  "-->SSA VARIABLE: " + ssa_var->ToString() + " with " + STR(ssa_var->CGetUseStmts().size()) +
1069  " use statements");
1070  for(const auto& stmt_count : ssa_var->CGetUseStmts())
1071  {
1072  const auto use_stmt = GET_CONST_NODE(stmt_count.first);
1073  const auto& use_count = stmt_count.second;
1074  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "---STMT: " + use_stmt->ToString());
1075  if(const auto ga = GetPointer<const gimple_assign>(use_stmt))
1076  {
1077  const auto op0_kind = GET_CONST_NODE(ga->op0)->get_kind();
1078  const auto op1_kind = GET_CONST_NODE(ga->op1)->get_kind();
1079  if(op0_kind == mem_ref_K)
1080  {
1081  if(op1_kind == mem_ref_K)
1082  {
1083  THROW_ERROR("Pattern currently not supported: *x=*y; " + use_stmt->ToString());
1084  }
1085  else
1086  {
1087  THROW_ASSERT(op1_kind == ssa_name_K || GetPointer<const cst_node>(GET_CONST_NODE(ga->op1)),
1088  "unexpected condition");
1089  if(GetPointer<const cst_node>(GET_CONST_NODE(ga->op1)) ||
1090  GetPointer<const ssa_name>(GET_CONST_NODE(ga->op1)) != ssa_var)
1091  {
1092  push_stmt(stmt_count.first, call_type::ct_write, ga->op1);
1093  }
1094  }
1095  }
1096  else if(op1_kind == mem_ref_K)
1097  {
1098  push_stmt(stmt_count.first, call_type::ct_read, ga->op0);
1099  if(tree_helper::IsPointerType(ga->op0))
1100  {
1101  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "---Pointer to pointer interface propagation");
1102  chase_ssa.push(ga->op0);
1103  }
1104  }
1105  else if(op1_kind == call_expr_K)
1106  {
1107  const auto ce = GetPointerS<const call_expr>(GET_CONST_NODE(ga->op1));
1108  const auto return_type = tree_helper::CGetType(ga->op0);
1109  if(tree_helper::IsPointerType(return_type))
1110  {
1111  THROW_ERROR("unexpected pattern");
1112  }
1113  tree_nodeRef ssa_val;
1114  const auto ct = propagate_arg_use(ssa_node, use_count, ce->fn, ce->args, ssa_val);
1115  push_stmt(stmt_count.first, ct, ssa_val);
1116  }
1117  else if(op1_kind == eq_expr_K || op1_kind == ne_expr_K || op1_kind == gt_expr_K || op1_kind == lt_expr_K ||
1118  op1_kind == ge_expr_K || op1_kind == le_expr_K)
1119  {
1120  THROW_WARNING("Pattern potentially not supported: pointer parameter is used in a compare statement: " +
1121  use_stmt->ToString() + ":" + GET_CONST_NODE(ga->op1)->get_kind_text());
1122  }
1123  else
1124  {
1125  if(!tree_helper::IsPointerType(ga->op0))
1126  {
1127  THROW_WARNING("Pattern potentially not supported: parameter converted to non-pointer type: " +
1128  use_stmt->ToString() + ":" + GET_CONST_NODE(ga->op1)->get_kind_text());
1129  }
1130  else if(op1_kind != nop_expr_K && op1_kind != view_convert_expr_K && op1_kind != ssa_name_K &&
1131  op1_kind != pointer_plus_expr_K && op1_kind != cond_expr_K)
1132  {
1133  THROW_WARNING("Pattern potentially not supported: parameter used in a non-supported statement: " +
1134  use_stmt->ToString() + ":" + GET_CONST_NODE(ga->op1)->get_kind_text());
1135  }
1136  ChasePointerInterfaceRecurse(Visited, ga->op0, writeStmt, readStmt, info);
1137  }
1138  }
1139  else if(const auto gc = GetPointer<const gimple_call>(use_stmt))
1140  {
1141  THROW_ASSERT(gc->fn, "unexpected condition");
1142  const auto fn_node = GET_CONST_NODE(gc->fn);
1143  if(fn_node->get_kind() == addr_expr_K)
1144  {
1145  const auto ae = GetPointerS<const addr_expr>(fn_node);
1146  const auto ae_op = GET_CONST_NODE(ae->op);
1147  if(ae_op->get_kind() == function_decl_K)
1148  {
1149  tree_nodeRef ssa_val;
1150  const auto ct = propagate_arg_use(ssa_node, use_count, ae->op, gc->args, ssa_val);
1151  push_stmt(stmt_count.first, ct, ssa_val);
1152  }
1153  else
1154  {
1155  THROW_ERROR("unexpected pattern: " + ae_op->ToString());
1156  }
1157  }
1158  else if(fn_node)
1159  {
1160  THROW_ERROR("unexpected pattern: " + fn_node->ToString());
1161  }
1162  else
1163  {
1164  THROW_ERROR("unexpected pattern");
1165  }
1166  }
1167  else if(const auto gp = GetPointer<const gimple_phi>(use_stmt))
1168  {
1169  THROW_ASSERT(ssa_var, "unexpected condition");
1170  THROW_ASSERT(!ssa_var->virtual_flag, "unexpected condition");
1171  ChasePointerInterfaceRecurse(Visited, gp->res, writeStmt, readStmt, info);
1172  }
1173  else
1174  {
1175  THROW_ERROR("USE PATTERN unexpected: " + use_stmt->ToString());
1176  }
1177  }
1179  }
1180 }
1181 
1182 void InterfaceInfer::ChasePointerInterface(tree_nodeRef ssa_node, std::list<tree_nodeRef>& writeStmt,
1183  std::list<tree_nodeRef>& readStmt, interface_info& info)
1184 {
1186  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "-->Parameter uses:");
1187  ChasePointerInterfaceRecurse(Visited, ssa_node, writeStmt, readStmt, info);
1189 }
1190 
1191 void InterfaceInfer::forwardInterface(const tree_nodeRef& fnode, const tree_nodeRef& parm_node,
1192  const interface_info& info)
1193 {
1194  const auto fd = GetPointer<const function_decl>(GET_CONST_NODE(fnode));
1195  const auto fsymbol = tree_helper::GetMangledFunctionName(fd);
1196  const auto func_arch = GetPointerS<HLS_manager>(AppM)->module_arch->GetArchitecture(fsymbol);
1197  if(func_arch)
1198  {
1199  // Update function architecture information on called function
1200  const auto pname = get_decl_name(parm_node);
1201  auto bname = func_arch->parms.at(pname).at(FunctionArchitecture::parm_bundle);
1202 #if HAVE_ASSERTS
1203  const auto ecount =
1204 #endif
1205  func_arch->parms.erase(pname);
1206  THROW_ASSERT(ecount, "Expected parameter information for parameter " + pname + " in function " + fsymbol);
1207  const auto is_bundle_used =
1208  std::any_of(func_arch->parms.begin(), func_arch->parms.end(), [&](const auto& name_attrs) {
1209  return name_attrs.second.at(FunctionArchitecture::parm_bundle) == bname;
1210  });
1211  if(!is_bundle_used)
1212  {
1213  func_arch->ifaces.erase(bname);
1214  }
1215  THROW_ASSERT(func_arch->parms.find(pname) == func_arch->parms.end(),
1216  "Duplicate parameter name " + pname + " in " + fsymbol + ".");
1217  bname = info.iface_attrs.at(FunctionArchitecture::iface_name);
1218  func_arch->parms[pname] = info.parm_attrs;
1219  func_arch->parms[pname].at(FunctionArchitecture::parm_port) = pname;
1220  func_arch->parms[pname].at(FunctionArchitecture::parm_bundle) = bname;
1221  if(func_arch->ifaces.find(bname) == func_arch->ifaces.end())
1222  {
1223  func_arch->ifaces[bname] = info.iface_attrs;
1224  }
1225  else
1226  {
1227  THROW_ASSERT(func_arch->ifaces.find(bname)->second.at(FunctionArchitecture::iface_mode) ==
1228  info.iface_attrs.at(FunctionArchitecture::iface_mode),
1229  "Duplicate interface bundle name " + bname + " in " + fsymbol + ".");
1230  }
1231  }
1232 }
1233 
1234 void InterfaceInfer::setReadInterface(tree_nodeRef stmt, const std::string& arg_name,
1235  std::set<std::string>& operationsR, bool commonRWSignature,
1236  tree_nodeConstRef interface_datatype, const tree_manipulationRef tree_man,
1237  const tree_managerRef TM)
1238 {
1239  const auto gn = GetPointerS<gimple_node>(GET_NODE(stmt));
1240  THROW_ASSERT(gn->scpe && GET_CONST_NODE(gn->scpe)->get_kind() == function_decl_K, "expected a function_decl scope");
1241  const auto fd = GetPointerS<function_decl>(GET_CONST_NODE(gn->scpe));
1242  const auto fname = tree_helper::GetMangledFunctionName(fd);
1243  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "-->LOAD from " + fname + ":");
1244  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "---BEFORE: " + stmt->ToString());
1245 
1246  THROW_ASSERT(fd->body, "expected a body");
1247  const auto sl = GetPointerS<statement_list>(GET_NODE(fd->body));
1248  const auto curr_bb = sl->list_of_bloc.at(gn->bb_index);
1249  const auto ret_call = GET_NODE(stmt)->get_kind() == gimple_assign_K &&
1250  GET_NODE(GetPointerS<gimple_assign>(GET_NODE(stmt))->op1)->get_kind() == call_expr_K;
1251  const auto ref_call = GET_NODE(stmt)->get_kind() == gimple_call_K;
1252  if(ret_call || ref_call)
1253  {
1254  bool valid_var;
1255  tree_nodeRef valid_ptr;
1256  tree_nodeConstRef data_type;
1257  tree_nodeRef stmt_op0;
1258  tree_nodeRef data_ptr;
1259  if(ret_call)
1260  {
1261  const auto ga = GetPointerS<const gimple_assign>(GET_CONST_NODE(stmt));
1262  stmt_op0 = ga->op0;
1263  const auto ce = GetPointerS<const call_expr>(GET_CONST_NODE(ga->op1));
1264  valid_var = ce->args.size() == 2;
1265  data_type = tree_helper::CGetType(ga->op0);
1266  if(valid_var)
1267  {
1268  valid_ptr = ce->args.at(1);
1269  }
1270  else
1271  {
1272  THROW_ASSERT(ce->args.size() == 1, "unexpected condition");
1273  }
1274  }
1275  else
1276  {
1277  const auto gc = GetPointerS<const gimple_call>(GET_CONST_NODE(stmt));
1278  valid_var = gc->args.size() == 3;
1279  auto first_arg = gc->args.at(0);
1280  THROW_ASSERT(tree_helper::IsPointerType(first_arg), "unexpected condition");
1281  data_ptr = first_arg;
1282  auto data_obj = TM->CGetTreeReindex(tree_helper::GetBaseVariable(first_arg)->index);
1283  THROW_ASSERT(data_obj != first_arg, "unexpected condition");
1284  data_type = tree_helper::CGetType(data_obj);
1285  if(valid_var)
1286  {
1287  valid_ptr = gc->args.at(2);
1288  }
1289  else
1290  {
1291  THROW_ASSERT(gc->args.size() == 2, "unexpected condition");
1292  }
1293  }
1294  THROW_ASSERT(!valid_ptr || tree_helper::IsPointerType(valid_ptr), "Valid type must be bool pointer");
1295  THROW_ASSERT(!gn->memdef && !gn->memuse, "");
1296  THROW_ASSERT(gn->vdef, "");
1297  const auto vdef = gn->vdef;
1298 
1299  const auto data_size = tree_helper::Size(data_type);
1300  const auto sel_type = tree_man->GetBooleanType();
1301  const auto ret_type = tree_man->GetCustomIntegerType(data_size + 1, true);
1302  const auto out_type = tree_man->GetCustomIntegerType(data_size, true);
1303  const auto out_ptr_type = tree_man->GetPointerType(out_type);
1304  const auto fdecl_node = [&]() {
1305  const auto interface_fname = ENCODE_FDNAME(arg_name, valid_var ? "_ReadAsync" : "_Read", "Channel");
1306  operationsR.insert(interface_fname);
1307  std::vector<tree_nodeConstRef> argsT;
1308  argsT.push_back(sel_type);
1309  return tree_man->create_function_decl(interface_fname, fd->scpe, argsT, ret_type, BUILTIN_SRCP, false);
1310  }();
1311 
1312  std::vector<tree_nodeRef> args;
1313  args.push_back(TM->CreateUniqueIntegerCst(valid_var, sel_type));
1314  const auto new_ce = tree_man->CreateCallExpr(fdecl_node, args, BUILTIN_SRCP);
1315  const auto new_call = tree_man->CreateGimpleAssign(ret_type, nullptr, nullptr, new_ce, fd->index, BUILTIN_SRCP);
1316  curr_bb->PushBefore(new_call, stmt, AppM);
1317  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "--- AFTER: " + new_call->ToString());
1318 
1319  // Mask and cast read data
1320  const auto retval = GetPointerS<const gimple_assign>(GET_CONST_NODE(new_call))->op0;
1321  auto ga_mask = tree_man->CreateNopExpr(retval, out_type, nullptr, nullptr, fd->index);
1322  curr_bb->PushBefore(ga_mask, stmt, AppM);
1323  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "--- MASK: " + ga_mask->ToString());
1324  auto data_mask = GetPointerS<const gimple_assign>(GET_CONST_NODE(ga_mask))->op0;
1325  if(tree_helper::IsRealType(data_type))
1326  {
1327  const auto vc = tree_man->create_unary_operation(data_type, data_mask, BUILTIN_SRCP, view_convert_expr_K);
1328  ga_mask = tree_man->CreateGimpleAssign(data_type, nullptr, nullptr, vc, fd->index, BUILTIN_SRCP);
1329  curr_bb->PushBefore(ga_mask, stmt, AppM);
1330  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "--- VIEW: " + ga_mask->ToString());
1331  data_mask = GetPointerS<const gimple_assign>(GET_CONST_NODE(ga_mask))->op0;
1332  }
1333 
1334  tree_nodeRef last_stmt;
1335  if(ret_call)
1336  {
1337  TM->ReplaceTreeNode(ga_mask, data_mask, stmt_op0);
1338  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "--- FIX: " + ga_mask->ToString());
1339  last_stmt = ga_mask;
1340  }
1341  else
1342  {
1343  const auto data_ptr_type = tree_helper::CGetType(data_ptr);
1344  const auto data_ref = tree_man->create_binary_operation(
1345  data_type, data_ptr, TM->CreateUniqueIntegerCst(0, data_ptr_type), BUILTIN_SRCP, mem_ref_K);
1346  const auto ga_store = tree_man->create_gimple_modify_stmt(data_ref, data_mask, fd->index, BUILTIN_SRCP);
1347  if(valid_var)
1348  {
1349  auto newSSAVdef = tree_man->create_ssa_name(tree_nodeRef(), tree_helper::CGetType(vdef), tree_nodeRef(),
1350  tree_nodeRef(), false, true);
1351  GetPointerS<gimple_assign>(GET_NODE(ga_store))->SetVdef(newSSAVdef);
1352  for(const auto& vuse : GetPointerS<gimple_assign>(GET_NODE(stmt))->vuses)
1353  {
1354  if(GetPointerS<gimple_node>(GET_NODE(ga_store))->AddVuse(vuse))
1355  {
1356  GetPointerS<ssa_name>(GET_NODE(vuse))->AddUseStmt(ga_store);
1357  }
1358  }
1359  THROW_ASSERT(GET_NODE(vdef)->get_kind() == ssa_name_K, "unexpected condition");
1360  auto vdef_ssa = GetPointerS<ssa_name>(GET_NODE(vdef));
1361  for(const auto& usingStmt : vdef_ssa->CGetUseStmts())
1362  {
1363  if(GetPointerS<gimple_node>(GET_NODE(usingStmt.first))->AddVuse(newSSAVdef))
1364  {
1365  GetPointerS<ssa_name>(GET_NODE(newSSAVdef))->AddUseStmt(usingStmt.first);
1366  }
1367  }
1368  curr_bb->PushBefore(ga_store, stmt, AppM);
1369  }
1370  else
1371  {
1372  curr_bb->Replace(stmt, ga_store, true, AppM);
1373  }
1374  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "--- STORE: " + ga_store->ToString());
1375 
1376  last_stmt = ga_store;
1377  }
1378 
1379  if(valid_var)
1380  {
1381  // Mask and cast valid bit
1382  const auto be_vshift = tree_man->create_binary_operation(
1383  ret_type, retval, TM->CreateUniqueIntegerCst(data_size, ret_type), BUILTIN_SRCP, rshift_expr_K);
1384  const auto ga_vshift =
1385  tree_man->CreateGimpleAssign(ret_type, nullptr, nullptr, be_vshift, fd->index, BUILTIN_SRCP);
1386  curr_bb->PushBefore(ga_vshift, stmt, AppM);
1387  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "---VSHIFT: " + ga_vshift->ToString());
1388  const auto v_shift = GetPointerS<const gimple_assign>(GET_CONST_NODE(ga_vshift))->op0;
1389  const auto valid_ptd_type = tree_man->GetBooleanType();
1390  const auto valid_type = tree_man->GetPointerType(valid_ptd_type);
1391  const auto ga_valid = tree_man->CreateNopExpr(v_shift, valid_ptd_type, nullptr, nullptr, fd->index);
1392  curr_bb->PushBefore(ga_valid, stmt, AppM);
1393  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "--- VALID: " + ga_valid->ToString());
1394  const auto valid_ref = GetPointerS<const gimple_assign>(GET_CONST_NODE(ga_valid))->op0;
1395  const auto valid_memref = tree_man->create_binary_operation(
1396  valid_ptd_type, valid_ptr, TM->CreateUniqueIntegerCst(0, valid_type), BUILTIN_SRCP, mem_ref_K);
1397  const auto ga_valid_store =
1398  tree_man->create_gimple_modify_stmt(valid_memref, valid_ref, fd->index, BUILTIN_SRCP);
1399  curr_bb->Replace(stmt, ga_valid_store, true, AppM);
1400  if(!ret_call)
1401  {
1402  auto ssaDef = GetPointerS<gimple_assign>(GET_NODE(last_stmt))->vdef;
1403  if(GetPointerS<gimple_node>(GET_NODE(ga_valid_store))->AddVuse(ssaDef))
1404  {
1405  GetPointerS<ssa_name>(GET_NODE(ssaDef))->AddUseStmt(ga_valid_store);
1406  }
1407  }
1408  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "--- VALID STORE: " + ga_valid_store->ToString());
1409  }
1410  else if(ret_call)
1411  {
1412  curr_bb->RemoveStmt(stmt, AppM);
1413  }
1414  }
1415  else
1416  {
1417  THROW_ASSERT(stmt && GET_NODE(stmt)->get_kind() == gimple_assign_K, "unexpected condition");
1418  const auto ga = GetPointerS<gimple_assign>(GET_NODE(stmt));
1419  THROW_ASSERT(GET_NODE(ga->op1)->get_kind() == mem_ref_K, "unexpected condition");
1420 
1422  const auto actual_type = tree_helper::CGetType(ga->op0);
1423  const auto bit_size_type = tree_man->GetUnsignedIntegerType();
1424  const auto boolean_type = tree_man->GetBooleanType();
1425  const auto fdecl_node = [&]() {
1426  const auto interface_fname = ENCODE_FDNAME(arg_name, "_Read", "");
1427  operationsR.insert(interface_fname);
1428  std::vector<tree_nodeConstRef> argsT;
1429  if(commonRWSignature)
1430  {
1431  argsT.push_back(boolean_type);
1432  argsT.push_back(bit_size_type);
1433  argsT.push_back(interface_datatype);
1434  }
1435  argsT.push_back(tree_helper::CGetType(ga->op1));
1436  return tree_man->create_function_decl(interface_fname, fd->scpe, argsT, interface_datatype, BUILTIN_SRCP,
1437  false);
1438  }();
1439  std::vector<tree_nodeRef> args;
1440  if(commonRWSignature)
1441  {
1442  const auto sel_value = TM->CreateUniqueIntegerCst(0, boolean_type);
1443  const auto size_value =
1444  TM->CreateUniqueIntegerCst(static_cast<long long>(tree_helper::Size(actual_type)), bit_size_type);
1445 
1446  const auto data_value = TM->CreateUniqueIntegerCst(0, interface_datatype);
1447  args.push_back(sel_value);
1448  args.push_back(size_value);
1449  args.push_back(data_value);
1450  }
1451 
1452  THROW_ASSERT(GET_CONST_NODE(ga->op1)->get_kind() == mem_ref_K, "unexpected condition");
1453  const auto mr = GetPointerS<const mem_ref>(GET_CONST_NODE(ga->op1));
1454  args.push_back(mr->op0);
1455 
1456  const auto ce = tree_man->CreateCallExpr(fdecl_node, args, BUILTIN_SRCP);
1457  if(tree_helper::IsSameType(interface_datatype, actual_type))
1458  {
1459  TM->ReplaceTreeNode(stmt, ga->op1, ce);
1462  GET_INDEX_CONST_NODE(fdecl_node), GET_INDEX_CONST_NODE(stmt),
1464  GetPointer<HLS_manager>(AppM)->design_interface_io[fname][ga->bb_index][arg_name].push_back(
1465  GET_INDEX_CONST_NODE(stmt));
1466  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "--- AFTER: " + stmt->ToString());
1467  }
1468  else
1469  {
1470  const auto is_real = tree_helper::IsRealType(actual_type);
1471  const auto tmp_type =
1472  is_real ? tree_man->GetCustomIntegerType(tree_helper::Size(actual_type), true) : interface_datatype;
1473  const auto tmp_ssa = tree_man->create_ssa_name(nullptr, tmp_type, nullptr, nullptr);
1474  const auto gc = tree_man->create_gimple_modify_stmt(tmp_ssa, ce, fd->index, BUILTIN_SRCP);
1475  curr_bb->Replace(stmt, gc, true, AppM);
1476  const auto vc = tree_man->create_unary_operation(actual_type, tmp_ssa, BUILTIN_SRCP,
1477  is_real ? view_convert_expr_K : nop_expr_K);
1478  const auto cast = tree_man->create_gimple_modify_stmt(ga->op0, vc, fd->index, BUILTIN_SRCP);
1479  curr_bb->PushAfter(cast, gc, AppM);
1480  GetPointer<HLS_manager>(AppM)->design_interface_io[fname][curr_bb->number][arg_name].push_back(
1481  GET_INDEX_CONST_NODE(gc));
1482 
1483  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "--- AFTER: " + gc->ToString());
1484  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "--- NOP: " + stmt->ToString());
1485  }
1486  }
1488 }
1489 
1490 void InterfaceInfer::setWriteInterface(tree_nodeRef stmt, const std::string& arg_name,
1491  std::set<std::string>& operationsW, bool commonRWSignature,
1492  tree_nodeConstRef interface_datatype, const tree_manipulationRef tree_man,
1493  const tree_managerRef TM)
1494 {
1495  const auto gn = GetPointerS<gimple_node>(GET_NODE(stmt));
1496  THROW_ASSERT(gn->scpe && GET_CONST_NODE(gn->scpe)->get_kind() == function_decl_K, "expected a function_decl scope");
1497  const auto fd = GetPointerS<function_decl>(GET_CONST_NODE(gn->scpe));
1498  const auto fname = tree_helper::GetMangledFunctionName(fd);
1499  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "-->STORE from " + fname + ":");
1500  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "---BEFORE: " + stmt->ToString());
1501 
1502  THROW_ASSERT(fd->body, "expected a body");
1503  const auto sl = GetPointerS<statement_list>(GET_NODE(fd->body));
1504  const auto curr_bb = sl->list_of_bloc.at(gn->bb_index);
1505  const auto ret_call = GET_NODE(stmt)->get_kind() == gimple_assign_K &&
1506  GET_NODE(GetPointerS<gimple_assign>(GET_NODE(stmt))->op1)->get_kind() == call_expr_K;
1507  const auto ref_call = GET_NODE(stmt)->get_kind() == gimple_call_K;
1508  if(ret_call || ref_call)
1509  {
1510  tree_nodeRef data_obj;
1511  tree_nodeRef data_ptr;
1512  tree_nodeConstRef ret_type;
1513  bool valid_var;
1514  bool isAStruct = false;
1515  if(ret_call)
1516  {
1517  const auto ga = GetPointerS<const gimple_assign>(GET_CONST_NODE(stmt));
1518  const auto ce = GetPointerS<const call_expr>(GET_CONST_NODE(ga->op1));
1519  THROW_ASSERT(ce->args.size() == 2, "unexpected condition");
1520  data_obj = ce->args.at(1);
1521  if(tree_helper::IsPointerType(data_obj))
1522  {
1523  data_ptr = data_obj;
1524  data_obj = TM->CGetTreeReindex(tree_helper::GetBaseVariable(data_obj)->index);
1525  THROW_ASSERT(data_obj != data_ptr, "unexpected condition");
1526  isAStruct = true;
1527  }
1528  valid_var = true;
1529  ret_type = tree_helper::CGetType(ga->op0);
1530  }
1531  else
1532  {
1533  const auto gc = GetPointerS<const gimple_call>(GET_CONST_NODE(stmt));
1534  THROW_ASSERT(gc->args.size() == 2, "unexpected condition");
1535  data_obj = gc->args.at(1);
1536  if(tree_helper::IsPointerType(data_obj))
1537  {
1538  data_ptr = data_obj;
1539  data_obj = TM->CGetTreeReindex(tree_helper::GetBaseVariable(data_obj)->index);
1540  THROW_ASSERT(data_obj != data_ptr, "unexpected condition");
1541  isAStruct = true;
1542  }
1543  valid_var = false;
1544  ret_type = tree_man->GetVoidType();
1545  }
1546 
1547  const auto data_type = tree_helper::CGetType(data_obj);
1548  const auto data_size = tree_helper::Size(data_type);
1549  const auto sel_type = tree_man->GetBooleanType();
1550  const auto out_type = tree_man->GetCustomIntegerType(data_size, true);
1551  const auto out_ptr_type = tree_man->GetPointerType(out_type);
1552  const auto fdecl_node = [&]() {
1553  const auto interface_fname = ENCODE_FDNAME(arg_name, valid_var ? "_WriteAsync" : "_Write", "Channel");
1554  operationsW.insert(interface_fname);
1555  std::vector<tree_nodeConstRef> argsT;
1556  argsT.push_back(sel_type);
1557  argsT.push_back(data_type);
1558  return tree_man->create_function_decl(interface_fname, fd->scpe, argsT, ret_type, BUILTIN_SRCP, false);
1559  }();
1560 
1561  tree_nodeRef lastStmt;
1562  if(isAStruct)
1563  {
1564  const auto ga_ptr = tree_man->CreateNopExpr(data_ptr, out_ptr_type, nullptr, nullptr, fd->index);
1565  curr_bb->PushBefore(ga_ptr, stmt, AppM);
1566  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "--- PCAST: " + ga_ptr->ToString());
1567  const auto out_data_ptr = GetPointerS<const gimple_assign>(GET_CONST_NODE(ga_ptr))->op0;
1568  const auto data_ref = tree_man->create_binary_operation(
1569  out_type, out_data_ptr, TM->CreateUniqueIntegerCst(0, out_ptr_type), BUILTIN_SRCP, mem_ref_K);
1570  const auto ga_load =
1571  tree_man->CreateGimpleAssign(out_type, nullptr, nullptr, data_ref, fd->index, BUILTIN_SRCP);
1572  curr_bb->Replace(stmt, ga_load, true, AppM);
1573  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "--- LOAD: " + ga_load->ToString());
1574  data_obj = GetPointerS<const gimple_assign>(GET_CONST_NODE(ga_load))->op0;
1575  lastStmt = ga_load;
1576  }
1577  else if(tree_helper::IsRealType(data_type))
1578  {
1579  const auto vc = tree_man->create_unary_operation(data_type, data_obj, BUILTIN_SRCP, view_convert_expr_K);
1580  const auto ga_vc = tree_man->CreateGimpleAssign(out_type, nullptr, nullptr, vc, fd->index, BUILTIN_SRCP);
1581  curr_bb->PushBefore(ga_vc, stmt, AppM);
1582  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "--- VIEW: " + ga_vc->ToString());
1583  data_obj = GetPointerS<const gimple_assign>(GET_CONST_NODE(ga_vc))->op0;
1584  }
1585 
1586  std::vector<tree_nodeRef> args;
1587  args.push_back(TM->CreateUniqueIntegerCst(valid_var, sel_type));
1588  args.push_back(data_obj);
1589  if(valid_var)
1590  {
1591  const auto ga_stmt = GetPointerS<const gimple_assign>(GET_CONST_NODE(stmt));
1592  const auto ce = tree_man->CreateCallExpr(fdecl_node, args, BUILTIN_SRCP);
1593  const auto ga_call = tree_man->create_gimple_modify_stmt(ga_stmt->op0, ce, fd->index, BUILTIN_SRCP);
1594  if(isAStruct)
1595  {
1596  curr_bb->PushAfter(ga_call, lastStmt, AppM);
1597  }
1598  else
1599  {
1600  curr_bb->Replace(stmt, ga_call, true, AppM);
1601  }
1602  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "--- AFTER: " + ga_call->ToString());
1603  }
1604  else
1605  {
1606  const auto gc = tree_man->create_gimple_call(fdecl_node, args, fd->index, BUILTIN_SRCP);
1607  if(isAStruct)
1608  {
1609  curr_bb->PushAfter(gc, lastStmt, AppM);
1610  }
1611  else
1612  {
1613  curr_bb->Replace(stmt, gc, true, AppM);
1614  }
1615  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "--- AFTER: " + gc->ToString());
1616  }
1617  }
1618  else
1619  {
1620  THROW_ASSERT(stmt && GET_NODE(stmt)->get_kind() == gimple_assign_K, "unexpected condition");
1621  const auto ga = GetPointerS<gimple_assign>(GET_NODE(stmt));
1622  THROW_ASSERT(GET_NODE(ga->op0)->get_kind() == mem_ref_K, "unexpected condition");
1623 
1624  auto value_node = ga->op1;
1625  auto actual_type = tree_helper::CGetType(value_node);
1626  if(tree_helper::IsSameType(interface_datatype, actual_type))
1627  {
1628  tree_nodeRef nop;
1629  if(tree_helper::IsRealType(actual_type))
1630  {
1631  const auto int_type = tree_man->GetCustomIntegerType(tree_helper::Size(actual_type), true);
1632  const auto vc = tree_man->create_unary_operation(int_type, value_node, BUILTIN_SRCP, view_convert_expr_K);
1633  value_node = tree_man->create_ssa_name(nullptr, int_type, nullptr, nullptr);
1634  nop = tree_man->create_gimple_modify_stmt(value_node, vc, fd->index, BUILTIN_SRCP);
1635  }
1636  else
1637  {
1638  nop = tree_man->CreateNopExpr(value_node, interface_datatype, nullptr, nullptr,
1639  GET_INDEX_CONST_NODE(ga->scpe));
1640  value_node = GetPointerS<const gimple_assign>(GET_CONST_NODE(nop))->op0;
1641  }
1642  curr_bb->PushBefore(nop, stmt, AppM);
1643  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "--- NOP: " + nop->ToString());
1644  }
1645  const auto boolean_type = tree_man->GetBooleanType();
1646  const auto bit_size_type = tree_man->GetUnsignedIntegerType();
1647 
1649  const auto fdecl_node = [&]() {
1650  const auto interface_fname = ENCODE_FDNAME(arg_name, "_Write", "");
1651  operationsW.insert(interface_fname);
1652  std::vector<tree_nodeConstRef> argsT;
1653  if(commonRWSignature)
1654  {
1655  argsT.push_back(boolean_type);
1656  }
1657  argsT.push_back(bit_size_type);
1658  argsT.push_back(interface_datatype);
1659  argsT.push_back(tree_helper::CGetType(ga->op0));
1660 
1661  return tree_man->create_function_decl(interface_fname, fd->scpe, argsT, tree_man->GetVoidType(), BUILTIN_SRCP,
1662  false);
1663  }();
1664 
1665  std::vector<tree_nodeRef> args;
1666  if(commonRWSignature)
1667  {
1668  args.push_back(TM->CreateUniqueIntegerCst(1, boolean_type));
1669  }
1670  args.push_back(TM->CreateUniqueIntegerCst(static_cast<long long>(tree_helper::Size(actual_type)), bit_size_type));
1671  args.push_back(value_node);
1672  const auto mr = GetPointerS<const mem_ref>(GET_CONST_NODE(ga->op0));
1673  args.push_back(mr->op0);
1674 
1675  const auto gc = tree_man->create_gimple_call(fdecl_node, args, GET_INDEX_NODE(ga->scpe), BUILTIN_SRCP);
1676  curr_bb->Replace(stmt, gc, true, AppM);
1677  GetPointer<HLS_manager>(AppM)->design_interface_io[fname][curr_bb->number][arg_name].push_back(
1678  GET_INDEX_CONST_NODE(gc));
1679 
1680  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "--- AFTER: " + gc->ToString());
1681  }
1683 }
1684 
1685 void InterfaceInfer::create_resource_Read_simple(const std::set<std::string>& operations, const interface_info& info,
1686  FunctionArchitectureRef func_arch, bool IO_port) const
1687 {
1688  if(operations.empty())
1689  {
1690  return;
1691  }
1692  const auto& parm_attrs = func_arch->parms.at(info.arg_id);
1693  const auto& bundle_name = parm_attrs.at(FunctionArchitecture::parm_bundle);
1694  const std::string ResourceName = ENCODE_FDNAME(bundle_name, "_Read_", info.name);
1695  const auto HLSMgr = GetPointer<HLS_manager>(AppM);
1696  const auto HLS_D = HLSMgr->get_HLS_device();
1697  const auto TechMan = HLS_D->get_technology_manager();
1698  if(!TechMan->is_library_manager(INTERFACE_LIBRARY) ||
1699  !TechMan->get_library_manager(INTERFACE_LIBRARY)->is_fu(ResourceName))
1700  {
1702  "-->Creating interface resource: " + INTERFACE_LIBRARY + ":" + ResourceName);
1704  structural_type_descriptorRef module_type(new structural_type_descriptor(ResourceName));
1705  CM->set_top_info(ResourceName, module_type);
1706  const auto interface_top = CM->get_circ();
1708  GetPointerS<module>(interface_top)->set_description("Interface module for function: " + ResourceName);
1709  GetPointerS<module>(interface_top)->set_copyright(GENERATED_COPYRIGHT);
1710  GetPointerS<module>(interface_top)->set_authors("Component automatically generated by bambu");
1711  GetPointerS<module>(interface_top)->set_license(GENERATED_LICENSE);
1712  GetPointerS<module>(interface_top)->set_multi_unit_multiplicity(1U);
1713  const auto if_name = info.name == "ovalid" ? "none" : info.name;
1714  const auto is_unbounded = if_name == "valid" || if_name == "handshake" || if_name == "fifo" || if_name == "axis";
1715 
1716  const auto address_bitsize = HLSMgr->get_address_bitsize();
1717  structural_type_descriptorRef addrType(new structural_type_descriptor("bool", address_bitsize));
1719  const auto out_bitsize = if_name == "fifo" ? (info.bitwidth + 1U) : info.bitwidth;
1720  structural_type_descriptorRef outType(new structural_type_descriptor("bool", out_bitsize));
1722  CM->add_port(CLOCK_PORT_NAME, port_o::IN, interface_top, bool_type);
1723  CM->add_port(RESET_PORT_NAME, port_o::IN, interface_top, bool_type);
1724  CM->add_port_vector(START_PORT_NAME, port_o::IN, 1U, interface_top, bool_type);
1725  if(is_unbounded)
1726  {
1727  CM->add_port_vector(DONE_PORT_NAME, port_o::OUT, 1U, interface_top, bool_type);
1728  }
1729  const auto addrPort = CM->add_port("in1", port_o::IN, interface_top, addrType);
1730  GetPointerS<port_o>(addrPort)->set_is_addr_bus(true);
1731  GetPointerS<port_o>(addrPort)->set_port_alignment(info.alignment);
1732  CM->add_port("out1", port_o::OUT, interface_top, outType);
1733 
1734  std::string port_data_name = "_" + info.arg_id;
1735  port_o::port_interface port_if = port_o::port_interface::PI_RNONE;
1736  if(if_name == "axis")
1737  {
1738  port_data_name = "_s_axis_" + info.arg_id + "_TDATA";
1739  port_if = port_o::port_interface::PI_S_AXIS_TDATA;
1740  }
1741  else if(if_name == "fifo")
1742  {
1743  port_data_name += "_dout";
1744  port_if = port_o::port_interface::PI_FDOUT;
1745  }
1746  else if(IO_port)
1747  {
1748  port_data_name += "_i";
1749  }
1750  const auto inPort = CM->add_port(port_data_name, port_o::IN, interface_top, dataType);
1751  GetPointerS<port_o>(inPort)->set_port_interface(port_if);
1752  if(if_name == "acknowledge" || if_name == "handshake")
1753  {
1754  const auto inPort_o_ack =
1755  CM->add_port("_" + info.arg_id + (IO_port ? "_i" : "") + "_ack", port_o::OUT, interface_top, bool_type);
1756  GetPointerS<port_o>(inPort_o_ack)->set_port_interface(port_o::port_interface::PI_RACK);
1757  }
1758  if(if_name == "valid" || if_name == "handshake")
1759  {
1760  const auto inPort_o_vld =
1761  CM->add_port("_" + info.arg_id + (IO_port ? "_i" : "") + "_vld", port_o::IN, interface_top, bool_type);
1762  GetPointerS<port_o>(inPort_o_vld)->set_port_interface(port_o::port_interface::PI_RVALID);
1763  }
1764  if(if_name == "fifo")
1765  {
1766  const auto inPort_empty_n = CM->add_port("_" + info.arg_id + "_empty_n", port_o::IN, interface_top, bool_type);
1767  GetPointerS<port_o>(inPort_empty_n)->set_port_interface(port_o::port_interface::PI_EMPTY_N);
1768  const auto inPort_read = CM->add_port("_" + info.arg_id + "_read", port_o::OUT, interface_top, bool_type);
1769  GetPointerS<port_o>(inPort_read)->set_port_interface(port_o::port_interface::PI_READ);
1770  }
1771  if(if_name == "axis")
1772  {
1773  const auto inPort_empty_n =
1774  CM->add_port("_s_axis_" + info.arg_id + "_TVALID", port_o::IN, interface_top, bool_type);
1775  GetPointerS<port_o>(inPort_empty_n)->set_port_interface(port_o::port_interface::PI_S_AXIS_TVALID);
1776  const auto inPort_read =
1777  CM->add_port("_s_axis_" + info.arg_id + "_TREADY", port_o::OUT, interface_top, bool_type);
1778  GetPointerS<port_o>(inPort_read)->set_port_interface(port_o::port_interface::PI_S_AXIS_TREADY);
1779  }
1780 
1781  CM->add_NP_functionality(interface_top, NP_functionality::LIBRARY, "in1 out1");
1783  "Read_" + if_name + "ModuleGenerator");
1784  TechMan->add_resource(INTERFACE_LIBRARY, ResourceName, CM);
1785  for(const auto& fdName : operations)
1786  {
1787  TechMan->add_operation(INTERFACE_LIBRARY, ResourceName, fdName);
1788  }
1789  auto fu = GetPointerS<functional_unit>(TechMan->get_fu(ResourceName, INTERFACE_LIBRARY));
1790  fu->area_m = area_info::factory(parameters);
1791  fu->area_m->set_area_value(0);
1792  if(!is_unbounded)
1793  {
1794  fu->logical_type = functional_unit::COMBINATIONAL;
1795  }
1796 
1797  for(const auto& fdName : operations)
1798  {
1799  const auto op = GetPointer<operation>(fu->get_operation(fdName));
1800  op->time_m = time_info::factory(parameters);
1801  if(if_name == "fifo")
1802  {
1803  op->bounded = fdName.find("Async") != std::string::npos;
1804  const auto exec_time =
1805  (!op->bounded ? HLS_D->get_technology_manager()->CGetSetupHoldTime() : 0.0) + EPSILON;
1806  const auto cycles = op->bounded ? 1U : 0U;
1807  op->time_m->set_execution_time(exec_time, cycles);
1808  }
1809  else
1810  {
1811  op->bounded = !is_unbounded;
1812  const auto exec_time =
1813  (is_unbounded ? HLS_D->get_technology_manager()->CGetSetupHoldTime() : 0.0) + EPSILON;
1814  const auto cycles = if_name == "acknowledge" ? 1U : 0U;
1815  op->time_m->set_execution_time(exec_time, cycles);
1816  }
1817  op->time_m->set_synthesis_dependent(true);
1818  }
1819  HLSMgr->global_resource_constraints[std::make_pair(ResourceName, INTERFACE_LIBRARY)] = std::make_pair(1U, 1U);
1820  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "<--Interface resource created");
1821  }
1822 }
1823 
1824 void InterfaceInfer::create_resource_Write_simple(const std::set<std::string>& operations, const interface_info& info,
1825  FunctionArchitectureRef func_arch, bool IO_port) const
1826 {
1827  if(operations.empty())
1828  {
1829  return;
1830  }
1831  const auto& parm_attrs = func_arch->parms.at(info.arg_id);
1832  const auto& bundle_name = parm_attrs.at(FunctionArchitecture::parm_bundle);
1833  const std::string ResourceName = ENCODE_FDNAME(bundle_name, "_Write_", info.name);
1834  const auto HLSMgr = GetPointer<HLS_manager>(AppM);
1835  const auto HLS_D = HLSMgr->get_HLS_device();
1836  const auto TechMan = HLS_D->get_technology_manager();
1837  if(!operations.empty() && !(TechMan->is_library_manager(INTERFACE_LIBRARY) &&
1838  TechMan->get_library_manager(INTERFACE_LIBRARY)->is_fu(ResourceName)))
1839  {
1841  "-->Creating interface resource: " + INTERFACE_LIBRARY + ":" + ResourceName);
1843  structural_type_descriptorRef module_type(new structural_type_descriptor(ResourceName));
1844  CM->set_top_info(ResourceName, module_type);
1845  const auto interface_top = CM->get_circ();
1847  GetPointerS<module>(interface_top)->set_description("Interface module for function: " + ResourceName);
1848  GetPointerS<module>(interface_top)->set_copyright(GENERATED_COPYRIGHT);
1849  GetPointerS<module>(interface_top)->set_authors("Component automatically generated by bambu");
1850  GetPointerS<module>(interface_top)->set_license(GENERATED_LICENSE);
1851  GetPointerS<module>(interface_top)->set_multi_unit_multiplicity(1U);
1852  const auto if_name = info.name == "ovalid" ? "valid" : info.name;
1853  const auto is_unbounded =
1854  if_name == "acknowledge" || if_name == "handshake" || if_name == "fifo" || if_name == "axis";
1855 
1856  const auto address_bitsize = HLSMgr->get_address_bitsize();
1857  structural_type_descriptorRef addrType(new structural_type_descriptor("bool", address_bitsize));
1859  const auto nbitDataSize = 64u - static_cast<unsigned>(__builtin_clzll(info.bitwidth));
1860  structural_type_descriptorRef rwsize(new structural_type_descriptor("bool", nbitDataSize));
1863 
1864  CM->add_port(CLOCK_PORT_NAME, port_o::IN, interface_top, bool_type);
1865  CM->add_port(RESET_PORT_NAME, port_o::IN, interface_top, bool_type);
1866  CM->add_port_vector(START_PORT_NAME, port_o::IN, 1U, interface_top, bool_type);
1867  if(is_unbounded)
1868  {
1869  CM->add_port_vector(DONE_PORT_NAME, port_o::OUT, 1U, interface_top, bool_type);
1870  }
1871  CM->add_port("in1", port_o::IN, interface_top, rwsize);
1872  CM->add_port("in2", port_o::IN, interface_top, rwtype);
1873  const auto addrPort = CM->add_port("in3", port_o::IN, interface_top, addrType);
1874  GetPointerS<port_o>(addrPort)->set_is_addr_bus(true);
1875  GetPointerS<port_o>(addrPort)->set_port_alignment(info.alignment);
1876  if(if_name == "fifo" || if_name == "axis")
1877  {
1878  CM->add_port("out1", port_o::OUT, interface_top, bool_type);
1879  }
1880  std::string port_data_name = "_" + info.arg_id;
1881  port_o::port_interface port_if = port_o::port_interface::PI_WNONE;
1882  if(if_name == "axis")
1883  {
1884  port_data_name = "_m_axis_" + info.arg_id + "_TDATA";
1885  port_if = port_o::port_interface::PI_M_AXIS_TDATA;
1886  }
1887  else if(if_name == "fifo")
1888  {
1889  port_data_name += "_din";
1890  port_if = port_o::port_interface::PI_FDIN;
1891  }
1892  else if(IO_port)
1893  {
1894  port_data_name += "_o";
1895  }
1896  const auto inPort_o = CM->add_port(port_data_name, port_o::OUT, interface_top, dataType);
1897  GetPointerS<port_o>(inPort_o)->set_port_interface(port_if);
1898  if(if_name == "acknowledge" || if_name == "handshake")
1899  {
1900  const auto inPort_o_ack =
1901  CM->add_port("_" + info.arg_id + (IO_port ? "_o" : "") + "_ack", port_o::IN, interface_top, bool_type);
1902  GetPointerS<port_o>(inPort_o_ack)->set_port_interface(port_o::port_interface::PI_WACK);
1903  }
1904  if(if_name == "valid" || if_name == "handshake")
1905  {
1906  const auto inPort_o_vld =
1907  CM->add_port("_" + info.arg_id + (IO_port ? "_o" : "") + "_vld", port_o::OUT, interface_top, bool_type);
1908  GetPointerS<port_o>(inPort_o_vld)->set_port_interface(port_o::port_interface::PI_WVALID);
1909  }
1910  if(if_name == "fifo")
1911  {
1912  const auto inPort_full_n = CM->add_port("_" + info.arg_id + "_full_n", port_o::IN, interface_top, bool_type);
1913  GetPointerS<port_o>(inPort_full_n)->set_port_interface(port_o::port_interface::PI_FULL_N);
1914  const auto inPort_read = CM->add_port("_" + info.arg_id + "_write", port_o::OUT, interface_top, bool_type);
1915  GetPointerS<port_o>(inPort_read)->set_port_interface(port_o::port_interface::PI_WRITE);
1916  }
1917  if(if_name == "axis")
1918  {
1919  const auto inPort_full_n =
1920  CM->add_port("_m_axis_" + info.arg_id + "_TREADY", port_o::IN, interface_top, bool_type);
1921  GetPointerS<port_o>(inPort_full_n)->set_port_interface(port_o::port_interface::PI_M_AXIS_TREADY);
1922  const auto inPort_read =
1923  CM->add_port("_m_axis_" + info.arg_id + "_TVALID", port_o::OUT, interface_top, bool_type);
1924  GetPointerS<port_o>(inPort_read)->set_port_interface(port_o::port_interface::PI_M_AXIS_TVALID);
1925  }
1926 
1927  CM->add_NP_functionality(interface_top, NP_functionality::LIBRARY, "in1 in2 in3");
1928  const auto writer = static_cast<HDLWriter_Language>(parameters->getOption<unsigned int>(OPT_writer_language));
1929  if(if_name == "none" && writer == HDLWriter_Language::VHDL)
1930  {
1932  "Write_" + if_name + "ModuleGenerator");
1933  }
1934  else
1935  {
1937  "Write_" + if_name + "ModuleGenerator");
1938  }
1939  TechMan->add_resource(INTERFACE_LIBRARY, ResourceName, CM);
1940  for(const auto& fdName : operations)
1941  {
1942  TechMan->add_operation(INTERFACE_LIBRARY, ResourceName, fdName);
1943  }
1944  auto fu = GetPointerS<functional_unit>(TechMan->get_fu(ResourceName, INTERFACE_LIBRARY));
1945  fu->area_m = area_info::factory(parameters);
1946  fu->area_m->set_area_value(0);
1947  if(!is_unbounded)
1948  {
1949  fu->logical_type = functional_unit::COMBINATIONAL;
1950  }
1951 
1952  const auto& iface_attrs = func_arch->ifaces.at(bundle_name);
1953  const auto is_registered = iface_attrs.find(FunctionArchitecture::iface_register) != iface_attrs.end();
1954  for(const auto& fdName : operations)
1955  {
1956  const auto op_bounded = fdName.find("Async") != std::string::npos || !is_unbounded;
1957  const auto exec_time = (op_bounded ? 0.0 : HLS_D->get_technology_manager()->CGetSetupHoldTime()) + EPSILON;
1958  const auto cycles = op_bounded ? (1U + is_registered) : 0U;
1959 
1960  const auto op = GetPointerS<operation>(fu->get_operation(fdName));
1961  op->time_m = time_info::factory(parameters);
1962  op->bounded = op_bounded;
1963  op->time_m->set_execution_time(exec_time, cycles);
1964  if(op_bounded && is_registered)
1965  {
1966  op->time_m->set_stage_period(HLS_D->get_technology_manager()->CGetSetupHoldTime() + EPSILON);
1967  op->time_m->set_initiation_time(ControlStep(1U));
1968  }
1969  op->time_m->set_synthesis_dependent(true);
1970  }
1971  HLSMgr->global_resource_constraints[std::make_pair(ResourceName, INTERFACE_LIBRARY)] = std::make_pair(1U, 1U);
1972  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "<--Interface resource created");
1973  }
1974 }
1975 
1976 void InterfaceInfer::create_resource_array(const std::set<std::string>& operationsR,
1977  const std::set<std::string>& operationsW, const interface_info& info,
1978  FunctionArchitectureRef func_arch) const
1979 {
1980  const auto n_channels = parameters->getOption<unsigned int>(OPT_channels_number);
1981  const auto isDP = n_channels == 2;
1982  const auto n_resources = isDP ? 2U : 1U;
1983  const auto read_write_string = (isDP ? std::string("ReadWriteDP_") : std::string("ReadWrite_"));
1984  const auto HLSMgr = GetPointerS<HLS_manager>(AppM);
1985  THROW_ASSERT(func_arch->parms.find(info.arg_id) != func_arch->parms.end(),
1986  "Missing parameter '" + info.arg_id + "' from function architecute.");
1987  const auto& parm_attrs = func_arch->parms.at(info.arg_id);
1988  const auto& bundle_name = parm_attrs.at(FunctionArchitecture::parm_bundle);
1989  const auto ResourceName = ENCODE_FDNAME(bundle_name, "", "");
1990  const auto HLS_D = HLSMgr->get_HLS_device();
1991  const auto TechMan = HLS_D->get_technology_manager();
1992  if(!TechMan->is_library_manager(INTERFACE_LIBRARY) ||
1993  !TechMan->get_library_manager(INTERFACE_LIBRARY)->is_fu(ResourceName))
1994  {
1996  "-->Creating interface resource: " + INTERFACE_LIBRARY + ":" + ResourceName +
1997  " (multi: " + STR(n_resources) + ")");
1998  structural_objectRef interface_top;
2000  const structural_type_descriptorRef module_type(new structural_type_descriptor(ResourceName));
2001  THROW_ASSERT(parm_attrs.find(FunctionArchitecture::parm_elem_count) != parm_attrs.end(),
2002  "Missing parameter element count for parameter '" + info.arg_id + "'.");
2003  const auto arraySize = std::stoull(parm_attrs.at(FunctionArchitecture::parm_elem_count));
2004  CM->set_top_info(ResourceName, module_type);
2005  interface_top = CM->get_circ();
2007  GetPointerS<module>(interface_top)->set_description("Interface module for function: " + ResourceName);
2008  GetPointerS<module>(interface_top)->set_copyright(GENERATED_COPYRIGHT);
2009  GetPointerS<module>(interface_top)->set_authors("Component automatically generated by bambu");
2010  GetPointerS<module>(interface_top)->set_license(GENERATED_LICENSE);
2011  GetPointerS<module>(interface_top)->set_multi_unit_multiplicity(n_resources);
2012  const auto address_bitsize = HLSMgr->get_address_bitsize();
2013  const auto nbit = 64u - static_cast<unsigned long long>(__builtin_clzll(arraySize - 1U));
2014  const auto nbitDataSize = 64u - static_cast<unsigned long long>(__builtin_clzll(info.bitwidth));
2015  const structural_type_descriptorRef addrType(new structural_type_descriptor("bool", address_bitsize));
2016  const structural_type_descriptorRef address_interface_datatype(new structural_type_descriptor("bool", nbit));
2017  const structural_type_descriptorRef dataType(new structural_type_descriptor("bool", info.bitwidth));
2018  const structural_type_descriptorRef size1(new structural_type_descriptor("bool", 1));
2019  const structural_type_descriptorRef rwsize(new structural_type_descriptor("bool", nbitDataSize));
2020  const structural_type_descriptorRef rwtype(new structural_type_descriptor("bool", info.bitwidth));
2021  const structural_type_descriptorRef bool_type(new structural_type_descriptor("bool", 0));
2022 
2023  CM->add_port(CLOCK_PORT_NAME, port_o::IN, interface_top, bool_type);
2024  CM->add_port(RESET_PORT_NAME, port_o::IN, interface_top, bool_type);
2025  CM->add_port_vector(START_PORT_NAME, port_o::IN, n_resources, interface_top, bool_type);
2026 
2027  CM->add_port_vector("in1", port_o::IN, n_resources, interface_top,
2028  size1); // when 0 is a read otherwise is a write
2029  CM->add_port_vector("in2", port_o::IN, n_resources, interface_top,
2030  rwsize); // bit-width size of the written or read data
2031  const auto dataPort = CM->add_port_vector("in3", port_o::IN, n_resources, interface_top,
2032  rwtype); // value written when the first operand is 1, 0 otherwise
2033  const auto addrPort = CM->add_port_vector("in4", port_o::IN, n_resources, interface_top, addrType); // address
2034  GetPointerS<port_o>(addrPort)->set_is_addr_bus(true);
2035  GetPointerS<port_o>(addrPort)->set_port_alignment(info.alignment);
2036 
2037  CM->add_port_vector("out1", port_o::OUT, n_resources, interface_top, rwtype);
2038 
2039  const auto inPort_address =
2040  CM->add_port("_" + bundle_name + "_address0", port_o::OUT, interface_top, address_interface_datatype);
2041  GetPointerS<port_o>(inPort_address)->set_port_interface(port_o::port_interface::PI_ADDRESS);
2042  if(isDP)
2043  {
2044  const auto inPort_address1 =
2045  CM->add_port("_" + bundle_name + "_address1", port_o::OUT, interface_top, address_interface_datatype);
2046  GetPointerS<port_o>(inPort_address1)->set_port_interface(port_o::port_interface::PI_ADDRESS);
2047  }
2048 
2049  const auto inPort_ce = CM->add_port("_" + bundle_name + "_ce0", port_o::OUT, interface_top, bool_type);
2050  GetPointerS<port_o>(inPort_ce)->set_port_interface(port_o::port_interface::PI_CHIPENABLE);
2051  if(isDP)
2052  {
2053  const auto inPort_ce1 = CM->add_port("_" + bundle_name + "_ce1", port_o::OUT, interface_top, bool_type);
2054  GetPointerS<port_o>(inPort_ce1)->set_port_interface(port_o::port_interface::PI_CHIPENABLE);
2055  }
2056 
2057  if(!operationsW.empty())
2058  {
2059  const auto inPort_we = CM->add_port("_" + bundle_name + "_we0", port_o::OUT, interface_top, bool_type);
2060  GetPointerS<port_o>(inPort_we)->set_port_interface(port_o::port_interface::PI_WRITEENABLE);
2061  if(isDP)
2062  {
2063  const auto inPort_we1 = CM->add_port("_" + bundle_name + "_we1", port_o::OUT, interface_top, bool_type);
2064  GetPointerS<port_o>(inPort_we1)->set_port_interface(port_o::port_interface::PI_WRITEENABLE);
2065  }
2066  }
2067  if(!operationsR.empty())
2068  {
2069  const auto inPort_din = CM->add_port("_" + bundle_name + "_q0", port_o::IN, interface_top, dataType);
2070  GetPointerS<port_o>(inPort_din)->set_port_interface(port_o::port_interface::PI_DIN);
2071  if(isDP)
2072  {
2073  const auto inPort_din1 = CM->add_port("_" + bundle_name + "_q1", port_o::IN, interface_top, dataType);
2074  GetPointerS<port_o>(inPort_din1)->set_port_interface(port_o::port_interface::PI_DIN);
2075  }
2076  }
2077  if(!operationsW.empty())
2078  {
2079  const auto inPort_dout = CM->add_port("_" + bundle_name + "_d0", port_o::OUT, interface_top, dataType);
2080  GetPointerS<port_o>(inPort_dout)->set_port_interface(port_o::port_interface::PI_DOUT);
2081  if(isDP)
2082  {
2083  const auto inPort_dout1 = CM->add_port("_" + bundle_name + "_d1", port_o::OUT, interface_top, dataType);
2084  GetPointerS<port_o>(inPort_dout1)->set_port_interface(port_o::port_interface::PI_DOUT);
2085  }
2086  }
2087 
2088  CM->add_NP_functionality(interface_top, NP_functionality::LIBRARY, "in1 in2 in3 in4 out1");
2090  read_write_string + info.name + "ModuleGenerator");
2091  TechMan->add_resource(INTERFACE_LIBRARY, ResourceName, CM);
2092  const auto fu = GetPointerS<functional_unit>(TechMan->get_fu(ResourceName, INTERFACE_LIBRARY));
2093  fu->area_m = area_info::factory(parameters);
2094  fu->area_m->set_area_value(0);
2095  HLSMgr->global_resource_constraints[std::make_pair(ResourceName, INTERFACE_LIBRARY)] =
2096  std::make_pair(n_resources, n_resources);
2097  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "<--Interface resource created");
2098  }
2099  for(const auto& fdName : operationsR)
2100  {
2101  TechMan->add_operation(INTERFACE_LIBRARY, ResourceName, fdName);
2102  }
2103  for(const auto& fdName : operationsW)
2104  {
2105  TechMan->add_operation(INTERFACE_LIBRARY, ResourceName, fdName);
2106  }
2107  const auto fu = GetPointerS<functional_unit>(TechMan->get_fu(ResourceName, INTERFACE_LIBRARY));
2108  const auto bram_f_unit = TechMan->get_fu(isDP ? ARRAY_1D_STD_BRAM_NN_SDS : ARRAY_1D_STD_BRAM_SDS, LIBRARY_STD_FU);
2109  const auto bram_fu = GetPointerS<functional_unit>(bram_f_unit);
2110  const auto load_op_node = bram_fu->get_operation("LOAD");
2111  const auto load_op = GetPointerS<operation>(load_op_node);
2112  const auto load_delay = load_op->time_m->get_execution_time();
2113  const auto load_cycles = load_op->time_m->get_cycles();
2114  const auto load_ii = load_op->time_m->get_initiation_time();
2115  const auto load_sp = load_op->time_m->get_stage_period();
2116  for(const auto& fdName : operationsR)
2117  {
2118  const auto op = GetPointerS<operation>(fu->get_operation(fdName));
2119  op->time_m = time_info::factory(parameters);
2120  op->bounded = true;
2121  op->time_m->set_execution_time(load_delay, load_cycles);
2122  op->time_m->set_initiation_time(load_ii);
2123  op->time_m->set_stage_period(load_sp);
2124  op->time_m->set_synthesis_dependent(true);
2125  }
2126  const auto store_op_node = bram_fu->get_operation("STORE");
2127  const auto store_op = GetPointerS<operation>(store_op_node);
2128  const auto store_delay = store_op->time_m->get_execution_time();
2129  const auto store_cycles = store_op->time_m->get_cycles();
2130  const auto store_ii = store_op->time_m->get_initiation_time();
2131  const auto store_sp = store_op->time_m->get_stage_period();
2132  for(const auto& fdName : operationsW)
2133  {
2134  const auto op = GetPointerS<operation>(fu->get_operation(fdName));
2135  op->time_m = time_info::factory(parameters);
2136  op->bounded = true;
2137  op->time_m->set_execution_time(store_delay, store_cycles);
2138  op->time_m->set_initiation_time(store_ii);
2139  op->time_m->set_stage_period(store_sp);
2140  op->time_m->set_synthesis_dependent(true);
2141  }
2142 }
2143 
2144 void InterfaceInfer::create_resource_m_axi(const std::set<std::string>& operationsR,
2145  const std::set<std::string>& operationsW, const interface_info& info,
2146  FunctionArchitectureRef func_arch) const
2147 {
2148  THROW_ASSERT(GetPointer<HLS_manager>(AppM), "");
2149  const auto HLSMgr = GetPointerS<HLS_manager>(AppM);
2150  THROW_ASSERT(func_arch->parms.find(info.arg_id) != func_arch->parms.end(),
2151  "Missing parameter '" + info.arg_id + "' from function architecute.");
2152  const auto& parm_attrs = func_arch->parms.at(info.arg_id);
2153  const auto& bundle_name = parm_attrs.at(FunctionArchitecture::parm_bundle);
2154  const auto ResourceName = ENCODE_FDNAME(bundle_name, "", "");
2155  const auto HLS_D = HLSMgr->get_HLS_device();
2156  const auto TechMan = HLS_D->get_technology_manager();
2157 
2158  if(!TechMan->is_library_manager(INTERFACE_LIBRARY) ||
2159  !TechMan->get_library_manager(INTERFACE_LIBRARY)->is_fu(ResourceName))
2160  {
2162  "-->Creating interface resource: " + INTERFACE_LIBRARY + ":" + ResourceName);
2163  const auto& iface_attrs = func_arch->ifaces.at(bundle_name);
2165  const structural_type_descriptorRef module_type(new structural_type_descriptor(ResourceName));
2166  CM->set_top_info(ResourceName, module_type);
2167  const auto interface_top = CM->get_circ();
2169  GetPointerS<module>(interface_top)->set_description("Interface module for function: " + ResourceName);
2170  GetPointerS<module>(interface_top)->set_copyright(GENERATED_COPYRIGHT);
2171  GetPointerS<module>(interface_top)->set_authors("Component automatically generated by bambu");
2172  GetPointerS<module>(interface_top)->set_license(GENERATED_LICENSE);
2173  GetPointerS<module>(interface_top)->set_multi_unit_multiplicity(1U);
2174 
2175  const auto address_bitsize = HLSMgr->get_address_bitsize();
2176  const auto nbitDataSize = 64u - static_cast<unsigned>(__builtin_clzll(info.bitwidth));
2177  const auto backEndBitsize =
2178  iface_attrs.find(FunctionArchitecture::iface_cache_bus_size) != iface_attrs.end() ?
2179  std::stoull(iface_attrs.find(FunctionArchitecture::iface_cache_bus_size)->second) :
2180  info.bitwidth;
2181 
2182  const structural_type_descriptorRef address_interface_datatype(
2183  new structural_type_descriptor("bool", address_bitsize));
2184  const structural_type_descriptorRef size1(new structural_type_descriptor("bool", 1));
2185  const structural_type_descriptorRef rwsize(new structural_type_descriptor("bool", nbitDataSize));
2186  const structural_type_descriptorRef rwtypeIn(new structural_type_descriptor("bool", info.bitwidth));
2187  const structural_type_descriptorRef rwtypeOut(new structural_type_descriptor("bool", backEndBitsize));
2188  const structural_type_descriptorRef idType(new structural_type_descriptor("bool", 6));
2189  const structural_type_descriptorRef lenType(new structural_type_descriptor("bool", 8));
2190  const structural_type_descriptorRef sizeType(new structural_type_descriptor("bool", 3));
2191  const structural_type_descriptorRef burstType(new structural_type_descriptor("bool", 2));
2192  const structural_type_descriptorRef lockType(new structural_type_descriptor("bool", 1));
2193  const structural_type_descriptorRef cacheType(new structural_type_descriptor("bool", 4));
2194  const structural_type_descriptorRef protType(new structural_type_descriptor("bool", 3));
2195  const structural_type_descriptorRef qosType(new structural_type_descriptor("bool", 4));
2196  const structural_type_descriptorRef regionType(new structural_type_descriptor("bool", 4));
2197  const structural_type_descriptorRef userType(new structural_type_descriptor("bool", 1));
2198  const structural_type_descriptorRef strbType(new structural_type_descriptor("bool", backEndBitsize / 8ULL));
2199  const structural_type_descriptorRef respType(new structural_type_descriptor("bool", 2));
2200  const structural_type_descriptorRef bool_type(new structural_type_descriptor("bool", 0));
2201 
2202  CM->add_port(CLOCK_PORT_NAME, port_o::IN, interface_top, bool_type);
2203  CM->add_port(RESET_PORT_NAME, port_o::IN, interface_top, bool_type);
2204  CM->add_port_vector(START_PORT_NAME, port_o::IN, 1U, interface_top, bool_type);
2205 
2206  // when 0 is a read otherwise is a write
2207  CM->add_port("in1", port_o::IN, interface_top, size1);
2208  // bit-width size of the written or read data
2209  CM->add_port("in2", port_o::IN, interface_top, rwsize);
2210  // value written when the first operand is 1, 0 otherwise
2211  CM->add_port("in3", port_o::IN, interface_top, rwtypeIn);
2212 
2213  const auto addrPort = CM->add_port("in4", port_o::IN, interface_top, address_interface_datatype);
2214  GetPointerS<port_o>(addrPort)->set_is_addr_bus(true);
2215 
2216  const auto awready = CM->add_port("_m_axi_" + bundle_name + "_awready", port_o::IN, interface_top, bool_type);
2217  GetPointerS<port_o>(awready)->set_port_interface(port_o::port_interface::M_AXI_AWREADY);
2218 
2219  const auto wready = CM->add_port("_m_axi_" + bundle_name + "_wready", port_o::IN, interface_top, bool_type);
2220  GetPointerS<port_o>(wready)->set_port_interface(port_o::port_interface::M_AXI_WREADY);
2221 
2222  const auto bid = CM->add_port_vector("_m_axi_" + bundle_name + "_bid", port_o::IN, 1, interface_top, idType);
2223  GetPointerS<port_o>(bid)->set_port_interface(port_o::port_interface::M_AXI_BID);
2224 
2225  const auto bresp = CM->add_port("_m_axi_" + bundle_name + "_bresp", port_o::IN, interface_top, respType);
2226  GetPointerS<port_o>(bresp)->set_port_interface(port_o::port_interface::M_AXI_BRESP);
2227 
2228  const auto buser =
2229  CM->add_port_vector("_m_axi_" + bundle_name + "_buser", port_o::IN, 1, interface_top, userType);
2230  GetPointerS<port_o>(buser)->set_port_interface(port_o::port_interface::M_AXI_BUSER);
2231 
2232  const auto bvalid = CM->add_port("_m_axi_" + bundle_name + "_bvalid", port_o::IN, interface_top, bool_type);
2233  GetPointerS<port_o>(bvalid)->set_port_interface(port_o::port_interface::M_AXI_BVALID);
2234 
2235  const auto arready = CM->add_port("_m_axi_" + bundle_name + "_arready", port_o::IN, interface_top, bool_type);
2236  GetPointerS<port_o>(arready)->set_port_interface(port_o::port_interface::M_AXI_ARREADY);
2237 
2238  const auto rid = CM->add_port_vector("_m_axi_" + bundle_name + "_rid", port_o::IN, 1, interface_top, idType);
2239  GetPointerS<port_o>(rid)->set_port_interface(port_o::port_interface::M_AXI_RID);
2240 
2241  const auto rdata = CM->add_port("_m_axi_" + bundle_name + "_rdata", port_o::IN, interface_top, rwtypeOut);
2242  GetPointerS<port_o>(rdata)->set_port_interface(port_o::port_interface::M_AXI_RDATA);
2243 
2244  const auto rresp = CM->add_port("_m_axi_" + bundle_name + "_rresp", port_o::IN, interface_top, respType);
2245  GetPointerS<port_o>(rresp)->set_port_interface(port_o::port_interface::M_AXI_RRESP);
2246 
2247  const auto rlast = CM->add_port("_m_axi_" + bundle_name + "_rlast", port_o::IN, interface_top, bool_type);
2248  GetPointerS<port_o>(rlast)->set_port_interface(port_o::port_interface::M_AXI_RLAST);
2249 
2250  const auto ruser =
2251  CM->add_port_vector("_m_axi_" + bundle_name + "_ruser", port_o::IN, 1, interface_top, userType);
2252  GetPointerS<port_o>(ruser)->set_port_interface(port_o::port_interface::M_AXI_RUSER);
2253 
2254  const auto rvalid = CM->add_port("_m_axi_" + bundle_name + "_rvalid", port_o::IN, interface_top, bool_type);
2255  GetPointerS<port_o>(rvalid)->set_port_interface(port_o::port_interface::M_AXI_RVALID);
2256 
2257  CM->add_port(DONE_PORT_NAME, port_o::OUT, interface_top, bool_type);
2258  CM->add_port("out1", port_o::OUT, interface_top, rwtypeIn);
2259 
2260  const auto awid = CM->add_port_vector("_m_axi_" + bundle_name + "_awid", port_o::OUT, 1, interface_top, idType);
2261  GetPointerS<port_o>(awid)->set_port_interface(port_o::port_interface::M_AXI_AWID);
2262 
2263  const auto awaddr =
2264  CM->add_port("_m_axi_" + bundle_name + "_awaddr", port_o::OUT, interface_top, address_interface_datatype);
2265  GetPointerS<port_o>(awaddr)->set_port_interface(port_o::port_interface::M_AXI_AWADDR);
2266 
2267  const auto awlen = CM->add_port("_m_axi_" + bundle_name + "_awlen", port_o::OUT, interface_top, lenType);
2268  GetPointerS<port_o>(awlen)->set_port_interface(port_o::port_interface::M_AXI_AWLEN);
2269 
2270  const auto awsize = CM->add_port("_m_axi_" + bundle_name + "_awsize", port_o::OUT, interface_top, sizeType);
2271  GetPointerS<port_o>(awsize)->set_port_interface(port_o::port_interface::M_AXI_AWSIZE);
2272 
2273  const auto awburst = CM->add_port("_m_axi_" + bundle_name + "_awburst", port_o::OUT, interface_top, burstType);
2274  GetPointerS<port_o>(awburst)->set_port_interface(port_o::port_interface::M_AXI_AWBURST);
2275 
2276  const auto awlock =
2277  CM->add_port_vector("_m_axi_" + bundle_name + "_awlock", port_o::OUT, 1, interface_top, lockType);
2278  GetPointerS<port_o>(awlock)->set_port_interface(port_o::port_interface::M_AXI_AWLOCK);
2279 
2280  const auto awcache = CM->add_port("_m_axi_" + bundle_name + "_awcache", port_o::OUT, interface_top, cacheType);
2281  GetPointerS<port_o>(awcache)->set_port_interface(port_o::port_interface::M_AXI_AWCACHE);
2282 
2283  const auto awprot = CM->add_port("_m_axi_" + bundle_name + "_awprot", port_o::OUT, interface_top, protType);
2284  GetPointerS<port_o>(awprot)->set_port_interface(port_o::port_interface::M_AXI_AWPROT);
2285 
2286  const auto awqos = CM->add_port("_m_axi_" + bundle_name + "_awqos", port_o::OUT, interface_top, qosType);
2287  GetPointerS<port_o>(awqos)->set_port_interface(port_o::port_interface::M_AXI_AWQOS);
2288 
2289  const auto awregion = CM->add_port("_m_axi_" + bundle_name + "_awregion", port_o::OUT, interface_top, regionType);
2290  GetPointerS<port_o>(awregion)->set_port_interface(port_o::port_interface::M_AXI_AWREGION);
2291 
2292  const auto awuser =
2293  CM->add_port_vector("_m_axi_" + bundle_name + "_awuser", port_o::OUT, 1, interface_top, userType);
2294  GetPointerS<port_o>(awuser)->set_port_interface(port_o::port_interface::M_AXI_AWUSER);
2295 
2296  const auto awvalid = CM->add_port("_m_axi_" + bundle_name + "_awvalid", port_o::OUT, interface_top, bool_type);
2297  GetPointerS<port_o>(awvalid)->set_port_interface(port_o::port_interface::M_AXI_AWVALID);
2298 
2299  const auto wdata = CM->add_port("_m_axi_" + bundle_name + "_wdata", port_o::OUT, interface_top, rwtypeOut);
2300  GetPointerS<port_o>(wdata)->set_port_interface(port_o::port_interface::M_AXI_WDATA);
2301 
2302  const auto wstrb =
2303  CM->add_port_vector("_m_axi_" + bundle_name + "_wstrb", port_o::OUT, 1, interface_top, strbType);
2304  GetPointerS<port_o>(wstrb)->set_port_interface(port_o::port_interface::M_AXI_WSTRB);
2305 
2306  const auto wlast = CM->add_port("_m_axi_" + bundle_name + "_wlast", port_o::OUT, interface_top, bool_type);
2307  GetPointerS<port_o>(wlast)->set_port_interface(port_o::port_interface::M_AXI_WLAST);
2308 
2309  const auto wuser =
2310  CM->add_port_vector("_m_axi_" + bundle_name + "_wuser", port_o::OUT, 1, interface_top, userType);
2311  GetPointerS<port_o>(wuser)->set_port_interface(port_o::port_interface::M_AXI_WUSER);
2312 
2313  const auto wvalid = CM->add_port("_m_axi_" + bundle_name + "_wvalid", port_o::OUT, interface_top, bool_type);
2314  GetPointerS<port_o>(wvalid)->set_port_interface(port_o::port_interface::M_AXI_WVALID);
2315 
2316  const auto bready = CM->add_port("_m_axi_" + bundle_name + "_bready", port_o::OUT, interface_top, bool_type);
2317  GetPointerS<port_o>(bready)->set_port_interface(port_o::port_interface::M_AXI_BREADY);
2318 
2319  const auto arid = CM->add_port_vector("_m_axi_" + bundle_name + "_arid", port_o::OUT, 1, interface_top, idType);
2320  GetPointerS<port_o>(arid)->set_port_interface(port_o::port_interface::M_AXI_ARID);
2321 
2322  const auto araddr =
2323  CM->add_port("_m_axi_" + bundle_name + "_araddr", port_o::OUT, interface_top, address_interface_datatype);
2324  GetPointerS<port_o>(araddr)->set_port_interface(port_o::port_interface::M_AXI_ARADDR);
2325 
2326  const auto arlen = CM->add_port("_m_axi_" + bundle_name + "_arlen", port_o::OUT, interface_top, lenType);
2327  GetPointerS<port_o>(arlen)->set_port_interface(port_o::port_interface::M_AXI_ARLEN);
2328 
2329  const auto arsize = CM->add_port("_m_axi_" + bundle_name + "_arsize", port_o::OUT, interface_top, sizeType);
2330  GetPointerS<port_o>(arsize)->set_port_interface(port_o::port_interface::M_AXI_ARSIZE);
2331 
2332  const auto arburst = CM->add_port("_m_axi_" + bundle_name + "_arburst", port_o::OUT, interface_top, burstType);
2333  GetPointerS<port_o>(arburst)->set_port_interface(port_o::port_interface::M_AXI_ARBURST);
2334 
2335  const auto arlock =
2336  CM->add_port_vector("_m_axi_" + bundle_name + "_arlock", port_o::OUT, 1, interface_top, lockType);
2337  GetPointerS<port_o>(arlock)->set_port_interface(port_o::port_interface::M_AXI_ARLOCK);
2338 
2339  const auto arcache = CM->add_port("_m_axi_" + bundle_name + "_arcache", port_o::OUT, interface_top, cacheType);
2340  GetPointerS<port_o>(arcache)->set_port_interface(port_o::port_interface::M_AXI_ARCACHE);
2341 
2342  const auto arprot = CM->add_port("_m_axi_" + bundle_name + "_arprot", port_o::OUT, interface_top, protType);
2343  GetPointerS<port_o>(arprot)->set_port_interface(port_o::port_interface::M_AXI_ARPROT);
2344 
2345  const auto arqos = CM->add_port("_m_axi_" + bundle_name + "_arqos", port_o::OUT, interface_top, qosType);
2346  GetPointerS<port_o>(arqos)->set_port_interface(port_o::port_interface::M_AXI_ARQOS);
2347 
2348  const auto arregion = CM->add_port("_m_axi_" + bundle_name + "_arregion", port_o::OUT, interface_top, regionType);
2349  GetPointerS<port_o>(arregion)->set_port_interface(port_o::port_interface::M_AXI_ARREGION);
2350 
2351  const auto aruser =
2352  CM->add_port_vector("_m_axi_" + bundle_name + "_aruser", port_o::OUT, 1, interface_top, userType);
2353  GetPointerS<port_o>(aruser)->set_port_interface(port_o::port_interface::M_AXI_ARUSER);
2354 
2355  const auto arvalid = CM->add_port("_m_axi_" + bundle_name + "_arvalid", port_o::OUT, interface_top, bool_type);
2356  GetPointerS<port_o>(arvalid)->set_port_interface(port_o::port_interface::M_AXI_ARVALID);
2357 
2358  const auto rready = CM->add_port("_m_axi_" + bundle_name + "_rready", port_o::OUT, interface_top, bool_type);
2359  GetPointerS<port_o>(rready)->set_port_interface(port_o::port_interface::M_AXI_RREADY);
2360 
2361  bool has_slave = false;
2362  for(auto& p : func_arch->parms)
2363  {
2364  if(p.second.at(FunctionArchitecture::parm_bundle) == bundle_name)
2365  {
2366  const auto& parm_offset = p.second.at(FunctionArchitecture::parm_offset);
2367  if(parm_offset == "slave")
2368  {
2369  has_slave = true;
2370  }
2371  else if(parm_offset == "direct")
2372  {
2373  const auto offset_port =
2374  CM->add_port("_" + p.first, port_o::IN, interface_top, address_interface_datatype);
2375  GetPointerS<port_o>(offset_port)->set_port_interface(port_o::port_interface::PI_M_AXI_DIRECT);
2376  }
2377  }
2378  }
2379  if(has_slave)
2380  {
2381  const auto s_awvalid = CM->add_port("_s_axi_AXILiteS_AWVALID", port_o::IN, interface_top, bool_type);
2382  GetPointerS<port_o>(s_awvalid)->set_port_interface(port_o::port_interface::S_AXIL_AWVALID);
2383  const auto s_awaddr =
2384  CM->add_port("_s_axi_AXILiteS_AWADDR", port_o::IN, interface_top, address_interface_datatype);
2385  GetPointerS<port_o>(s_awaddr)->set_port_interface(port_o::port_interface::S_AXIL_AWADDR);
2386  const auto s_wvalid = CM->add_port("_s_axi_AXILiteS_WVALID", port_o::IN, interface_top, bool_type);
2387  GetPointerS<port_o>(s_wvalid)->set_port_interface(port_o::port_interface::S_AXIL_WVALID);
2388  const auto s_wdata =
2389  CM->add_port("_s_axi_AXILiteS_WDATA", port_o::IN, interface_top, address_interface_datatype);
2390  GetPointerS<port_o>(s_wdata)->set_port_interface(port_o::port_interface::S_AXIL_WDATA);
2391  const auto s_wstrb = CM->add_port("_s_axi_AXILiteS_WSTRB", port_o::IN, interface_top, strbType);
2392  GetPointerS<port_o>(s_wstrb)->set_port_interface(port_o::port_interface::S_AXIL_WSTRB);
2393  const auto s_arvalid = CM->add_port("_s_axi_AXILiteS_ARVALID", port_o::IN, interface_top, bool_type);
2394  GetPointerS<port_o>(s_arvalid)->set_port_interface(port_o::port_interface::S_AXIL_ARVALID);
2395  const auto s_araddr =
2396  CM->add_port("_s_axi_AXILiteS_ARADDR", port_o::IN, interface_top, address_interface_datatype);
2397  GetPointerS<port_o>(s_araddr)->set_port_interface(port_o::port_interface::S_AXIL_ARADDR);
2398  const auto s_rready = CM->add_port("_s_axi_AXILiteS_RREADY", port_o::IN, interface_top, bool_type);
2399  GetPointerS<port_o>(s_rready)->set_port_interface(port_o::port_interface::S_AXIL_RREADY);
2400  const auto s_bready = CM->add_port("_s_axi_AXILiteS_BREADY", port_o::IN, interface_top, bool_type);
2401  GetPointerS<port_o>(s_bready)->set_port_interface(port_o::port_interface::S_AXIL_BREADY);
2402 
2403  const auto s_awready = CM->add_port("_s_axi_AXILiteS_AWREADY", port_o::OUT, interface_top, bool_type);
2404  GetPointerS<port_o>(s_awready)->set_port_interface(port_o::port_interface::S_AXIL_AWREADY);
2405  const auto s_wready = CM->add_port("_s_axi_AXILiteS_WREADY", port_o::OUT, interface_top, bool_type);
2406  GetPointerS<port_o>(s_wready)->set_port_interface(port_o::port_interface::S_AXIL_WREADY);
2407  const auto s_arready = CM->add_port("_s_axi_AXILiteS_ARREADY", port_o::OUT, interface_top, bool_type);
2408  GetPointerS<port_o>(s_arready)->set_port_interface(port_o::port_interface::S_AXIL_ARREADY);
2409  const auto s_rvalid = CM->add_port("_s_axi_AXILiteS_RVALID", port_o::OUT, interface_top, bool_type);
2410  GetPointerS<port_o>(s_rvalid)->set_port_interface(port_o::port_interface::S_AXIL_RVALID);
2411  const auto s_rdata =
2412  CM->add_port("_s_axi_AXILiteS_RDATA", port_o::OUT, interface_top, address_interface_datatype);
2413  GetPointerS<port_o>(s_rdata)->set_port_interface(port_o::port_interface::S_AXIL_RDATA);
2414  const auto s_rresp = CM->add_port("_s_axi_AXILiteS_RRESP", port_o::OUT, interface_top, respType);
2415  GetPointerS<port_o>(s_rresp)->set_port_interface(port_o::port_interface::S_AXIL_RRESP);
2416  const auto s_bvalid = CM->add_port("_s_axi_AXILiteS_BVALID", port_o::OUT, interface_top, bool_type);
2417  GetPointerS<port_o>(s_bvalid)->set_port_interface(port_o::port_interface::S_AXIL_BVALID);
2418  const auto s_bresp = CM->add_port("_s_axi_AXILiteS_BRESP", port_o::OUT, interface_top, respType);
2419  GetPointerS<port_o>(s_bresp)->set_port_interface(port_o::port_interface::S_AXIL_BRESP);
2420  }
2421 
2422  CM->add_NP_functionality(interface_top, NP_functionality::LIBRARY, "in1 in2 in3 in4 out1");
2424  "ReadWrite_" + info.name + "ModuleGenerator");
2425 
2426  TechMan->add_resource(INTERFACE_LIBRARY, ResourceName, CM);
2427 
2428  const auto fu = GetPointerS<functional_unit>(TechMan->get_fu(ResourceName, INTERFACE_LIBRARY));
2429  fu->area_m = area_info::factory(parameters);
2430  fu->area_m->set_area_value(0);
2431  if(iface_attrs.find(FunctionArchitecture::iface_cache_line_count) != iface_attrs.end())
2432  {
2433  const auto flushName = ENCODE_FDNAME(bundle_name, "_Flush_", "m_axi");
2434  TechMan->add_operation(INTERFACE_LIBRARY, ResourceName, flushName);
2435  const auto op = GetPointer<operation>(fu->get_operation(flushName));
2436  op->time_m = time_info::factory(parameters);
2437  op->bounded = false;
2438  op->time_m->set_execution_time(HLS_D->get_technology_manager()->CGetSetupHoldTime() + EPSILON, 0);
2439  op->time_m->set_synthesis_dependent(true);
2440  }
2441  HLSMgr->global_resource_constraints[std::make_pair(ResourceName, INTERFACE_LIBRARY)] = std::make_pair(1U, 1U);
2442  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "<--Interface resource created");
2443  }
2444 
2445  for(const auto& fdName : operationsR)
2446  {
2447  TechMan->add_operation(INTERFACE_LIBRARY, ResourceName, fdName);
2448  }
2449  for(const auto& fdName : operationsW)
2450  {
2451  TechMan->add_operation(INTERFACE_LIBRARY, ResourceName, fdName);
2452  }
2453 
2454  /* Flush Op */
2455  const auto fu = GetPointerS<functional_unit>(TechMan->get_fu(ResourceName, INTERFACE_LIBRARY));
2456 
2457  for(const auto& fdName : operationsR)
2458  {
2459  const auto op = GetPointerS<operation>(fu->get_operation(fdName));
2460  op->time_m = time_info::factory(parameters);
2461  op->bounded = false;
2462  op->time_m->set_execution_time(HLS_D->get_technology_manager()->CGetSetupHoldTime() + EPSILON, 0);
2463  op->time_m->set_synthesis_dependent(true);
2464  }
2465  for(const auto& fdName : operationsW)
2466  {
2467  const auto op = GetPointer<operation>(fu->get_operation(fdName));
2468  op->time_m = time_info::factory(parameters);
2469  op->bounded = false;
2470  op->time_m->set_execution_time(HLS_D->get_technology_manager()->CGetSetupHoldTime() + EPSILON, 0);
2471  op->time_m->set_synthesis_dependent(true);
2472  }
2473 }
2474 
2475 void InterfaceInfer::create_resource(const std::set<std::string>& operationsR, const std::set<std::string>& operationsW,
2476  const interface_info& info, FunctionArchitectureRef func_arch) const
2477 {
2478  if(info.name == "none" || info.name == "acknowledge" || info.name == "valid" || info.name == "ovalid" ||
2479  info.name == "handshake" || info.name == "fifo" || info.name == "axis")
2480  {
2481  THROW_ASSERT(!operationsR.empty() || !operationsW.empty(), "unexpected condition");
2482  const auto IO_P = !operationsR.empty() && !operationsW.empty();
2483  create_resource_Read_simple(operationsR, info, func_arch, IO_P);
2484  create_resource_Write_simple(operationsW, info, func_arch, IO_P);
2485  }
2486  else if(info.name == "array")
2487  {
2488  create_resource_array(operationsR, operationsW, info, func_arch);
2489  }
2490  else if(info.name == "m_axi")
2491  {
2492  create_resource_m_axi(operationsR, operationsW, info, func_arch);
2493  }
2494  else
2495  {
2496  THROW_ERROR("interface not supported: " + info.name);
2497  }
2498 }
#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) ...
static size_t CGetPointerSize(const ParameterConstRef parameters)
Return the size of the pointer in bit.
#define DEBUG_LEVEL_VERY_PEDANTIC
extremely verbose debugging print is performed.
Data structure representing the entire HLS information.
#define INDENT_DBG_MEX(dbgLevel, curDbgLevel, mex)
We are producing a debug version of the program, so the message is printed;.
void ChasePointerInterface(tree_nodeRef ptr_var, std::list< tree_nodeRef > &writeStmt, std::list< tree_nodeRef > &readStmt, interface_info &info)
Collect information about resource area.
File containing functions and utilities to support the printing of debug messagges.
#define STR_CST_interface_parameter_keyword
interface_parameter_keyword
std::string ToString() const
Print this node as string in gimple format.
#define DEBUG_LEVEL_PEDANTIC
very verbose debugging print is performed.
#define START_PORT_NAME
Structure representing the most relevant information about the type of a structural object...
Step successfully executed.
#define EPSILON
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.
static std::vector< unsigned int > GetSortedRoots(const CallGraphManagerConstRef &CGM)
void ReplaceTreeNode(const tree_nodeRef &stmt, const tree_nodeRef &old_node, const tree_nodeRef &new_node)
Replace the occurrences of tree node old_node with new_node in statement identified by tn...
#define GENERATED_LICENSE
#define BB_EXIT
constant identifying the basic block node of type exit
static std::string GetString(enum port_direction)
constexpr T get_aligned_ac_bitsize(T bitsize)
Definition of the class representing a generic C application.
const structural_objectRef get_circ() const
Get a reference to circ field.
const int output_level
The output level.
static tree_nodeConstRef CGetArrayBaseType(const tree_nodeConstRef &type)
static bool IsArrayEquivType(const tree_nodeConstRef &type)
Return true if treenode is an array or it is equivalent to an array (record recursively having a sing...
std::map< enum parm_attr, std::string > parm_attrs
Definition: hls_manager.hpp:99
RelationshipType
The relationship type.
Source must be executed to satisfy target.
mathematical utility function not provided by standard libraries
#define INDENT_OUT_MEX(outLevel, curOutLevel, mex)
bool HasToBeExecuted() const override
Check if this step has actually to be executed.
void create_resource_Read_simple(const std::set< std::string > &operations, const interface_info &info, FunctionArchitectureRef func_arch, bool IO_port) const
std::map< enum iface_attr, std::string > iface_attrs
#define ARRAY_1D_STD_BRAM_NN_SDS
This class manages the circuit structures.
tree_nodeRef create_binary_operation(const tree_nodeConstRef &type, const tree_nodeRef &op0, const tree_nodeRef &op1, const std::string &srcp, enum kind operation_kind) const
Function used to create a binary expression.
A simple interface to token object of the raw files.
Collect information about resource performance.
#define ARRAY_1D_STD_BRAM_SDS
#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
#define LIBRARY_STD_FU
standard library where all standard HLS resources are defined
static const std::regex signature_param_typename("((?:\+\*)+(?:<[^>]*>)?\*[\&\]*\*)")
static std::string print_function_name(const tree_managerConstRef &TM, const function_decl *fd)
Return the name of the function in a string.
Class specification of the manager of the technology library data structures.
Data structure describing a basic block at tree level.
#define INTERFACE_LIBRARY
interface library
#define OUTPUT_LEVEL_MINIMUM
minimum debugging print is performed.
~InterfaceInfer() override
Destructor.
tree_nodeRef create_unary_operation(const tree_nodeConstRef &type, const tree_nodeRef &op, const std::string &srcp, enum kind operation_kind) const
EXPRESSION_TREE_NODES.
const tree_nodeConstRef CGetTreeNode(const unsigned int i) const
tree_nodeRef CreateGimpleAssign(const tree_nodeConstRef &type, const tree_nodeConstRef &min, const tree_nodeConstRef &max, const tree_nodeRef &op, unsigned int function_decl_nid, const std::string &srcp) const
Create gimple assignment.
static std::string GetMangledFunctionName(const function_decl *fd)
Return the mangled function name.
#define THROW_WARNING(str_expr)
helper function used to throw a warning in a standard way: though it uses PRINT_DBG_MEX, the debug level used is such that the message is always printed
Definition: exceptions.hpp:300
#define STR(s)
Macro which performs a lexical_cast to a string.
Auxiliary methods for manipulating string.
#define max
Definition: backprop.h:17
HDLWriter_Language
#define CLOCK_PORT_NAME
standard name for ports
static void addCallPointAndExpand(CustomUnorderedSet< unsigned int > &AV, const application_managerRef AM, unsigned int caller_id, unsigned int called_id, unsigned int call_id, enum FunctionEdgeInfo::CallType call_type, int DL)
void ChasePointerInterfaceRecurse(CustomOrderedSet< unsigned > &Visited, tree_nodeRef ptr_var, std::list< tree_nodeRef > &writeStmt, std::list< tree_nodeRef > &readStmt, interface_info &info)
static bool IsArrayType(const tree_nodeConstRef &type)
Return true if treenode is an array.
#define THROW_UNREACHABLE(str_expr)
helper function used to specify that some points should never be reached
Definition: exceptions.hpp:292
static void add_NP_functionality(structural_objectRef cir, NP_functionality::NP_functionaly_type dt, std::string functionality_description)
Add a not-parsed functionality.
static unsigned long long Size(const tree_nodeConstRef &tn)
Return the size of a tree object.
tree_nodeRef GetPointerType(const tree_nodeConstRef &ptd, unsigned long long algn=0) const
Function that creates a pointer type if it is not already present, otherwise it returns the one that ...
void set_top_info(const std::string &id, const technology_managerRef &LM, const std::string &Library="")
#define DONE_PORT_NAME
HLSFlowStep_Type
Definition: hls_step.hpp:95
void update(const tree_nodeRef &tn, const std::string &_type_name, ParameterConstRef parameters)
void create_resource_m_axi(const std::set< std::string > &operationsR, const std::set< std::string > &operationsW, const interface_info &info, FunctionArchitectureRef func_arch) const
This class writes different HDL based descriptions (VHDL, Verilog, SystemC) starting from a structura...
Class specification of the data structures used to manage technology information. ...
InterfaceInfer(const application_managerRef AppM, const DesignFlowManagerConstRef design_flow_manager, const ParameterConstRef parameters)
Constructor.
port_interface
Enum type describing if the port is associated with a specific interface type.
static structural_objectRef add_port(const std::string &id, port_o::port_direction pdir, structural_objectRef owner, structural_type_descriptorRef type_descr, unsigned int treenode=0)
Create a new port.
const unsigned int index
Represent the index read from the raw file and the index-1 of the vector of tree_node associated to t...
Definition: tree_node.hpp:146
Classes to describe design flow graph.
tree_nodeRef CreateUniqueIntegerCst(integer_cst_t value, const tree_nodeConstRef &type)
memoization of integer constants
#define index(x, y)
Definition: Keccak.c:74
static const std::string ComputeSignature(const TechnologyFlowStep_Type technology_flow_step_type)
Compute the signature of a technology flow step.
Factory for technology flow step.
#define BB_ENTRY
constant identifying the basic block node of type entry
const Wrefcount< const DesignFlowManager > design_flow_manager
The design flow manager.
constexpr T get_aligned_bitsize(T bitsize)
#define GET_CONST_NODE(t)
Definition: tree_node.hpp:347
void create_resource_array(const std::set< std::string > &operationsR, const std::set< std::string > &operationsW, const interface_info &info, FunctionArchitectureRef func_arch) const
Load parsed protocol interface attributes.
Classes specification of the tree_node data structures.
const ParameterConstRef parameters
Set of input parameters.
DesignFlowStep_Status
The status of a step.
Call graph hierarchy.
Class defining some useful functions to create tree nodes and to manipulate the tree manager...
#define DEBUG_LEVEL_NONE
no debugging print is performed.
FunctionArchitecture::iface_attrs & iface_attrs
#define THROW_ERROR(str_expr)
helper function used to throw an error in a standard way
Definition: exceptions.hpp:263
Wrapper of design_flow.
tree_nodeRef create_function_decl(const std::string &function_name, const tree_nodeRef &scpe, const std::vector< tree_nodeConstRef > &argsT, const tree_nodeConstRef &returnType, const std::string &srcp, bool with_body) const
create the declaration of a function without its body
tree_nodeRef GetBooleanType() const
Function that creates a boolean type if it is not already present, otherwise it returns the one that ...
This file collects some utility functions.
tree_nodeRef GetCustomIntegerType(unsigned long long prec, bool unsigned_p) const
create an integer type starting from a given prec
static std::vector< tree_nodeRef > GetCallArgs(tree_nodeRef stmt)
static tree_nodeConstRef ResolvePointerAlias(const CallGraphManagerConstRef &CGM, const tree_managerConstRef &TM, const tree_nodeConstRef &var, unsigned int fid)
static std::string get_decl_name(tree_nodeRef tn)
#define ENCODE_FDNAME(arg_name, MODE, interface_type)
FunctionArchitecture::parm_attrs & parm_attrs
interface_info(const std::string &_arg_id, const std::string &_interface_fname, bool fixed_size, FunctionArchitecture::parm_attrs &_parm_attrs, FunctionArchitecture::iface_attrs &_iface_attrs)
refcount< T > lock() const
Definition: refcount.hpp:212
tree_nodeRef CreateCallExpr(const tree_nodeConstRef &called_function, const std::vector< tree_nodeRef > &args, const std::string &srcp) const
Create a call_expr.
#define BUILTIN_SRCP
void ComputeRelationships(DesignFlowStepSet &relationship, const DesignFlowStep::RelationshipType relationship_type) override
Compute the relationships of a step with other steps.
static tree_nodeConstRef GetBaseVariable(const tree_nodeConstRef &mem)
Retrun the base variable of a memory access.
void setReadInterface(tree_nodeRef stmt, const std::string &arg_name, std::set< std::string > &operationsR, bool commonRWSignature, tree_nodeConstRef interface_datatype, const tree_manipulationRef tree_man, const tree_managerRef TM)
This class describes all classes used to represent a structural object.
static area_infoRef factory(const ParameterConstRef &Param)
Factory method.
Definition: area_info.cpp:52
const application_managerRef AppM
The application manager.
Class specification of the tree_reindex support class.
static std::tuple< unsigned int, unsigned int > GetCallStmt(const CallGraphManagerConstRef &CGM, unsigned int fid)
static std::string PrintType(const tree_managerConstRef &TM, const tree_nodeConstRef &type, bool global=false, bool print_qualifiers=false, bool print_storage=false, const tree_nodeConstRef &var=nullptr, const var_pp_functorConstRef &vppf=var_pp_functorConstRef(), const std::string &prefix="", const std::string &tail="")
Print a type and its variable in case var is not zero.
DesignFlowStep_Status Exec() override
Execute this step.
This struct represent a &#39;return&#39; statement.
Definition: tree_node.hpp:4387
tree_nodeRef GetVoidType() const
TYPE_OBJ.
tree_nodeRef create_gimple_call(const tree_nodeConstRef &called_function, const std::vector< tree_nodeRef > &args, unsigned int function_decl_nid, const std::string &srcp) const
GIMPLE_CALL.
TYPE distance(TYPE position_x[nAtoms], TYPE position_y[nAtoms], TYPE position_z[nAtoms], int i, int j)
Definition: md_kernel_test.c:3
void create_resource_Write_simple(const std::set< std::string > &operations, const interface_info &info, FunctionArchitectureRef func_arch, bool IO_port) const
tree_nodeRef CreateNopExpr(const tree_nodeConstRef &operand, const tree_nodeConstRef &type, const tree_nodeConstRef &min, const tree_nodeConstRef &max, unsigned int function_decl_nid) const
Create a nop_expr to perform a conversion.
static tree_nodeConstRef CGetType(const tree_nodeConstRef &node)
Return the treenode of the type of node.
static bool IsStructType(const tree_nodeConstRef &type)
Return true if treenode is a record.
tree_nodeRef GetUnsignedIntegerType() const
Function that creates a unsigned integer type if it is not already present, otherwise it returns the ...
unsigned long long ac_type_bitwidth(const std::string &intType, bool &is_signed, bool &is_fixed)
It collects all the common strings covering PandA copyrights issues.
static tree_nodeConstRef CGetPointedType(const tree_nodeConstRef &pointer)
Return the pointed type of a pointer object.
void create_resource(const std::set< std::string > &operationsR, const std::set< std::string > &operationsW, const interface_info &info, FunctionArchitectureRef func_arch) const
this class is used to manage the command-line or XML options.
void forwardInterface(const tree_nodeRef &fnode, const tree_nodeRef &parm_node, const interface_info &info)
tree_nodeRef create_ssa_name(const tree_nodeConstRef &var, const tree_nodeConstRef &type, const tree_nodeConstRef &min, const tree_nodeConstRef &max, bool volatile_flag=false, bool virtual_flag=false) const
MISCELLANEOUS_OBJ_TREE_NODES.
constant strings
refcount< tree_node > tree_nodeRef
RefCount type definition of the tree_node class structure.
Definition: tree_node.hpp:212
const CustomUnorderedSet< std::pair< FrontendFlowStepType, FunctionRelationship > > ComputeFrontendRelationships(const DesignFlowStep::RelationshipType relationship_type) const override
Return the set of analyses in relationship with this design step.
#define RESET_PORT_NAME
static std::string GetFunctionName(const tree_managerConstRef &TM, const tree_nodeConstRef &decl)
Return the name of the function.
Wrapper to call graph.
Class implementation of the structural_manager.
Class specification of the manager for each library.
int debug_level
The debug level.
void setWriteInterface(tree_nodeRef stmt, const std::string &arg_name, std::set< std::string > &operationsW, bool commonRWSignature, tree_nodeConstRef interface_datatype, const tree_manipulationRef tree_man, const tree_managerRef TM)
#define GET_INDEX_CONST_NODE(t)
Definition: tree_node.hpp:363
static bool IsPointerType(const tree_nodeConstRef &type)
Return true if treenode index is a pointer.
tree_nodeRef create_identifier_node(const std::string &strg) const
IDENTIFIER_TREE_NODE.
static structural_objectRef add_port_vector(std::string id, port_o::port_direction pdir, unsigned int n_ports, structural_objectRef owner, structural_type_descriptorRef type_descr, unsigned int treenode=0)
Create a new port_vector.
tree_nodeRef create_gimple_modify_stmt(const tree_nodeRef &op0, const tree_nodeRef &op1, unsigned int function_decl_nid, const std::string &srcp) const
GIMPLE_ASSIGN.
#define GENERATED_COPYRIGHT
std::string cxa_demangle(const std::string &input)
This class creates a layer to add nodes and to manipulate the tree_nodes manager. ...
static time_infoRef factory(const ParameterConstRef Param)
Definition: time_info.cpp:110
Class specification of the manager of the tree structures extracted from the raw file.
static unsigned long long GetArrayTotalSize(const tree_nodeConstRef &node)
Return the total number of elements of the the base type in the array.
Base class for technology flow steps.
HLS specialization of generic_device.
void ComputeRelationships(DesignFlowStepSet &relationship, const DesignFlowStep::RelationshipType relationship_type) override
Compute the relationships of a step with other steps.
A brief description of the C++ Header File.
static bool IsRealType(const tree_nodeConstRef &type)
Return true if the treenode is of real type.
int sl
Definition: adpcm.c:105
#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
Implementation of the wrapper to Gcc for C sources.

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