PandA-2024.02
HDL_manager.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  */
44 #include "HDL_manager.hpp"
46 
48 #include "config_HAVE_ASSERTS.hpp" // for HAVE_ASSERTS
49 #include "config_HAVE_EXPERIMENTAL.hpp"
50 #include "config_HAVE_FLOPOCO.hpp"
51 #include "config_PACKAGE_BUGREPORT.hpp"
52 #include "config_PACKAGE_NAME.hpp"
53 #include "config_PACKAGE_VERSION.hpp"
54 
55 #include "NP_functionality.hpp"
56 #include "structural_manager.hpp"
57 #include "structural_objects.hpp"
58 
59 #include "generic_device.hpp"
60 
61 #if HAVE_FLOPOCO
62 #include "flopoco_wrapper.hpp"
63 #endif
64 
65 #include "Parameter.hpp"
66 #include "dbgPrintHelper.hpp"
67 #include "exceptions.hpp"
68 
69 #include <boost/tokenizer.hpp>
70 #include <fstream>
71 #include <iosfwd>
72 
74 #include <boost/algorithm/string.hpp>
75 #include <boost/algorithm/string/case_conv.hpp>
76 
78 #include "design_flow_manager.hpp"
79 
81 #include "VHDL_writer.hpp"
82 #include "verilog_writer.hpp"
83 
85 #include "hls_manager.hpp"
86 
88 #include "custom_map.hpp"
89 #include "custom_set.hpp"
90 #include <utility>
91 
93 #include "fileIO.hpp"
94 #include "string_manipulation.hpp" // for GET_CLASS
95 #include "technology_manager.hpp"
96 #include "technology_node.hpp"
97 
99  const ParameterConstRef _parameters)
100  : HLSMgr(_HLSMgr),
101  device(_device),
102  TM(_device->get_technology_manager()),
103 #if HAVE_FLOPOCO
104  flopo_wrap(new flopoco_wrapper(_parameters->getOption<int>(OPT_debug_level),
105  _device->get_parameter<std::string>("family"))),
106 #endif
107  SM(_SM),
108  parameters(_parameters),
109  debug_level(_parameters->get_class_debug_level(GET_CLASS(*this)))
110 {
111 }
112 
114  const ParameterConstRef _parameters)
115  : HLSMgr(_HLSMgr),
116  device(_device),
117  TM(_device->get_technology_manager()),
118 #if HAVE_FLOPOCO
119  flopo_wrap(new flopoco_wrapper(_parameters->getOption<int>(OPT_debug_level),
120  _device->get_parameter<std::string>("family"))),
121 #endif
122  parameters(_parameters),
123  debug_level(_parameters->get_class_debug_level(GET_CLASS(*this)))
124 {
125 }
126 
127 HDL_manager::~HDL_manager() = default;
128 
129 std::string HDL_manager::write_components(const std::string& filename, HDLWriter_Language language,
130  const std::list<structural_objectRef>& components,
131  std::list<std::string>& aux_files) const
132 {
134 
135  writer->write_comment(std::string("\n"));
136  writer->write_comment(std::string("Politecnico di Milano\n"));
137  writer->write_comment(std::string("Code created using ") + PACKAGE_NAME + " - " + parameters->PrintVersion() +
138  std::string(" - Date " + TimeStamp::GetCurrentTimeStamp()) + "\n");
139  if(parameters->isOption(OPT_cat_args))
140  {
141  writer->write_comment(parameters->getOption<std::string>(OPT_program_name) +
142  " executed with: " + parameters->getOption<std::string>(OPT_cat_args) + "\n");
143  }
144 
145  writer->write_comment("\n");
146  writer->write_comment(std::string("Send any bug to: ") + PACKAGE_BUGREPORT + "\n");
147  writer->WriteLicense();
148 
150  writer->write_header();
151 
152  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Writing components");
154  for(const auto& c : components)
155  {
156  NP_functionalityRef npf = GetPointer<module>(c)->get_NP_functionality();
158  {
159  write_module(writer, c, aux_files);
160  continue;
161  }
162  else if(npf and (npf->get_NP_functionality(NP_functionality::VERILOG_FILE_PROVIDED) != "" ||
164  {
166  language == HDLWriter_Language::VERILOG)
167  {
168  std::string filename_HDL = GetPath(npf->get_NP_functionality(NP_functionality::VERILOG_FILE_PROVIDED));
169  if(std::find(aux_files.begin(), aux_files.end(), filename_HDL) == aux_files.end())
170  {
171  aux_files.push_back(filename_HDL);
172  }
173  }
175  language == HDLWriter_Language::VHDL)
176  {
177  std::string filename_HDL = GetPath(npf->get_NP_functionality(NP_functionality::VHDL_FILE_PROVIDED));
178  if(std::find(aux_files.begin(), aux_files.end(), filename_HDL) == aux_files.end())
179  {
180  aux_files.push_back(filename_HDL);
181  }
182  }
184  {
185  std::string filename_HDL = GetPath(npf->get_NP_functionality(NP_functionality::VERILOG_FILE_PROVIDED));
186  if(std::find(aux_files.begin(), aux_files.end(), filename_HDL) == aux_files.end())
187  {
188  aux_files.push_back(filename_HDL);
189  }
190  }
192  {
193  std::string filename_HDL = GetPath(npf->get_NP_functionality(NP_functionality::VHDL_FILE_PROVIDED));
194  if(std::find(aux_files.begin(), aux_files.end(), filename_HDL) == aux_files.end())
195  {
196  aux_files.push_back(filename_HDL);
197  }
198  }
199  else
200  {
201  THROW_UNREACHABLE("unexpected condition");
202  }
203  continue;
204  }
205  std::string library = TM->get_library(c->get_typeRef()->id_type);
206  structural_objectRef obj = c;
208  if(library.size())
209  {
211  "---Component " + c->get_typeRef()->id_type + " is in library " + library);
212  technology_nodeRef tn = TM->get_fu(c->get_typeRef()->id_type, library);
213  if(GetPointer<functional_unit>(tn))
214  {
215  THROW_ASSERT(GetPointer<functional_unit>(tn)->CM, tn->get_name());
216  obj = GetPointer<functional_unit>(tn)->CM->get_circ();
217  }
218  else if(GetPointer<functional_unit_template>(tn))
219  {
220  technology_nodeRef FU = GetPointer<functional_unit_template>(tn)->FU;
221  obj = GetPointer<functional_unit>(FU)->CM->get_circ();
222  }
223  else
224  {
225  THROW_ERROR("unexpected condition");
226  }
227  }
228  write_module(writer, obj, aux_files);
229  }
230  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Written components");
231  auto filename_ext = GetPath(filename + writer->get_extension());
232  writer->WriteFile(filename_ext);
233  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Written " + filename_ext);
234  return filename_ext;
235 }
236 
237 void HDL_manager::write_components(const std::string& filename, const std::list<structural_objectRef>& components,
238  std::list<std::string>& hdl_files, std::list<std::string>& aux_files, bool tb)
239 {
240  bool multiFileP =
241  !tb && parameters->IsParameter("enable-multifiles") && parameters->GetParameter<bool>("enable-multifiles");
243  auto language = static_cast<HDLWriter_Language>(parameters->getOption<unsigned int>(OPT_writer_language));
244 
245  PRINT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, " Everything seems ok. Let's start with the real job.");
246 
248  if(language == HDLWriter_Language::VERILOG)
249  {
251  }
252  else if(language == HDLWriter_Language::SYSTEM_VERILOG)
253  {
255  }
256  else if(language == HDLWriter_Language::VHDL)
257  {
259  }
260  else
261  {
262  THROW_ERROR("Language not supported");
263  }
264 
266  std::map<HDLWriter_Language, std::list<structural_objectRef>> component_language;
267  for(const auto& component : components)
268  {
269  auto* mod = GetPointer<module>(component);
270  THROW_ASSERT(mod, "Expected a component object");
271 
272  unsigned int n_elements = mod->get_internal_objects_size();
273 
274  const NP_functionalityRef np = mod->get_NP_functionality();
275 
276  if(n_elements || (np && (np->exist_NP_functionality(type) ||
277  (language == HDLWriter_Language::VERILOG &&
279  (language == HDLWriter_Language::VHDL &&
281  {
282  component_language[language].push_back(component);
283  }
284  else
285  {
286  if(np and
288  {
289  component_language[language].push_back(component);
290  }
293  {
294  if(!parameters->getOption<bool>(OPT_mixed_design))
295  {
296  THROW_ERROR("VHDL implementation of " + component->get_path() + " is not available");
297  }
298 #if HAVE_EXPERIMENTAL
299  else
300  {
301  const auto module_type = mod->get_typeRef()->id_type;
302  const auto fu = GetPointer<functional_unit>(TM->get_fu(module_type, TM->get_library(module_type)));
303  if(module_type.find("gimple_asm") == std::string::npos and
304  module_type.find("__builtin_trap") == std::string::npos and
305  module_type.find("return_value_mm_register") == std::string::npos and
306  module_type.find("notify_caller_minimal") == std::string::npos and
307  module_type.find("memory_mapped_register") == std::string::npos and
308  module_type.find("status_register") == std::string::npos and
309  module_type.find("__builtin_wait_call") == std::string::npos and
310  module_type.find("PROXY_CTRL") == std::string::npos and
311  module_type.find("PRINTF") == std::string::npos and
312  module_type.find("trunc_") == std::string::npos and
313  module_type.find("__builtin_memstore") == std::string::npos and module_type != "ui_mult_expr_FU" and
314  module_type != "mult_expr_FU" and module_type.find("ADDRESS_DECODING_LOGIC") == std::string::npos and
315  module_type.find("BRAM") == std::string::npos and module_type != "STD_N21_BYTEMUX" and
316  module_type != "STD_LIVE_VALUE_TABLE" and module_type.find("MEMORY_CTRL") == std::string::npos and
317  module_type != "register_SARSE" and module_type.find("DISTRAM") == std::string::npos and
318  (not fu or (fu->memory_type == "" or fu->memory_ctrl_type == "")))
319  {
320  // THROW_UNREACHABLE("VHDL implementation of " + module_type + " not found");
321  }
322  }
323 #endif
324  component_language[HDLWriter_Language::VERILOG].push_back(component);
325  }
329  {
330  if(!parameters->getOption<bool>(OPT_mixed_design))
331  {
332  THROW_ERROR("Verilog implementation of " + component->get_path() + " is not available");
333  }
334  else
335  {
336  THROW_WARNING(component->get_path() + " is available only in VHDL");
337  }
338  component_language[HDLWriter_Language::VHDL].push_back(component);
339  }
341  {
342  component_language[HDLWriter_Language::SYSTEM_VERILOG].push_back(component);
343  }
344  else
345  {
346  THROW_ERROR("Language not supported! Module " + mod->get_path());
347  }
348  }
349  }
350 
352  for(auto l = component_language.begin(); l != component_language.end(); ++l)
353  {
354  if(language == l->first)
355  {
356  continue;
357  }
358  if(multiFileP)
359  {
361  for(const auto& c : component_language[l->first])
362  {
363  std::list<structural_objectRef> singletonList;
364  singletonList.push_back(c);
365  std::string mod_name = convert_to_identifier(writer.get(), GET_TYPE_NAME(c));
366  std::string generated_filename = write_components(GetPath(mod_name), l->first, singletonList, aux_files);
367  aux_files.push_back(generated_filename);
368  }
369  }
370  else
371  {
372  std::string generated_filename = write_components(filename, l->first, component_language[l->first], aux_files);
373  aux_files.push_back(generated_filename);
374  }
375  }
376 
377  if(multiFileP)
378  {
380 
381  auto counter = component_language[language].size();
382  for(const auto& c : component_language[language])
383  {
384  --counter;
385  std::list<structural_objectRef> singletonList;
386  singletonList.push_back(c);
387  std::string mod_name = convert_to_identifier(writer.get(), GET_TYPE_NAME(c));
388  if(counter == 0)
389  {
390  mod_name = filename;
391  }
392  std::string generated_filename = write_components(GetPath(mod_name), language, singletonList, aux_files);
393  if(counter == 0)
394  {
395  hdl_files.push_back(generated_filename);
396  }
397  else
398  {
399  aux_files.push_back(generated_filename);
400  }
401  }
402  }
403  else
404  {
405  std::string complete_filename = write_components(filename, language, component_language[language], aux_files);
407  hdl_files.push_back(complete_filename);
408  }
409 
410 #if HAVE_FLOPOCO
411  const std::string flopoco_common = flopo_wrap->writeVHDLcommon();
413  if(flopoco_common != "")
414  {
415  aux_files.push_back(flopoco_common);
416  }
417 #endif
418 }
419 
420 void HDL_manager::hdl_gen(const std::string& filename, const std::list<structural_objectRef>& cirs,
421  std::list<std::string>& hdl_files, std::list<std::string>& aux_files, bool tb)
422 {
424  " compute the list of components for which a structural description exists");
426  std::list<structural_objectRef> list_of_com;
427  for(const auto& cir : cirs)
428  {
429  get_post_order_structural_components(cir, list_of_com);
430  }
431  if(list_of_com.empty())
432  {
433 #if HAVE_ASSERTS
434  for(const auto& cir : cirs)
435  {
436  THROW_ASSERT(GetPointer<module>(cir), "Expected a component or a channel");
437  THROW_ASSERT(GetPointer<module>(cir)->get_NP_functionality(), "Structural empty description received");
438  }
439 #endif
440  return;
441  }
442 
444  write_components(filename, list_of_com, hdl_files, aux_files, tb);
445 }
446 
451 {
452  // predicate function
454  {
456  }
457  find_eq_module(const language_writer* _lan, const structural_objectRef& _target) : lan(_lan), target(_target)
458  {
459  THROW_ASSERT(_target, "structural_objectRef must exist");
460  }
461 
462  private:
465 };
466 
468 {
470  auto* mod_inst = GetPointer<module>(cir);
471  THROW_ASSERT(mod_inst, "Expected a component or a channel");
472  const NP_functionalityRef& np = mod_inst->get_NP_functionality();
473  if(np)
474  {
477  }
478  return false;
479 }
480 
482  std::list<structural_objectRef>& list_of_com) const
483 {
484  switch(cir->get_kind())
485  {
486  case component_o_K:
487  case channel_o_K:
488  {
489  auto* mod = GetPointer<module>(cir);
490  unsigned int n_elements = mod->get_internal_objects_size();
491  for(unsigned int i = 0; i < n_elements; i++)
492  {
493  switch(mod->get_internal_object(i)->get_kind())
494  {
495  case channel_o_K:
496  case component_o_K:
497  {
498  if(!mod->get_internal_object(i)->get_black_box() &&
499  !TM->IsBuiltin(GET_TYPE_NAME(mod->get_internal_object(i))))
500  {
501  get_post_order_structural_components(mod->get_internal_object(i), list_of_com);
502  }
503  break;
504  }
505  case constant_o_K:
506  case signal_vector_o_K:
507  case signal_o_K:
508  case bus_connection_o_K:
509  break;
510  case action_o_K:
511  case data_o_K:
512  case event_o_K:
513  case port_o_K:
514  case port_vector_o_K:
515  default:
516  THROW_ERROR("Structural object not foreseen: " +
517  std::string(mod->get_internal_object(i)->get_kind_text()));
518  }
519  }
520  const auto NPF = mod->get_NP_functionality();
521  if(NPF && NPF->exist_NP_functionality(NP_functionality::IP_COMPONENT))
522  {
523  const auto ip_cores = NPF->get_NP_functionality(NP_functionality::IP_COMPONENT);
524  const auto ip_cores_list = string_to_container<std::vector<std::string>>(ip_cores, ",");
525  for(const auto& ip_core : ip_cores_list)
526  {
527  const auto ip_core_vec = string_to_container<std::vector<std::string>>(ip_core, ":");
528  if(ip_core_vec.size() < 1 || ip_core_vec.size() > 2)
529  {
530  THROW_ERROR("Malformed IP component definition \"" + ip_core + "\"");
531  }
532  std::string library, component_name;
533  if(ip_core_vec.size() == 2)
534  {
535  library = ip_core_vec[0];
536  component_name = ip_core_vec[1];
537  }
538  else
539  {
540  component_name = ip_core_vec[0];
541  library = TM->get_library(component_name);
542  }
543  const auto tn = TM->get_fu(component_name, library);
544  structural_objectRef core_cir;
545  if(tn->get_kind() == functional_unit_K)
546  {
547  core_cir = GetPointer<functional_unit>(tn)->CM->get_circ();
548  }
549  else if(tn->get_kind() == functional_unit_template_K &&
550  GetPointer<functional_unit>(GetPointer<functional_unit_template>(tn)->FU))
551  {
552  core_cir = GetPointer<functional_unit>(GetPointer<functional_unit_template>(tn)->FU)->CM->get_circ();
553  }
554  else
555  {
556  THROW_ERROR("Unexpected pattern");
557  }
558  THROW_ASSERT(core_cir, "unexpected condition");
559  get_post_order_structural_components(core_cir, list_of_com);
560  auto fo = std::find_if(list_of_com.begin(), list_of_com.end(), find_eq_module(nullptr, core_cir));
561  if(fo == list_of_com.end())
562  {
563  list_of_com.push_back(core_cir);
564  }
565  }
566  }
567  auto fo = std::find_if(list_of_com.begin(), list_of_com.end(), find_eq_module(nullptr, cir));
568  if(fo == list_of_com.end())
569  {
570  list_of_com.push_back(cir);
571  }
572  break;
573  }
574  case action_o_K:
575  case bus_connection_o_K:
576  case constant_o_K:
577  case data_o_K:
578  case event_o_K:
579  case port_o_K:
580  case port_vector_o_K:
581  case signal_o_K:
582  case signal_vector_o_K:
583  default:
584  THROW_ERROR("Structural object not foreseen");
585  }
586 }
587 
588 void HDL_manager::io_signal_fix_ith(const language_writerRef writer, const structural_objectRef po, bool& lspf) const
589 {
590  THROW_ASSERT(po && po->get_kind() == port_o_K, "Expected a port; got something different");
591  auto* p = GetPointer<port_o>(po);
592  structural_objectRef po_owner = po->get_owner();
593  if(po_owner->get_kind() == port_vector_o_K)
594  {
595  po_owner = po_owner->get_owner();
596  }
597  for(unsigned int j = 0; j < p->get_connections_size(); j++)
598  {
599  if(p->get_connection(j)->get_kind() == signal_o_K and
600  (p->get_connection(j)->get_owner() == po_owner or
601  (p->get_connection(j)->get_owner()->get_kind() == signal_vector_o_K and
602  p->get_connection(j)->get_owner()->get_owner() == po_owner)))
603  {
604  if(!lspf)
605  {
606  writer->write_comment("io-signal post fix\n");
607  lspf = true;
608  }
609  writer->write_io_signal_post_fix(po, p->get_connection(j));
610  }
611  if(p->get_connection(j)->get_kind() == constant_o_K and p->get_connection(j)->get_owner() == po_owner)
612  {
613  if(!lspf)
614  {
615  writer->write_comment("io-signal post fix\n");
616  lspf = true;
617  }
618  writer->write_io_signal_post_fix(po, p->get_connection(j));
619  }
620  }
621 }
622 
624  bool& lspf) const
625 {
626  THROW_ASSERT(po && po->get_kind() == port_vector_o_K, "Expected a port; got something different");
627  auto* p = GetPointer<port_o>(po);
628  THROW_ASSERT(p, "Expected a port; got something different");
629  structural_objectRef po_owner = po->get_owner();
630  for(unsigned int j = 0; j < p->get_connections_size(); j++)
631  {
632  if(p->get_connection(j)->get_kind() == signal_vector_o_K and p->get_connection(j)->get_owner() == po_owner)
633  {
634  if(!lspf)
635  {
636  writer->write_comment("io-signal post fix\n");
637  lspf = true;
638  }
639  writer->write_io_signal_post_fix_vector(po, p->get_connection(j));
640  }
641  if(p->get_connection(j)->get_kind() == constant_o_K and p->get_connection(j)->get_owner() == po_owner)
642  {
643  THROW_ERROR("unexpected condition");
644  }
645  }
646 }
647 
649  std::list<std::string>& aux_files) const
650 {
651  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Writing module " + GET_TYPE_NAME(cir));
652  const module* mod = GetPointer<module>(cir);
653  THROW_ASSERT(mod, "Expected a module got something of different");
654 
655  const NP_functionalityRef& np = mod->get_NP_functionality();
657  {
658  PRINT_DBG_MEX(DEBUG_LEVEL_PARANOIC, this->debug_level, "FloPoCo compliant module: " + mod->get_id());
659  this->write_flopoco_module(cir, aux_files);
660  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Written module " + cir->get_path());
661  return;
662  }
663 
665  writer->write_comment(mod->get_description() + "\n");
666  writer->write_comment(mod->get_copyright() + "\n");
667  writer->write_comment("Author(s): " + mod->get_authors() + "\n");
668  writer->write_comment("License: " + mod->get_license() + "\n");
669 
671  writer->write_library_declaration(cir);
672 
673  writer->write_module_declaration(cir);
674 
675  writer->write_module_parametrization_decl(cir);
676 
677  writer->write_port_decl_header();
678 
680  if(mod->get_in_port_size())
681  {
682  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Writing input port declaration");
683  writer->write_comment("IN\n");
684  for(unsigned int i = 0; i < mod->get_in_port_size(); i++)
685  {
687  "-->Writing port declaration " + mod->get_in_port(i)->get_id() + " of type " +
688  mod->get_in_port(i)->get_kind_text());
689  if(i == mod->get_in_port_size() - 1 && !mod->get_out_port_size() && !mod->get_in_out_port_size() &&
690  !mod->get_gen_port_size())
691  {
692  writer->write_port_declaration(mod->get_in_port(i), true);
693  }
694  else
695  {
696  writer->write_port_declaration(mod->get_in_port(i), false);
697  }
699  }
700  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Written input port declaration");
701  }
702  if(mod->get_out_port_size())
703  {
704  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Writing output port declaration");
705  writer->write_comment("OUT\n");
706  for(unsigned int i = 0; i < mod->get_out_port_size(); i++)
707  {
708  if(i == mod->get_out_port_size() - 1 && !mod->get_in_out_port_size() && !mod->get_gen_port_size())
709  {
710  writer->write_port_declaration(mod->get_out_port(i), true);
711  }
712  else
713  {
714  writer->write_port_declaration(mod->get_out_port(i), false);
715  }
716  }
717  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Written output port declaration");
718  }
719  if(mod->get_in_out_port_size())
720  {
721  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Writing inout port declaration");
722  writer->write_comment("INOUT\n");
723  for(unsigned int i = 0; i < mod->get_in_out_port_size(); i++)
724  {
725  if(i == mod->get_in_out_port_size() - 1 && !mod->get_gen_port_size())
726  {
727  writer->write_port_declaration(mod->get_in_out_port(i), true);
728  }
729  else
730  {
731  writer->write_port_declaration(mod->get_in_out_port(i), false);
732  }
733  }
734  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Written inout port declaration");
735  }
736 
737  if(mod->get_gen_port_size())
738  {
739  writer->write_comment("Ports\n");
740  for(unsigned int i = 0; i < mod->get_gen_port_size(); i++)
741  {
742  if(i == mod->get_gen_port_size() - 1)
743  {
744  writer->write_port_declaration(mod->get_gen_port(i), true);
745  }
746  else
747  {
748  writer->write_port_declaration(mod->get_gen_port(i), false);
749  }
750  }
751  }
752 
753  writer->write_port_decl_tail();
754 
756  writer->write_module_internal_declaration(cir);
757 
760  unsigned int n_elements = mod->get_internal_objects_size();
761  if(n_elements)
762  {
763  writer->write_comment("Component and signal declarations\n");
764 
765  std::list<std::pair<std::string, structural_objectRef>> cs;
766  for(unsigned int i = 0; i < n_elements; i++)
767  {
768  switch(mod->get_internal_object(i)->get_kind())
769  {
770  case constant_o_K:
771  {
772  continue;
773  }
774  case channel_o_K:
775  case component_o_K:
776  {
777  break;
778  }
779  case signal_vector_o_K:
780  case signal_o_K:
781  {
782  cs.push_back(std::make_pair(mod->get_internal_object(i)->get_id(), mod->get_internal_object(i)));
783  continue;
784  }
785  case bus_connection_o_K:
786  THROW_ERROR("Bus connection not yes supported.");
787  case action_o_K:
788  case data_o_K:
789  case event_o_K:
790  case port_o_K:
791  case port_vector_o_K:
792  default:; // do nothing
793  }
794  writer->write_component_declaration(mod->get_internal_object(i));
795  }
796  cs.sort();
797 
798  for(auto& c : cs)
799  {
800  writer->write_signal_declaration(c.second);
801  }
802 
803  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Writing module instantiation of " + cir->get_id());
804 
806  writer->write_module_definition_begin(cir);
807 
808  cs.clear();
810  for(unsigned int i = 0; i < n_elements; i++)
811  {
812  switch(mod->get_internal_object(i)->get_kind())
813  {
814  case channel_o_K:
815  case component_o_K:
816  {
817  cs.push_back(std::make_pair(mod->get_internal_object(i)->get_id(), mod->get_internal_object(i)));
818  break;
819  }
820  case action_o_K:
821  case bus_connection_o_K:
822  case constant_o_K:
823  case data_o_K:
824  case event_o_K:
825  case port_o_K:
826  case port_vector_o_K:
827  case signal_o_K:
828  case signal_vector_o_K:
829  default:; // do nothing
830  }
831  }
832  cs.sort();
833 
834  for(auto& c : cs)
835  {
836  structural_objectRef obj = c.second;
837  if(TM->IsBuiltin(GET_TYPE_NAME(obj)))
838  {
839  writer->WriteBuiltin(obj);
840  }
841  else
842  {
843  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Writing module instance " + obj->get_id());
844  writer->write_module_instance_begin(obj, get_mod_typename(writer.get(), obj), true);
846  auto* mod_inst = GetPointer<module>(obj);
847  bool first_port_analyzed = false;
850  if(writer->has_output_prefix())
851  {
852  if(mod_inst->get_out_port_size())
853  {
854  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Writing output ports binding");
855  // writer->write_comment("OUT binding\n");
856  for(unsigned int i = 0; i < mod_inst->get_out_port_size(); i++)
857  {
859  "-->Writing port binding of " + mod_inst->get_out_port(i)->get_id());
860  if(mod_inst->get_out_port(i)->get_kind() == port_o_K)
861  {
862  const structural_objectRef object_bounded =
863  GetPointer<port_o>(mod_inst->get_out_port(i))->find_bounded_object(cir);
864  if(!object_bounded)
865  {
867  "<--Skipped " + mod_inst->get_out_port(i)->get_path());
868  continue;
869  }
870  writer->write_port_binding(mod_inst->get_out_port(i), object_bounded, first_port_analyzed);
871  }
872  else
873  {
874  writer->write_vector_port_binding(mod_inst->get_out_port(i), first_port_analyzed);
875  }
876  first_port_analyzed = true;
878  "<--Written port binding of " + mod_inst->get_out_port(i)->get_id());
879  }
880  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Written output ports binding");
881  }
882  }
883  if(mod_inst->get_in_port_size())
884  {
885  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Writing input ports binding");
886  // writer->write_comment("IN binding\n");
887  for(unsigned int i = 0; i < mod_inst->get_in_port_size(); i++)
888  {
890  "-->Writing port binding of " + mod_inst->get_in_port(i)->get_id());
891  if(mod_inst->get_in_port(i)->get_kind() == port_o_K)
892  {
893  const structural_objectRef object_bounded =
894  GetPointer<port_o>(mod_inst->get_in_port(i))->find_bounded_object(cir);
896  "---Bounded object is " +
897  (object_bounded ? object_bounded->get_path() : "nothing"));
898  writer->write_port_binding(mod_inst->get_in_port(i), object_bounded, first_port_analyzed);
899  }
900  else
901  {
902  writer->write_vector_port_binding(mod_inst->get_in_port(i), first_port_analyzed);
903  }
904  first_port_analyzed = true;
906  "<--Written port binding of " + mod_inst->get_in_port(i)->get_id());
907  }
908  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Written input ports binding");
909  }
910  if(mod_inst->get_in_out_port_size())
911  {
912  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Writing inout ports binding");
913  // writer->write_comment("INOUT binding\n");
914  for(unsigned int i = 0; i < mod_inst->get_in_out_port_size(); i++)
915  {
916  if(mod_inst->get_in_out_port(i)->get_kind() == port_o_K)
917  {
918  const structural_objectRef object_bounded =
919  GetPointer<port_o>(mod_inst->get_in_out_port(i))->find_bounded_object();
920  if(!object_bounded)
921  {
922  continue;
923  }
924  writer->write_port_binding(mod_inst->get_in_out_port(i), object_bounded, first_port_analyzed);
925  }
926  else
927  {
928  writer->write_vector_port_binding(mod_inst->get_in_out_port(i), first_port_analyzed);
929  }
930  first_port_analyzed = true;
931  }
932  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Written inout ports binding");
933  }
934  if(mod_inst->get_gen_port_size())
935  {
936  // writer->write_comment("Ports binding\n");
937  for(unsigned int i = 0; i < mod_inst->get_gen_port_size(); i++)
938  {
939  if(mod_inst->get_gen_port(i)->get_kind() == port_o_K)
940  {
941  writer->write_port_binding(mod_inst->get_gen_port(i),
942  GetPointer<port_o>(mod_inst->get_gen_port(i))->find_bounded_object(),
943  first_port_analyzed);
944  }
945  else
946  {
947  writer->write_vector_port_binding(mod_inst->get_gen_port(i), first_port_analyzed);
948  }
949  first_port_analyzed = true;
950  }
951  }
952  if(!writer->has_output_prefix())
953  {
954  if(mod_inst->get_out_port_size())
955  {
956  // writer->write_comment("OUT binding\n");
957  for(unsigned int i = 0; i < mod_inst->get_out_port_size(); i++)
958  {
959  if(mod_inst->get_out_port(i)->get_kind() == port_o_K)
960  {
961  const structural_objectRef object_bounded =
962  GetPointer<port_o>(mod_inst->get_out_port(i))->find_bounded_object();
963  if(!object_bounded)
964  {
965  continue;
966  }
967  writer->write_port_binding(mod_inst->get_out_port(i), object_bounded, first_port_analyzed);
968  }
969  else
970  {
971  writer->write_vector_port_binding(mod_inst->get_out_port(i), first_port_analyzed);
972  }
973  first_port_analyzed = true;
974  }
975  }
976  }
977 
978  writer->write_module_instance_end(obj);
979  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Written module instance " + obj->get_id());
980  }
981  }
982 
984  bool lspf = false;
985  if(mod->get_in_port_size())
986  {
987  for(unsigned int i = 0; i < mod->get_in_port_size(); i++)
988  {
989  if(mod->get_in_port(i)->get_kind() == port_o_K)
990  {
991  io_signal_fix_ith(writer, mod->get_in_port(i), lspf);
992  }
993  else
994  {
995  io_signal_fix_ith_vector(writer, mod->get_in_port(i), lspf);
996  auto* pv = GetPointer<port_o>(mod->get_in_port(i));
997  for(unsigned int k = 0; k < pv->get_ports_size(); k++)
998  {
999  io_signal_fix_ith(writer, pv->get_port(k), lspf);
1000  }
1001  }
1002  }
1003  }
1004  if(mod->get_out_port_size())
1005  {
1006  for(unsigned int i = 0; i < mod->get_out_port_size(); i++)
1007  {
1008  if(mod->get_out_port(i)->get_kind() == port_o_K)
1009  {
1010  io_signal_fix_ith(writer, mod->get_out_port(i), lspf);
1011  }
1012  else
1013  {
1014  io_signal_fix_ith_vector(writer, mod->get_out_port(i), lspf);
1015  auto* pv = GetPointer<port_o>(mod->get_out_port(i));
1016  for(unsigned int k = 0; k < pv->get_ports_size(); k++)
1017  {
1018  io_signal_fix_ith(writer, pv->get_port(k), lspf);
1019  }
1020  }
1021  }
1022  }
1023  if(mod->get_in_out_port_size())
1024  {
1025  for(unsigned int i = 0; i < mod->get_in_out_port_size(); i++)
1026  {
1027  if(mod->get_in_out_port(i)->get_kind() == port_o_K)
1028  {
1029  io_signal_fix_ith(writer, mod->get_in_out_port(i), lspf);
1030  }
1031  else
1032  {
1033  io_signal_fix_ith_vector(writer, mod->get_in_out_port(i), lspf);
1034  auto* pv = GetPointer<port_o>(mod->get_in_out_port(i));
1035  for(unsigned int k = 0; k < pv->get_ports_size(); k++)
1036  {
1037  io_signal_fix_ith(writer, pv->get_port(k), lspf);
1038  }
1039  }
1040  }
1041  }
1043  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Written module instantiation of " + cir->get_id());
1044  }
1046  else if(is_fsm(cir))
1047  {
1048  THROW_ASSERT(np,
1049  "Behavior not expected: " + HDL_manager::convert_to_identifier(writer.get(), GET_TYPE_NAME(cir)));
1050  THROW_ASSERT(
1052  "Cannot exist both FSM and fsm_cs for the same function");
1053  std::string fsm_desc;
1055  {
1057  }
1058  else
1059  {
1061  }
1062  THROW_ASSERT(fsm_desc != "",
1063  "Behavior not expected: " + HDL_manager::convert_to_identifier(writer.get(), GET_TYPE_NAME(cir)));
1064  write_fsm(writer, cir, fsm_desc);
1065  }
1066  else if(np)
1067  {
1069  {
1070  std::string ip_cores = np->get_NP_functionality(NP_functionality::IP_COMPONENT);
1071  std::vector<std::string> ip_cores_list = string_to_container<std::vector<std::string>>(ip_cores, ",");
1072  for(const auto& ip_core : ip_cores_list)
1073  {
1074  std::vector<std::string> ip_core_vec = string_to_container<std::vector<std::string>>(ip_core, ":");
1075  if(ip_core_vec.size() < 1 or ip_core_vec.size() > 2)
1076  {
1077  THROW_ERROR("Malformed IP component definition \"" + ip_core + "\"");
1078  }
1079  std::string library, component_name;
1080  if(ip_core_vec.size() == 2)
1081  {
1082  library = ip_core_vec[0];
1083  component_name = ip_core_vec[1];
1084  }
1085  else
1086  {
1087  component_name = ip_core_vec[0];
1088  library = TM->get_library(component_name);
1089  }
1090  technology_nodeRef tn = TM->get_fu(component_name, library);
1091  structural_objectRef core_cir;
1092  if(tn->get_kind() == functional_unit_K)
1093  {
1094  core_cir = GetPointer<functional_unit>(tn)->CM->get_circ();
1095  }
1096  else if(tn->get_kind() == functional_unit_template_K &&
1097  GetPointer<functional_unit>(GetPointer<functional_unit_template>(tn)->FU))
1098  {
1099  core_cir = GetPointer<functional_unit>(GetPointer<functional_unit_template>(tn)->FU)->CM->get_circ();
1100  }
1101  else
1102  {
1103  THROW_ERROR("Unexpected pattern");
1104  }
1105  writer->write_component_declaration(core_cir);
1106  }
1107  }
1108  writer->write_NP_functionalities(cir);
1109  }
1110  else
1111  {
1112  THROW_ASSERT(!cir->get_black_box(), "black box component has to be managed in a different way");
1113  }
1114 
1116  writer->write_module_definition_end(cir);
1117  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Written module " + GET_TYPE_NAME(cir));
1118 }
1119 
1120 void HDL_manager::write_flopoco_module(const structural_objectRef& cir, std::list<std::string>&
1121 #if HAVE_FLOPOCO
1122  aux_files
1123 #endif
1124 ) const
1125 {
1126  auto* mod_inst = GetPointer<module>(cir);
1127  unsigned long long int mod_size_in = 0, mod_size_out = 0;
1128  for(unsigned int i = 0; i < mod_inst->get_in_port_size(); i++)
1129  {
1130  // Size of module is size of the largest output
1131  if(mod_size_in < STD_GET_SIZE(mod_inst->get_in_port(i)->get_typeRef()))
1132  {
1133  mod_size_in = STD_GET_SIZE(mod_inst->get_in_port(i)->get_typeRef());
1134  }
1135  }
1136  for(unsigned int i = 0; i < mod_inst->get_out_port_size(); i++)
1137  {
1138  // Size of module is size of the largest output
1139  if(mod_size_out < STD_GET_SIZE(mod_inst->get_out_port(i)->get_typeRef()))
1140  {
1141  mod_size_out = STD_GET_SIZE(mod_inst->get_out_port(i)->get_typeRef());
1142  }
1143  }
1144 #if HAVE_FLOPOCO
1146  std::string mod_type = mod_inst->get_NP_functionality()->get_NP_functionality(NP_functionality::FLOPOCO_PROVIDED);
1147  std::string mod_name = convert_to_identifier(lan.get(), GET_TYPE_NAME(cir));
1148  // Create the module
1150  "Creating " + mod_type + ", named " + mod_name + " whose size is " + STR(mod_size_in) + "|" +
1151  STR(mod_size_out));
1152  std::string pipe_parameter;
1153  if(mod_inst->ExistsParameter(PIPE_PARAMETER))
1154  {
1155  pipe_parameter = mod_inst->GetParameter(PIPE_PARAMETER);
1156  }
1157  flopo_wrap->add_FU(mod_type, static_cast<unsigned int>(mod_size_in), static_cast<unsigned int>(mod_size_out),
1158  mod_name, pipe_parameter);
1159  std::string created_file;
1160  flopo_wrap->writeVHDL(mod_name, static_cast<unsigned int>(mod_size_in), static_cast<unsigned int>(mod_size_out),
1161  pipe_parameter, created_file);
1162  aux_files.push_back(created_file);
1163 #else
1164  THROW_ERROR("Floating point based HLS requires --enable-flopoco at configuration time");
1165 #endif
1166 }
1167 
1169  const std::string& behav) const
1170 {
1171  std::vector<std::string> SplitVec = SplitString(behav, ";");
1172  THROW_ASSERT(SplitVec.size(), "Expected at least one behavioral description");
1173 
1174  for(auto& i : SplitVec)
1175  {
1176  std::vector<std::string> SplitVec2 = SplitString(i, "=");
1177  THROW_ASSERT(SplitVec2.size() == 2, "Expected two operands");
1178  writer->write_assign(SplitVec2[0], SplitVec2[1]);
1179  }
1180 }
1181 
1183  const std::string& fsm_desc_i) const
1184 {
1185  PRINT_DBG_MEX(DEBUG_LEVEL_VERBOSE, debug_level, "Start writing the FSM...");
1186 
1187  std::string fsm_desc = fsm_desc_i;
1188  boost::algorithm::erase_all(fsm_desc, "\n");
1189 
1190  std::vector<std::string> SplitVec = SplitString(fsm_desc, ";");
1191  THROW_ASSERT(SplitVec.size() > 2, "Expected more than one ';' in the FSM specification (the first is the reset)");
1192 
1193  using tokenizer = boost::tokenizer<boost::char_separator<char>>;
1194  boost::char_separator<char> sep(" ", nullptr);
1195  // compute the list of states
1196  std::list<std::string> list_of_states;
1197  auto it_end = SplitVec.cend();
1198  auto it = SplitVec.cbegin();
1199  tokenizer first_line_tokens(*it, sep);
1200  tokenizer::iterator tok_iter = first_line_tokens.begin();
1201  std::string reset_state = convert_to_identifier(writer.get(), *tok_iter);
1202  PRINT_DBG_MEX(DEBUG_LEVEL_VERBOSE, debug_level, "Reset state: '" << reset_state << "'");
1203  ++tok_iter;
1204  THROW_ASSERT(tok_iter != first_line_tokens.end(), "Wrong FSM description: expected the reset port name");
1205  std::string reset_port = convert_to_identifier(writer.get(), *tok_iter);
1206  PRINT_DBG_MEX(DEBUG_LEVEL_VERBOSE, debug_level, "Reset port: '" << reset_port << "'");
1207  ++tok_iter;
1208  THROW_ASSERT(tok_iter != first_line_tokens.end(), "Wrong FSM description: expected the start port name");
1209  std::string start_port = convert_to_identifier(writer.get(), *tok_iter);
1210  PRINT_DBG_MEX(DEBUG_LEVEL_VERBOSE, debug_level, "Start port: '" << start_port << "'");
1211  ++tok_iter;
1212  THROW_ASSERT(tok_iter != first_line_tokens.end(), "Wrong FSM description: expected the clock port name");
1213  std::string clock_port = convert_to_identifier(writer.get(), *tok_iter);
1214  PRINT_DBG_MEX(DEBUG_LEVEL_VERBOSE, debug_level, "Clock port: '" << clock_port << "'");
1215  ++tok_iter;
1216  THROW_ASSERT(tok_iter == first_line_tokens.end(), "Wrong FSM description: unexpetcted tokens" + *tok_iter);
1217 
1218  ++it;
1220  std::map<unsigned int, std::map<std::string, std::set<unsigned int>>> bypass_signals;
1221  if(!it->empty())
1222  {
1223  std::vector<std::string> BypassVec = SplitString(*it, ":");
1224  for(const auto& assign : BypassVec)
1225  {
1226  std::vector<std::string> AssignPair = SplitString(assign, "=");
1227  THROW_ASSERT(AssignPair.size() == 2, "malformed FSM description " + STR(AssignPair.size()));
1228  auto out = static_cast<unsigned>(std::stoul(AssignPair.at(0)));
1229  std::vector<std::string> inStateVec = SplitString(AssignPair.at(1), ",");
1230  for(const auto& inState : inStateVec)
1231  {
1232  std::vector<std::string> StateInsPair = SplitString(inState, ">");
1233  THROW_ASSERT(StateInsPair.size() == 2, "malformed FSM description " + STR(StateInsPair.size()));
1234  std::vector<std::string> inVec = SplitString(StateInsPair.at(1), "<");
1235  for(const auto& in : inVec)
1236  {
1237  auto in_val = static_cast<unsigned>(std::stoul(in));
1238  bypass_signals[out][StateInsPair.at(0)].insert(in_val);
1239  }
1240  }
1241  }
1242  }
1243 
1244  ++it;
1245  auto first = it;
1246  for(; it + 1 != it_end; ++it)
1247  {
1248  tokenizer tokens(*it, sep);
1249  list_of_states.push_back(convert_to_identifier(writer.get(), *tokens.begin()));
1250  }
1251  auto end = it;
1252  PRINT_DBG_MEX(DEBUG_LEVEL_VERBOSE, debug_level, "Number of states: " << list_of_states.size());
1253  // std::cout << list_of_states.size() << " " << bitnumber(list_of_states.size()-1) << std::endl;
1254  THROW_ASSERT(reset_state == *(list_of_states.begin()),
1255  "reset state and first state has to be the same " + reset_state + " : " + fsm_desc);
1256 
1258  std::string vendor;
1259  if(device->has_parameter("vendor"))
1260  {
1261  vendor = device->get_parameter<std::string>("vendor");
1262  boost::algorithm::to_lower(vendor);
1263  }
1264  bool one_hot_encoding = false;
1265  if(parameters->getOption<std::string>(OPT_fsm_encoding) == "one-hot")
1266  {
1267  one_hot_encoding = true;
1268  }
1269  else if(parameters->getOption<std::string>(OPT_fsm_encoding) == "auto" && vendor == "xilinx" &&
1270  list_of_states.size() < 256)
1271  {
1272  one_hot_encoding = true;
1273  }
1274  std::string family;
1275  if(device->has_parameter("vendor"))
1276  {
1277  family = device->get_parameter<std::string>("family");
1278  boost::algorithm::to_lower(family);
1279  }
1280 
1281  const auto is_yosys = family.find("yosys") != std::string::npos;
1282 
1283  writer->write_state_declaration(cir, list_of_states, reset_port, reset_state, one_hot_encoding);
1284 
1285  PRINT_DBG_MEX(DEBUG_LEVEL_VERBOSE, debug_level, "write module_instantiation begin");
1286  // write module_instantiation begin
1287  writer->write_module_definition_begin(cir);
1288 
1289  PRINT_DBG_MEX(DEBUG_LEVEL_VERBOSE, debug_level, "write the present_state update");
1291  writer->write_present_state_update(cir, reset_state, reset_port, clock_port,
1292  parameters->getOption<std::string>(OPT_reset_type),
1293  cir->find_member(PRESENT_STATE_PORT_NAME, port_o_K, cir).get() != nullptr);
1294 
1295  PRINT_DBG_MEX(DEBUG_LEVEL_VERBOSE, debug_level, "write transition and output functions");
1297  if(parameters->IsParameter("multi-proc-fsm") and parameters->GetParameter<int>("multi-proc-fsm") == 1)
1298  {
1299  const auto mod = GetPointer<module>(cir);
1300  const auto n_outs = mod->get_out_port_size();
1301  for(unsigned int output_index = 0; output_index <= n_outs; output_index++)
1302  {
1303  if(output_index != n_outs && mod->get_out_port(output_index)->get_id() == PRESENT_STATE_PORT_NAME)
1304  {
1305  continue;
1306  }
1307  if(output_index != n_outs && mod->get_out_port(output_index)->get_id() == NEXT_STATE_PORT_NAME)
1308  {
1309  continue;
1310  }
1311  writer->write_transition_output_functions(false, output_index, cir, reset_state, reset_port, start_port,
1312  clock_port, first, end, is_yosys, bypass_signals);
1313  }
1314  }
1315  else
1316  {
1317  writer->write_transition_output_functions(true, 0, cir, reset_state, reset_port, start_port, clock_port, first,
1318  end, is_yosys, bypass_signals);
1319  }
1320  PRINT_DBG_MEX(DEBUG_LEVEL_VERBOSE, debug_level, "FSM writing completed!");
1321 }
1322 
1323 std::string HDL_manager::convert_to_identifier(const language_writer* writer, const std::string& id)
1324 {
1325  auto ret = id;
1326  if(dynamic_cast<const VHDL_writer*>(writer))
1327  {
1328  if(ret.find("__") != std::string::npos or ret.front() == '_' or ret.back() == '_' or writer->check_keyword(ret))
1329  {
1330  return "\\" + ret + "\\";
1331  }
1332  else
1333  {
1334  return ret;
1335  }
1336  }
1337  else if(dynamic_cast<const verilog_writer*>(writer))
1338  {
1339  if((ret[0] >= '0' && ret[0] <= '9') || (ret.find('.') != std::string::npos) ||
1340  (ret.find('[') != std::string::npos) || (ret.find(']') != std::string::npos))
1341  {
1342  return "\\" + ret + " ";
1343  }
1344  else if(writer and writer->check_keyword(ret))
1345  {
1346  return "\\" + ret + " ";
1347  }
1348  else if(ret == "array")
1349  {
1350  return ret + "_S";
1351  }
1352  else
1353  {
1354  return ret;
1355  }
1356  }
1357  else
1358  {
1359  return ret;
1360  }
1361  THROW_UNREACHABLE("");
1362  return ret;
1363 }
1364 
1366 {
1367  std::string res = GET_TYPE_NAME(cir);
1368  auto* mod = GetPointer<module>(cir);
1369  const NP_functionalityRef& np = mod->get_NP_functionality();
1370  if(np && np->get_NP_functionality(NP_functionality::FLOPOCO_PROVIDED) != "")
1371  {
1372  unsigned long long int mod_size_in = 0;
1373  for(unsigned int i = 0; i < mod->get_in_port_size(); i++)
1374  {
1375  // Size of module is size of the largest output
1376  if(mod_size_in < STD_GET_SIZE(mod->get_in_port(i)->get_typeRef()))
1377  {
1378  mod_size_in = STD_GET_SIZE(mod->get_in_port(i)->get_typeRef());
1379  }
1380  }
1381  res = res + "_" + STR(mod_size_in);
1382  unsigned long long int mod_size_out = 0;
1383  for(unsigned int i = 0; i < mod->get_out_port_size(); i++)
1384  {
1385  // Size of module is size of the largest output
1386  if(mod_size_out < STD_GET_SIZE(mod->get_out_port(i)->get_typeRef()))
1387  {
1388  mod_size_out = STD_GET_SIZE(mod->get_out_port(i)->get_typeRef());
1389  }
1390  }
1391  res = res + "_" + STR(mod_size_out);
1392  if(mod->ExistsParameter(PIPE_PARAMETER) and mod->GetParameter(PIPE_PARAMETER) != "")
1393  {
1394  res = res + "_" + mod->GetParameter(PIPE_PARAMETER);
1395  }
1396  }
1397  return convert_to_identifier(lan, res);
1398 }
static std::string get_mod_typename(const language_writer *lan, const structural_objectRef &cir)
Returns the module typename taking into account even the flopoco customizations.
#define PRESENT_STATE_PORT_NAME
#define DEBUG_LEVEL_VERY_PEDANTIC
extremely verbose debugging print is performed.
Data structure representing the entire HLS information.
#define INDENT_DBG_MEX(dbgLevel, curDbgLevel, mex)
We are producing a debug version of the program, so the message is printed;.
static std::string convert_to_identifier(const language_writer *writer, const std::string &id)
Converts a generic string to a language compliant identifier.
void write_fsm(const language_writerRef writer, const structural_objectRef &cir, const std::string &fsm_desc) const
Writes a mealy/moore finite state machine behavioral description.
File containing functions and utilities to support the printing of debug messagges.
const structural_objectRef get_internal_object(unsigned int n) const
Return the ith internal objects.
#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
void hdl_gen(const std::string &filename, const std::list< structural_objectRef > &cirs, std::list< std::string > &hdl_files, std::list< std::string > &aux_files, bool tb)
Generates HDL code.
HDL_manager(const HLS_managerRef _HLSMgr, const generic_deviceRef device, const ParameterConstRef parameters)
Constructor.
#define DEBUG_LEVEL_PEDANTIC
very verbose debugging print is performed.
const std::string & get_id() const
Return the identifier associated with the structural_object.
const std::string get_copyright() const
Return the copyright associated with the module.
string target
Definition: lenet_tvm.py:16
std::string filename
#define GET_CLASS(obj)
Macro returning the actual type of an object.
const std::vector< std::string > SplitString(const std::string &input, const std::string &separators)
Function which splits a string into tokens.
unsigned int get_out_port_size() const
Return the number of output ports.
This class defines the methods to write VHDL descriptions.
std::string get_NP_functionality(NP_functionaly_type type) const
Return the description provided the type.
exceptions managed by PandA
static language_writerRef create_writer(HDLWriter_Language language, const technology_managerConstRef TM, const ParameterConstRef parameters)
Creates the specialization of the writer based on the desired language.
const structural_objectRef get_in_port(unsigned int n) const
Return the ith input port.
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...
Definition of hash function for EdgeDescriptor.
Definition: graph.hpp:1321
void write_flopoco_module(const structural_objectRef &cir, std::list< std::string > &aux_files) const
Writes the FloPoCo module description to a VHDL file.
unsigned int get_internal_objects_size() const
Return the number of internal objects.
Class specification of the manager of the technology library data structures.
const std::string get_description() const
Return the description associated with the module.
redefinition of map to manage ordered/unordered structures
#define GET_TYPE_NAME(structural_obj)
Macro returning the string name of a type.
unsigned int get_gen_port_size() const
Return the number of generic ports.
#define THROW_WARNING(str_expr)
helper function used to throw a warning in a standard way: though it uses PRINT_DBG_MEX, the debug level used is such that the message is always printed
Definition: exceptions.hpp:300
#define STR(s)
Macro which performs a lexical_cast to a string.
Auxiliary methods for manipulating string.
~HDL_manager()
Destructor.
HDLWriter_Language
const int debug_level
The debug level.
static std::string GetCurrentTimeStamp()
Return a timestamp of the current time.
Definition: utility.cpp:55
const language_writer * lan
virtual std::string get_kind_text() const =0
Virtual function used to get the string name of a structural_object instance.
#define THROW_UNREACHABLE(str_expr)
helper function used to specify that some points should never be reached
Definition: exceptions.hpp:292
void write_module(const language_writerRef writer, const structural_objectRef cir, std::list< std::string > &aux_files) const
Writes the module description.
Class for system verilog writing.
const HLS_managerRef HLSMgr
The high level synthesis manager.
Definition: HDL_manager.hpp:81
static const uint32_t k[]
Definition: sha-256.c:22
void get_post_order_structural_components(const structural_objectRef cir, std::list< structural_objectRef > &list_of_com) const
Returns the list of components that have a structural-based description.
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.
const NP_functionalityRef & get_NP_functionality() const
Return the alternative functionalities.
const structural_objectRef get_out_port(unsigned int n) const
Return the ith output port.
virtual bool check_keyword(const std::string &id) const =0
redefinition of set to manage ordered/unordered structures
virtual enum tec_kind get_kind() const =0
Virtual function used to find the real type of a technology_nodeinstance.
#define PIPE_PARAMETER
utility function used to read files.
const structural_objectRef get_gen_port(unsigned int n) const
Return the ith generic port.
bool is_fsm(const structural_objectRef &cir) const
Returns true if the module has a FSM description associated with, false otherwise.
virtual enum so_kind get_kind() const =0
Virtual function used to find the real type of a structural_object instance.
#define THROW_ERROR(str_expr)
helper function used to throw an error in a standard way
Definition: exceptions.hpp:263
Wrapper of design_flow.
const structural_objectRef target
const ParameterConstRef parameters
The set of input parameters.
Definition: HDL_manager.hpp:98
const generic_deviceRef device
reference to the target device
Definition: HDL_manager.hpp:84
unsigned int get_in_port_size() const
Return the number of input ports.
Main class for wrapping the FloPoCo code generator.
bool operator()(const structural_objectRef &el)
void io_signal_fix_ith(const language_writerRef writer, const structural_objectRef po, bool &lspf) const
Writes signal port connection post fix.
This class describes all classes used to represent a structural object.
std::string GetPath(std::filesystem::path path)
Definition: fileIO.hpp:140
int el
Definition: adpcm.c:105
const structural_objectRef get_owner() const
Return the owner.
Template borrowed from the ANTLR library by Terence Parr (http://www.jGuru.com - Software rights: htt...
Definition: refcount.hpp:94
HDL writer base class used to specify the interface of the different language writers.
T * get() const
Definition: refcount.hpp:169
Used to test if a component has been already inserted into the component list.
#define DEBUG_LEVEL_PARANOIC
paranoid level debugging print is performed.
bool get_black_box() const
Return the black box property.
this class is used to manage the command-line or XML options.
NP_functionaly_type
functionality type descriptors.
const std::string get_license() const
Return the license of the functional description of the module.
Wrapper to FloPoCo for VHDL code generation.
const structural_objectRef get_in_out_port(unsigned int n) const
Return the ith input-output port.
Not parsed functionality manager.
find_eq_module(const language_writer *_lan, const structural_objectRef &_target)
Class implementation of the structural_manager.
unsigned counter[N_THREADS]
Definition: data.c:3
Generic device description.
const technology_managerConstRef TM
reference to the class containing all the technology information
Definition: HDL_manager.hpp:87
std::string write_components(const std::string &filename, const HDLWriter_Language language, const std::list< structural_objectRef > &components, std::list< std::string > &aux_files) const
Generates the HDL description for the given components in the specified language. ...
This class writes different HDL based descriptions (VHDL, Verilog, SystemC) starting from a structura...
const std::string get_authors() const
Return the authors of the functional description of the module.
bool exist_NP_functionality(NP_functionaly_type type) const
Return true in case there exist a functionaly of the given type.
#define DEBUG_LEVEL_VERBOSE
verbose debugging print is performed.
void write_behavioral(const language_writerRef writer, const structural_objectRef &cir, const std::string &behav) const
Writes the behavioral description associated with the component.
This class describes a generic module.
void io_signal_fix_ith_vector(const language_writerRef writer, const structural_objectRef po, bool &lspf) const
unsigned int get_in_out_port_size() const
Return the number of output ports.
#define STD_GET_SIZE(structural_obj)
Macro returning the size of a type.
#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:51 for PandA-2024.02 by doxygen 1.8.13