yosys-master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
verilog_backend.cc
Go to the documentation of this file.
1 /*
2  * yosys -- Yosys Open SYnthesis Suite
3  *
4  * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
5  *
6  * Permission to use, copy, modify, and/or distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  *
18  * ---
19  *
20  * A simple and straightforward verilog backend.
21  *
22  * Note that RTLIL processes can't always be mapped easily to a Verilog
23  * process. Therefore this frontend should only be used to export a
24  * Verilog netlist (i.e. after the "proc" pass has converted all processes
25  * to logic networks and registers).
26  *
27  */
28 
29 #include "kernel/register.h"
30 #include "kernel/celltypes.h"
31 #include "kernel/log.h"
32 #include <string>
33 #include <sstream>
34 #include <set>
35 #include <map>
36 
39 
42 std::map<RTLIL::IdString, int> auto_name_map;
43 std::set<RTLIL::IdString> reg_wires, reg_ct;
44 
46 
47 void reset_auto_counter_id(RTLIL::IdString id, bool may_rename)
48 {
49  const char *str = id.c_str();
50 
51  if (*str == '$' && may_rename && !norename)
53 
54  if (str[0] != '\\' || str[1] != '_' || str[2] == 0)
55  return;
56 
57  for (int i = 2; str[i] != 0; i++) {
58  if (str[i] == '_' && str[i+1] == 0)
59  continue;
60  if (str[i] < '0' || str[i] > '9')
61  return;
62  }
63 
64  int num = atoi(str+2);
65  if (num >= auto_name_offset)
66  auto_name_offset = num + 1;
67 }
68 
70 {
71  auto_name_map.clear();
73  auto_name_offset = 0;
74 
75  reset_auto_counter_id(module->name, false);
76 
77  for (auto it = module->wires_.begin(); it != module->wires_.end(); it++)
78  reset_auto_counter_id(it->second->name, true);
79 
80  for (auto it = module->cells_.begin(); it != module->cells_.end(); it++) {
81  reset_auto_counter_id(it->second->name, true);
82  reset_auto_counter_id(it->second->type, false);
83  }
84 
85  for (auto it = module->processes.begin(); it != module->processes.end(); it++)
86  reset_auto_counter_id(it->second->name, false);
87 
88  auto_name_digits = 1;
89  for (size_t i = 10; i < auto_name_offset + auto_name_map.size(); i = i*10)
91 
92  for (auto it = auto_name_map.begin(); it != auto_name_map.end(); it++)
93  log(" renaming `%s' to `_%0*d_'.\n", it->first.c_str(), auto_name_digits, auto_name_offset + it->second);
94 }
95 
96 std::string id(RTLIL::IdString internal_id, bool may_rename = true)
97 {
98  const char *str = internal_id.c_str();
99  bool do_escape = false;
100 
101  if (may_rename && auto_name_map.count(internal_id) != 0) {
102  char buffer[100];
103  snprintf(buffer, 100, "_%0*d_", auto_name_digits, auto_name_offset + auto_name_map[internal_id]);
104  return std::string(buffer);
105  }
106 
107  if (*str == '\\')
108  str++;
109 
110  if ('0' <= *str && *str <= '9')
111  do_escape = true;
112 
113  for (int i = 0; str[i]; i++)
114  {
115  if ('0' <= str[i] && str[i] <= '9')
116  continue;
117  if ('a' <= str[i] && str[i] <= 'z')
118  continue;
119  if ('A' <= str[i] && str[i] <= 'Z')
120  continue;
121  if (str[i] == '_')
122  continue;
123  do_escape = true;
124  break;
125  }
126 
127  if (do_escape)
128  return "\\" + std::string(str) + " ";
129  return std::string(str);
130 }
131 
132 bool is_reg_wire(RTLIL::SigSpec sig, std::string &reg_name)
133 {
134  if (!sig.is_chunk() || sig.as_chunk().wire == NULL)
135  return false;
136 
137  RTLIL::SigChunk chunk = sig.as_chunk();
138 
139  if (reg_wires.count(chunk.wire->name) == 0)
140  return false;
141 
142  reg_name = id(chunk.wire->name);
143  if (sig.size() != chunk.wire->width) {
144  if (sig.size() == 1)
145  reg_name += stringf("[%d]", chunk.wire->start_offset + chunk.offset);
146  else
147  reg_name += stringf("[%d:%d]", chunk.wire->start_offset + chunk.offset + chunk.width - 1,
148  chunk.wire->start_offset + chunk.offset);
149  }
150 
151  return true;
152 }
153 
154 void dump_const(std::ostream &f, const RTLIL::Const &data, int width = -1, int offset = 0, bool no_decimal = false, bool set_signed = false)
155 {
156  if (width < 0)
157  width = data.bits.size() - offset;
158  if ((data.flags & RTLIL::CONST_FLAG_STRING) == 0 || width != (int)data.bits.size()) {
159  if (width == 32 && !no_decimal) {
160  int32_t val = 0;
161  for (int i = offset+width-1; i >= offset; i--) {
162  log_assert(i < (int)data.bits.size());
163  if (data.bits[i] != RTLIL::S0 && data.bits[i] != RTLIL::S1)
164  goto dump_bits;
165  if (data.bits[i] == RTLIL::S1 && (i - offset) == 31)
166  goto dump_bits;
167  if (data.bits[i] == RTLIL::S1)
168  val |= 1 << (i - offset);
169  }
170  f << stringf("32'%sd%d", set_signed ? "s" : "", val);
171  } else {
172  dump_bits:
173  f << stringf("%d'%sb", width, set_signed ? "s" : "");
174  if (width == 0)
175  f << stringf("0");
176  for (int i = offset+width-1; i >= offset; i--) {
177  log_assert(i < (int)data.bits.size());
178  switch (data.bits[i]) {
179  case RTLIL::S0: f << stringf("0"); break;
180  case RTLIL::S1: f << stringf("1"); break;
181  case RTLIL::Sx: f << stringf("x"); break;
182  case RTLIL::Sz: f << stringf("z"); break;
183  case RTLIL::Sa: f << stringf("z"); break;
184  case RTLIL::Sm: log_error("Found marker state in final netlist.");
185  }
186  }
187  }
188  } else {
189  f << stringf("\"");
190  std::string str = data.decode_string();
191  for (size_t i = 0; i < str.size(); i++) {
192  if (str[i] == '\n')
193  f << stringf("\\n");
194  else if (str[i] == '\t')
195  f << stringf("\\t");
196  else if (str[i] < 32)
197  f << stringf("\\%03o", str[i]);
198  else if (str[i] == '"')
199  f << stringf("\\\"");
200  else if (str[i] == '\\')
201  f << stringf("\\\\");
202  else
203  f << str[i];
204  }
205  f << stringf("\"");
206  }
207 }
208 
209 void dump_sigchunk(std::ostream &f, const RTLIL::SigChunk &chunk, bool no_decimal = false)
210 {
211  if (chunk.wire == NULL) {
212  dump_const(f, chunk.data, chunk.width, chunk.offset, no_decimal);
213  } else {
214  if (chunk.width == chunk.wire->width && chunk.offset == 0) {
215  f << stringf("%s", id(chunk.wire->name).c_str());
216  } else if (chunk.width == 1) {
217  if (chunk.wire->upto)
218  f << stringf("%s[%d]", id(chunk.wire->name).c_str(), (chunk.wire->width - chunk.offset - 1) + chunk.wire->start_offset);
219  else
220  f << stringf("%s[%d]", id(chunk.wire->name).c_str(), chunk.offset + chunk.wire->start_offset);
221  } else {
222  if (chunk.wire->upto)
223  f << stringf("%s[%d:%d]", id(chunk.wire->name).c_str(),
224  (chunk.wire->width - (chunk.offset + chunk.width - 1) - 1) + chunk.wire->start_offset,
225  (chunk.wire->width - chunk.offset - 1) + chunk.wire->start_offset);
226  else
227  f << stringf("%s[%d:%d]", id(chunk.wire->name).c_str(),
228  (chunk.offset + chunk.width - 1) + chunk.wire->start_offset,
229  chunk.offset + chunk.wire->start_offset);
230  }
231  }
232 }
233 
234 void dump_sigspec(std::ostream &f, const RTLIL::SigSpec &sig)
235 {
236  if (sig.is_chunk()) {
237  dump_sigchunk(f, sig.as_chunk());
238  } else {
239  f << stringf("{ ");
240  for (auto it = sig.chunks().rbegin(); it != sig.chunks().rend(); it++) {
241  if (it != sig.chunks().rbegin())
242  f << stringf(", ");
243  dump_sigchunk(f, *it, true);
244  }
245  f << stringf(" }");
246  }
247 }
248 
249 void dump_attributes(std::ostream &f, std::string indent, std::map<RTLIL::IdString, RTLIL::Const> &attributes, char term = '\n')
250 {
251  if (noattr)
252  return;
253  for (auto it = attributes.begin(); it != attributes.end(); it++) {
254  f << stringf("%s" "%s %s", indent.c_str(), attr2comment ? "/*" : "(*", id(it->first).c_str());
255  f << stringf(" = ");
256  dump_const(f, it->second);
257  f << stringf(" %s%c", attr2comment ? "*/" : "*)", term);
258  }
259 }
260 
261 void dump_wire(std::ostream &f, std::string indent, RTLIL::Wire *wire)
262 {
263  dump_attributes(f, indent, wire->attributes);
264 #if 0
265  if (wire->port_input && !wire->port_output)
266  f << stringf("%s" "input %s", indent.c_str(), reg_wires.count(wire->name) ? "reg " : "");
267  else if (!wire->port_input && wire->port_output)
268  f << stringf("%s" "output %s", indent.c_str(), reg_wires.count(wire->name) ? "reg " : "");
269  else if (wire->port_input && wire->port_output)
270  f << stringf("%s" "inout %s", indent.c_str(), reg_wires.count(wire->name) ? "reg " : "");
271  else
272  f << stringf("%s" "%s ", indent.c_str(), reg_wires.count(wire->name) ? "reg" : "wire");
273  if (wire->width != 1)
274  f << stringf("[%d:%d] ", wire->width - 1 + wire->start_offset, wire->start_offset);
275  f << stringf("%s;\n", id(wire->name).c_str());
276 #else
277  // do not use Verilog-2k "outut reg" syntax in verilog export
278  std::string range = "";
279  if (wire->width != 1) {
280  if (wire->upto)
281  range = stringf(" [%d:%d]", wire->start_offset, wire->width - 1 + wire->start_offset);
282  else
283  range = stringf(" [%d:%d]", wire->width - 1 + wire->start_offset, wire->start_offset);
284  }
285  if (wire->port_input && !wire->port_output)
286  f << stringf("%s" "input%s %s;\n", indent.c_str(), range.c_str(), id(wire->name).c_str());
287  if (!wire->port_input && wire->port_output)
288  f << stringf("%s" "output%s %s;\n", indent.c_str(), range.c_str(), id(wire->name).c_str());
289  if (wire->port_input && wire->port_output)
290  f << stringf("%s" "inout%s %s;\n", indent.c_str(), range.c_str(), id(wire->name).c_str());
291  if (reg_wires.count(wire->name))
292  f << stringf("%s" "reg%s %s;\n", indent.c_str(), range.c_str(), id(wire->name).c_str());
293  else if (!wire->port_input && !wire->port_output)
294  f << stringf("%s" "wire%s %s;\n", indent.c_str(), range.c_str(), id(wire->name).c_str());
295 #endif
296 }
297 
298 void dump_memory(std::ostream &f, std::string indent, RTLIL::Memory *memory)
299 {
300  dump_attributes(f, indent, memory->attributes);
301  f << stringf("%s" "reg [%d:0] %s [%d:0];\n", indent.c_str(), memory->width-1, id(memory->name).c_str(), memory->size-1);
302 }
303 
304 void dump_cell_expr_port(std::ostream &f, RTLIL::Cell *cell, std::string port, bool gen_signed = true)
305 {
306  if (gen_signed && cell->parameters.count("\\" + port + "_SIGNED") > 0 && cell->parameters["\\" + port + "_SIGNED"].as_bool()) {
307  f << stringf("$signed(");
308  dump_sigspec(f, cell->getPort("\\" + port));
309  f << stringf(")");
310  } else
311  dump_sigspec(f, cell->getPort("\\" + port));
312 }
313 
314 std::string cellname(RTLIL::Cell *cell)
315 {
316  if (!norename && cell->name[0] == '$' && reg_ct.count(cell->type) && cell->hasPort("\\Q"))
317  {
318  RTLIL::SigSpec sig = cell->getPort("\\Q");
319  if (GetSize(sig) != 1 || sig.is_fully_const())
320  goto no_special_reg_name;
321 
322  RTLIL::Wire *wire = sig[0].wire;
323 
324  if (wire->name[0] != '\\')
325  goto no_special_reg_name;
326 
327  std::string cell_name = wire->name.str();
328 
329  size_t pos = cell_name.find('[');
330  if (pos != std::string::npos)
331  cell_name = cell_name.substr(0, pos) + "_reg" + cell_name.substr(pos);
332  else
333  cell_name = cell_name + "_reg";
334 
335  if (wire->width != 1)
336  cell_name += stringf("[%d]", wire->start_offset + sig[0].offset);
337 
338  if (active_module && active_module->count_id(cell_name) > 0)
339  goto no_special_reg_name;
340 
341  return id(cell_name);
342  }
343  else
344  {
345 no_special_reg_name:
346  return id(cell->name).c_str();
347  }
348 }
349 
350 void dump_cell_expr_uniop(std::ostream &f, std::string indent, RTLIL::Cell *cell, std::string op)
351 {
352  f << stringf("%s" "assign ", indent.c_str());
353  dump_sigspec(f, cell->getPort("\\Y"));
354  f << stringf(" = %s ", op.c_str());
355  dump_attributes(f, "", cell->attributes, ' ');
356  dump_cell_expr_port(f, cell, "A", true);
357  f << stringf(";\n");
358 }
359 
360 void dump_cell_expr_binop(std::ostream &f, std::string indent, RTLIL::Cell *cell, std::string op)
361 {
362  f << stringf("%s" "assign ", indent.c_str());
363  dump_sigspec(f, cell->getPort("\\Y"));
364  f << stringf(" = ");
365  dump_cell_expr_port(f, cell, "A", true);
366  f << stringf(" %s ", op.c_str());
367  dump_attributes(f, "", cell->attributes, ' ');
368  dump_cell_expr_port(f, cell, "B", true);
369  f << stringf(";\n");
370 }
371 
372 bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
373 {
374  if (cell->type == "$_NOT_") {
375  f << stringf("%s" "assign ", indent.c_str());
376  dump_sigspec(f, cell->getPort("\\Y"));
377  f << stringf(" = ");
378  f << stringf("~");
379  dump_attributes(f, "", cell->attributes, ' ');
380  dump_cell_expr_port(f, cell, "A", false);
381  f << stringf(";\n");
382  return true;
383  }
384 
385  if (cell->type.in("$_AND_", "$_NAND_", "$_OR_", "$_NOR_", "$_XOR_", "$_XNOR_")) {
386  f << stringf("%s" "assign ", indent.c_str());
387  dump_sigspec(f, cell->getPort("\\Y"));
388  f << stringf(" = ");
389  if (cell->type.in("$_NAND_", "$_NOR_", "$_XNOR_"))
390  f << stringf("~(");
391  dump_cell_expr_port(f, cell, "A", false);
392  f << stringf(" ");
393  if (cell->type.in("$_AND_", "$_NAND_"))
394  f << stringf("&");
395  if (cell->type.in("$_OR_", "$_NOR_"))
396  f << stringf("|");
397  if (cell->type.in("$_XOR_", "$_XNOR_"))
398  f << stringf("^");
399  dump_attributes(f, "", cell->attributes, ' ');
400  f << stringf(" ");
401  dump_cell_expr_port(f, cell, "B", false);
402  if (cell->type.in("$_NAND_", "$_NOR_", "$_XNOR_"))
403  f << stringf(")");
404  f << stringf(";\n");
405  return true;
406  }
407 
408  if (cell->type == "$_MUX_") {
409  f << stringf("%s" "assign ", indent.c_str());
410  dump_sigspec(f, cell->getPort("\\Y"));
411  f << stringf(" = ");
412  dump_cell_expr_port(f, cell, "S", false);
413  f << stringf(" ? ");
414  dump_attributes(f, "", cell->attributes, ' ');
415  dump_cell_expr_port(f, cell, "B", false);
416  f << stringf(" : ");
417  dump_cell_expr_port(f, cell, "A", false);
418  f << stringf(";\n");
419  return true;
420  }
421 
422  if (cell->type.in("$_AOI3_", "$_OAI3_")) {
423  f << stringf("%s" "assign ", indent.c_str());
424  dump_sigspec(f, cell->getPort("\\Y"));
425  f << stringf(" = ~((");
426  dump_cell_expr_port(f, cell, "A", false);
427  f << stringf(cell->type == "$_AOI3_" ? " & " : " | ");
428  dump_cell_expr_port(f, cell, "B", false);
429  f << stringf(cell->type == "$_AOI3_" ? ") |" : ") &");
430  dump_attributes(f, "", cell->attributes, ' ');
431  f << stringf(" ");
432  dump_cell_expr_port(f, cell, "C", false);
433  f << stringf(");\n");
434  return true;
435  }
436 
437  if (cell->type.in("$_AOI4_", "$_OAI4_")) {
438  f << stringf("%s" "assign ", indent.c_str());
439  dump_sigspec(f, cell->getPort("\\Y"));
440  f << stringf(" = ~((");
441  dump_cell_expr_port(f, cell, "A", false);
442  f << stringf(cell->type == "$_AOI4_" ? " & " : " | ");
443  dump_cell_expr_port(f, cell, "B", false);
444  f << stringf(cell->type == "$_AOI4_" ? ") |" : ") &");
445  dump_attributes(f, "", cell->attributes, ' ');
446  f << stringf(" (");
447  dump_cell_expr_port(f, cell, "C", false);
448  f << stringf(cell->type == "$_AOI4_" ? " & " : " | ");
449  dump_cell_expr_port(f, cell, "D", false);
450  f << stringf("));\n");
451  return true;
452  }
453 
454  if (cell->type.substr(0, 6) == "$_DFF_")
455  {
456  std::string reg_name = cellname(cell);
457  bool out_is_reg_wire = is_reg_wire(cell->getPort("\\Q"), reg_name);
458 
459  if (!out_is_reg_wire)
460  f << stringf("%s" "reg %s;\n", indent.c_str(), reg_name.c_str());
461 
462  dump_attributes(f, indent, cell->attributes);
463  f << stringf("%s" "always @(%sedge ", indent.c_str(), cell->type[6] == 'P' ? "pos" : "neg");
464  dump_sigspec(f, cell->getPort("\\C"));
465  if (cell->type[7] != '_') {
466  f << stringf(" or %sedge ", cell->type[7] == 'P' ? "pos" : "neg");
467  dump_sigspec(f, cell->getPort("\\R"));
468  }
469  f << stringf(")\n");
470 
471  if (cell->type[7] != '_') {
472  f << stringf("%s" " if (%s", indent.c_str(), cell->type[7] == 'P' ? "" : "!");
473  dump_sigspec(f, cell->getPort("\\R"));
474  f << stringf(")\n");
475  f << stringf("%s" " %s <= %c;\n", indent.c_str(), reg_name.c_str(), cell->type[8]);
476  f << stringf("%s" " else\n", indent.c_str());
477  }
478 
479  f << stringf("%s" " %s <= ", indent.c_str(), reg_name.c_str());
480  dump_cell_expr_port(f, cell, "D", false);
481  f << stringf(";\n");
482 
483  if (!out_is_reg_wire) {
484  f << stringf("%s" "assign ", indent.c_str());
485  dump_sigspec(f, cell->getPort("\\Q"));
486  f << stringf(" = %s;\n", reg_name.c_str());
487  }
488 
489  return true;
490  }
491 
492  if (cell->type.substr(0, 8) == "$_DFFSR_")
493  {
494  char pol_c = cell->type[8], pol_s = cell->type[9], pol_r = cell->type[10];
495 
496  std::string reg_name = cellname(cell);
497  bool out_is_reg_wire = is_reg_wire(cell->getPort("\\Q"), reg_name);
498 
499  if (!out_is_reg_wire)
500  f << stringf("%s" "reg %s;\n", indent.c_str(), reg_name.c_str());
501 
502  dump_attributes(f, indent, cell->attributes);
503  f << stringf("%s" "always @(%sedge ", indent.c_str(), pol_c == 'P' ? "pos" : "neg");
504  dump_sigspec(f, cell->getPort("\\C"));
505  f << stringf(" or %sedge ", pol_s == 'P' ? "pos" : "neg");
506  dump_sigspec(f, cell->getPort("\\S"));
507  f << stringf(" or %sedge ", pol_r == 'P' ? "pos" : "neg");
508  dump_sigspec(f, cell->getPort("\\R"));
509  f << stringf(")\n");
510 
511  f << stringf("%s" " if (%s", indent.c_str(), pol_r == 'P' ? "" : "!");
512  dump_sigspec(f, cell->getPort("\\R"));
513  f << stringf(")\n");
514  f << stringf("%s" " %s <= 0;\n", indent.c_str(), reg_name.c_str());
515 
516  f << stringf("%s" " else if (%s", indent.c_str(), pol_s == 'P' ? "" : "!");
517  dump_sigspec(f, cell->getPort("\\S"));
518  f << stringf(")\n");
519  f << stringf("%s" " %s <= 1;\n", indent.c_str(), reg_name.c_str());
520 
521  f << stringf("%s" " else\n", indent.c_str());
522  f << stringf("%s" " %s <= ", indent.c_str(), reg_name.c_str());
523  dump_cell_expr_port(f, cell, "D", false);
524  f << stringf(";\n");
525 
526  if (!out_is_reg_wire) {
527  f << stringf("%s" "assign ", indent.c_str());
528  dump_sigspec(f, cell->getPort("\\Q"));
529  f << stringf(" = %s;\n", reg_name.c_str());
530  }
531 
532  return true;
533  }
534 
535 #define HANDLE_UNIOP(_type, _operator) \
536  if (cell->type ==_type) { dump_cell_expr_uniop(f, indent, cell, _operator); return true; }
537 #define HANDLE_BINOP(_type, _operator) \
538  if (cell->type ==_type) { dump_cell_expr_binop(f, indent, cell, _operator); return true; }
539 
540  HANDLE_UNIOP("$not", "~")
541  HANDLE_UNIOP("$pos", "+")
542  HANDLE_UNIOP("$neg", "-")
543 
544  HANDLE_BINOP("$and", "&")
545  HANDLE_BINOP("$or", "|")
546  HANDLE_BINOP("$xor", "^")
547  HANDLE_BINOP("$xnor", "~^")
548 
549  HANDLE_UNIOP("$reduce_and", "&")
550  HANDLE_UNIOP("$reduce_or", "|")
551  HANDLE_UNIOP("$reduce_xor", "^")
552  HANDLE_UNIOP("$reduce_xnor", "~^")
553  HANDLE_UNIOP("$reduce_bool", "|")
554 
555  HANDLE_BINOP("$shl", "<<")
556  HANDLE_BINOP("$shr", ">>")
557  HANDLE_BINOP("$sshl", "<<<")
558  HANDLE_BINOP("$sshr", ">>>")
559 
560  HANDLE_BINOP("$lt", "<")
561  HANDLE_BINOP("$le", "<=")
562  HANDLE_BINOP("$eq", "==")
563  HANDLE_BINOP("$ne", "!=")
564  HANDLE_BINOP("$eqx", "===")
565  HANDLE_BINOP("$nex", "!==")
566  HANDLE_BINOP("$ge", ">=")
567  HANDLE_BINOP("$gt", ">")
568 
569  HANDLE_BINOP("$add", "+")
570  HANDLE_BINOP("$sub", "-")
571  HANDLE_BINOP("$mul", "*")
572  HANDLE_BINOP("$div", "/")
573  HANDLE_BINOP("$mod", "%")
574  HANDLE_BINOP("$pow", "**")
575 
576  HANDLE_UNIOP("$logic_not", "!")
577  HANDLE_BINOP("$logic_and", "&&")
578  HANDLE_BINOP("$logic_or", "||")
579 
580 #undef HANDLE_UNIOP
581 #undef HANDLE_BINOP
582 
583  if (cell->type == "$mux")
584  {
585  f << stringf("%s" "assign ", indent.c_str());
586  dump_sigspec(f, cell->getPort("\\Y"));
587  f << stringf(" = ");
588  dump_sigspec(f, cell->getPort("\\S"));
589  f << stringf(" ? ");
590  dump_attributes(f, "", cell->attributes, ' ');
591  dump_sigspec(f, cell->getPort("\\B"));
592  f << stringf(" : ");
593  dump_sigspec(f, cell->getPort("\\A"));
594  f << stringf(";\n");
595  return true;
596  }
597 
598  if (cell->type == "$pmux" || cell->type == "$pmux_safe")
599  {
600  int width = cell->parameters["\\WIDTH"].as_int();
601  int s_width = cell->getPort("\\S").size();
602  std::string func_name = cellname(cell);
603 
604  f << stringf("%s" "function [%d:0] %s;\n", indent.c_str(), width-1, func_name.c_str());
605  f << stringf("%s" " input [%d:0] a;\n", indent.c_str(), width-1);
606  f << stringf("%s" " input [%d:0] b;\n", indent.c_str(), s_width*width-1);
607  f << stringf("%s" " input [%d:0] s;\n", indent.c_str(), s_width-1);
608 
609  dump_attributes(f, indent + " ", cell->attributes);
610  if (cell->type != "$pmux_safe" && !noattr)
611  f << stringf("%s" " (* parallel_case *)\n", indent.c_str());
612  f << stringf("%s" " casez (s)", indent.c_str());
613  if (cell->type != "$pmux_safe")
614  f << stringf(noattr ? " // synopsys parallel_case\n" : "\n");
615 
616  for (int i = 0; i < s_width; i++)
617  {
618  f << stringf("%s" " %d'b", indent.c_str(), s_width);
619 
620  for (int j = s_width-1; j >= 0; j--)
621  f << stringf("%c", j == i ? '1' : cell->type == "$pmux_safe" ? '0' : '?');
622 
623  f << stringf(":\n");
624  f << stringf("%s" " %s = b[%d:%d];\n", indent.c_str(), func_name.c_str(), (i+1)*width-1, i*width);
625  }
626 
627  f << stringf("%s" " default:\n", indent.c_str());
628  f << stringf("%s" " %s = a;\n", indent.c_str(), func_name.c_str());
629 
630  f << stringf("%s" " endcase\n", indent.c_str());
631  f << stringf("%s" "endfunction\n", indent.c_str());
632 
633  f << stringf("%s" "assign ", indent.c_str());
634  dump_sigspec(f, cell->getPort("\\Y"));
635  f << stringf(" = %s(", func_name.c_str());
636  dump_sigspec(f, cell->getPort("\\A"));
637  f << stringf(", ");
638  dump_sigspec(f, cell->getPort("\\B"));
639  f << stringf(", ");
640  dump_sigspec(f, cell->getPort("\\S"));
641  f << stringf(");\n");
642  return true;
643  }
644 
645  if (cell->type == "$slice")
646  {
647  f << stringf("%s" "assign ", indent.c_str());
648  dump_sigspec(f, cell->getPort("\\Y"));
649  f << stringf(" = ");
650  dump_sigspec(f, cell->getPort("\\A"));
651  f << stringf(" >> %d;\n", cell->parameters.at("\\OFFSET").as_int());
652  return true;
653  }
654 
655  if (cell->type == "$concat")
656  {
657  f << stringf("%s" "assign ", indent.c_str());
658  dump_sigspec(f, cell->getPort("\\Y"));
659  f << stringf(" = { ");
660  dump_sigspec(f, cell->getPort("\\B"));
661  f << stringf(" , ");
662  dump_sigspec(f, cell->getPort("\\A"));
663  f << stringf(" };\n");
664  return true;
665  }
666 
667  if (cell->type == "$dff" || cell->type == "$adff")
668  {
669  RTLIL::SigSpec sig_clk, sig_arst, val_arst;
670  bool pol_clk, pol_arst = false;
671 
672  sig_clk = cell->getPort("\\CLK");
673  pol_clk = cell->parameters["\\CLK_POLARITY"].as_bool();
674 
675  if (cell->type == "$adff") {
676  sig_arst = cell->getPort("\\ARST");
677  pol_arst = cell->parameters["\\ARST_POLARITY"].as_bool();
678  val_arst = RTLIL::SigSpec(cell->parameters["\\ARST_VALUE"]);
679  }
680 
681  std::string reg_name = cellname(cell);
682  bool out_is_reg_wire = is_reg_wire(cell->getPort("\\Q"), reg_name);
683 
684  if (!out_is_reg_wire)
685  f << stringf("%s" "reg [%d:0] %s;\n", indent.c_str(), cell->parameters["\\WIDTH"].as_int()-1, reg_name.c_str());
686 
687  f << stringf("%s" "always @(%sedge ", indent.c_str(), pol_clk ? "pos" : "neg");
688  dump_sigspec(f, sig_clk);
689  if (cell->type == "$adff") {
690  f << stringf(" or %sedge ", pol_arst ? "pos" : "neg");
691  dump_sigspec(f, sig_arst);
692  }
693  f << stringf(")\n");
694 
695  if (cell->type == "$adff") {
696  f << stringf("%s" " if (%s", indent.c_str(), pol_arst ? "" : "!");
697  dump_sigspec(f, sig_arst);
698  f << stringf(")\n");
699  f << stringf("%s" " %s <= ", indent.c_str(), reg_name.c_str());
700  dump_sigspec(f, val_arst);
701  f << stringf(";\n");
702  f << stringf("%s" " else\n", indent.c_str());
703  }
704 
705  f << stringf("%s" " %s <= ", indent.c_str(), reg_name.c_str());
706  dump_cell_expr_port(f, cell, "D", false);
707  f << stringf(";\n");
708 
709  if (!out_is_reg_wire) {
710  f << stringf("%s" "assign ", indent.c_str());
711  dump_sigspec(f, cell->getPort("\\Q"));
712  f << stringf(" = %s;\n", reg_name.c_str());
713  }
714 
715  return true;
716  }
717 
718  // FIXME: $_SR_[PN][PN]_, $_DLATCH_[PN]_, $_DLATCHSR_[PN][PN][PN]_
719  // FIXME: $sr, $dffsr, $dlatch, $memrd, $memwr, $mem, $fsm
720 
721  return false;
722 }
723 
724 void dump_cell(std::ostream &f, std::string indent, RTLIL::Cell *cell)
725 {
726  if (cell->type[0] == '$' && !noexpr) {
727  if (dump_cell_expr(f, indent, cell))
728  return;
729  }
730 
731  dump_attributes(f, indent, cell->attributes);
732  f << stringf("%s" "%s", indent.c_str(), id(cell->type, false).c_str());
733 
734  if (cell->parameters.size() > 0) {
735  f << stringf(" #(");
736  for (auto it = cell->parameters.begin(); it != cell->parameters.end(); it++) {
737  if (it != cell->parameters.begin())
738  f << stringf(",");
739  f << stringf("\n%s .%s(", indent.c_str(), id(it->first).c_str());
740  bool is_signed = (it->second.flags & RTLIL::CONST_FLAG_SIGNED) != 0;
741  dump_const(f, it->second, -1, 0, !is_signed, is_signed);
742  f << stringf(")");
743  }
744  f << stringf("\n%s" ")", indent.c_str());
745  }
746 
747  std::string cell_name = cellname(cell);
748  if (cell_name != id(cell->name))
749  f << stringf(" %s /* %s */ (", cell_name.c_str(), id(cell->name).c_str());
750  else
751  f << stringf(" %s (", cell_name.c_str());
752 
753  bool first_arg = true;
754  std::set<RTLIL::IdString> numbered_ports;
755  for (int i = 1; true; i++) {
756  char str[16];
757  snprintf(str, 16, "$%d", i);
758  for (auto it = cell->connections().begin(); it != cell->connections().end(); it++) {
759  if (it->first != str)
760  continue;
761  if (!first_arg)
762  f << stringf(",");
763  first_arg = false;
764  f << stringf("\n%s ", indent.c_str());
765  dump_sigspec(f, it->second);
766  numbered_ports.insert(it->first);
767  goto found_numbered_port;
768  }
769  break;
770  found_numbered_port:;
771  }
772  for (auto it = cell->connections().begin(); it != cell->connections().end(); it++) {
773  if (numbered_ports.count(it->first))
774  continue;
775  if (!first_arg)
776  f << stringf(",");
777  first_arg = false;
778  f << stringf("\n%s .%s(", indent.c_str(), id(it->first).c_str());
779  if (it->second.size() > 0)
780  dump_sigspec(f, it->second);
781  f << stringf(")");
782  }
783  f << stringf("\n%s" ");\n", indent.c_str());
784 }
785 
786 void dump_conn(std::ostream &f, std::string indent, const RTLIL::SigSpec &left, const RTLIL::SigSpec &right)
787 {
788  f << stringf("%s" "assign ", indent.c_str());
789  dump_sigspec(f, left);
790  f << stringf(" = ");
791  dump_sigspec(f, right);
792  f << stringf(";\n");
793 }
794 
795 void dump_proc_switch(std::ostream &f, std::string indent, RTLIL::SwitchRule *sw);
796 
797 void dump_case_body(std::ostream &f, std::string indent, RTLIL::CaseRule *cs, bool omit_trailing_begin = false)
798 {
799  int number_of_stmts = cs->switches.size() + cs->actions.size();
800 
801  if (!omit_trailing_begin && number_of_stmts >= 2)
802  f << stringf("%s" "begin\n", indent.c_str());
803 
804  for (auto it = cs->actions.begin(); it != cs->actions.end(); it++) {
805  if (it->first.size() == 0)
806  continue;
807  f << stringf("%s ", indent.c_str());
808  dump_sigspec(f, it->first);
809  f << stringf(" = ");
810  dump_sigspec(f, it->second);
811  f << stringf(";\n");
812  }
813 
814  for (auto it = cs->switches.begin(); it != cs->switches.end(); it++)
815  dump_proc_switch(f, indent + " ", *it);
816 
817  if (!omit_trailing_begin && number_of_stmts == 0)
818  f << stringf("%s /* empty */;\n", indent.c_str());
819 
820  if (omit_trailing_begin || number_of_stmts >= 2)
821  f << stringf("%s" "end\n", indent.c_str());
822 }
823 
824 void dump_proc_switch(std::ostream &f, std::string indent, RTLIL::SwitchRule *sw)
825 {
826  if (sw->signal.size() == 0) {
827  f << stringf("%s" "begin\n", indent.c_str());
828  for (auto it = sw->cases.begin(); it != sw->cases.end(); it++) {
829  if ((*it)->compare.size() == 0)
830  dump_case_body(f, indent + " ", *it);
831  }
832  f << stringf("%s" "end\n", indent.c_str());
833  return;
834  }
835 
836  f << stringf("%s" "casez (", indent.c_str());
837  dump_sigspec(f, sw->signal);
838  f << stringf(")\n");
839 
840  for (auto it = sw->cases.begin(); it != sw->cases.end(); it++) {
841  f << stringf("%s ", indent.c_str());
842  if ((*it)->compare.size() == 0)
843  f << stringf("default");
844  else {
845  for (size_t i = 0; i < (*it)->compare.size(); i++) {
846  if (i > 0)
847  f << stringf(", ");
848  dump_sigspec(f, (*it)->compare[i]);
849  }
850  }
851  f << stringf(":\n");
852  dump_case_body(f, indent + " ", *it);
853  }
854 
855  f << stringf("%s" "endcase\n", indent.c_str());
856 }
857 
859 {
860  for (auto it = cs->switches.begin(); it != cs->switches.end(); it++)
861  for (auto it2 = (*it)->cases.begin(); it2 != (*it)->cases.end(); it2++)
862  case_body_find_regs(*it2);
863 
864  for (auto it = cs->actions.begin(); it != cs->actions.end(); it++) {
865  for (auto &c : it->first.chunks())
866  if (c.wire != NULL)
867  reg_wires.insert(c.wire->name);
868  }
869 }
870 
871 void dump_process(std::ostream &f, std::string indent, RTLIL::Process *proc, bool find_regs = false)
872 {
873  if (find_regs) {
875  for (auto it = proc->syncs.begin(); it != proc->syncs.end(); it++)
876  for (auto it2 = (*it)->actions.begin(); it2 != (*it)->actions.end(); it2++) {
877  for (auto &c : it2->first.chunks())
878  if (c.wire != NULL)
879  reg_wires.insert(c.wire->name);
880  }
881  return;
882  }
883 
884  f << stringf("%s" "always @* begin\n", indent.c_str());
885  dump_case_body(f, indent, &proc->root_case, true);
886 
887  std::string backup_indent = indent;
888 
889  for (size_t i = 0; i < proc->syncs.size(); i++)
890  {
891  RTLIL::SyncRule *sync = proc->syncs[i];
892  indent = backup_indent;
893 
894  if (sync->type == RTLIL::STa) {
895  f << stringf("%s" "always @* begin\n", indent.c_str());
896  } else {
897  f << stringf("%s" "always @(", indent.c_str());
898  if (sync->type == RTLIL::STp || sync->type == RTLIL::ST1)
899  f << stringf("posedge ");
900  if (sync->type == RTLIL::STn || sync->type == RTLIL::ST0)
901  f << stringf("negedge ");
902  dump_sigspec(f, sync->signal);
903  f << stringf(") begin\n");
904  }
905  std::string ends = indent + "end\n";
906  indent += " ";
907 
908  if (sync->type == RTLIL::ST0 || sync->type == RTLIL::ST1) {
909  f << stringf("%s" "if (%s", indent.c_str(), sync->type == RTLIL::ST0 ? "!" : "");
910  dump_sigspec(f, sync->signal);
911  f << stringf(") begin\n");
912  ends = indent + "end\n" + ends;
913  indent += " ";
914  }
915 
916  if (sync->type == RTLIL::STp || sync->type == RTLIL::STn) {
917  for (size_t j = 0; j < proc->syncs.size(); j++) {
918  RTLIL::SyncRule *sync2 = proc->syncs[j];
919  if (sync2->type == RTLIL::ST0 || sync2->type == RTLIL::ST1) {
920  f << stringf("%s" "if (%s", indent.c_str(), sync2->type == RTLIL::ST1 ? "!" : "");
921  dump_sigspec(f, sync2->signal);
922  f << stringf(") begin\n");
923  ends = indent + "end\n" + ends;
924  indent += " ";
925  }
926  }
927  }
928 
929  for (auto it = sync->actions.begin(); it != sync->actions.end(); it++) {
930  if (it->first.size() == 0)
931  continue;
932  f << stringf("%s ", indent.c_str());
933  dump_sigspec(f, it->first);
934  f << stringf(" <= ");
935  dump_sigspec(f, it->second);
936  f << stringf(";\n");
937  }
938 
939  f << stringf("%s", ends.c_str());
940  }
941 }
942 
943 void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module)
944 {
945  reg_wires.clear();
946  reset_auto_counter(module);
947  active_module = module;
948 
949  f << stringf("\n");
950  for (auto it = module->processes.begin(); it != module->processes.end(); it++)
951  dump_process(f, indent + " ", it->second, true);
952 
953  if (!noexpr)
954  {
955  std::set<std::pair<RTLIL::Wire*,int>> reg_bits;
956  for (auto &it : module->cells_)
957  {
958  RTLIL::Cell *cell = it.second;
959  if (!reg_ct.count(cell->type) || !cell->hasPort("\\Q"))
960  continue;
961 
962  RTLIL::SigSpec sig = cell->getPort("\\Q");
963 
964  if (sig.is_chunk()) {
965  RTLIL::SigChunk chunk = sig.as_chunk();
966  if (chunk.wire != NULL)
967  for (int i = 0; i < chunk.width; i++)
968  reg_bits.insert(std::pair<RTLIL::Wire*,int>(chunk.wire, chunk.offset+i));
969  }
970  }
971  for (auto &it : module->wires_)
972  {
973  RTLIL::Wire *wire = it.second;
974  for (int i = 0; i < wire->width; i++)
975  if (reg_bits.count(std::pair<RTLIL::Wire*,int>(wire, i)) == 0)
976  goto this_wire_aint_reg;
977  if (wire->width)
978  reg_wires.insert(wire->name);
979  this_wire_aint_reg:;
980  }
981  }
982 
983  dump_attributes(f, indent, module->attributes);
984  f << stringf("%s" "module %s(", indent.c_str(), id(module->name, false).c_str());
985  bool keep_running = true;
986  for (int port_id = 1; keep_running; port_id++) {
987  keep_running = false;
988  for (auto it = module->wires_.begin(); it != module->wires_.end(); it++) {
989  RTLIL::Wire *wire = it->second;
990  if (wire->port_id == port_id) {
991  if (port_id != 1)
992  f << stringf(", ");
993  f << stringf("%s", id(wire->name).c_str());
994  keep_running = true;
995  continue;
996  }
997  }
998  }
999  f << stringf(");\n");
1000 
1001  for (auto it = module->wires_.begin(); it != module->wires_.end(); it++)
1002  dump_wire(f, indent + " ", it->second);
1003 
1004  for (auto it = module->memories.begin(); it != module->memories.end(); it++)
1005  dump_memory(f, indent + " ", it->second);
1006 
1007  for (auto it = module->cells_.begin(); it != module->cells_.end(); it++)
1008  dump_cell(f, indent + " ", it->second);
1009 
1010  for (auto it = module->processes.begin(); it != module->processes.end(); it++)
1011  dump_process(f, indent + " ", it->second);
1012 
1013  for (auto it = module->connections().begin(); it != module->connections().end(); it++)
1014  dump_conn(f, indent + " ", it->first, it->second);
1015 
1016  f << stringf("%s" "endmodule\n", indent.c_str());
1017  active_module = NULL;
1018 }
1019 
1020 struct VerilogBackend : public Backend {
1021  VerilogBackend() : Backend("verilog", "write design to verilog file") { }
1022  virtual void help()
1023  {
1024  // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
1025  log("\n");
1026  log(" write_verilog [options] [filename]\n");
1027  log("\n");
1028  log("Write the current design to a verilog file.\n");
1029  log("\n");
1030  log(" -norename\n");
1031  log(" without this option all internal object names (the ones with a dollar\n");
1032  log(" instead of a backslash prefix) are changed to short names in the\n");
1033  log(" format '_<number>_'.\n");
1034  log("\n");
1035  log(" -noattr\n");
1036  log(" with this option no attributes are included in the output\n");
1037  log("\n");
1038  log(" -attr2comment\n");
1039  log(" with this option attributes are included as comments in the output\n");
1040  log("\n");
1041  log(" -noexpr\n");
1042  log(" without this option all internal cells are converted to verilog\n");
1043  log(" expressions.\n");
1044  log("\n");
1045  log(" -blackboxes\n");
1046  log(" usually modules with the 'blackbox' attribute are ignored. with\n");
1047  log(" this option set only the modules with the 'blackbox' attribute\n");
1048  log(" are written to the output file.\n");
1049  log("\n");
1050  log(" -selected\n");
1051  log(" only write selected modules. modules must be selected entirely or\n");
1052  log(" not at all.\n");
1053  log("\n");
1054  }
1055  virtual void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design)
1056  {
1057  log_header("Executing Verilog backend.\n");
1058 
1059  norename = false;
1060  noattr = false;
1061  attr2comment = false;
1062  noexpr = false;
1063 
1064  bool blackboxes = false;
1065  bool selected = false;
1066 
1067  reg_ct.clear();
1068 
1069  reg_ct.insert("$dff");
1070  reg_ct.insert("$adff");
1071 
1072  reg_ct.insert("$_DFF_N_");
1073  reg_ct.insert("$_DFF_P_");
1074 
1075  reg_ct.insert("$_DFF_NN0_");
1076  reg_ct.insert("$_DFF_NN1_");
1077  reg_ct.insert("$_DFF_NP0_");
1078  reg_ct.insert("$_DFF_NP1_");
1079  reg_ct.insert("$_DFF_PN0_");
1080  reg_ct.insert("$_DFF_PN1_");
1081  reg_ct.insert("$_DFF_PP0_");
1082  reg_ct.insert("$_DFF_PP1_");
1083 
1084  reg_ct.insert("$_DFFSR_NNN_");
1085  reg_ct.insert("$_DFFSR_NNP_");
1086  reg_ct.insert("$_DFFSR_NPN_");
1087  reg_ct.insert("$_DFFSR_NPP_");
1088  reg_ct.insert("$_DFFSR_PNN_");
1089  reg_ct.insert("$_DFFSR_PNP_");
1090  reg_ct.insert("$_DFFSR_PPN_");
1091  reg_ct.insert("$_DFFSR_PPP_");
1092 
1093  size_t argidx;
1094  for (argidx = 1; argidx < args.size(); argidx++) {
1095  std::string arg = args[argidx];
1096  if (arg == "-norename") {
1097  norename = true;
1098  continue;
1099  }
1100  if (arg == "-noattr") {
1101  noattr = true;
1102  continue;
1103  }
1104  if (arg == "-attr2comment") {
1105  attr2comment = true;
1106  continue;
1107  }
1108  if (arg == "-noexpr") {
1109  noexpr = true;
1110  continue;
1111  }
1112  if (arg == "-blackboxes") {
1113  blackboxes = true;
1114  continue;
1115  }
1116  if (arg == "-selected") {
1117  selected = true;
1118  continue;
1119  }
1120  break;
1121  }
1122  extra_args(f, filename, args, argidx);
1123 
1124  *f << stringf("/* Generated by %s */\n", yosys_version_str);
1125  for (auto it = design->modules_.begin(); it != design->modules_.end(); it++) {
1126  if (it->second->get_bool_attribute("\\blackbox") != blackboxes)
1127  continue;
1128  if (selected && !design->selected_whole_module(it->first)) {
1129  if (design->selected_module(it->first))
1130  log_cmd_error("Can't handle partially selected module %s!\n", RTLIL::id2cstr(it->first));
1131  continue;
1132  }
1133  log("Dumping module `%s'.\n", it->first.c_str());
1134  dump_module(*f, "", it->second);
1135  }
1136 
1137  reg_ct.clear();
1138  }
1139 } VerilogBackend;
1140 
const char * yosys_version_str
const char * c_str() const
Definition: rtlil.h:178
std::string str() const
Definition: rtlil.h:182
std::string stringf(const char *fmt,...)
Definition: yosys.cc:58
std::set< RTLIL::IdString > reg_wires
int auto_name_offset
int auto_name_counter
void dump_wire(std::ostream &f, std::string indent, RTLIL::Wire *wire)
bool selected_module(RTLIL::IdString mod_name) const
Definition: rtlil.cc:379
bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
int flags
Definition: rtlil.h:437
virtual void execute(std::ostream *&f, std::string filename, std::vector< std::string > args, RTLIL::Design *design)
void log_header(const char *format,...)
Definition: log.cc:188
const std::vector< RTLIL::SigSig > & connections() const
Definition: rtlil.cc:1307
RTLIL::SyncType type
Definition: rtlil.h:1144
std::map< RTLIL::IdString, RTLIL::Wire * > wires_
Definition: rtlil.h:595
RTLIL_ATTRIBUTE_MEMBERS std::vector< RTLIL::CaseRule * > cases
Definition: rtlil.h:1134
RTLIL::IdString name
Definition: rtlil.h:853
bool upto
Definition: rtlil.h:827
virtual void help()
bool port_input
Definition: rtlil.h:827
int width
Definition: rtlil.h:826
std::map< RTLIL::IdString, RTLIL::Memory * > memories
Definition: rtlil.h:601
void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module)
bool is_reg_wire(RTLIL::SigSpec sig, std::string &reg_name)
void log_error(const char *format,...)
Definition: log.cc:204
RTLIL::Module * module
Definition: abc.cc:94
std::string cellname(RTLIL::Cell *cell)
int port_id
Definition: rtlil.h:826
RTLIL::IdString type
Definition: rtlil.h:854
void dump_conn(std::ostream &f, std::string indent, const RTLIL::SigSpec &left, const RTLIL::SigSpec &right)
std::map< RTLIL::IdString, RTLIL::Const > parameters
Definition: rtlil.h:856
RTLIL::SigSpec signal
Definition: rtlil.h:1145
int size
Definition: rtlil.h:836
int size() const
Definition: rtlil.h:1019
bool in(T first, Args...rest)
Definition: rtlil.h:241
void dump_sigspec(std::ostream &f, const RTLIL::SigSpec &sig)
void dump_cell_expr_uniop(std::ostream &f, std::string indent, RTLIL::Cell *cell, std::string op)
void dump_sigchunk(std::ostream &f, const RTLIL::SigChunk &chunk, bool no_decimal=false)
bool port_output
Definition: rtlil.h:827
void dump_process(std::ostream &f, std::string indent, RTLIL::Process *proc, bool find_regs=false)
RTLIL::Wire * wire
Definition: rtlil.h:885
void extra_args(std::ostream *&f, std::string &filename, std::vector< std::string > args, size_t argidx)
Definition: register.cc:439
bool is_chunk() const
Definition: rtlil.cc:2755
RTLIL::SigSpec signal
Definition: rtlil.h:1132
#define PRIVATE_NAMESPACE_BEGIN
Definition: yosys.h:97
RTLIL_ATTRIBUTE_MEMBERS bool hasPort(RTLIL::IdString portname) const
Definition: rtlil.cc:1766
const RTLIL::SigSpec & getPort(RTLIL::IdString portname) const
Definition: rtlil.cc:1809
void reset_auto_counter(RTLIL::Module *module)
int GetSize(RTLIL::Wire *wire)
Definition: yosys.cc:334
void dump_cell(std::ostream &f, std::string indent, RTLIL::Cell *cell)
#define HANDLE_BINOP(_type, _operator)
RTLIL::IdString name
Definition: rtlil.h:835
std::string decode_string() const
Definition: rtlil.cc:131
#define log_assert(_assert_expr_)
Definition: log.h:85
bool is_fully_const() const
Definition: rtlil.cc:2763
void dump_proc_switch(std::ostream &f, std::string indent, RTLIL::SwitchRule *sw)
RTLIL::IdString name
Definition: rtlil.h:599
RTLIL::SigChunk as_chunk() const
Definition: rtlil.cc:2877
bool selected_whole_module(RTLIL::IdString mod_name) const
Definition: rtlil.cc:388
void dump_const(std::ostream &f, const RTLIL::Const &data, int width=-1, int offset=0, bool no_decimal=false, bool set_signed=false)
USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN bool attr2comment
#define PRIVATE_NAMESPACE_END
Definition: yosys.h:98
VerilogBackend VerilogBackend
RTLIL::IdString name
Definition: rtlil.h:825
std::vector< RTLIL::SigSig > actions
Definition: rtlil.h:1146
static const char * id2cstr(const RTLIL::IdString &str)
Definition: rtlil.h:267
void log_cmd_error(const char *format,...)
Definition: log.cc:211
int auto_name_digits
std::map< RTLIL::IdString, RTLIL::Process * > processes
Definition: rtlil.h:602
void case_body_find_regs(RTLIL::CaseRule *cs)
std::string substr(size_t pos=0, size_t len=std::string::npos) const
Definition: rtlil.h:208
#define USING_YOSYS_NAMESPACE
Definition: yosys.h:102
virtual size_t count_id(RTLIL::IdString id)
Definition: rtlil.cc:472
std::map< RTLIL::IdString, RTLIL::Module * > modules_
Definition: rtlil.h:507
std::map< RTLIL::IdString, int > auto_name_map
#define NULL
std::map< RTLIL::IdString, RTLIL::Cell * > cells_
Definition: rtlil.h:596
void dump_cell_expr_port(std::ostream &f, RTLIL::Cell *cell, std::string port, bool gen_signed=true)
std::set< RTLIL::IdString > reg_ct
void log(const char *format,...)
Definition: log.cc:180
std::vector< RTLIL::SyncRule * > syncs
Definition: rtlil.h:1157
#define HANDLE_UNIOP(_type, _operator)
USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN bool norename
RTLIL::Module * active_module
void reset_auto_counter_id(RTLIL::IdString id, bool may_rename)
std::vector< RTLIL::State > bits
Definition: rtlil.h:438
int start_offset
Definition: rtlil.h:826
int width
Definition: rtlil.h:836
std::vector< RTLIL::SigSig > actions
Definition: rtlil.h:1120
void dump_memory(std::ostream &f, std::string indent, RTLIL::Memory *memory)
USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN bool noexpr
std::string id(RTLIL::IdString internal_id, bool may_rename=true)
void dump_attributes(std::ostream &f, std::string indent, std::map< RTLIL::IdString, RTLIL::Const > &attributes, char term= '\n')
std::vector< RTLIL::SwitchRule * > switches
Definition: rtlil.h:1121
void dump_cell_expr_binop(std::ostream &f, std::string indent, RTLIL::Cell *cell, std::string op)
const std::map< RTLIL::IdString, RTLIL::SigSpec > & connections() const
Definition: rtlil.cc:1814
std::vector< RTLIL::State > data
Definition: rtlil.h:886
void dump_case_body(std::ostream &f, std::string indent, RTLIL::CaseRule *cs, bool omit_trailing_begin=false)
USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN bool noattr
const std::vector< RTLIL::SigChunk > & chunks() const
Definition: rtlil.h:1016
RTLIL_ATTRIBUTE_MEMBERS RTLIL::CaseRule root_case
Definition: rtlil.h:1156