yosys-master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
genrtlil.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  * This is the AST frontend library.
21  *
22  * The AST frontend library is not a frontend on it's own but provides a
23  * generic abstract syntax tree (AST) abstraction for HDL code and can be
24  * used by HDL frontends. See "ast.h" for an overview of the API and the
25  * Verilog frontend for an usage example.
26  *
27  */
28 
29 #include "kernel/log.h"
30 #include "kernel/utils.h"
31 #include "libs/sha1/sha1.h"
32 #include "ast.h"
33 
34 #include <sstream>
35 #include <stdarg.h>
36 #include <algorithm>
37 
39 
40 using namespace AST;
41 using namespace AST_INTERNAL;
42 
43 // helper function for creating RTLIL code for unary operations
44 static RTLIL::SigSpec uniop2rtlil(AstNode *that, std::string type, int result_width, const RTLIL::SigSpec &arg, bool gen_attributes = true)
45 {
46  std::stringstream sstr;
47  sstr << type << "$" << that->filename << ":" << that->linenum << "$" << (autoidx++);
48 
49  RTLIL::Cell *cell = current_module->addCell(sstr.str(), type);
50  cell->attributes["\\src"] = stringf("%s:%d", that->filename.c_str(), that->linenum);
51 
52  RTLIL::Wire *wire = current_module->addWire(cell->name.str() + "_Y", result_width);
53  wire->attributes["\\src"] = stringf("%s:%d", that->filename.c_str(), that->linenum);
54 
55  if (gen_attributes)
56  for (auto &attr : that->attributes) {
57  if (attr.second->type != AST_CONSTANT)
58  log_error("Attribute `%s' with non-constant value at %s:%d!\n",
59  attr.first.c_str(), that->filename.c_str(), that->linenum);
60  cell->attributes[attr.first] = attr.second->asAttrConst();
61  }
62 
63  cell->parameters["\\A_SIGNED"] = RTLIL::Const(that->children[0]->is_signed);
64  cell->parameters["\\A_WIDTH"] = RTLIL::Const(arg.size());
65  cell->setPort("\\A", arg);
66 
67  cell->parameters["\\Y_WIDTH"] = result_width;
68  cell->setPort("\\Y", wire);
69  return wire;
70 }
71 
72 // helper function for extending bit width (preferred over SigSpec::extend() because of correct undef propagation in ConstEval)
73 static void widthExtend(AstNode *that, RTLIL::SigSpec &sig, int width, bool is_signed)
74 {
75  if (width <= sig.size()) {
76  sig.extend(width, is_signed);
77  return;
78  }
79 
80  std::stringstream sstr;
81  sstr << "$extend" << "$" << that->filename << ":" << that->linenum << "$" << (autoidx++);
82 
83  RTLIL::Cell *cell = current_module->addCell(sstr.str(), "$pos");
84  cell->attributes["\\src"] = stringf("%s:%d", that->filename.c_str(), that->linenum);
85 
86  RTLIL::Wire *wire = current_module->addWire(cell->name.str() + "_Y", width);
87  wire->attributes["\\src"] = stringf("%s:%d", that->filename.c_str(), that->linenum);
88 
89  if (that != NULL)
90  for (auto &attr : that->attributes) {
91  if (attr.second->type != AST_CONSTANT)
92  log_error("Attribute `%s' with non-constant value at %s:%d!\n",
93  attr.first.c_str(), that->filename.c_str(), that->linenum);
94  cell->attributes[attr.first] = attr.second->asAttrConst();
95  }
96 
97  cell->parameters["\\A_SIGNED"] = RTLIL::Const(is_signed);
98  cell->parameters["\\A_WIDTH"] = RTLIL::Const(sig.size());
99  cell->setPort("\\A", sig);
100 
101  cell->parameters["\\Y_WIDTH"] = width;
102  cell->setPort("\\Y", wire);
103  sig = wire;
104 }
105 
106 // helper function for creating RTLIL code for binary operations
107 static RTLIL::SigSpec binop2rtlil(AstNode *that, std::string type, int result_width, const RTLIL::SigSpec &left, const RTLIL::SigSpec &right)
108 {
109  std::stringstream sstr;
110  sstr << type << "$" << that->filename << ":" << that->linenum << "$" << (autoidx++);
111 
112  RTLIL::Cell *cell = current_module->addCell(sstr.str(), type);
113  cell->attributes["\\src"] = stringf("%s:%d", that->filename.c_str(), that->linenum);
114 
115  RTLIL::Wire *wire = current_module->addWire(cell->name.str() + "_Y", result_width);
116  wire->attributes["\\src"] = stringf("%s:%d", that->filename.c_str(), that->linenum);
117 
118  for (auto &attr : that->attributes) {
119  if (attr.second->type != AST_CONSTANT)
120  log_error("Attribute `%s' with non-constant value at %s:%d!\n",
121  attr.first.c_str(), that->filename.c_str(), that->linenum);
122  cell->attributes[attr.first] = attr.second->asAttrConst();
123  }
124 
125  cell->parameters["\\A_SIGNED"] = RTLIL::Const(that->children[0]->is_signed);
126  cell->parameters["\\B_SIGNED"] = RTLIL::Const(that->children[1]->is_signed);
127 
128  cell->parameters["\\A_WIDTH"] = RTLIL::Const(left.size());
129  cell->parameters["\\B_WIDTH"] = RTLIL::Const(right.size());
130 
131  cell->setPort("\\A", left);
132  cell->setPort("\\B", right);
133 
134  cell->parameters["\\Y_WIDTH"] = result_width;
135  cell->setPort("\\Y", wire);
136  return wire;
137 }
138 
139 // helper function for creating RTLIL code for multiplexers
140 static RTLIL::SigSpec mux2rtlil(AstNode *that, const RTLIL::SigSpec &cond, const RTLIL::SigSpec &left, const RTLIL::SigSpec &right)
141 {
142  log_assert(cond.size() == 1);
143 
144  std::stringstream sstr;
145  sstr << "$ternary$" << that->filename << ":" << that->linenum << "$" << (autoidx++);
146 
147  RTLIL::Cell *cell = current_module->addCell(sstr.str(), "$mux");
148  cell->attributes["\\src"] = stringf("%s:%d", that->filename.c_str(), that->linenum);
149 
150  RTLIL::Wire *wire = current_module->addWire(cell->name.str() + "_Y", left.size());
151  wire->attributes["\\src"] = stringf("%s:%d", that->filename.c_str(), that->linenum);
152 
153  for (auto &attr : that->attributes) {
154  if (attr.second->type != AST_CONSTANT)
155  log_error("Attribute `%s' with non-constant value at %s:%d!\n",
156  attr.first.c_str(), that->filename.c_str(), that->linenum);
157  cell->attributes[attr.first] = attr.second->asAttrConst();
158  }
159 
160  cell->parameters["\\WIDTH"] = RTLIL::Const(left.size());
161 
162  cell->setPort("\\A", right);
163  cell->setPort("\\B", left);
164  cell->setPort("\\S", cond);
165  cell->setPort("\\Y", wire);
166 
167  return wire;
168 }
169 
170 // helper class for converting AST always nodes to RTLIL processes
172 {
173  // input and output structures
178 
179  // This always points to the RTLIL::CaseRule beeing filled at the moment
181 
182  // This map contains the replacement pattern to be used in the right hand side
183  // of an assignment. E.g. in the code "foo = bar; foo = func(foo);" the foo in the right
184  // hand side of the 2nd assignment needs to be replace with the temporary signal holding
185  // the value assigned in the first assignment. So when the first assignement is processed
186  // the according information is appended to subst_rvalue_from and subst_rvalue_to.
188 
189  // This map contains the replacement pattern to be used in the left hand side
190  // of an assignment. E.g. in the code "always @(posedge clk) foo <= bar" the signal bar
191  // should not be connected to the signal foo. Instead it must be connected to the temporary
192  // signal that is used as input for the register that drives the signal foo.
194 
195  // The code here generates a number of temprorary signal for each output register. This
196  // map helps generating nice numbered names for all this temporary signals.
197  std::map<RTLIL::Wire*, int> new_temp_count;
198 
199  // Buffer for generating the init action
201 
202  ProcessGenerator(AstNode *always, RTLIL::SigSpec initSyncSignalsArg = RTLIL::SigSpec()) : always(always), initSyncSignals(initSyncSignalsArg)
203  {
204  // generate process and simple root case
205  proc = new RTLIL::Process;
206  proc->attributes["\\src"] = stringf("%s:%d", always->filename.c_str(), always->linenum);
207  proc->name = stringf("$proc$%s:%d$%d", always->filename.c_str(), always->linenum, autoidx++);
208  for (auto &attr : always->attributes) {
209  if (attr.second->type != AST_CONSTANT)
210  log_error("Attribute `%s' with non-constant value at %s:%d!\n",
211  attr.first.c_str(), always->filename.c_str(), always->linenum);
212  proc->attributes[attr.first] = attr.second->asAttrConst();
213  }
214  current_module->processes[proc->name] = proc;
215  current_case = &proc->root_case;
216 
217  // create initial temporary signal for all output registers
218  RTLIL::SigSpec subst_lvalue_from, subst_lvalue_to;
219  collect_lvalues(subst_lvalue_from, always, true, true);
220  subst_lvalue_to = new_temp_signal(subst_lvalue_from);
221  subst_lvalue_map = subst_lvalue_from.to_sigbit_map(subst_lvalue_to);
222 
223  bool found_anyedge_syncs = false;
224  for (auto child : always->children)
225  if (child->type == AST_EDGE)
226  found_anyedge_syncs = true;
227 
228  if (found_anyedge_syncs) {
229  log("Note: Assuming pure combinatorial block at %s:%d in\n", always->filename.c_str(), always->linenum);
230  log("compliance with IEC 62142(E):2005 / IEEE Std. 1364.1(E):2002. Recommending\n");
231  log("use of @* instead of @(...) for better match of synthesis and simulation.\n");
232  }
233 
234  // create syncs for the process
235  bool found_clocked_sync = false;
236  for (auto child : always->children)
237  if (child->type == AST_POSEDGE || child->type == AST_NEGEDGE) {
238  found_clocked_sync = true;
239  if (found_anyedge_syncs)
240  log_error("Found non-synthesizable event list at %s:%d!\n", always->filename.c_str(), always->linenum);
241  RTLIL::SyncRule *syncrule = new RTLIL::SyncRule;
242  syncrule->type = child->type == AST_POSEDGE ? RTLIL::STp : RTLIL::STn;
243  syncrule->signal = child->children[0]->genRTLIL();
244  addChunkActions(syncrule->actions, subst_lvalue_from, subst_lvalue_to, true);
245  proc->syncs.push_back(syncrule);
246  }
247  if (proc->syncs.empty()) {
248  RTLIL::SyncRule *syncrule = new RTLIL::SyncRule;
249  syncrule->type = RTLIL::STa;
250  syncrule->signal = RTLIL::SigSpec();
251  addChunkActions(syncrule->actions, subst_lvalue_from, subst_lvalue_to, true);
252  proc->syncs.push_back(syncrule);
253  }
254 
255  // create initial assignments for the temporary signals
256  if ((flag_nolatches || always->get_bool_attribute("\\nolatches") || current_module->get_bool_attribute("\\nolatches")) && !found_clocked_sync) {
257  subst_rvalue_map = subst_lvalue_from.to_sigbit_map(RTLIL::SigSpec(RTLIL::State::Sx, GetSize(subst_lvalue_from)));
258  } else {
259  addChunkActions(current_case->actions, subst_lvalue_to, subst_lvalue_from);
260  }
261 
262  // process the AST
263  for (auto child : always->children)
264  if (child->type == AST_BLOCK)
265  processAst(child);
266 
267  if (initSyncSignals.size() > 0)
268  {
269  RTLIL::SyncRule *sync = new RTLIL::SyncRule;
270  sync->type = RTLIL::SyncType::STi;
271  proc->syncs.push_back(sync);
272 
273  log_assert(init_lvalue.size() == init_rvalue.size());
274 
275  int offset = 0;
276  for (auto &init_lvalue_c : init_lvalue.chunks()) {
277  RTLIL::SigSpec lhs = init_lvalue_c;
278  RTLIL::SigSpec rhs = init_rvalue.extract(offset, init_lvalue_c.width);
279  remove_unwanted_lvalue_bits(lhs, rhs);
280  sync->actions.push_back(RTLIL::SigSig(lhs, rhs));
281  offset += lhs.size();
282  }
283  }
284 
285  outputSignals = RTLIL::SigSpec(subst_lvalue_from);
286  }
287 
289  {
290  RTLIL::SigSpec new_lhs, new_rhs;
291 
292  log_assert(GetSize(lhs) == GetSize(rhs));
293  for (int i = 0; i < GetSize(lhs); i++) {
294  if (lhs[i].wire == nullptr)
295  continue;
296  new_lhs.append(lhs[i]);
297  new_rhs.append(rhs[i]);
298  }
299 
300  lhs = new_lhs;
301  rhs = new_rhs;
302  }
303 
304  // create new temporary signals
306  {
307  std::vector<RTLIL::SigChunk> chunks = sig.chunks();
308 
309  for (int i = 0; i < GetSize(chunks); i++)
310  {
311  RTLIL::SigChunk &chunk = chunks[i];
312  if (chunk.wire == NULL)
313  continue;
314 
315  std::string wire_name;
316  do {
317  wire_name = stringf("$%d%s[%d:%d]", new_temp_count[chunk.wire]++,
318  chunk.wire->name.c_str(), chunk.width+chunk.offset-1, chunk.offset);;
319  if (chunk.wire->name.str().find('$') != std::string::npos)
320  wire_name += stringf("$%d", autoidx++);
321  } while (current_module->wires_.count(wire_name) > 0);
322 
323  RTLIL::Wire *wire = current_module->addWire(wire_name, chunk.width);
324  wire->attributes["\\src"] = stringf("%s:%d", always->filename.c_str(), always->linenum);
325 
326  chunk.wire = wire;
327  chunk.offset = 0;
328  }
329 
330  return chunks;
331  }
332 
333  // recursively traverse the AST an collect all assigned signals
334  void collect_lvalues(RTLIL::SigSpec &reg, AstNode *ast, bool type_eq, bool type_le, bool run_sort_and_unify = true)
335  {
336  switch (ast->type)
337  {
338  case AST_CASE:
339  for (auto child : ast->children)
340  if (child != ast->children[0]) {
341  log_assert(child->type == AST_COND);
342  collect_lvalues(reg, child, type_eq, type_le, false);
343  }
344  break;
345 
346  case AST_COND:
347  case AST_ALWAYS:
348  case AST_INITIAL:
349  for (auto child : ast->children)
350  if (child->type == AST_BLOCK)
351  collect_lvalues(reg, child, type_eq, type_le, false);
352  break;
353 
354  case AST_BLOCK:
355  for (auto child : ast->children) {
356  if (child->type == AST_ASSIGN_EQ && type_eq)
357  reg.append(child->children[0]->genRTLIL());
358  if (child->type == AST_ASSIGN_LE && type_le)
359  reg.append(child->children[0]->genRTLIL());
360  if (child->type == AST_CASE || child->type == AST_BLOCK)
361  collect_lvalues(reg, child, type_eq, type_le, false);
362  }
363  break;
364 
365  default:
366  log_abort();
367  }
368 
369  if (run_sort_and_unify) {
370  std::set<RTLIL::SigBit> sorted_reg;
371  for (auto bit : reg)
372  if (bit.wire)
373  sorted_reg.insert(bit);
374  reg = RTLIL::SigSpec(sorted_reg);
375  }
376  }
377 
378  // remove all assignments to the given signal pattern in a case and all its children.
379  // e.g. when the last statement in the code "a = 23; if (b) a = 42; a = 0;" is processed this
380  // function is called to clean up the first two assignments as they are overwritten by
381  // the third assignment.
382  void removeSignalFromCaseTree(const std::set<RTLIL::SigBit> &pattern, RTLIL::CaseRule *cs)
383  {
384  for (auto it = cs->actions.begin(); it != cs->actions.end(); it++)
385  it->first.remove2(pattern, &it->second);
386 
387  for (auto it = cs->switches.begin(); it != cs->switches.end(); it++)
388  for (auto it2 = (*it)->cases.begin(); it2 != (*it)->cases.end(); it2++)
389  removeSignalFromCaseTree(pattern, *it2);
390  }
391 
392  // add an assignment (aka "action") but split it up in chunks. this way huge assignments
393  // are avoided and the generated $mux cells have a more "natural" size.
394  void addChunkActions(std::vector<RTLIL::SigSig> &actions, RTLIL::SigSpec lvalue, RTLIL::SigSpec rvalue, bool inSyncRule = false)
395  {
396  if (inSyncRule && initSyncSignals.size() > 0) {
397  init_lvalue.append(lvalue.extract(initSyncSignals));
398  init_rvalue.append(lvalue.extract(initSyncSignals, &rvalue));
399  lvalue.remove2(initSyncSignals, &rvalue);
400  }
401  log_assert(lvalue.size() == rvalue.size());
402 
403  int offset = 0;
404  for (auto &lvalue_c : lvalue.chunks()) {
405  RTLIL::SigSpec lhs = lvalue_c;
406  RTLIL::SigSpec rhs = rvalue.extract(offset, lvalue_c.width);
407  if (inSyncRule && lvalue_c.wire && lvalue_c.wire->get_bool_attribute("\\nosync"))
408  rhs = RTLIL::SigSpec(RTLIL::State::Sx, rhs.size());
409  remove_unwanted_lvalue_bits(lhs, rhs);
410  actions.push_back(RTLIL::SigSig(lhs, rhs));
411  offset += lhs.size();
412  }
413  }
414 
415  // recursively process the AST and fill the RTLIL::Process
416  void processAst(AstNode *ast)
417  {
418  switch (ast->type)
419  {
420  case AST_BLOCK:
421  for (auto child : ast->children)
422  processAst(child);
423  break;
424 
425  case AST_ASSIGN_EQ:
426  case AST_ASSIGN_LE:
427  {
428  RTLIL::SigSpec unmapped_lvalue = ast->children[0]->genRTLIL(), lvalue = unmapped_lvalue;
429  RTLIL::SigSpec rvalue = ast->children[1]->genWidthRTLIL(lvalue.size(), &subst_rvalue_map.stdmap());
430  lvalue.replace(subst_lvalue_map.stdmap());
431 
432  if (ast->type == AST_ASSIGN_EQ) {
433  for (int i = 0; i < GetSize(unmapped_lvalue); i++)
434  subst_rvalue_map.set(unmapped_lvalue[i], rvalue[i]);
435  }
436 
437  removeSignalFromCaseTree(lvalue.to_sigbit_set(), current_case);
438  remove_unwanted_lvalue_bits(lvalue, rvalue);
439  current_case->actions.push_back(RTLIL::SigSig(lvalue, rvalue));
440  }
441  break;
442 
443  case AST_CASE:
444  {
446  sw->signal = ast->children[0]->genWidthRTLIL(-1, &subst_rvalue_map.stdmap());
447  current_case->switches.push_back(sw);
448 
449  for (auto &attr : ast->attributes) {
450  if (attr.second->type != AST_CONSTANT)
451  log_error("Attribute `%s' with non-constant value at %s:%d!\n",
452  attr.first.c_str(), ast->filename.c_str(), ast->linenum);
453  sw->attributes[attr.first] = attr.second->asAttrConst();
454  }
455 
456  RTLIL::SigSpec this_case_eq_lvalue;
457  collect_lvalues(this_case_eq_lvalue, ast, true, false);
458 
459  RTLIL::SigSpec this_case_eq_ltemp = new_temp_signal(this_case_eq_lvalue);
460 
461  RTLIL::SigSpec this_case_eq_rvalue = this_case_eq_lvalue;
462  this_case_eq_rvalue.replace(subst_rvalue_map.stdmap());
463 
464  RTLIL::CaseRule *default_case = NULL;
465  RTLIL::CaseRule *last_generated_case = NULL;
466  for (auto child : ast->children)
467  {
468  if (child == ast->children[0])
469  continue;
470  log_assert(child->type == AST_COND);
471 
472  subst_lvalue_map.save();
473  subst_rvalue_map.save();
474 
475  for (int i = 0; i < GetSize(this_case_eq_lvalue); i++)
476  subst_lvalue_map.set(this_case_eq_lvalue[i], this_case_eq_ltemp[i]);
477 
478  RTLIL::CaseRule *backup_case = current_case;
479  current_case = new RTLIL::CaseRule;
480  last_generated_case = current_case;
481  addChunkActions(current_case->actions, this_case_eq_ltemp, this_case_eq_rvalue);
482  for (auto node : child->children) {
483  if (node->type == AST_DEFAULT)
484  default_case = current_case;
485  else if (node->type == AST_BLOCK)
486  processAst(node);
487  else
488  current_case->compare.push_back(node->genWidthRTLIL(sw->signal.size(), &subst_rvalue_map.stdmap()));
489  }
490  if (default_case != current_case)
491  sw->cases.push_back(current_case);
492  else
493  log_assert(current_case->compare.size() == 0);
494  current_case = backup_case;
495 
496  subst_lvalue_map.restore();
497  subst_rvalue_map.restore();
498  }
499 
500  if (last_generated_case != NULL && ast->get_bool_attribute("\\full_case") && default_case == NULL) {
501  last_generated_case->compare.clear();
502  } else {
503  if (default_case == NULL) {
504  default_case = new RTLIL::CaseRule;
505  addChunkActions(default_case->actions, this_case_eq_ltemp, this_case_eq_rvalue);
506  }
507  sw->cases.push_back(default_case);
508  }
509 
510  for (int i = 0; i < GetSize(this_case_eq_lvalue); i++)
511  subst_rvalue_map.set(this_case_eq_lvalue[i], this_case_eq_ltemp[i]);
512 
513  this_case_eq_lvalue.replace(subst_lvalue_map.stdmap());
514  removeSignalFromCaseTree(this_case_eq_lvalue.to_sigbit_set(), current_case);
515  addChunkActions(current_case->actions, this_case_eq_lvalue, this_case_eq_ltemp);
516  }
517  break;
518 
519  case AST_WIRE:
520  log_error("Found wire declaration in block without label at at %s:%d!\n", ast->filename.c_str(), ast->linenum);
521  break;
522 
523  case AST_TCALL:
524  case AST_FOR:
525  break;
526 
527  default:
528  log_abort();
529  }
530  }
531 };
532 
533 // detect sign and width of an expression
534 void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *found_real)
535 {
536  std::string type_name;
537  bool sub_sign_hint = true;
538  int sub_width_hint = -1;
539  int this_width = 0;
540  AstNode *range = NULL;
541  AstNode *id_ast = NULL;
542 
543  bool local_found_real = false;
544  if (found_real == NULL)
545  found_real = &local_found_real;
546 
547  switch (type)
548  {
549  case AST_CONSTANT:
550  width_hint = std::max(width_hint, int(bits.size()));
551  if (!is_signed)
552  sign_hint = false;
553  break;
554 
555  case AST_REALVALUE:
556  *found_real = true;
557  width_hint = std::max(width_hint, 32);
558  break;
559 
560  case AST_IDENTIFIER:
561  id_ast = id2ast;
562  if (id_ast == NULL && current_scope.count(str))
563  id_ast = current_scope.at(str);
564  if (!id_ast)
565  log_error("Failed to resolve identifier %s for width detection at %s:%d!\n", str.c_str(), filename.c_str(), linenum);
566  if (id_ast->type == AST_PARAMETER || id_ast->type == AST_LOCALPARAM) {
567  if (id_ast->children.size() > 1 && id_ast->children[1]->range_valid) {
568  this_width = id_ast->children[1]->range_left - id_ast->children[1]->range_right + 1;
569  } else
570  if (id_ast->children[0]->type == AST_CONSTANT) {
571  this_width = id_ast->children[0]->bits.size();
572  } else
573  log_error("Failed to detect width for parameter %s at %s:%d!\n", str.c_str(), filename.c_str(), linenum);
574  if (children.size() != 0)
575  range = children[0];
576  } else if (id_ast->type == AST_WIRE || id_ast->type == AST_AUTOWIRE) {
577  if (!id_ast->range_valid) {
578  if (id_ast->type == AST_AUTOWIRE)
579  this_width = 1;
580  else {
581  // current_ast_mod->dumpAst(NULL, "mod> ");
582  // log("---\n");
583  // id_ast->dumpAst(NULL, "decl> ");
584  // dumpAst(NULL, "ref> ");
585  log_error("Failed to detect with of signal access `%s' at %s:%d!\n", str.c_str(), filename.c_str(), linenum);
586  }
587  } else {
588  this_width = id_ast->range_left - id_ast->range_right + 1;
589  if (children.size() != 0)
590  range = children[0];
591  }
592  } else if (id_ast->type == AST_GENVAR) {
593  this_width = 32;
594  } else if (id_ast->type == AST_MEMORY) {
595  if (!id_ast->children[0]->range_valid)
596  log_error("Failed to detect with of memory access `%s' at %s:%d!\n", str.c_str(), filename.c_str(), linenum);
597  this_width = id_ast->children[0]->range_left - id_ast->children[0]->range_right + 1;
598  } else
599  log_error("Failed to detect width for identifier %s at %s:%d!\n", str.c_str(), filename.c_str(), linenum);
600  if (range) {
601  if (range->children.size() == 1)
602  this_width = 1;
603  else if (!range->range_valid) {
604  AstNode *left_at_zero_ast = children[0]->children[0]->clone();
605  AstNode *right_at_zero_ast = children[0]->children.size() >= 2 ? children[0]->children[1]->clone() : left_at_zero_ast->clone();
606  while (left_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { }
607  while (right_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { }
608  if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT)
609  log_error("Unsupported expression on dynamic range select on signal `%s' at %s:%d!\n",
610  str.c_str(), filename.c_str(), linenum);
611  this_width = left_at_zero_ast->integer - right_at_zero_ast->integer + 1;
612  delete left_at_zero_ast;
613  delete right_at_zero_ast;
614  } else
615  this_width = range->range_left - range->range_right + 1;
616  sign_hint = false;
617  }
618  width_hint = std::max(width_hint, this_width);
619  if (!id_ast->is_signed)
620  sign_hint = false;
621  break;
622 
623  case AST_TO_BITS:
624  while (children[0]->simplify(true, false, false, 1, -1, false, false) == true) { }
625  if (children[0]->type != AST_CONSTANT)
626  log_error("Left operand of tobits expression is not constant at %s:%d!\n", filename.c_str(), linenum);
627  children[1]->detectSignWidthWorker(sub_width_hint, sign_hint);
628  width_hint = std::max(width_hint, children[0]->bitsAsConst().as_int());
629  break;
630 
631  case AST_TO_SIGNED:
632  children.at(0)->detectSignWidthWorker(width_hint, sub_sign_hint);
633  break;
634 
635  case AST_TO_UNSIGNED:
636  children.at(0)->detectSignWidthWorker(width_hint, sub_sign_hint);
637  sign_hint = false;
638  break;
639 
640  case AST_CONCAT:
641  for (auto child : children) {
642  sub_width_hint = 0;
643  sub_sign_hint = true;
644  child->detectSignWidthWorker(sub_width_hint, sub_sign_hint);
645  this_width += sub_width_hint;
646  }
647  width_hint = std::max(width_hint, this_width);
648  sign_hint = false;
649  break;
650 
651  case AST_REPLICATE:
652  while (children[0]->simplify(true, false, false, 1, -1, false, true) == true) { }
653  if (children[0]->type != AST_CONSTANT)
654  log_error("Left operand of replicate expression is not constant at %s:%d!\n", filename.c_str(), linenum);
655  children[1]->detectSignWidthWorker(sub_width_hint, sub_sign_hint);
656  width_hint = std::max(width_hint, children[0]->bitsAsConst().as_int() * sub_width_hint);
657  sign_hint = false;
658  break;
659 
660  case AST_NEG:
661  case AST_BIT_NOT:
662  case AST_POS:
663  children[0]->detectSignWidthWorker(width_hint, sign_hint, found_real);
664  break;
665 
666  case AST_BIT_AND:
667  case AST_BIT_OR:
668  case AST_BIT_XOR:
669  case AST_BIT_XNOR:
670  for (auto child : children)
671  child->detectSignWidthWorker(width_hint, sign_hint, found_real);
672  break;
673 
674  case AST_REDUCE_AND:
675  case AST_REDUCE_OR:
676  case AST_REDUCE_XOR:
677  case AST_REDUCE_XNOR:
678  case AST_REDUCE_BOOL:
679  width_hint = std::max(width_hint, 1);
680  sign_hint = false;
681  break;
682 
683  case AST_SHIFT_LEFT:
684  case AST_SHIFT_RIGHT:
685  case AST_SHIFT_SLEFT:
686  case AST_SHIFT_SRIGHT:
687  case AST_POW:
688  children[0]->detectSignWidthWorker(width_hint, sign_hint, found_real);
689  break;
690 
691  case AST_LT:
692  case AST_LE:
693  case AST_EQ:
694  case AST_NE:
695  case AST_EQX:
696  case AST_NEX:
697  case AST_GE:
698  case AST_GT:
699  width_hint = std::max(width_hint, 1);
700  sign_hint = false;
701  break;
702 
703  case AST_ADD:
704  case AST_SUB:
705  case AST_MUL:
706  case AST_DIV:
707  case AST_MOD:
708  for (auto child : children)
709  child->detectSignWidthWorker(width_hint, sign_hint, found_real);
710  break;
711 
712  case AST_LOGIC_AND:
713  case AST_LOGIC_OR:
714  case AST_LOGIC_NOT:
715  width_hint = std::max(width_hint, 1);
716  sign_hint = false;
717  break;
718 
719  case AST_TERNARY:
720  children.at(1)->detectSignWidthWorker(width_hint, sign_hint, found_real);
721  children.at(2)->detectSignWidthWorker(width_hint, sign_hint, found_real);
722  break;
723 
724  case AST_MEMRD:
725  if (!id2ast->is_signed)
726  sign_hint = false;
727  if (!id2ast->children[0]->range_valid)
728  log_error("Failed to detect with of memory access `%s' at %s:%d!\n", str.c_str(), filename.c_str(), linenum);
729  this_width = id2ast->children[0]->range_left - id2ast->children[0]->range_right + 1;
730  width_hint = std::max(width_hint, this_width);
731  break;
732 
733  // everything should have been handled above -> print error if not.
734  default:
735  for (auto f : log_files)
736  current_ast->dumpAst(f, "verilog-ast> ");
737  log_error("Don't know how to detect sign and width for %s node at %s:%d!\n",
738  type2str(type).c_str(), filename.c_str(), linenum);
739  }
740 
741  if (*found_real)
742  sign_hint = true;
743 }
744 
745 // detect sign and width of an expression
746 void AstNode::detectSignWidth(int &width_hint, bool &sign_hint, bool *found_real)
747 {
748  width_hint = -1;
749  sign_hint = true;
750  if (found_real)
751  *found_real = false;
752  detectSignWidthWorker(width_hint, sign_hint, found_real);
753 }
754 
755 // create RTLIL from an AST node
756 // all generated cells, wires and processes are added to the module pointed to by 'current_module'
757 // when the AST node is an expression (AST_ADD, AST_BIT_XOR, etc.), the result signal is returned.
758 //
759 // note that this function is influenced by a number of global variables that might be set when
760 // called from genWidthRTLIL(). also note that this function recursively calls itself to transform
761 // larger expressions into a netlist of cells.
762 RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
763 {
764  // in the following big switch() statement there are some uses of
765  // Clifford's Device (http://www.clifford.at/cfun/cliffdev/). In this
766  // cases this variable is used to hold the type of the cell that should
767  // be instanciated for this type of AST node.
768  std::string type_name;
769 
770  current_filename = filename;
771  set_line_num(linenum);
772 
773  switch (type)
774  {
775  // simply ignore this nodes.
776  // they are eighter leftovers from simplify() or are referenced by other nodes
777  // and are only accessed here thru this references
778  case AST_TASK:
779  case AST_FUNCTION:
780  case AST_DPI_FUNCTION:
781  case AST_AUTOWIRE:
782  case AST_LOCALPARAM:
783  case AST_DEFPARAM:
784  case AST_GENVAR:
785  case AST_GENFOR:
786  case AST_GENBLOCK:
787  case AST_GENIF:
788  case AST_GENCASE:
789  break;
790 
791  // remember the parameter, needed for example in techmap
792  case AST_PARAMETER:
793  current_module->avail_parameters.insert(str);
794  break;
795 
796  // create an RTLIL::Wire for an AST_WIRE node
797  case AST_WIRE: {
798  if (current_module->wires_.count(str) != 0)
799  log_error("Re-definition of signal `%s' at %s:%d!\n",
800  str.c_str(), filename.c_str(), linenum);
801  if (!range_valid)
802  log_error("Signal `%s' with non-constant width at %s:%d!\n",
803  str.c_str(), filename.c_str(), linenum);
804 
805  log_assert(range_left >= range_right || (range_left == -1 && range_right == 0));
806 
807  RTLIL::Wire *wire = current_module->addWire(str, range_left - range_right + 1);
808  wire->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
809  wire->start_offset = range_right;
810  wire->port_id = port_id;
811  wire->port_input = is_input;
812  wire->port_output = is_output;
813  wire->upto = range_swapped;
814 
815  for (auto &attr : attributes) {
816  if (attr.second->type != AST_CONSTANT)
817  log_error("Attribute `%s' with non-constant value at %s:%d!\n",
818  attr.first.c_str(), filename.c_str(), linenum);
819  wire->attributes[attr.first] = attr.second->asAttrConst();
820  }
821  }
822  break;
823 
824  // create an RTLIL::Memory for an AST_MEMORY node
825  case AST_MEMORY: {
826  if (current_module->memories.count(str) != 0)
827  log_error("Re-definition of memory `%s' at %s:%d!\n",
828  str.c_str(), filename.c_str(), linenum);
829 
830  log_assert(children.size() >= 2);
831  log_assert(children[0]->type == AST_RANGE);
832  log_assert(children[1]->type == AST_RANGE);
833 
834  if (!children[0]->range_valid || !children[1]->range_valid)
835  log_error("Memory `%s' with non-constant width or size at %s:%d!\n",
836  str.c_str(), filename.c_str(), linenum);
837 
838  RTLIL::Memory *memory = new RTLIL::Memory;
839  memory->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
840  memory->name = str;
841  memory->width = children[0]->range_left - children[0]->range_right + 1;
842  memory->start_offset = children[0]->range_right;
843  memory->size = children[1]->range_left - children[1]->range_right;
844  current_module->memories[memory->name] = memory;
845 
846  if (memory->size < 0)
847  memory->size *= -1;
848  memory->size += std::min(children[1]->range_left, children[1]->range_right) + 1;
849 
850  for (auto &attr : attributes) {
851  if (attr.second->type != AST_CONSTANT)
852  log_error("Attribute `%s' with non-constant value at %s:%d!\n",
853  attr.first.c_str(), filename.c_str(), linenum);
854  memory->attributes[attr.first] = attr.second->asAttrConst();
855  }
856  }
857  break;
858 
859  // simply return the corresponding RTLIL::SigSpec for an AST_CONSTANT node
860  case AST_CONSTANT:
861  {
862  if (width_hint < 0)
863  detectSignWidth(width_hint, sign_hint);
864 
865  is_signed = sign_hint;
866  return RTLIL::SigSpec(bitsAsConst());
867  }
868 
869  case AST_REALVALUE:
870  {
871  RTLIL::SigSpec sig = realAsConst(width_hint);
872  log_warning("converting real value %e to binary %s at %s:%d.\n",
873  realvalue, log_signal(sig), filename.c_str(), linenum);
874  return sig;
875  }
876 
877  // simply return the corresponding RTLIL::SigSpec for an AST_IDENTIFIER node
878  // for identifiers with dynamic bit ranges (e.g. "foo[bar]" or "foo[bar+3:bar]") a
879  // shifter cell is created and the output signal of this cell is returned
880  case AST_IDENTIFIER:
881  {
882  RTLIL::Wire *wire = NULL;
883  RTLIL::SigChunk chunk;
884 
885  int add_undef_bits_msb = 0;
886  int add_undef_bits_lsb = 0;
887 
888  if (id2ast && id2ast->type == AST_AUTOWIRE && current_module->wires_.count(str) == 0) {
889  RTLIL::Wire *wire = current_module->addWire(str);
890  wire->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
891  wire->name = str;
892  if (flag_autowire)
893  log_warning("Identifier `%s' is implicitly declared at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
894  else
895  log_error("Identifier `%s' is implicitly declared at %s:%d and `default_nettype is set to none.\n", str.c_str(), filename.c_str(), linenum);
896  }
897  else if (id2ast->type == AST_PARAMETER || id2ast->type == AST_LOCALPARAM) {
898  if (id2ast->children[0]->type != AST_CONSTANT)
899  log_error("Parameter %s does not evaluate to constant value at %s:%d!\n",
900  str.c_str(), filename.c_str(), linenum);
901  chunk = RTLIL::Const(id2ast->children[0]->bits);
902  goto use_const_chunk;
903  }
904  else if (!id2ast || (id2ast->type != AST_WIRE && id2ast->type != AST_AUTOWIRE &&
905  id2ast->type != AST_MEMORY) || current_module->wires_.count(str) == 0)
906  log_error("Identifier `%s' doesn't map to any signal at %s:%d!\n",
907  str.c_str(), filename.c_str(), linenum);
908 
909  if (id2ast->type == AST_MEMORY)
910  log_error("Identifier `%s' does map to an unexpanded memory at %s:%d!\n",
911  str.c_str(), filename.c_str(), linenum);
912 
913  wire = current_module->wires_[str];
914  chunk.wire = wire;
915  chunk.width = wire->width;
916  chunk.offset = 0;
917 
918  use_const_chunk:
919  if (children.size() != 0) {
920  log_assert(children[0]->type == AST_RANGE);
921  int source_width = id2ast->range_left - id2ast->range_right + 1;
922  int source_offset = id2ast->range_right;
923  if (!children[0]->range_valid) {
924  AstNode *left_at_zero_ast = children[0]->children[0]->clone();
925  AstNode *right_at_zero_ast = children[0]->children.size() >= 2 ? children[0]->children[1]->clone() : left_at_zero_ast->clone();
926  while (left_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { }
927  while (right_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { }
928  if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT)
929  log_error("Unsupported expression on dynamic range select on signal `%s' at %s:%d!\n",
930  str.c_str(), filename.c_str(), linenum);
931  int width = left_at_zero_ast->integer - right_at_zero_ast->integer + 1;
932  AstNode *fake_ast = new AstNode(AST_NONE, clone(), children[0]->children.size() >= 2 ?
933  children[0]->children[1]->clone() : children[0]->children[0]->clone());
934  fake_ast->children[0]->delete_children();
935  RTLIL::SigSpec shift_val = fake_ast->children[1]->genRTLIL();
936  if (id2ast->range_right != 0) {
937  shift_val = current_module->Sub(NEW_ID, shift_val, id2ast->range_right, fake_ast->children[1]->is_signed);
938  fake_ast->children[1]->is_signed = true;
939  }
940  if (id2ast->range_swapped) {
941  shift_val = current_module->Sub(NEW_ID, RTLIL::SigSpec(source_width - width), shift_val, fake_ast->children[1]->is_signed);
942  fake_ast->children[1]->is_signed = true;
943  }
944  if (GetSize(shift_val) >= 32)
945  fake_ast->children[1]->is_signed = true;
946  RTLIL::SigSpec sig = binop2rtlil(fake_ast, "$shiftx", width, fake_ast->children[0]->genRTLIL(), shift_val);
947  delete left_at_zero_ast;
948  delete right_at_zero_ast;
949  delete fake_ast;
950  return sig;
951  } else {
952  chunk.width = children[0]->range_left - children[0]->range_right + 1;
953  chunk.offset = children[0]->range_right - source_offset;
954  if (id2ast->range_swapped)
955  chunk.offset = (id2ast->range_left - id2ast->range_right + 1) - (chunk.offset + chunk.width);
956  if (chunk.offset >= source_width || chunk.offset + chunk.width < 0) {
957  if (chunk.width == 1)
958  log_warning("Range select out of bounds on signal `%s' at %s:%d: Setting result bit to undef.\n",
959  str.c_str(), filename.c_str(), linenum);
960  else
961  log_warning("Range select out of bounds on signal `%s' at %s:%d: Setting all %d result bits to undef.\n",
962  str.c_str(), filename.c_str(), linenum, chunk.width);
963  chunk = RTLIL::SigChunk(RTLIL::State::Sx, chunk.width);
964  } else {
965  if (chunk.width + chunk.offset > source_width) {
966  add_undef_bits_msb = (chunk.width + chunk.offset) - source_width;
967  chunk.width -= add_undef_bits_msb;
968  }
969  if (chunk.offset < 0) {
970  add_undef_bits_lsb = -chunk.offset;
971  chunk.width -= add_undef_bits_lsb;
972  chunk.offset += add_undef_bits_lsb;
973  }
974  if (add_undef_bits_lsb)
975  log_warning("Range select out of bounds on signal `%s' at %s:%d: Setting %d LSB bits to undef.\n",
976  str.c_str(), filename.c_str(), linenum, add_undef_bits_lsb);
977  if (add_undef_bits_msb)
978  log_warning("Range select out of bounds on signal `%s' at %s:%d: Setting %d MSB bits to undef.\n",
979  str.c_str(), filename.c_str(), linenum, add_undef_bits_msb);
980  }
981  }
982  }
983 
984  RTLIL::SigSpec sig = { RTLIL::SigSpec(RTLIL::State::Sx, add_undef_bits_msb), chunk, RTLIL::SigSpec(RTLIL::State::Sx, add_undef_bits_lsb) };
985 
986  if (genRTLIL_subst_ptr)
988 
989  is_signed = children.size() > 0 ? false : id2ast->is_signed && sign_hint;
990  return sig;
991  }
992 
993  // just pass thru the signal. the parent will evaluate the is_signed property and interpret the SigSpec accordingly
994  case AST_TO_SIGNED:
995  case AST_TO_UNSIGNED: {
996  RTLIL::SigSpec sig = children[0]->genRTLIL();
997  if (sig.size() < width_hint)
998  sig.extend_u0(width_hint, sign_hint);
999  is_signed = sign_hint;
1000  return sig;
1001  }
1002 
1003  // concatenation of signals can be done directly using RTLIL::SigSpec
1004  case AST_CONCAT: {
1005  RTLIL::SigSpec sig;
1006  for (auto it = children.begin(); it != children.end(); it++)
1007  sig.append((*it)->genRTLIL());
1008  if (sig.size() < width_hint)
1009  sig.extend_u0(width_hint, false);
1010  return sig;
1011  }
1012 
1013  // replication of signals can be done directly using RTLIL::SigSpec
1014  case AST_REPLICATE: {
1015  RTLIL::SigSpec left = children[0]->genRTLIL();
1016  RTLIL::SigSpec right = children[1]->genRTLIL();
1017  if (!left.is_fully_const())
1018  log_error("Left operand of replicate expression is not constant at %s:%d!\n", filename.c_str(), linenum);
1019  int count = left.as_int();
1020  RTLIL::SigSpec sig;
1021  for (int i = 0; i < count; i++)
1022  sig.append(right);
1023  if (sig.size() < width_hint)
1024  sig.extend_u0(width_hint, false);
1025  is_signed = false;
1026  return sig;
1027  }
1028 
1029  // generate cells for unary operations: $not, $pos, $neg
1030  if (0) { case AST_BIT_NOT: type_name = "$not"; }
1031  if (0) { case AST_POS: type_name = "$pos"; }
1032  if (0) { case AST_NEG: type_name = "$neg"; }
1033  {
1034  RTLIL::SigSpec arg = children[0]->genRTLIL(width_hint, sign_hint);
1035  is_signed = children[0]->is_signed;
1036  int width = arg.size();
1037  if (width_hint > 0) {
1038  width = width_hint;
1039  widthExtend(this, arg, width, is_signed);
1040  }
1041  return uniop2rtlil(this, type_name, width, arg);
1042  }
1043 
1044  // generate cells for binary operations: $and, $or, $xor, $xnor
1045  if (0) { case AST_BIT_AND: type_name = "$and"; }
1046  if (0) { case AST_BIT_OR: type_name = "$or"; }
1047  if (0) { case AST_BIT_XOR: type_name = "$xor"; }
1048  if (0) { case AST_BIT_XNOR: type_name = "$xnor"; }
1049  {
1050  if (width_hint < 0)
1051  detectSignWidth(width_hint, sign_hint);
1052  RTLIL::SigSpec left = children[0]->genRTLIL(width_hint, sign_hint);
1053  RTLIL::SigSpec right = children[1]->genRTLIL(width_hint, sign_hint);
1054  int width = std::max(left.size(), right.size());
1055  if (width_hint > 0)
1056  width = width_hint;
1057  is_signed = children[0]->is_signed && children[1]->is_signed;
1058  return binop2rtlil(this, type_name, width, left, right);
1059  }
1060 
1061  // generate cells for unary operations: $reduce_and, $reduce_or, $reduce_xor, $reduce_xnor
1062  if (0) { case AST_REDUCE_AND: type_name = "$reduce_and"; }
1063  if (0) { case AST_REDUCE_OR: type_name = "$reduce_or"; }
1064  if (0) { case AST_REDUCE_XOR: type_name = "$reduce_xor"; }
1065  if (0) { case AST_REDUCE_XNOR: type_name = "$reduce_xnor"; }
1066  {
1067  RTLIL::SigSpec arg = children[0]->genRTLIL();
1068  RTLIL::SigSpec sig = uniop2rtlil(this, type_name, std::max(width_hint, 1), arg);
1069  return sig;
1070  }
1071 
1072  // generate cells for unary operations: $reduce_bool
1073  // (this is actually just an $reduce_or, but for clearity a different cell type is used)
1074  if (0) { case AST_REDUCE_BOOL: type_name = "$reduce_bool"; }
1075  {
1076  RTLIL::SigSpec arg = children[0]->genRTLIL();
1077  RTLIL::SigSpec sig = arg.size() > 1 ? uniop2rtlil(this, type_name, std::max(width_hint, 1), arg) : arg;
1078  return sig;
1079  }
1080 
1081  // generate cells for binary operations: $shl, $shr, $sshl, $sshr
1082  if (0) { case AST_SHIFT_LEFT: type_name = "$shl"; }
1083  if (0) { case AST_SHIFT_RIGHT: type_name = "$shr"; }
1084  if (0) { case AST_SHIFT_SLEFT: type_name = "$sshl"; }
1085  if (0) { case AST_SHIFT_SRIGHT: type_name = "$sshr"; }
1086  {
1087  if (width_hint < 0)
1088  detectSignWidth(width_hint, sign_hint);
1089  RTLIL::SigSpec left = children[0]->genRTLIL(width_hint, sign_hint);
1090  RTLIL::SigSpec right = children[1]->genRTLIL();
1091  int width = width_hint > 0 ? width_hint : left.size();
1092  is_signed = children[0]->is_signed;
1093  return binop2rtlil(this, type_name, width, left, right);
1094  }
1095 
1096  // generate cells for binary operations: $pow
1097  case AST_POW:
1098  {
1099  int right_width;
1100  bool right_signed;
1101  children[1]->detectSignWidth(right_width, right_signed);
1102  if (width_hint < 0)
1103  detectSignWidth(width_hint, sign_hint);
1104  RTLIL::SigSpec left = children[0]->genRTLIL(width_hint, sign_hint);
1105  RTLIL::SigSpec right = children[1]->genRTLIL(right_width, right_signed);
1106  int width = width_hint > 0 ? width_hint : left.size();
1107  is_signed = children[0]->is_signed;
1108  if (!flag_noopt && left.is_fully_const() && left.as_int() == 2 && !right_signed)
1109  return binop2rtlil(this, "$shl", width, RTLIL::SigSpec(1, left.size()), right);
1110  return binop2rtlil(this, "$pow", width, left, right);
1111  }
1112 
1113  // generate cells for binary operations: $lt, $le, $eq, $ne, $ge, $gt
1114  if (0) { case AST_LT: type_name = "$lt"; }
1115  if (0) { case AST_LE: type_name = "$le"; }
1116  if (0) { case AST_EQ: type_name = "$eq"; }
1117  if (0) { case AST_NE: type_name = "$ne"; }
1118  if (0) { case AST_EQX: type_name = "$eqx"; }
1119  if (0) { case AST_NEX: type_name = "$nex"; }
1120  if (0) { case AST_GE: type_name = "$ge"; }
1121  if (0) { case AST_GT: type_name = "$gt"; }
1122  {
1123  int width = std::max(width_hint, 1);
1124  width_hint = -1, sign_hint = true;
1125  children[0]->detectSignWidthWorker(width_hint, sign_hint);
1126  children[1]->detectSignWidthWorker(width_hint, sign_hint);
1127  RTLIL::SigSpec left = children[0]->genRTLIL(width_hint, sign_hint);
1128  RTLIL::SigSpec right = children[1]->genRTLIL(width_hint, sign_hint);
1129  RTLIL::SigSpec sig = binop2rtlil(this, type_name, width, left, right);
1130  return sig;
1131  }
1132 
1133  // generate cells for binary operations: $add, $sub, $mul, $div, $mod
1134  if (0) { case AST_ADD: type_name = "$add"; }
1135  if (0) { case AST_SUB: type_name = "$sub"; }
1136  if (0) { case AST_MUL: type_name = "$mul"; }
1137  if (0) { case AST_DIV: type_name = "$div"; }
1138  if (0) { case AST_MOD: type_name = "$mod"; }
1139  {
1140  if (width_hint < 0)
1141  detectSignWidth(width_hint, sign_hint);
1142  RTLIL::SigSpec left = children[0]->genRTLIL(width_hint, sign_hint);
1143  RTLIL::SigSpec right = children[1]->genRTLIL(width_hint, sign_hint);
1144  #if 0
1145  int width = std::max(left.size(), right.size());
1146  if (width > width_hint && width_hint > 0)
1147  width = width_hint;
1148  if (width < width_hint) {
1149  if (type == AST_ADD || type == AST_SUB || type == AST_DIV)
1150  width++;
1151  if (type == AST_SUB && (!children[0]->is_signed || !children[1]->is_signed))
1152  width = width_hint;
1153  if (type == AST_MUL)
1154  width = std::min(left.size() + right.size(), width_hint);
1155  }
1156  #else
1157  int width = std::max(std::max(left.size(), right.size()), width_hint);
1158  #endif
1159  is_signed = children[0]->is_signed && children[1]->is_signed;
1160  return binop2rtlil(this, type_name, width, left, right);
1161  }
1162 
1163  // generate cells for binary operations: $logic_and, $logic_or
1164  if (0) { case AST_LOGIC_AND: type_name = "$logic_and"; }
1165  if (0) { case AST_LOGIC_OR: type_name = "$logic_or"; }
1166  {
1167  RTLIL::SigSpec left = children[0]->genRTLIL();
1168  RTLIL::SigSpec right = children[1]->genRTLIL();
1169  return binop2rtlil(this, type_name, std::max(width_hint, 1), left, right);
1170  }
1171 
1172  // generate cells for unary operations: $logic_not
1173  case AST_LOGIC_NOT:
1174  {
1175  RTLIL::SigSpec arg = children[0]->genRTLIL();
1176  return uniop2rtlil(this, "$logic_not", std::max(width_hint, 1), arg);
1177  }
1178 
1179  // generate multiplexer for ternary operator (aka ?:-operator)
1180  case AST_TERNARY:
1181  {
1182  if (width_hint < 0)
1183  detectSignWidth(width_hint, sign_hint);
1184 
1185  RTLIL::SigSpec cond = children[0]->genRTLIL();
1186  RTLIL::SigSpec val1 = children[1]->genRTLIL(width_hint, sign_hint);
1187  RTLIL::SigSpec val2 = children[2]->genRTLIL(width_hint, sign_hint);
1188 
1189  if (cond.size() > 1)
1190  cond = uniop2rtlil(this, "$reduce_bool", 1, cond, false);
1191 
1192  int width = std::max(val1.size(), val2.size());
1193  is_signed = children[1]->is_signed && children[2]->is_signed;
1194  widthExtend(this, val1, width, is_signed);
1195  widthExtend(this, val2, width, is_signed);
1196 
1197  RTLIL::SigSpec sig = mux2rtlil(this, cond, val1, val2);
1198 
1199  if (sig.size() < width_hint)
1200  sig.extend_u0(width_hint, sign_hint);
1201  return sig;
1202  }
1203 
1204  // generate $memrd cells for memory read ports
1205  case AST_MEMRD:
1206  {
1207  std::stringstream sstr;
1208  sstr << "$memrd$" << str << "$" << filename << ":" << linenum << "$" << (autoidx++);
1209 
1210  RTLIL::Cell *cell = current_module->addCell(sstr.str(), "$memrd");
1211  cell->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
1212 
1213  RTLIL::Wire *wire = current_module->addWire(cell->name.str() + "_DATA", current_module->memories[str]->width);
1214  wire->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
1215 
1216  int addr_bits = 1;
1217  while ((1 << addr_bits) < current_module->memories[str]->size)
1218  addr_bits++;
1219 
1220  cell->setPort("\\CLK", RTLIL::SigSpec(RTLIL::State::Sx, 1));
1221  cell->setPort("\\ADDR", children[0]->genWidthRTLIL(addr_bits));
1222  cell->setPort("\\DATA", RTLIL::SigSpec(wire));
1223 
1224  cell->parameters["\\MEMID"] = RTLIL::Const(str);
1225  cell->parameters["\\ABITS"] = RTLIL::Const(addr_bits);
1226  cell->parameters["\\WIDTH"] = RTLIL::Const(wire->width);
1227 
1228  cell->parameters["\\CLK_ENABLE"] = RTLIL::Const(0);
1229  cell->parameters["\\CLK_POLARITY"] = RTLIL::Const(0);
1230  cell->parameters["\\TRANSPARENT"] = RTLIL::Const(0);
1231 
1232  return RTLIL::SigSpec(wire);
1233  }
1234 
1235  // generate $memwr cells for memory write ports
1236  case AST_MEMWR:
1237  {
1238  std::stringstream sstr;
1239  sstr << "$memwr$" << str << "$" << filename << ":" << linenum << "$" << (autoidx++);
1240 
1241  RTLIL::Cell *cell = current_module->addCell(sstr.str(), "$memwr");
1242  cell->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
1243 
1244  int addr_bits = 1;
1245  while ((1 << addr_bits) < current_module->memories[str]->size)
1246  addr_bits++;
1247 
1248  cell->setPort("\\CLK", RTLIL::SigSpec(RTLIL::State::Sx, 1));
1249  cell->setPort("\\ADDR", children[0]->genWidthRTLIL(addr_bits));
1250  cell->setPort("\\DATA", children[1]->genWidthRTLIL(current_module->memories[str]->width));
1251  cell->setPort("\\EN", children[2]->genRTLIL());
1252 
1253  cell->parameters["\\MEMID"] = RTLIL::Const(str);
1254  cell->parameters["\\ABITS"] = RTLIL::Const(addr_bits);
1255  cell->parameters["\\WIDTH"] = RTLIL::Const(current_module->memories[str]->width);
1256 
1257  cell->parameters["\\CLK_ENABLE"] = RTLIL::Const(0);
1258  cell->parameters["\\CLK_POLARITY"] = RTLIL::Const(0);
1259 
1260  cell->parameters["\\PRIORITY"] = RTLIL::Const(autoidx-1);
1261  }
1262  break;
1263 
1264  // generate $assert cells
1265  case AST_ASSERT:
1266  {
1267  log_assert(children.size() == 2);
1268 
1269  RTLIL::SigSpec check = children[0]->genRTLIL();
1270  log_assert(check.size() == 1);
1271 
1272  RTLIL::SigSpec en = children[1]->genRTLIL();
1273  log_assert(en.size() == 1);
1274 
1275  std::stringstream sstr;
1276  sstr << "$assert$" << filename << ":" << linenum << "$" << (autoidx++);
1277 
1278  RTLIL::Cell *cell = current_module->addCell(sstr.str(), "$assert");
1279  cell->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
1280 
1281  for (auto &attr : attributes) {
1282  if (attr.second->type != AST_CONSTANT)
1283  log_error("Attribute `%s' with non-constant value at %s:%d!\n",
1284  attr.first.c_str(), filename.c_str(), linenum);
1285  cell->attributes[attr.first] = attr.second->asAttrConst();
1286  }
1287 
1288  cell->setPort("\\A", check);
1289  cell->setPort("\\EN", en);
1290  }
1291  break;
1292 
1293  // add entries to current_module->connections for assignments (outside of always blocks)
1294  case AST_ASSIGN:
1295  {
1296  if (children[0]->type == AST_IDENTIFIER && children[0]->id2ast && children[0]->id2ast->type == AST_AUTOWIRE) {
1297  RTLIL::SigSpec right = children[1]->genRTLIL();
1298  RTLIL::SigSpec left = children[0]->genWidthRTLIL(right.size());
1299  current_module->connect(RTLIL::SigSig(left, right));
1300  } else {
1301  RTLIL::SigSpec left = children[0]->genRTLIL();
1302  RTLIL::SigSpec right = children[1]->genWidthRTLIL(left.size());
1303  current_module->connect(RTLIL::SigSig(left, right));
1304  }
1305  }
1306  break;
1307 
1308  // create an RTLIL::Cell for an AST_CELL
1309  case AST_CELL:
1310  {
1311  int port_counter = 0, para_counter = 0;
1312 
1313  if (current_module->count_id(str) != 0)
1314  log_error("Re-definition of cell `%s' at %s:%d!\n",
1315  str.c_str(), filename.c_str(), linenum);
1316 
1317  RTLIL::Cell *cell = current_module->addCell(str, "");
1318  cell->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
1319 
1320  for (auto it = children.begin(); it != children.end(); it++) {
1321  AstNode *child = *it;
1322  if (child->type == AST_CELLTYPE) {
1323  cell->type = child->str;
1324  if (flag_icells && cell->type.substr(0, 2) == "\\$")
1325  cell->type = cell->type.substr(1);
1326  continue;
1327  }
1328  if (child->type == AST_PARASET) {
1329  if (child->children[0]->type != AST_CONSTANT)
1330  log_error("Parameter `%s' with non-constant value at %s:%d!\n",
1331  child->str.c_str(), filename.c_str(), linenum);
1332  if (child->str.size() == 0) {
1333  char buf[100];
1334  snprintf(buf, 100, "$%d", ++para_counter);
1335  cell->parameters[buf] = child->children[0]->asParaConst();
1336  } else {
1337  cell->parameters[child->str] = child->children[0]->asParaConst();
1338  }
1339  continue;
1340  }
1341  if (child->type == AST_ARGUMENT) {
1342  RTLIL::SigSpec sig;
1343  if (child->children.size() > 0)
1344  sig = child->children[0]->genRTLIL();
1345  if (child->str.size() == 0) {
1346  char buf[100];
1347  snprintf(buf, 100, "$%d", ++port_counter);
1348  cell->setPort(buf, sig);
1349  } else {
1350  cell->setPort(child->str, sig);
1351  }
1352  continue;
1353  }
1354  log_abort();
1355  }
1356  for (auto &attr : attributes) {
1357  if (attr.second->type != AST_CONSTANT)
1358  log_error("Attribute `%s' with non-constant value at %s:%d!\n",
1359  attr.first.c_str(), filename.c_str(), linenum);
1360  cell->attributes[attr.first] = attr.second->asAttrConst();
1361  }
1362  }
1363  break;
1364 
1365  // use ProcessGenerator for always blocks
1366  case AST_ALWAYS: {
1367  AstNode *always = this->clone();
1368  ProcessGenerator generator(always);
1370  delete always;
1371  } break;
1372 
1373  case AST_INITIAL: {
1374  AstNode *always = this->clone();
1375  ProcessGenerator generator(always, ignoreThisSignalsInInitial);
1376  delete always;
1377  } break;
1378 
1379  // everything should have been handled above -> print error if not.
1380  default:
1381  for (auto f : log_files)
1382  current_ast->dumpAst(f, "verilog-ast> ");
1383  type_name = type2str(type);
1384  log_error("Don't know how to generate RTLIL code for %s node at %s:%d!\n",
1385  type_name.c_str(), filename.c_str(), linenum);
1386  }
1387 
1388  return RTLIL::SigSpec();
1389 }
1390 
1391 // this is a wrapper for AstNode::genRTLIL() when a specific signal width is requested and/or
1392 // signals must be substituted before beeing used as input values (used by ProcessGenerator)
1393 // note that this is using some global variables to communicate this special settings to AstNode::genRTLIL().
1394 RTLIL::SigSpec AstNode::genWidthRTLIL(int width, const std::map<RTLIL::SigBit, RTLIL::SigBit> *new_subst_ptr)
1395 {
1396  const std::map<RTLIL::SigBit, RTLIL::SigBit> *backup_subst_ptr = genRTLIL_subst_ptr;
1397 
1398  if (new_subst_ptr)
1399  genRTLIL_subst_ptr = new_subst_ptr;
1400 
1401  bool sign_hint = true;
1402  int width_hint = width;
1403  detectSignWidthWorker(width_hint, sign_hint);
1404  RTLIL::SigSpec sig = genRTLIL(width_hint, sign_hint);
1405 
1406  genRTLIL_subst_ptr = backup_subst_ptr;
1407 
1408  if (width >= 0)
1409  sig.extend_u0(width, is_signed);
1410 
1411  return sig;
1412 }
1413 
1415 
std::map< std::string, AstNode * > current_scope
Definition: ast.cc:58
const char * c_str() const
Definition: rtlil.h:178
bool range_valid
Definition: ast.h:158
std::string str() const
Definition: rtlil.h:182
RTLIL::SigSpec genWidthRTLIL(int width, const std::map< RTLIL::SigBit, RTLIL::SigBit > *new_subst_ptr=NULL)
Definition: genrtlil.cc:1394
stackmap< RTLIL::SigBit, RTLIL::SigBit > subst_lvalue_map
Definition: genrtlil.cc:193
std::string stringf(const char *fmt,...)
Definition: yosys.cc:58
RTLIL::SigSpec outputSignals
Definition: genrtlil.cc:177
void log_warning(const char *format,...)
Definition: log.cc:196
RTLIL::Cell * addCell(RTLIL::IdString name, RTLIL::IdString type)
Definition: rtlil.cc:1353
void addChunkActions(std::vector< RTLIL::SigSig > &actions, RTLIL::SigSpec lvalue, RTLIL::SigSpec rvalue, bool inSyncRule=false)
Definition: genrtlil.cc:394
#define YOSYS_NAMESPACE_END
Definition: yosys.h:100
void dumpAst(FILE *f, std::string indent)
Definition: ast.cc:250
RTLIL::SyncType type
Definition: rtlil.h:1144
std::map< RTLIL::IdString, RTLIL::Wire * > wires_
Definition: rtlil.h:595
std::set< RTLIL::SigBit > to_sigbit_set() const
Definition: rtlil.cc:2909
RTLIL_ATTRIBUTE_MEMBERS std::vector< RTLIL::CaseRule * > cases
Definition: rtlil.h:1134
const char * log_signal(const RTLIL::SigSpec &sig, bool autoint)
Definition: log.cc:269
RTLIL::IdString name
Definition: rtlil.h:853
bool upto
Definition: rtlil.h:827
RTLIL::SigSpec genRTLIL(int width_hint=-1, bool sign_hint=false)
Definition: genrtlil.cc:762
void setPort(RTLIL::IdString portname, RTLIL::SigSpec signal)
Definition: rtlil.cc:1789
bool port_input
Definition: rtlil.h:827
RTLIL::SigSpec Sub(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, bool is_signed=false)
std::map< RTLIL::IdString, RTLIL::Memory * > memories
Definition: rtlil.h:601
void(* set_line_num)(int)
Definition: ast.cc:50
std::map< RTLIL::IdString, AstNode * > attributes
Definition: ast.h:152
static void widthExtend(AstNode *that, RTLIL::SigSpec &sig, int width, bool is_signed)
Definition: genrtlil.cc:73
void log_error(const char *format,...)
Definition: log.cc:204
std::set< RTLIL::IdString > avail_parameters
Definition: rtlil.h:600
int port_id
Definition: rtlil.h:826
RTLIL::IdString type
Definition: rtlil.h:854
std::map< RTLIL::IdString, RTLIL::Const > parameters
Definition: rtlil.h:856
void extend_u0(int width, bool is_signed=false)
Definition: rtlil.cc:2612
RTLIL::SigSpec signal
Definition: rtlil.h:1145
int size() const
Definition: rtlil.h:1019
#define log_abort()
Definition: log.h:84
std::map< RTLIL::Wire *, int > new_temp_count
Definition: genrtlil.cc:197
AstNode * current_ast
Definition: ast.cc:57
std::vector< RTLIL::SigSpec > compare
Definition: rtlil.h:1119
void remove_unwanted_lvalue_bits(RTLIL::SigSpec &lhs, RTLIL::SigSpec &rhs)
Definition: genrtlil.cc:288
bool get_bool_attribute(RTLIL::IdString id)
Definition: ast.cc:166
std::string type2str(AstNodeType type)
Definition: ast.cc:66
static RTLIL::SigSpec binop2rtlil(AstNode *that, std::string type, int result_width, const RTLIL::SigSpec &left, const RTLIL::SigSpec &right)
Definition: genrtlil.cc:107
static RTLIL::SigSpec mux2rtlil(AstNode *that, const RTLIL::SigSpec &cond, const RTLIL::SigSpec &left, const RTLIL::SigSpec &right)
Definition: genrtlil.cc:140
bool port_output
Definition: rtlil.h:827
RTLIL::Wire * wire
Definition: rtlil.h:885
void collect_lvalues(RTLIL::SigSpec &reg, AstNode *ast, bool type_eq, bool type_le, bool run_sort_and_unify=true)
Definition: genrtlil.cc:334
RTLIL::CaseRule * current_case
Definition: genrtlil.cc:180
RTLIL::SigSpec ignoreThisSignalsInInitial
Definition: ast.cc:60
void connect(const RTLIL::SigSig &conn)
Definition: rtlil.cc:1278
YOSYS_NAMESPACE_BEGIN std::vector< FILE * > log_files
Definition: log.cc:37
RTLIL::SigSpec signal
Definition: rtlil.h:1132
static RTLIL::SigSpec uniop2rtlil(AstNode *that, std::string type, int result_width, const RTLIL::SigSpec &arg, bool gen_attributes=true)
Definition: genrtlil.cc:44
int range_right
Definition: ast.h:159
bool flag_autowire
Definition: ast.cc:56
int GetSize(RTLIL::Wire *wire)
Definition: yosys.cc:334
const BigUnsigned & check(const BigUnsigned &x)
Definition: testsuite.cc:25
#define log_assert(_assert_expr_)
Definition: log.h:85
bool is_fully_const() const
Definition: rtlil.cc:2763
RTLIL::Wire * addWire(RTLIL::IdString name, int width=1)
Definition: rtlil.cc:1331
#define NEW_ID
Definition: yosys.h:166
void detectSignWidth(int &width_hint, bool &sign_hint, bool *found_real=NULL)
Definition: genrtlil.cc:746
bool flag_noopt
Definition: ast.cc:56
void processAst(AstNode *ast)
Definition: genrtlil.cc:416
AstNodeType type
Definition: ast.h:146
void remove2(const RTLIL::SigSpec &pattern, RTLIL::SigSpec *other)
Definition: rtlil.cc:2353
RTLIL::IdString name
Definition: rtlil.h:825
std::vector< RTLIL::SigSig > actions
Definition: rtlil.h:1146
uint32_t integer
Definition: ast.h:160
void detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *found_real=NULL)
Definition: genrtlil.cc:534
RTLIL::SigSpec new_temp_signal(RTLIL::SigSpec sig)
Definition: genrtlil.cc:305
int range_left
Definition: ast.h:159
std::map< RTLIL::IdString, RTLIL::Process * > processes
Definition: rtlil.h:602
std::string substr(size_t pos=0, size_t len=std::string::npos) const
Definition: rtlil.h:208
virtual size_t count_id(RTLIL::IdString id)
Definition: rtlil.cc:472
void replace(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec &with)
Definition: rtlil.cc:2297
stackmap< RTLIL::SigBit, RTLIL::SigBit > subst_rvalue_map
Definition: genrtlil.cc:187
std::string current_filename
Definition: ast.cc:49
AstNode * clone()
Definition: ast.cc:208
#define NULL
#define YOSYS_NAMESPACE_BEGIN
Definition: yosys.h:99
bool simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, int width_hint, bool sign_hint, bool in_param)
Definition: simplify.cc:50
int as_int(bool is_signed=false) const
Definition: rtlil.cc:2829
std::string filename
Definition: ast.h:175
void log(const char *format,...)
Definition: log.cc:180
RTLIL::SigSpec extract(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec *other=NULL) const
Definition: rtlil.cc:2414
void append(const RTLIL::SigSpec &signal)
Definition: rtlil.cc:2523
bool is_signed
Definition: ast.h:158
void extend(int width, bool is_signed=false)
Definition: rtlil.cc:2593
std::string str
Definition: ast.h:156
int start_offset
Definition: rtlil.h:826
bool flag_nolatches
Definition: ast.cc:56
std::vector< AstNode * > children
Definition: ast.h:149
void removeSignalFromCaseTree(const std::set< RTLIL::SigBit > &pattern, RTLIL::CaseRule *cs)
Definition: genrtlil.cc:382
std::vector< RTLIL::SigSig > actions
Definition: rtlil.h:1120
ProcessGenerator(AstNode *always, RTLIL::SigSpec initSyncSignalsArg=RTLIL::SigSpec())
Definition: genrtlil.cc:202
int linenum
Definition: ast.h:176
const std::map< RTLIL::SigBit, RTLIL::SigBit > * genRTLIL_subst_ptr
Definition: ast.cc:59
AstModule * current_module
Definition: ast.cc:62
bool flag_icells
Definition: ast.cc:56
std::map< RTLIL::SigBit, RTLIL::SigBit > to_sigbit_map(const RTLIL::SigSpec &other) const
Definition: rtlil.cc:2929
std::vector< RTLIL::SwitchRule * > switches
Definition: rtlil.h:1121
std::pair< SigSpec, SigSpec > SigSig
Definition: rtlil.h:71
YOSYS_NAMESPACE_BEGIN int autoidx
Definition: yosys.cc:51
const std::vector< RTLIL::SigChunk > & chunks() const
Definition: rtlil.h:1016
RTLIL::SigSpec initSyncSignals
Definition: genrtlil.cc:175