PandA-2024.02
fu_binding.cpp
Go to the documentation of this file.
1 /*
2  *
3  * _/_/_/ _/_/ _/ _/ _/_/_/ _/_/
4  * _/ _/ _/ _/ _/_/ _/ _/ _/ _/ _/
5  * _/_/_/ _/_/_/_/ _/ _/_/ _/ _/ _/_/_/_/
6  * _/ _/ _/ _/ _/ _/ _/ _/ _/
7  * _/ _/ _/ _/ _/ _/_/_/ _/ _/
8  *
9  * ***********************************************
10  * PandA Project
11  * URL: http://panda.dei.polimi.it
12  * Politecnico di Milano - DEIB
13  * System Architectures Group
14  * ***********************************************
15  * Copyright (C) 2004-2024 Politecnico di Milano
16  *
17  * This file is part of the PandA framework.
18  *
19  * The PandA framework is free software; you can redistribute it and/or modify
20  * it under the terms of the GNU General Public License as published by
21  * the Free Software Foundation; either version 3 of the License, or
22  * (at your option) any later version.
23  *
24  * This program is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27  * GNU General Public License for more details.
28  *
29  * You should have received a copy of the GNU General Public License
30  * along with this program. If not, see <http://www.gnu.org/licenses/>.
31  *
32  */
46 #include "fu_binding.hpp"
47 
48 #include "fu_binding_cs.hpp"
49 #include "funit_obj.hpp"
50 
51 #include "call_graph_manager.hpp"
52 #include "hls.hpp"
53 #include "hls_device.hpp"
54 #include "hls_manager.hpp"
55 #include "memory.hpp"
56 #include "memory_allocation.hpp"
57 #include "memory_cs.hpp"
58 #include "memory_symbol.hpp"
59 #include "omp_functions.hpp"
60 #include "reg_binding.hpp"
61 
62 #include "functions.hpp"
63 
64 #include "structural_manager.hpp"
65 #include "structural_objects.hpp"
66 
67 #include "constant_strings.hpp"
68 
69 #include "utility.hpp"
70 
71 #include "behavioral_helper.hpp"
72 #include "tree_helper.hpp"
73 #include "tree_manager.hpp"
74 #include "tree_node.hpp"
75 #include "tree_reindex.hpp"
76 
77 #include "conn_binding.hpp"
78 
79 #include "library_manager.hpp"
80 #include "technology_manager.hpp"
81 #include "technology_node.hpp"
82 
83 #include <boost/algorithm/string/replace.hpp>
84 
85 #include "Parameter.hpp"
86 
88 #include "language_writer.hpp"
89 
92 
94 #include "custom_set.hpp"
95 #include <algorithm>
96 #include <fstream>
97 #include <limits>
98 #include <string>
99 #include <utility>
100 #include <vector>
101 
103 #include "fileIO.hpp"
104 #include "math_function.hpp"
105 #include "string_manipulation.hpp"
106 
108 
109 fu_binding::fu_binding(const HLS_managerConstRef _HLSMgr, const unsigned int _function_id,
110  const ParameterConstRef _parameters)
111  : allocation_information(_HLSMgr->get_HLS(_function_id)->allocation_information),
112  TreeM(_HLSMgr->get_tree_manager()),
113  op_graph(_HLSMgr->CGetFunctionBehavior(_function_id)->CGetOpGraph(FunctionBehavior::DFG)),
114  parameters(_parameters),
115  debug_level(_parameters->get_class_debug_level(GET_CLASS(*this))),
116  has_resource_sharing_p(true)
117 {
118 }
119 
121  : unique_table(original.unique_table),
122  operations(original.operations),
123  op_binding(original.op_binding),
125  TreeM(original.TreeM),
126  op_graph(original.op_graph),
127  parameters(original.parameters),
128  debug_level(parameters->get_class_debug_level(GET_CLASS(*this))),
130 {
131 }
132 
133 fu_binding::~fu_binding() = default;
134 
135 fu_bindingRef fu_binding::create_fu_binding(const HLS_managerConstRef _HLSMgr, const unsigned int _function_id,
136  const ParameterConstRef _parameters)
137 {
138  if(_parameters->isOption(OPT_context_switch))
139  {
140  auto omp_functions = GetPointer<OmpFunctions>(_HLSMgr->Rfuns);
141  bool found = false;
142  if(omp_functions->kernel_functions.find(_function_id) != omp_functions->kernel_functions.end())
143  {
144  found = true;
145  }
146  if(omp_functions->hierarchical_functions.find(_function_id) != omp_functions->hierarchical_functions.end())
147  {
148  found = true;
149  }
150  if(omp_functions->parallelized_functions.find(_function_id) != omp_functions->parallelized_functions.end())
151  {
152  found = true;
153  }
154  if(omp_functions->atomic_functions.find(_function_id) != omp_functions->atomic_functions.end())
155  {
156  found = true;
157  }
158  if(found)
159  {
160  return fu_bindingRef(new fu_binding_cs(_HLSMgr, _function_id, _parameters));
161  }
162  else
163  {
164  return fu_bindingRef(new fu_binding(_HLSMgr, _function_id, _parameters));
165  }
166  }
167  else
168  {
169  return fu_bindingRef(new fu_binding(_HLSMgr, _function_id, _parameters));
170  }
171 }
172 
173 void fu_binding::bind(const vertex& v, unsigned int unit, unsigned int index)
174 {
175  const auto key = std::make_pair(unit, index);
176  if(!unique_table.count(key))
177  {
178  unique_table[key] =
179  generic_objRef(new funit_obj(allocation_information->get_string_name(unit) + "_i" + STR(index), unit, index));
180  }
181  const auto statement_index = op_graph->CGetOpNodeInfo(v)->GetNodeId();
182  op_binding[statement_index] = unique_table[key];
183  if(!operations.count(key))
184  {
185  operations.insert(std::make_pair(key, OpVertexSet(op_graph)));
186  }
187  operations.at(key).insert(v);
188  if(index != INFINITE_UINT)
189  {
190  update_allocation(unit, index + 1);
191  }
192 }
193 
194 OpVertexSet fu_binding::get_operations(unsigned int unit, unsigned int index) const
195 {
196  if(operations.find(std::make_pair(unit, index)) == operations.end())
197  {
198  return OpVertexSet(op_graph);
199  }
200  return operations.find(std::make_pair(unit, index))->second;
201 }
202 
204 {
205  const auto statement_index = op_graph->CGetOpNodeInfo(v)->GetNodeId();
206  THROW_ASSERT(op_binding.count(statement_index), "vertex not preset");
207  return *(GetPointer<funit_obj>(op_binding.at(statement_index)));
208 }
209 
210 bool fu_binding::is_assigned(const vertex& v) const
211 {
212  const auto statement_index = op_graph->CGetOpNodeInfo(v)->GetNodeId();
213  return is_assigned(statement_index);
214 }
215 
216 bool fu_binding::is_assigned(const unsigned int statement_index) const
217 {
218  return op_binding.count(statement_index);
219 }
220 
221 std::list<unsigned int> fu_binding::get_allocation_list() const
222 {
223  std::list<unsigned int> allocation_list;
224  for(const auto alloc : allocation_map)
225  {
226  if(alloc.second > 0)
227  {
228  allocation_list.push_back(alloc.first);
229  }
230  }
231  return allocation_list;
232 }
233 
234 void fu_binding::update_allocation(unsigned int unit, unsigned int number)
235 {
236  if(number > allocation_map[unit])
237  {
238  allocation_map[unit] = number;
239  }
240 }
241 
242 unsigned int fu_binding::get_assign(vertex const& v) const
243 {
244  const auto statement_index = op_graph->CGetOpNodeInfo(v)->GetNodeId();
245  return get_assign(statement_index);
246 }
247 
248 unsigned int fu_binding::get_assign(const unsigned int statement_index) const
249 {
250  THROW_ASSERT(op_binding.find(statement_index) != op_binding.end(),
251  "Operation " + TreeM->get_tree_node_const(statement_index)->ToString() + " not assigned");
252  THROW_ASSERT(GetPointer<funit_obj>(op_binding.find(statement_index)->second), "");
253  return GetPointer<funit_obj>(op_binding.at(statement_index))->get_fu();
254 }
255 
256 std::string fu_binding::get_fu_name(vertex const& v) const
257 {
259 }
260 
261 unsigned int fu_binding::get_index(vertex const& v) const
262 {
263  const auto statement_index = op_graph->CGetOpNodeInfo(v)->GetNodeId();
264  return GetPointer<funit_obj>(op_binding.at(statement_index))->get_index();
265 }
266 
268  const std::string& name, const OpVertexSet& ops,
269  structural_objectRef clock_port, structural_objectRef reset_port) const
270 {
271  const auto FB = HLSMgr->CGetFunctionBehavior(HLS->functionId);
272  const auto data = FB->CGetOpGraph(FunctionBehavior::CFG);
273  const auto& SM = HLS->datapath;
274  const auto circuit = SM->get_circ();
275  structural_objectRef curr_gate(new component_o(debug_level, circuit));
277  structural_objectRef curr_lib_instance;
278  if(GetPointerS<functional_unit>(fu)->fu_template_name == "")
279  {
280  curr_lib_instance = GetPointer<functional_unit>(fu)->CM->get_circ();
281  }
282  else
283  {
284  const auto template_name = GetPointer<functional_unit>(fu)->fu_template_name;
285  const auto library_name = HLS->HLS_D->get_technology_manager()->get_library(template_name);
286  curr_lib_instance =
287  GetPointerS<functional_unit>(GetPointerS<functional_unit_template>(
288  HLS->HLS_D->get_technology_manager()->get_fu(template_name, library_name))
289  ->FU)
290  ->CM->get_circ();
291  }
292  THROW_ASSERT(curr_lib_instance, "structural description not provided: check the library given. Component: " +
293  GetPointerS<functional_unit>(fu)->functional_unit_name);
294 
295  curr_lib_instance->copy(curr_gate);
296  if(ops.size() == 1)
297  {
298  curr_gate->set_id("fu_" + GET_NAME(data, *(ops.begin())));
299  }
300  else
301  {
302  THROW_ASSERT(!name.empty(), "cannot name the added gate if the name is empty");
303  curr_gate->set_id(name);
304  }
305 
307  const auto port_ck = curr_gate->find_member(CLOCK_PORT_NAME, port_o_K, curr_gate);
308  if(port_ck)
309  {
310  SM->add_connection(clock_port, port_ck);
311  }
312  const auto port_rst = curr_gate->find_member(RESET_PORT_NAME, port_o_K, curr_gate);
313  if(port_rst)
314  {
315  SM->add_connection(reset_port, port_rst);
316  }
317  GetPointerS<module>(circuit)->add_internal_object(curr_gate);
318 
319  return curr_gate;
320 }
321 
322 void fu_binding::kill_proxy_memory_units(std::map<unsigned int, unsigned int>& memory_units,
323  structural_objectRef curr_gate,
324  std::map<unsigned int, std::list<structural_objectRef>>& var_call_sites_rel,
325  std::map<unsigned int, unsigned int>& reverse_memory_units)
326 {
328  OrderedSetStd<unsigned int> killing_vars;
329  const auto it_mu_end = memory_units.end();
330  for(auto it_mu = memory_units.begin(); it_mu != it_mu_end; ++it_mu)
331  {
332  killing_vars.insert(it_mu->second);
333  reverse_memory_units[it_mu->second] = it_mu->first;
334  }
335  for(const auto kv : killing_vars)
336  {
337  structural_objectRef port_proxy_in1 = curr_gate->find_member("proxy_in1_" + STR(kv), port_o_K, curr_gate);
338  if(port_proxy_in1)
339  {
340  var_call_sites_rel[kv].push_back(curr_gate);
341  GetPointer<port_o>(port_proxy_in1)->set_is_memory(false);
342  for(const auto p_name :
343  {"proxy_in2_", "proxy_in2r_", "proxy_in2w_", "proxy_in3_", "proxy_in3r_", "proxy_in3w_", "proxy_out1_",
344  "proxy_sel_LOAD_", "proxy_sel_STORE_", "proxy_in4r_", "proxy_in4w_"})
345  {
346  const auto port = curr_gate->find_member(p_name + STR(kv), port_o_K, curr_gate);
347  if(port)
348  {
349  GetPointerS<port_o>(port)->set_is_memory(false);
350  }
351  }
352  }
353  }
354 }
355 
356 void fu_binding::kill_proxy_function_units(std::map<unsigned int, std::string>& wrapped_units,
357  structural_objectRef curr_gate,
358  std::map<std::string, std::list<structural_objectRef>>& fun_call_sites_rel,
359  std::map<std::string, unsigned int>& reverse_wrapped_units)
360 {
362  OrderedSetStd<std::string> killing_funs;
363  const auto it_mu_end = wrapped_units.end();
364  for(auto it_mu = wrapped_units.begin(); it_mu != it_mu_end; ++it_mu)
365  {
366  killing_funs.insert(it_mu->second);
367  reverse_wrapped_units[it_mu->second] = it_mu->first;
368  }
369  for(const auto& fun_name : killing_funs)
370  {
371  auto inPortSize = static_cast<unsigned int>(GetPointer<module>(curr_gate)->get_in_port_size());
372  for(unsigned int currentPort = 0; currentPort < inPortSize; ++currentPort)
373  {
374  structural_objectRef curr_port = GetPointer<module>(curr_gate)->get_in_port(currentPort);
375  if(!GetPointer<port_o>(curr_port)->get_is_memory())
376  {
377  continue;
378  }
379  std::string port_name = curr_port->get_id();
380  if(starts_with(port_name, PROXY_PREFIX))
381  {
382  size_t found = port_name.rfind(fun_name);
383  if(found != std::string::npos && found + fun_name.size() == port_name.size())
384  {
385  GetPointer<port_o>(curr_port)->set_is_memory(false);
386  if(std::find(fun_call_sites_rel[fun_name].begin(), fun_call_sites_rel[fun_name].end(), curr_gate) ==
387  fun_call_sites_rel[fun_name].end())
388  {
389  fun_call_sites_rel[fun_name].push_back(curr_gate);
390  }
391  }
392  }
393  }
394  auto outPortSize = static_cast<unsigned int>(GetPointer<module>(curr_gate)->get_out_port_size());
395  for(unsigned int currentPort = 0; currentPort < outPortSize; ++currentPort)
396  {
397  structural_objectRef curr_port = GetPointer<module>(curr_gate)->get_out_port(currentPort);
398  if(!GetPointer<port_o>(curr_port)->get_is_memory())
399  {
400  continue;
401  }
402  std::string port_name = curr_port->get_id();
403  size_t found = port_name.rfind(fun_name);
404  if(found != std::string::npos && found + fun_name.size() == port_name.size())
405  {
406  GetPointer<port_o>(curr_port)->set_is_memory(false);
407  if(std::find(fun_call_sites_rel[fun_name].begin(), fun_call_sites_rel[fun_name].end(), curr_gate) ==
408  fun_call_sites_rel[fun_name].end())
409  {
410  fun_call_sites_rel[fun_name].push_back(curr_gate);
411  }
412  }
413  }
414  }
415 }
416 
418  std::map<unsigned int, structural_objectRef>& mem_obj, std::map<unsigned int, unsigned int>& reverse_memory_units,
419  std::map<unsigned int, std::list<structural_objectRef>>& var_call_sites_rel, const structural_managerRef SM,
420  const hlsRef HLS, unsigned int& _unique_id)
421 {
422  const auto circuit = SM->get_circ();
423  for(const auto& vcsr : var_call_sites_rel)
424  {
425  const auto& var = vcsr.first;
426  const auto& proxies = vcsr.second;
427 
428  THROW_ASSERT(reverse_memory_units.count(var), "var not found");
429  const auto storage_fu_id = reverse_memory_units.at(var);
430  THROW_ASSERT(mem_obj.count(storage_fu_id), "storage_fu not found: " + STR(storage_fu_id));
431  const auto storage_fu = mem_obj.at(storage_fu_id);
432  const auto storage_port_out = storage_fu->find_member("proxy_out1", port_o_K, storage_fu);
433  THROW_ASSERT(storage_port_out, "missing proxy_out1 port");
434  const auto storage_port_out_sign = [&]() {
435  if(storage_port_out->get_kind() == port_vector_o_K)
436  {
437  return SM->add_sign_vector("S" + storage_port_out->get_id() + "_" + STR(var),
438  GetPointerS<port_o>(storage_port_out)->get_ports_size(), circuit,
439  storage_port_out->get_typeRef());
440  }
441  return SM->add_sign("S" + storage_port_out->get_id() + "_" + STR(var), circuit,
442  storage_port_out->get_typeRef());
443  }();
444  SM->add_connection(storage_port_out_sign, storage_port_out);
445 
446  const auto proxy_ports = [&]() {
447  std::vector<structural_objectRef> ports;
448  for(const auto& pname : {"proxy_in1", "proxy_in2", "proxy_in2r", "proxy_in2w", "proxy_in3", "proxy_in3r",
449  "proxy_in3w", "proxy_sel_LOAD", "proxy_sel_STORE", "proxy_in4r", "proxy_in4w"})
450  {
451  const auto port = storage_fu->find_member(pname, port_o_K, storage_fu);
452  if(port)
453  {
454  ports.push_back(port);
455  }
456  }
457  return ports;
458  }();
459  std::map<structural_objectRef, std::list<structural_objectRef>, jms_sorter> to_be_merged;
460  const auto var_suffix = "_" + STR(var);
461  for(const auto& proxied_unit : proxies)
462  {
463  const auto port_out = proxied_unit->find_member("proxy_out1" + var_suffix, port_o_K, proxied_unit);
464  THROW_ASSERT(port_out, "missing proxied proxy_out1 port");
465  SM->add_connection(storage_port_out_sign, port_out);
466 
467  for(const auto& pport : proxy_ports)
468  {
469  const auto port = proxied_unit->find_member(pport->get_id() + var_suffix, port_o_K, proxied_unit);
470  if(port)
471  {
472  to_be_merged[pport].push_back(port);
473  }
474  }
475  }
476  join_merge_split(SM, HLS, to_be_merged, circuit, _unique_id);
477  }
478 }
479 
481  std::map<unsigned int, structural_objectRef>& fun_obj, std::map<std::string, unsigned int>& reverse_function_units,
482  std::map<std::string, std::list<structural_objectRef>>& fun_call_sites_rel, const structural_managerRef SM,
483  const hlsRef HLS, unsigned int& _unique_id)
484 {
485  const auto circuit = SM->get_circ();
486  for(const auto& fcsr : fun_call_sites_rel)
487  {
488  const auto& fun = fcsr.first;
489  const auto& proxies = fcsr.second;
490  THROW_ASSERT(reverse_function_units.count(fun), "fun not found");
491  const auto wrapped_fu_unit_id = reverse_function_units.at(fun);
492  THROW_ASSERT(fun_obj.count(wrapped_fu_unit_id), "wrapped_fu_unit not found");
493  const auto wrapped_fu_unit = fun_obj.at(wrapped_fu_unit_id);
494  std::map<structural_objectRef, std::list<structural_objectRef>, jms_sorter> to_be_merged;
495 
496  const auto inPortSize = GetPointer<module>(wrapped_fu_unit)->get_in_port_size();
497  for(auto currentPort = 0U; currentPort < inPortSize; ++currentPort)
498  {
499  const auto curr_port = GetPointerS<module>(wrapped_fu_unit)->get_in_port(currentPort);
500  const auto port_name = curr_port->get_id();
501  if(starts_with(port_name, PROXY_PREFIX))
502  {
503  for(const auto& proxied_unit : proxies)
504  {
505  const auto port_proxy_in_i = proxied_unit->find_member(port_name + "_" + fun, port_o_K, proxied_unit);
506  if(port_proxy_in_i)
507  {
508  to_be_merged[curr_port].push_back(port_proxy_in_i);
509  }
510  }
511  }
512  }
513  const auto outPortSize = GetPointer<module>(wrapped_fu_unit)->get_out_port_size();
514  for(auto currentPort = 0U; currentPort < outPortSize; ++currentPort)
515  {
516  const auto wrapped_port_proxy_out_i = GetPointerS<module>(wrapped_fu_unit)->get_out_port(currentPort);
517  const auto port_name = wrapped_port_proxy_out_i->get_id();
518  if(starts_with(port_name, PROXY_PREFIX))
519  {
520  structural_objectRef wrapped_port_proxy_out_i_sign;
521  for(const auto& proxied_unit : proxies)
522  {
523  const auto port_proxy_out_i = proxied_unit->find_member(port_name + "_" + fun, port_o_K, proxied_unit);
524  if(port_proxy_out_i)
525  {
526  if(!wrapped_port_proxy_out_i_sign)
527  {
528  if(wrapped_port_proxy_out_i->get_kind() == port_vector_o_K)
529  {
530  wrapped_port_proxy_out_i_sign =
531  SM->add_sign_vector(wrapped_port_proxy_out_i->get_id() + "_" + fun,
532  GetPointer<port_o>(wrapped_port_proxy_out_i)->get_ports_size(), circuit,
533  wrapped_port_proxy_out_i->get_typeRef());
534  }
535  else
536  {
537  wrapped_port_proxy_out_i_sign = SM->add_sign(wrapped_port_proxy_out_i->get_id() + "_" + fun,
538  circuit, wrapped_port_proxy_out_i->get_typeRef());
539  }
540  SM->add_connection(wrapped_port_proxy_out_i_sign, wrapped_port_proxy_out_i);
541  }
542  SM->add_connection(wrapped_port_proxy_out_i_sign, port_proxy_out_i);
543  }
544  }
545  }
546  }
547  join_merge_split(SM, HLS, to_be_merged, circuit, _unique_id);
548  }
549 }
550 
551 void fu_binding::add_to_SM(const HLS_managerRef HLSMgr, const hlsRef HLS, structural_objectRef clock_port,
552  structural_objectRef reset_port)
553 {
554  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Adding functional units to circuit");
555  const auto SM = HLS->datapath;
556  const auto TechM = HLS->HLS_D->get_technology_manager();
557 
559  unsigned int unique_id = 0U;
560 
562  has_resource_sharing_p = !HLS->Rreg->is_all_regs_without_enable(); // it assumes that HLS->Rreg->add_to_SM is called
563  // first and then HLS->Rfu->add_to_SM
564 
565  const auto circuit = SM->get_circ();
566 
567  std::list<structural_objectRef> memory_modules;
568 
570  const auto FB = HLSMgr->CGetFunctionBehavior(HLS->functionId);
571  const auto function_parameters = FB->CGetBehavioralHelper()->get_parameters();
572  unsigned int sign_id = 0;
573  const auto start_port = GetPointer<module>(circuit)->find_member(START_PORT_NAME, port_o_K, circuit);
574  const auto done_port = GetPointer<module>(circuit)->find_member(DONE_PORT_NAME, port_o_K, circuit);
575  structural_objectRef in_chain = start_port;
576  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Adding parameter ports");
577  for(const auto& function_parameter : function_parameters)
578  {
579  if(HLSMgr->Rmem->is_parm_decl_copied(function_parameter) &&
580  !HLSMgr->Rmem->is_parm_decl_stored(function_parameter))
581  {
582  PRINT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "Managing parameter copy: " + STR(function_parameter));
583  const auto fu_lib_unit = TechM->get_fu(MEMCPY_STD, WORK_LIBRARY);
584  THROW_ASSERT(fu_lib_unit,
585  "functional unit not available: check the library given. Component: " + std::string(MEMCPY_STD));
586  const auto curr_gate = add_gate(HLSMgr, HLS, fu_lib_unit, "parameter_manager_" + STR(function_parameter),
587  OpVertexSet(op_graph), clock_port, reset_port);
588  const auto curr_gate_m = GetPointerS<module>(curr_gate);
589  const auto port_obj = HLS->Rconn->get_port(function_parameter, conn_binding::IN);
590  const auto in_par = port_obj->get_out_sign();
591  const auto src = curr_gate_m->find_member("src", port_o_K, curr_gate);
592  SM->add_connection(in_par, src);
593  const auto dest = curr_gate_m->find_member("dest", port_o_K, curr_gate);
594 
595  const auto const_obj = SM->add_module_from_technology_library(
596  "memcpy_dest_" + HLSMgr->Rmem->get_symbol(function_parameter, HLS->functionId)->get_symbol_name(),
597  CONSTANT_STD, LIBRARY_STD, circuit, TechM);
598  const_obj->SetParameter("value",
599  HLSMgr->Rmem->get_symbol(function_parameter, HLS->functionId)->get_symbol_name());
600  const auto name = "out_const_memcpy_dest_" +
601  HLSMgr->Rmem->get_symbol(function_parameter, HLS->functionId)->get_symbol_name();
602  const auto dest_sign = SM->add_sign(name, circuit, dest->get_typeRef());
603  const auto out_port = const_obj->find_member("out1", port_o_K, const_obj);
604  // customize output port size
605  out_port->type_resize(STD_GET_SIZE(dest->get_typeRef()));
606  SM->add_connection(dest_sign, out_port);
607  SM->add_connection(dest, dest_sign);
608  const auto n = curr_gate_m->find_member("len", port_o_K, curr_gate);
609  const auto n_obj = SM->add_constant(
610  "constant_len_" + STR(function_parameter), circuit, n->get_typeRef(),
611  STR(tree_helper::Size(tree_helper::CGetType(TreeM->CGetTreeReindex(function_parameter))) / 8));
612  SM->add_connection(n, n_obj);
613  THROW_ASSERT(in_chain, "missing in chain element");
614  const auto start_obj = curr_gate_m->find_member(START_PORT_NAME, port_o_K, curr_gate);
615 
616  if(HLS->registered_inputs && in_chain == start_port)
617  {
618  const auto delay_unit = [&]() {
619  const auto reset_type = parameters->getOption<std::string>(OPT_reset_type);
620  return TechM->get_fu(reset_type == "sync" ? flipflop_SR : flipflop_AR, LIBRARY_STD);
621  }();
622  THROW_ASSERT(delay_unit, "");
623  const auto delay_gate = add_gate(HLSMgr, HLS, delay_unit, "start_delayed_" + STR(function_parameter),
624  OpVertexSet(op_graph), clock_port, reset_port);
625  const auto sign =
626  SM->add_sign(START_PORT_NAME + STR("_") + STR(sign_id), circuit, start_obj->get_typeRef());
627  ++sign_id;
628  SM->add_connection(sign, in_chain);
629  SM->add_connection(sign, GetPointer<module>(delay_gate)->get_in_port(2));
630  }
631 
632  if(in_chain == start_port)
633  {
634  SM->add_connection(in_chain, start_obj);
635  }
636  else
637  {
638  const auto sign = SM->add_sign(START_PORT_NAME + STR("_") + STR(sign_id), circuit, in_chain->get_typeRef());
639  ++sign_id;
640  SM->add_connection(sign, in_chain);
641  SM->add_connection(sign, start_obj);
642  }
643  in_chain = curr_gate_m->find_member(DONE_PORT_NAME, port_o_K, curr_gate);
644  manage_module_ports(HLSMgr, HLS, SM, curr_gate, 0);
645  memory_modules.push_back(curr_gate);
646  }
647  else if(HLSMgr->Rmem->is_parm_decl_stored(function_parameter))
648  {
650  "---Managing parameter initialization: " + STR(function_parameter));
651  auto bus_data_bitsize = HLSMgr->Rmem->get_bus_data_bitsize();
652  auto bus_addr_bitsize = HLSMgr->get_address_bitsize();
653  auto bus_size_bitsize = HLSMgr->Rmem->get_bus_size_bitsize();
654  unsigned long long bus_tag_bitsize = 0;
655  if(HLS->Param->getOption<bool>(OPT_parse_pragma) && HLS->Param->isOption(OPT_context_switch))
656  {
657  bus_tag_bitsize = GetPointer<memory_cs>(HLSMgr->Rmem)->get_bus_tag_bitsize();
658  }
659  const auto is_multiport = FB->GetChannelsType() == MemoryAllocation_ChannelsType::MEM_ACC_NN;
660  const auto fu_lib_unit = TechM->get_fu(is_multiport ? MEMSTORE_STDN : MEMSTORE_STD, LIBRARY_STD_FU);
661  THROW_ASSERT(fu_lib_unit, "functional unit not available: check the library given. Component: " +
662  STR(is_multiport ? MEMSTORE_STDN : MEMSTORE_STD));
663  const auto max_n_ports = FB->GetChannelsNumber();
664  const auto curr_gate = add_gate(HLSMgr, HLS, fu_lib_unit, "parameter_manager_" + STR(function_parameter),
665  OpVertexSet(op_graph), clock_port, reset_port);
666  const auto port_obj = HLS->Rconn->get_port(function_parameter, conn_binding::IN);
667  const auto in_par = port_obj->get_out_sign();
668  const auto data = GetPointer<module>(curr_gate)->find_member("data", port_o_K, curr_gate);
669  data->type_resize(STD_GET_SIZE(in_par->get_typeRef()));
670  SM->add_connection(in_par, data);
671 
672  const auto size = GetPointer<module>(curr_gate)->find_member("size", port_o_K, curr_gate);
673  size->type_resize(STD_GET_SIZE(in_par->get_typeRef()));
674  const auto size_const_obj = SM->add_module_from_technology_library(
675  "size_par_" + HLSMgr->Rmem->get_symbol(function_parameter, HLS->functionId)->get_symbol_name(),
676  CONSTANT_STD, LIBRARY_STD, circuit, TechM);
677  const std::string parameter_value =
678  (static_cast<HDLWriter_Language>(parameters->getOption<unsigned int>(OPT_writer_language)) ==
680  std::string("\"") +
681  NumberToBinaryString(STD_GET_SIZE(in_par->get_typeRef()), STD_GET_SIZE(in_par->get_typeRef())) +
682  std::string("\"") :
683  STR(STD_GET_SIZE(in_par->get_typeRef()));
684  size_const_obj->SetParameter("value", parameter_value);
685  const auto size_name =
686  "out_const_size_par_" + HLSMgr->Rmem->get_symbol(function_parameter, HLS->functionId)->get_symbol_name();
687  const auto size_sign = SM->add_sign(size_name, circuit, size->get_typeRef());
688  const auto size_out_port = size_const_obj->find_member("out1", port_o_K, size_const_obj);
689  // customize output port size
690  size_out_port->type_resize(STD_GET_SIZE(in_par->get_typeRef()));
691  SM->add_connection(size_sign, size_out_port);
692  SM->add_connection(size, size_sign);
693 
694  const auto addr = GetPointer<module>(curr_gate)->find_member("addr", port_o_K, curr_gate);
695  addr->type_resize(bus_addr_bitsize);
696  const auto const_obj = SM->add_module_from_technology_library(
697  "addr_par_" + HLSMgr->Rmem->get_symbol(function_parameter, HLS->functionId)->get_symbol_name(),
698  CONSTANT_STD, LIBRARY_STD, circuit, TechM);
699  const_obj->SetParameter("value",
700  HLSMgr->Rmem->get_symbol(function_parameter, HLS->functionId)->get_symbol_name());
701  const auto name =
702  "out_const_addr_par_" + HLSMgr->Rmem->get_symbol(function_parameter, HLS->functionId)->get_symbol_name();
703  const auto addr_sign = SM->add_sign(name, circuit, addr->get_typeRef());
704  const auto out_port = const_obj->find_member("out1", port_o_K, const_obj);
705  // customize output port size
706  out_port->type_resize(bus_addr_bitsize);
707  SM->add_connection(addr_sign, out_port);
708  SM->add_connection(addr, addr_sign);
709 
710  THROW_ASSERT(in_chain, "missing in chain element");
711  structural_objectRef start_obj =
712  GetPointer<module>(curr_gate)->find_member(START_PORT_NAME, port_o_K, curr_gate);
713  if(HLS->registered_inputs && in_chain == start_port)
714  {
715  technology_nodeRef delay_unit;
716  auto reset_type = parameters->getOption<std::string>(OPT_reset_type);
717  if(reset_type == "sync")
718  {
719  delay_unit = TechM->get_fu(flipflop_SR, LIBRARY_STD);
720  }
721  else
722  {
723  delay_unit = TechM->get_fu(flipflop_AR, LIBRARY_STD);
724  }
725  structural_objectRef delay_gate =
726  add_gate(HLSMgr, HLS, delay_unit, "start_delayed_" + STR(function_parameter), OpVertexSet(op_graph),
727  clock_port, reset_port);
729  SM->add_sign(START_PORT_NAME + STR("_") + STR(sign_id), circuit, start_obj->get_typeRef());
730  ++sign_id;
731  SM->add_connection(sign, in_chain);
732  SM->add_connection(sign, GetPointer<module>(delay_gate)->get_in_port(2));
733  in_chain = GetPointer<module>(delay_gate)->get_out_port(0);
734  }
735 
736  if(in_chain == start_port)
737  {
738  SM->add_connection(in_chain, start_obj);
739  }
740  else
741  {
743  SM->add_sign(START_PORT_NAME + STR("_") + STR(sign_id), circuit, in_chain->get_typeRef());
744  ++sign_id;
745  SM->add_connection(sign, in_chain);
746  SM->add_connection(sign, start_obj);
747  }
748  in_chain = GetPointer<module>(curr_gate)->find_member(DONE_PORT_NAME, port_o_K, curr_gate);
750  for(unsigned int i = 0; i < GetPointer<module>(curr_gate)->get_in_port_size(); i++)
751  {
752  structural_objectRef port = GetPointer<module>(curr_gate)->get_in_port(i);
753  if(is_multiport && port->get_kind() == port_vector_o_K && GetPointer<port_o>(port)->get_ports_size() == 0)
754  {
755  GetPointer<port_o>(port)->add_n_ports(static_cast<unsigned int>(max_n_ports), port);
756  }
757  port_o::resize_if_busport(bus_size_bitsize, bus_addr_bitsize, bus_data_bitsize, bus_tag_bitsize, port);
758  }
759  for(unsigned int i = 0; i < GetPointer<module>(curr_gate)->get_out_port_size(); i++)
760  {
761  structural_objectRef port = GetPointer<module>(curr_gate)->get_out_port(i);
762  if(is_multiport && port->get_kind() == port_vector_o_K && GetPointer<port_o>(port)->get_ports_size() == 0)
763  {
764  GetPointer<port_o>(port)->add_n_ports(static_cast<unsigned int>(max_n_ports), port);
765  }
766  port_o::resize_if_busport(bus_size_bitsize, bus_addr_bitsize, bus_data_bitsize, bus_tag_bitsize, port);
767  }
768  manage_module_ports(HLSMgr, HLS, SM, curr_gate, 0);
769  memory_modules.push_back(curr_gate);
770  }
771  }
772  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Added parameter ports");
773  if(in_chain)
774  {
775  SM->add_connection(in_chain, done_port);
776  }
777  else
778  {
779  THROW_ASSERT(!done_port, "done port not connected");
780  }
781 
782  if(HLS->control_flow_checker)
783  {
784  structural_objectRef controller_flow_circuit = HLS->control_flow_checker->get_circ();
786  controller_flow_circuit->copy(curr_gate);
787  curr_gate->set_id("ControlFlowChecker_i");
788  GetPointer<module>(circuit)->add_internal_object(curr_gate);
789  structural_objectRef controller_flow_clock = curr_gate->find_member(CLOCK_PORT_NAME, port_o_K, curr_gate);
790  SM->add_connection(controller_flow_clock, clock_port);
791  structural_objectRef controller_flow_reset = curr_gate->find_member(RESET_PORT_NAME, port_o_K, curr_gate);
792  SM->add_connection(controller_flow_reset, reset_port);
793  structural_objectRef controller_flow_start = curr_gate->find_member(START_PORT_NAME, port_o_K, curr_gate);
794  structural_objectRef start_CFC =
795  SM->add_port(START_PORT_NAME_CFC, port_o::IN, circuit,
797  SM->add_connection(start_CFC, controller_flow_start);
798  structural_objectRef controller_flow_done = curr_gate->find_member(DONE_PORT_NAME, port_o_K, curr_gate);
799  structural_objectRef done_CFC =
800  SM->add_port(DONE_PORT_NAME_CFC, port_o::IN, circuit,
802  SM->add_connection(done_CFC, controller_flow_done);
803  structural_objectRef controller_flow_present_state =
804  curr_gate->find_member(PRESENT_STATE_PORT_NAME, port_o_K, curr_gate);
805  structural_objectRef controller_present_state =
806  SM->add_port(PRESENT_STATE_PORT_NAME, port_o::IN, circuit, controller_flow_present_state->get_typeRef());
807  SM->add_connection(controller_present_state, controller_flow_present_state);
808  structural_objectRef controller_flow_next_state =
809  curr_gate->find_member(NEXT_STATE_PORT_NAME, port_o_K, curr_gate);
810  structural_objectRef controller_next_state =
811  SM->add_port(NEXT_STATE_PORT_NAME, port_o::IN, circuit, controller_flow_next_state->get_typeRef());
812  SM->add_connection(controller_next_state, controller_flow_next_state);
813  memory_modules.push_back(curr_gate);
814  }
815 
816  const auto is_sparse_memory =
817  parameters->isOption(OPT_sparse_memory) && parameters->getOption<bool>(OPT_sparse_memory);
818  std::map<unsigned int, unsigned int> memory_units = allocation_information->get_memory_units();
819  std::map<unsigned int, structural_objectRef> mem_obj;
820  for(const auto& m : memory_units)
821  {
822  const auto fu_type_id = m.first;
823  auto var = m.second;
824  std::string name;
825  const auto fun_unit_name = allocation_information->get_fu_name(fu_type_id).first;
827  {
828  name = "array_" + STR(var);
829  }
830  else
831  {
832  THROW_ERROR("Unit not currently supported: " + fun_unit_name);
833  }
834  const technology_nodeRef fu_lib_unit = allocation_information->get_fu(fu_type_id);
835  THROW_ASSERT(fu_lib_unit, "functional unit not available: check the library given. Component: " + fun_unit_name);
836  const auto is_splitted_memory = [&]() {
837  const auto& memory_type = GetPointerS<const functional_unit>(fu_lib_unit)->memory_type;
838  const auto& channels_type = GetPointerS<const functional_unit>(fu_lib_unit)->channels_type;
839  return memory_type == MEMORY_TYPE_SYNCHRONOUS_UNALIGNED &&
840  (channels_type == CHANNELS_TYPE_MEM_ACC_N1 || channels_type == CHANNELS_TYPE_MEM_ACC_NN);
841  }();
842  const auto is_sds_memory = [&]() {
843  const auto& memory_type = GetPointerS<const functional_unit>(fu_lib_unit)->memory_type;
844  return memory_type == MEMORY_TYPE_SYNCHRONOUS_SDS || memory_type == MEMORY_TYPE_SYNCHRONOUS_SDS_BUS ||
845  memory_type == MEMORY_TYPE_ASYNCHRONOUS;
846  }();
847 
849  "Memory Unit: " + allocation_information->get_string_name(fu_type_id) + " for variable: " +
850  HLSMgr->CGetFunctionBehavior(HLS->functionId)->CGetBehavioralHelper()->PrintVariable(var));
851  const auto base_address = HLSMgr->Rmem->get_symbol(var, HLS->functionId)->get_symbol_name();
852  const auto rangesize = HLSMgr->Rmem->get_rangesize(var);
853  PRINT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, " - base address: " + STR(base_address));
854  PRINT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, " - range size: " + STR(rangesize));
855  const auto n_channels = allocation_information->get_number_channels(fu_type_id);
856  const auto total_allocated = get_number(fu_type_id);
857  const auto n_iterations = std::max(1u, total_allocated);
858  for(unsigned int num = 0; num < n_iterations; num += n_channels)
859  {
860  OpVertexSet operations_set(op_graph);
861  for(unsigned int channel_index = 0; channel_index < n_channels && (num + channel_index < total_allocated);
862  ++channel_index)
863  {
864  auto key = std::make_pair(fu_type_id, num + channel_index);
865  if(operations.find(key) != operations.end())
866  {
867  auto opset = operations.at(key);
868  operations_set.insert(opset.begin(), opset.end());
869  }
870  }
871  has_resource_sharing_p = has_resource_sharing_p || (operations_set.size() > 1);
872  structural_objectRef curr_gate = add_gate(HLSMgr, HLS, fu_lib_unit, name + "_" + STR(num / n_channels),
873  OpVertexSet(op_graph), clock_port, reset_port);
874  specialise_fu(HLSMgr, HLS, curr_gate, fu_type_id, operations_set, var);
875  specialize_memory_unit(HLSMgr, HLS, curr_gate, var, base_address, rangesize, is_splitted_memory,
876  is_sparse_memory, is_sds_memory);
877  check_parametrization(curr_gate);
878  mem_obj[fu_type_id] = curr_gate;
879  for(unsigned int channel_index = 0; (channel_index < n_channels) && ((num + channel_index) < total_allocated);
880  ++channel_index)
881  {
882  generic_objRef module_obj = get(fu_type_id, num + channel_index);
883  module_obj->set_structural_obj(curr_gate);
884  }
885  if(!HLSMgr->Rmem->is_private_memory(var))
886  {
887  manage_module_ports(HLSMgr, HLS, SM, curr_gate, 0);
888  memory_modules.push_back(curr_gate);
889  }
890  }
891  }
892 
893  std::map<unsigned int, unsigned int> reverse_memory_units;
894  std::map<std::string, unsigned int> reverse_function_units;
895  std::map<unsigned int, std::list<structural_objectRef>> var_call_sites_rel;
896  std::map<std::string, std::list<structural_objectRef>> fun_call_sites_rel;
897  std::map<unsigned int, structural_objectRef> fun_obj;
898  std::map<unsigned int, std::string> wrapped_units = allocation_information->get_proxy_wrapped_units();
899  for(auto wu = wrapped_units.begin(); wu != wrapped_units.end(); ++wu)
900  {
901  has_resource_sharing_p = true;
902  const auto fu_lib_unit = allocation_information->get_fu(wu->first);
903  THROW_ASSERT(fu_lib_unit, "functional unit not available: check the library given. Component: " +
904  allocation_information->get_fu_name(wu->first).first);
905  const auto curr_gate =
906  add_gate(HLSMgr, HLS, fu_lib_unit, wu->second + "_instance", OpVertexSet(op_graph), clock_port, reset_port);
908  "Wrapped Unit: " + allocation_information->get_string_name(wu->first));
909  const auto mapped_operations = get_operations(wu->first, 0);
910  specialise_fu(HLSMgr, HLS, curr_gate, wu->first, mapped_operations, 0);
911  check_parametrization(curr_gate);
912  fun_obj[wu->first] = curr_gate;
913  kill_proxy_memory_units(memory_units, curr_gate, var_call_sites_rel, reverse_memory_units);
914  kill_proxy_function_units(wrapped_units, curr_gate, fun_call_sites_rel, reverse_function_units);
915  const auto added_memory_element = manage_module_ports(HLSMgr, HLS, SM, curr_gate, 0);
916  if(added_memory_element)
917  {
918  memory_modules.push_back(curr_gate);
919  }
922  }
923 
924  const std::map<unsigned int, unsigned int>& proxy_memory_units = allocation_information->get_proxy_memory_units();
925  const std::map<unsigned int, std::string>& proxy_function_units = allocation_information->get_proxy_function_units();
926 
927  std::list<std::pair<structural_objectRef, unsigned int>> proxy_memory_units_to_be_renamed_back;
928  std::list<std::pair<structural_objectRef, std::string>> proxy_function_units_to_be_renamed_back;
929 
930  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Specializing functional units");
931 
932  for(auto i : this->get_allocation_list())
933  {
935  "-->Functional Unit: " + allocation_information->get_string_name(i));
937  {
938  const auto obj = circuit->find_member(RETURN_PORT_NAME, port_o_K, circuit);
939  get(i, 0)->set_structural_obj(obj);
940  }
941 
943  {
944  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--It has not to be synthesized");
945  continue;
946  }
947  const auto is_multichannel = allocation_information->get_number_channels(i) > 1;
948 
949  for(unsigned int num = 0; num < get_number(i); num++)
950  {
951  const auto module_obj = get(i, num);
952  THROW_ASSERT(module_obj,
953  "module missing: " + allocation_information->get_fu_name(i).first + " instance " + STR(num));
954  const auto name = module_obj->get_string();
955 
956  structural_objectRef curr_gate;
958  {
959  continue;
960  }
961  else if(wrapped_units.find(i) != wrapped_units.end())
962  {
963  curr_gate = fun_obj[i];
964  }
965  else if(is_multichannel && (num % allocation_information->get_number_channels(i)) != 0)
966  {
967  const auto n_channels = allocation_information->get_number_channels(i);
968  const auto true_module_obj = get(i, (num / n_channels) * n_channels);
969  curr_gate = true_module_obj->get_structural_obj();
970  const auto mapped_operations = get_operations(i, num);
971  has_resource_sharing_p = has_resource_sharing_p || (mapped_operations.size() > 1);
972  const auto ar_var =
974  specialise_fu(HLSMgr, HLS, curr_gate, i, mapped_operations, ar_var);
975  module_obj->set_structural_obj(curr_gate);
976  }
977  else
978  {
979  const auto fu_lib_unit = allocation_information->get_fu(i);
980  const auto mapped_operations = get_operations(i, num);
981  THROW_ASSERT(fu_lib_unit, "functional unit not available: check the library given. Component: " +
983  curr_gate = add_gate(HLSMgr, HLS, fu_lib_unit, name,
987  mapped_operations,
988  clock_port, reset_port);
989  has_resource_sharing_p = has_resource_sharing_p || (mapped_operations.size() > 1);
990  std::string current_op;
991  if(mapped_operations.size())
992  {
993  current_op = tree_helper::NormalizeTypename(
994  op_graph->CGetOpNodeInfo(*(mapped_operations.begin()))->GetOperation());
995  }
996  if(current_op == BUILTIN_WAIT_CALL)
997  {
998  has_resource_sharing_p = true;
999  const auto site = *mapped_operations.begin();
1000  const auto vertex_node_id = op_graph->CGetOpNodeInfo(site)->GetNodeId();
1001 
1002  const auto callSiteMemorySym = HLSMgr->Rmem->get_symbol(vertex_node_id, HLS->functionId);
1003  memory::add_memory_parameter(HLS->datapath, callSiteMemorySym->get_symbol_name(),
1004  STR(callSiteMemorySym->get_address()));
1005  }
1006  const auto ar_var =
1008  specialise_fu(HLSMgr, HLS, curr_gate, i, mapped_operations, ar_var);
1009  check_parametrization(curr_gate);
1010  if(proxy_memory_units.find(i) != proxy_memory_units.end())
1011  {
1012  proxy_memory_units_to_be_renamed_back.push_back(
1013  std::make_pair(curr_gate, proxy_memory_units.find(i)->second));
1014  std::string var_name = "_" + STR(proxy_memory_units.find(i)->second);
1015 
1017  const auto port_proxy_in1 = curr_gate->find_member("proxy_in1", port_o_K, curr_gate);
1018  port_proxy_in1->set_id(port_proxy_in1->get_id() + var_name);
1019  const auto is_dual = allocation_information->is_dual_port_memory(i);
1020  if(is_dual)
1021  {
1022  const auto port_proxy_in2r = curr_gate->find_member("proxy_in2r", port_o_K, curr_gate);
1023  const auto port_proxy_in2w = curr_gate->find_member("proxy_in2w", port_o_K, curr_gate);
1024  const auto port_proxy_in3r = curr_gate->find_member("proxy_in3r", port_o_K, curr_gate);
1025  const auto port_proxy_in3w = curr_gate->find_member("proxy_in3w", port_o_K, curr_gate);
1026  const auto port_proxy_in4r = curr_gate->find_member("proxy_in4r", port_o_K, curr_gate);
1027  const auto port_proxy_in4w = curr_gate->find_member("proxy_in4w", port_o_K, curr_gate);
1028  port_proxy_in2r->set_id(port_proxy_in2r->get_id() + var_name);
1029  port_proxy_in2w->set_id(port_proxy_in2w->get_id() + var_name);
1030  port_proxy_in3r->set_id(port_proxy_in3r->get_id() + var_name);
1031  port_proxy_in3w->set_id(port_proxy_in3w->get_id() + var_name);
1032  port_proxy_in4r->set_id(port_proxy_in4r->get_id() + var_name);
1033  port_proxy_in4w->set_id(port_proxy_in4w->get_id() + var_name);
1034  }
1035  else
1036  {
1037  const auto port_proxy_in2 = curr_gate->find_member("proxy_in2", port_o_K, curr_gate);
1038  const auto port_proxy_in3 = curr_gate->find_member("proxy_in3", port_o_K, curr_gate);
1039  port_proxy_in2->set_id(port_proxy_in2->get_id() + var_name);
1040  port_proxy_in3->set_id(port_proxy_in3->get_id() + var_name);
1041  }
1042  const auto port_sel_LOAD = curr_gate->find_member("proxy_sel_LOAD", port_o_K, curr_gate);
1043  const auto port_sel_STORE = curr_gate->find_member("proxy_sel_STORE", port_o_K, curr_gate);
1044  const auto port_proxy_out1 = curr_gate->find_member("proxy_out1", port_o_K, curr_gate);
1045  port_sel_LOAD->set_id(port_sel_LOAD->get_id() + var_name);
1046  port_sel_STORE->set_id(port_sel_STORE->get_id() + var_name);
1047  port_proxy_out1->set_id(port_proxy_out1->get_id() + var_name);
1048  }
1049  kill_proxy_memory_units(memory_units, curr_gate, var_call_sites_rel, reverse_memory_units);
1050 
1051  if(proxy_function_units.find(i) != proxy_function_units.end())
1052  {
1053  std::string fun_name = "_" + STR(proxy_function_units.find(i)->second);
1054  proxy_function_units_to_be_renamed_back.push_back(
1055  std::make_pair(curr_gate, proxy_function_units.find(i)->second));
1056  auto inPortSize = static_cast<unsigned int>(GetPointer<module>(curr_gate)->get_in_port_size());
1057  for(unsigned int currentPort = 0; currentPort < inPortSize; ++currentPort)
1058  {
1059  structural_objectRef curr_port = GetPointer<module>(curr_gate)->get_in_port(currentPort);
1060  if(!GetPointer<port_o>(curr_port)->get_is_memory())
1061  {
1062  continue;
1063  }
1064  std::string port_name = curr_port->get_id();
1065  if(starts_with(port_name, PROXY_PREFIX))
1066  {
1067  GetPointer<port_o>(curr_port)->set_id(port_name + fun_name);
1068  }
1069  }
1070  auto outPortSize = static_cast<unsigned int>(GetPointer<module>(curr_gate)->get_out_port_size());
1071  for(unsigned int currentPort = 0; currentPort < outPortSize; ++currentPort)
1072  {
1073  structural_objectRef curr_port = GetPointer<module>(curr_gate)->get_out_port(currentPort);
1074  if(!GetPointer<port_o>(curr_port)->get_is_memory())
1075  {
1076  continue;
1077  }
1078  std::string port_name = curr_port->get_id();
1079  if(starts_with(port_name, PROXY_PREFIX))
1080  {
1081  GetPointer<port_o>(curr_port)->set_id(port_name + fun_name);
1082  }
1083  }
1084  }
1085  kill_proxy_function_units(wrapped_units, curr_gate, fun_call_sites_rel, reverse_function_units);
1086 
1087  bool added_memory_element = manage_module_ports(HLSMgr, HLS, SM, curr_gate, num);
1088  if(added_memory_element &&
1089  std::find(memory_modules.begin(), memory_modules.end(), curr_gate) == memory_modules.end())
1090  {
1091  memory_modules.push_back(curr_gate);
1092  }
1093 
1096  }
1097  module_obj->set_structural_obj(curr_gate);
1098  }
1100  }
1101  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Specialized functional units");
1103  {
1105  "---Resources are not shared in function " +
1106  HLSMgr->CGetFunctionBehavior(HLS->functionId)->CGetBehavioralHelper()->get_function_name() +
1107  ": function pipelining may come for free");
1108  }
1109 
1110  const auto cg_man = HLSMgr->CGetCallGraphManager();
1111  const auto top_function_ids = cg_man->GetRootFunctions();
1112  if(top_function_ids.find(HLS->functionId) != top_function_ids.end() && cg_man->ExistsAddressedFunction())
1113  {
1114  const auto addressed_functions = cg_man->GetAddressedFunctions();
1115  const auto constBitZero =
1116  SM->add_module_from_technology_library("constBitZero", CONSTANT_STD, LIBRARY_STD, circuit, TechM);
1117  const auto signBitZero =
1118  SM->add_sign("bitZero", circuit, circuit->find_member(CLOCK_PORT_NAME, port_o_K, circuit)->get_typeRef());
1119  SM->add_connection(signBitZero, constBitZero->find_member("out1", port_o_K, constBitZero));
1120 
1121  for(const auto& f_id : addressed_functions)
1122  {
1123  const auto FUName = functions::GetFUName(tree_helper::name_function(TreeM, f_id), HLSMgr);
1124  if(HLSMgr->Rfuns->is_a_proxied_function(FUName))
1125  {
1126  continue;
1127  }
1128 
1129  const auto FU = SM->add_module_from_technology_library(FUName + "_i0", FUName, WORK_LIBRARY, circuit, TechM);
1130  if(std::find(memory_modules.begin(), memory_modules.end(), FU) == memory_modules.end())
1131  {
1132  memory_modules.push_back(FU);
1133  }
1134 
1136  "---Considering additional top: " + FUName + "@" + STR(f_id));
1137  if(HLSMgr->Rfuns->has_proxied_shared_functions(f_id))
1138  {
1139  auto proxied_shared_functions = HLSMgr->Rfuns->get_proxied_shared_functions(f_id);
1140 #ifndef NDEBUG
1141  for(const auto& name : proxied_shared_functions)
1142  {
1143  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "--- proxy shared function: " + name);
1144  }
1145 #endif
1146  kill_proxy_function_units(wrapped_units, FU, fun_call_sites_rel, reverse_function_units);
1147  }
1148 
1149  SM->add_connection(FU->find_member(CLOCK_PORT_NAME, port_o_K, FU),
1150  circuit->find_member(CLOCK_PORT_NAME, port_o_K, circuit));
1151  SM->add_connection(FU->find_member(RESET_PORT_NAME, port_o_K, FU),
1152  circuit->find_member(RESET_PORT_NAME, port_o_K, circuit));
1153 
1154  const auto fu_start = FU->find_member(START_PORT_NAME, port_o_K, FU);
1155  if(fu_start)
1156  {
1157  SM->add_connection(fu_start, signBitZero);
1158  }
1159 
1160  for(const auto additional_parameter :
1161  HLSMgr->CGetFunctionBehavior(f_id)->CGetBehavioralHelper()->get_parameters())
1162  {
1163  const auto parameterName =
1164  HLSMgr->CGetFunctionBehavior(f_id)->CGetBehavioralHelper()->PrintVariable(additional_parameter);
1165 
1166  const auto parameterPort = FU->find_member(parameterName, port_o_K, FU);
1167  const auto constZeroParam = SM->add_module_from_technology_library(
1168  "zeroParam_" + FUName + "_" + parameterName, CONSTANT_STD, LIBRARY_STD, circuit, TechM);
1169  const auto constZeroOutPort = constZeroParam->find_member("out1", port_o_K, constZeroParam);
1170  const auto parameter_value =
1171  (static_cast<HDLWriter_Language>(parameters->getOption<unsigned int>(OPT_writer_language)) ==
1173  std::string("\"") + NumberToBinaryString(0, STD_GET_SIZE(parameterPort->get_typeRef())) +
1174  std::string("\"") :
1175  "0";
1176  constZeroParam->SetParameter("value", parameter_value);
1177 
1178  constZeroOutPort->type_resize(STD_GET_SIZE(parameterPort->get_typeRef()));
1179 
1180  const auto signBitZeroParam = SM->add_sign("signZeroParam_" + FUName + "_" + parameterName, SM->get_circ(),
1181  constZeroOutPort->get_typeRef());
1182 
1183  SM->add_connection(parameterPort, signBitZeroParam);
1184  SM->add_connection(constZeroOutPort, signBitZeroParam);
1185  }
1186  manage_module_ports(HLSMgr, HLS, SM, FU, 0);
1188  }
1189  }
1190  if(parameters->IsParameter("chained-memory-modules") && parameters->GetParameter<int>("chained-memory-modules") == 1)
1191  {
1192  manage_memory_ports_chained(SM, memory_modules, circuit);
1193  }
1194  else
1195  {
1196  manage_memory_ports_parallel_chained(HLSMgr, SM, memory_modules, circuit, HLS, unique_id);
1197  }
1198  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Managed memory ports");
1199 
1201  for(const auto& pmutbrb : proxy_memory_units_to_be_renamed_back)
1202  {
1203  const auto curr_gate = pmutbrb.first;
1204  THROW_ASSERT(curr_gate, "missing structural object");
1205  const auto var_name = "_" + STR(pmutbrb.second);
1206  for(const auto& pname :
1207  {"proxy_in1", "proxy_in2", "proxy_in2r", "proxy_in2w", "proxy_in3", "proxy_in3r", "proxy_in3w", "proxy_in4r",
1208  "proxy_in4w", "proxy_sel_LOAD", "proxy_sel_STORE", "proxy_out1"})
1209  {
1210  const auto port = curr_gate->find_member(pname + var_name, port_o_K, curr_gate);
1211  if(port)
1212  {
1213  port->set_id(pname);
1214  }
1215  }
1216  }
1217  HLS->Rfu->manage_killing_memory_proxies(mem_obj, reverse_memory_units, var_call_sites_rel, SM, HLS, unique_id);
1218  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Managed memory proxies");
1219 
1221  for(const auto& pfutbrb : proxy_function_units_to_be_renamed_back)
1222  {
1223  const auto& curr_gate = pfutbrb.first;
1224  THROW_ASSERT(curr_gate, "missing structural object");
1225  const auto fun_name = "_" + STR(pfutbrb.second);
1226  const auto inPortSize = GetPointerS<module>(curr_gate)->get_in_port_size();
1227  for(auto currentPort = 0U; currentPort < inPortSize; ++currentPort)
1228  {
1229  const auto curr_port = GetPointerS<module>(curr_gate)->get_in_port(currentPort);
1230  const auto port_name = curr_port->get_id();
1231  if(starts_with(port_name, PROXY_PREFIX))
1232  {
1233  const auto found = port_name.rfind(fun_name);
1234  if(found != std::string::npos)
1235  {
1236  const auto orig_port_name = port_name.substr(0, found);
1237  GetPointerS<port_o>(curr_port)->set_id(orig_port_name);
1238  }
1239  }
1240  }
1241  const auto outPortSize = GetPointerS<module>(curr_gate)->get_out_port_size();
1242  for(auto currentPort = 0U; currentPort < outPortSize; ++currentPort)
1243  {
1244  const auto curr_port = GetPointerS<module>(curr_gate)->get_out_port(currentPort);
1245  const auto port_name = curr_port->get_id();
1246  if(starts_with(port_name, PROXY_PREFIX))
1247  {
1248  const auto found = port_name.rfind(fun_name);
1249  if(found != std::string::npos)
1250  {
1251  const auto orig_port_name = port_name.substr(0, found);
1252  GetPointerS<port_o>(curr_port)->set_id(orig_port_name);
1253  }
1254  }
1255  }
1256  }
1257  HLS->Rfu->manage_killing_function_proxies(fun_obj, reverse_function_units, fun_call_sites_rel, SM, HLS, unique_id);
1258  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Added functional units to circuit");
1259 }
1260 
1262 #if HAVE_ASSERTS
1263  curr_gate
1264 #endif
1265 )
1266 {
1267 #if HAVE_ASSERTS
1268  const auto fu_module = GetPointer<module>(curr_gate);
1269  const auto np = fu_module->get_NP_functionality();
1270  if(np)
1271  {
1272  std::vector<std::string> param;
1273  np->get_library_parameters(param);
1274  for(const auto& p : param)
1275  {
1276  THROW_ASSERT(curr_gate->find_member(p, port_o_K, curr_gate) ||
1277  curr_gate->find_member(p, port_vector_o_K, curr_gate) || curr_gate->ExistsParameter(p),
1278  "parameter not yet specialized: " + p + " for module " + GET_TYPE_NAME(curr_gate));
1279  }
1280  }
1281 #endif
1282 }
1283 
1285  const structural_objectRef curr_gate, unsigned int num)
1286 {
1287  const auto circuit = SM->get_circ();
1288  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Routing module ports - " + circuit->get_path());
1290  bool added_memory_element = false;
1291  for(unsigned int j = 0; j < GetPointer<module>(curr_gate)->get_in_port_size(); j++)
1292  {
1293  const auto port_in = GetPointer<module>(curr_gate)->get_in_port(j);
1294  manage_extern_global_port(HLSMgr, HLS, SM, port_in, port_o::IN, circuit, num);
1295  if(GetPointer<port_o>(port_in)->get_is_memory())
1296  {
1297  added_memory_element = true;
1298  }
1299  }
1301  for(unsigned int j = 0; j < GetPointer<module>(curr_gate)->get_out_port_size(); j++)
1302  {
1303  structural_objectRef port_out = GetPointer<module>(curr_gate)->get_out_port(j);
1304  manage_extern_global_port(HLSMgr, HLS, SM, port_out, port_o::OUT, circuit, num);
1305  }
1307  for(unsigned int j = 0; j < GetPointer<module>(curr_gate)->get_in_out_port_size(); j++)
1308  {
1309  structural_objectRef port_in_out = GetPointer<module>(curr_gate)->get_in_out_port(j);
1310  manage_extern_global_port(HLSMgr, HLS, SM, port_in_out, port_o::IO, circuit, num);
1311  }
1313  return added_memory_element;
1314 }
1315 
1317  const std::list<structural_objectRef>& memory_modules,
1318  const structural_objectRef circuit)
1319 {
1320  std::map<std::string, structural_objectRef> from_ports;
1321  std::map<std::string, structural_objectRef> primary_outs;
1322  structural_objectRef cir_port;
1323  unsigned int sign_id = 0;
1324  for(const auto& memory_module : memory_modules)
1325  {
1326  for(unsigned int j = 0; j < GetPointer<module>(memory_module)->get_in_port_size(); j++)
1327  {
1328  structural_objectRef port_i = GetPointer<module>(memory_module)->get_in_port(j);
1329  if(GetPointer<port_o>(port_i)->get_is_memory() && (!GetPointer<port_o>(port_i)->get_is_global()) &&
1330  (!GetPointer<port_o>(port_i)->get_is_extern()))
1331  {
1332  std::string port_name = GetPointer<port_o>(port_i)->get_id();
1333  THROW_ASSERT(port_name.substr(1, 3) == "in_", "Expected the \"?in_\" prefix:" + port_name);
1334  std::string key = port_name.substr(0, 1) + port_name.substr(4);
1335  cir_port = circuit->find_member(port_name, port_i->get_kind(), circuit);
1336  THROW_ASSERT(!cir_port || GetPointer<port_o>(cir_port), "should be a port or null");
1337  if(!cir_port)
1338  {
1339  if(port_i->get_kind() == port_vector_o_K)
1340  {
1341  cir_port = SM->add_port_vector(port_name, port_o::IN, GetPointer<port_o>(port_i)->get_ports_size(),
1342  circuit, port_i->get_typeRef());
1343  }
1344  else
1345  {
1346  cir_port = SM->add_port(port_name, port_o::IN, circuit, port_i->get_typeRef());
1347  }
1348  port_o::fix_port_properties(port_i, cir_port);
1349  SM->add_connection(cir_port, port_i);
1350  }
1351  else
1352  {
1353  THROW_ASSERT(from_ports.find(key) != from_ports.end(),
1354  "somewhere the signal " + key + " should be produced");
1356  if(port_i->get_kind() == port_vector_o_K)
1357  {
1358  sign =
1359  SM->add_sign_vector(key + "_" + std::to_string(sign_id),
1360  GetPointer<port_o>(port_i)->get_ports_size(), circuit, port_i->get_typeRef());
1361  }
1362  else
1363  {
1364  sign = SM->add_sign(key + "_" + std::to_string(sign_id), circuit, port_i->get_typeRef());
1365  }
1366  ++sign_id;
1367  SM->add_connection(sign, port_i);
1368  SM->add_connection(sign, from_ports.find(key)->second);
1369  from_ports[key] = structural_objectRef();
1370  }
1371  }
1372  }
1373  for(unsigned int j = 0; j < GetPointer<module>(memory_module)->get_out_port_size(); j++)
1374  {
1375  structural_objectRef port_i = GetPointer<module>(memory_module)->get_out_port(j);
1376  if(GetPointer<port_o>(port_i)->get_is_memory() && (!GetPointer<port_o>(port_i)->get_is_global()) &&
1377  (!GetPointer<port_o>(port_i)->get_is_extern()))
1378  {
1379  std::string port_name = GetPointer<port_o>(port_i)->get_id();
1380  THROW_ASSERT(port_name.substr(1, 4) == "out_", "Expected the \"?out_\" prefix: " + port_name);
1381  std::string key = port_name.substr(0, 1) + port_name.substr(5);
1382  cir_port = circuit->find_member(port_name, port_i->get_kind(), circuit);
1383  THROW_ASSERT(!cir_port || GetPointer<port_o>(cir_port), "should be a port or null");
1384  if(!cir_port)
1385  {
1386  if(port_i->get_kind() == port_vector_o_K)
1387  {
1388  cir_port = SM->add_port_vector(port_name, port_o::OUT, GetPointer<port_o>(port_i)->get_ports_size(),
1389  circuit, port_i->get_typeRef());
1390  }
1391  else
1392  {
1393  cir_port = SM->add_port(port_name, port_o::OUT, circuit, port_i->get_typeRef());
1394  }
1395  port_o::fix_port_properties(port_i, cir_port);
1396  primary_outs[port_name] = cir_port;
1397  }
1398  from_ports[key] = port_i;
1399  }
1400  }
1401  }
1402  auto po_end = primary_outs.end();
1403  for(auto po = primary_outs.begin(); po != po_end; ++po)
1404  {
1405  THROW_ASSERT(from_ports.find(po->first.substr(0, 1) + po->first.substr(5)) != from_ports.end(),
1406  "Port source not present");
1407  SM->add_connection(po->second, from_ports.find(po->first.substr(0, 1) + po->first.substr(5))->second);
1408  }
1409 }
1410 
1412  const structural_managerRef SM, const hlsRef HLS,
1413  std::map<structural_objectRef, std::list<structural_objectRef>, jms_sorter>& primary_outs,
1414  const structural_objectRef circuit, unsigned int& _unique_id)
1415 {
1416  static const auto js_name = "join_signal";
1417  static const auto ss_name = "split_signal";
1418  static const auto bus_merger_res_name = "bus_merger";
1419  const auto js_library = HLS->HLS_D->get_technology_manager()->get_library(js_name);
1420  const auto ss_library = HLS->HLS_D->get_technology_manager()->get_library(ss_name);
1421  const auto bm_library = HLS->HLS_D->get_technology_manager()->get_library(bus_merger_res_name);
1422 
1423  for(const auto& po : primary_outs)
1424  {
1425  const auto& bus_port = po.first;
1426  const auto is_vector_bus = bus_port->get_kind() == port_vector_o_K;
1427  const auto& merged_ports = po.second;
1428  const auto bus_merger_inst_name = bus_merger_res_name + bus_port->get_id() + STR(_unique_id++) + "_";
1430 
1431  if(merged_ports.size() == 1U)
1432  {
1433  out_port = merged_ports.front();
1434  THROW_ASSERT(out_port->get_kind() == bus_port->get_kind(), "Out port has type " + bus_port->get_kind_text() +
1435  " while internal port has type " +
1436  out_port->get_kind_text());
1437  }
1438  else
1439  {
1440  const auto bus_merger_mod = SM->add_module_from_technology_library(
1441  bus_merger_inst_name, bus_merger_res_name, bm_library, circuit, HLS->HLS_D->get_technology_manager());
1442  const auto bm_in_port = GetPointerS<module>(bus_merger_mod)->get_in_port(0U);
1443  GetPointerS<port_o>(bm_in_port)->add_n_ports(static_cast<unsigned int>(merged_ports.size()), bm_in_port);
1444  if(is_vector_bus)
1445  {
1446  port_o::resize_std_port(GetPointerS<port_o>(bus_port)->get_ports_size() *
1447  STD_GET_SIZE(bus_port->get_typeRef()),
1448  0U, DEBUG_LEVEL_NONE, bm_in_port);
1449  }
1450  else
1451  {
1452  port_o::resize_std_port(STD_GET_SIZE(bus_port->get_typeRef()), 0U, DEBUG_LEVEL_NONE, bm_in_port);
1453  }
1454  auto in_id = 0U;
1455  for(const auto& merged_port : merged_ports)
1456  {
1457  if(is_vector_bus)
1458  {
1459  const auto sign_v_in = SM->add_sign_vector("sig_in_vector_" + bus_merger_inst_name + STR(in_id),
1460  GetPointerS<port_o>(merged_port)->get_ports_size(), circuit,
1461  merged_port->get_typeRef());
1462  const auto js_mod =
1463  SM->add_module_from_technology_library(js_name + bus_merger_inst_name + STR(in_id), js_name,
1464  js_library, circuit, HLS->HLS_D->get_technology_manager());
1465  const auto js_in_port = GetPointerS<module>(js_mod)->get_in_port(0U);
1466  GetPointerS<port_o>(js_in_port)
1467  ->add_n_ports(static_cast<unsigned int>(GetPointerS<port_o>(merged_port)->get_ports_size()),
1468  js_in_port);
1469  port_o::resize_std_port(STD_GET_SIZE((merged_port)->get_typeRef()), 0U, DEBUG_LEVEL_NONE, js_in_port);
1470  SM->add_connection(sign_v_in, merged_port);
1471  SM->add_connection(sign_v_in, js_in_port);
1472  const auto js_out_port = GetPointerS<module>(js_mod)->get_out_port(0U);
1473  port_o::resize_std_port(GetPointerS<port_o>(bus_port)->get_ports_size() *
1474  STD_GET_SIZE(bus_port->get_typeRef()),
1475  0U, DEBUG_LEVEL_NONE, js_out_port);
1477  bus_port->get_typeRef()->copy(sig_type);
1478  const auto sign_in = SM->add_sign("sig_in_" + bus_merger_inst_name + STR(in_id), circuit, sig_type);
1479  if(sig_type->type == structural_type_descriptor::BOOL)
1480  {
1482  sign_in->type_resize(1U, GetPointerS<port_o>(bus_port)->get_ports_size() *
1483  STD_GET_SIZE(bus_port->get_typeRef()));
1484  }
1485  else
1486  {
1487  sign_in->type_resize(GetPointer<port_o>(bus_port)->get_ports_size() *
1488  STD_GET_SIZE(bus_port->get_typeRef()));
1489  }
1490  SM->add_connection(sign_in, js_out_port);
1491  SM->add_connection(sign_in, GetPointer<port_o>(bm_in_port)->get_port(in_id));
1492  }
1493  else
1494  {
1495  const auto sign_in =
1496  SM->add_sign("sig_in_" + bus_merger_inst_name + STR(in_id), circuit, bus_port->get_typeRef());
1497  SM->add_connection(sign_in, merged_port);
1498  SM->add_connection(sign_in, GetPointerS<port_o>(bm_in_port)->get_port(in_id));
1499  }
1500  in_id += 1U;
1501  }
1502  out_port = GetPointerS<module>(bus_merger_mod)->get_out_port(0);
1503  if(is_vector_bus)
1504  {
1505  port_o::resize_std_port(GetPointerS<port_o>(bus_port)->get_ports_size() *
1506  STD_GET_SIZE(bus_port->get_typeRef()),
1507  0U, DEBUG_LEVEL_NONE, out_port);
1508  }
1509  else
1510  {
1511  port_o::resize_std_port(STD_GET_SIZE(bus_port->get_typeRef()), 0U, DEBUG_LEVEL_NONE, out_port);
1512  }
1513  if(is_vector_bus)
1514  {
1515  const auto ss_mod = SM->add_module_from_technology_library(
1516  ss_name + bus_merger_inst_name, ss_name, ss_library, circuit, HLS->HLS_D->get_technology_manager());
1518  bus_port->get_typeRef()->copy(sig_type);
1519  const auto sign_out = SM->add_sign("sig_out_" + bus_merger_inst_name, circuit, sig_type);
1520  if(sig_type->type == structural_type_descriptor::BOOL)
1521  {
1523  sign_out->type_resize(1, GetPointer<port_o>(bus_port)->get_ports_size() *
1524  STD_GET_SIZE(bus_port->get_typeRef()));
1525  }
1526  else
1527  {
1528  sign_out->type_resize(GetPointer<port_o>(bus_port)->get_ports_size() *
1529  STD_GET_SIZE(bus_port->get_typeRef()));
1530  }
1531  const auto ss_in_port = GetPointerS<module>(ss_mod)->get_in_port(0U);
1532  port_o::resize_std_port(GetPointer<port_o>(bus_port)->get_ports_size() *
1533  STD_GET_SIZE(bus_port->get_typeRef()),
1534  0U, DEBUG_LEVEL_NONE, ss_in_port);
1535  SM->add_connection(sign_out, out_port);
1536  SM->add_connection(sign_out, ss_in_port);
1537  out_port = GetPointerS<module>(ss_mod)->get_out_port(0U);
1538  GetPointerS<port_o>(out_port)->add_n_ports(
1539  static_cast<unsigned int>(GetPointerS<port_o>(bus_port)->get_ports_size()), out_port);
1540  port_o::resize_std_port(STD_GET_SIZE(bus_port->get_typeRef()), 0U, DEBUG_LEVEL_NONE, out_port);
1541  }
1542  }
1543  THROW_ASSERT(out_port, "");
1544  if(is_vector_bus)
1545  {
1546  if(bus_port->get_owner() != circuit)
1547  {
1549  if(is_vector_bus)
1550  {
1551  sig = SM->add_sign_vector("sig_out_vector_" + bus_merger_inst_name,
1552  GetPointerS<port_o>(bus_port)->get_ports_size(), circuit,
1553  bus_port->get_typeRef());
1554  }
1555  else
1556  {
1557  sig = SM->add_sign("sig_out_" + bus_merger_inst_name, circuit, out_port->get_typeRef());
1558  }
1559  SM->add_connection(sig, out_port);
1560  SM->add_connection(sig, bus_port);
1561  }
1562  else
1563  {
1564  SM->add_connection(out_port, bus_port);
1565  }
1566  }
1567  else
1568  {
1570  out_port->get_typeRef()->copy(sig_type);
1571  const auto sign_out = SM->add_sign("sig_out_" + bus_merger_inst_name, circuit, sig_type);
1572  sign_out->type_resize(STD_GET_SIZE(bus_port->get_typeRef()));
1573  SM->add_connection(sign_out, out_port);
1574  SM->add_connection(sign_out, bus_port);
1575  }
1576  }
1577 }
1578 
1580 {
1581  return a->get_path() < b->get_path();
1582 }
1583 
1585  const std::list<structural_objectRef>& memory_modules,
1586  const structural_objectRef circuit, const hlsRef HLS,
1587  unsigned int& _unique_id)
1588 {
1589  std::map<structural_objectRef, std::list<structural_objectRef>, jms_sorter> primary_outs;
1590  structural_objectRef cir_port;
1591  const auto vector_to_port = [](structural_objectRef& a, structural_objectRef& b) {
1592  if(a->get_kind() != b->get_kind())
1593  {
1594  if(a->get_kind() == port_vector_o_K)
1595  {
1596  THROW_ASSERT(b->get_kind() == port_o_K, "");
1597  const auto port_v = GetPointerS<const port_o>(a);
1598  THROW_ASSERT(port_v->get_ports_size() == 1U,
1599  "Multiple ports: " + STR(port_v->get_ports_size()) + " in " + port_v->get_path());
1600  a = port_v->get_port(0U);
1601  }
1602  else if(b->get_kind() == port_vector_o_K)
1603  {
1604  THROW_ASSERT(a->get_kind() == port_o_K, "");
1605  const auto port_v = GetPointerS<const port_o>(b);
1606  THROW_ASSERT(port_v->get_ports_size() == 1U,
1607  "Multiple ports: " + STR(port_v->get_ports_size()) + " in " + port_v->get_path());
1608  b = port_v->get_port(0U);
1609  }
1610  }
1611  };
1612  for(const auto& memory_module : memory_modules)
1613  {
1614  for(unsigned int j = 0; j < GetPointer<module>(memory_module)->get_in_port_size(); ++j)
1615  {
1616  structural_objectRef port_i = GetPointer<module>(memory_module)->get_in_port(j);
1617  if(GetPointer<port_o>(port_i)->get_is_memory() && (!GetPointer<port_o>(port_i)->get_is_global()) &&
1618  (!GetPointer<port_o>(port_i)->get_is_extern()))
1619  {
1620  std::string port_name = GetPointer<port_o>(port_i)->get_id();
1621  cir_port = circuit->find_member(port_name, port_i->get_kind(), circuit);
1622  THROW_ASSERT(!cir_port || GetPointer<port_o>(cir_port), "should be a port or null");
1623  if(!cir_port)
1624  {
1625  if(port_i->get_kind() == port_vector_o_K)
1626  {
1627  cir_port = SM->add_port_vector(port_name, port_o::IN, GetPointer<port_o>(port_i)->get_ports_size(),
1628  circuit, port_i->get_typeRef());
1629  }
1630  else
1631  {
1632  cir_port = SM->add_port(port_name, port_o::IN, circuit, port_i->get_typeRef());
1633  }
1634  port_o::fix_port_properties(port_i, cir_port);
1635  SM->add_connection(cir_port, port_i);
1636  }
1637  else
1638  {
1640  port_i->get_path() + " <-> " + cir_port->get_path());
1641  vector_to_port(port_i, cir_port);
1642  THROW_ASSERT(port_i->get_kind() == cir_port->get_kind(),
1643  "unexpected condition: " + port_i->get_path() + "(" + port_i->get_kind_text() +
1644  ") != " + cir_port->get_path() + "(" + cir_port->get_kind_text() + ")");
1645  if(port_i->get_kind() == port_vector_o_K &&
1646  GetPointerS<port_o>(port_i)->get_ports_size() > GetPointerS<port_o>(cir_port)->get_ports_size())
1647  {
1648  const auto n_ports =
1649  GetPointerS<port_o>(port_i)->get_ports_size() - GetPointerS<port_o>(cir_port)->get_ports_size();
1650  GetPointerS<port_o>(cir_port)->add_n_ports(n_ports, cir_port);
1651  }
1652  SM->add_connection(cir_port, port_i);
1653  }
1654  }
1655  }
1656 
1657  for(unsigned int j = 0; j < GetPointer<module>(memory_module)->get_out_port_size(); j++)
1658  {
1659  structural_objectRef port_i = GetPointer<module>(memory_module)->get_out_port(j);
1660  if(GetPointer<port_o>(port_i)->get_is_memory() && (!GetPointer<port_o>(port_i)->get_is_global()) &&
1661  (!GetPointer<port_o>(port_i)->get_is_extern()))
1662  {
1663  const auto port_name = GetPointerS<port_o>(port_i)->get_id();
1664  cir_port = circuit->find_member(port_name, port_i->get_kind(), circuit);
1665  THROW_ASSERT(!cir_port || GetPointer<port_o>(cir_port), "should be a port or null");
1666  if(!cir_port)
1667  {
1668  if(port_i->get_kind() == port_vector_o_K)
1669  {
1670  cir_port = SM->add_port_vector(port_name, port_o::OUT, GetPointerS<port_o>(port_i)->get_ports_size(),
1671  circuit, port_i->get_typeRef());
1672  }
1673  else
1674  {
1675  cir_port = SM->add_port(port_name, port_o::OUT, circuit, port_i->get_typeRef());
1676  }
1677  port_o::fix_port_properties(port_i, cir_port);
1678  }
1679  else
1680  {
1682  port_i->get_path() + " <-> " + cir_port->get_path());
1683  vector_to_port(port_i, cir_port);
1684  THROW_ASSERT(port_i->get_kind() == cir_port->get_kind(),
1685  "unexpected condition: " + port_i->get_path() + "(" + port_i->get_kind_text() +
1686  ") != " + cir_port->get_path() + "(" + cir_port->get_kind_text() + ")");
1687  if(port_i->get_kind() == port_vector_o_K &&
1688  GetPointerS<port_o>(port_i)->get_ports_size() > GetPointerS<port_o>(cir_port)->get_ports_size())
1689  {
1690  auto n_ports =
1691  GetPointerS<port_o>(port_i)->get_ports_size() - GetPointerS<port_o>(cir_port)->get_ports_size();
1692  GetPointerS<port_o>(cir_port)->add_n_ports(n_ports, cir_port);
1693  }
1694  }
1695  if(std::find(primary_outs[cir_port].begin(), primary_outs[cir_port].end(), port_i) ==
1696  primary_outs[cir_port].end())
1697  {
1698  primary_outs[cir_port].push_back(port_i);
1699  }
1700  }
1701  }
1702  }
1703  join_merge_split(SM, HLS, primary_outs, circuit, _unique_id);
1704 }
1705 
1707  const structural_managerRef SM, structural_objectRef port_in,
1708  unsigned int _dir, structural_objectRef circuit, unsigned int num)
1709 {
1710  auto dir = static_cast<port_o::port_direction>(_dir);
1711  const auto inPort = GetPointer<port_o>(port_in);
1712  const auto port_name = inPort->get_id();
1713  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Port: " + inPort->get_path());
1714  structural_objectRef ext_port = circuit->find_member(port_name, port_in->get_kind(), circuit);
1715  if(inPort->get_is_extern())
1716  {
1717  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Manage extern port");
1718  if(inPort->get_is_global())
1719  {
1720  THROW_ASSERT(!ext_port || GetPointer<port_o>(ext_port), "should be a port or null");
1721  if(ext_port && GetPointerS<port_o>(ext_port)->get_port_direction() != dir)
1722  {
1723  THROW_ASSERT(port_in->get_kind() == ext_port->get_kind(), "unexpected condition");
1724  if(port_in->get_kind() == port_vector_o_K &&
1725  inPort->get_ports_size() > GetPointerS<port_o>(ext_port)->get_ports_size())
1726  {
1727  const auto n_ports = inPort->get_ports_size() - GetPointerS<port_o>(ext_port)->get_ports_size();
1728  GetPointerS<port_o>(ext_port)->add_n_ports(n_ports, ext_port);
1729  }
1730  SM->change_port_direction(ext_port, dir, circuit);
1731  if(STD_GET_SIZE(ext_port->get_typeRef()) < STD_GET_SIZE(port_in->get_typeRef()))
1732  {
1733  port_o::resize_std_port(STD_GET_SIZE(port_in->get_typeRef()), 0, 0, ext_port);
1734  }
1735  }
1736  else if(!ext_port)
1737  {
1738  if(port_in->get_kind() == port_vector_o_K)
1739  {
1740  ext_port =
1741  SM->add_port_vector(port_name, dir, inPort->get_ports_size(), circuit, port_in->get_typeRef());
1742  }
1743  else
1744  {
1745  ext_port = SM->add_port(port_name, dir, circuit, port_in->get_typeRef());
1746  }
1747  }
1748  else
1749  {
1750  THROW_ASSERT(port_in->get_kind() == ext_port->get_kind(), "unexpected condition");
1751  if(port_in->get_kind() == port_vector_o_K &&
1752  inPort->get_ports_size() > GetPointerS<port_o>(ext_port)->get_ports_size())
1753  {
1754  const auto n_ports = inPort->get_ports_size() - GetPointerS<port_o>(ext_port)->get_ports_size();
1755  GetPointer<port_o>(ext_port)->add_n_ports(n_ports, ext_port);
1756  }
1757  }
1758  }
1759  else
1760  {
1761  if(port_in->get_kind() == port_vector_o_K)
1762  {
1763  ext_port = SM->add_port_vector("ext_" + inPort->get_id() + "_" + std::to_string(num), dir,
1764  inPort->get_ports_size(), circuit, port_in->get_typeRef());
1765  }
1766  else
1767  {
1768  ext_port = SM->add_port("ext_" + inPort->get_id() + "_" + std::to_string(num), dir, circuit,
1769  port_in->get_typeRef());
1770  }
1771  }
1772  }
1773  else if(inPort->get_is_global())
1774  {
1775  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Manage global port");
1776  THROW_ASSERT(!ext_port || GetPointer<port_o>(ext_port), "should be a port or null");
1777  if(!ext_port)
1778  {
1779  if(port_in->get_kind() == port_vector_o_K)
1780  {
1781  ext_port = SM->add_port_vector(port_name, dir, inPort->get_ports_size(), circuit, port_in->get_typeRef());
1782  }
1783  else
1784  {
1785  ext_port = SM->add_port(port_name, dir, circuit, port_in->get_typeRef());
1786  }
1787  }
1788  }
1789  else if(inPort->get_port_interface() != port_o::port_interface::PI_DEFAULT)
1790  {
1791  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Manage interface port");
1792  const auto fsymbol =
1793  HLSMgr->CGetFunctionBehavior(HLS->functionId)->CGetBehavioralHelper()->GetMangledFunctionName();
1794  const auto func_arch = HLSMgr->module_arch->GetArchitecture(fsymbol);
1795  const auto is_dataflow_top =
1796  func_arch && func_arch->attrs.find(FunctionArchitecture::func_dataflow) != func_arch->attrs.end() &&
1797  func_arch->attrs.find(FunctionArchitecture::func_dataflow)->second == "top";
1798  if(is_dataflow_top && starts_with(port_name, "_DF_bambu"))
1799  {
1800  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Stop interface propagation at dataflow top module");
1801  return;
1802  }
1803  THROW_ASSERT(!ext_port || GetPointer<port_o>(ext_port), "should be a port or null");
1804  if(ext_port && GetPointer<port_o>(ext_port)->get_port_direction() != dir)
1805  {
1806  SM->change_port_direction(ext_port, dir, circuit);
1807  if(STD_GET_SIZE(ext_port->get_typeRef()) < STD_GET_SIZE(port_in->get_typeRef()))
1808  {
1809  port_o::resize_std_port(STD_GET_SIZE(port_in->get_typeRef()), 0, 0, ext_port);
1810  }
1811  }
1812  else if(!ext_port)
1813  {
1814  if(port_in->get_kind() == port_vector_o_K)
1815  {
1816  ext_port = SM->add_port_vector(port_name, dir, inPort->get_ports_size(), circuit, port_in->get_typeRef());
1817  }
1818  else
1819  {
1820  ext_port = SM->add_port(port_name, dir, circuit, port_in->get_typeRef());
1821  }
1822  }
1823  }
1824  else
1825  {
1826  ext_port = nullptr;
1827  }
1828  if(ext_port)
1829  {
1830  port_o::fix_port_properties(port_in, ext_port);
1831  SM->add_connection(port_in, ext_port);
1832  }
1833 }
1834 
1837  unsigned int fu, const OpVertexSet& mapped_operations, unsigned int ar)
1838 {
1839  const auto FB = HLSMgr->CGetFunctionBehavior(HLS->functionId);
1840  const auto memory_allocation_policy = FB->GetMemoryAllocationPolicy();
1841  auto bus_data_bitsize = HLSMgr->Rmem->get_bus_data_bitsize();
1842  auto bus_size_bitsize = HLSMgr->Rmem->get_bus_size_bitsize();
1843  const auto bus_addr_bitsize = HLSMgr->get_address_bitsize();
1844  const auto bus_tag_bitsize =
1845  HLS->Param->isOption(OPT_context_switch) ? GetPointer<memory_cs>(HLSMgr->Rmem)->get_bus_tag_bitsize() : 0;
1846  auto* fu_module = GetPointer<module>(fu_obj);
1847  const auto fu_tech_obj = allocation_information->get_fu(fu);
1849  "-->Specializing " + fu_obj->get_path() + " of type " + GET_TYPE_NAME(fu_obj));
1850  std::map<unsigned int, unsigned long long> required_variables;
1851  std::map<unsigned int, unsigned long long> num_elements;
1852  unsigned long long n_out_elements = 0;
1853  unsigned long long produced_variables = 1;
1854  const auto is_multiport = allocation_information->get_number_channels(fu) > 1U;
1855  const auto max_n_ports = is_multiport ? allocation_information->get_number_channels(fu) : 0U;
1856 
1857  if(ar)
1858  {
1859  bool has_misaligned_indirect_ref = false;
1861  {
1862  const auto type_node = tree_helper::CGetType(TreeM->CGetTreeReindex(ar));
1863  const auto elmt_bitsize = tree_helper::AccessedMaximumBitsize(type_node, 1);
1864 
1866  {
1867  required_variables[0] = elmt_bitsize;
1868  if(HLSMgr->Rmem->is_private_memory(ar))
1869  {
1870  bus_data_bitsize = std::max(bus_data_bitsize, elmt_bitsize);
1871  }
1872  required_variables[1] = bus_addr_bitsize;
1873  if(HLSMgr->Rmem->is_private_memory(ar))
1874  {
1875  for(; elmt_bitsize >= (1u << bus_size_bitsize); ++bus_size_bitsize)
1876  {
1877  }
1878  }
1879  required_variables[2] = bus_size_bitsize;
1880  produced_variables = elmt_bitsize;
1881  }
1882  else
1883  {
1884  THROW_ERROR("Unit currently not supported: " + allocation_information->get_fu_name(fu).first);
1885  }
1886  const OpGraphConstRef data = FB->CGetOpGraph(FunctionBehavior::CFG);
1887  for(const auto& mapped_operation : mapped_operations)
1888  {
1890  " on BRAM = " + data->CGetOpNodeInfo(mapped_operation)->GetOperation() + " " +
1891  GET_NAME(data, mapped_operation));
1892  const auto vars = HLSMgr->get_required_values(HLS->functionId, mapped_operation);
1893  const auto out_var = HLSMgr->get_produced_value(HLS->functionId, mapped_operation);
1894  if(GET_TYPE(data, mapped_operation) & TYPE_STORE)
1895  {
1896  THROW_ASSERT(std::get<0>(vars[0]), "Expected a tree node in case of a value to store");
1897  required_variables[0] =
1898  std::max(required_variables[0],
1899  tree_helper::Size(tree_helper::CGetType(TreeM->CGetTreeReindex(std::get<0>(vars[0])))));
1900  if(tree_helper::is_a_misaligned_vector(TreeM, std::get<0>(vars[0])))
1901  {
1902  has_misaligned_indirect_ref = true;
1903  }
1904  }
1905  else if(GET_TYPE(data, mapped_operation) & TYPE_LOAD)
1906  {
1907  THROW_ASSERT(out_var, "Expected a tree node in case of a value to load");
1908  produced_variables = std::max(produced_variables,
1909  tree_helper::Size(tree_helper::CGetType(TreeM->CGetTreeReindex(out_var))));
1911  {
1912  has_misaligned_indirect_ref = true;
1913  }
1914  }
1915  }
1916  }
1917  if(fu_module->ExistsParameter("BRAM_BITSIZE"))
1918  {
1919  auto bram_bitsize = HLSMgr->Rmem->get_bram_bitsize();
1920  if(HLSMgr->Rmem->is_private_memory(ar))
1921  {
1922  auto accessed_bitsize = std::max(required_variables[0], produced_variables);
1923  accessed_bitsize = ceil_pow2(accessed_bitsize);
1924  bram_bitsize = has_misaligned_indirect_ref ? std::max(bram_bitsize, accessed_bitsize) :
1925  std::max(bram_bitsize, accessed_bitsize / 2);
1926  if(bram_bitsize > HLSMgr->Rmem->get_maxbram_bitsize())
1927  {
1928  THROW_ERROR("incorrect operation mapping on memory module");
1929  }
1930  }
1931  fu_module->SetParameter("BRAM_BITSIZE", STR(bram_bitsize));
1932  }
1933  if(fu_module->ExistsParameter("BUS_PIPELINED"))
1934  {
1935  const auto has_extern_mem =
1936  ((HLSMgr->Rmem->get_memory_address() - HLSMgr->base_address) > 0 &&
1937  memory_allocation_policy != MemoryAllocation_Policy::EXT_PIPELINED_BRAM) ||
1938  (HLSMgr->Rmem->has_unknown_addresses() && memory_allocation_policy != MemoryAllocation_Policy::ALL_BRAM &&
1939  memory_allocation_policy != MemoryAllocation_Policy::EXT_PIPELINED_BRAM);
1940  fu_module->SetParameter("BUS_PIPELINED", has_extern_mem ? "0" : "1");
1941  }
1942  }
1943  else
1944  {
1945  const auto data = FB->CGetOpGraph(FunctionBehavior::CFG);
1946 
1947  for(const auto& mapped_operation : mapped_operations)
1948  {
1949  const auto vars = HLSMgr->get_required_values(HLS->functionId, mapped_operation);
1951  "---Considering operation " +
1952  HLSMgr->get_tree_manager()
1953  ->get_tree_node_const(data->CGetOpNodeInfo(mapped_operation)->GetNodeId())
1954  ->ToString());
1955  const auto out_var = HLSMgr->get_produced_value(HLS->functionId, mapped_operation);
1956  const auto fun_unit = GetPointerS<functional_unit>(fu_tech_obj);
1957  const auto& memory_ctrl_type = fun_unit->memory_ctrl_type;
1958 
1959  if(memory_ctrl_type != "")
1960  {
1961  unsigned long long mem_var_size_in = 1;
1962  unsigned long long mem_var_size_out = 1;
1963 
1964  if(GET_TYPE(data, mapped_operation) & TYPE_STORE)
1965  {
1966  THROW_ASSERT(std::get<0>(vars[0]), "Expected a tree node in case of a value to store");
1967  mem_var_size_in =
1968  std::max(mem_var_size_in,
1969  tree_helper::Size(tree_helper::CGetType(TreeM->CGetTreeReindex(std::get<0>(vars[0])))));
1970  }
1971  else if(GET_TYPE(data, mapped_operation) & TYPE_LOAD)
1972  {
1973  THROW_ASSERT(out_var, "Expected a tree node in case of a value to load");
1974  mem_var_size_out = std::max(mem_var_size_out,
1975  tree_helper::Size(tree_helper::CGetType(TreeM->CGetTreeReindex(out_var))));
1976  }
1978  required_variables.insert(std::make_pair(0, 0));
1979  required_variables[0] = std::max(required_variables[0], mem_var_size_in);
1980  required_variables[1] = bus_addr_bitsize;
1982  {
1983  bus_data_bitsize = std::max(bus_data_bitsize, std::max(mem_var_size_in, mem_var_size_out));
1984  for(; bus_data_bitsize >= (1u << bus_size_bitsize); ++bus_size_bitsize)
1985  {
1986  ;
1987  }
1988  }
1989  required_variables[2] = bus_size_bitsize;
1990  produced_variables = std::max(produced_variables, mem_var_size_out);
1991  }
1992  else if(HLS->HLS_D->get_technology_manager()->get_library(allocation_information->get_fu_name(fu).first) !=
1993  WORK_LIBRARY &&
1994  HLS->HLS_D->get_technology_manager()->get_library(allocation_information->get_fu_name(fu).first) !=
1995  PROXY_LIBRARY) // functions just synthesized shouldn't be customized
1996  {
1997  const auto np = fu_module->get_NP_functionality();
1998  const auto is_flopoco = np && np->exist_NP_functionality(NP_functionality::FLOPOCO_PROVIDED);
1999  const auto op_name = data->CGetOpNodeInfo(mapped_operation)->GetOperation();
2000  const auto is_float_expr = op_name.find(FLOAT_EXPR) != std::string::npos;
2001  for(auto i = 0U; i < vars.size(); ++i)
2002  {
2003  const auto& tree_var = std::get<0>(vars[i]);
2004  if(tree_var == 0)
2005  {
2006  continue;
2007  }
2008  required_variables.insert(std::make_pair(i, 0));
2009  const auto var_node = TreeM->CGetTreeReindex(tree_var);
2010  if(tree_helper::IsVectorType(var_node))
2011  {
2012  const auto type = tree_helper::CGetType(var_node);
2013  const auto size = tree_helper::Size(type);
2014  const auto element_type = tree_helper::CGetElements(type);
2015  const auto element_size = tree_helper::Size(element_type);
2016  required_variables[i] = std::max(required_variables[i], element_size);
2017 
2018  if(num_elements.find(i) == num_elements.end())
2019  {
2020  num_elements[i] = size / element_size;
2021  }
2022  else
2023  {
2024  THROW_ASSERT(num_elements.find(i)->second == size / element_size,
2025  "Performed a wrong module allocation");
2026  }
2027  }
2028  else
2029  {
2030  auto bitsize = tree_helper::Size(var_node);
2031  if(is_float_expr && is_flopoco)
2032  {
2033  if(bitsize < 32)
2034  {
2035  bitsize = 32;
2036  }
2037  else if(bitsize > 32 && bitsize < 64)
2038  {
2039  bitsize = 64;
2040  }
2041  }
2042  required_variables[i] = std::max(required_variables[i], bitsize);
2043  }
2044  }
2045  if(np)
2046  {
2047  std::vector<std::string> param;
2048  np->get_library_parameters(param);
2049  auto it_end = param.end();
2050  for(auto it = param.begin(); it != it_end; ++it)
2051  {
2052  if(*it == "LSB_PARAMETER" && op_name == "pointer_plus_expr")
2053  {
2054  unsigned int curr_LSB = 0;
2055  auto op0_tree_var = std::get<0>(vars[0]);
2056  if(op0_tree_var)
2057  {
2058  const auto var = tree_helper::GetBaseVariable(TreeM->CGetTreeReindex(op0_tree_var));
2059  if(var && FB->is_variable_mem(GET_INDEX_CONST_NODE(var)) &&
2060  HLSMgr->Rmem->is_sds_var(GET_INDEX_CONST_NODE(var)))
2061  {
2062  const auto type = tree_helper::CGetType(var);
2063  const auto value_bitsize = tree_helper::AccessedMaximumBitsize(type, 1);
2064  if(value_bitsize <= 8)
2065  {
2066  curr_LSB = 0;
2067  }
2068  else if(value_bitsize == 16)
2069  {
2070  curr_LSB = 1;
2071  }
2072  else if(value_bitsize == 32)
2073  {
2074  curr_LSB = 2;
2075  }
2076  else if(value_bitsize == 64)
2077  {
2078  curr_LSB = 3;
2079  }
2080  else if(value_bitsize == 128)
2081  {
2082  curr_LSB = 4;
2083  }
2084  else if(value_bitsize == 256)
2085  {
2086  curr_LSB = 5;
2087  }
2088  else
2089  {
2090  curr_LSB = 0;
2091  }
2092  }
2093  }
2094  auto op0 = TreeM->get_tree_node_const(op0_tree_var);
2095  auto op1 = TreeM->get_tree_node_const(std::get<0>(vars[1]));
2096  if(op0->get_kind() == ssa_name_K)
2097  {
2098  auto ssa_var0 = GetPointer<ssa_name>(op0);
2099  if(!ssa_var0->bit_values.empty())
2100  {
2101  auto tailZeros = 0u;
2102  const auto lengthBV = ssa_var0->bit_values.size();
2103  const auto& currBit = ssa_var0->bit_values.at(lengthBV - 1 - tailZeros);
2104  while(lengthBV > tailZeros && (currBit == '0' || currBit == 'X'))
2105  {
2106  ++tailZeros;
2107  }
2108  if(tailZeros < curr_LSB)
2109  {
2110  curr_LSB = tailZeros;
2111  }
2112  }
2113  else
2114  {
2115  curr_LSB = 0;
2116  }
2117  }
2118  else
2119  {
2120  curr_LSB = 0;
2121  }
2122  if(op1->get_kind() == ssa_name_K)
2123  {
2124  auto ssa_var1 = GetPointer<ssa_name>(op1);
2125  if(!ssa_var1->bit_values.empty())
2126  {
2127  auto tailZeros = 0u;
2128  const auto lengthBV = ssa_var1->bit_values.size();
2129  const auto& currBit = ssa_var1->bit_values.at(lengthBV - 1 - tailZeros);
2130  while(lengthBV > tailZeros && (currBit == '0' || currBit == 'X'))
2131  {
2132  ++tailZeros;
2133  }
2134  if(tailZeros < curr_LSB)
2135  {
2136  curr_LSB = tailZeros;
2137  }
2138  }
2139  else
2140  {
2141  curr_LSB = 0;
2142  }
2143  }
2144  else if(op1->get_kind() == integer_cst_K)
2145  {
2146  const auto offset_value = tree_helper::GetConstValue(op1);
2147  if(offset_value)
2148  {
2149  auto tailZeros = 0u;
2150  while((offset_value & (integer_cst_t(1) << tailZeros)) == 0)
2151  {
2152  ++tailZeros;
2153  }
2154  if(tailZeros < curr_LSB)
2155  {
2156  curr_LSB = tailZeros;
2157  }
2158  }
2159  }
2160  else
2161  {
2162  curr_LSB = 0;
2163  }
2164  if(fu_module->ExistsParameter("LSB_PARAMETER"))
2165  {
2166  int lsb_parameter = std::stoi(fu_module->GetParameter("LSB_PARAMETER"));
2167  if(lsb_parameter < 0)
2168  {
2169  lsb_parameter = static_cast<int>(curr_LSB);
2170  }
2171  else
2172  {
2173  lsb_parameter = std::min(lsb_parameter, static_cast<int>(curr_LSB));
2174  }
2175  fu_module->SetParameter("LSB_PARAMETER", STR(lsb_parameter));
2176  }
2177  else
2178  {
2179  fu_module->SetParameter("LSB_PARAMETER", STR(curr_LSB));
2180  }
2181  }
2182  if(*it == "OFFSET_PARAMETER" && op_name == "bit_ior_concat_expr")
2183  {
2184  auto index = data->CGetOpNodeInfo(mapped_operation)->GetNodeId();
2185  const auto ga_node = TreeM->GetTreeNode(index);
2186  const auto ga = GetPointer<gimple_assign>(ga_node);
2187  const auto ce = GetPointer<bit_ior_concat_expr>(GET_NODE(ga->op1));
2188  const auto offset_value = tree_helper::GetConstValue(ce->op2);
2189  fu_module->SetParameter("OFFSET_PARAMETER", STR(offset_value));
2190  }
2191  if(*it == "unlock_address" && op_name == BUILTIN_WAIT_CALL)
2192  {
2193  auto index = data->CGetOpNodeInfo(mapped_operation)->GetNodeId();
2194  std::string parameterName = HLSMgr->Rmem->get_symbol(index, HLS->functionId)->get_symbol_name();
2195  fu_module->SetParameter("unlock_address", parameterName);
2196  }
2197  if(*it == "MEMORY_INIT_file" && op_name == BUILTIN_WAIT_CALL)
2198  {
2199  auto index = data->CGetOpNodeInfo(mapped_operation)->GetNodeId();
2200  const auto parameterAddressFileName = "function_addresses_" + STR(index) + ".mem";
2201  std::ofstream parameterAddressFile(GetPath(parameterAddressFileName));
2202 
2203  const auto call = TreeM->CGetTreeNode(index);
2204  const auto& calledFunction = GetPointerS<const gimple_call>(call)->args[0];
2205  const auto& hasreturn_node = GetPointerS<const gimple_call>(call)->args[1];
2206  const auto hasreturn_value = tree_helper::get_integer_cst_value(
2207  GetPointerS<const integer_cst>(GET_CONST_NODE(hasreturn_node)));
2208  const auto addrExpr = GET_NODE(calledFunction);
2209  const auto functionType = getFunctionType(addrExpr);
2210  const auto alignment = HLSMgr->Rmem->get_parameter_alignment();
2211  unsigned long long int address = 0;
2212  address = HLSMgr->Rmem->compute_next_base_address(address, index, alignment);
2213  auto paramList = GetPointerS<const function_type>(functionType)->prms;
2214  while(paramList)
2215  {
2216  const auto node = GetPointerS<const tree_list>(GET_CONST_NODE(paramList));
2217  if(GET_CONST_NODE(node->valu)->get_kind() != void_type_K)
2218  {
2219  const auto str_address = convert_to_binary(address, HLSMgr->get_address_bitsize());
2220  parameterAddressFile << str_address << "\n";
2221  address = HLSMgr->Rmem->compute_next_base_address(address, GET_INDEX_CONST_NODE(node->valu),
2222  alignment);
2223  }
2224  paramList = node->chan;
2225  }
2226  const auto return_type = GetPointerS<const function_type>(functionType)->retn;
2227  if(return_type && GET_CONST_NODE(return_type)->get_kind() != void_type_K && hasreturn_value)
2228  {
2229  const auto str_address = convert_to_binary(address, HLSMgr->get_address_bitsize());
2230  parameterAddressFile << str_address << "\n";
2231  }
2232  parameterAddressFile.close();
2233  fu_module->SetParameter("MEMORY_INIT_file", "\"\"" + GetPath(parameterAddressFileName) + "\"\"");
2234  }
2235  }
2236  }
2237  if(out_var)
2238  {
2239  const auto out_node = TreeM->CGetTreeNode(out_var);
2240  if(tree_helper::IsVectorType(out_node))
2241  {
2242  const auto type = tree_helper::CGetType(out_node);
2243  const auto size = tree_helper::Size(type);
2244  const auto element_type = tree_helper::CGetElements(type);
2245  const auto element_size = tree_helper::Size(element_type);
2246  n_out_elements = size / element_size;
2247  produced_variables = element_size;
2248  }
2249  else
2250  {
2251  produced_variables = std::max(produced_variables, tree_helper::Size(out_node));
2252  }
2254  if(np)
2255  {
2256  std::vector<std::string> param;
2257  np->get_library_parameters(param);
2258  auto it_end = param.end();
2259  for(auto it = param.begin(); it != it_end; ++it)
2260  {
2261  if(*it == "PRECISION")
2262  {
2263  auto sizetype = tree_helper::Size(tree_helper::CGetType(out_node));
2264  if(sizetype == 1)
2265  {
2266  sizetype = 8;
2267  }
2268  fu_module->SetParameter("PRECISION", STR(sizetype));
2269  }
2270  }
2271  }
2272  }
2273  }
2274  }
2275  }
2276 
2277  unsigned int offset = 0;
2278  bool is_multi_read_cond = allocation_information->get_fu_name(fu).first == MULTI_READ_COND_STD;
2279  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Resizing input ports");
2280  for(unsigned int i = 0; i < fu_module->get_in_port_size(); i++)
2281  {
2282  structural_objectRef port = fu_module->get_in_port(i);
2283  if(port->get_id() == CLOCK_PORT_NAME || port->get_id() == RESET_PORT_NAME || port->get_id() == START_PORT_NAME)
2284  {
2285  ++offset;
2286  }
2287  if(is_multiport && port->get_kind() == port_vector_o_K && GetPointer<port_o>(port)->get_ports_size() == 0)
2288  {
2289  GetPointer<port_o>(port)->add_n_ports(static_cast<unsigned int>(max_n_ports), port);
2290  }
2291  else if(is_multi_read_cond && port->get_kind() == port_vector_o_K &&
2292  GetPointer<port_o>(port)->get_ports_size() == 0)
2293  {
2294  GetPointer<port_o>(port)->add_n_ports(static_cast<unsigned int>(required_variables.size()), port);
2295  }
2296  port_o::resize_if_busport(bus_size_bitsize, bus_addr_bitsize, bus_data_bitsize, bus_tag_bitsize, port);
2297  }
2298  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Resized input ports");
2299  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Resizing variables");
2300  auto is_dual = allocation_information->is_dual_port_memory(fu);
2301 
2302  for(auto l = required_variables.begin(); l != required_variables.end() && !is_multi_read_cond; ++l)
2303  {
2304  unsigned long long n_elmts = 0;
2305  if(num_elements.find(l->first) != num_elements.end())
2306  {
2307  n_elmts = num_elements.find(l->first)->second;
2308  }
2309  auto bitsize_variable = l->second;
2310  auto piIndexLimit = 1U;
2311  if(is_dual && l->first)
2312  {
2313  piIndexLimit = 2U;
2314  }
2315  for(auto piOffset = 0U; piOffset < piIndexLimit; ++piOffset)
2316  {
2317  structural_objectRef port = fu_module->get_in_port(l->first + offset + piOffset);
2318  port_o::resize_std_port(bitsize_variable, n_elmts, debug_level, port);
2319  }
2320  if(is_dual && l->first)
2321  {
2322  ++offset;
2323  }
2324  }
2325 
2326  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Resized variables");
2327  offset = 0;
2328  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Resizing output ports");
2329  for(unsigned int i = 0; i < fu_module->get_out_port_size(); i++)
2330  {
2331  structural_objectRef port = fu_module->get_out_port(i);
2332  if(port->get_id() == DONE_PORT_NAME)
2333  {
2334  offset++;
2335  }
2336  if(is_multiport && port->get_kind() == port_vector_o_K && GetPointer<port_o>(port)->get_ports_size() == 0)
2337  {
2338  GetPointer<port_o>(port)->add_n_ports(static_cast<unsigned int>(max_n_ports), port);
2339  }
2340  port_o::resize_if_busport(bus_size_bitsize, bus_addr_bitsize, bus_data_bitsize, bus_tag_bitsize, port);
2341  }
2342  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Resized output ports");
2343  if(offset < fu_module->get_out_port_size())
2344  {
2345  structural_objectRef port = fu_module->get_out_port(offset);
2347  {
2348  if(is_multi_read_cond)
2349  {
2350  port_o::resize_std_port(static_cast<unsigned int>(required_variables.size()), 0, debug_level, port);
2351  }
2352  else
2353  {
2354  port_o::resize_std_port(produced_variables, n_out_elements, debug_level, port);
2355  }
2356  }
2357  }
2358 
2359  auto* fun_unit = GetPointer<functional_unit>(fu_tech_obj);
2360  if(fun_unit)
2361  {
2362  const functional_unit::operation_vec& Ops = fun_unit->get_operations();
2363  auto ops_end = Ops.end();
2364  for(auto ops = Ops.begin(); ops != ops_end; ++ops)
2365  {
2366  auto* curr_op = GetPointer<operation>(*ops);
2367  std::string pipe_parameters_str = curr_op->pipe_parameters;
2368  if(pipe_parameters_str != "")
2369  {
2370  fu_module->SetParameter(PIPE_PARAMETER, pipe_parameters_str);
2371  }
2372  }
2373  }
2374  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "<--Specialized " + fu_obj->get_path());
2375 }
2376 
2378  unsigned int ar, const std::string& base_address,
2379  unsigned long long int rangesize, bool is_memory_splitted,
2380  bool is_sparse_memory, bool is_sds)
2381 {
2382  const auto fu_module = GetPointer<module>(fu_obj);
2384  fu_module->SetParameter("address_space_begin", STR(base_address));
2385  fu_module->SetParameter("address_space_rangesize", STR(rangesize));
2386  fu_module->SetParameter("USE_SPARSE_MEMORY", is_sparse_memory ? "1" : "0");
2387  memory::add_memory_parameter(HLS->datapath, base_address, STR(HLSMgr->Rmem->get_base_address(ar, HLS->functionId)));
2388 
2390  THROW_ASSERT(ar, "expected a real tree node index");
2391  const auto init_filename = "array_ref_" + STR(ar) + ".mem";
2392  std::ofstream init_file_a(GetPath(init_filename));
2393  std::ofstream init_file_b;
2394  if(is_memory_splitted)
2395  {
2396  init_file_b.open(GetPath("0_" + init_filename));
2397  }
2398  unsigned long long vec_size = 0, elts_size = 0;
2399  const auto bitsize_align = is_sds ? 0ULL : std::stoull(fu_module->GetParameter("BRAM_BITSIZE"));
2400  fill_array_ref_memory(init_file_a, init_file_b, ar, vec_size, elts_size, HLSMgr->Rmem, TreeM, is_sds, bitsize_align);
2401  THROW_ASSERT(vec_size, "at least one element is expected");
2402  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---elts_size " + STR(elts_size));
2403  if(is_sds)
2404  {
2405  fu_module->SetParameter("ALIGNMENT", STR(elts_size));
2406  }
2407  if(is_memory_splitted)
2408  {
2409  fu_module->SetParameter("MEMORY_INIT_file_a", "\"\"" + GetPath(init_filename) + "\"\"");
2410  fu_module->SetParameter("MEMORY_INIT_file_b", "\"\"" + GetPath("0_" + init_filename) + "\"\"");
2411  }
2412  else
2413  {
2414  fu_module->SetParameter("MEMORY_INIT_file", "\"\"" + GetPath(init_filename) + "\"\"");
2415  }
2416 
2418  fu_module->SetParameter("n_elements", STR(vec_size));
2419  fu_module->SetParameter("data_size", STR(elts_size));
2420  fu_module->SetParameter("PRIVATE_MEMORY", HLSMgr->Rmem->is_private_memory(ar) ? "1" : "0");
2421  fu_module->SetParameter("READ_ONLY_MEMORY", HLSMgr->Rmem->is_read_only_variable(ar) ? "1" : "0");
2422 }
2423 
2424 void fu_binding::fill_array_ref_memory(std::ostream& init_file_a, std::ostream& init_file_b, unsigned int ar,
2425  unsigned long long& vec_size, unsigned long long& elts_size, const memoryRef mem,
2426  tree_managerConstRef TM, bool is_sds, unsigned long long bitsize_align)
2427 {
2428  init_file_b.put(0);
2429  const auto is_memory_splitted = init_file_b.good();
2430  init_file_b.seekp(std::ios_base::beg);
2431 
2432  const auto ar_node = TM->CGetTreeReindex(ar);
2433  tree_nodeRef init_node;
2434  const auto vd = GetPointer<const var_decl>(GET_CONST_NODE(ar_node));
2435  if(vd && vd->init)
2436  {
2437  init_node = vd->init;
2438  }
2439  else if(GetPointer<const string_cst>(GET_CONST_NODE(ar_node)))
2440  {
2441  init_node = ar_node;
2442  }
2443  const auto array_type_node = tree_helper::CGetType(ar_node);
2444  unsigned long long element_align = 0;
2445  if(tree_helper::IsArrayEquivType(array_type_node))
2446  {
2447  std::vector<unsigned long long> dims;
2448  tree_helper::get_array_dim_and_bitsize(TM, array_type_node->index, dims, elts_size);
2449  THROW_ASSERT(dims.size(), "something wrong happened");
2450  vec_size = std::accumulate(dims.begin(), dims.end(), 1ULL,
2451  [](unsigned long long a, unsigned long long b) { return a * b; });
2452  }
2453  else if(GetPointer<const integer_type>(GET_CONST_NODE(array_type_node)) ||
2454  tree_helper::IsRealType(array_type_node) || tree_helper::IsEnumType(array_type_node) ||
2455  tree_helper::IsPointerType(array_type_node) || tree_helper::IsStructType(array_type_node) ||
2456  tree_helper::IsUnionType(array_type_node) || tree_helper::IsComplexType(array_type_node))
2457  {
2458  elts_size = tree_helper::Size(array_type_node);
2459  vec_size = 1;
2460  }
2461  else if(tree_helper::IsBooleanType(array_type_node))
2462  {
2463  elts_size = 8;
2464  vec_size = 1;
2465  }
2466  else if(tree_helper::IsVectorType(array_type_node))
2467  {
2468  elts_size = tree_helper::Size(array_type_node);
2469  const auto element_type = tree_helper::CGetElements(array_type_node);
2470  element_align = tree_helper::Size(element_type);
2471  vec_size = 1;
2472  }
2473  else
2474  {
2475  THROW_ERROR("Type not supported: " + GET_CONST_NODE(array_type_node)->get_kind_text());
2476  }
2477  THROW_ASSERT(elts_size && vec_size, "");
2478  if(is_sds)
2479  {
2480  bitsize_align = elts_size;
2481  }
2482  else
2483  {
2484  elts_size = get_aligned_bitsize(elts_size, 8ULL);
2485  }
2486 
2487  const auto nbyte_on_memory = bitsize_align / 8;
2488 
2489  if(init_node &&
2490  ((GetPointer<constructor>(GET_NODE(init_node)) &&
2491  GetPointerS<constructor>(GET_NODE(init_node))->list_of_idx_valu.size()) ||
2492  (GetPointer<string_cst>(GET_NODE(init_node)) && GetPointerS<string_cst>(GET_NODE(init_node))->strg.size()) ||
2493  (!GetPointer<constructor>(GET_NODE(init_node)) && !GetPointer<string_cst>(GET_NODE(init_node)))))
2494  {
2495  std::vector<std::string> init_string;
2496  write_init(TM, ar_node, init_node, init_string, mem, element_align);
2497  if(is_sds && (element_align == 0 || elts_size == element_align))
2498  {
2499  THROW_ASSERT(!is_memory_splitted, "unexpected condition");
2500  for(const auto& init_value : init_string)
2501  {
2502  THROW_ASSERT(elts_size, "unexpected condition");
2503  if(elts_size != init_value.size() && (init_value.size() % elts_size == 0))
2504  {
2505  const auto n_elmts = init_value.size() / elts_size;
2506  for(auto index = 0u; index < n_elmts; ++index)
2507  {
2508  init_file_a << init_value.substr(init_value.size() - elts_size - index * elts_size, elts_size)
2509  << std::endl;
2510  }
2511  }
2512  else
2513  {
2514  init_file_a << init_value << std::endl;
2515  }
2516  }
2517  }
2518  else
2519  {
2520  std::vector<std::string> eightbit_string;
2521  std::string bits_offset = "";
2522  for(unsigned int l = 0; l < init_string.size(); ++l)
2523  {
2524  if(init_string[l].size() < 8 && init_string.size() == 1)
2525  {
2526  std::string res = init_string[l];
2527  while(res.size() < 8)
2528  {
2529  res = "0" + res;
2530  }
2531  eightbit_string.push_back(res);
2532  }
2533  else
2534  {
2535  std::string local_binary_string;
2536  size_t local_data_bitsize;
2537  size_t data_bitsize = init_string[l].size();
2538  if(bits_offset.size())
2539  {
2540  if(static_cast<int>(data_bitsize) - 8 + static_cast<int>(bits_offset.size()) >= 0)
2541  {
2542  local_data_bitsize = data_bitsize - (8 - bits_offset.size());
2543  eightbit_string.push_back(
2544  init_string[l].substr(data_bitsize - (8 - bits_offset.size()), 8 - bits_offset.size()) +
2545  bits_offset);
2546  local_binary_string = init_string[l].substr(0, local_data_bitsize);
2547  bits_offset = "";
2548  }
2549  else
2550  {
2551  local_data_bitsize = 0;
2552  bits_offset = init_string[l] + bits_offset;
2553  }
2554  }
2555  else
2556  {
2557  local_binary_string = init_string[l];
2558  local_data_bitsize = data_bitsize;
2559  }
2560  for(unsigned int base_index = 0; base_index < local_data_bitsize; base_index = base_index + 8)
2561  {
2562  if((static_cast<int>(local_data_bitsize) - 8 - static_cast<int>(base_index)) >= 0)
2563  {
2564  eightbit_string.push_back(local_binary_string.substr(local_data_bitsize - 8 - base_index, 8));
2565  }
2566  else
2567  {
2568  bits_offset = local_binary_string.substr(0, local_data_bitsize - base_index);
2569  }
2570  }
2571  }
2572  }
2573  if(bits_offset.size())
2574  {
2575  std::string tail_padding;
2576  for(auto tail_padding_ind = bits_offset.size(); tail_padding_ind < 8; ++tail_padding_ind)
2577  {
2578  tail_padding += "0";
2579  }
2580  tail_padding = tail_padding + bits_offset;
2581  eightbit_string.push_back(tail_padding);
2582  }
2583  if(eightbit_string.size() % nbyte_on_memory != 0)
2584  {
2585  for(size_t l = eightbit_string.size() % nbyte_on_memory; l < nbyte_on_memory; ++l)
2586  {
2587  eightbit_string.push_back("00000000");
2588  }
2589  }
2590  if(static_cast<size_t>(tree_helper::Size(array_type_node) / 8) > eightbit_string.size())
2591  {
2592  size_t tail_bytes = static_cast<size_t>(tree_helper::Size(array_type_node) / 8) - eightbit_string.size();
2593  for(size_t l = 0; l < tail_bytes; ++l)
2594  {
2595  eightbit_string.push_back("00000000");
2596  }
2597  }
2598 
2599  std::string str_bit;
2600  bool is_even = true;
2601  unsigned int counter;
2602  for(unsigned int l = 0; l < eightbit_string.size();)
2603  {
2604  str_bit = "";
2605  for(counter = 0; counter < nbyte_on_memory && l < eightbit_string.size(); counter++, l++)
2606  {
2607  str_bit = eightbit_string[l] + str_bit;
2608  }
2609  if(is_even || !is_memory_splitted)
2610  {
2611  init_file_a << str_bit << std::endl;
2612  }
2613  else
2614  {
2615  init_file_b << str_bit << std::endl;
2616  }
2617  is_even = !is_even;
2618  }
2619  if(!is_even && is_memory_splitted)
2620  {
2621  bool need_newline_b = false;
2622  for(unsigned int l = 0; l < (nbyte_on_memory * 8); ++l)
2623  {
2624  init_file_b << "0";
2625  need_newline_b = true;
2626  }
2627  if(need_newline_b)
2628  {
2629  init_file_b << std::endl;
2630  }
2631  }
2632  }
2633  }
2634  else
2635  {
2636  if(is_sds)
2637  {
2638  THROW_ASSERT(!is_memory_splitted, "unexpected condition");
2639  for(unsigned int i = 0; i < vec_size; ++i)
2640  {
2641  for(unsigned int j = 0; j < elts_size; ++j)
2642  {
2643  init_file_a << "0";
2644  }
2645  init_file_a << std::endl;
2646  }
2647  }
2648  else
2649  {
2650  unsigned int counter = 0;
2651  bool is_even = true;
2652  bool need_newline_a = false;
2653  bool need_newline_b = false;
2654  for(unsigned int i = 0; i < vec_size; ++i)
2655  {
2656  for(unsigned int j = 0; j < elts_size; ++j)
2657  {
2658  if(is_even || !is_memory_splitted)
2659  {
2660  init_file_a << "0";
2661  need_newline_a = true;
2662  }
2663  else
2664  {
2665  init_file_b << "0";
2666  need_newline_b = true;
2667  }
2668  counter++;
2669  if(counter % (nbyte_on_memory * 8) == 0)
2670  {
2671  if(is_even || !is_memory_splitted)
2672  {
2673  init_file_a << std::endl;
2674  need_newline_a = false;
2675  }
2676  else
2677  {
2678  init_file_b << std::endl;
2679  need_newline_b = false;
2680  }
2681  is_even = !is_even;
2682  }
2683  }
2684  }
2685  if(counter % (nbyte_on_memory * 8) != 0)
2686  {
2687  for(auto l = counter % (nbyte_on_memory * 8); l < (nbyte_on_memory * 8); ++l)
2688  {
2689  if(is_even || !is_memory_splitted)
2690  {
2691  init_file_a << "0";
2692  need_newline_a = true;
2693  }
2694  else
2695  {
2696  init_file_b << "0";
2697  need_newline_b = true;
2698  }
2699  }
2700  is_even = !is_even;
2701  }
2702  if(!is_even && is_memory_splitted)
2703  {
2704  for(unsigned int l = 0; l < (nbyte_on_memory * 8); ++l)
2705  {
2706  init_file_b << "0";
2707  need_newline_b = true;
2708  }
2709  }
2710  if(need_newline_a)
2711  {
2712  init_file_a << std::endl;
2713  }
2714  if(need_newline_b)
2715  {
2716  init_file_b << std::endl;
2717  }
2718  }
2719  }
2720 }
2721 
2723  std::vector<std::string>& init_file, const memoryRef mem, unsigned long long element_align)
2724 {
2725  std::string trimmed_value;
2726  THROW_ASSERT(!var_node || var_node->get_kind() == tree_reindex_K, "");
2727  const auto init_node = GET_CONST_NODE(_init_node);
2728  switch(init_node->get_kind())
2729  {
2730  case real_cst_K:
2731  {
2732  auto precision = tree_helper::Size(tree_helper::CGetType(_init_node));
2733  const auto rc = GetPointerS<const real_cst>(init_node);
2734  std::string C_value = rc->valr;
2735  trimmed_value = convert_fp_to_string(C_value, precision);
2736  init_file.push_back(trimmed_value);
2737  break;
2738  }
2739  case integer_cst_K:
2740  {
2741  const auto ull_value = tree_helper::GetConstValue(init_node);
2742  trimmed_value = "";
2743  auto precision = std::max(8ull, tree_helper::Size(tree_helper::CGetType(_init_node)));
2744  if(element_align)
2745  {
2746  precision = std::min(precision, element_align);
2747  }
2748  for(auto ind = 1U; ind <= precision; ind++)
2749  {
2750  trimmed_value.push_back(((integer_cst_t(1) << (precision - ind)) & ull_value) ? '1' : '0');
2751  }
2752  init_file.push_back(trimmed_value);
2753  break;
2754  }
2755  case complex_cst_K:
2756  {
2757  const auto precision = tree_helper::Size(tree_helper::CGetType(_init_node));
2758  const auto cc = GetPointerS<const complex_cst>(init_node);
2759  write_init(TreeM, var_node, cc->real, init_file, mem, precision / 2);
2760  write_init(TreeM, var_node, cc->imag, init_file, mem, precision / 2);
2761  break;
2762  }
2763  case constructor_K:
2764  {
2765  const auto co = GetPointerS<const constructor>(init_node);
2766  bool designated_initializers_used = false;
2767  bool is_struct = false;
2768  bool is_union = false;
2769  unsigned long long union_size = 0;
2770  std::vector<tree_nodeRef>* field_list = nullptr;
2772  if(co->list_of_idx_valu.size() && GET_NODE(co->list_of_idx_valu.front().first)->get_kind() == field_decl_K)
2773  {
2774  auto iv_it = co->list_of_idx_valu.begin();
2775  const auto iv_end = co->list_of_idx_valu.end();
2776  const auto scpe = GET_NODE(GetPointerS<field_decl>(GET_NODE(iv_it->first))->scpe);
2777 
2778  if(scpe->get_kind() == record_type_K)
2779  {
2780  field_list = &GetPointerS<record_type>(scpe)->list_of_flds;
2781  // struct_or_union_align = GetPointer<record_type>(scpe)->algn;
2782  is_struct = true;
2783  }
2784  else if(scpe->get_kind() == union_type_K)
2785  {
2786  field_list = &GetPointerS<union_type>(scpe)->list_of_flds;
2787  is_union = true;
2788  union_size = tree_helper::Size(scpe);
2789  }
2790  else
2791  {
2792  THROW_ERROR("expected a record_type or a union_type");
2793  }
2794  auto fl_it = field_list->begin();
2795  const auto fl_end = field_list->end();
2796  for(; fl_it != fl_end && iv_it != iv_end; ++iv_it, ++fl_it)
2797  {
2798  if(iv_it->first && GET_INDEX_NODE(iv_it->first) != GET_INDEX_NODE(*fl_it))
2799  {
2800  break;
2801  }
2802  }
2803  if(fl_it != fl_end && is_struct)
2804  {
2805  designated_initializers_used = true;
2806  }
2807  }
2808 
2809  const auto main_element_align = element_align;
2810  if(designated_initializers_used)
2811  {
2812  THROW_ASSERT(field_list, "something wrong happened");
2813  auto fli = field_list->begin();
2814  const auto flend = field_list->end();
2815  auto iv_it = co->list_of_idx_valu.begin();
2816  const auto iv_end = co->list_of_idx_valu.end();
2817  for(; fli != flend; ++fli)
2818  {
2819  if(!GetPointer<field_decl>(GET_NODE(*fli)))
2820  {
2821  continue;
2822  }
2823  const auto is_bitfield = GetPointer<field_decl>(GET_NODE(*fli))->is_bitfield();
2824  auto inext = fli;
2825  ++inext;
2826  while(inext != flend && !GetPointer<field_decl>(GET_NODE(*inext)))
2827  {
2828  ++inext;
2829  }
2830 
2831  if(is_bitfield)
2832  {
2833  const auto size_type = tree_helper::CGetType(*fli);
2834  // fix the element precision to pass to write_init
2835  element_align = tree_helper::Size(size_type);
2836  }
2837 
2838  if(iv_it != iv_end && GET_INDEX_NODE(iv_it->first) == GET_INDEX_NODE(*fli))
2839  {
2840  write_init(TreeM, iv_it->first, iv_it->second, init_file, mem, element_align);
2841  ++iv_it;
2842  }
2843  else
2844  {
2845  write_init(TreeM, *fli, *fli, init_file, mem, element_align);
2846  }
2847 
2848  if(is_bitfield)
2849  {
2850  // reset the element_align to the main value
2851  element_align = main_element_align;
2852  }
2853 
2854  if(!is_bitfield)
2855  {
2857  unsigned long long int nbits;
2858  if(inext != flend)
2859  {
2860  const auto idx_next_fd = GetPointerS<field_decl>(GET_NODE(*inext));
2861  THROW_ASSERT(tree_helper::GetConstValue(idx_next_fd->bpos) >= 0, "");
2862  nbits = static_cast<unsigned long long int>(tree_helper::GetConstValue(idx_next_fd->bpos));
2863  }
2864  else
2865  {
2866  nbits = tree_helper::Size(co->type);
2867  }
2868  const auto idx_curr_fd = GetPointer<field_decl>(GET_NODE(*fli));
2869  const auto field_decl_size = tree_helper::Size(tree_helper::CGetType(*fli));
2870  THROW_ASSERT(nbits >= (tree_helper::GetConstValue(idx_curr_fd->bpos) + field_decl_size), "");
2871  nbits -= static_cast<unsigned long long int>(tree_helper::GetConstValue(idx_curr_fd->bpos)) +
2872  field_decl_size;
2873  if(nbits)
2874  {
2876  init_file.push_back(std::string(nbits, '0'));
2877  }
2878  }
2879  }
2880  }
2881  else
2882  {
2883  auto iv_it = co->list_of_idx_valu.begin();
2884  const auto iv_end = co->list_of_idx_valu.end();
2885  for(; iv_it != iv_end; ++iv_it)
2886  {
2887  if(is_struct && !GetPointer<field_decl>(GET_NODE(iv_it->first)))
2888  {
2889  continue;
2890  }
2891  const auto is_bitfield = is_struct && GetPointer<field_decl>(GET_NODE(iv_it->first))->is_bitfield();
2892  auto iv_next = iv_it;
2893  ++iv_next;
2894  while(iv_next != iv_end && is_struct && !GetPointer<field_decl>(GET_NODE(iv_next->first)))
2895  {
2896  ++iv_next;
2897  }
2898  if(is_struct && is_bitfield)
2899  {
2900  const auto size_type = tree_helper::CGetType(iv_it->first);
2901  // fix the element precision to pass to write_init
2902  element_align = tree_helper::Size(size_type);
2903  }
2904  write_init(TreeM, iv_it->first, iv_it->second, init_file, mem, element_align);
2905  if(is_struct && is_bitfield)
2906  {
2907  // reset the element_align to the main value
2908  element_align = main_element_align;
2909  }
2910 
2911  if(is_struct && !is_bitfield)
2912  {
2914  unsigned long long int nbits;
2915  if(iv_next != iv_end)
2916  {
2917  const auto idx_next_fd = GetPointerS<field_decl>(GET_NODE(iv_next->first));
2918  THROW_ASSERT(tree_helper::GetConstValue(idx_next_fd->bpos) >= 0, "");
2919  nbits = static_cast<unsigned long long int>(tree_helper::GetConstValue(idx_next_fd->bpos));
2920  }
2921  else
2922  {
2923  nbits = tree_helper::Size(co->type);
2924  }
2925  const auto field_decl_size = tree_helper::Size(tree_helper::CGetType(iv_it->first));
2926  const auto idx_curr_fd = GetPointerS<field_decl>(GET_NODE(iv_it->first));
2927  THROW_ASSERT(nbits >= (tree_helper::GetConstValue(idx_curr_fd->bpos) + field_decl_size), "");
2928  nbits -= static_cast<unsigned long long int>(tree_helper::GetConstValue(idx_curr_fd->bpos)) +
2929  field_decl_size;
2930  if(nbits)
2931  {
2933  init_file.push_back(std::string(nbits, '0'));
2934  }
2935  }
2936  else if(is_union)
2937  {
2939  THROW_ASSERT(co->list_of_idx_valu.size() == 1, "just one initializer is possible");
2940  const auto field_decl_size = tree_helper::Size(iv_it->first);
2941  THROW_ASSERT(union_size >= field_decl_size, "");
2942  const auto nbits = union_size - field_decl_size;
2943  if(nbits)
2944  {
2946  init_file.push_back(std::string(nbits, '0'));
2947  }
2948  }
2949  }
2950  }
2951  const auto type_n = tree_helper::CGetType(var_node);
2952  if(GetPointer<const array_type>(GET_CONST_NODE(type_n)))
2953  {
2954  unsigned long long size_of_data;
2955  std::vector<unsigned long long> dims;
2956  tree_helper::get_array_dim_and_bitsize(TreeM, type_n->index, dims, size_of_data);
2957  if(element_align)
2958  {
2959  size_of_data = std::min(size_of_data, element_align);
2960  }
2961  auto num_elements = dims[0];
2962  if(num_elements < co->list_of_idx_valu.size())
2963  {
2964  THROW_ERROR("C description not supported: Array with undefined size or not correctly initialized " +
2965  STR(co->list_of_idx_valu.size()) + "-" + STR(num_elements));
2966  }
2967  THROW_ASSERT(num_elements >= static_cast<unsigned long long>(co->list_of_idx_valu.size()), "");
2968  num_elements -= static_cast<unsigned long long>(co->list_of_idx_valu.size());
2969  init_file.insert(init_file.end(), num_elements, std::string(size_of_data, '0'));
2970  }
2971  break;
2972  }
2973  case string_cst_K:
2974  {
2975  const auto sc = GetPointerS<const string_cst>(init_node);
2976  const auto string_value = [&]() {
2977  std::string tmp;
2978  const char* c_str = sc->strg.c_str();
2979  for(size_t index = 0; index < sc->strg.size(); ++index)
2980  {
2981  if(c_str[index] == '\\' && c_str[index + 1] == '0')
2982  {
2983  tmp += '\0';
2984  ++index;
2985  }
2986  else
2987  {
2988  tmp += c_str[index];
2989  }
2990  }
2991  boost::replace_all(tmp, "\\a", "\a");
2992  boost::replace_all(tmp, "\\b", "\b");
2993  boost::replace_all(tmp, "\\t", "\t");
2994  boost::replace_all(tmp, "\\n", "\n");
2995  boost::replace_all(tmp, "\\v", "\v");
2996  boost::replace_all(tmp, "\\f", "\f");
2997  boost::replace_all(tmp, "\\r", "\r");
2998  boost::replace_all(tmp, "\\'", "'");
2999  boost::replace_all(tmp, "\\\"", "\"");
3000  boost::replace_all(tmp, "\\\\", "\\");
3001  return tmp;
3002  }();
3003  unsigned long long elmt_bitsize;
3004  std::vector<unsigned long long> dims;
3005 
3006  tree_helper::get_array_dim_and_bitsize(TreeM, GET_INDEX_NODE(sc->type), dims, elmt_bitsize);
3007  if(elmt_bitsize != 8)
3008  {
3009  THROW_ERROR("non-standard 8-bit char conversion not supported");
3010  }
3011  for(const auto j : string_value)
3012  {
3013  auto ull_value = static_cast<unsigned long int>(j);
3014  trimmed_value = "";
3015  for(auto ind = 0U; ind < elmt_bitsize; ++ind)
3016  {
3017  trimmed_value = trimmed_value + (((1LLU << (elmt_bitsize - ind - 1)) & ull_value) ? '1' : '0');
3018  }
3019  init_file.push_back(trimmed_value);
3020  }
3021  // String terminator
3022  init_file.push_back(std::string(elmt_bitsize, '0'));
3023 
3024  const auto type_n = tree_helper::CGetType(var_node);
3025  THROW_ASSERT(GetPointer<const array_type>(GET_CONST_NODE(type_n)), "expected an array_type");
3026  dims.clear();
3027  unsigned long long size_of_data;
3028  tree_helper::get_array_dim_and_bitsize(TreeM, type_n->index, dims, size_of_data);
3029  THROW_ASSERT(size_of_data == elmt_bitsize, "something wrong happened");
3030  auto num_elements = std::accumulate(dims.begin(), dims.end(), 1ULL,
3031  [](unsigned long long a, unsigned long long b) { return a * b; });
3032  std::string value;
3033  if(num_elements < (string_value.size() + 1))
3034  {
3035  THROW_ERROR("C description not supported: string with undefined size or not correctly initialized " +
3036  STR(string_value.size() + 1) + "-" + STR(num_elements));
3037  }
3038  num_elements -= string_value.size() + 1;
3039  init_file.insert(init_file.end(), num_elements, std::string(size_of_data, '0'));
3040  break;
3041  }
3042  case view_convert_expr_K:
3043  case nop_expr_K:
3044  {
3045  const auto ue = GetPointerS<unary_expr>(init_node);
3046  if(GetPointer<addr_expr>(GET_NODE(ue->op)))
3047  {
3048  write_init(TreeM, ue->op, ue->op, init_file, mem, element_align);
3049  }
3050  else if(GetPointer<integer_cst>(GET_NODE(ue->op)))
3051  {
3052  const auto precision =
3053  std::max(std::max(8ull, element_align), tree_helper::Size(tree_helper::CGetType(init_node)));
3054  write_init(TreeM, ue->op, ue->op, init_file, mem, precision);
3055  }
3056  else
3057  {
3058  THROW_ERROR("Something unexpected happened: " + STR(init_node->index) + " | " +
3059  GET_NODE(ue->op)->get_kind_text());
3060  }
3061  break;
3062  }
3063  case addr_expr_K:
3064  {
3065  auto* ae = GetPointerS<addr_expr>(init_node);
3066  tree_nodeRef addr_expr_op = GET_NODE(ae->op);
3067  auto addr_expr_op_idx = GET_INDEX_NODE(ae->op);
3068  unsigned long long int ull_value = 0;
3069  const auto precision = tree_helper::Size(tree_helper::CGetType(_init_node));
3070  switch(addr_expr_op->get_kind())
3071  {
3072  case ssa_name_K:
3073  case var_decl_K:
3074  case parm_decl_K:
3075  case string_cst_K:
3076  {
3077  THROW_ASSERT(mem->has_base_address(addr_expr_op_idx), "missing base address for: " + ae->ToString());
3078  ull_value = mem->get_base_address(addr_expr_op_idx, 0);
3079  break;
3080  }
3081  case array_ref_K:
3082  {
3083  const auto ar = GetPointerS<array_ref>(addr_expr_op);
3084  if(GetPointer<integer_cst>(GET_NODE(ar->op1)))
3085  {
3086  switch(GET_NODE(ar->op0)->get_kind())
3087  {
3088  case ssa_name_K:
3089  case var_decl_K:
3090  case parm_decl_K:
3091  case string_cst_K:
3092  {
3093  const auto step = tree_helper::Size(tree_helper::CGetType(ae->op)) / 8;
3094  THROW_ASSERT(tree_helper::GetConstValue(ar->op1) >= 0, "");
3095  ull_value = mem->get_base_address(GET_INDEX_NODE(ar->op0), 0) +
3096  step * static_cast<unsigned long long>(tree_helper::GetConstValue(ar->op1));
3097  break;
3098  }
3099  case binfo_K:
3100  case block_K:
3101  case call_expr_K:
3102  case aggr_init_expr_K:
3103  case case_label_expr_K:
3104  case constructor_K:
3105  case identifier_node_K:
3106  case statement_list_K:
3107  case target_expr_K:
3108  case target_mem_ref_K:
3109  case target_mem_ref461_K:
3110  case tree_list_K:
3111  case tree_vec_K:
3112  case lut_expr_K:
3114  case CASE_CPP_NODES:
3115  case CASE_FAKE_NODES:
3116  case CASE_GIMPLE_NODES:
3117  case CASE_PRAGMA_NODES:
3120  case CASE_TYPE_NODES:
3121  case CASE_UNARY_EXPRESSION:
3122  case complex_cst_K:
3123  case integer_cst_K:
3124  case real_cst_K:
3125  case vector_cst_K:
3126  case void_cst_K:
3127  case const_decl_K:
3128  case field_decl_K:
3129  case function_decl_K:
3130  case label_decl_K:
3131  case namespace_decl_K:
3132  case result_decl_K:
3133  case translation_unit_decl_K:
3134  case error_mark_K:
3135  case using_decl_K:
3136  case type_decl_K:
3137  case template_decl_K:
3138  default:
3139  THROW_ERROR("addr_expr-array_ref[0] pattern not supported: " +
3140  std::string(addr_expr_op->get_kind_text()) + " @" + STR(addr_expr_op_idx));
3141  }
3142  }
3143  else
3144  {
3145  THROW_ERROR("addr_expr-array_ref[0] pattern not supported: " +
3146  std::string(addr_expr_op->get_kind_text()) + " @" + STR(addr_expr_op_idx));
3147  }
3148  break;
3149  }
3150  case function_decl_K:
3151  {
3152  THROW_ASSERT(mem->has_base_address(addr_expr_op_idx), "missing base address for: " + ae->ToString());
3153  ull_value = mem->get_base_address(addr_expr_op_idx, addr_expr_op_idx);
3154  break;
3155  }
3157  {
3158  if(addr_expr_op->get_kind() == mem_ref_K)
3159  {
3160  const auto mr = GetPointerS<mem_ref>(addr_expr_op);
3161  const auto op1 = GET_NODE(mr->op1);
3162  if(op1->get_kind() == integer_cst_K)
3163  {
3164  THROW_ASSERT(tree_helper::GetConstValue(mr->op1) >= 0, "");
3165  const auto offset = static_cast<unsigned long long>(tree_helper::GetConstValue(mr->op1));
3166  if(GET_CONST_NODE(mr->op0)->get_kind() == var_decl_K)
3167  {
3168  ull_value = mem->get_base_address(GET_INDEX_CONST_NODE(mr->op0), 0) + offset;
3169  }
3170  else if(GET_CONST_NODE(mr->op0)->get_kind() == addr_expr_K)
3171  {
3172  const auto base = GetPointerS<addr_expr>(GET_CONST_NODE(mr->op0))->op;
3173  if(GET_CONST_NODE(base)->get_kind() == var_decl_K)
3174  {
3175  ull_value = mem->get_base_address(GET_INDEX_CONST_NODE(base), 0) + offset;
3176  }
3177  else
3178  {
3179  THROW_ERROR("addr_expr pattern not supported: " +
3180  std::string(addr_expr_op->get_kind_text()) + " @" + STR(addr_expr_op_idx));
3181  }
3182  }
3183  else
3184  {
3185  THROW_ERROR("addr_expr pattern not supported: " + std::string(addr_expr_op->get_kind_text()) +
3186  " @" + STR(addr_expr_op_idx));
3187  }
3188  }
3189  else
3190  {
3191  THROW_ERROR("addr_expr pattern not supported: " + std::string(addr_expr_op->get_kind_text()) +
3192  " @" + STR(addr_expr_op_idx));
3193  }
3194  }
3195  else
3196  {
3197  THROW_ERROR("addr_expr pattern not supported: " + std::string(addr_expr_op->get_kind_text()) + " @" +
3198  STR(addr_expr_op_idx));
3199  }
3200  break;
3201  }
3202  case array_range_ref_K:
3203  case binfo_K:
3204  case bit_field_ref_K:
3205  case block_K:
3206  case call_expr_K:
3207  case aggr_init_expr_K:
3208  case case_label_expr_K:
3209  case complex_cst_K:
3210  case component_ref_K:
3211  case cond_expr_K:
3212  case const_decl_K:
3213  case constructor_K:
3214  case dot_prod_expr_K:
3215  case ternary_plus_expr_K:
3216  case ternary_pm_expr_K:
3217  case ternary_mp_expr_K:
3218  case ternary_mm_expr_K:
3219  case fshl_expr_K:
3220  case fshr_expr_K:
3221  case insertvalue_expr_K:
3222  case insertelement_expr_K:
3223  case bit_ior_concat_expr_K:
3224  case field_decl_K:
3225  case identifier_node_K:
3226  case integer_cst_K:
3227  case label_decl_K:
3228  case namespace_decl_K:
3229  case obj_type_ref_K:
3230  case real_cst_K:
3231  case result_decl_K:
3232  case save_expr_K:
3233  case statement_list_K:
3234  case target_expr_K:
3235  case target_mem_ref_K:
3236  case target_mem_ref461_K:
3237  case translation_unit_decl_K:
3238  case template_decl_K:
3239  case error_mark_K:
3240  case using_decl_K:
3241  case tree_list_K:
3242  case tree_vec_K:
3243  case type_decl_K:
3244  case vec_cond_expr_K:
3245  case vec_perm_expr_K:
3246  case vector_cst_K:
3247  case void_cst_K:
3248  case vtable_ref_K:
3249  case with_cleanup_expr_K:
3250  case lut_expr_K:
3251  case CASE_CPP_NODES:
3252  case CASE_FAKE_NODES:
3253  case CASE_GIMPLE_NODES:
3254  case CASE_PRAGMA_NODES:
3255  case CASE_TYPE_NODES:
3256  case CASE_UNARY_EXPRESSION:
3257  default:
3258  THROW_ERROR("addr_expr pattern not supported: " + std::string(addr_expr_op->get_kind_text()) + " @" +
3259  STR(addr_expr_op_idx));
3260  }
3261  for(unsigned int ind = 0; ind < precision; ind++)
3262  {
3263  trimmed_value = trimmed_value + (((1LLU << (precision - ind - 1)) & ull_value) ? '1' : '0');
3264  }
3265  init_file.push_back(trimmed_value);
3266 
3267  break;
3268  }
3269  case field_decl_K:
3270  {
3271  const auto field_decl_size = tree_helper::Size(tree_helper::CGetType(_init_node));
3272  if(field_decl_size)
3273  {
3274  init_file.push_back(std::string(field_decl_size, '0'));
3275  }
3276  break;
3277  }
3278  case vector_cst_K:
3279  {
3280  const auto vc = GetPointerS<vector_cst>(init_node);
3281  for(const auto& i : vc->list_of_valu) // vector elements
3282  {
3283  write_init(TreeM, i, i, init_file, mem, element_align);
3284  }
3285  break;
3286  }
3287  case void_cst_K:
3288  case binfo_K:
3289  case block_K:
3290  case call_expr_K:
3291  case aggr_init_expr_K:
3292  case case_label_expr_K:
3293  case identifier_node_K:
3294  case paren_expr_K:
3295  case ssa_name_K:
3296  case statement_list_K:
3297  case target_mem_ref_K:
3298  case target_mem_ref461_K:
3299  case tree_list_K:
3300  case tree_vec_K:
3301  case const_decl_K:
3302  case function_decl_K:
3303  case label_decl_K:
3304  case namespace_decl_K:
3305  case parm_decl_K:
3306  case result_decl_K:
3307  case translation_unit_decl_K:
3308  case template_decl_K:
3309  case error_mark_K:
3310  case using_decl_K:
3311  case type_decl_K:
3312  case var_decl_K:
3313  case abs_expr_K:
3314  case alignof_expr_K:
3315  case arrow_expr_K:
3316  case bit_not_expr_K:
3317  case buffer_ref_K:
3318  case card_expr_K:
3319  case cleanup_point_expr_K:
3320  case conj_expr_K:
3321  case convert_expr_K:
3322  case exit_expr_K:
3323  case fix_ceil_expr_K:
3324  case fix_floor_expr_K:
3325  case fix_round_expr_K:
3326  case fix_trunc_expr_K:
3327  case float_expr_K:
3328  case imagpart_expr_K:
3329  case indirect_ref_K:
3330  case misaligned_indirect_ref_K:
3331  case loop_expr_K:
3332  case negate_expr_K:
3333  case non_lvalue_expr_K:
3334  case realpart_expr_K:
3335  case reference_expr_K:
3336  case reinterpret_cast_expr_K:
3337  case sizeof_expr_K:
3338  case static_cast_expr_K:
3339  case throw_expr_K:
3340  case target_expr_K:
3341  case truth_not_expr_K:
3342  case unsave_expr_K:
3343  case va_arg_expr_K:
3344  case reduc_max_expr_K:
3345  case reduc_min_expr_K:
3346  case reduc_plus_expr_K:
3347  case vec_unpack_hi_expr_K:
3348  case vec_unpack_lo_expr_K:
3349  case vec_unpack_float_hi_expr_K:
3350  case vec_unpack_float_lo_expr_K:
3351  case lut_expr_K:
3353  case CASE_CPP_NODES:
3354  case CASE_FAKE_NODES:
3355  case CASE_GIMPLE_NODES:
3356  case CASE_PRAGMA_NODES:
3359  case CASE_TYPE_NODES:
3360  default:
3361  THROW_ERROR("elements not yet supported: " + init_node->get_kind_text() + init_node->ToString() +
3362  (var_node ? STR(var_node) : ""));
3363  }
3364 }
3365 
3367 {
3368  THROW_ASSERT(GetPointer<addr_expr>(exp) || GetPointer<ssa_name>(exp), "Input must be a ssa_name or an addr_expr");
3369  auto* sa = GetPointer<ssa_name>(exp);
3370  if(sa)
3371  {
3372  THROW_ASSERT(sa, "Function pointer not in SSA-form");
3373  pointer_type* pt;
3374  if(sa->var)
3375  {
3376  auto* var = GetPointer<decl_node>(GET_NODE(sa->var));
3377  THROW_ASSERT(var, "Call expression does not point to a declaration node");
3378  pt = GetPointer<pointer_type>(GET_NODE(var->type));
3379  }
3380  else
3381  {
3382  pt = GetPointer<pointer_type>(GET_NODE(sa->type));
3383  }
3384 
3385  THROW_ASSERT(pt, "Declaration node has not information about pointer_type");
3386  THROW_ASSERT(GetPointer<function_type>(GET_NODE(pt->ptd)),
3387  "Pointer type has not information about pointed function_type");
3388 
3389  return GET_NODE(pt->ptd);
3390  }
3391 
3392  auto* AE = GetPointer<addr_expr>(exp);
3393  auto* FD = GetPointer<function_decl>(GET_NODE(AE->op));
3394  return GET_NODE(FD->type);
3395 }
3396 
3398 {
3399  if(condition)
3400  {
3401  ports_are_swapped.insert(v);
3402  }
3403  else
3404  {
3405  ports_are_swapped.erase(v);
3406  }
3407 }
3408 
3410 {
3411  const auto statement_index = op_graph->CGetOpNodeInfo(v)->GetNodeId();
3412  return op_binding.at(statement_index);
3413 }
#define GET_NODE(t)
Macro used to hide implementation details when accessing a tree_node from another tree_node...
Definition: tree_node.hpp:343
std::string convert_fp_to_string(std::string num, unsigned long long precision)
convert a real number stored in a string into a string of bits with a given precision ...
tree_nodeRef ptd
ptd field points to the node for the type pointed to.
Definition: tree_node.hpp:3909
static void propagate_memory_parameters(const structural_objectRef src, const structural_managerRef tgt)
Propagates the memory parameters from the source (innermost) module to the target (outermost) one...
Definition: memory.cpp:654
void add_connection(structural_objectRef src, structural_objectRef dest)
Create a connection between a source structural object and a destination structural object...
#define CHANNELS_TYPE_MEM_ACC_N1
#define PRESENT_STATE_PORT_NAME
#define DEBUG_LEVEL_VERY_PEDANTIC
extremely verbose debugging print is performed.
static bool IsUnionType(const tree_nodeConstRef &type)
Return if treenode is an union.
static bool IsComplexType(const tree_nodeConstRef &type)
Return if treenode is a complex.
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;.
TVMValue param[3]
void check_parametrization(structural_objectRef curr_gate)
check the module parametrization
int debug_level
The debug level.
Definition: fu_binding.hpp:121
static std::string name_function(const tree_managerConstRef &tm, const unsigned int index)
Return the name of the function.
#define GET_TYPE(data, vertex_index)
Helper macro returning the type associated with a node.
static unsigned long long AccessedMaximumBitsize(const tree_nodeConstRef &type_node, unsigned long long bitsize)
return the maximum bitsize associated with the elements accessible through type_node ...
refcount< structural_type_descriptor > structural_type_descriptorRef
RefCount type definition of the structural_type_descriptor class structure.
#define PRINT_DBG_MEX(dbgLevel, curDbgLevel, mex)
We are producing a debug version of the program, so the message is printed;.
#define NEXT_STATE_PORT_NAME
generic_objRef get(const vertex v) const
Returns reference to funit object associated with this vertex.
#define FLOAT_EXPR
constant string identifying integer to float conversions
Definition: op_graph.hpp:340
#define DEBUG_LEVEL_PEDANTIC
very verbose debugging print is performed.
#define CHANNELS_TYPE_MEM_ACC_NN
structural_managerRef datapath
Store the datapath description.
Definition: hls.hpp:155
#define START_PORT_NAME
Structure representing the most relevant information about the type of a structural object...
tree_nodeRef getFunctionType(tree_nodeRef exp)
#define CASE_BINARY_EXPRESSION
This macro collects all case labels for binary_expr objects.
Definition: tree_node.hpp:463
bool is_direct_access_memory_unit(unsigned int fu_type) const
return true in case fu type is a memory unit with direct access channels
const ParameterConstRef Param
class containing all the parameters
Definition: hls.hpp:169
const std::string & get_id() const
Return the identifier associated with the structural_object.
std::map< unsigned int, unsigned int > allocation_map
map between functional unit id and number of units allocated
Definition: fu_binding.hpp:94
refcount< fu_binding > fu_bindingRef
RefCount type definition of the fu_binding class structure.
Definition: fu_binding.hpp:402
#define GET_CLASS(obj)
Macro returning the actual type of an object.
char base
This version is stamped on May 10, 2016.
Definition: nussinov.c:24
const structural_objectRef get_circ() const
Get a reference to circ field.
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...
#define CONSTANT_STD
static bool is_a_misaligned_vector(const tree_managerConstRef &TM, const unsigned int index)
Return true if the treenode index is a a misaligned access to a vector data object.
static fu_bindingRef create_fu_binding(const HLS_managerConstRef _HLSMgr, const unsigned int _function_id, const ParameterConstRef _parameters)
create_fu_binding: factory method for fu_binding
Definition: fu_binding.cpp:135
Datastructure to represent a memory symbol in HLS.
mathematical utility function not provided by standard libraries
#define INDENT_OUT_MEX(outLevel, curOutLevel, mex)
generic_objRef get_port(unsigned int var, direction_type dir)
Returns reference to generic object associated to a given variable, for a specific port direction...
unsigned int get_assign(const vertex &v) const
Returns the functional unit assigned to the vertex.
Definition: fu_binding.cpp:242
static tree_nodeConstRef CGetElements(const tree_nodeConstRef &type)
Given an array or a vector return the element type.
#define GET_NAME(data, vertex_index)
Helper macro returning the name associated with a node.
std::pair< std::string, std::string > get_fu_name(unsigned int id) const
Returns the name of the functional unit, associated with the name of the library, given the correspon...
const structural_objectRef get_out_sign() const
Gets structural_object of output signal associated to this object.
const HLS_deviceRef HLS_D
reference to the information representing the target for the synthesis
Definition: hls.hpp:107
structural_objectRef add_gate(const HLS_managerRef HLSMgr, const hlsRef HLS, const technology_nodeRef fu, const std::string &name, const OpVertexSet &ops, structural_objectRef clock_port, structural_objectRef reset_port) const
Add an instance of the current port.
Definition: fu_binding.cpp:267
const funit_obj & operator[](const vertex &v)
Redefinition of the [] operator.
Definition: fu_binding.cpp:203
const std::map< unsigned int, unsigned int > & get_proxy_memory_units() const
return the set of proxy memory units
virtual structural_objectRef find_member(const std::string &id, so_kind type, const structural_objectRef owner) const =0
Return the object named id of a given type which belongs to or it is associated with the object...
#define BUILTIN_WAIT_CALL
constant defining the builtin wait call intrinsic function
Definition: op_graph.hpp:358
virtual void add_to_SM(const HLS_managerRef HLSMgr, const hlsRef HLS, structural_objectRef clock_port, structural_objectRef reset_port)
Instance the functional unit inside the structural representation of the datapath.
Definition: fu_binding.cpp:551
#define MEMORY_TYPE_SYNCHRONOUS_SDS_BUS
#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
#define min(x, y)
virtual void manage_extern_global_port(const HLS_managerRef HLSMgr, const hlsRef HLS, const structural_managerRef SM, structural_objectRef port_in, unsigned int dir, structural_objectRef circuit, unsigned int num)
const tree_managerConstRef TreeM
information about the tree data-structure
Definition: fu_binding.hpp:109
void set_structural_obj(const structural_objectRef &SM_)
Sets structural_object associated to this object.
Class specification of the manager of the technology library data structures.
all objects that need to be stored in memory are allocated on an external memory
std::string NumberToBinaryString(const T number, const size_t precision=0)
Function which print number in binary format.
static technology_nodeRef get_fu(const std::string &fu_name, const HLS_managerConstRef hls_manager)
Returns the technology_node associated with the given operation.
unsigned long long int get_base_address(unsigned int var, unsigned int funId) const
Get the current base address of the given variable.
Definition: memory.cpp:467
std::string get_fu_name(vertex const &v) const
Returns the name of the functional unit.
Definition: fu_binding.cpp:256
#define RETURN_PORT_NAME
#define OUTPUT_LEVEL_MINIMUM
minimum debugging print is performed.
static bool IsEnumType(const tree_nodeConstRef &type)
Return if treenode index is an enumeral type.
bool operator()(const structural_objectRef &a, const structural_objectRef &b) const
#define GET_TYPE_NAME(structural_obj)
Macro returning the string name of a type.
Derived class to add module scheduler, mem_ctrl_parallel and bind correctly the channels.
std::map< std::pair< unsigned int, unsigned int >, generic_objRef > unique_table
map between unit and allocated objects
Definition: fu_binding.hpp:97
#define MEMORY_TYPE_ASYNCHRONOUS
#define TYPE_LOAD
Constant string identifying a memory load operation.
Definition: op_graph.hpp:172
static void write_init(const tree_managerConstRef TreeM, tree_nodeRef var_node, tree_nodeRef init_node, std::vector< std::string > &init_file, const memoryRef mem, unsigned long long element_precision)
A set of operation vertices.
Definition: op_graph.hpp:654
void kill_proxy_function_units(std::map< unsigned int, std::string > &wrapped_units, structural_objectRef curr_gate, std::map< std::string, std::list< structural_objectRef >> &fun_call_sites_rel, std::map< std::string, unsigned int > &reverse_wrapped_units)
Definition: fu_binding.cpp:356
virtual enum kind get_kind() const =0
Virtual function returning the type of the actual class.
#define STR(s)
Macro which performs a lexical_cast to a string.
Auxiliary methods for manipulating string.
static void add_memory_parameter(const structural_managerRef SM, const std::string &name, const std::string &value)
Adds the given memory parameter to the corresponding object.
Definition: memory.cpp:725
void kill_proxy_memory_units(std::map< unsigned int, unsigned int > &memory_units, structural_objectRef curr_gate, std::map< unsigned int, std::list< structural_objectRef >> &var_call_sites_rel, std::map< unsigned int, unsigned int > &reverse_memory_units)
fix port properties for proxy memory ports
Definition: fu_binding.cpp:322
int key[32]
Definition: aes.h:67
#define max
Definition: backprop.h:17
HDLWriter_Language
s_type type
The type of the port or the signal.
port_direction
Enumerative type describing the direction of a port.
bool is_assigned(const vertex &v) const
return true in case the vertex has been previously assigned
Definition: fu_binding.cpp:210
std::string ToString(ActorGraphBackend_Type actor_graph_backend_type)
Header include.
const std::map< unsigned int, std::string > & get_proxy_wrapped_units() const
return the set of proxy wrapped units
void specialize_memory_unit(const HLS_managerRef HLSMgr, const hlsRef HLS, structural_objectRef fu_obj, unsigned int ar, const std::string &base_address, unsigned long long rangesize, bool is_memory_splitted, bool is_sparse_memory, bool is_sds)
Specialize a memory unit.
#define CLOCK_PORT_NAME
standard name for ports
static void fill_array_ref_memory(std::ostream &init_file_a, std::ostream &init_file_b, unsigned int ar, unsigned long long &vec_size, unsigned long long &elts_size, const memoryRef mem, tree_managerConstRef TM, bool is_sds, unsigned long long bitsize_align)
fill the memory of the array ref
bool is_all_regs_without_enable()
return true when all registers are without write enable: pipelining comes for free ...
#define MEMORY_TYPE_SYNCHRONOUS_UNALIGNED
bool registered_inputs
true when the module has registered inputs
Definition: hls.hpp:147
const OpNodeInfoConstRef CGetOpNodeInfo(const vertex node) const
Returns the info associated with a node.
Definition: op_graph.hpp:843
virtual std::string get_kind_text() const =0
Virtual function used to get the string name of a structural_object instance.
std::string convert_to_binary(G _value, unsigned long long precision)
Definition: utility.hpp:110
fu_bindingRef Rfu
Store the refcounted functional unit binding of the operations.
Definition: hls.hpp:121
bool starts_with(const std::string &str, const std::string &pattern)
const OpGraphConstRef op_graph
The operation graph.
Definition: fu_binding.hpp:112
Data structure used to store the register binding of variables.
static unsigned long long Size(const tree_nodeConstRef &tn)
Return the size of a tree object.
std::map< std::pair< unsigned int, unsigned int >, OpVertexSet > operations
reverse map that associated each functional unit with the set of operations that are executed ...
Definition: fu_binding.hpp:100
unsigned int get_proxy_memory_var(const unsigned int fu_name) const
return the var associated with the proxy unit
std::set< Key, Compare, Alloc > OrderedSetStd
Definition: custom_set.hpp:59
void manage_killing_memory_proxies(std::map< unsigned int, structural_objectRef > &mem_obj, std::map< unsigned int, unsigned int > &reverse_memory_units, std::map< unsigned int, std::list< structural_objectRef >> &var_call_sites_rel, const structural_managerRef SM, const hlsRef HLS, unsigned int &_unique_id)
connect proxies with storage components
Definition: fu_binding.cpp:417
static bool IsBooleanType(const tree_nodeConstRef &type)
Return true if the treenode is of bool type.
APInt integer_cst_t
Definition: panda_types.hpp:47
unsigned map[NUM_VERTICES]
Definition: bfs.c:12
unsigned int get_number(unsigned int unit) const
Returns number of functional unit allocated.
Definition: fu_binding.hpp:249
Data structure used to store the interconnection binding of datapath elements.
#define DONE_PORT_NAME
#define CASE_QUATERNARY_EXPRESSION
This macro collects all case labels for quaternary_expr objects.
Definition: tree_node.hpp:574
Control flow graph.
#define CASE_UNARY_EXPRESSION
This macro collects all case labels for unary_expr objects.
Definition: tree_node.hpp:371
all global variables, static variables and strings are allocated on BRAMs
bool is_direct_proxy_memory_unit(unsigned int fu_type) const
return true in case4 fu type is a memory unit accessed through a proxy module
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. ...
const std::string get_path() const
Return a unique identifier of the structural object.
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.
static bool resize_if_busport(unsigned long long bus_size_bitsize, unsigned long long bus_addr_bitsize, unsigned long long bus_data_bitsize, unsigned long long bus_tag_bitsize, structural_objectRef port)
auxiliary function used to resize the bus ports with respect to their associated bus size ...
static integer_cst_t get_integer_cst_value(const integer_cst *ic)
Convert a integer_cst in a long long value.
void update_allocation(unsigned int unit, unsigned int number)
Update number of allocated units.
Definition: fu_binding.cpp:234
int output_level
verbosity level of the class
Definition: hls.hpp:175
#define FD(x)
Definition: aes.c:8
#define index(x, y)
Definition: Keccak.c:74
void bind(const vertex &v, unsigned int unit, unsigned int index=std::numeric_limits< unsigned int >::max())
Binds an operation vertex to a functional unit.
Definition: fu_binding.cpp:173
#define flipflop_AR
flipflop with asynchronous reset
redefinition of set to manage ordered/unordered structures
#define LIBRARY_STD
standard library where all built-in ports are defined.
Datastructure to describe functions allocation in high-level synthesis.
#define TYPE_STORE
Constant string identifying a memory store operation.
Definition: op_graph.hpp:177
#define MEMORY_TYPE_SYNCHRONOUS_SDS
#define PIPE_PARAMETER
boost::graph_traits< graph >::vertex_descriptor vertex
vertex definition.
Definition: graph.hpp:1303
utility function used to read files.
#define PROXY_PREFIX
static bool IsVectorType(const tree_nodeConstRef &type)
Return true if the treenode is a vector.
unsigned offset[NUM_VERTICES+1]
Definition: graph.h:3
virtual ~fu_binding()
Destructor.
constexpr T get_aligned_bitsize(T bitsize)
static void fix_port_properties(structural_objectRef port_i, structural_objectRef cir_port)
copy the port properties from port_i to cir_port
const std::map< unsigned int, std::string > & get_proxy_function_units() const
return the set of proxy function units
static std::string GetFUName(const std::string &fname, const HLS_managerRef HLSMgr)
Return FU used to implement given function.
Definition: functions.cpp:118
#define GET_CONST_NODE(t)
Definition: tree_node.hpp:347
virtual enum so_kind get_kind() const =0
Virtual function used to find the real type of a structural_object instance.
Classes specification of the tree_node data structures.
static std::string NormalizeTypename(const std::string &id)
Return normalized name of types and variables.
This package is used by all HLS packages to manage resource constraints and characteristics.
#define MEMSTORE_STD
This file collects some utility functions and macros.
Base class to allocate memories in high-level synthesis.
#define DEBUG_LEVEL_NONE
no debugging print is performed.
reg_bindingRef Rreg
Store the refcounted register binding of the variables.
Definition: hls.hpp:133
std::list< unsigned int > get_allocation_list() const
Returns the set of allocated unit.
Definition: fu_binding.cpp:221
bool is_proxy_memory_unit(const unsigned int fu_name) const
Returns true if the fu_name is a proxy memory unit.
#define THROW_ERROR(str_expr)
helper function used to throw an error in a standard way
Definition: exceptions.hpp:263
virtual void manage_memory_ports_parallel_chained(const HLS_managerRef HLSMgr, const structural_managerRef SM, const std::list< structural_objectRef > &memory_modules, const structural_objectRef circuit, const hlsRef HLS, unsigned int &unique_id)
struct definition of the pointer_type tree node.
Definition: tree_node.hpp:3896
static const unsigned int UNKNOWN
The value used to identified unknown functional unit.
Definition: fu_binding.hpp:178
Class representing functional units in the datapath.
Definition: funit_obj.hpp:56
void type_resize(unsigned long long new_bit_size)
Just resize the size of the bits of the object.
#define CASE_TYPE_NODES
This macro collects all case labels for type objects.
Definition: tree_node.hpp:581
This file collects some utility functions.
#define MEMSTORE_STDN
void specialise_fu(const HLS_managerRef HLSMgr, const hlsRef HLS, structural_objectRef fu_obj, unsigned int fu, const OpVertexSet &operations, unsigned int ar)
Specialize the functional unit based on variables associated with the corresponding operations...
structural_objectRef add_module_from_technology_library(const std::string &id, const std::string &fu_name, const std::string &library_name, const structural_objectRef owner, const technology_managerConstRef TM)
Create a new object starting from a library component.
void set_ports_are_swapped(vertex v, bool condition)
specify if vertex v have or not its ports swapped
AllocationInformationRef allocation_information
allocation manager. Used to retrieve the string name of the functional units.
Definition: fu_binding.hpp:106
for each memory at maximum n parallel direct accesses and one indirect access
static tree_nodeConstRef GetBaseVariable(const tree_nodeConstRef &mem)
Retrun the base variable of a memory access.
This class describes all classes used to represent a structural object.
virtual bool manage_module_ports(const HLS_managerRef HLSMgr, const hlsRef HLS, const structural_managerRef SM, const structural_objectRef curr_gate, unsigned int num)
bool has_resource_sharing_p
useful to know for automatic pipelining
Definition: fu_binding.hpp:124
const structural_type_descriptorRef & get_typeRef() const
Return the type descriptor of the structural_object.
structural_managerRef control_flow_checker
Store the description of the control flow checker.
Definition: hls.hpp:161
std::string GetPath(std::filesystem::path path)
Definition: fileIO.hpp:140
static void join_merge_split(const structural_managerRef SM, const hlsRef HLS, std::map< structural_objectRef, std::list< structural_objectRef >, jms_sorter > &primary_outs, const structural_objectRef circuit, unsigned int &unique_id)
bool is_dual_port_memory(unsigned int fu_type) const
return true in case the memory has decoupled addresses for writing and reading
std::map< unsigned int, generic_objRef > op_binding
operation binding
Definition: fu_binding.hpp:103
struct definition of the type node structures.
Definition: tree_node.hpp:1318
Class specification of the tree_reindex support class.
#define CASE_FAKE_NODES
This macro collects all case labels for fake or empty nodes.
Definition: tree_node.hpp:635
void set_id(const std::string &s)
Set the identifier associated with the structural_object.
unsigned int get_number_channels(unsigned int fu_name) const
return the number of channels available for the functional unit
static structural_objectRef add_sign(std::string id, structural_objectRef owner, structural_type_descriptorRef sign_type, unsigned int treenode=0)
Create a new signal.
std::string get_string_name(unsigned int fu_name) const
Returns the name of the functional for debug purpose.
bool has_base_address(unsigned int var) const
Check if there is a base address for the given variable.
Definition: memory.cpp:461
Data structure used to store the functional-unit binding of the vertexes.
#define WORK_LIBRARY
working library.
#define INFINITE_UINT
UNSIGNED INT representing infinite.
Definition: utility.hpp:70
virtual void copy(structural_objectRef dest) const
Perform a copy of the structural object.
void manage_killing_function_proxies(std::map< unsigned int, structural_objectRef > &fun_obj, std::map< std::string, unsigned int > &reverse_function_units, std::map< std::string, std::list< structural_objectRef >> &fun_call_sites_rel, const structural_managerRef SM, const hlsRef HLS, unsigned int &_unique_id)
Definition: fu_binding.cpp:480
static void change_port_direction(structural_objectRef port_object, port_o::port_direction pdir, structural_objectRef owner)
Change the direction of the port.
int original[DIMENSION_Y][DIMENSION_X]
Definition: boxfilter.h:1
refcount< structural_object > structural_objectRef
RefCount type definition of the structural_object class structure.
#define MEMCPY_STD
Template borrowed from the ANTLR library by Terence Parr (http://www.jGuru.com - Software rights: htt...
Definition: refcount.hpp:94
static tree_nodeConstRef CGetType(const tree_nodeConstRef &node)
Return the treenode of the type of node.
static bool IsStructType(const tree_nodeConstRef &type)
Return true if treenode is a record.
#define DONE_PORT_NAME_CFC
bool is_return(const unsigned int fu_name) const
Checks if the functional unit implements a RETURN operation.
this class is used to manage the command-line or XML options.
#define CASE_CPP_NODES
This macro collects all case labels for cpp nodes.
Definition: tree_node.hpp:644
#define MULTI_READ_COND_STD
constant strings
static void manage_memory_ports_chained(const structural_managerRef SM, const std::list< structural_objectRef > &memory_modules, const structural_objectRef circuit)
Manage the connections between memory ports.
unsigned int functionId
this is the identifier of the function to be implemented
Definition: hls.hpp:87
#define RESET_PORT_NAME
Wrapper to call graph.
Class implementation of the structural_manager.
bool is_memory_unit(const unsigned int fu_name) const
Returns true if the fu_name is a memory unit.
bool is_indirect_access_memory_unit(unsigned int fu) const
return true in case fu type is a resource unit performing an indirect access to memory ...
This class describes a generic component.
uint32_t sign
OpVertexSet get_operations(unsigned int unit, unsigned int index) const
Return the operations that are executed by the given functional unit.
Definition: fu_binding.cpp:194
unsigned counter[N_THREADS]
Definition: data.c:3
Class managing the functional-unit binding.
Definition: fu_binding.hpp:90
Class specification of the manager for each library.
static void resize_std_port(unsigned long long bitsize_variable, unsigned long long n_elements, int debug_level, structural_objectRef port)
auxiliary function used to resize the standard ports
#define CASE_GIMPLE_NODES
This macro collects all cases labels for gimple nodes.
Definition: tree_node.hpp:700
static integer_cst_t GetConstValue(const tree_nodeConstRef &tn, bool is_signed=true)
Get value from integer constant.
const ParameterConstRef parameters
The set of input parameters.
Definition: fu_binding.hpp:118
bool has_to_be_synthetized(const unsigned int fu_name) const
Checks if the functional unit has to be synthetized.
std::vector< technology_nodeRef > operation_vec
Type definition of a vector of functional_unit.
int fun(float *A, float *invA, float *b, float *x, float *I)
#define GET_INDEX_CONST_NODE(t)
Definition: tree_node.hpp:363
Datastructure to describe functions allocation in high-level synthesis.
Base class for all register into datapath.
#define flipflop_SR
flipflop with synchronous reset
static bool IsPointerType(const tree_nodeConstRef &type)
Return true if treenode index is a pointer.
CustomOrderedSet< vertex > ports_are_swapped
port assignment: ports are swapped predicate
Definition: fu_binding.hpp:115
std::map< unsigned int, unsigned int > get_memory_units() const
Returns the memory units.
Data structure definition for high-level synthesis flow.
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.
conn_bindingRef Rconn
Store the refcounted interconnection of datapath elements.
Definition: hls.hpp:139
Datastructure to represent memory information in high-level synthesis.
#define PROXY_LIBRARY
proxy library
fu_binding(const HLS_managerConstRef _HLSMgr, const unsigned int function_id, const ParameterConstRef parameters)
Constructor.
Definition: fu_binding.cpp:109
unsigned int get_index(const vertex &v) const
Returns the index of functional unit assigned to the vertex.
Definition: fu_binding.cpp:261
uint32_t exp
#define CASE_TERNARY_EXPRESSION
This macro collects all case labels for ternary_expr objects.
Definition: tree_node.hpp:550
Class specification of the manager of the tree structures extracted from the raw file.
refcount< generic_obj > generic_objRef
RefCount definition for generic_obj class.
HLS specialization of generic_device.
#define START_PORT_NAME_CFC
void copy(structural_type_descriptorRef dest)
Method that copies the contents of the current structural_type_descriptorRef into another structural_...
static bool IsRealType(const tree_nodeConstRef &type)
Return true if the treenode is of real type.
#define STD_GET_SIZE(structural_obj)
Macro returning the size of a type.
static structural_objectRef add_sign_vector(std::string id, unsigned int n_signs, structural_objectRef owner, structural_type_descriptorRef sign_type, unsigned int treenode=0)
static void get_array_dim_and_bitsize(const tree_managerConstRef &TM, const unsigned int index, std::vector< unsigned long long > &dims, unsigned long long &elts_bitsize)
Return the dimension of the array.
#define CASE_PRAGMA_NODES
This macro collects all case labels for pragma objects.
Definition: tree_node.hpp:610
#define THROW_ASSERT(cond, str_expr)
helper function used to check an assert and if needed to throw an error in a standard way ...
Definition: exceptions.hpp:289

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