PandA-2024.02
verilog_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  */
44 #include "verilog_writer.hpp"
45 
46 #include "config_HAVE_FROM_C_BUILT.hpp"
47 
48 #include "HDL_manager.hpp"
49 #include "NP_functionality.hpp"
50 #include "Parameter.hpp"
51 #include "dbgPrintHelper.hpp"
52 #include "exceptions.hpp"
55 #include "string_manipulation.hpp"
56 #include "structural_objects.hpp"
57 #include "technology_manager.hpp"
58 #include "technology_node.hpp"
60 #include "time_info.hpp"
61 
62 #include <algorithm>
63 #include <boost/algorithm/string.hpp>
64 #include <boost/tokenizer.hpp>
65 #include <fstream>
66 #include <functional>
67 #include <iosfwd>
68 #include <limits>
69 #include <utility>
70 
71 #define VERILOG_2001_SUPPORTED
72 
73 const std::map<std::string, std::string> verilog_writer::builtin_to_verilog_keyword = {
74  {AND_GATE_STD, "and"}, {NAND_GATE_STD, "nand"}, {OR_GATE_STD, "or"},
75  {NOR_GATE_STD, "nor"}, {XOR_GATE_STD, "xor"}, {XNOR_GATE_STD, "xnor"},
76  {NOT_GATE_STD, "not"}, {DFF_GATE_STD, "dff"}, {BUFF_GATE_STD, "buf"},
77 };
78 
79 const std::set<std::string> verilog_writer::keywords = {
80  "abs", "abstol", "access", "acos", "acosh", "always", "analog", "and", "asin", "asinh", "assign", "atan", "atan2",
81  "atanh", "automatic", "begin", "bool", "buf", "bufif0", "bufif1", "case", "casex", "casez", "ceil", "cell", "cmos",
82  "config", "continuous", "cos", "cosh", "ddt_nature", "deassign", "default", "defparam", "design", "disable",
83  "discipline", "discrete", "domain", "edge", "else", "end", "endcase", "endconfig", "enddiscipline", "endfunction",
84  "endgenerate", "endmodule", "endnature", "endprimitive", "endspecify", "endtable", "endtask", "event", "exclude",
85  "exp", "floor", "flow", "for", "force", "forever", "fork", "from", "function", "generate", "genvar", "ground",
86  "highz0", "highz1", "hypot", "idt_nature", "if", "ifnone", "incdir", "include", "inf", "initial", "inout", "input",
87  "instance", "integer", "join", "large", "liblist", "library", "ln", "localparam", "log", "macromodule", "max",
88  "medium", "min", "module", "nand", "nature", "negedge", "nmos", "nor", "noshowcancelled", "not", "notif0", "notif1",
89  "or", "output", "parameter", "pmos", "posedge", "potential", "pow", "primitive", "pull0", "pull1", "pulldown",
90  "pullup", "pulsestyle_onevent", "pulsestyle_ondetect", "rcmos", "real", "realtime", "reg", "release", "repeat",
91  "rnmos", "rpmos", "rtran", "rtranif0", "rtranif1", "scalared", "showcancelled", "signed", "sin", "sinh", "small",
92  "specify", "specparam", "sqrt", "strong0", "strong1", "supply0", "supply1", "table", "tan", "tanh", "task", "time",
93  "tran", "tranif0", "tranif1", "tri", "tri0", "tri1", "triand", "trior", "trireg", "units", "unsigned", "use",
94  "uwire", "vectored", "wait", "wand", "weak0", "weak1", "while", "wire", "wone", "wor", "xnor", "xor",
96  "alias", "always_comb", "always_ff", "always_latch", "assert", "assume", "before", "bind", "bins", "binsof", "bit",
97  "break", "byte", "chandle", "class", "clocking", "const", "constraint", "context", "continue", "cover",
98  "covergroup", "coverpoint", "cross", "dist", "do", "endclass", "endgroup", "endsequence", "endclocking",
99  "endpackage", "endinterface", "endprogram", "endproperty", "enum", "expect", "export", "extends", "extern", "final",
100  "first_match", "foreach", "forkjoin", "iff", "ignore_bins", "illegal_bins", "import", "intersect", "inside",
101  "interface", "int", "join_any", "join_none", "local", "logic", "longint", "matches", "modport", "new", "null",
102  "package", "packed", "priority", "program", "property", "protected", "pure", "rand", "randc", "randcase",
103  "randomize", "randsequence", "ref", "return", "sequence", "shortint", "shortreal", "solve", "static", "string",
104  "struct", "super", "tagged", "this", "throughout", "timeprecision", "timeunit", "type", "typedef", "unique", "var",
105  "virtual", "void", "wait_order", "wildcard", "with", "within",
107  "accept_on", "checker", "endchecker", "eventually", "global", "implies", "let", "nexttime", "reject_on", "restrict",
108  "s_always", "s_eventually", "s_nexttime", "s_until", "s_until_with", "strong", "sync_accept_on", "sync_reject_on",
109  "unique0", "until", "until_with", "untyped", "weak",
111  "implements", "interconnect", "nettype", "soft"};
112 
113 void verilog_writer::write_comment(const std::string& comment_string)
114 {
115  indented_output_stream->Append("// " + comment_string);
116 }
117 
119 {
120  switch(Type->type)
121  {
123  {
124  return "";
125  }
127  {
128  return "signed ";
129  }
131  {
132  return "";
133  }
135  {
136  THROW_ERROR("USER type not yet supported");
137  break;
138  }
140  {
141  return "";
142  }
144  {
145  return "";
146  }
148  {
149  return "signed ";
150  }
152  {
153  return "";
154  }
156  {
157  break;
158  }
160  {
161  THROW_ERROR("VECTOR_USER type not yet supported");
162  break;
163  }
165  {
166  return Type->id_type;
167  }
169  default:
170  THROW_ERROR("Not initialized type");
171  }
172  return "";
173 }
174 
176 {
178  const structural_objectRef Owner = cir->get_owner();
179  auto* mod = GetPointer<module>(Owner);
180  std::string port_name = cir->get_id();
181  bool specialization_string = false;
182  if(mod)
183  {
184  const NP_functionalityRef& np = mod->get_NP_functionality();
185  if(np)
186  {
187  std::vector<std::pair<std::string, structural_objectRef>> library_parameters;
188  mod->get_NP_library_parameters(Owner, library_parameters);
189  for(auto const& library_parameter : library_parameters)
190  {
191  if(port_name == library_parameter.first)
192  {
193  specialization_string = true;
194  }
195  }
196  }
197  }
198  switch(Type->type)
199  {
201  {
202  if(cir->get_kind() == port_vector_o_K)
203  {
204  if(specialization_string)
205  {
206  return "[" + (PORTSIZE_PREFIX + port_name) + "-1:0] ";
207  }
208  else
209  {
210  return "[" + STR(GetPointer<port_o>(cir)->get_ports_size() - 1) + ":0] ";
211  }
212  }
213  else if(cir->get_owner() and cir->get_owner()->get_kind() == port_vector_o_K)
214  {
215  const auto owner_vector = GetPointer<const port_o>(cir->get_owner());
216  for(unsigned int vector_index = 0; vector_index < owner_vector->get_ports_size(); vector_index++)
217  {
218  if(owner_vector->get_port(vector_index) == cir)
219  {
220  return "[" + STR(vector_index) + ":" + STR(vector_index) + "]";
221  }
222  }
223  THROW_UNREACHABLE("");
224  }
225  else
226  {
227  return "";
228  }
229  break;
230  }
232  {
233  Type->print(std::cerr);
234  THROW_ERROR("USER type not yet supported");
235  break;
236  }
241  {
242  if(specialization_string)
243  {
244  if(cir->get_kind() == port_vector_o_K)
245  {
246  auto lsb = GetPointer<port_o>(cir)->get_lsb();
247  return "[(" + (PORTSIZE_PREFIX + port_name) + "*" + (BITSIZE_PREFIX + port_name) + ")+(" +
248  STR(static_cast<int>(lsb) - 1) + "):" + STR(lsb) + "] ";
249  }
250  else if(cir->get_owner() and cir->get_owner()->get_kind() == port_vector_o_K)
251  {
252  THROW_UNREACHABLE("");
253  }
254  else
255  {
256  return "[" + (BITSIZE_PREFIX + port_name) + "-1:0] ";
257  }
258  }
259  else
260  {
261  if(cir->get_kind() == signal_vector_o_K)
262  {
263  const structural_objectRef first_sig = GetPointer<signal_o>(cir)->get_signal(0);
264  structural_type_descriptorRef Type_fs = first_sig->get_typeRef();
265  auto n_sign = GetPointer<signal_o>(cir)->get_signals_size();
266  auto size_fs = Type_fs->vector_size > 0 ? Type_fs->size * Type_fs->vector_size : Type_fs->size;
267  auto lsb = GetPointer<signal_o>(cir)->get_lsb();
268  auto msb = size_fs * n_sign + lsb;
269 
270  return "[" + STR(static_cast<int>(msb) - 1) + ":" + STR(lsb) + "] ";
271  }
272  else if(cir->get_kind() == port_vector_o_K)
273  {
274  auto lsb = GetPointer<port_o>(cir)->get_lsb();
275  auto n_ports = GetPointer<port_o>(cir)->get_ports_size();
276  const structural_objectRef first_port = GetPointer<port_o>(cir)->get_port(0);
277  const auto Type_fp = first_port->get_typeRef();
278  auto size_fp = Type_fp->vector_size > 0 ? Type_fp->size * Type_fp->vector_size : Type_fp->size;
279  auto msb = size_fp * n_ports + lsb;
280  return "[" + STR(static_cast<int>(msb) - 1) + ":" + STR(lsb) + "] ";
281  }
282  else if(cir->get_owner() and cir->get_owner()->get_kind() == port_vector_o_K)
283  {
284  const auto owner_vector = GetPointer<const port_o>(cir->get_owner());
285  auto lsb = owner_vector->get_lsb();
286  for(unsigned int vector_index = 0; vector_index < owner_vector->get_ports_size(); vector_index++)
287  {
288  if(owner_vector->get_port(vector_index) == cir)
289  {
290  const structural_objectRef first_port = owner_vector->get_port(0);
291  auto single_size_port = GET_TYPE_SIZE(first_port);
292  return "[" + STR(((vector_index + 1) * single_size_port) - 1 + lsb) + ":" +
293  STR(vector_index * single_size_port + lsb) + "]";
294  }
295  }
296  THROW_UNREACHABLE("");
297  }
298  if(Type->vector_size > 1 && Type->size == 1)
299  {
300  return "[" + STR(static_cast<int>(Type->vector_size) - 1) + ":0] ";
301  }
302  else if(Type->vector_size == 1 && Type->size == 1)
303  {
304  return "";
305  }
306  else if(Type->vector_size == 0 && Type->size != 0)
307  {
308  return "[" + STR(static_cast<int>(Type->size) - 1) + ":0] ";
309  }
310  else
311  {
312  THROW_ERROR("Not completely specified: " + port_name);
313  }
314  }
315  break;
316  }
320  {
321  if(specialization_string)
322  {
323  return "[" + (BITSIZE_PREFIX + port_name) + "*" + (NUM_ELEM_PREFIX + port_name) + "-1:0] ";
324  }
325  else if(Type->vector_size * Type->size > 1)
326  {
327  return "[" + STR(Type->vector_size * Type->size - 1) + ":0] ";
328  }
329  else
330  {
331  return "";
332  }
333  }
335  {
336  THROW_ERROR("VECTOR_USER type not yet supported");
337  break;
338  }
340  {
341  return Type->id_type;
342  }
344  default:
345  THROW_ERROR("Not initialized type");
346  }
347  return "";
348 }
349 
351 {
353  const structural_objectRef Owner = cir->get_owner();
354  auto* mod = GetPointer<module>(Owner);
355  std::string port_name = cir->get_id();
356  bool specialization_string = false;
357  if(mod)
358  {
359  const NP_functionalityRef& np = mod->get_NP_functionality();
360  if(np)
361  {
362  std::vector<std::pair<std::string, structural_objectRef>> library_parameters;
363  mod->get_NP_library_parameters(Owner, library_parameters);
364  for(const auto& library_parameter : library_parameters)
365  {
366  if(port_name == library_parameter.first)
367  {
368  specialization_string = true;
369  }
370  }
371  }
372  }
373  switch(Type->type)
374  {
376  {
377  if(Owner->get_kind() == port_vector_o_K)
378  {
379  return "[" + GetPointer<port_o>(cir)->get_id() + "]";
380  }
381  else
382  {
383  return "";
384  }
385  }
387  {
388  Type->print(std::cerr);
389  THROW_ERROR("USER type not yet supported");
390  break;
391  }
396  {
397  if(specialization_string)
398  {
399  if(Owner->get_kind() == port_vector_o_K)
400  {
401  auto lsb = GetPointer<port_o>(Owner)->get_lsb();
402  return "[((" + STR(GetPointer<port_o>(cir)->get_id()) + "+1)*" + (BITSIZE_PREFIX + port_name) + ")+(" +
403  STR(static_cast<int>(lsb) - 1) + "):(" + STR(GetPointer<port_o>(cir)->get_id()) + "*" +
404  (BITSIZE_PREFIX + port_name) + ")+" + STR(lsb) + "]";
405  }
406  else
407  {
408  return "";
409  }
410  }
411  else
412  {
413  if(Owner->get_kind() == port_vector_o_K)
414  {
416  auto size_fp = Type_fp->vector_size > 0 ? Type_fp->size * Type_fp->vector_size : Type_fp->size;
417  auto lsb = GetPointer<port_o>(Owner)->get_lsb();
418  return "[" +
419  STR((1 + std::stoi(GetPointer<port_o>(cir)->get_id())) * static_cast<int>(size_fp) +
420  static_cast<int>(lsb) - 1) +
421  ":" +
422  STR((std::stoi(GetPointer<port_o>(cir)->get_id())) * static_cast<int>(size_fp) +
423  static_cast<int>(lsb)) +
424  "]";
425  }
426  else
427  {
428  return "";
429  }
430  }
431  break;
432  }
436  {
437  if(specialization_string)
438  {
439  if(Owner->get_kind() == port_vector_o_K)
440  {
441  auto lsb = GetPointer<port_o>(Owner)->get_lsb();
442  return "[((" + STR(GetPointer<port_o>(cir)->get_id()) + "+1)*" + (BITSIZE_PREFIX + port_name) + "*" +
443  (NUM_ELEM_PREFIX + port_name) + ")+(" + STR(static_cast<int>(lsb) - 1) + "):(" +
444  STR(GetPointer<port_o>(cir)->get_id()) + "*" + (BITSIZE_PREFIX + port_name) + "*" +
445  (NUM_ELEM_PREFIX + port_name) + ")+" + STR(lsb) + "]";
446  }
447  else
448  {
449  return "";
450  }
451  }
452  else
453  {
454  if(Owner->get_kind() == port_vector_o_K)
455  {
457  auto size_fp = Type_fp->vector_size > 0 ? Type_fp->size * Type_fp->vector_size : Type_fp->size;
458  auto lsb = GetPointer<port_o>(Owner)->get_lsb();
459  return "[" +
460  STR((1 + std::stoi(GetPointer<port_o>(cir)->get_id())) * static_cast<int>(size_fp) +
461  static_cast<int>(lsb) - 1) +
462  ":" +
463  STR((std::stoi(GetPointer<port_o>(cir)->get_id())) * static_cast<int>(size_fp) +
464  static_cast<int>(lsb)) +
465  "]";
466  }
467  else
468  {
469  return "";
470  }
471  }
472  break;
473  }
476  {
477  THROW_ERROR("VECTOR_USER type not yet supported");
478  break;
479  }
481  default:
482  THROW_ERROR("Not initialized type");
483  }
484  return "";
485 }
486 
488 {
489  THROW_ASSERT(cir->get_kind() == component_o_K || cir->get_kind() == channel_o_K,
490  "Expected a component or a channel got something of different");
491  NP_functionalityRef NPF = GetPointer<module>(cir)->get_NP_functionality();
492  if(NPF and NPF->exist_NP_functionality(NP_functionality::IP_INCLUDE))
493  {
494  const auto IP_includes = NPF->get_NP_functionality(NP_functionality::IP_INCLUDE);
495  const auto IP_includes_list = string_to_container<std::vector<std::string>>(IP_includes, ";");
496  for(const auto& inc : IP_includes_list)
497  {
498  indented_output_stream->Append("`include \"" + inc + "\"\n");
499  }
500  }
501 }
502 
504 {
505  auto* mod = GetPointer<module>(cir);
506  THROW_ASSERT(mod, "Expected a module got something of different");
507  indented_output_stream->Append("`timescale 1ns / 1ps\n");
508  if(mod->get_keep_hierarchy())
509  {
510  indented_output_stream->Append("(* keep_hierarchy = \"yes\" *) ");
511  }
513  bool first_obj = false;
516  for(unsigned int i = 0; i < mod->get_num_ports(); i++)
517  {
518  if(first_obj)
519  {
521  }
522  else
523  {
524  first_obj = true;
525  }
526  indented_output_stream->Append(HDL_manager::convert_to_identifier(this, mod->get_positional_port(i)->get_id()));
527  }
532  {
533  indented_output_stream->Append(")/* synthesis syn_hier = \"hard\"*/;\n");
534  }
535  else
536  {
538  }
540 }
541 
543 {
544 }
545 
546 void verilog_writer::write_assign(const std::string& op0, const std::string& op1)
547 {
548  if(op0 != op1)
549  {
550  indented_output_stream->Append(" assign " + op0 + " = " + op1 + ";\n");
551  }
552 }
553 
555 {
556  THROW_ASSERT(cir->get_kind() == port_o_K || cir->get_kind() == port_vector_o_K,
557  "Expected a port got something of different " + cir->get_id());
559  dir = GetPointer<port_o>(cir)->get_port_direction();
560  switch(dir)
561  {
562  case port_o::IN:
563  {
564  indented_output_stream->Append("input ");
565  break;
566  }
567  case port_o::OUT:
568  {
569  indented_output_stream->Append("output ");
570  break;
571  }
572  case port_o::IO:
573  {
574  indented_output_stream->Append("inout ");
575  break;
576  }
577  case port_o::GEN:
578  {
579  THROW_ERROR("Generic port not yet supported!");
580  break;
581  }
582  case port_o::TLM_IN:
583  case port_o::TLM_INOUT:
584  case port_o::TLM_OUT:
585  case port_o::UNKNOWN:
586  default:
587  THROW_ERROR("Something went wrong!");
588  }
589 
592 }
593 
595 {
596 }
597 
599 {
601  "Expected a signal or a signal vector got something of different");
604  {
605  const structural_objectRef first_sig = GetPointer<signal_o>(cir)->get_signal(0);
606  structural_type_descriptorRef Type_fs = first_sig->get_typeRef();
607  auto n_sign = GetPointer<signal_o>(cir)->get_signals_size();
608  auto size_fs = Type_fs->vector_size > 0 ? Type_fs->size * Type_fs->vector_size : Type_fs->size;
609  auto lsb = GetPointer<signal_o>(cir)->get_lsb();
610  auto msb = size_fs * n_sign + lsb;
611  indented_output_stream->Append("[" + STR(msb - 1) + ":" + STR(lsb) + "] ");
612  }
614 }
615 
617 {
619 }
620 
621 void verilog_writer::WriteBuiltin(const structural_objectConstRef component)
622 {
623  const auto mod = GetPointer<const module>(component);
624  THROW_ASSERT(mod, component->get_path() + " is not a module");
625  THROW_ASSERT(GetPointer<const port_o>(mod->get_out_port(0)), "does not have an output port");
626  THROW_ASSERT(component->get_owner(), "does not have an owner");
627  THROW_ASSERT(GetPointer<const port_o>(mod->get_out_port(0))->find_bounded_object(component->get_owner()),
628  component->get_path() + " does not have a bounded object");
629  const auto object_bounded =
630  GetPointer<const port_o>(mod->get_out_port(0))->find_bounded_object(component->get_owner());
631  const auto component_name = GET_TYPE_NAME(component);
633  "Verilog keyword corresponding to " + component_name + " not found");
634  indented_output_stream->Append(builtin_to_verilog_keyword.find(component_name)->second + " " +
635  builtin_to_verilog_keyword.find(component_name)->second + "_" + component->get_id() +
636  "(");
637  THROW_ASSERT(mod->get_out_port_size() == 1,
638  component->get_path() + " has " + STR(mod->get_out_port_size()) + " output ports");
639  indented_output_stream->Append(" " + HDL_manager::convert_to_identifier(this, object_bounded->get_id()) + ", ");
640  for(unsigned int i = 0; i < mod->get_in_port_size(); i++)
641  {
642  if(mod->get_in_port(i)->get_kind() == port_o_K)
643  {
644  THROW_ASSERT(GetPointer<port_o>(mod->get_in_port(i))->find_bounded_object(component->get_owner()),
645  "does not have a structural object connected to the input");
646  const auto in_object_bounded =
647  GetPointer<port_o>(mod->get_in_port(i))->find_bounded_object(component->get_owner());
648  indented_output_stream->Append(HDL_manager::convert_to_identifier(this, in_object_bounded->get_id()));
649  }
650  else if(mod->get_in_port(i)->get_kind() == port_vector_o_K)
651  {
652  const auto port = GetPointer<port_o>(mod->get_in_port(i));
653  const auto in_object_bounded = port->find_bounded_object(component);
654  if(in_object_bounded)
655  {
656  indented_output_stream->Append(HDL_manager::convert_to_identifier(this, in_object_bounded->get_id()));
657  }
658  else
659  {
660  auto n_ports = port->get_ports_size();
661  for(decltype(n_ports) port_index = 0; port_index < n_ports; port_index++)
662  {
663  if(i != 0 or port_index != 0)
664  {
666  }
667  const auto vec_in_object_bounded = GetPointer<port_o>(port->get_port(port_index))->find_bounded_object();
668  THROW_ASSERT(vec_in_object_bounded, port->get_port(port_index)->get_path());
670  HDL_manager::convert_to_identifier(this, vec_in_object_bounded->get_id()));
671  }
672  }
673  }
674  else
675  {
676  THROW_UNREACHABLE("");
677  }
678  }
680 }
681 
682 void verilog_writer::write_module_instance_begin(const structural_objectRef& cir, const std::string& module_name,
683  bool write_parametrization)
684 {
685  THROW_ASSERT(cir->get_kind() == component_o_K || cir->get_kind() == channel_o_K,
686  "Expected a component or a channel got something of different");
687 #if 0
688  if(module_name.find("widen_mult_expr") != std::string::npos)
689  {
690  indented_output_stream->Append("(* dont_touch = \"true\" *) ");
691  }
692 #endif
693  indented_output_stream->Append(module_name);
694 
696  if(write_parametrization)
697  {
699  }
702 }
703 
705 {
708 }
709 
711 {
713  indented_output_stream->Append("\nendmodule\n\n");
714 }
715 
716 void verilog_writer::write_vector_port_binding(const structural_objectRef& port, bool first_port_analyzed)
717 {
718  THROW_ASSERT(port, "NULL object_bounded received");
719  THROW_ASSERT(port->get_kind() == port_vector_o_K, "Expected a port vector, got something of different");
720  const structural_objectRef p_object_bounded = GetPointer<port_o>(port)->find_bounded_object(port->get_owner());
721  if(p_object_bounded)
722  {
723  if(first_port_analyzed)
724  {
726  }
730  if(p_object_bounded->get_kind() == port_vector_o_K)
731  {
732  indented_output_stream->Append(HDL_manager::convert_to_identifier(this, p_object_bounded->get_id()));
733  }
734  else if(p_object_bounded->get_kind() == signal_vector_o_K)
735  {
736  indented_output_stream->Append(HDL_manager::convert_to_identifier(this, p_object_bounded->get_id()));
737  }
738  else
739  {
740  THROW_ERROR("not expected case");
741  }
743  }
744  else
745  {
747  "-->Port binding for " + port->get_path() + " not found - looking for single port binding");
748  std::string port_binding;
749  auto* pv = GetPointer<port_o>(port);
750  bool local_first_port_analyzed = false;
751  unsigned long long msb, lsb;
754  structural_objectRef slice;
755  structural_objectRef null_object;
756  auto n_ports = pv->get_ports_size();
757  for(unsigned int j = 0; j < n_ports; ++j)
758  {
759  auto index = n_ports - j - 1;
760  structural_objectRef object_bounded = GetPointer<port_o>(pv->get_port(index))->find_bounded_object();
761  if(!object_bounded)
762  {
763  THROW_ERROR("not bounded: " + pv->get_port(index)->get_path());
764  }
765 
766  if(object_bounded->get_owner()->get_kind() == port_vector_o_K ||
767  object_bounded->get_owner()->get_kind() == signal_vector_o_K)
768  {
769  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Bounded to a port of a port vector");
770  auto vector_position = static_cast<unsigned>(std::stoul(object_bounded->get_id()));
771  if(slice and slice->get_id() != object_bounded->get_owner()->get_id())
772  {
773  if(local_first_port_analyzed)
774  {
775  port_binding += ",\n";
776  }
777  port_binding += HDL_manager::convert_to_identifier(this, slice->get_id());
778  unsigned int max = 0;
779  auto* pvs = GetPointer<port_o>(slice);
780  if(pvs)
781  {
782  max = pvs->get_ports_size();
783  }
784  else
785  {
786  auto* sv = GetPointer<signal_o>(slice);
787  if(sv)
788  {
789  max = sv->get_signals_size();
790  }
791  }
792  if(lsb != 0 || msb != (max - 1))
793  {
794  port_binding += "[" + STR(msb);
795  if(msb != lsb)
796  {
797  port_binding += ":" + STR(lsb);
798  }
799  port_binding += "]";
800  }
801  local_first_port_analyzed = true;
802  slice = null_object;
804  }
805  if(!slice || (slice->get_id() == object_bounded->get_owner()->get_id() and
806  (((vector_position + 1) * GET_TYPE_SIZE(object_bounded)) - 1) == lsb - 1))
807  {
808  slice = object_bounded->get_owner();
810  {
811  msb = (vector_position + 1) * GET_TYPE_SIZE(object_bounded) - 1;
812  }
813  lsb = vector_position * GET_TYPE_SIZE(object_bounded);
814  continue;
815  }
816  }
817  else if(object_bounded->get_kind() == constant_o_K)
818  {
819  if(local_first_port_analyzed)
820  {
821  port_binding += ",\n";
822  }
823  if(slice)
824  {
825  port_binding += HDL_manager::convert_to_identifier(this, slice->get_id());
826  unsigned int max = 0;
827  auto* pvs = GetPointer<port_o>(slice);
828  if(pvs)
829  {
830  max = pvs->get_ports_size();
831  }
832  else
833  {
834  auto* sv = GetPointer<signal_o>(slice);
835  if(sv)
836  {
837  max = sv->get_signals_size();
838  }
839  }
840  if(lsb != 0 || msb != (max - 1))
841  {
842  port_binding += "[" + STR(msb);
843  if(msb != lsb)
844  {
845  port_binding += ":" + STR(lsb);
846  }
847  port_binding += "], ";
848  }
849  else if(local_first_port_analyzed)
850  {
851  port_binding += ",\n";
852  }
853  slice = null_object;
855  }
856  auto* con = GetPointer<constant_o>(object_bounded);
857  std::string trimmed_value = "";
858  auto long_value = std::stoull(con->get_value());
859  for(unsigned int ind = 0; ind < GET_TYPE_SIZE(con); ind++)
860  {
861  trimmed_value = trimmed_value + (((1LLU << (GET_TYPE_SIZE(con) - ind - 1)) & long_value) ? '1' : '0');
862  }
863  port_binding += STR(GET_TYPE_SIZE(con)) + "'b" + trimmed_value;
864  }
865  else
866  {
867  if(local_first_port_analyzed)
868  {
869  port_binding += ",\n";
870  }
871  if(slice)
872  {
873  port_binding += HDL_manager::convert_to_identifier(this, slice->get_id());
874  unsigned int max = 0;
875  auto* pvs = GetPointer<port_o>(slice);
876  if(pvs)
877  {
878  max = pvs->get_ports_size();
879  }
880  else
881  {
882  auto* sv = GetPointer<signal_o>(slice);
883  if(sv)
884  {
885  max = sv->get_signals_size();
886  }
887  }
888  if(lsb != 0 || msb != (max - 1))
889  {
890  port_binding += "[" + STR(msb);
891  if(msb != lsb)
892  {
893  port_binding += ":" + STR(lsb);
894  }
895  port_binding += "], ";
896  }
897  else if(local_first_port_analyzed)
898  {
899  port_binding += ",\n";
900  }
901  slice = null_object;
903  }
904  port_binding += HDL_manager::convert_to_identifier(this, object_bounded->get_id());
905  }
906  local_first_port_analyzed = true;
907  }
908  if(slice)
909  {
910  if(local_first_port_analyzed)
911  {
912  port_binding += ",\n";
913  }
914  port_binding += HDL_manager::convert_to_identifier(this, slice->get_id());
915  unsigned int max = 0;
916  auto* pvs = GetPointer<port_o>(slice);
917  if(pvs)
918  {
919  max = pvs->get_ports_size();
920  }
921  else
922  {
923  auto* sv = GetPointer<signal_o>(slice);
924  if(sv)
925  {
926  max = sv->get_signals_size();
927  }
928  }
929  if(lsb != 0 || msb != (max - 1))
930  {
931  port_binding += "[" + STR(msb);
932  if(msb != lsb)
933  {
934  port_binding += ":" + STR(lsb);
935  }
936  port_binding += "]";
937  }
938  }
939 
940  if(port_binding.size() == 0)
941  {
942  return;
943  }
944 
945  if(first_port_analyzed)
946  {
948  }
953  indented_output_stream->Append(port_binding);
957  "<--Port binding for " + port->get_path() + " not found - looking for single port binding");
958  }
959 }
960 
962  bool first_port_analyzed)
963 {
964  if(!object_bounded)
965  {
966  return;
967  }
968  THROW_ASSERT(port, "NULL object_bounded received");
969  THROW_ASSERT(port->get_kind() == port_o_K, "Expected a port got something of different");
970  THROW_ASSERT(port->get_owner(), "The port has to have an owner");
971  THROW_ASSERT(object_bounded, "NULL object_bounded received for port: " + port->get_path());
972  THROW_ASSERT(object_bounded->get_kind() != port_o_K || object_bounded->get_owner(),
973  "A port has to have always an owner");
974  if(first_port_analyzed)
975  {
977  }
978  if(port->get_owner()->get_kind() == port_vector_o_K)
979  {
982  port->get_id() + "]");
983  }
984  else
985  {
988  }
990  if(object_bounded->get_kind() == port_o_K && object_bounded->get_owner()->get_kind() == port_vector_o_K)
991  {
992  indented_output_stream->Append(HDL_manager::convert_to_identifier(this, object_bounded->get_owner()->get_id()) +
993  type_converter_size(object_bounded));
994  }
995  else if(object_bounded->get_kind() == signal_o_K && object_bounded->get_owner()->get_kind() == signal_vector_o_K)
996  {
997  indented_output_stream->Append(HDL_manager::convert_to_identifier(this, object_bounded->get_owner()->get_id()) +
998  type_converter_size(object_bounded));
999  }
1000  else if(object_bounded->get_kind() == constant_o_K)
1001  {
1002  auto* con = GetPointer<constant_o>(object_bounded);
1003  std::string trimmed_value = "";
1004  auto long_value = std::stoull(con->get_value());
1005  for(unsigned int ind = 0; ind < GET_TYPE_SIZE(con); ind++)
1006  {
1007  trimmed_value = trimmed_value + (((1LLU << (GET_TYPE_SIZE(con) - ind - 1)) & long_value) ? '1' : '0');
1008  }
1009  indented_output_stream->Append(STR(GET_TYPE_SIZE(con)) + "'b" + trimmed_value);
1010  }
1011  else
1012  {
1014  }
1016 }
1017 
1019 {
1020  THROW_ASSERT(port && port->get_kind() == port_o_K, "Expected a port got something of different");
1021  THROW_ASSERT(port->get_owner(), "Expected a port with an owner");
1022  THROW_ASSERT(sig && (sig->get_kind() == signal_o_K || sig->get_kind() == constant_o_K),
1023  "Expected a signal or a constant, got something of different");
1024  std::string port_string;
1025  std::string signal_string;
1026  if(sig->get_kind() == constant_o_K)
1027  {
1028  auto* con = GetPointer<constant_o>(sig);
1029  std::string trimmed_value = "";
1030  auto long_value = std::stoull(con->get_value());
1031  for(unsigned int ind = 0; ind < GET_TYPE_SIZE(con); ind++)
1032  {
1033  trimmed_value = trimmed_value + (((1LLU << (GET_TYPE_SIZE(con) - ind - 1)) & long_value) ? '1' : '0');
1034  }
1035  signal_string = STR(GET_TYPE_SIZE(con)) + "'b" + trimmed_value;
1036  }
1037  else if(sig->get_kind() == signal_o_K)
1038  {
1039  if(sig->get_owner()->get_kind() == signal_vector_o_K)
1040  {
1041  signal_string = HDL_manager::convert_to_identifier(this, sig->get_owner()->get_id()) + may_slice_string(port);
1042  }
1043  else
1044  {
1045  signal_string = HDL_manager::convert_to_identifier(this, sig->get_id());
1046  }
1047  }
1048  if(port->get_owner()->get_kind() == port_vector_o_K)
1049  {
1050  port_string = HDL_manager::convert_to_identifier(this, port->get_owner()->get_id()) + may_slice_string(port);
1051  }
1052  else
1053  {
1054  port_string = HDL_manager::convert_to_identifier(this, port->get_id());
1055  }
1056  if(GetPointer<port_o>(port)->get_port_direction() == port_o::IN)
1057  {
1058  std::swap(port_string, signal_string);
1059  }
1060  if(port_string != signal_string)
1061  {
1062  indented_output_stream->Append("assign " + port_string + " = " + signal_string + ";\n");
1063  }
1064 }
1065 
1067 {
1068  THROW_ASSERT(port && port->get_kind() == port_vector_o_K, "Expected a port got something of different");
1069  THROW_ASSERT(port->get_owner(), "Expected a port with an owner");
1070  THROW_ASSERT(sig && sig->get_kind() == signal_vector_o_K, "Expected a signal got something of different");
1071  std::string port_string;
1072  std::string signal_string;
1073  signal_string = HDL_manager::convert_to_identifier(this, sig->get_id());
1074  port_string = HDL_manager::convert_to_identifier(this, port->get_id());
1075  if(GetPointer<port_o>(port)->get_port_direction() == port_o::IN)
1076  {
1077  std::swap(port_string, signal_string);
1078  }
1079  if(port_string != signal_string)
1080  {
1081  indented_output_stream->Append("assign " + port_string + " = " + signal_string + ";\n");
1082  }
1083 }
1084 
1086 {
1087  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Writing module generics of " + cir->get_path());
1088  THROW_ASSERT(cir->get_kind() == component_o_K || cir->get_kind() == channel_o_K,
1089  "Expected a component or a channel got something of different");
1090  auto* mod = GetPointer<module>(cir);
1091  bool first_it = true;
1092  const NP_functionalityRef& np = mod->get_NP_functionality();
1093 
1095  if(mod->ExistsParameter(MEMORY_PARAMETER))
1096  {
1097  std::string memory_str = mod->GetParameter(MEMORY_PARAMETER);
1098  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Writing memory parameters " + memory_str);
1099  std::vector<std::string> mem_tag = string_to_container<std::vector<std::string>>(memory_str, ";");
1100  for(const auto& i : mem_tag)
1101  {
1102  std::vector<std::string> mem_add = string_to_container<std::vector<std::string>>(i, "=");
1103  THROW_ASSERT(mem_add.size() == 2, "malformed address");
1104  if(first_it)
1105  {
1108  first_it = false;
1109  }
1110  else
1111  {
1113  }
1114  std::string name = mem_add[0];
1115  std::string value;
1116  if(mod->get_owner() && GetPointer<module>(mod->get_owner()) &&
1117  GetPointer<module>(mod->get_owner())->ExistsParameter(MEMORY_PARAMETER))
1118  {
1119  value = name;
1120  }
1121  else
1122  {
1123  value = mem_add[1];
1124  }
1125 
1126  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Writing ." + name + "(" + name + ")");
1127  indented_output_stream->Append("." + name + "(" + value + ")");
1128  }
1129  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--written memory parameters");
1130  }
1131 
1132  if(np)
1133  {
1134  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Writing np parameters");
1135  std::vector<std::pair<std::string, structural_objectRef>> library_parameters;
1136  mod->get_NP_library_parameters(cir, library_parameters);
1137  for(const auto& library_parameter : library_parameters)
1138  {
1139  if(first_it)
1140  {
1143  first_it = false;
1144  }
1145  else
1146  {
1148  }
1149  const std::string& name = library_parameter.first;
1150  structural_objectRef obj = library_parameter.second;
1151 
1152  if(!mod->ExistsParameter(std::string(BITSIZE_PREFIX) + name) && obj)
1153  {
1157  {
1158  indented_output_stream->Append("." + std::string(BITSIZE_PREFIX + name) + "(" +
1159  STR(obj->get_typeRef()->size) + ")");
1161  indented_output_stream->Append("." + std::string(NUM_ELEM_PREFIX + name) + "(" +
1162  STR(obj->get_typeRef()->vector_size) + ")");
1163  }
1164  else
1165  {
1166  indented_output_stream->Append("." + std::string(BITSIZE_PREFIX) + name + "(" + STR(GET_TYPE_SIZE(obj)) +
1167  ")");
1168  if(obj->get_kind() == port_vector_o_K)
1169  {
1171  auto ports_size = GetPointer<port_o>(obj)->get_ports_size();
1172  indented_output_stream->Append("." + std::string(PORTSIZE_PREFIX) + name + "(" + STR(ports_size) +
1173  ")");
1174  }
1175  }
1176  }
1177  else
1178  {
1179  std::string param_value, param_name;
1180  if(mod->ExistsParameter(name))
1181  {
1182  param_value = mod->GetParameter(name);
1183  param_name = name;
1184  }
1185  else if(mod->ExistsParameter(std::string(BITSIZE_PREFIX) + name))
1186  {
1187  param_value = mod->GetParameter(std::string(BITSIZE_PREFIX) + name);
1188  param_name = std::string(BITSIZE_PREFIX) + name;
1189  }
1190  else
1191  {
1192  cir->print(std::cerr);
1193  THROW_ERROR("Parameter is missing for port " + name + " in module " + cir->get_path());
1194  }
1195  if(param_value.find("\"\"") != std::string::npos)
1196  {
1197  boost::replace_all(param_value, "\"\"", "\"");
1198  }
1199  else if(param_value.find('\"') != std::string::npos)
1200  {
1201  boost::replace_all(param_value, "\"", "");
1202  param_value = STR(param_value.size()) + "'b" + param_value;
1203  }
1205  "---Written ." + param_name + "(" + param_value + ")");
1206  indented_output_stream->Append("." + param_name + "(" + param_value + ")");
1207  }
1208  }
1209  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Written np parameters");
1210  }
1211 
1212  if(!first_it)
1213  {
1216  }
1217  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Written module generics of " + cir->get_path());
1218 }
1219 
1221  const std::list<std::string>& list_of_states, const std::string&,
1222  const std::string& reset_state, bool one_hot)
1223 {
1224  PRINT_DBG_MEX(DEBUG_LEVEL_VERBOSE, debug_level, "Starting state declaration...");
1225 
1226  auto it_end = list_of_states.end();
1227  auto n_states = static_cast<unsigned int>(list_of_states.size());
1228  unsigned int count = 0;
1229  auto bitsnumber = language_writer::bitnumber(n_states - 1);
1231  unsigned max_value = 0;
1232  for(auto it = list_of_states.begin(); it != it_end; ++it)
1233  {
1234  max_value = std::max(max_value, static_cast<unsigned>(std::stoul(it->substr(strlen(STATE_NAME_PREFIX)))));
1235  }
1236  if(max_value != n_states - 1)
1237  {
1238  bitsnumber = language_writer::bitnumber(max_value);
1239  }
1240  if(one_hot)
1241  {
1242  indented_output_stream->Append("parameter [" + STR(max_value) + ":0] ");
1243  }
1244  else
1245  {
1246  indented_output_stream->Append("parameter [" + STR(bitsnumber - 1) + ":0] ");
1247  }
1248  for(auto it = list_of_states.begin(); it != it_end; ++it)
1249  {
1250  if(one_hot)
1251  {
1253  *it + " = " + STR(max_value + 1) + "'b" +
1254  encode_one_hot(1 + max_value, static_cast<unsigned>(std::stoul(it->substr(strlen(STATE_NAME_PREFIX))))));
1255  }
1256  else
1257  {
1258  indented_output_stream->Append(*it + " = " + STR(bitsnumber) + "'d" +
1259  STR(it->substr(strlen(STATE_NAME_PREFIX))));
1260  }
1261  count++;
1262  if(count == n_states)
1263  {
1264  ;
1265  }
1266  else
1267  {
1268  if(count == 1)
1269  {
1271  }
1273  }
1274  }
1275  if(count > 1)
1276  {
1278  }
1280  // indented_output_stream->Append("// synthesis attribute init of _present_state is " + reset_state + ";\n");
1281  // indented_output_stream->Append("// synthesis attribute use_sync_reset of _present_state is no;\n");
1282  auto* mod = GetPointer<module>(cir);
1283  const NP_functionalityRef& np = mod->get_NP_functionality();
1284  if(np->exist_NP_functionality(NP_functionality::FSM_CS)) // fsm of context_switch
1285  {
1286  if(one_hot)
1287  {
1288  indented_output_stream->Append("reg [" + STR(max_value) + ":0] _present_state[" +
1289  STR(parameters->getOption<unsigned int>(OPT_context_switch) - 1) + ":0];\n");
1290  indented_output_stream->Append("reg [" + STR(max_value) + ":0] _next_state;\n");
1291  // start initializing memory_FSM
1292  indented_output_stream->Append("integer i;\n");
1293  indented_output_stream->Append("initial begin\n");
1295  " for (i=0; i<" + STR(parameters->getOption<unsigned int>(OPT_context_switch)) + "; i=i+1) begin\n");
1296  indented_output_stream->Append(" _present_state[i] = " + STR(max_value + 1) + "'d1;\n");
1297  indented_output_stream->Append(" end\n");
1298  indented_output_stream->Append("end\n");
1299  }
1300  else
1301  {
1302  indented_output_stream->Append("reg [" + STR(bitsnumber - 1) + ":0] _present_state[" +
1303  STR(parameters->getOption<unsigned int>(OPT_context_switch) - 1) + ":0];\n");
1304  indented_output_stream->Append("reg [" + STR(bitsnumber - 1) + ":0] _next_state;\n");
1305  // start initializing memory_FSM
1306  indented_output_stream->Append("integer i;\n");
1307  indented_output_stream->Append("initial begin\n");
1309  " for (i=0; i<" + STR(parameters->getOption<unsigned int>(OPT_context_switch)) + "; i=i+1) begin\n");
1310  indented_output_stream->Append(" _present_state[i] = " + STR(bitsnumber) + "'d0;\n");
1311  indented_output_stream->Append(" end\n");
1312  indented_output_stream->Append("end\n");
1313  }
1314  }
1315  else
1316  {
1317  if(one_hot)
1318  {
1319  indented_output_stream->Append("reg [" + STR(max_value) + ":0] _present_state=" + reset_state +
1320  ", _next_state;\n");
1321  }
1322  else
1323  {
1324  indented_output_stream->Append("reg [" + STR(bitsnumber - 1) + ":0] _present_state=" + reset_state +
1325  ", _next_state;\n");
1326  }
1327  }
1328  THROW_ASSERT(mod, "Expected a component object");
1329  THROW_ASSERT(mod->get_out_port_size(), "Expected a FSM with at least one output");
1330 
1331  std::string port_name;
1332 
1334  for(unsigned int i = 0; i < mod->get_out_port_size(); i++)
1335  {
1336  if(mod->get_out_port(i)->get_id() == PRESENT_STATE_PORT_NAME)
1337  {
1338  continue;
1339  }
1340  if(mod->get_out_port(i)->get_id() == NEXT_STATE_PORT_NAME)
1341  {
1342  continue;
1343  }
1344  port_name = HDL_manager::convert_to_identifier(this, mod->get_out_port(i)->get_id());
1345  indented_output_stream->Append("reg " + port_name + ";\n");
1346  }
1347 
1348  PRINT_DBG_MEX(DEBUG_LEVEL_VERBOSE, debug_level, "Completed state declaration");
1349 }
1350 
1351 void verilog_writer::write_present_state_update(const structural_objectRef cir, const std::string& reset_state,
1352  const std::string& reset_port, const std::string& clock_port,
1353  const std::string& reset_type, bool connect_present_next_state_signals)
1354 {
1355  if(reset_type == "no" || reset_type == "sync")
1356  {
1357  indented_output_stream->Append("always @(posedge " + clock_port + ")\n");
1358  }
1359  else if(!parameters->getOption<bool>(OPT_reset_level))
1360  {
1361  indented_output_stream->Append("always @(posedge " + clock_port + " or negedge " + reset_port + ")\n");
1362  }
1363  else
1364  {
1365  indented_output_stream->Append("always @(posedge " + clock_port + " or posedge " + reset_port + ")\n");
1366  }
1369  auto* mod = GetPointer<module>(cir);
1370  const NP_functionalityRef& np = mod->get_NP_functionality();
1371  if(np->exist_NP_functionality(NP_functionality::FSM_CS)) // fsm of context_switch
1372  {
1373  if(!parameters->getOption<bool>(OPT_reset_level))
1374  {
1375  indented_output_stream->Append("if (" + reset_port + " == 1'b0) _present_state[" +
1376  STR(SELECTOR_REGISTER_FILE) + "] <= " + reset_state + ";\n");
1377  }
1378  else
1379  {
1380  indented_output_stream->Append("if (" + reset_port + " == 1'b1) _present_state[" +
1381  STR(SELECTOR_REGISTER_FILE) + "] <= " + reset_state + ";\n");
1382  }
1383  indented_output_stream->Append("else _present_state[" + STR(SELECTOR_REGISTER_FILE) + "] <= _next_state;\n");
1384  }
1385  else
1386  {
1387  if(!parameters->getOption<bool>(OPT_reset_level))
1388  {
1389  indented_output_stream->Append("if (" + reset_port + " == 1'b0) _present_state <= " + reset_state + ";\n");
1390  }
1391  else
1392  {
1393  indented_output_stream->Append("if (" + reset_port + " == 1'b1) _present_state <= " + reset_state + ";\n");
1394  }
1395  indented_output_stream->Append("else _present_state <= _next_state;\n");
1396  }
1398  if(connect_present_next_state_signals)
1399  {
1400  indented_output_stream->Append("assign " PRESENT_STATE_PORT_NAME "= _present_state;\nassign " NEXT_STATE_PORT_NAME
1401  "= _next_state;\n");
1402  }
1403 }
1404 
1406  bool single_proc, unsigned int output_index, const structural_objectRef& cir, const std::string& reset_state,
1407  const std::string& reset_port, const std::string& start_port, const std::string& clock_port,
1408  std::vector<std::string>::const_iterator& first, std::vector<std::string>::const_iterator& end, bool is_yosys,
1409  const std::map<unsigned int, std::map<std::string, std::set<unsigned int>>>& bypass_signals)
1410 {
1411  using tokenizer = boost::tokenizer<boost::char_separator<char>>;
1412  const char soc[3] = {STD_OPENING_CHAR, '\n', '\0'};
1413  const char scc[3] = {STD_CLOSING_CHAR, '\n', '\0'};
1414  const char soc1[2] = {STD_OPENING_CHAR, '\0'};
1415  const char scc1[2] = {STD_CLOSING_CHAR, '\0'};
1416 
1417  boost::char_separator<char> state_sep(":", nullptr);
1418  boost::char_separator<char> sep(" ", nullptr);
1419 
1420  auto* mod = GetPointer<module>(cir);
1421  THROW_ASSERT(mod, "Expected a component object");
1422  THROW_ASSERT(mod->get_out_port_size(), "Expected a FSM with at least one output");
1423  std::string port_name;
1424 
1425  const NP_functionalityRef& np = mod->get_NP_functionality();
1426  unsigned int numInputIgnored; // clock,reset,start_port are always present
1428  {
1429  numInputIgnored = 4; // added selector
1430  }
1431  else
1432  {
1433  numInputIgnored = 3;
1434  }
1436 #ifdef VERILOG_2001_SUPPORTED
1437  indented_output_stream->Append("\nalways @(*)\nbegin");
1438 #else
1439  if(np->exist_NP_functionality(NP_functionality::FSM_CS)) // fsm of context_switch
1440  indented_output_stream->Append("\nalways @(_present_state[" + STR(SELECTOR_REGISTER_FILE) + "]");
1441  else
1442  indented_output_stream->Append("\nalways @(_present_state");
1443  if(mod->get_in_port_size())
1444  {
1445  for(unsigned int i = 0; i < mod->get_in_port_size(); i++)
1446  {
1447  port_name = HDL_manager::convert_to_identifier(this, mod->get_in_port(i)->get_id());
1448  if(port_name != reset_port && port_name != clock_port)
1449  indented_output_stream->Append(" or " + port_name);
1450  }
1451  }
1452  indented_output_stream->Append(")\nbegin");
1453 #endif
1455 
1457  if(!single_proc && output_index == mod->get_out_port_size())
1458  {
1459  indented_output_stream->Append("_next_state = " + reset_state + ";\n");
1460  }
1461 
1463  std::string default_output;
1464  for(unsigned int i = 0; i < mod->get_out_port_size(); i++)
1465  {
1466  if(mod->get_out_port(i)->get_id() == PRESENT_STATE_PORT_NAME)
1467  {
1468  continue;
1469  }
1470  if(mod->get_out_port(i)->get_id() == NEXT_STATE_PORT_NAME)
1471  {
1472  continue;
1473  }
1474  default_output += "0";
1475  if(!single_proc && output_index != i)
1476  {
1477  continue;
1478  }
1479  port_name = HDL_manager::convert_to_identifier(this, mod->get_out_port(i)->get_id());
1480  indented_output_stream->Append(port_name + " = 1'b0;\n");
1481  }
1482 
1484  { // fsm of context_switch
1485  indented_output_stream->Append("case (_present_state[" + STR(SELECTOR_REGISTER_FILE) + "])");
1486  }
1487  else
1488  {
1489  indented_output_stream->Append("case (_present_state)");
1490  }
1492 
1493  for(auto first_it = first; first_it != end; ++first_it)
1494  {
1495  tokenizer state_tokens_first(*first_it, state_sep);
1496 
1497  tokenizer::const_iterator it = state_tokens_first.begin();
1498 
1499  std::string state_description = *it;
1500  ++it;
1501 
1502  std::vector<std::string> state_transitions;
1503  for(; it != state_tokens_first.end(); ++it)
1504  {
1505  state_transitions.push_back(*it);
1506  }
1507 
1508  tokenizer tokens_curr(state_description, sep);
1509 
1511  it = tokens_curr.begin();
1512  std::string present_state = HDL_manager::convert_to_identifier(this, *it);
1514  ++it;
1515  std::string current_output = *it;
1516 
1518  bool skip_state = !single_proc && output_index != mod->get_out_port_size() &&
1519  default_output[output_index] == current_output[output_index];
1520  bool skip_state_transition = !single_proc && output_index != mod->get_out_port_size();
1521  if(!single_proc && output_index != mod->get_out_port_size())
1522  {
1523  for(const auto& current_transition : state_transitions)
1524  {
1525  tokenizer transition_tokens(current_transition, sep);
1526  tokenizer::const_iterator itt = transition_tokens.begin();
1527 
1528  tokenizer::const_iterator current_input_it;
1529  std::string input_string = *itt;
1530  if(mod->get_in_port_size() - numInputIgnored) // clock and reset are always present
1531  {
1532  boost::char_separator<char> comma_sep(",", nullptr);
1533  tokenizer current_input_tokens(input_string, comma_sep);
1534  current_input_it = current_input_tokens.begin();
1535  ++itt;
1536  }
1537  ++itt;
1538  std::string transition_outputs = *itt;
1539  ++itt;
1540  THROW_ASSERT(itt == transition_tokens.end(), "Bad transition format");
1541  if(transition_outputs[output_index] != '-')
1542  {
1543  skip_state = false;
1544  skip_state_transition = false;
1545  }
1546  }
1547  }
1548  if(skip_state)
1549  {
1550  continue;
1551  }
1552 
1554  indented_output_stream->Append(present_state + " :\n");
1555 
1556  if(reset_state == present_state)
1557  {
1558  indented_output_stream->Append("if(" + start_port + " == 1'b1)\n");
1559  }
1560 
1561  indented_output_stream->Append("begin");
1563 
1564  bool unique_transition = (state_transitions.size() == 1);
1565  if(current_output != default_output && (single_proc || !unique_transition || skip_state_transition))
1566  {
1567  for(unsigned int i = 0; i < mod->get_out_port_size(); i++)
1568  {
1569  if(mod->get_out_port(i)->get_id() == PRESENT_STATE_PORT_NAME)
1570  {
1571  continue;
1572  }
1573  if(mod->get_out_port(i)->get_id() == NEXT_STATE_PORT_NAME)
1574  {
1575  continue;
1576  }
1577  port_name = HDL_manager::convert_to_identifier(this, mod->get_out_port(i)->get_id());
1578  if(default_output[i] != current_output[i])
1579  {
1580  if(single_proc || output_index == i)
1581  {
1582  switch(current_output[i])
1583  {
1584  case '1':
1585  {
1586  if(bypass_signals.find(i) == bypass_signals.end() ||
1587  bypass_signals.find(i)->second.find(present_state) == bypass_signals.find(i)->second.end())
1588  {
1589  indented_output_stream->Append(port_name + " = 1'b1;\n");
1590  }
1591  else
1592  {
1593  indented_output_stream->Append(port_name + " = ");
1594  for(const auto& stateIns : bypass_signals.find(i)->second)
1595  {
1596  if(stateIns.first != present_state)
1597  {
1598  continue;
1599  }
1600  bool first_i = true;
1601  for(const auto& in : stateIns.second)
1602  {
1603  if(first_i)
1604  {
1605  first_i = false;
1606  }
1607  else
1608  {
1609  indented_output_stream->Append(" || ");
1610  }
1611  auto in_port_name =
1612  HDL_manager::convert_to_identifier(this, mod->get_in_port(in)->get_id());
1613  indented_output_stream->Append(in_port_name);
1614  }
1615  }
1617  }
1618  break;
1619  }
1620  case '2':
1621  indented_output_stream->Append(port_name + " = 1'bX;\n");
1622  break;
1623 
1624  default:
1625  THROW_ERROR("Unsupported value in current output");
1626  break;
1627  }
1628  }
1629  }
1630  }
1631  }
1632 
1633  if(!skip_state_transition)
1634  {
1636  bool unique_case_condition = true;
1637  std::string guard_casez_port;
1638  auto n_bits_guard_casez_port = 0ULL;
1639  if(!unique_transition)
1640  {
1641  for(unsigned int i = 0; i < state_transitions.size(); i++)
1642  {
1643  tokenizer transition_tokens(state_transitions[i], sep);
1644  tokenizer::const_iterator itt = transition_tokens.begin();
1645 
1646  tokenizer::const_iterator current_input_it;
1647  std::string input_string = *itt;
1648  if(mod->get_in_port_size() - numInputIgnored)
1649  {
1650  boost::char_separator<char> comma_sep(",", nullptr);
1651  tokenizer current_input_tokens(input_string, comma_sep);
1652  current_input_it = current_input_tokens.begin();
1653  ++itt;
1654  }
1655  std::string next_state = *itt;
1656  ++itt;
1657  std::string transition_outputs = *itt;
1658  ++itt;
1659  THROW_ASSERT(itt == transition_tokens.end(), "Bad transition format");
1660  if((i + 1) < state_transitions.size())
1661  {
1662  bool first_test = true;
1663  for(unsigned int ind = 0; ind < mod->get_in_port_size() && unique_case_condition; ind++)
1664  {
1665  port_name = HDL_manager::convert_to_identifier(this, mod->get_in_port(ind)->get_id());
1666  auto port_size = mod->get_in_port(ind)->get_typeRef()->size;
1667  auto vec_size = mod->get_in_port(ind)->get_typeRef()->vector_size;
1668  if(port_name != reset_port && port_name != clock_port && port_name != start_port &&
1669  port_name != STR(SELECTOR_REGISTER_FILE))
1670  {
1671  std::string in_or_conditions = *current_input_it;
1672  boost::char_separator<char> pipe_sep("|", nullptr);
1673  tokenizer in_or_conditions_tokens(in_or_conditions, pipe_sep);
1674 
1675  if((*in_or_conditions_tokens.begin()) != "-")
1676  {
1677  if(guard_casez_port.empty())
1678  {
1679  guard_casez_port = port_name;
1680  }
1681  else if(guard_casez_port != port_name)
1682  {
1683  unique_case_condition = false;
1684  }
1685  if(!first_test)
1686  {
1687  unique_case_condition = false;
1688  }
1689  else
1690  {
1691  first_test = false;
1692  }
1693  bool first_test_or = true;
1694  for(tokenizer::const_iterator in_or_conditions_tokens_it = in_or_conditions_tokens.begin();
1695  in_or_conditions_tokens_it != in_or_conditions_tokens.end() && unique_case_condition;
1696  ++in_or_conditions_tokens_it)
1697  {
1698  THROW_ASSERT((*in_or_conditions_tokens_it) != "-", "wrong conditions structure");
1699  if(!first_test_or)
1700  {
1701  unique_case_condition = false;
1702  }
1703  else
1704  {
1705  first_test_or = false;
1706  }
1707 
1708  if((*in_or_conditions_tokens_it)[0] != '&')
1709  {
1710  unique_case_condition = false;
1711  }
1712  else
1713  {
1714  if(n_bits_guard_casez_port == 0)
1715  {
1716  n_bits_guard_casez_port = vec_size == 0 ? port_size : vec_size;
1717  }
1718  }
1719  }
1720  }
1721  ++current_input_it;
1722  }
1723  }
1724  }
1725  }
1726  }
1727 
1728  if(!unique_transition)
1729  {
1730  if(unique_case_condition)
1731  {
1732  indented_output_stream->Append("casez (" + guard_casez_port + ")");
1734  }
1735  }
1736  for(unsigned int i = 0; i < state_transitions.size(); i++)
1737  {
1738  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Analyzing transition " + state_transitions[i]);
1739  tokenizer transition_tokens(state_transitions[i], sep);
1740  tokenizer::const_iterator itt = transition_tokens.begin();
1741 
1742  tokenizer::const_iterator current_input_it;
1743  std::string input_string = *itt;
1744  if(mod->get_in_port_size() - numInputIgnored)
1745  {
1746  boost::char_separator<char> comma_sep(",", nullptr);
1747  tokenizer current_input_tokens(input_string, comma_sep);
1748  current_input_it = current_input_tokens.begin();
1749  ++itt;
1750  }
1751  std::string next_state = *itt;
1752  ++itt;
1753  std::string transition_outputs = *itt;
1754  ++itt;
1755  THROW_ASSERT(itt == transition_tokens.end(), "Bad transition format");
1756 
1757  if(!unique_transition)
1758  {
1759  if(i == 0)
1760  {
1761  if(unique_case_condition)
1762  {
1763  indented_output_stream->Append(STR(n_bits_guard_casez_port) + "'b");
1764  }
1765  else
1766  {
1767  indented_output_stream->Append("if (");
1768  }
1769  }
1770  else if((i + 1) == state_transitions.size())
1771  {
1772  if(unique_case_condition)
1773  {
1774  indented_output_stream->Append("default:");
1775  }
1776  else
1777  {
1778  indented_output_stream->Append("else");
1779  }
1780  }
1781  else
1782  {
1783  if(unique_case_condition)
1784  {
1785  indented_output_stream->Append(STR(n_bits_guard_casez_port) + "'b");
1786  }
1787  else
1788  {
1789  indented_output_stream->Append("else if (");
1790  }
1791  }
1792  if((i + 1) < state_transitions.size())
1793  {
1794  bool first_test = true;
1795  for(unsigned int ind = 0; ind < mod->get_in_port_size(); ind++)
1796  {
1797  port_name = HDL_manager::convert_to_identifier(this, mod->get_in_port(ind)->get_id());
1798  auto port_size = mod->get_in_port(ind)->get_typeRef()->size;
1799  auto vec_size = mod->get_in_port(ind)->get_typeRef()->vector_size;
1800  if(port_name != reset_port && port_name != clock_port && port_name != start_port &&
1801  port_name != STR(SELECTOR_REGISTER_FILE))
1802  {
1803  std::string in_or_conditions = *current_input_it;
1804  boost::char_separator<char> pipe_sep("|", nullptr);
1805  tokenizer in_or_conditions_tokens(in_or_conditions, pipe_sep);
1806 
1807  if((*in_or_conditions_tokens.begin()) != "-")
1808  {
1809  if(!first_test)
1810  {
1811  indented_output_stream->Append(" && ");
1812  }
1813  else
1814  {
1815  first_test = false;
1816  }
1817  bool first_test_or = true;
1818  bool need_parenthesis = false;
1819  std::string res_or_conditions;
1820  for(tokenizer::const_iterator in_or_conditions_tokens_it = in_or_conditions_tokens.begin();
1821  in_or_conditions_tokens_it != in_or_conditions_tokens.end();
1822  ++in_or_conditions_tokens_it)
1823  {
1824  THROW_ASSERT((*in_or_conditions_tokens_it) != "-", "wrong conditions structure");
1825  if(!first_test_or)
1826  {
1827  res_or_conditions += " || ";
1828  need_parenthesis = true;
1829  }
1830  else
1831  {
1832  first_test_or = false;
1833  }
1834 
1835  res_or_conditions += port_name;
1836  if((*in_or_conditions_tokens_it)[0] == '&')
1837  {
1838  auto n_bits = vec_size == 0 ? port_size : vec_size;
1839  auto pos = static_cast<unsigned>(std::stoul((*in_or_conditions_tokens_it).substr(1)));
1840  if(unique_case_condition)
1841  {
1842  res_or_conditions = "";
1843  for(unsigned int guard_ind = 0; guard_ind < n_bits; ++guard_ind)
1844  {
1845  res_or_conditions =
1846  (guard_ind == pos ? "1" : (guard_ind < pos ? "0" : (is_yosys ? "0" : "?"))) +
1847  res_or_conditions;
1848  }
1849  }
1850  else
1851  {
1852  res_or_conditions +=
1853  (n_bits > 1 ? std::string("[") + STR(pos) + "]" : "") + " == 1'b1";
1854  }
1855  }
1856  else
1857  {
1858  res_or_conditions += std::string(" == ") +
1859  ((*in_or_conditions_tokens_it)[0] == '-' ? "-" : "") +
1860  (vec_size == 0 ? STR(port_size) : STR(vec_size));
1861  if(port_size > 1 || (port_size == 1 && vec_size > 0))
1862  {
1863  res_or_conditions += "'d" + (((*in_or_conditions_tokens_it)[0] == '-') ?
1864  ((*in_or_conditions_tokens_it).substr(1)) :
1865  *in_or_conditions_tokens_it);
1866  }
1867  else
1868  {
1869  res_or_conditions += "'b" + *in_or_conditions_tokens_it;
1870  }
1871  }
1872  }
1873  if(need_parenthesis)
1874  {
1875  res_or_conditions = "(" + res_or_conditions + ")";
1876  }
1877  indented_output_stream->Append(res_or_conditions);
1878  }
1879  ++current_input_it;
1880  }
1881  }
1882  if(unique_case_condition)
1883  {
1885  }
1886  else
1887  {
1889  }
1890  }
1892  indented_output_stream->Append("begin");
1894  }
1895  if(single_proc || output_index == mod->get_out_port_size())
1896  {
1897  indented_output_stream->Append("_next_state = " + next_state + ";\n");
1898  }
1899  for(unsigned int ind = 0; ind < mod->get_out_port_size(); ind++)
1900  {
1901  if(mod->get_out_port(ind)->get_id() == PRESENT_STATE_PORT_NAME)
1902  {
1903  continue;
1904  }
1905  if(mod->get_out_port(ind)->get_id() == NEXT_STATE_PORT_NAME)
1906  {
1907  continue;
1908  }
1909  port_name = HDL_manager::convert_to_identifier(this, mod->get_out_port(ind)->get_id());
1910  if(transition_outputs[ind] != '-')
1911  {
1912  if(single_proc || output_index == ind)
1913  {
1914  if(transition_outputs[ind] == '2')
1915  {
1916  indented_output_stream->Append(port_name + " = 1'bX;\n");
1917  }
1918  else
1919  {
1920  if(bypass_signals.find(ind) == bypass_signals.end() ||
1921  bypass_signals.find(ind)->second.find(present_state) ==
1922  bypass_signals.find(ind)->second.end())
1923  {
1924  indented_output_stream->Append(port_name + " = 1'b" + transition_outputs[ind] + ";\n");
1925  }
1926  else
1927  {
1928  indented_output_stream->Append(port_name + " = ");
1929  for(const auto& stateIns : bypass_signals.find(ind)->second)
1930  {
1931  if(stateIns.first != present_state)
1932  {
1933  continue;
1934  }
1935  bool first_i = true;
1936  for(const auto& in : stateIns.second)
1937  {
1938  if(first_i)
1939  {
1940  first_i = false;
1941  }
1942  else
1943  {
1944  indented_output_stream->Append(" || ");
1945  }
1946  auto in_port_name =
1947  HDL_manager::convert_to_identifier(this, mod->get_in_port(in)->get_id());
1948  indented_output_stream->Append(in_port_name);
1949  }
1950  }
1952  }
1953  }
1954  }
1955  }
1956  }
1957  if(!unique_transition)
1958  {
1962  }
1963  }
1964  if(!unique_transition)
1965  {
1966  if(unique_case_condition)
1967  {
1969  indented_output_stream->Append("endcase\n");
1970  }
1971  }
1972  }
1973 
1976 
1977  if(reset_state == present_state)
1978  {
1979  indented_output_stream->Append("\nelse");
1980  indented_output_stream->Append("\nbegin");
1982 
1983  for(unsigned int i = 0; i < mod->get_out_port_size(); i++)
1984  {
1985  if(mod->get_out_port(i)->get_id() == PRESENT_STATE_PORT_NAME)
1986  {
1987  continue;
1988  }
1989  if(mod->get_out_port(i)->get_id() == NEXT_STATE_PORT_NAME)
1990  {
1991  continue;
1992  }
1993  if(starts_with(mod->get_out_port(i)->get_id(), "selector_MUX") ||
1994  starts_with(mod->get_out_port(i)->get_id(), "wrenable_reg"))
1995  {
1996  port_name = HDL_manager::convert_to_identifier(this, mod->get_out_port(i)->get_id());
1997  if((single_proc || output_index == i) &&
1998  (parameters->IsParameter("enable-FSMX") && parameters->GetParameter<int>("enable-FSMX") == 1))
1999  {
2000  indented_output_stream->Append(port_name + " = 1'bX;\n");
2001  }
2002  }
2003  }
2004  if(single_proc || output_index == mod->get_out_port_size())
2005  {
2006  indented_output_stream->Append("_next_state = " + present_state + ";");
2007  }
2010  }
2012  }
2013 
2015  indented_output_stream->Append("default :\n");
2016  indented_output_stream->Append("begin");
2017  if(single_proc)
2018  {
2020  indented_output_stream->Append("_next_state = " + reset_state + ";\n");
2021  for(unsigned int i = 0; i < mod->get_out_port_size(); i++)
2022  {
2023  if(mod->get_out_port(i)->get_id() == PRESENT_STATE_PORT_NAME)
2024  {
2025  continue;
2026  }
2027  if(mod->get_out_port(i)->get_id() == NEXT_STATE_PORT_NAME)
2028  {
2029  continue;
2030  }
2031  if(starts_with(mod->get_out_port(i)->get_id(), "selector_MUX") ||
2032  starts_with(mod->get_out_port(i)->get_id(), "wrenable_reg"))
2033  {
2034  port_name = HDL_manager::convert_to_identifier(this, mod->get_out_port(i)->get_id());
2035  if((single_proc || output_index == i) &&
2036  (parameters->IsParameter("enable-FSMX") && parameters->GetParameter<int>("enable-FSMX") == 1))
2037  {
2038  indented_output_stream->Append(port_name + " = 1'bX;\n");
2039  }
2040  }
2041  }
2043  }
2044  else
2045  {
2047  }
2051  indented_output_stream->Append("endcase\n");
2054 }
2055 
2057 {
2058  auto* mod = GetPointer<module>(cir);
2059  THROW_ASSERT(mod, "Expected a component object");
2060  const NP_functionalityRef& np = mod->get_NP_functionality();
2061  THROW_ASSERT(np, "NP Behavioral description is missing for module: " +
2063  std::string beh_desc = np->get_NP_functionality(NP_functionality::VERILOG_PROVIDED);
2064  THROW_ASSERT(beh_desc != "", "VERILOG behavioral description is missing for module: " +
2067  if(!parameters->getOption<bool>(OPT_reset_level))
2068  {
2069  boost::replace_all(beh_desc, "1RESET_EDGE_FORCE", "or negedge " + std::string(RESET_PORT_NAME));
2070  if(parameters->getOption<std::string>(OPT_reset_type) == "async")
2071  {
2072  boost::replace_all(beh_desc, "1RESET_EDGE", "or negedge " + std::string(RESET_PORT_NAME));
2073  }
2074  else
2075  {
2076  boost::replace_all(beh_desc, "1RESET_EDGE", "");
2077  }
2078  boost::replace_all(beh_desc, "1RESET_VALUE", std::string(RESET_PORT_NAME) + " == 1'b0");
2079  }
2080  else
2081  {
2082  boost::replace_all(beh_desc, "1RESET_EDGE_FORCE", "or posedge " + std::string(RESET_PORT_NAME));
2083  if(parameters->getOption<std::string>(OPT_reset_type) == "async")
2084  {
2085  boost::replace_all(beh_desc, "1RESET_EDGE", "or posedge " + std::string(RESET_PORT_NAME));
2086  }
2087  else
2088  {
2089  boost::replace_all(beh_desc, "1RESET_EDGE", "");
2090  }
2091  boost::replace_all(beh_desc, "1RESET_VALUE", std::string(RESET_PORT_NAME) + " == 1'b1");
2092  }
2093  if(parameters->getOption<bool>(OPT_reg_init_value))
2094  {
2095  boost::replace_all(beh_desc, "1INIT_ZERO_VALUE", "=0");
2096  }
2097  else
2098  {
2099  boost::replace_all(beh_desc, "1INIT_ZERO_VALUE", "");
2100  }
2101  indented_output_stream->Append(beh_desc);
2102 }
2103 
2105 {
2107 }
2108 
2110 {
2112 }
2113 
2115 {
2116  THROW_ASSERT(cir->get_kind() == component_o_K || cir->get_kind() == channel_o_K,
2117  "Expected a component or a channel got something of different");
2118  auto* mod = GetPointer<module>(cir);
2119  const NP_functionalityRef& np = mod->get_NP_functionality();
2120  bool first_it = true;
2121 
2123  if(mod->ExistsParameter(MEMORY_PARAMETER))
2124  {
2126  std::string memory_str = mod->GetParameter(MEMORY_PARAMETER);
2127  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "MEMORY_PARAMETER is " + memory_str);
2128  std::vector<std::string> mem_tag = string_to_container<std::vector<std::string>>(memory_str, ";");
2129  for(const auto& i : mem_tag)
2130  {
2131  std::vector<std::string> mem_add = string_to_container<std::vector<std::string>>(i, "=");
2132  THROW_ASSERT(mem_add.size() == 2, "malformed address");
2133  if(first_it)
2134  {
2135  indented_output_stream->Append("parameter ");
2137  first_it = false;
2138  }
2139  else
2140  {
2142  }
2143  std::string name = mem_add[0];
2144  std::string value = mem_add[1];
2145  if(value.find("\"\"") != std::string::npos)
2146  {
2147  boost::replace_all(value, "\"\"", "\"");
2148  }
2149  else if(value.find('\"') != std::string::npos)
2150  {
2151  boost::replace_all(value, "\"", "");
2152  value = STR(value.size()) + "'b" + value;
2153  }
2154  indented_output_stream->Append(name + "=" + value);
2155  }
2156  }
2157 
2158  if(np)
2159  {
2161  std::vector<std::pair<std::string, structural_objectRef>> library_parameters;
2162  mod->get_NP_library_parameters(cir, library_parameters);
2163  for(const auto& library_parameter : library_parameters)
2164  {
2165  if(first_it)
2166  {
2167  indented_output_stream->Append("parameter ");
2169  first_it = false;
2170  }
2171  else
2172  {
2174  }
2175  const auto& name = library_parameter.first;
2176  const auto obj = library_parameter.second;
2177  if(obj)
2178  {
2179  structural_type_descriptor::s_type type = obj->get_typeRef()->type;
2182  {
2183  indented_output_stream->Append(BITSIZE_PREFIX + name + "=" + STR(obj->get_typeRef()->size));
2185  indented_output_stream->Append(NUM_ELEM_PREFIX + name + "=" + STR(obj->get_typeRef()->vector_size));
2186  }
2187  else
2188  {
2190  if(obj->get_kind() == port_vector_o_K)
2191  {
2193  auto ports_size = GetPointer<port_o>(obj)->get_ports_size();
2194  if(ports_size == 0)
2195  {
2196  ports_size = 2;
2197  }
2198  indented_output_stream->Append(PORTSIZE_PREFIX + name + "=" + STR(ports_size));
2199  }
2200  }
2201  }
2202  else
2203  {
2204  std::string param = mod->GetDefaultParameter(name);
2206  " parameter = #" << name << "#; value = #" << param << "#");
2207  if(param.find("\"\"") != std::string::npos)
2208  {
2209  boost::replace_all(param, "\"\"", "\"");
2210  }
2211  else if(param.find('\"') != std::string::npos)
2212  {
2213  boost::replace_all(param, "\"", "");
2214  param = STR(param.size()) + "'b" + param;
2215  }
2216  indented_output_stream->Append(name + "=" + param);
2217  }
2218  }
2219  }
2220 
2222  if(!first_it)
2223  {
2226  }
2227 }
2228 
2231 {
2232  debug_level = parameters->get_class_debug_level(GET_CLASS(*this));
2233 }
2234 
2236 
2237 bool verilog_writer::check_keyword(const std::string& id) const
2238 {
2239  return check_keyword_verilog(id);
2240 }
2241 
2242 bool verilog_writer::check_keyword_verilog(const std::string& id)
2243 {
2244  return keywords.count(id);
2245 }
2246 
2248 {
2250 `ifdef __ICARUS__
2251  `define _SIM_HAVE_CLOG2
2252 `endif
2253 `ifdef VERILATOR
2254  `define _SIM_HAVE_CLOG2
2255 `endif
2256 `ifdef MODEL_TECH
2257  `define _SIM_HAVE_CLOG2
2258 `endif
2259 `ifdef VCS
2260  `define _SIM_HAVE_CLOG2
2261 `endif
2262 `ifdef NCVERILOG
2263  `define _SIM_HAVE_CLOG2
2264 `endif
2265 `ifdef XILINX_SIMULATOR
2266  `define _SIM_HAVE_CLOG2
2267 `endif
2268 `ifdef XILINX_ISIM
2269  `define _SIM_HAVE_CLOG2
2270 `endif
2271 
2272 )");
2273 }
#define register_AR_NORETIME_INT
#define PRESENT_STATE_PORT_NAME
#define DEBUG_LEVEL_VERY_PEDANTIC
extremely verbose debugging print is performed.
#define PORTSIZE_PREFIX
void write_port_decl_header() override
Write the header for port_decl.
#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;.
TVMValue param[3]
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 register_AR_NORETIME_UINT
#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 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.
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.
#define AND_GATE_STD
int debug_level
debugging level of the class
void write_assign(const std::string &op0, const std::string &op1) override
void WriteBuiltin(const structural_objectConstRef component) override
Write a builtin component.
std::string get_NP_functionality(NP_functionaly_type type) const
Return the description provided the type.
std::string type_converter(structural_type_descriptorRef Type) override
Return a language based type string given a structural_type_descriptor.
#define MEMORY_PARAMETER
void Indent()
Manually increase the indenting of the code.
void write_io_signal_post_fix_vector(const structural_objectRef &port, const structural_objectRef &sig) override
void write_vector_port_binding(const structural_objectRef &port, bool first_port_analyzed) override
exceptions managed by PandA
#define DFF_GATE_STD
Collect information about resource performance.
Class to print indented code.
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
const IndentedOutputStreamRef indented_output_stream
Represents the stream we are currently writing to.
Class specification of the manager of the technology library data structures.
void write_module_internal_declaration(const structural_objectRef &cir) override
Write the declaration of internal objects of the module.
#define GET_TYPE_NAME(structural_obj)
Macro returning the string name of a type.
bool check_keyword(const std::string &id) const override
#define BITSIZE_PREFIX
verilog_writer(const ParameterConstRef parameters)
Constructor.
void write_comment(const std::string &comment_string) override
Print a comment.
#define STR(s)
Macro which performs a lexical_cast to a string.
Auxiliary methods for manipulating string.
void write_header() override
Writes the header part of the file.
#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_module_parametrization(const structural_objectRef &cir) override
Module can be parameterized with respect different features.
#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_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 is_yosys, const std::map< unsigned int, std::map< std::string, std::set< unsigned int >>> &bypass_signals) override
Write the transition and output functions.
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...
s_type
Define the possible type of a structural object.
Class for system verilog writing.
unsigned map[NUM_VERTICES]
Definition: bfs.c:12
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.
#define NAND_GATE_STD
void write_module_definition_begin(const structural_objectRef &cir) override
Write the top constructor declaration.
virtual void print(std::ostream &os) const
Print the structural_object (for debug purpose)
#define index(x, y)
Definition: Keccak.c:74
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.
void write_module_instance_end(const structural_objectRef &cir) override
Write the ending part of the instance of a module.
#define register_AR_NORETIME
register with asynchronous reset no retime
virtual enum so_kind get_kind() const =0
Virtual function used to find the real type of a structural_object instance.
void write_io_signal_post_fix(const structural_objectRef &port, const structural_objectRef &sig) override
Write some code managing primary ports to signals connections.
static const std::map< std::string, std::string > builtin_to_verilog_keyword
map putting into relation standard gates with the corresponding built-in Verilog statements.
#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.
#define NOR_GATE_STD
constants used in testbench generation
void write_module_definition_end(const structural_objectRef &cir) override
Write the end part in a module declaration.
#define XOR_GATE_STD
void write_module_parametrization_decl(const structural_objectRef &cir) override
Write the declaration of the module parameters.
void write_port_decl_tail() override
Write the tail for port_decl.
#define GET_TYPE_SIZE(structural_obj)
Macro returning the size of the type of a structural object.
std::string id_type
Original type id of the structural object.
#define STD_CLOSING_CHAR
Special closing character used to close the current nested level.
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 register_AR_NORETIME_REAL
void write_component_declaration(const structural_objectRef &cir) override
Write the declaration of a component.
void write_module_declaration(const structural_objectRef &cir) override
Write the declaration of the module.
#define STATE_NAME_PREFIX
state name prefix
const structural_objectRef get_owner() const
Return the owner.
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.
~verilog_writer() override
Destructor.
void write_library_declaration(const structural_objectRef &cir) override
Write the #include for each used library.
#define BUFF_GATE_STD
static unsigned int bitnumber(unsigned long long n)
Counts the number of bits in an unsigned int.
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...
const ParameterConstRef parameters
the set of input parameters
static bool check_keyword_verilog(const std::string &word)
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.
#define NOT_GATE_STD
#define SELECTOR_REGISTER_FILE
Not parsed functionality manager.
void Deindent()
Manually reduce the indenting of the code.
std::string may_slice_string(const structural_objectRef &cir)
return the slice in case of a port owned by a port vector
#define RESET_PORT_NAME
This class writes different HDL based descriptions (VHDL, Verilog, SystemC) starting from a structura...
void print(std::ostream &os) const
function that prints the class.
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.
static const std::set< std::string > keywords
void write_port_declaration(const structural_objectRef &cir, bool last_port_to_analyze) override
Write the port declaration starting from a port object.
#define XNOR_GATE_STD
unsigned long long vector_size
The number of the elements of a vector.
#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