PandA-2024.02
VHDL_writer.cpp
Go to the documentation of this file.
1 /*
2  *
3  * _/_/_/ _/_/ _/ _/ _/_/_/ _/_/
4  * _/ _/ _/ _/ _/_/ _/ _/ _/ _/ _/
5  * _/_/_/ _/_/_/_/ _/ _/_/ _/ _/ _/_/_/_/
6  * _/ _/ _/ _/ _/ _/ _/ _/ _/
7  * _/ _/ _/ _/ _/ _/_/_/ _/ _/
8  *
9  * ***********************************************
10  * PandA Project
11  * URL: http://panda.dei.polimi.it
12  * Politecnico di Milano - DEIB
13  * System Architectures Group
14  * ***********************************************
15  * Copyright (C) 2004-2024 Politecnico di Milano
16  *
17  * This file is part of the PandA framework.
18  *
19  * The PandA framework is free software; you can redistribute it and/or modify
20  * it under the terms of the GNU General Public License as published by
21  * the Free Software Foundation; either version 3 of the License, or
22  * (at your option) any later version.
23  *
24  * This program is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27  * GNU General Public License for more details.
28  *
29  * You should have received a copy of the GNU General Public License
30  * along with this program. If not, see <http://www.gnu.org/licenses/>.
31  *
32  */
41 #include "VHDL_writer.hpp"
42 
43 #include "HDL_manager.hpp"
44 #include "NP_functionality.hpp"
45 #include "Parameter.hpp"
46 #include "dbgPrintHelper.hpp"
47 #include "exceptions.hpp"
50 #include "string_manipulation.hpp"
51 #include "structural_objects.hpp"
52 #include "technology_node.hpp"
53 
54 #include <algorithm>
55 #include <boost/algorithm/string.hpp>
56 #include <boost/range/adaptor/reversed.hpp>
57 #include <boost/tokenizer.hpp>
58 #include <fstream>
59 #include <functional>
60 #include <iosfwd>
61 #include <utility>
62 
63 const std::set<std::string> VHDL_writer::keywords = {
64  "ABS", "ACCESS", "AFTER", "ALIAS", "ALL", "AND",
65  "ARCHITECTURE", "ARRAY", "ASSERT", "ATTRIBUTE", "BEGIN", "BLOCK",
66  "BODY", "BUFFER", "BUS", "CASE", "COMPONENT", "CONFIGURATION",
67  "CONSTANT", "DISCONNECT", "DOWNTO", "ELSE", "ELSIF", "END",
68  "ENTITY", "EXIT", "FILE", "FOR", "FUNCTION", "GENERATE",
69  "GENERIC", "GROUP", "GUARDED", "IF", "IMPURE", "IN",
70  "INERTIAL", "INOUT", "IS", "LABEL", "LIBRARY", "LINKAGE",
71  "LITERAL", "LOOP", "MAP", "MOD", "NAND", "NEW",
72  "NEXT", "NOR", "NOT", "NULL", "OF", "ON",
73  "OPEN", "OR", "OTHERS", "OUT", "PACKAGE", "PORT",
74  "POSTPONED", "PROCEDURE", "PROCESS", "PURE", "RANGE", "RECORD",
75  "REGISTER", "REJECT", "REM", "RETURN", "ROL", "ROR",
76  "SELECT", "SEVERITY", "SIGNAL", "SHARED", "SLA", "SLI",
77  "SRA", "SRL", "SUBTYPE", "THEN", "TO", "TRANSPORT",
78  "TYPE", "UNAFFECTED", "UNITS", "UNTIL", "USE", "VARIABLE",
79  "WAIT", "WHEN", "WHILE", "WITH", "XNOR", "XOR"};
80 
81 VHDL_writer::VHDL_writer(const technology_managerConstRef _TM, const ParameterConstRef _parameters)
82  : language_writer(STD_OPENING_CHAR, STD_OPENING_CHAR, _parameters), TM(_TM)
83 {
84  debug_level = parameters->get_class_debug_level(GET_CLASS(*this));
85 }
86 
87 VHDL_writer::~VHDL_writer() = default;
88 
89 void VHDL_writer::write_comment(const std::string& comment_string)
90 {
91  indented_output_stream->Append("-- " + comment_string);
92 }
93 
95 {
96  switch(Type->type)
97  {
99  {
100  return "std_logic";
101  }
103  {
104  return "signed";
105  }
107  {
108  return "unsigned";
109  }
111  {
112  return "std_logic_vector";
113  }
115  {
116  THROW_ERROR("USER type not yet supported");
117  break;
118  }
120  {
121  return "std_logic_vector";
122  }
126  {
127  return "std_logic_vector";
128  }
130  {
131  THROW_ERROR("VECTOR_USER type not yet supported");
132  break;
133  }
135  {
136  return Type->id_type;
137  }
139  default:
140  THROW_UNREACHABLE("");
141  }
142  return "";
143 }
144 
146 {
147  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---type_converter_size of " + cir->get_path());
149  const structural_objectRef Owner = cir->get_owner();
150  auto* mod = GetPointer<module>(Owner);
151  std::string port_name = cir->get_id();
152  bool specialization_string = false;
153  // std::cerr << "cir: " << cir->get_id() << " " << GetPointer<port_o>(cir)->size_parameter << std::endl;
154  if(mod)
155  {
157  const NP_functionalityRef& np = mod->get_NP_functionality();
158  if(np)
159  {
160  std::vector<std::pair<std::string, structural_objectRef>> library_parameters;
161  mod->get_NP_library_parameters(Owner, library_parameters);
162  for(const auto& library_parameter : library_parameters)
163  {
164  if(port_name == library_parameter.first)
165  {
166  specialization_string = true;
167  }
168  }
169  }
170  }
171  switch(Type->type)
172  {
174  {
175  if(cir->get_kind() == port_vector_o_K)
176  {
177  if(specialization_string)
178  {
179  return "((" + (PORTSIZE_PREFIX + port_name) + "*" + (BITSIZE_PREFIX + port_name) + ")-1 downto 0) ";
180  }
181  else
182  {
183  const auto& port_vector = GetPointer<port_o>(cir);
184  return " (" + STR(port_vector->get_ports_size() - 1) + " downto 0)";
185  }
186  }
187  else
188  {
189  return "";
190  }
191  }
195  {
196  if(!GetPointer<port_o>(cir) or !GetPointer<port_o>(cir)->get_reverse())
197  {
198  if(GetPointer<port_o>(cir) && GetPointer<port_o>(cir)->size_parameter.size())
199  {
200  return " (" + (GetPointer<port_o>(cir)->size_parameter) + "-1 downto 0)";
201  }
202  else if(specialization_string)
203  {
204  return " (" + (HDL_manager::convert_to_identifier(this, BITSIZE_PREFIX + port_name)) + "-1 downto 0)";
205  }
206  else
207  {
208  return " (" + std::to_string(Type->size - 1) + " downto 0)";
209  }
210  }
211  else
212  {
213  if(GetPointer<port_o>(cir) && GetPointer<port_o>(cir)->size_parameter.size())
214  {
215  return " (0 to " + (GetPointer<port_o>(cir)->size_parameter) + "-1)";
216  }
217  else if(specialization_string)
218  {
219  return " (0 to " + (HDL_manager::convert_to_identifier(this, BITSIZE_PREFIX + port_name)) + "-1)";
220  }
221  else
222  {
223  return " (0 to " + std::to_string(Type->size - 1) + ")";
224  }
225  }
226  }
228  {
229  THROW_ERROR("USER type not yet supported");
230  break;
231  }
233  {
234  if(specialization_string)
235  {
236  if(cir->get_kind() == port_vector_o_K)
237  {
238  auto lsb = GetPointer<port_o>(cir)->get_lsb();
239  return "((" + (PORTSIZE_PREFIX + port_name) + "*" + (BITSIZE_PREFIX + port_name) + ")+(" +
240  std::to_string(static_cast<int>(lsb) - 1) + ") downto " + std::to_string(lsb) + ") ";
241  }
242  else
243  {
244  return "(" + (BITSIZE_PREFIX + port_name) + "-1 downto 0) ";
245  }
246  }
247  else
248  {
249  if(cir->get_kind() == signal_vector_o_K)
250  {
251  const structural_objectRef first_sig = GetPointer<signal_o>(cir)->get_signal(0);
252  structural_type_descriptorRef Type_fs = first_sig->get_typeRef();
253  auto n_sign = GetPointer<signal_o>(cir)->get_signals_size();
254  auto size_fs = Type_fs->vector_size > 0 ? Type_fs->size * Type_fs->vector_size : Type_fs->size;
255  auto lsb = GetPointer<signal_o>(cir)->get_lsb();
256  auto msb = size_fs * n_sign + lsb;
257 
258  return "(" + std::to_string(static_cast<int>(msb) - 1) + " downto " + std::to_string(lsb) + ") ";
259  }
260  else if(cir->get_kind() == port_vector_o_K)
261  {
262  auto lsb = GetPointer<port_o>(cir)->get_lsb();
263  auto n_ports = GetPointer<port_o>(cir)->get_ports_size();
264  const structural_objectRef first_port = GetPointer<port_o>(cir)->get_port(0);
265  const auto Type_fp = first_port->get_typeRef();
266  auto size_fp = Type_fp->vector_size > 0 ? Type_fp->size * Type_fp->vector_size : Type_fp->size;
267  auto msb = size_fp * n_ports + lsb;
268  return "(" + std::to_string(static_cast<int>(msb) - 1) + " downto " + std::to_string(lsb) + ") ";
269  }
270  if(Type->vector_size > 1 && Type->size == 1)
271  {
272  return "(" + std::to_string(static_cast<int>(Type->vector_size) - 1) + " downto 0) ";
273  }
274  else if(Type->vector_size == 1 && Type->size == 1)
275  {
276  return "(0 downto 0)";
277  }
278  else if(Type->vector_size == 0 && Type->size != 0)
279  {
280  return "(" + std::to_string(static_cast<int>(Type->size) - 1) + " downto 0) ";
281  }
282  else
283  {
284  THROW_ERROR("Not completely specified: " + port_name);
285  }
286  }
287  break;
288  }
292  {
293  if(GetPointer<port_o>(cir) and specialization_string)
294  {
295  return " (" + HDL_manager::convert_to_identifier(this, BITSIZE_PREFIX + port_name) + "*" +
296  HDL_manager::convert_to_identifier(this, NUM_ELEM_PREFIX + port_name) + "-1 downto 0)";
297  }
298  else
299  {
300  return "(" + STR(GET_TYPE_SIZE(cir) - 1) + " downto 0)";
301  }
302  }
304  {
305  THROW_UNREACHABLE("");
306  break;
307  }
309  {
310  return Type->id_type;
311  }
313  default:
314  THROW_ERROR("Not initialized type");
315  }
316  return "";
317 }
318 
320 {
322  const structural_objectRef Owner = cir->get_owner();
323  auto* mod = GetPointer<module>(Owner);
324  std::string port_name = cir->get_id();
325  bool specialization_string = false;
326  if(mod)
327  {
328  const NP_functionalityRef& np = mod->get_NP_functionality();
329  if(np)
330  {
331  std::vector<std::pair<std::string, structural_objectRef>> library_parameters;
332  mod->get_NP_library_parameters(Owner, library_parameters);
333  for(const auto& library_parameter : library_parameters)
334  {
335  if(port_name == library_parameter.first)
336  {
337  specialization_string = true;
338  }
339  }
340  }
341  }
342  switch(Type->type)
343  {
345  {
346  if(Owner->get_kind() == port_vector_o_K)
347  {
348  return "(" + GetPointer<port_o>(cir)->get_id() + ")";
349  }
350  else
351  {
352  return "";
353  }
354  }
356  {
357  Type->print(std::cerr);
358  THROW_ERROR("USER type not yet supported");
359  break;
360  }
365  {
366  if(specialization_string)
367  {
368  if(Owner->get_kind() == port_vector_o_K)
369  {
370  auto lsb = GetPointer<port_o>(Owner)->get_lsb();
371  return "(((" + GetPointer<port_o>(cir)->get_id() + "+1)*" + (BITSIZE_PREFIX + port_name) + ")+(" +
372  std::to_string(static_cast<int>(lsb) - 1) + ") downto (" + GetPointer<port_o>(cir)->get_id() +
373  "*" + (BITSIZE_PREFIX + port_name) + ")+" + std::to_string(lsb) + ")";
374  }
375  else
376  {
377  return "";
378  }
379  }
380  else
381  {
382  if(Owner->get_kind() == port_vector_o_K)
383  {
385  auto size_fp = Type_fp->vector_size > 0 ? Type_fp->size * Type_fp->vector_size : Type_fp->size;
386  auto lsb = GetPointer<port_o>(Owner)->get_lsb();
387  return "(" +
388  std::to_string((1 + std::stoi(GetPointer<port_o>(cir)->get_id())) * static_cast<int>(size_fp) +
389  static_cast<int>(lsb) - 1) +
390  " downto " +
391  std::to_string((std::stoi(GetPointer<port_o>(cir)->get_id())) * static_cast<int>(size_fp) +
392  static_cast<int>(lsb)) +
393  ")";
394  }
395  else
396  {
397  return "";
398  }
399  }
400  break;
401  }
405  {
406  if(specialization_string)
407  {
408  if(Owner->get_kind() == port_vector_o_K)
409  {
410  auto lsb = GetPointer<port_o>(Owner)->get_lsb();
411  return "(((" + GetPointer<port_o>(cir)->get_id() + "+1)*" + (BITSIZE_PREFIX + port_name) + "*" +
412  (NUM_ELEM_PREFIX + port_name) + ")+(" + std::to_string(static_cast<int>(lsb) - 1) + ") downto (" +
413  GetPointer<port_o>(cir)->get_id() + "*" + (BITSIZE_PREFIX + port_name) + "*" +
414  (NUM_ELEM_PREFIX + port_name) + ")+" + std::to_string(lsb) + ")";
415  }
416  else
417  {
418  return "";
419  }
420  }
421  else
422  {
423  if(Owner->get_kind() == port_vector_o_K)
424  {
426  auto size_fp = Type_fp->vector_size > 0 ? Type_fp->size * Type_fp->vector_size : Type_fp->size;
427  auto lsb = GetPointer<port_o>(Owner)->get_lsb();
428  return "(" +
429  std::to_string((1 + std::stoi(GetPointer<port_o>(cir)->get_id())) * static_cast<int>(size_fp) +
430  static_cast<int>(lsb) - 1) +
431  " downto " +
432  std::to_string((std::stoi(GetPointer<port_o>(cir)->get_id())) * static_cast<int>(size_fp) +
433  static_cast<int>(lsb)) +
434  ")";
435  }
436  else
437  {
438  return "";
439  }
440  }
441  break;
442  }
445  {
446  THROW_ERROR("VECTOR_USER type not yet supported");
447  break;
448  }
450  default:
451  THROW_ERROR("Not initialized type");
452  }
453  return "";
454 }
455 
457 {
458  THROW_ASSERT(cir->get_kind() == component_o_K || cir->get_kind() == channel_o_K,
459  "Expected a component or a channel got something of different");
460  NP_functionalityRef NPF = GetPointer<module>(cir)->get_NP_functionality();
461  if(!NPF or !NPF->exist_NP_functionality(NP_functionality::IP_LIBRARY))
462  {
463  indented_output_stream->Append("library IEEE;\n");
464  indented_output_stream->Append("use IEEE.std_logic_1164.all;\n");
465  indented_output_stream->Append("use IEEE.numeric_std.all;\n");
466  indented_output_stream->Append("use IEEE.math_real.all;\n");
467  indented_output_stream->Append("use STD.textio.all;\n");
468  indented_output_stream->Append("use IEEE.std_logic_textio.all;\n");
469  indented_output_stream->Append("-- synthesis translate_off\n");
470  indented_output_stream->Append("use STD.env.all;\n");
471  indented_output_stream->Append("-- synthesis translate_on\n");
472  indented_output_stream->Append("use work.panda_pkg.all;\n");
473  return;
474  }
475  std::string library = NPF->get_NP_functionality(NP_functionality::IP_LIBRARY);
476  std::vector<std::string> library_list = string_to_container<std::vector<std::string>>(library, ";");
477  for(const auto& l : library_list)
478  {
479  indented_output_stream->Append(l + ";\n");
480  }
481 }
482 
484 {
485  THROW_ASSERT(cir->get_kind() == component_o_K || cir->get_kind() == channel_o_K,
486  "Expected a component or a channel got something of different");
488  list_of_comp_already_def.clear();
489 }
490 
492 {
493  THROW_ASSERT(cir->get_kind() == component_o_K || cir->get_kind() == channel_o_K,
494  "Expected a component or a channel got something of different");
496  indented_output_stream->Append("\narchitecture " +
497  HDL_manager::convert_to_identifier(this, GET_TYPE_NAME(cir) + "_arch") + " of ");
500 }
501 
502 void VHDL_writer::write_port_declaration(const structural_objectRef& cir, bool last_port_to_analyze)
503 {
504  THROW_ASSERT(cir->get_kind() == port_o_K || cir->get_kind() == port_vector_o_K,
505  "Expected a port got something of different " + cir->get_id());
507  dir = GetPointer<port_o>(cir)->get_port_direction();
509  switch(dir)
510  {
511  case port_o::IN:
512  {
514  break;
515  }
516  case port_o::OUT:
517  {
519  break;
520  }
521  case port_o::IO:
522  {
523  indented_output_stream->Append("inout");
524  break;
525  }
526  case port_o::GEN:
527  case port_o::TLM_IN:
528  case port_o::TLM_INOUT:
529  case port_o::TLM_OUT:
530  case port_o::UNKNOWN:
531  default:
532  THROW_ERROR("Something went wrong!");
533  }
535  " " + (cir->get_kind() == port_o_K ? type_converter(cir->get_typeRef()) : "std_logic_vector") +
536  type_converter_size(cir));
537  if(not last_port_to_analyze)
538  {
540  }
542 }
543 
545 {
546  auto* mod = GetPointer<module>(cir);
547  THROW_ASSERT(mod, "Expected a module got a " + cir->get_kind_text() + ": " + cir->get_path());
548 
549  const std::string comp = HDL_manager::get_mod_typename(this, cir);
550 
551  if(list_of_comp_already_def.find(comp) == list_of_comp_already_def.end())
552  {
553  list_of_comp_already_def.insert(comp);
554  }
555  else
556  {
557  return;
558  }
559 
560  indented_output_stream->Append("\ncomponent " + comp + "\n");
562  indented_output_stream->Append("port (\n");
564  if(mod->get_in_port_size())
565  {
566  write_comment("IN\n");
567  for(unsigned int i = 0; i < mod->get_in_port_size(); i++)
568  {
569  if(i == mod->get_in_port_size() - 1 && !mod->get_out_port_size() && !mod->get_in_out_port_size() &&
570  !mod->get_gen_port_size())
571  {
572  write_port_declaration(mod->get_in_port(i), true);
573  }
574  else
575  {
576  write_port_declaration(mod->get_in_port(i), false);
577  }
578  }
579  }
580  if(mod->get_out_port_size())
581  {
582  write_comment("OUT\n");
583  for(unsigned int i = 0; i < mod->get_out_port_size(); i++)
584  {
585  if(i == mod->get_out_port_size() - 1 && !mod->get_in_out_port_size() && !mod->get_gen_port_size())
586  {
587  write_port_declaration(mod->get_out_port(i), true);
588  }
589  else
590  {
591  write_port_declaration(mod->get_out_port(i), false);
592  }
593  }
594  }
595  if(mod->get_in_out_port_size())
596  {
597  write_comment("INOUT\n");
598  for(unsigned int i = 0; i < mod->get_in_out_port_size(); i++)
599  {
600  if(i == mod->get_in_out_port_size() - 1 && !mod->get_gen_port_size())
601  {
602  write_port_declaration(mod->get_in_out_port(i), true);
603  }
604  else
605  {
606  write_port_declaration(mod->get_in_out_port(i), false);
607  }
608  }
609  }
610  if(mod->get_gen_port_size())
611  {
612  write_comment("Ports\n");
613  for(unsigned int i = 0; i < mod->get_gen_port_size(); i++)
614  {
615  if(i == mod->get_gen_port_size() - 1)
616  {
617  write_port_declaration(mod->get_gen_port(i), true);
618  }
619  else
620  {
621  write_port_declaration(mod->get_gen_port(i), false);
622  }
623  }
624  }
626 
627  indented_output_stream->Append("\n);\nend component;\n");
628 }
629 
631 {
632  if(cir->get_kind() == signal_o_K)
633  {
634  indented_output_stream->Append("signal " + HDL_manager::convert_to_identifier(this, cir->get_id()) + " : " +
635  type_converter(cir->get_typeRef()) + type_converter_size(cir) + ";\n");
636  }
637  else if(cir->get_kind() == signal_vector_o_K and
640  {
641  const structural_objectRef first_sig = GetPointer<signal_o>(cir)->get_signal(0);
642  structural_type_descriptorRef Type_fs = first_sig->get_typeRef();
643  auto n_sign = GetPointer<signal_o>(cir)->get_signals_size();
644  auto size_fs = Type_fs->vector_size > 0 ? Type_fs->size * Type_fs->vector_size : Type_fs->size;
645  auto lsb = GetPointer<signal_o>(cir)->get_lsb();
646  auto msb = size_fs * n_sign + lsb;
648  " : std_logic_vector (" + STR(msb - 1) + " downto " + STR(lsb) + ");\n");
649  }
650  else
651  {
652  THROW_UNREACHABLE("");
653  }
654 }
655 
657 {
659  indented_output_stream->Append("begin\n");
661 }
662 
663 void VHDL_writer::write_module_instance_begin(const structural_objectRef& cir, const std::string& module_name,
664  bool write_parametrization)
665 {
666  THROW_ASSERT(cir->get_kind() == component_o_K || cir->get_kind() == channel_o_K,
667  "Expected a component or a channel got something of different");
668  indented_output_stream->Append(HDL_manager::convert_to_identifier(this, cir->get_id()) + " : " + module_name);
669  // check possible module parametrization
670  if(write_parametrization)
671  {
673  }
674  indented_output_stream->Append(" port map (");
676 }
677 
679 {
682 }
683 
685 {
686  THROW_ASSERT(cir->get_kind() == component_o_K || cir->get_kind() == channel_o_K,
687  "Expected a component or a channel got something of different");
690  ";\n\n");
691 }
692 
693 void VHDL_writer::write_vector_port_binding(const structural_objectRef& port, bool first_port_analyzed)
694 {
695  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Writing vector port binding of " + port->get_id());
696  THROW_ASSERT(port, "NULL object_bounded received");
697  THROW_ASSERT(port->get_kind() == port_vector_o_K, "Expected a port vector, got something of different");
698  if(first_port_analyzed)
699  {
701  }
702  const structural_objectRef p_object_bounded = GetPointer<port_o>(port)->find_bounded_object(port->get_owner());
703  if(p_object_bounded)
704  {
707  if(p_object_bounded->get_kind() == port_vector_o_K)
708  {
710  }
711  else if(p_object_bounded->get_kind() == signal_vector_o_K)
712  {
714  }
715  else
716  {
717  THROW_UNREACHABLE("not expected case");
718  }
719  }
720  else
721  {
722  const auto port_vector = GetPointer<port_o>(port);
723  const auto vector_port_size = GET_TYPE_SIZE(port) * port_vector->get_ports_size();
724  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Vector port size is " + STR(vector_port_size));
725  auto msb = vector_port_size - 1;
726  bool open = true;
727  for(unsigned int local_port_index = 0; local_port_index < port_vector->get_ports_size(); local_port_index++)
728  {
729  if(GetPointer<port_o>(port_vector->get_port(local_port_index))->find_bounded_object())
730  {
731  open = false;
732  }
733  }
734  if(open)
735  {
737  indented_output_stream->Append(" => open");
738  }
739  else
740  {
742  for(unsigned int local_port_index = 0; local_port_index < port_vector->get_ports_size(); local_port_index++)
743  {
744  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Considering port " + STR(local_port_index));
745  if(local_port_index != 0)
746  {
748  }
750  auto reverse_port_index = port_vector->get_ports_size() - local_port_index - 1;
751  const auto object_bounded =
752  GetPointer<port_o>(port_vector->get_port(reverse_port_index))->find_bounded_object();
753  THROW_ASSERT(object_bounded, port_vector->get_port(reverse_port_index)->get_path());
754  const auto single_port_size = GET_TYPE_SIZE(object_bounded);
755  if(single_port_size == 1 and object_bounded->get_typeRef()->type == structural_type_descriptor::BOOL)
756  {
757  indented_output_stream->Append("(" + STR(msb) + ")");
758  }
759  else
760  {
761  indented_output_stream->Append("(" + STR(msb) + " downto " + STR(msb - single_port_size + 1) + ")");
762  }
763  msb = msb - single_port_size;
764  THROW_ASSERT(msb <= vector_port_size or msb + 1 == 0, STR(msb) + " of " + port->get_id());
766  if(object_bounded->get_kind() == port_o_K or object_bounded->get_kind() == port_vector_o_K or
767  object_bounded->get_kind() == signal_o_K or object_bounded->get_kind() == signal_vector_o_K)
768  {
769  if(object_bounded->get_typeRef()->type == structural_type_descriptor::BOOL or
770  object_bounded->get_typeRef()->type == structural_type_descriptor::VECTOR_BOOL)
771  {
772  indented_output_stream->Append(HDL_manager::convert_to_identifier(this, object_bounded->get_id()));
773  }
774  else
775  {
777  "std_logic_vector(" + HDL_manager::convert_to_identifier(this, object_bounded->get_id()) + ")");
778  }
779  }
780  else if(object_bounded->get_kind() == constant_o_K)
781  {
782  auto* con = GetPointer<constant_o>(object_bounded);
783  std::string trimmed_value = "";
784  auto long_value = std::stoull(con->get_value());
785  for(unsigned int ind = 0; ind < GET_TYPE_SIZE(con); ind++)
786  {
787  trimmed_value = trimmed_value + (((1LLU << (GET_TYPE_SIZE(con) - ind - 1)) & long_value) ? '1' : '0');
788  }
789  if(single_port_size == 1 and object_bounded->get_typeRef()->type == structural_type_descriptor::BOOL)
790  {
791  indented_output_stream->Append("'" + trimmed_value + "'");
792  }
793  else
794  {
795  indented_output_stream->Append("\"" + trimmed_value + "\"");
796  }
797  }
798  else
799  {
800  THROW_UNREACHABLE("");
801  }
802  }
804  }
805  }
806  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Written vector port binding of " + port->get_id());
807 }
808 
810  bool first_port_analyzed)
811 {
812  THROW_ASSERT(port, "NULL object_bounded received");
815  "-->Write port binding " + port->get_id() + " (" + port->get_typeRef()->get_name() + ") => " +
816  (object_bounded ? object_bounded->get_id() + " (" + object_bounded->get_typeRef()->get_name() + ")" : ""));
817  THROW_ASSERT(port->get_kind() == port_o_K, "Expected a port got something of different");
818  THROW_ASSERT(port->get_owner(), "The port has to have an owner");
819  if(first_port_analyzed)
820  {
822  }
823  if(port->get_owner()->get_kind() == port_vector_o_K)
824  {
826  const auto port_name = HDL_manager::convert_to_identifier(this, port->get_owner()->get_id());
827  if(object_bounded && object_bounded->get_typeRef()->type == structural_type_descriptor::BOOL)
828  {
829  indented_output_stream->Append(port_name + "(" + STR(port->get_id()) + ") => ");
830  }
831  else
832  {
833  indented_output_stream->Append(port_name + "(" +
834  STR(((std::stoull(port->get_id()) + 1) * GET_TYPE_SIZE(port)) - 1) +
835  " downto " + STR(std::stoull(port->get_id()) * GET_TYPE_SIZE(port)) + ") => ");
836  }
837  }
840  object_bounded && object_bounded->get_typeRef()->type == structural_type_descriptor::BOOL)
841  {
843  }
844  else
845  {
847  }
848 
849  if(!object_bounded and GetPointer<port_o>(port)->get_port_direction() == port_o::IN)
850  {
851  auto size = GET_TYPE_SIZE(port);
853  {
855  }
856  else
857  {
858  std::string null;
859  for(unsigned int s = 0; s < size; s++)
860  {
861  null += "0";
862  }
863  indented_output_stream->Append("\"" + null + "\"");
864  }
866  "<--Written port binding " + port->get_id() + " => " +
867  (object_bounded ? object_bounded->get_path() : ""));
868  return;
869  }
870  THROW_ASSERT(object_bounded, "NULL object_bounded received");
871  THROW_ASSERT(object_bounded->get_kind() != port_o_K || object_bounded->get_owner(),
872  "A port has to have always an owner");
873  if(object_bounded->get_kind() == constant_o_K)
874  {
875  auto* con = GetPointer<constant_o>(object_bounded);
876  std::string trimmed_value = "";
877  auto long_value = std::stoull(con->get_value());
878  for(unsigned int ind = 0; ind < GET_TYPE_SIZE(con); ind++)
879  {
880  trimmed_value = trimmed_value + (((1LLU << (GET_TYPE_SIZE(con) - ind - 1)) & long_value) ? '1' : '0');
881  }
883  {
884  indented_output_stream->Append("\"" + trimmed_value + "\"");
885  }
887  {
888  if(port->get_owner()->get_kind() == port_vector_o_K)
889  {
890  indented_output_stream->Append("\"" + trimmed_value + "\"");
891  }
892  else
893  {
894  indented_output_stream->Append("'" + trimmed_value + "'");
895  }
896  }
897  else if(port->get_typeRef()->type == structural_type_descriptor::UINT or
902  {
903  indented_output_stream->Append("\"" + trimmed_value + "\"");
904  }
905  else
906  {
908  }
909  }
910  else if(port->get_typeRef()->type == object_bounded->get_typeRef()->type or
911  object_bounded->get_typeRef()->type == structural_type_descriptor::BOOL)
912  {
913  if(object_bounded->get_kind() == port_o_K && object_bounded->get_owner()->get_kind() == port_vector_o_K)
914  {
916  HDL_manager::convert_to_identifier(this, object_bounded->get_owner()->get_id()) +
917  may_slice_string(object_bounded));
918  }
919  else
920  {
922  }
923  }
924  else
925  {
926  THROW_ASSERT(GetPointer<port_o>(port)->get_port_direction() == port_o::IN or
935  "Needed a conversion on output port binding " + port->get_path() + " => " +
936  object_bounded->get_path() + " - Types are " + port->get_typeRef()->get_name() + " vs. " +
937  object_bounded->get_typeRef()->get_name());
940  object_bounded->get_typeRef()->size == 1)
941  {
942  indented_output_stream->Append(HDL_manager::convert_to_identifier(this, object_bounded->get_id()) + "(0)");
943  }
944  else if((port->get_typeRef()->type == structural_type_descriptor::INT and
947  object_bounded->get_typeRef()->type == structural_type_descriptor::UINT) or
953  object_bounded->get_typeRef()->type == structural_type_descriptor::UINT) or
955  object_bounded->get_typeRef()->type == structural_type_descriptor::INT) or
957  object_bounded->get_typeRef()->type == structural_type_descriptor::REAL)
961  {
963  (HDL_manager::convert_to_identifier(this, object_bounded->get_id())) + ")");
964  }
973  {
975  }
976  else if(port->get_typeRef()->type == structural_type_descriptor::BOOL and
977  (object_bounded->get_typeRef()->type == structural_type_descriptor::UINT and
978  object_bounded->get_typeRef()->size == 1))
979  {
981  (HDL_manager::convert_to_identifier(this, object_bounded->get_id())) + "(0))");
982  }
983  else
984  {
985  THROW_UNREACHABLE("Conversion required on port binding: " + port->get_path() + "(" +
986  port->get_typeRef()->get_name() + ") (" + object_bounded->get_id() + "(" +
987  object_bounded->get_typeRef()->get_name() + ")");
988  }
989  }
991  "<--Written port binding " + port->get_id() + " => " +
992  (object_bounded ? object_bounded->get_id() : ""));
993 }
994 
996 {
997  THROW_ASSERT(port && port->get_kind() == port_o_K, "Expected a port got something of different");
998  THROW_ASSERT(port->get_owner(), "Expected a port with an owner");
999  THROW_ASSERT(sig && (sig->get_kind() == signal_o_K || sig->get_kind() == constant_o_K),
1000  "Expected a signal or a constant, got something of different");
1001  std::string port_string;
1002  std::string signal_string;
1003  if(sig->get_kind() == constant_o_K)
1004  {
1005  auto* con = GetPointer<constant_o>(sig);
1006  std::string trimmed_value = "";
1007  auto long_value = std::stoull(con->get_value());
1008  for(unsigned int ind = 0; ind < GET_TYPE_SIZE(con); ind++)
1009  {
1010  trimmed_value = trimmed_value + (((1LLU << (GET_TYPE_SIZE(con) - ind - 1)) & long_value) ? '1' : '0');
1011  }
1012  signal_string = "\"" + trimmed_value + "\"";
1013  }
1014  else if(sig->get_kind() == signal_o_K)
1015  {
1016  if(sig->get_owner()->get_kind() == signal_vector_o_K)
1017  {
1018  signal_string = HDL_manager::convert_to_identifier(this, sig->get_owner()->get_id()) + may_slice_string(port);
1019  }
1020  else
1021  {
1022  signal_string = HDL_manager::convert_to_identifier(this, sig->get_id());
1023  }
1024  }
1025  if(port->get_owner()->get_kind() == port_vector_o_K)
1026  {
1027  port_string = HDL_manager::convert_to_identifier(this, port->get_owner()->get_id()) + may_slice_string(port);
1028  }
1029  else
1030  {
1031  port_string = HDL_manager::convert_to_identifier(this, port->get_id());
1032  }
1033 
1034  if(GetPointer<port_o>(port)->get_port_direction() == port_o::IN)
1035  {
1036  std::swap(port_string, signal_string);
1037  }
1038 
1039  if(port_string != signal_string)
1040  {
1041  const auto left = GetPointer<port_o>(port)->get_port_direction() == port_o::IN ? sig : port;
1042  const auto right = GetPointer<port_o>(port)->get_port_direction() == port_o::IN ? port : sig;
1043  if(left->get_typeRef()->type == structural_type_descriptor::UINT and
1044  right->get_typeRef()->type == structural_type_descriptor::VECTOR_BOOL)
1045  {
1046  signal_string = "unsigned(" + signal_string + ")";
1047  }
1048  else if(left->get_typeRef()->type == structural_type_descriptor::INT and
1049  right->get_typeRef()->type == structural_type_descriptor::VECTOR_BOOL)
1050  {
1051  signal_string = "signed(" + signal_string + ")";
1052  }
1053  else if(left->get_typeRef()->type == structural_type_descriptor::VECTOR_BOOL and
1054  right->get_typeRef()->type == structural_type_descriptor::UINT)
1055  {
1056  signal_string = "std_logic_vector(" + signal_string + ")";
1057  }
1058  else if(left->get_typeRef()->type == structural_type_descriptor::BOOL and
1059  right->get_typeRef()->type == structural_type_descriptor::VECTOR_BOOL)
1060  {
1061  signal_string = "" + signal_string + "(0)";
1062  }
1063  else if(left->get_typeRef()->type == structural_type_descriptor::BOOL and
1064  right->get_typeRef()->type == structural_type_descriptor::BOOL and right->get_kind() == constant_o_K)
1065  {
1066  signal_string = std::string("'") + signal_string.at(1) + "'";
1067  }
1068  indented_output_stream->Append(port_string + " <= " + signal_string + ";\n");
1069  }
1070 
1071  // const auto left = GetPointer<port_o>(port)->get_port_direction() == port_o::IN ? sig : port;
1072  // const auto right = GetPointer<port_o>(port)->get_port_direction() == port_o::IN ? port : sig;
1073  // const auto left_string = HDL_manager::convert_to_identifier(this, left->get_id());
1074  // const auto right_string = HDL_manager::convert_to_identifier(this, right->get_id());
1075  // indented_output_stream->Append(left_string + " <= ");
1076  // if(left->get_typeRef()->type == right->get_typeRef()->type)
1077  // {
1078  // indented_output_stream->Append(right_string + ";\n");
1079  // }
1080  // /// This part fix the assignment between std_logic_vector of size 1 and std_logic
1081  // else if(left->get_typeRef()->type == structural_type_descriptor::BOOL and right->get_typeRef()->type ==
1082  // structural_type_descriptor::VECTOR_BOOL)
1083  // {
1084  // THROW_ASSERT(sig->get_typeRef()->size == 1, "Unexpected pattern");
1085  // indented_output_stream->Append(right_string + "(0);\n");
1086  // }
1087  // else if(left->get_owner() and left->get_owner()->get_kind() == port_vector_o_K)
1088  // {
1089  // indented_output_stream->Append(right_string + "(" + left->get_id() + ");\n");
1090  // }
1091  // else if(left->get_typeRef()->type == structural_type_descriptor::INT and right->get_typeRef()->type ==
1092  // structural_type_descriptor::VECTOR_BOOL)
1093  // {
1094  // indented_output_stream->Append("signed(" + right_string + ");\n");
1095  // }
1096  // else if(left->get_typeRef()->type == structural_type_descriptor::UINT and right->get_typeRef()->type ==
1097  // structural_type_descriptor::VECTOR_BOOL)
1098  // {
1099  // indented_output_stream->Append("unsigned(" + right_string + ");\n");
1100  // }
1101  // else if(left->get_typeRef()->type == structural_type_descriptor::REAL and right->get_typeRef()->type ==
1102  // structural_type_descriptor::VECTOR_BOOL)
1103  // {
1104  // indented_output_stream->Append(right_string + ";\n");
1105  // }
1106  // else if(left->get_typeRef()->type == structural_type_descriptor::VECTOR_BOOL and right->get_typeRef()->type ==
1107  // structural_type_descriptor::UINT)
1108  // {
1109  // indented_output_stream->Append("std_logic_vector(" + right_string + ");\n");
1110  // }
1111  // else
1112  // {
1113  // THROW_UNREACHABLE(left_string + "(" + left->get_typeRef()->get_name() + ") <= " + right_string + "(" +
1114  // right->get_typeRef()->get_name() + ")");
1115  // }
1116 }
1117 
1119 {
1120  THROW_ASSERT(port && port->get_kind() == port_vector_o_K, "Expected a port got something of different");
1121  THROW_ASSERT(port->get_owner(), "Expected a port with an owner");
1122  THROW_ASSERT(sig && sig->get_kind() == signal_vector_o_K, "Expected a signal got something of different");
1123  std::string port_string;
1124  std::string signal_string;
1125  signal_string = HDL_manager::convert_to_identifier(this, sig->get_id());
1126  port_string = HDL_manager::convert_to_identifier(this, port->get_id());
1127 
1128  if(GetPointer<port_o>(port)->get_port_direction() == port_o::IN)
1129  {
1130  std::swap(port_string, signal_string);
1131  }
1132 
1133  if(port_string != signal_string)
1134  {
1135  const auto left = GetPointer<port_o>(port)->get_port_direction() == port_o::IN ? sig : port;
1136  const auto right = GetPointer<port_o>(port)->get_port_direction() == port_o::IN ? port : sig;
1137  if(left->get_typeRef()->type == structural_type_descriptor::UINT and
1138  right->get_typeRef()->type == structural_type_descriptor::VECTOR_BOOL)
1139  {
1140  signal_string = "unsigned(" + signal_string + ")";
1141  }
1142  else if(left->get_typeRef()->type == structural_type_descriptor::INT and
1143  right->get_typeRef()->type == structural_type_descriptor::VECTOR_BOOL)
1144  {
1145  signal_string = "signed(" + signal_string + ")";
1146  }
1147  else if(left->get_typeRef()->type == structural_type_descriptor::VECTOR_BOOL and
1148  right->get_typeRef()->type == structural_type_descriptor::UINT)
1149  {
1150  signal_string = "std_logic_vector(" + signal_string + ")";
1151  }
1152  else if(left->get_typeRef()->type == structural_type_descriptor::BOOL and
1153  right->get_typeRef()->type == structural_type_descriptor::VECTOR_BOOL)
1154  {
1155  signal_string = "" + signal_string + "(0)";
1156  }
1157  indented_output_stream->Append(port_string + " <= " + signal_string + ";\n");
1158  }
1159 }
1160 
1162 {
1163  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Writing module generics of " + cir->get_path());
1164  THROW_ASSERT(cir->get_kind() == component_o_K || cir->get_kind() == channel_o_K,
1165  "Expected a component or a channel got something of different");
1166  auto* mod = GetPointer<module>(cir);
1168 
1169  bool first_it = true;
1170  if(mod->ExistsParameter(MEMORY_PARAMETER))
1171  {
1172  std::string memory_str = mod->GetParameter(MEMORY_PARAMETER);
1173  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Memory parameters are " + memory_str);
1174  std::vector<std::string> mem_tag = string_to_container<std::vector<std::string>>(memory_str, ";");
1175  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Found " + STR(mem_tag.size()) + " parameters");
1176  for(const auto& i : mem_tag)
1177  {
1178  std::vector<std::string> mem_add = string_to_container<std::vector<std::string>>(i, "=");
1179  THROW_ASSERT(mem_add.size() == 2, "malformed address");
1180  if(first_it)
1181  {
1182  indented_output_stream->Append(" generic map(");
1184  first_it = false;
1185  }
1186  else
1187  {
1189  }
1190  std::string name = mem_add[0];
1191  std::string value;
1192  if(mod->get_owner() && GetPointer<module>(mod->get_owner()) &&
1193  GetPointer<module>(mod->get_owner())->ExistsParameter(MEMORY_PARAMETER))
1194  {
1195  value = name;
1196  }
1197  else
1198  {
1199  value = mem_add[1];
1200  }
1201  indented_output_stream->Append(name + "=>(" + value + ")");
1202  }
1203  }
1204 
1205  const NP_functionalityRef& np = mod->get_NP_functionality();
1206  if(np)
1207  {
1208  std::vector<std::pair<std::string, structural_objectRef>> library_parameters;
1209  mod->get_NP_library_parameters(cir, library_parameters);
1210 
1211  for(const auto& library_parameter : library_parameters)
1212  {
1213  if(first_it)
1214  {
1215  indented_output_stream->Append(" generic map(");
1217  first_it = false;
1218  }
1219  else
1220  {
1222  }
1223  const std::string& name = library_parameter.first;
1224  structural_objectRef obj = library_parameter.second;
1225  if(obj)
1226  {
1230  {
1232  STR(obj->get_typeRef()->size));
1234  "=>" + STR(obj->get_typeRef()->vector_size));
1235  }
1236  else
1237  {
1239  STR(GET_TYPE_SIZE(obj)));
1240  if(obj->get_kind() == port_vector_o_K)
1241  {
1244  "=>" + STR(GetPointer<port_o>(obj)->get_ports_size()));
1245  }
1246  }
1247  }
1248  else
1249  {
1250  const auto parameter = mod->GetParameter(name);
1251  const auto parameter_type = mod->get_parameter_type(TM, name);
1252  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Parameter " + name + " has value " + parameter);
1253  switch(parameter_type)
1254  {
1256  {
1257  if(parameter.substr(0, 2) == "\"\"")
1258  {
1259  indented_output_stream->Append(name + "=>" + parameter.substr(1, parameter.size() - 2));
1260  }
1261  else
1262  {
1263  THROW_UNREACHABLE("");
1264  }
1265  break;
1266  }
1268  {
1269  if(parameter.front() == '\"' and parameter.back() == '\"')
1270  {
1271  indented_output_stream->Append(name + "=>" + parameter);
1272  }
1274  else if(mod->get_owner())
1275  {
1276  if(GetPointer<const module>(mod->get_owner()))
1277  {
1278  if(mod->get_owner()->ExistsParameter(parameter))
1279  {
1280 #if HAVE_ASSERTS
1281  const auto actual_parameter_type =
1282  GetPointer<const module>(mod->get_owner())->get_parameter_type(TM, parameter);
1283 #endif
1284  THROW_ASSERT(actual_parameter_type == parameter_type, "");
1285  }
1286  else if(mod->get_owner()->ExistsParameter(MEMORY_PARAMETER))
1287  {
1288 #if HAVE_ASSERTS
1289  bool found = false;
1290 #endif
1291  std::string memory_str = mod->get_owner()->GetParameter(MEMORY_PARAMETER);
1292  std::vector<std::string> mem_tag =
1293  string_to_container<std::vector<std::string>>(memory_str, ";");
1294  for(const auto& i : mem_tag)
1295  {
1296  std::vector<std::string> mem_add = string_to_container<std::vector<std::string>>(i, "=");
1297  THROW_ASSERT(mem_add.size() == 2, "malformed address");
1299  "---Checking owner memory parameter " + mem_add[0]);
1300  if(mem_add[0] == parameter)
1301  {
1308  THROW_ASSERT(mod->get_typeRef()->id_type == "constant_value",
1309  mod->get_typeRef()->id_type);
1310  THROW_ASSERT(mod->get_out_port_size() == 1, STR(mod->get_out_port_size()));
1312  name + "=> std_logic_vector(to_unsigned(" + parameter + ", " +
1313  STR(STD_GET_SIZE(mod->get_out_port(0)->get_typeRef())) + "))");
1314 #if HAVE_ASSERTS
1315  found = true;
1316 #endif
1317  break;
1318  }
1319  }
1320  THROW_ASSERT(found, parameter + " " + memory_str);
1321  break;
1322  }
1323  else
1324  {
1325  THROW_UNREACHABLE("");
1326  }
1327  }
1328  else
1329  {
1330  THROW_UNREACHABLE("");
1331  }
1332  }
1333  else
1334  {
1335  THROW_UNREACHABLE("");
1336  }
1337  break;
1338  }
1341  {
1342  if(parameter.front() == '\"' and parameter.back() == '\"')
1343  {
1344  long long int value = 0;
1345  long long int mult = 1;
1346  for(const auto digit : boost::adaptors::reverse(parameter.substr(1, parameter.size() - 2)))
1347  {
1348  if(digit == '1')
1349  {
1350  value += mult;
1351  }
1352  else if(digit == '0')
1353  {
1354  }
1355  else
1356  {
1357  THROW_UNREACHABLE(parameter);
1358  }
1359  mult *= 2;
1360  }
1361  indented_output_stream->Append(name + "=>" + STR(value));
1362  }
1363  else
1364  {
1365  indented_output_stream->Append(name + "=>" + parameter);
1366  }
1367  break;
1368  }
1377  {
1378  THROW_UNREACHABLE("Type of parameter " + parameter + " (" + STR(parameter_type) + ") not supported");
1379  break;
1380  }
1381  default:
1382  THROW_UNREACHABLE("");
1383  }
1384  }
1385  }
1386  }
1387  if(!first_it)
1388  {
1391  }
1392  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Written module generics of " + cir->get_path());
1393 }
1394 
1395 void VHDL_writer::write_state_declaration(const structural_objectRef&, const std::list<std::string>& list_of_states,
1396  const std::string&, const std::string& reset_state, bool one_hot)
1397 {
1398  auto it_end = list_of_states.end();
1399  size_t n_states = list_of_states.size();
1400  auto bitsnumber = language_writer::bitnumber(static_cast<unsigned int>(n_states - 1));
1402  unsigned max_value = 0;
1403  for(auto it = list_of_states.begin(); it != it_end; ++it)
1404  {
1405  max_value = std::max(max_value, static_cast<unsigned>(std::stoul(it->substr(strlen(STATE_NAME_PREFIX)))));
1406  }
1407  if(max_value != n_states - 1)
1408  {
1409  bitsnumber = language_writer::bitnumber(max_value);
1410  }
1411 
1412  write_comment("define the states of FSM model\n");
1413  if(one_hot or ((parameters->isOption(OPT_generate_vcd) and parameters->getOption<bool>(OPT_generate_vcd)) or
1414  (parameters->isOption(OPT_discrepancy) and parameters->getOption<bool>(OPT_discrepancy))))
1415  {
1416  for(const auto& state : list_of_states)
1417  {
1418  if(one_hot)
1419  {
1421  "constant " + state + ": std_logic_vector(" + STR(max_value) + " downto 0) := \"" +
1422  encode_one_hot(1 + max_value,
1423  static_cast<unsigned>(std::stoul(state.substr(strlen(STATE_NAME_PREFIX))))) +
1424  "\";\n");
1425  }
1426  else
1427  {
1429  "constant " + state + ": std_logic_vector(" + STR(bitsnumber - 1) + " downto 0) := \"" +
1430  NumberToBinaryString(std::stoul(state.substr(strlen(STATE_NAME_PREFIX))), bitsnumber) + "\";\n");
1431  }
1432  }
1433  if(one_hot)
1434  {
1435  indented_output_stream->Append("signal present_state : std_logic_vector(" + STR(max_value) +
1436  " downto 0) := " + reset_state + ";\n");
1437  indented_output_stream->Append("signal next_state : std_logic_vector(" + STR(max_value) + " downto 0);\n");
1438  }
1439  else
1440  {
1441  indented_output_stream->Append("signal present_state : std_logic_vector(" + STR(bitsnumber - 1) +
1442  " downto 0) := " + reset_state + ";\n");
1443  indented_output_stream->Append("signal next_state : std_logic_vector(" + STR(bitsnumber - 1) +
1444  " downto 0);\n");
1445  }
1446  }
1447  else
1448  {
1449  indented_output_stream->Append("type state_type is (");
1450  unsigned int count = 0;
1451  for(auto it = list_of_states.begin(); it != it_end; ++it)
1452  {
1454  count++;
1455  if(count != n_states)
1456  {
1458  }
1459  }
1460  indented_output_stream->Append(");\n");
1461  indented_output_stream->Append("signal present_state, next_state : state_type;\n");
1462  }
1463 }
1464 
1465 void VHDL_writer::write_present_state_update(const structural_objectRef, const std::string& reset_state,
1466  const std::string& reset_port, const std::string& clock_port,
1467  const std::string& reset_type, bool)
1468 {
1469  write_comment("concurrent process#1: state registers\n");
1470  if(reset_type == "no" || reset_type == "sync")
1471  {
1472  indented_output_stream->Append("state_reg: process(" + clock_port + ")\n");
1473  indented_output_stream->Append("begin\n");
1475  indented_output_stream->Append("if (" + clock_port + "'event and " + clock_port + "='1') then\n");
1477  if(!parameters->getOption<bool>(OPT_reset_level))
1478  {
1479  indented_output_stream->Append("if (" + reset_port + "='0') then\n");
1480  }
1481  else
1482  {
1483  indented_output_stream->Append("if (" + reset_port + "='1') then\n");
1484  }
1486  indented_output_stream->Append("present_state <= " + reset_state + ";\n");
1488  indented_output_stream->Append("else\n");
1490  indented_output_stream->Append("present_state <= next_state;\n");
1492  indented_output_stream->Append("end if;\n");
1493  }
1494  else
1495  {
1496  indented_output_stream->Append("state_reg: process(" + clock_port + ", " + reset_port + ")\n");
1497  indented_output_stream->Append("begin\n");
1499  if(!parameters->getOption<bool>(OPT_reset_level))
1500  {
1501  indented_output_stream->Append("if (" + reset_port + "='0') then\n");
1502  }
1503  else
1504  {
1505  indented_output_stream->Append("if (" + reset_port + "='1') then\n");
1506  }
1508  indented_output_stream->Append("present_state <= " + reset_state + ";\n");
1510  indented_output_stream->Append("elsif (" + clock_port + "'event and " + clock_port + "='1') then\n");
1512  indented_output_stream->Append("present_state <= next_state;\n");
1513  }
1515  indented_output_stream->Append("end if;\n");
1517  indented_output_stream->Append("end process;\n");
1518 }
1519 
1521  bool single_proc, unsigned int output_index, const structural_objectRef& cir, const std::string& reset_state,
1522  const std::string& reset_port, const std::string& start_port, const std::string& clock_port,
1523  std::vector<std::string>::const_iterator& first, std::vector<std::string>::const_iterator& end, bool,
1524  const std::map<unsigned int, std::map<std::string, std::set<unsigned int>>>& bypass_signals)
1525 {
1526  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Writing transition output function");
1527  auto* mod = GetPointer<module>(cir);
1528  boost::char_separator<char> state_sep(":", nullptr);
1529  boost::char_separator<char> sep(" ", nullptr);
1530  using tokenizer = boost::tokenizer<boost::char_separator<char>>;
1531 
1533 
1534  write_comment("concurrent process#" + STR(output_index) + ": combinational logic\n");
1535  indented_output_stream->Append("comb_logic" + STR(output_index) + ": process(present_state");
1536  for(unsigned int i = 0; i < mod->get_in_port_size(); i++)
1537  {
1538  std::string port_name = HDL_manager::convert_to_identifier(this, mod->get_in_port(i)->get_id());
1539  if(port_name != clock_port and port_name != reset_port)
1540  {
1541  indented_output_stream->Append(", " + port_name);
1542  }
1543  }
1545 
1546  indented_output_stream->Append("begin\n");
1548 
1550  std::string default_output;
1551  for(unsigned int i = 0; i < mod->get_out_port_size(); i++)
1552  {
1553  if(mod->get_out_port(i)->get_id() == PRESENT_STATE_PORT_NAME)
1554  {
1555  continue;
1556  }
1557  if(mod->get_out_port(i)->get_id() == NEXT_STATE_PORT_NAME)
1558  {
1559  continue;
1560  }
1561  default_output += "0";
1562  if(!single_proc && output_index != i)
1563  {
1564  continue;
1565  }
1566  std::string port_name = HDL_manager::convert_to_identifier(this, mod->get_out_port(i)->get_id());
1567  indented_output_stream->Append(port_name + " <= '0';\n");
1568  }
1569  if(single_proc || output_index == mod->get_out_port_size())
1570  {
1571  indented_output_stream->Append("next_state <= " + reset_state + ";\n");
1572  }
1573 
1574  indented_output_stream->Append("case present_state is\n");
1576 
1577  for(auto first_it = first; first_it != end; ++first_it)
1578  {
1579  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Writing " + *first_it);
1580  tokenizer state_tokens_first(*first_it, state_sep);
1581 
1582  tokenizer::const_iterator its = state_tokens_first.begin();
1583 
1584  std::string state_description = *its;
1585  ++its;
1586 
1587  std::vector<std::string> state_transitions;
1588  for(; its != state_tokens_first.end(); ++its)
1589  {
1590  state_transitions.push_back(*its);
1591  }
1592 
1593  tokenizer tokens_curr(state_description, sep);
1595  its = tokens_curr.begin();
1596  std::string present_state = HDL_manager::convert_to_identifier(this, *its);
1598  ++its;
1599  std::string current_output = *its;
1600 
1602  bool skip_state = !single_proc && output_index != mod->get_out_port_size() &&
1603  default_output[output_index] == current_output[output_index];
1604  bool skip_state_transition = !single_proc && output_index != mod->get_out_port_size();
1605  if(!single_proc && output_index != mod->get_out_port_size())
1606  {
1607  for(const auto& current_transition : state_transitions)
1608  {
1609  tokenizer transition_tokens(current_transition, sep);
1610  tokenizer::const_iterator itt = transition_tokens.begin();
1611 
1612  // std::string current_input;
1613  tokenizer::const_iterator current_input_it;
1614  std::string input_string = *itt;
1615  if(mod->get_in_port_size() - 3) // clock and reset are always present
1616  {
1617  boost::char_separator<char> comma_sep(",", nullptr);
1618  tokenizer current_input_tokens(input_string, comma_sep);
1619  current_input_it = current_input_tokens.begin();
1620  ++itt;
1621  }
1622  ++itt;
1623  std::string transition_outputs = *itt;
1624  ++itt;
1625  THROW_ASSERT(itt == transition_tokens.end(), "Bad transition format");
1626  if(transition_outputs[output_index] != '-')
1627  {
1628  skip_state = false;
1629  skip_state_transition = false;
1630  }
1631  }
1632  }
1633  if(skip_state)
1634  {
1635  continue;
1636  }
1637 
1638  indented_output_stream->Append("when " + present_state + " =>\n");
1640 
1641  if(reset_state == present_state)
1642  {
1643  indented_output_stream->Append("if(" + start_port + " /= '1') then\n");
1644  for(unsigned int i = 0; i < mod->get_out_port_size(); i++)
1645  {
1646  if(mod->get_out_port(i)->get_id() == PRESENT_STATE_PORT_NAME)
1647  {
1648  continue;
1649  }
1650  if(mod->get_out_port(i)->get_id() == NEXT_STATE_PORT_NAME)
1651  {
1652  continue;
1653  }
1654  if(starts_with(mod->get_out_port(i)->get_id(), "selector_MUX") ||
1655  starts_with(mod->get_out_port(i)->get_id(), "wrenable_reg"))
1656  {
1657  auto port_name = HDL_manager::convert_to_identifier(this, mod->get_out_port(i)->get_id());
1658  if(single_proc || output_index == i)
1659  {
1660  indented_output_stream->Append(" " + port_name + " <= 'X';\n");
1661  }
1662  }
1663  }
1664  if(single_proc || output_index == mod->get_out_port_size())
1665  {
1666  indented_output_stream->Append(" next_state <= " + present_state + ";\n");
1667  }
1668  indented_output_stream->Append("else\n");
1670  }
1671 
1672  bool unique_transition = (state_transitions.size() == 1);
1673  if(current_output != default_output && (single_proc || !unique_transition || skip_state_transition))
1674  {
1675  for(unsigned int i = 0; i < mod->get_out_port_size(); i++)
1676  {
1677  if(mod->get_out_port(i)->get_id() == PRESENT_STATE_PORT_NAME)
1678  {
1679  continue;
1680  }
1681  if(mod->get_out_port(i)->get_id() == NEXT_STATE_PORT_NAME)
1682  {
1683  continue;
1684  }
1685  std::string port_name = HDL_manager::convert_to_identifier(this, mod->get_out_port(i)->get_id());
1686  if(default_output[i] != current_output[i])
1687  {
1688  if(single_proc || output_index == i)
1689  {
1690  switch(current_output[i])
1691  {
1692  case '1':
1693  {
1694  if(bypass_signals.find(i) == bypass_signals.end() ||
1695  bypass_signals.find(i)->second.find(present_state) == bypass_signals.find(i)->second.end())
1696  {
1697  indented_output_stream->Append(port_name + " <= '1';\n");
1698  }
1699  else
1700  {
1701  indented_output_stream->Append(port_name + " <= ");
1702  for(const auto& stateIns : bypass_signals.find(i)->second)
1703  {
1704  if(stateIns.first != present_state)
1705  {
1706  continue;
1707  }
1708  bool first_i = true;
1709  for(const auto& in : stateIns.second)
1710  {
1711  if(first_i)
1712  {
1713  first_i = false;
1714  }
1715  else
1716  {
1717  indented_output_stream->Append(" or ");
1718  }
1719  auto in_port_name =
1720  HDL_manager::convert_to_identifier(this, mod->get_in_port(in)->get_id());
1721  indented_output_stream->Append(in_port_name);
1722  }
1723  }
1725  }
1726  break;
1727  }
1728  case '2':
1729  indented_output_stream->Append(port_name + " <= 'X';\n");
1730  break;
1731 
1732  default:
1733  THROW_ERROR("Unsupported value in current output");
1734  break;
1735  }
1736  }
1737  }
1738  }
1739  }
1740 
1741  if(!skip_state_transition)
1742  {
1743  for(unsigned int i = 0; i < state_transitions.size(); i++)
1744  {
1745  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Writing transition " + state_transitions[i]);
1746  // std::cerr << " transition '" << state_transitions[i] << "'" << std::endl;
1747  tokenizer transition_tokens(state_transitions[i], sep);
1748  tokenizer::const_iterator itt = transition_tokens.begin();
1749  THROW_ASSERT(itt != transition_tokens.end(), "");
1750 
1751  // std::string current_input;
1752  tokenizer::const_iterator current_input_it;
1753  std::string input_string = *itt;
1754  if(mod->get_in_port_size() - 3) // clock and reset are always present
1755  {
1756  boost::char_separator<char> comma_sep(",", nullptr);
1757  tokenizer current_input_tokens(input_string, comma_sep);
1758  current_input_it = current_input_tokens.begin();
1759  ++itt;
1760  }
1761  THROW_ASSERT(itt != transition_tokens.end(), "");
1762  std::string next_state = HDL_manager::convert_to_identifier(this, *itt);
1763  ++itt;
1764  THROW_ASSERT(itt != transition_tokens.end(), "");
1765  std::string transition_outputs = *itt;
1766  ++itt;
1767  THROW_ASSERT(itt == transition_tokens.end(), "Bad transition format");
1768 
1769  if(!unique_transition)
1770  {
1771  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Not single transition");
1772  if(i == 0)
1773  {
1774  indented_output_stream->Append("if (");
1775  }
1776  else if((i + 1) == state_transitions.size())
1777  {
1778  indented_output_stream->Append("else\n");
1779  }
1780  else
1781  {
1782  indented_output_stream->Append("elsif (");
1783  }
1784  if((i + 1) < state_transitions.size())
1785  {
1786  bool first_test = true;
1787  for(unsigned int ind = 0; ind < mod->get_in_port_size(); ind++)
1788  {
1789  std::string port_name = HDL_manager::convert_to_identifier(this, mod->get_in_port(ind)->get_id());
1790  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Considering port " + port_name);
1791  auto port_size = mod->get_in_port(ind)->get_typeRef()->size;
1792  auto vec_size = mod->get_in_port(ind)->get_typeRef()->vector_size;
1793  if(port_name != reset_port && port_name != clock_port && port_name != start_port)
1794  {
1795  std::string in_or_conditions = *current_input_it;
1796  boost::char_separator<char> pipe_sep("|", nullptr);
1797  tokenizer in_or_conditions_tokens(in_or_conditions, pipe_sep);
1798  THROW_ASSERT(in_or_conditions_tokens.begin() != in_or_conditions_tokens.end(), "");
1799 
1800  if((*in_or_conditions_tokens.begin()) != "-")
1801  {
1802  if(!first_test)
1803  {
1804  indented_output_stream->Append(" and ");
1805  }
1806  else
1807  {
1808  first_test = false;
1809  }
1810  bool first_test_or = true;
1811  bool need_parenthesis = false;
1812  std::string res_or_conditions;
1813  for(tokenizer::const_iterator in_or_conditions_tokens_it = in_or_conditions_tokens.begin();
1814  in_or_conditions_tokens_it != in_or_conditions_tokens.end();
1815  ++in_or_conditions_tokens_it)
1816  {
1817  THROW_ASSERT((*in_or_conditions_tokens_it) != "-", "wrong conditions structure");
1818  if(!first_test_or)
1819  {
1820  res_or_conditions += " or ";
1821  need_parenthesis = true;
1822  }
1823  else
1824  {
1825  first_test_or = false;
1826  }
1827 
1828  res_or_conditions += port_name;
1829  if((*in_or_conditions_tokens_it)[0] == '&')
1830  {
1831  auto pos = std::stoull((*in_or_conditions_tokens_it).substr(1));
1832  res_or_conditions += std::string("(") + STR(pos) + ") = '1'";
1833  }
1834  else
1835  {
1836  res_or_conditions +=
1837  std::string(" = ") + ((*in_or_conditions_tokens_it)[0] == '-' ? "-" : "");
1838  if(port_size > 1 || (port_size == 1 && vec_size > 0))
1839  {
1840  res_or_conditions +=
1841  "\"" +
1842  NumberToBinaryString(llabs(std::stoll(*in_or_conditions_tokens_it)),
1843  port_size) +
1844  "\"";
1845  }
1846  else
1847  {
1848  res_or_conditions += "'" + *in_or_conditions_tokens_it + "'";
1849  }
1850  }
1851  }
1852  if(need_parenthesis)
1853  {
1854  res_or_conditions = "(" + res_or_conditions + ")";
1855  }
1856  indented_output_stream->Append(res_or_conditions);
1857  }
1858  ++current_input_it;
1859  }
1860  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Considered port " + port_name);
1861  }
1862  indented_output_stream->Append(") then\n");
1863  }
1865  }
1866  if(single_proc || output_index == mod->get_out_port_size())
1867  {
1868  indented_output_stream->Append("next_state <= " + next_state + ";\n");
1869  }
1870  for(unsigned int i2 = 0; i2 < mod->get_out_port_size(); i2++)
1871  {
1872  if(mod->get_out_port(i2)->get_id() == PRESENT_STATE_PORT_NAME)
1873  {
1874  continue;
1875  }
1876  if(mod->get_out_port(i2)->get_id() == NEXT_STATE_PORT_NAME)
1877  {
1878  continue;
1879  }
1880  if(transition_outputs[i2] != '-')
1881  {
1882  std::string port_name = HDL_manager::convert_to_identifier(this, mod->get_out_port(i2)->get_id());
1883  if(single_proc || output_index == i2)
1884  {
1885  if(transition_outputs[i2] == '2')
1886  {
1887  indented_output_stream->Append(port_name + " <= 'X';\n");
1888  }
1889  else if(transition_outputs[i2] == '1')
1890  {
1891  if(bypass_signals.find(i2) == bypass_signals.end() ||
1892  bypass_signals.find(i2)->second.find(present_state) == bypass_signals.find(i2)->second.end())
1893  {
1894  indented_output_stream->Append(port_name + " <= '1';\n");
1895  }
1896  else
1897  {
1898  indented_output_stream->Append(port_name + " <= ");
1899  for(const auto& stateIns : bypass_signals.find(i2)->second)
1900  {
1901  if(stateIns.first != present_state)
1902  {
1903  continue;
1904  }
1905  bool first_i = true;
1906  for(const auto& in : stateIns.second)
1907  {
1908  if(first_i)
1909  {
1910  first_i = false;
1911  }
1912  else
1913  {
1914  indented_output_stream->Append(" or ");
1915  }
1916  auto in_port_name =
1917  HDL_manager::convert_to_identifier(this, mod->get_in_port(in)->get_id());
1918  indented_output_stream->Append(in_port_name);
1919  }
1920  }
1922  }
1923  }
1924  else
1925  {
1926  indented_output_stream->Append(port_name + " <= '0';\n");
1927  }
1928  }
1929  }
1930  }
1932  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Written transition " + state_transitions[i]);
1933  }
1934  if(!unique_transition)
1935  {
1936  indented_output_stream->Append("end if;\n");
1938  }
1939  }
1940  else
1941  {
1943  }
1944  if(reset_state == present_state)
1945  {
1946  indented_output_stream->Append("end if;\n");
1948  }
1950  }
1951 
1953  indented_output_stream->Append("when others =>\n");
1954  for(unsigned int i = 0; i < mod->get_out_port_size(); i++)
1955  {
1956  if(mod->get_out_port(i)->get_id() == PRESENT_STATE_PORT_NAME)
1957  {
1958  continue;
1959  }
1960  if(mod->get_out_port(i)->get_id() == NEXT_STATE_PORT_NAME)
1961  {
1962  continue;
1963  }
1964  if(starts_with(mod->get_out_port(i)->get_id(), "selector_MUX") ||
1965  starts_with(mod->get_out_port(i)->get_id(), "wrenable_reg"))
1966  {
1967  auto port_name = HDL_manager::convert_to_identifier(this, mod->get_out_port(i)->get_id());
1968  if(single_proc || output_index == i)
1969  {
1970  indented_output_stream->Append(" " + port_name + " <= 'X';\n");
1971  }
1972  }
1973  }
1974 
1976  indented_output_stream->Append("end case;\n");
1978  indented_output_stream->Append("end process;\n");
1979  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Written transition output function");
1980 }
1981 
1982 void VHDL_writer::write_assign(const std::string&, const std::string&)
1983 {
1984  THROW_ERROR("Not yet implemented");
1985 }
1986 
1988 {
1989  auto* mod = GetPointer<module>(cir);
1990  THROW_ASSERT(mod, "Expected a component object");
1991  const NP_functionalityRef& np = mod->get_NP_functionality();
1992  THROW_ASSERT(np, "NP Behavioral description is missing for module: " +
1994  std::string beh_desc = np->get_NP_functionality(NP_functionality::VHDL_PROVIDED);
1995  THROW_ASSERT(beh_desc != "", "VHDL behavioral description is missing for module: " +
1998  if(!parameters->getOption<bool>(OPT_reset_level))
1999  {
2000  boost::replace_all(beh_desc, "1RESET_VALUE", std::string(RESET_PORT_NAME) + " = '0'");
2001  }
2002  else
2003  {
2004  boost::replace_all(beh_desc, "1RESET_VALUE", std::string(RESET_PORT_NAME) + " = '1'");
2005  }
2006  if(parameters->getOption<bool>(OPT_reg_init_value))
2007  {
2008  boost::replace_all(beh_desc, "1INIT_ZERO_VALUEb", ":= '0'");
2009  boost::replace_all(beh_desc, "1INIT_ZERO_VALUE", ":= (others => '0')");
2010  }
2011  else
2012  {
2013  boost::replace_all(beh_desc, "1INIT_ZERO_VALUEb", "");
2014  boost::replace_all(beh_desc, "1INIT_ZERO_VALUE", "");
2015  }
2016  indented_output_stream->Append(beh_desc);
2017 }
2018 
2020 {
2021  indented_output_stream->Append("port (\n");
2023 }
2024 
2026 {
2028  indented_output_stream->Append("\n);\n");
2029 }
2030 
2032 {
2033  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Writing generics of entity " + cir->get_id());
2034  THROW_ASSERT(cir->get_kind() == component_o_K || cir->get_kind() == channel_o_K,
2035  "Expected a component or a channel got something of different");
2036  auto* mod = GetPointer<module>(cir);
2037  bool first_it = true;
2039  if(mod->ExistsParameter(MEMORY_PARAMETER) and mod->GetParameter(MEMORY_PARAMETER) != "")
2040  {
2041  indented_output_stream->Append("generic(\n");
2042  std::string memory_str = mod->GetParameter(MEMORY_PARAMETER);
2043  std::vector<std::string> mem_tag = string_to_container<std::vector<std::string>>(memory_str, ";");
2044  for(const auto& i : mem_tag)
2045  {
2046  std::vector<std::string> mem_add = string_to_container<std::vector<std::string>>(i, "=");
2047  THROW_ASSERT(mem_add.size() == 2, "malformed address");
2048  if(first_it)
2049  {
2050  first_it = false;
2051  }
2052  else
2053  {
2055  }
2056  std::string name = mem_add[0];
2057  std::string value = mem_add[1];
2058  auto binary_value = NumberToBinaryString(std::stoull(value));
2059  indented_output_stream->Append(" " + name + ": integer := " + value);
2060  }
2061  }
2062 
2063  const NP_functionalityRef& np = mod->get_NP_functionality();
2064  if(np)
2065  {
2066  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Considering parameters");
2067  std::vector<std::pair<std::string, structural_objectRef>> library_parameters;
2068  mod->get_NP_library_parameters(cir, library_parameters);
2069  if(library_parameters.size() and first_it)
2070  {
2071  indented_output_stream->Append("generic(\n");
2072  }
2073  for(const auto& library_parameter : library_parameters)
2074  {
2075  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Considering parameter " + library_parameter.first);
2076  if(first_it)
2077  {
2078  first_it = false;
2079  }
2080  else
2081  {
2083  }
2084  const std::string& name = library_parameter.first;
2085  structural_objectRef obj = library_parameter.second;
2086  if(obj)
2087  {
2088  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Object of type " + obj->get_kind_text());
2092  {
2094  std::string(" ") + HDL_manager::convert_to_identifier(this, BITSIZE_PREFIX + name) + ": integer");
2096  ";\n " + HDL_manager::convert_to_identifier(this, NUM_ELEM_PREFIX + name) + ": integer");
2097  }
2098  else
2099  {
2101  std::string(" ") + HDL_manager::convert_to_identifier(this, BITSIZE_PREFIX + name) + ": integer");
2102  if(obj->get_kind() == port_vector_o_K)
2103  {
2105  ";\n " + HDL_manager::convert_to_identifier(this, PORTSIZE_PREFIX + name) + ": integer");
2106  }
2107  }
2108  }
2109  else
2110  {
2111  const auto parameter = mod->GetDefaultParameter(name);
2112  const auto parameter_type = mod->get_parameter_type(TM, name);
2114  "---Parameter " + name + " has default value " + parameter);
2115  switch(parameter_type)
2116  {
2118  {
2119  indented_output_stream->Append(" " + name + ": integer");
2120  break;
2121  }
2123  {
2124  indented_output_stream->Append(" " + name + ": string");
2125  break;
2126  }
2128  {
2129  indented_output_stream->Append(" " + name + ": std_logic_vector");
2130  break;
2131  }
2133  {
2134  indented_output_stream->Append(" " + name + ": real");
2135  break;
2136  }
2145  default:
2146  THROW_UNREACHABLE("");
2147  }
2148  }
2149  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Considered parameter " + library_parameter.first);
2150  }
2151  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Considered parameters");
2153  }
2154  if(!first_it)
2155  {
2156  indented_output_stream->Append(");\n");
2157  }
2158  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Written generics of entity " + cir->get_id());
2159 }
2160 
2161 bool VHDL_writer::check_keyword(const std::string& id) const
2162 {
2163  return check_keyword_vhdl(id);
2164 }
2165 
2166 bool VHDL_writer::check_keyword_vhdl(const std::string& id)
2167 {
2168  return keywords.count(boost::to_upper_copy(id));
2169 }
2170 
2171 void VHDL_writer::WriteBuiltin(const structural_objectConstRef component)
2172 {
2174  "-->Writing builtin component " + component->get_path() + " of type " + GET_TYPE_NAME(component));
2175  std::string operand;
2176  if(GET_TYPE_NAME(component) == OR_GATE_STD)
2177  {
2178  operand = "or";
2179  }
2180  else if(GET_TYPE_NAME(component) == AND_GATE_STD)
2181  {
2182  operand = "and";
2183  }
2184  else
2185  {
2186  THROW_UNREACHABLE(GET_TYPE_NAME(component));
2187  }
2188  const auto mod = GetPointer<const module>(component);
2189  THROW_ASSERT(mod, component->get_path() + " is not a module");
2190  THROW_ASSERT(GetPointer<const port_o>(mod->get_out_port(0)), "Not a port");
2191  const auto object_bounded =
2192  GetPointer<const port_o>(mod->get_out_port(0))->find_bounded_object(component->get_owner());
2193  THROW_ASSERT(object_bounded, "Object bounded to output not found");
2194  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Output bounded object is " + object_bounded->get_path());
2195  THROW_ASSERT(mod->get_out_port_size() == 1,
2196  component->get_path() + " has " + STR(mod->get_out_port_size()) + " output ports");
2197  indented_output_stream->Append(HDL_manager::convert_to_identifier(this, object_bounded->get_id()) + " <= ");
2198  for(unsigned int i = 0; i < mod->get_in_port_size(); i++)
2199  {
2200  if(i != 0)
2201  {
2202  indented_output_stream->Append(" " + operand + " ");
2203  }
2204  if(mod->get_in_port(i)->get_kind() == port_o_K)
2205  {
2206  const auto in_object_bounded =
2207  GetPointer<port_o>(mod->get_in_port(i))->find_bounded_object(component->get_owner());
2208  indented_output_stream->Append(HDL_manager::convert_to_identifier(this, in_object_bounded->get_id()));
2209  }
2210  else if(mod->get_in_port(i)->get_kind() == port_vector_o_K)
2211  {
2212  const auto port = GetPointer<port_o>(mod->get_in_port(i));
2213  const auto in_object_bounded = port->find_bounded_object(component);
2214  if(in_object_bounded)
2215  {
2216  indented_output_stream->Append(HDL_manager::convert_to_identifier(this, in_object_bounded->get_id()));
2217  }
2218  else
2219  {
2220  auto n_ports = port->get_ports_size();
2221  for(decltype(n_ports) port_index = 0; port_index < n_ports; port_index++)
2222  {
2223  if(i != 0 or port_index != 0)
2224  {
2225  indented_output_stream->Append(" " + operand + " ");
2226  }
2227  const auto vec_in_object_bounded = GetPointer<port_o>(port->get_port(port_index))->find_bounded_object();
2228  THROW_ASSERT(vec_in_object_bounded, "");
2230  HDL_manager::convert_to_identifier(this, vec_in_object_bounded->get_id()));
2231  }
2232  }
2233  }
2234  else
2235  {
2236  THROW_UNREACHABLE("");
2237  }
2238  }
2241  "<--Written builtin component " + component->get_path() + " of type " + GET_TYPE_NAME(component));
2242 }
2243 
2245 {
2247  indented_output_stream->Append("library IEEE;\n");
2248  indented_output_stream->Append("use IEEE.numeric_std.all;\n");
2250  indented_output_stream->Append("package panda_pkg is\n");
2251  indented_output_stream->Append(" function resize_signed(input : signed; size : integer) return signed;\n");
2252  indented_output_stream->Append("end;\n");
2254  indented_output_stream->Append("package body panda_pkg is\n");
2255  indented_output_stream->Append(" function resize_signed(input : signed; size : integer) return signed is\n");
2256  indented_output_stream->Append(" begin\n");
2257  indented_output_stream->Append(" if (size > input'length) then\n");
2258  indented_output_stream->Append(" return resize(input, size);\n");
2259  indented_output_stream->Append(" else\n");
2260  indented_output_stream->Append(" return input(size-1+input'right downto input'right);\n");
2261  indented_output_stream->Append(" end if;\n");
2262  indented_output_stream->Append(" end function;\n");
2263  indented_output_stream->Append("end package body;\n");
2265 }
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.
void write_library_declaration(const structural_objectRef &cir) override
Write used library.
void write_module_parametrization_decl(const structural_objectRef &cir) override
Write the declaration of the module parameters.
#define PRESENT_STATE_PORT_NAME
#define DEBUG_LEVEL_VERY_PEDANTIC
extremely verbose debugging print is performed.
#define PORTSIZE_PREFIX
#define OR_GATE_STD
#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.
File containing functions and utilities to support the printing of debug messagges.
#define NEXT_STATE_PORT_NAME
This file contains the structures needed to manage a graph that will represent the state transition g...
const std::string & get_id() const
Return the identifier associated with the structural_object.
#define GET_CLASS(obj)
Macro returning the actual type of an object.
void write_module_parametrization(const structural_objectRef &cir) override
Module can be parametrized with respect different features.
#define AND_GATE_STD
void write_port_decl_header() override
Write the header for port_decl.
int debug_level
debugging level of the class
static const std::set< std::string > keywords
Definition: VHDL_writer.hpp:57
This class defines the methods to write VHDL descriptions.
void write_vector_port_binding(const structural_objectRef &port, bool first_port_analyzed) override
std::string get_NP_functionality(NP_functionaly_type type) const
Return the description provided the type.
#define MEMORY_PARAMETER
void Indent()
Manually increase the indenting of the code.
void write_module_instance_begin(const structural_objectRef &cir, const std::string &module_name, bool write_parametrization) override
Write the initial part of the instance of a module.
~VHDL_writer() override
Destructor.
std::string type_converter(structural_type_descriptorRef Type) override
Return a language based type string given a structural_type_descriptor.
Definition: VHDL_writer.cpp:94
exceptions managed by PandA
void write_transition_output_functions(bool single_proc, unsigned int output_index, const structural_objectRef &cir, const std::string &reset_state, const std::string &reset_port, const std::string &start_port, const std::string &clock_port, std::vector< std::string >::const_iterator &first, std::vector< std::string >::const_iterator &end, bool, const std::map< unsigned int, std::map< std::string, std::set< unsigned int >>> &bypass_signals) override
Write the transition and output functions.
Class to print indented code.
const IndentedOutputStreamRef indented_output_stream
Represents the stream we are currently writing to.
std::string NumberToBinaryString(const T number, const size_t precision=0)
Function which print number in binary format.
void write_module_internal_declaration(const structural_objectRef &cir) override
Write the declaration of internal objects of the module.
VHDL_writer(const technology_managerConstRef TM, const ParameterConstRef parameters)
Constructor.
Definition: VHDL_writer.cpp:81
void write_module_instance_end(const structural_objectRef &cir) override
Write the ending part of the instance of a module.
#define GET_TYPE_NAME(structural_obj)
Macro returning the string name of a type.
#define BITSIZE_PREFIX
#define STR(s)
Macro which performs a lexical_cast to a string.
void write_module_declaration(const structural_objectRef &cir) override
Write the declaration of the module.
Auxiliary methods for manipulating string.
#define max
Definition: backprop.h:17
s_type type
The type of the port or the signal.
port_direction
Enumerative type describing the direction of a port.
unsigned long long size
The size of the object (in bit). The objects having a size are: ports, signals, channels, data, and actions.
void write_io_signal_post_fix(const structural_objectRef &port, const structural_objectRef &sig) override
Write some code managing primary ports to signals connections.
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
bool starts_with(const std::string &str, const std::string &pattern)
void write_header() override
Write the header of vhdl file.
s_type
Define the possible type of a structural object.
unsigned map[NUM_VERTICES]
Definition: bfs.c:12
void write_comment(const std::string &comment_string) override
Print a comment.
Definition: VHDL_writer.cpp:89
void Append(const std::string &str)
Append a string to the output.
#define NUM_ELEM_PREFIX
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.
void write_state_declaration(const structural_objectRef &cir, const std::list< std::string > &list_of_states, const std::string &reset_port, const std::string &reset_state, bool one_hot) override
write the declaration of all the states of the finite state machine.
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
#define STD_OPENING_CHAR
STD include.
static bool check_keyword_vhdl(const std::string &id)
void WriteBuiltin(const structural_objectConstRef component) override
Write a builtin component.
void write_component_declaration(const structural_objectRef &cir) override
Write the declaration of a component.
void write_assign(const std::string &op0, const std::string &op1) override
#define GET_TYPE_SIZE(structural_obj)
Macro returning the size of the type of a structural object.
void write_io_signal_post_fix_vector(const structural_objectRef &port, const structural_objectRef &sig) override
std::string id_type
Original type id of the structural object.
void write_present_state_update(const structural_objectRef cir, const std::string &reset_state, const std::string &reset_port, const std::string &clock_port, const std::string &reset_type, bool connect_present_next_state_signals) override
write the present_state update process
This class describes all classes used to represent a structural object.
const structural_type_descriptorRef & get_typeRef() const
Return the type descriptor of the structural_object.
std::string encode_one_hot(unsigned int n_states, unsigned int val) const
#define STATE_NAME_PREFIX
state name prefix
void write_port_decl_tail() override
Write the tail for port_decl.
const structural_objectRef get_owner() const
Return the owner.
std::string type_converter_size(const structural_objectRef &cir) override
Return a language based type string given a structural_type_descriptor for the range of the array...
CustomOrderedSet< std::string > list_of_comp_already_def
Definition: VHDL_writer.hpp:59
static unsigned int bitnumber(unsigned long long n)
Counts the number of bits in an unsigned int.
const ParameterConstRef parameters
the set of input parameters
void write_module_definition_end(const structural_objectRef &cir) override
Write the end part in a module declaration.
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.
this class is used to manage the command-line or XML options.
Not parsed functionality manager.
void Deindent()
Manually reduce the indenting of the code.
#define RESET_PORT_NAME
void write_port_binding(const structural_objectRef &port, const structural_objectRef &object_bounded, bool first_port_analyzed) override
Write the binding of a port.
void write_signal_declaration(const structural_objectRef &cir) override
Write the declaration of a signal.
const technology_managerConstRef TM
The technology manager.
Definition: VHDL_writer.hpp:62
This class writes different HDL based descriptions (VHDL, Verilog, SystemC) starting from a structura...
std::string may_slice_string(const structural_objectRef &cir)
return the slice in case of a port owned by a port vector
void print(std::ostream &os) const
function that prints the class.
bool check_keyword(const std::string &) const override
void write_module_definition_begin(const structural_objectRef &cir) override
Write the top constructor declaration.
const std::string get_name() const
Returns the name of the type descriptor.
void write_NP_functionalities(const structural_objectRef &cir) override
Write in the proper language the behavioral description of the module described in "Not Parsed" form...
void write_port_declaration(const structural_objectRef &cir, bool last_port_to_analyze) override
Write the port declaration starting from a port object.
unsigned long long vector_size
The number of the elements of a vector.
#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