Merge pull request #2632 from zachjs/width-limit
[yosys.git] / frontends / ast / genrtlil.cc
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
38 YOSYS_NAMESPACE_BEGIN
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, IdString type, int result_width, const RTLIL::SigSpec &arg, bool gen_attributes = true)
45 {
46 IdString name = stringf("%s$%s:%d$%d", type.c_str(), that->filename.c_str(), that->location.first_line, autoidx++);
47 RTLIL::Cell *cell = current_module->addCell(name, type);
48 set_src_attr(cell, that);
49
50 RTLIL::Wire *wire = current_module->addWire(cell->name.str() + "_Y", result_width);
51 set_src_attr(wire, that);
52 wire->is_signed = that->is_signed;
53
54 if (gen_attributes)
55 for (auto &attr : that->attributes) {
56 if (attr.second->type != AST_CONSTANT)
57 log_file_error(that->filename, that->location.first_line, "Attribute `%s' with non-constant value!\n", attr.first.c_str());
58 cell->attributes[attr.first] = attr.second->asAttrConst();
59 }
60
61 cell->parameters[ID::A_SIGNED] = RTLIL::Const(that->children[0]->is_signed);
62 cell->parameters[ID::A_WIDTH] = RTLIL::Const(arg.size());
63 cell->setPort(ID::A, arg);
64
65 cell->parameters[ID::Y_WIDTH] = result_width;
66 cell->setPort(ID::Y, wire);
67 return wire;
68 }
69
70 // helper function for extending bit width (preferred over SigSpec::extend() because of correct undef propagation in ConstEval)
71 static void widthExtend(AstNode *that, RTLIL::SigSpec &sig, int width, bool is_signed)
72 {
73 if (width <= sig.size()) {
74 sig.extend_u0(width, is_signed);
75 return;
76 }
77
78 IdString name = stringf("$extend$%s:%d$%d", that->filename.c_str(), that->location.first_line, autoidx++);
79 RTLIL::Cell *cell = current_module->addCell(name, ID($pos));
80 set_src_attr(cell, that);
81
82 RTLIL::Wire *wire = current_module->addWire(cell->name.str() + "_Y", width);
83 set_src_attr(wire, that);
84 wire->is_signed = that->is_signed;
85
86 if (that != NULL)
87 for (auto &attr : that->attributes) {
88 if (attr.second->type != AST_CONSTANT)
89 log_file_error(that->filename, that->location.first_line, "Attribute `%s' with non-constant value!\n", attr.first.c_str());
90 cell->attributes[attr.first] = attr.second->asAttrConst();
91 }
92
93 cell->parameters[ID::A_SIGNED] = RTLIL::Const(is_signed);
94 cell->parameters[ID::A_WIDTH] = RTLIL::Const(sig.size());
95 cell->setPort(ID::A, sig);
96
97 cell->parameters[ID::Y_WIDTH] = width;
98 cell->setPort(ID::Y, wire);
99 sig = wire;
100 }
101
102 // helper function for creating RTLIL code for binary operations
103 static RTLIL::SigSpec binop2rtlil(AstNode *that, IdString type, int result_width, const RTLIL::SigSpec &left, const RTLIL::SigSpec &right)
104 {
105 IdString name = stringf("%s$%s:%d$%d", type.c_str(), that->filename.c_str(), that->location.first_line, autoidx++);
106 RTLIL::Cell *cell = current_module->addCell(name, type);
107 set_src_attr(cell, that);
108
109 RTLIL::Wire *wire = current_module->addWire(cell->name.str() + "_Y", result_width);
110 set_src_attr(wire, that);
111 wire->is_signed = that->is_signed;
112
113 for (auto &attr : that->attributes) {
114 if (attr.second->type != AST_CONSTANT)
115 log_file_error(that->filename, that->location.first_line, "Attribute `%s' with non-constant value!\n", attr.first.c_str());
116 cell->attributes[attr.first] = attr.second->asAttrConst();
117 }
118
119 cell->parameters[ID::A_SIGNED] = RTLIL::Const(that->children[0]->is_signed);
120 cell->parameters[ID::B_SIGNED] = RTLIL::Const(that->children[1]->is_signed);
121
122 cell->parameters[ID::A_WIDTH] = RTLIL::Const(left.size());
123 cell->parameters[ID::B_WIDTH] = RTLIL::Const(right.size());
124
125 cell->setPort(ID::A, left);
126 cell->setPort(ID::B, right);
127
128 cell->parameters[ID::Y_WIDTH] = result_width;
129 cell->setPort(ID::Y, wire);
130 return wire;
131 }
132
133 // helper function for creating RTLIL code for multiplexers
134 static RTLIL::SigSpec mux2rtlil(AstNode *that, const RTLIL::SigSpec &cond, const RTLIL::SigSpec &left, const RTLIL::SigSpec &right)
135 {
136 log_assert(cond.size() == 1);
137
138 std::stringstream sstr;
139 sstr << "$ternary$" << that->filename << ":" << that->location.first_line << "$" << (autoidx++);
140
141 RTLIL::Cell *cell = current_module->addCell(sstr.str(), ID($mux));
142 set_src_attr(cell, that);
143
144 RTLIL::Wire *wire = current_module->addWire(cell->name.str() + "_Y", left.size());
145 set_src_attr(wire, that);
146 wire->is_signed = that->is_signed;
147
148 for (auto &attr : that->attributes) {
149 if (attr.second->type != AST_CONSTANT)
150 log_file_error(that->filename, that->location.first_line, "Attribute `%s' with non-constant value!\n", attr.first.c_str());
151 cell->attributes[attr.first] = attr.second->asAttrConst();
152 }
153
154 cell->parameters[ID::WIDTH] = RTLIL::Const(left.size());
155
156 cell->setPort(ID::A, right);
157 cell->setPort(ID::B, left);
158 cell->setPort(ID::S, cond);
159 cell->setPort(ID::Y, wire);
160
161 return wire;
162 }
163
164 // helper class for rewriting simple lookahead references in AST always blocks
165 struct AST_INTERNAL::LookaheadRewriter
166 {
167 dict<IdString, pair<AstNode*, AstNode*>> lookaheadids;
168
169 void collect_lookaheadids(AstNode *node)
170 {
171 if (node->lookahead) {
172 log_assert(node->type == AST_IDENTIFIER);
173 if (!lookaheadids.count(node->str)) {
174 AstNode *wire = new AstNode(AST_WIRE);
175 for (auto c : node->id2ast->children)
176 wire->children.push_back(c->clone());
177 wire->str = stringf("$lookahead%s$%d", node->str.c_str(), autoidx++);
178 wire->attributes[ID::nosync] = AstNode::mkconst_int(1, false);
179 wire->is_logic = true;
180 while (wire->simplify(true, false, false, 1, -1, false, false)) { }
181 current_ast_mod->children.push_back(wire);
182 lookaheadids[node->str] = make_pair(node->id2ast, wire);
183 wire->genRTLIL();
184 }
185 }
186
187 for (auto child : node->children)
188 collect_lookaheadids(child);
189 }
190
191 bool has_lookaheadids(AstNode *node)
192 {
193 if (node->type == AST_IDENTIFIER && lookaheadids.count(node->str) != 0)
194 return true;
195
196 for (auto child : node->children)
197 if (has_lookaheadids(child))
198 return true;
199
200 return false;
201 }
202
203 bool has_nonlookaheadids(AstNode *node)
204 {
205 if (node->type == AST_IDENTIFIER && lookaheadids.count(node->str) == 0)
206 return true;
207
208 for (auto child : node->children)
209 if (has_nonlookaheadids(child))
210 return true;
211
212 return false;
213 }
214
215 void rewrite_lookaheadids(AstNode *node, bool lhs = false)
216 {
217 if (node->type == AST_ASSIGN_LE)
218 {
219 if (has_lookaheadids(node->children[0]))
220 {
221 if (has_nonlookaheadids(node->children[0]))
222 log_error("incompatible mix of lookahead and non-lookahead IDs in LHS expression.\n");
223
224 rewrite_lookaheadids(node->children[0], true);
225 node->type = AST_ASSIGN_EQ;
226 }
227
228 rewrite_lookaheadids(node->children[1], lhs);
229 return;
230 }
231
232 if (node->type == AST_IDENTIFIER && (node->lookahead || lhs)) {
233 AstNode *newwire = lookaheadids.at(node->str).second;
234 node->str = newwire->str;
235 node->id2ast = newwire;
236 lhs = false;
237 }
238
239 for (auto child : node->children)
240 rewrite_lookaheadids(child, lhs);
241 }
242
243 LookaheadRewriter(AstNode *top)
244 {
245 // top->dumpAst(NULL, "REWRITE-BEFORE> ");
246 // top->dumpVlog(NULL, "REWRITE-BEFORE> ");
247
248 AstNode *block = nullptr;
249
250 for (auto c : top->children)
251 if (c->type == AST_BLOCK) {
252 log_assert(block == nullptr);
253 block = c;
254 }
255 log_assert(block != nullptr);
256
257 collect_lookaheadids(block);
258 rewrite_lookaheadids(block);
259
260 for (auto it : lookaheadids)
261 {
262 AstNode *ref_orig = new AstNode(AST_IDENTIFIER);
263 ref_orig->str = it.second.first->str;
264 ref_orig->id2ast = it.second.first;
265 ref_orig->was_checked = true;
266
267 AstNode *ref_temp = new AstNode(AST_IDENTIFIER);
268 ref_temp->str = it.second.second->str;
269 ref_temp->id2ast = it.second.second;
270 ref_temp->was_checked = true;
271
272 AstNode *init_assign = new AstNode(AST_ASSIGN_EQ, ref_temp->clone(), ref_orig->clone());
273 AstNode *final_assign = new AstNode(AST_ASSIGN_LE, ref_orig, ref_temp);
274
275 block->children.insert(block->children.begin(), init_assign);
276 block->children.push_back(final_assign);
277 }
278
279 // top->dumpAst(NULL, "REWRITE-AFTER> ");
280 // top->dumpVlog(NULL, "REWRITE-AFTER> ");
281 }
282 };
283
284 // helper class for converting AST always nodes to RTLIL processes
285 struct AST_INTERNAL::ProcessGenerator
286 {
287 // input and output structures
288 AstNode *always;
289 RTLIL::SigSpec initSyncSignals;
290 RTLIL::Process *proc;
291 RTLIL::SigSpec outputSignals;
292
293 // This always points to the RTLIL::CaseRule being filled at the moment
294 RTLIL::CaseRule *current_case;
295
296 // This map contains the replacement pattern to be used in the right hand side
297 // of an assignment. E.g. in the code "foo = bar; foo = func(foo);" the foo in the right
298 // hand side of the 2nd assignment needs to be replace with the temporary signal holding
299 // the value assigned in the first assignment. So when the first assignment is processed
300 // the according information is appended to subst_rvalue_from and subst_rvalue_to.
301 stackmap<RTLIL::SigBit, RTLIL::SigBit> subst_rvalue_map;
302
303 // This map contains the replacement pattern to be used in the left hand side
304 // of an assignment. E.g. in the code "always @(posedge clk) foo <= bar" the signal bar
305 // should not be connected to the signal foo. Instead it must be connected to the temporary
306 // signal that is used as input for the register that drives the signal foo.
307 stackmap<RTLIL::SigBit, RTLIL::SigBit> subst_lvalue_map;
308
309 // The code here generates a number of temporary signal for each output register. This
310 // map helps generating nice numbered names for all this temporary signals.
311 std::map<RTLIL::Wire*, int> new_temp_count;
312
313 // Buffer for generating the init action
314 RTLIL::SigSpec init_lvalue, init_rvalue;
315
316 ProcessGenerator(AstNode *always, RTLIL::SigSpec initSyncSignalsArg = RTLIL::SigSpec()) : always(always), initSyncSignals(initSyncSignalsArg)
317 {
318 // rewrite lookahead references
319 LookaheadRewriter la_rewriter(always);
320
321 // generate process and simple root case
322 proc = new RTLIL::Process;
323 set_src_attr(proc, always);
324 proc->name = stringf("$proc$%s:%d$%d", always->filename.c_str(), always->location.first_line, autoidx++);
325 for (auto &attr : always->attributes) {
326 if (attr.second->type != AST_CONSTANT)
327 log_file_error(always->filename, always->location.first_line, "Attribute `%s' with non-constant value!\n",
328 attr.first.c_str());
329 proc->attributes[attr.first] = attr.second->asAttrConst();
330 }
331 current_module->processes[proc->name] = proc;
332 current_case = &proc->root_case;
333
334 // create initial temporary signal for all output registers
335 RTLIL::SigSpec subst_lvalue_from, subst_lvalue_to;
336 collect_lvalues(subst_lvalue_from, always, true, true);
337 subst_lvalue_to = new_temp_signal(subst_lvalue_from);
338 subst_lvalue_map = subst_lvalue_from.to_sigbit_map(subst_lvalue_to);
339
340 bool found_global_syncs = false;
341 bool found_anyedge_syncs = false;
342 for (auto child : always->children)
343 {
344 if ((child->type == AST_POSEDGE || child->type == AST_NEGEDGE) && GetSize(child->children) == 1 && child->children.at(0)->type == AST_IDENTIFIER &&
345 child->children.at(0)->id2ast && child->children.at(0)->id2ast->type == AST_WIRE && child->children.at(0)->id2ast->get_bool_attribute(ID::gclk)) {
346 found_global_syncs = true;
347 }
348 if (child->type == AST_EDGE) {
349 if (GetSize(child->children) == 1 && child->children.at(0)->type == AST_IDENTIFIER && child->children.at(0)->str == "\\$global_clock")
350 found_global_syncs = true;
351 else
352 found_anyedge_syncs = true;
353 }
354 }
355
356 if (found_anyedge_syncs) {
357 if (found_global_syncs)
358 log_file_error(always->filename, always->location.first_line, "Found non-synthesizable event list!\n");
359 log("Note: Assuming pure combinatorial block at %s in\n", always->loc_string().c_str());
360 log("compliance with IEC 62142(E):2005 / IEEE Std. 1364.1(E):2002. Recommending\n");
361 log("use of @* instead of @(...) for better match of synthesis and simulation.\n");
362 }
363
364 // create syncs for the process
365 bool found_clocked_sync = false;
366 for (auto child : always->children)
367 if (child->type == AST_POSEDGE || child->type == AST_NEGEDGE) {
368 if (GetSize(child->children) == 1 && child->children.at(0)->type == AST_IDENTIFIER && child->children.at(0)->id2ast &&
369 child->children.at(0)->id2ast->type == AST_WIRE && child->children.at(0)->id2ast->get_bool_attribute(ID::gclk))
370 continue;
371 found_clocked_sync = true;
372 if (found_global_syncs || found_anyedge_syncs)
373 log_file_error(always->filename, always->location.first_line, "Found non-synthesizable event list!\n");
374 RTLIL::SyncRule *syncrule = new RTLIL::SyncRule;
375 syncrule->type = child->type == AST_POSEDGE ? RTLIL::STp : RTLIL::STn;
376 syncrule->signal = child->children[0]->genRTLIL();
377 if (GetSize(syncrule->signal) != 1)
378 log_file_error(always->filename, always->location.first_line, "Found posedge/negedge event on a signal that is not 1 bit wide!\n");
379 addChunkActions(syncrule->actions, subst_lvalue_from, subst_lvalue_to, true);
380 proc->syncs.push_back(syncrule);
381 }
382 if (proc->syncs.empty()) {
383 RTLIL::SyncRule *syncrule = new RTLIL::SyncRule;
384 syncrule->type = found_global_syncs ? RTLIL::STg : RTLIL::STa;
385 syncrule->signal = RTLIL::SigSpec();
386 addChunkActions(syncrule->actions, subst_lvalue_from, subst_lvalue_to, true);
387 proc->syncs.push_back(syncrule);
388 }
389
390 // create initial assignments for the temporary signals
391 if ((flag_nolatches || always->get_bool_attribute(ID::nolatches) || current_module->get_bool_attribute(ID::nolatches)) && !found_clocked_sync) {
392 subst_rvalue_map = subst_lvalue_from.to_sigbit_dict(RTLIL::SigSpec(RTLIL::State::Sx, GetSize(subst_lvalue_from)));
393 } else {
394 addChunkActions(current_case->actions, subst_lvalue_to, subst_lvalue_from);
395 }
396
397 // process the AST
398 for (auto child : always->children)
399 if (child->type == AST_BLOCK)
400 processAst(child);
401
402 if (initSyncSignals.size() > 0)
403 {
404 RTLIL::SyncRule *sync = new RTLIL::SyncRule;
405 sync->type = RTLIL::SyncType::STi;
406 proc->syncs.push_back(sync);
407
408 log_assert(init_lvalue.size() == init_rvalue.size());
409
410 int offset = 0;
411 for (auto &init_lvalue_c : init_lvalue.chunks()) {
412 RTLIL::SigSpec lhs = init_lvalue_c;
413 RTLIL::SigSpec rhs = init_rvalue.extract(offset, init_lvalue_c.width);
414 remove_unwanted_lvalue_bits(lhs, rhs);
415 sync->actions.push_back(RTLIL::SigSig(lhs, rhs));
416 offset += lhs.size();
417 }
418 }
419
420 outputSignals = RTLIL::SigSpec(subst_lvalue_from);
421 }
422
423 void remove_unwanted_lvalue_bits(RTLIL::SigSpec &lhs, RTLIL::SigSpec &rhs)
424 {
425 RTLIL::SigSpec new_lhs, new_rhs;
426
427 log_assert(GetSize(lhs) == GetSize(rhs));
428 for (int i = 0; i < GetSize(lhs); i++) {
429 if (lhs[i].wire == nullptr)
430 continue;
431 new_lhs.append(lhs[i]);
432 new_rhs.append(rhs[i]);
433 }
434
435 lhs = new_lhs;
436 rhs = new_rhs;
437 }
438
439 // create new temporary signals
440 RTLIL::SigSpec new_temp_signal(RTLIL::SigSpec sig)
441 {
442 std::vector<RTLIL::SigChunk> chunks = sig.chunks();
443
444 for (int i = 0; i < GetSize(chunks); i++)
445 {
446 RTLIL::SigChunk &chunk = chunks[i];
447 if (chunk.wire == NULL)
448 continue;
449
450 std::string wire_name;
451 do {
452 wire_name = stringf("$%d%s[%d:%d]", new_temp_count[chunk.wire]++,
453 chunk.wire->name.c_str(), chunk.width+chunk.offset-1, chunk.offset);;
454 if (chunk.wire->name.str().find('$') != std::string::npos)
455 wire_name += stringf("$%d", autoidx++);
456 } while (current_module->wires_.count(wire_name) > 0);
457
458 RTLIL::Wire *wire = current_module->addWire(wire_name, chunk.width);
459 set_src_attr(wire, always);
460
461 chunk.wire = wire;
462 chunk.offset = 0;
463 }
464
465 return chunks;
466 }
467
468 // recursively traverse the AST and collect all assigned signals
469 void collect_lvalues(RTLIL::SigSpec &reg, AstNode *ast, bool type_eq, bool type_le, bool run_sort_and_unify = true)
470 {
471 switch (ast->type)
472 {
473 case AST_CASE:
474 for (auto child : ast->children)
475 if (child != ast->children[0]) {
476 log_assert(child->type == AST_COND || child->type == AST_CONDX || child->type == AST_CONDZ);
477 collect_lvalues(reg, child, type_eq, type_le, false);
478 }
479 break;
480
481 case AST_COND:
482 case AST_CONDX:
483 case AST_CONDZ:
484 case AST_ALWAYS:
485 case AST_INITIAL:
486 for (auto child : ast->children)
487 if (child->type == AST_BLOCK)
488 collect_lvalues(reg, child, type_eq, type_le, false);
489 break;
490
491 case AST_BLOCK:
492 for (auto child : ast->children) {
493 if (child->type == AST_ASSIGN_EQ && type_eq)
494 reg.append(child->children[0]->genRTLIL());
495 if (child->type == AST_ASSIGN_LE && type_le)
496 reg.append(child->children[0]->genRTLIL());
497 if (child->type == AST_CASE || child->type == AST_BLOCK)
498 collect_lvalues(reg, child, type_eq, type_le, false);
499 }
500 break;
501
502 default:
503 log_abort();
504 }
505
506 if (run_sort_and_unify) {
507 std::set<RTLIL::SigBit> sorted_reg;
508 for (auto bit : reg)
509 if (bit.wire)
510 sorted_reg.insert(bit);
511 reg = RTLIL::SigSpec(sorted_reg);
512 }
513 }
514
515 // remove all assignments to the given signal pattern in a case and all its children.
516 // e.g. when the last statement in the code "a = 23; if (b) a = 42; a = 0;" is processed this
517 // function is called to clean up the first two assignments as they are overwritten by
518 // the third assignment.
519 void removeSignalFromCaseTree(const RTLIL::SigSpec &pattern, RTLIL::CaseRule *cs)
520 {
521 for (auto it = cs->actions.begin(); it != cs->actions.end(); it++)
522 it->first.remove2(pattern, &it->second);
523
524 for (auto it = cs->switches.begin(); it != cs->switches.end(); it++)
525 for (auto it2 = (*it)->cases.begin(); it2 != (*it)->cases.end(); it2++)
526 removeSignalFromCaseTree(pattern, *it2);
527 }
528
529 // add an assignment (aka "action") but split it up in chunks. this way huge assignments
530 // are avoided and the generated $mux cells have a more "natural" size.
531 void addChunkActions(std::vector<RTLIL::SigSig> &actions, RTLIL::SigSpec lvalue, RTLIL::SigSpec rvalue, bool inSyncRule = false)
532 {
533 if (inSyncRule && initSyncSignals.size() > 0) {
534 init_lvalue.append(lvalue.extract(initSyncSignals));
535 init_rvalue.append(lvalue.extract(initSyncSignals, &rvalue));
536 lvalue.remove2(initSyncSignals, &rvalue);
537 }
538 log_assert(lvalue.size() == rvalue.size());
539
540 int offset = 0;
541 for (auto &lvalue_c : lvalue.chunks()) {
542 RTLIL::SigSpec lhs = lvalue_c;
543 RTLIL::SigSpec rhs = rvalue.extract(offset, lvalue_c.width);
544 if (inSyncRule && lvalue_c.wire && lvalue_c.wire->get_bool_attribute(ID::nosync))
545 rhs = RTLIL::SigSpec(RTLIL::State::Sx, rhs.size());
546 remove_unwanted_lvalue_bits(lhs, rhs);
547 actions.push_back(RTLIL::SigSig(lhs, rhs));
548 offset += lhs.size();
549 }
550 }
551
552 // recursively process the AST and fill the RTLIL::Process
553 void processAst(AstNode *ast)
554 {
555 switch (ast->type)
556 {
557 case AST_BLOCK:
558 for (auto child : ast->children)
559 processAst(child);
560 break;
561
562 case AST_ASSIGN_EQ:
563 case AST_ASSIGN_LE:
564 {
565 RTLIL::SigSpec unmapped_lvalue = ast->children[0]->genRTLIL(), lvalue = unmapped_lvalue;
566 RTLIL::SigSpec rvalue = ast->children[1]->genWidthRTLIL(lvalue.size(), &subst_rvalue_map.stdmap());
567
568 pool<SigBit> lvalue_sigbits;
569 for (int i = 0; i < GetSize(lvalue); i++) {
570 if (lvalue_sigbits.count(lvalue[i]) > 0) {
571 unmapped_lvalue.remove(i);
572 lvalue.remove(i);
573 rvalue.remove(i--);
574 } else
575 lvalue_sigbits.insert(lvalue[i]);
576 }
577
578 lvalue.replace(subst_lvalue_map.stdmap());
579
580 if (ast->type == AST_ASSIGN_EQ) {
581 for (int i = 0; i < GetSize(unmapped_lvalue); i++)
582 subst_rvalue_map.set(unmapped_lvalue[i], rvalue[i]);
583 }
584
585 removeSignalFromCaseTree(lvalue, current_case);
586 remove_unwanted_lvalue_bits(lvalue, rvalue);
587 current_case->actions.push_back(RTLIL::SigSig(lvalue, rvalue));
588 }
589 break;
590
591 case AST_CASE:
592 {
593 RTLIL::SwitchRule *sw = new RTLIL::SwitchRule;
594 set_src_attr(sw, ast);
595 sw->signal = ast->children[0]->genWidthRTLIL(-1, &subst_rvalue_map.stdmap());
596 current_case->switches.push_back(sw);
597
598 for (auto &attr : ast->attributes) {
599 if (attr.second->type != AST_CONSTANT)
600 log_file_error(ast->filename, ast->location.first_line, "Attribute `%s' with non-constant value!\n", attr.first.c_str());
601 sw->attributes[attr.first] = attr.second->asAttrConst();
602 }
603
604 RTLIL::SigSpec this_case_eq_lvalue;
605 collect_lvalues(this_case_eq_lvalue, ast, true, false);
606
607 RTLIL::SigSpec this_case_eq_ltemp = new_temp_signal(this_case_eq_lvalue);
608
609 RTLIL::SigSpec this_case_eq_rvalue = this_case_eq_lvalue;
610 this_case_eq_rvalue.replace(subst_rvalue_map.stdmap());
611
612 RTLIL::CaseRule *default_case = NULL;
613 RTLIL::CaseRule *last_generated_case = NULL;
614 for (auto child : ast->children)
615 {
616 if (child == ast->children[0])
617 continue;
618 log_assert(child->type == AST_COND || child->type == AST_CONDX || child->type == AST_CONDZ);
619
620 subst_lvalue_map.save();
621 subst_rvalue_map.save();
622
623 for (int i = 0; i < GetSize(this_case_eq_lvalue); i++)
624 subst_lvalue_map.set(this_case_eq_lvalue[i], this_case_eq_ltemp[i]);
625
626 RTLIL::CaseRule *backup_case = current_case;
627 current_case = new RTLIL::CaseRule;
628 set_src_attr(current_case, child);
629 last_generated_case = current_case;
630 addChunkActions(current_case->actions, this_case_eq_ltemp, this_case_eq_rvalue);
631 for (auto node : child->children) {
632 if (node->type == AST_DEFAULT)
633 default_case = current_case;
634 else if (node->type == AST_BLOCK)
635 processAst(node);
636 else
637 current_case->compare.push_back(node->genWidthRTLIL(sw->signal.size(), &subst_rvalue_map.stdmap()));
638 }
639 if (default_case != current_case)
640 sw->cases.push_back(current_case);
641 else
642 log_assert(current_case->compare.size() == 0);
643 current_case = backup_case;
644
645 subst_lvalue_map.restore();
646 subst_rvalue_map.restore();
647 }
648
649 if (last_generated_case != NULL && ast->get_bool_attribute(ID::full_case) && default_case == NULL) {
650 #if 0
651 // this is a valid transformation, but as optimization it is premature.
652 // better: add a default case that assigns 'x' to everything, and let later
653 // optimizations take care of the rest
654 last_generated_case->compare.clear();
655 #else
656 default_case = new RTLIL::CaseRule;
657 addChunkActions(default_case->actions, this_case_eq_ltemp, SigSpec(State::Sx, GetSize(this_case_eq_rvalue)));
658 sw->cases.push_back(default_case);
659 #endif
660 } else {
661 if (default_case == NULL) {
662 default_case = new RTLIL::CaseRule;
663 addChunkActions(default_case->actions, this_case_eq_ltemp, this_case_eq_rvalue);
664 }
665 sw->cases.push_back(default_case);
666 }
667
668 for (int i = 0; i < GetSize(this_case_eq_lvalue); i++)
669 subst_rvalue_map.set(this_case_eq_lvalue[i], this_case_eq_ltemp[i]);
670
671 this_case_eq_lvalue.replace(subst_lvalue_map.stdmap());
672 removeSignalFromCaseTree(this_case_eq_lvalue, current_case);
673 addChunkActions(current_case->actions, this_case_eq_lvalue, this_case_eq_ltemp);
674 }
675 break;
676
677 case AST_WIRE:
678 log_file_error(ast->filename, ast->location.first_line, "Found reg declaration in block without label!\n");
679 break;
680
681 case AST_ASSIGN:
682 log_file_error(ast->filename, ast->location.first_line, "Found continous assignment in always/initial block!\n");
683 break;
684
685 case AST_PARAMETER:
686 case AST_LOCALPARAM:
687 log_file_error(ast->filename, ast->location.first_line, "Found parameter declaration in block without label!\n");
688 break;
689
690 case AST_NONE:
691 case AST_TCALL:
692 case AST_FOR:
693 break;
694
695 default:
696 // ast->dumpAst(NULL, "ast> ");
697 // current_ast_mod->dumpAst(NULL, "mod> ");
698 log_abort();
699 }
700 }
701 };
702
703 // detect sign and width of an expression
704 void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *found_real)
705 {
706 std::string type_name;
707 bool sub_sign_hint = true;
708 int sub_width_hint = -1;
709 int this_width = 0;
710 AstNode *range = NULL;
711 AstNode *id_ast = NULL;
712
713 bool local_found_real = false;
714 if (found_real == NULL)
715 found_real = &local_found_real;
716
717 switch (type)
718 {
719 case AST_NONE:
720 // unallocated enum, ignore
721 break;
722 case AST_CONSTANT:
723 width_hint = max(width_hint, int(bits.size()));
724 if (!is_signed)
725 sign_hint = false;
726 break;
727
728 case AST_REALVALUE:
729 *found_real = true;
730 width_hint = max(width_hint, 32);
731 break;
732
733 case AST_IDENTIFIER:
734 id_ast = id2ast;
735 if (id_ast == NULL && current_scope.count(str))
736 id_ast = current_scope.at(str);
737 if (!id_ast)
738 log_file_error(filename, location.first_line, "Failed to resolve identifier %s for width detection!\n", str.c_str());
739 if (id_ast->type == AST_PARAMETER || id_ast->type == AST_LOCALPARAM || id_ast->type == AST_ENUM_ITEM) {
740 if (id_ast->children.size() > 1 && id_ast->children[1]->range_valid) {
741 this_width = id_ast->children[1]->range_left - id_ast->children[1]->range_right + 1;
742 } else
743 if (id_ast->children[0]->type != AST_CONSTANT)
744 while (id_ast->simplify(true, false, false, 1, -1, false, true)) { }
745 if (id_ast->children[0]->type == AST_CONSTANT)
746 this_width = id_ast->children[0]->bits.size();
747 else
748 log_file_error(filename, location.first_line, "Failed to detect width for parameter %s!\n", str.c_str());
749 if (children.size() != 0)
750 range = children[0];
751 } else if (id_ast->type == AST_WIRE || id_ast->type == AST_AUTOWIRE) {
752 if (!id_ast->range_valid) {
753 if (id_ast->type == AST_AUTOWIRE)
754 this_width = 1;
755 else {
756 // current_ast_mod->dumpAst(NULL, "mod> ");
757 // log("---\n");
758 // id_ast->dumpAst(NULL, "decl> ");
759 // dumpAst(NULL, "ref> ");
760 log_file_error(filename, location.first_line, "Failed to detect width of signal access `%s'!\n", str.c_str());
761 }
762 } else {
763 this_width = id_ast->range_left - id_ast->range_right + 1;
764 if (children.size() != 0)
765 range = children[0];
766 }
767 } else if (id_ast->type == AST_GENVAR) {
768 this_width = 32;
769 } else if (id_ast->type == AST_MEMORY) {
770 if (!id_ast->children[0]->range_valid)
771 log_file_error(filename, location.first_line, "Failed to detect width of memory access `%s'!\n", str.c_str());
772 this_width = id_ast->children[0]->range_left - id_ast->children[0]->range_right + 1;
773 if (children.size() > 1)
774 range = children[1];
775 } else
776 log_file_error(filename, location.first_line, "Failed to detect width for identifier %s!\n", str.c_str());
777 if (range) {
778 if (range->children.size() == 1)
779 this_width = 1;
780 else if (!range->range_valid) {
781 AstNode *left_at_zero_ast = children[0]->children[0]->clone();
782 AstNode *right_at_zero_ast = children[0]->children.size() >= 2 ? children[0]->children[1]->clone() : left_at_zero_ast->clone();
783 while (left_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { }
784 while (right_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { }
785 if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT)
786 log_file_error(filename, location.first_line, "Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str());
787 this_width = abs(int(left_at_zero_ast->integer - right_at_zero_ast->integer)) + 1;
788 delete left_at_zero_ast;
789 delete right_at_zero_ast;
790 } else
791 this_width = range->range_left - range->range_right + 1;
792 sign_hint = false;
793 }
794 width_hint = max(width_hint, this_width);
795 if (!id_ast->is_signed)
796 sign_hint = false;
797 break;
798
799 case AST_TO_BITS:
800 while (children[0]->simplify(true, false, false, 1, -1, false, false) == true) { }
801 if (children[0]->type != AST_CONSTANT)
802 log_file_error(filename, location.first_line, "Left operand of tobits expression is not constant!\n");
803 children[1]->detectSignWidthWorker(sub_width_hint, sign_hint);
804 width_hint = max(width_hint, children[0]->bitsAsConst().as_int());
805 break;
806
807 case AST_TO_SIGNED:
808 children.at(0)->detectSignWidthWorker(width_hint, sub_sign_hint);
809 break;
810
811 case AST_TO_UNSIGNED:
812 children.at(0)->detectSignWidthWorker(width_hint, sub_sign_hint);
813 sign_hint = false;
814 break;
815
816 case AST_SELFSZ:
817 sub_width_hint = 0;
818 children.at(0)->detectSignWidthWorker(sub_width_hint, sign_hint);
819 break;
820
821 case AST_CAST_SIZE:
822 while (children.at(0)->simplify(true, false, false, 1, -1, false, false)) { }
823 if (children.at(0)->type != AST_CONSTANT)
824 log_file_error(filename, location.first_line, "Static cast with non constant expression!\n");
825 children.at(1)->detectSignWidthWorker(width_hint, sign_hint);
826 width_hint = children.at(0)->bitsAsConst().as_int();
827 if (width_hint <= 0)
828 log_file_error(filename, location.first_line, "Static cast with zero or negative size!\n");
829 break;
830
831 case AST_CONCAT:
832 for (auto child : children) {
833 sub_width_hint = 0;
834 sub_sign_hint = true;
835 child->detectSignWidthWorker(sub_width_hint, sub_sign_hint);
836 this_width += sub_width_hint;
837 }
838 width_hint = max(width_hint, this_width);
839 sign_hint = false;
840 break;
841
842 case AST_REPLICATE:
843 while (children[0]->simplify(true, false, false, 1, -1, false, true) == true) { }
844 if (children[0]->type != AST_CONSTANT)
845 log_file_error(filename, location.first_line, "Left operand of replicate expression is not constant!\n");
846 children[1]->detectSignWidthWorker(sub_width_hint, sub_sign_hint);
847 width_hint = max(width_hint, children[0]->bitsAsConst().as_int() * sub_width_hint);
848 sign_hint = false;
849 break;
850
851 case AST_NEG:
852 case AST_BIT_NOT:
853 case AST_POS:
854 children[0]->detectSignWidthWorker(width_hint, sign_hint, found_real);
855 break;
856
857 case AST_BIT_AND:
858 case AST_BIT_OR:
859 case AST_BIT_XOR:
860 case AST_BIT_XNOR:
861 for (auto child : children)
862 child->detectSignWidthWorker(width_hint, sign_hint, found_real);
863 break;
864
865 case AST_REDUCE_AND:
866 case AST_REDUCE_OR:
867 case AST_REDUCE_XOR:
868 case AST_REDUCE_XNOR:
869 case AST_REDUCE_BOOL:
870 width_hint = max(width_hint, 1);
871 sign_hint = false;
872 break;
873
874 case AST_SHIFT_LEFT:
875 case AST_SHIFT_RIGHT:
876 case AST_SHIFT_SLEFT:
877 case AST_SHIFT_SRIGHT:
878 case AST_SHIFTX:
879 case AST_SHIFT:
880 case AST_POW:
881 children[0]->detectSignWidthWorker(width_hint, sign_hint, found_real);
882 break;
883
884 case AST_LT:
885 case AST_LE:
886 case AST_EQ:
887 case AST_NE:
888 case AST_EQX:
889 case AST_NEX:
890 case AST_GE:
891 case AST_GT:
892 width_hint = max(width_hint, 1);
893 sign_hint = false;
894 break;
895
896 case AST_ADD:
897 case AST_SUB:
898 case AST_MUL:
899 case AST_DIV:
900 case AST_MOD:
901 for (auto child : children)
902 child->detectSignWidthWorker(width_hint, sign_hint, found_real);
903 break;
904
905 case AST_LOGIC_AND:
906 case AST_LOGIC_OR:
907 case AST_LOGIC_NOT:
908 width_hint = max(width_hint, 1);
909 sign_hint = false;
910 break;
911
912 case AST_TERNARY:
913 children.at(1)->detectSignWidthWorker(width_hint, sign_hint, found_real);
914 children.at(2)->detectSignWidthWorker(width_hint, sign_hint, found_real);
915 break;
916
917 case AST_MEMRD:
918 if (!id2ast->is_signed)
919 sign_hint = false;
920 if (!id2ast->children[0]->range_valid)
921 log_file_error(filename, location.first_line, "Failed to detect width of memory access `%s'!\n", str.c_str());
922 this_width = id2ast->children[0]->range_left - id2ast->children[0]->range_right + 1;
923 width_hint = max(width_hint, this_width);
924 break;
925
926 case AST_FCALL:
927 if (str == "\\$anyconst" || str == "\\$anyseq" || str == "\\$allconst" || str == "\\$allseq") {
928 if (GetSize(children) == 1) {
929 while (children[0]->simplify(true, false, false, 1, -1, false, true) == true) { }
930 if (children[0]->type != AST_CONSTANT)
931 log_file_error(filename, location.first_line, "System function %s called with non-const argument!\n",
932 RTLIL::unescape_id(str).c_str());
933 width_hint = max(width_hint, int(children[0]->asInt(true)));
934 }
935 break;
936 }
937 if (str == "\\$past") {
938 if (GetSize(children) > 0) {
939 sub_width_hint = 0;
940 sub_sign_hint = true;
941 children.at(0)->detectSignWidthWorker(sub_width_hint, sub_sign_hint);
942 width_hint = max(width_hint, sub_width_hint);
943 sign_hint = false;
944 }
945 break;
946 }
947 if (current_scope.count(str))
948 {
949 // This width detection is needed for function calls which are
950 // unelaborated, which currently only applies to calls to recursive
951 // functions reached by unevaluated ternary branches.
952 const AstNode *func = current_scope.at(str);
953 if (func->type != AST_FUNCTION)
954 log_file_error(filename, location.first_line, "Function call to %s resolved to something that isn't a function!\n", RTLIL::unescape_id(str).c_str());
955 const AstNode *wire = nullptr;
956 for (const AstNode *child : func->children)
957 if (child->str == func->str) {
958 wire = child;
959 break;
960 }
961 log_assert(wire && wire->type == AST_WIRE);
962 sign_hint = wire->is_signed;
963 width_hint = 1;
964 if (!wire->children.empty())
965 {
966 log_assert(wire->children.size() == 1);
967 const AstNode *range = wire->children.at(0);
968 log_assert(range->type == AST_RANGE && range->children.size() == 2);
969 AstNode *left = range->children.at(0)->clone();
970 AstNode *right = range->children.at(1)->clone();
971 while (left->simplify(true, false, false, 1, -1, false, true)) { }
972 while (right->simplify(true, false, false, 1, -1, false, true)) { }
973 if (left->type != AST_CONSTANT || right->type != AST_CONSTANT)
974 log_file_error(filename, location.first_line, "Function %s has non-constant width!",
975 RTLIL::unescape_id(str).c_str());
976 width_hint = abs(int(left->asInt(true) - right->asInt(true)));
977 delete left;
978 delete right;
979 }
980 break;
981 }
982 YS_FALLTHROUGH
983
984 // everything should have been handled above -> print error if not.
985 default:
986 for (auto f : log_files)
987 current_ast_mod->dumpAst(f, "verilog-ast> ");
988 log_file_error(filename, location.first_line, "Don't know how to detect sign and width for %s node!\n", type2str(type).c_str());
989 }
990
991 if (*found_real)
992 sign_hint = true;
993 }
994
995 // detect sign and width of an expression
996 void AstNode::detectSignWidth(int &width_hint, bool &sign_hint, bool *found_real)
997 {
998 width_hint = -1;
999 sign_hint = true;
1000 if (found_real)
1001 *found_real = false;
1002 detectSignWidthWorker(width_hint, sign_hint, found_real);
1003
1004 constexpr int kWidthLimit = 1 << 24;
1005 if (width_hint >= kWidthLimit)
1006 log_file_error(filename, location.first_line,
1007 "Expression width %d exceeds implementation limit of %d!\n",
1008 width_hint, kWidthLimit);
1009 }
1010
1011 static void check_unique_id(RTLIL::Module *module, RTLIL::IdString id,
1012 const AstNode *node, const char *to_add_kind)
1013 {
1014 auto already_exists = [&](const RTLIL::AttrObject *existing, const char *existing_kind) {
1015 std::string src = existing->get_string_attribute(ID::src);
1016 std::string location_str = "earlier";
1017 if (!src.empty())
1018 location_str = "at " + src;
1019 log_file_error(node->filename, node->location.first_line,
1020 "Cannot add %s `%s' because a %s with the same name was already created %s!\n",
1021 to_add_kind, id.c_str(), existing_kind, location_str.c_str());
1022 };
1023
1024 if (const RTLIL::Wire *wire = module->wire(id))
1025 already_exists(wire, "signal");
1026 if (const RTLIL::Cell *cell = module->cell(id))
1027 already_exists(cell, "cell");
1028 if (module->processes.count(id))
1029 already_exists(module->processes.at(id), "process");
1030 if (module->memories.count(id))
1031 already_exists(module->memories.at(id), "memory");
1032 }
1033
1034 // create RTLIL from an AST node
1035 // all generated cells, wires and processes are added to the module pointed to by 'current_module'
1036 // when the AST node is an expression (AST_ADD, AST_BIT_XOR, etc.), the result signal is returned.
1037 //
1038 // note that this function is influenced by a number of global variables that might be set when
1039 // called from genWidthRTLIL(). also note that this function recursively calls itself to transform
1040 // larger expressions into a netlist of cells.
1041 RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
1042 {
1043 // in the following big switch() statement there are some uses of
1044 // Clifford's Device (http://www.clifford.at/cfun/cliffdev/). In this
1045 // cases this variable is used to hold the type of the cell that should
1046 // be instantiated for this type of AST node.
1047 IdString type_name;
1048
1049 current_filename = filename;
1050
1051 switch (type)
1052 {
1053 // simply ignore this nodes.
1054 // they are either leftovers from simplify() or are referenced by other nodes
1055 // and are only accessed here thru this references
1056 case AST_NONE:
1057 case AST_TASK:
1058 case AST_FUNCTION:
1059 case AST_DPI_FUNCTION:
1060 case AST_AUTOWIRE:
1061 case AST_DEFPARAM:
1062 case AST_GENVAR:
1063 case AST_GENFOR:
1064 case AST_GENBLOCK:
1065 case AST_GENIF:
1066 case AST_GENCASE:
1067 case AST_PACKAGE:
1068 case AST_ENUM:
1069 case AST_MODPORT:
1070 case AST_MODPORTMEMBER:
1071 case AST_TYPEDEF:
1072 case AST_STRUCT:
1073 case AST_UNION:
1074 break;
1075 case AST_INTERFACEPORT: {
1076 // If a port in a module with unknown type is found, mark it with the attribute 'is_interface'
1077 // This is used by the hierarchy pass to know when it can replace interface connection with the individual
1078 // signals.
1079 RTLIL::IdString id = str;
1080 check_unique_id(current_module, id, this, "interface port");
1081 RTLIL::Wire *wire = current_module->addWire(id, 1);
1082 set_src_attr(wire, this);
1083 wire->start_offset = 0;
1084 wire->port_id = port_id;
1085 wire->port_input = true;
1086 wire->port_output = true;
1087 wire->set_bool_attribute(ID::is_interface);
1088 if (children.size() > 0) {
1089 for(size_t i=0; i<children.size();i++) {
1090 if(children[i]->type == AST_INTERFACEPORTTYPE) {
1091 std::pair<std::string,std::string> res = AST::split_modport_from_type(children[i]->str);
1092 wire->attributes[ID::interface_type] = res.first;
1093 if (res.second != "")
1094 wire->attributes[ID::interface_modport] = res.second;
1095 break;
1096 }
1097 }
1098 }
1099 wire->upto = 0;
1100 }
1101 break;
1102 case AST_INTERFACEPORTTYPE:
1103 break;
1104
1105 // remember the parameter, needed for example in techmap
1106 case AST_PARAMETER:
1107 current_module->avail_parameters(str);
1108 if (GetSize(children) >= 1 && children[0]->type == AST_CONSTANT) {
1109 current_module->parameter_default_values[str] = children[0]->asParaConst();
1110 }
1111 YS_FALLTHROUGH
1112 case AST_LOCALPARAM:
1113 if (flag_pwires)
1114 {
1115 if (GetSize(children) < 1 || children[0]->type != AST_CONSTANT)
1116 log_file_error(filename, location.first_line, "Parameter `%s' with non-constant value!\n", str.c_str());
1117
1118 RTLIL::Const val = children[0]->bitsAsConst();
1119 RTLIL::IdString id = str;
1120 check_unique_id(current_module, id, this, "pwire");
1121 RTLIL::Wire *wire = current_module->addWire(id, GetSize(val));
1122 current_module->connect(wire, val);
1123 wire->is_signed = children[0]->is_signed;
1124
1125 set_src_attr(wire, this);
1126 wire->attributes[type == AST_PARAMETER ? ID::parameter : ID::localparam] = 1;
1127
1128 for (auto &attr : attributes) {
1129 if (attr.second->type != AST_CONSTANT)
1130 log_file_error(filename, location.first_line, "Attribute `%s' with non-constant value!\n", attr.first.c_str());
1131 wire->attributes[attr.first] = attr.second->asAttrConst();
1132 }
1133 }
1134 break;
1135
1136 // create an RTLIL::Wire for an AST_WIRE node
1137 case AST_WIRE: {
1138 if (!range_valid)
1139 log_file_error(filename, location.first_line, "Signal `%s' with non-constant width!\n", str.c_str());
1140
1141 if (!(range_left + 1 >= range_right))
1142 log_file_error(filename, location.first_line, "Signal `%s' with invalid width range %d!\n", str.c_str(), range_left - range_right + 1);
1143
1144 RTLIL::IdString id = str;
1145 check_unique_id(current_module, id, this, "signal");
1146 RTLIL::Wire *wire = current_module->addWire(id, range_left - range_right + 1);
1147 set_src_attr(wire, this);
1148 wire->start_offset = range_right;
1149 wire->port_id = port_id;
1150 wire->port_input = is_input;
1151 wire->port_output = is_output;
1152 wire->upto = range_swapped;
1153 wire->is_signed = is_signed;
1154
1155 for (auto &attr : attributes) {
1156 if (attr.second->type != AST_CONSTANT)
1157 log_file_error(filename, location.first_line, "Attribute `%s' with non-constant value!\n", attr.first.c_str());
1158 wire->attributes[attr.first] = attr.second->asAttrConst();
1159 }
1160
1161 if (is_wand) wire->set_bool_attribute(ID::wand);
1162 if (is_wor) wire->set_bool_attribute(ID::wor);
1163 }
1164 break;
1165
1166 // create an RTLIL::Memory for an AST_MEMORY node
1167 case AST_MEMORY: {
1168 log_assert(children.size() >= 2);
1169 log_assert(children[0]->type == AST_RANGE);
1170 log_assert(children[1]->type == AST_RANGE);
1171
1172 if (!children[0]->range_valid || !children[1]->range_valid)
1173 log_file_error(filename, location.first_line, "Memory `%s' with non-constant width or size!\n", str.c_str());
1174
1175 RTLIL::Memory *memory = new RTLIL::Memory;
1176 set_src_attr(memory, this);
1177 memory->name = str;
1178 memory->width = children[0]->range_left - children[0]->range_right + 1;
1179 if (children[1]->range_right < children[1]->range_left) {
1180 memory->start_offset = children[1]->range_right;
1181 memory->size = children[1]->range_left - children[1]->range_right + 1;
1182 } else {
1183 memory->start_offset = children[1]->range_left;
1184 memory->size = children[1]->range_right - children[1]->range_left + 1;
1185 }
1186 check_unique_id(current_module, memory->name, this, "memory");
1187 current_module->memories[memory->name] = memory;
1188
1189 for (auto &attr : attributes) {
1190 if (attr.second->type != AST_CONSTANT)
1191 log_file_error(filename, location.first_line, "Attribute `%s' with non-constant value!\n", attr.first.c_str());
1192 memory->attributes[attr.first] = attr.second->asAttrConst();
1193 }
1194 }
1195 break;
1196
1197 // simply return the corresponding RTLIL::SigSpec for an AST_CONSTANT node
1198 case AST_CONSTANT:
1199 case AST_REALVALUE:
1200 {
1201 if (width_hint < 0)
1202 detectSignWidth(width_hint, sign_hint);
1203 is_signed = sign_hint;
1204
1205 if (type == AST_CONSTANT) {
1206 if (is_unsized) {
1207 return RTLIL::SigSpec(bitsAsUnsizedConst(width_hint));
1208 } else {
1209 return RTLIL::SigSpec(bitsAsConst());
1210 }
1211 }
1212
1213 RTLIL::SigSpec sig = realAsConst(width_hint);
1214 log_file_warning(filename, location.first_line, "converting real value %e to binary %s.\n", realvalue, log_signal(sig));
1215 return sig;
1216 }
1217
1218 // simply return the corresponding RTLIL::SigSpec for an AST_IDENTIFIER node
1219 // for identifiers with dynamic bit ranges (e.g. "foo[bar]" or "foo[bar+3:bar]") a
1220 // shifter cell is created and the output signal of this cell is returned
1221 case AST_IDENTIFIER:
1222 {
1223 RTLIL::Wire *wire = NULL;
1224 RTLIL::SigChunk chunk;
1225 bool is_interface = false;
1226
1227 int add_undef_bits_msb = 0;
1228 int add_undef_bits_lsb = 0;
1229
1230 log_assert(id2ast != nullptr);
1231
1232 if (id2ast->type == AST_AUTOWIRE && current_module->wires_.count(str) == 0) {
1233 RTLIL::Wire *wire = current_module->addWire(str);
1234 set_src_attr(wire, this);
1235 wire->name = str;
1236 if (flag_autowire)
1237 log_file_warning(filename, location.first_line, "Identifier `%s' is implicitly declared.\n", str.c_str());
1238 else
1239 log_file_error(filename, location.first_line, "Identifier `%s' is implicitly declared and `default_nettype is set to none.\n", str.c_str());
1240 }
1241 else if (id2ast->type == AST_PARAMETER || id2ast->type == AST_LOCALPARAM || id2ast->type == AST_ENUM_ITEM) {
1242 if (id2ast->children[0]->type != AST_CONSTANT)
1243 log_file_error(filename, location.first_line, "Parameter %s does not evaluate to constant value!\n", str.c_str());
1244 chunk = RTLIL::Const(id2ast->children[0]->bits);
1245 goto use_const_chunk;
1246 }
1247 else if ((id2ast->type == AST_WIRE || id2ast->type == AST_AUTOWIRE || id2ast->type == AST_MEMORY) && current_module->wires_.count(str) != 0) {
1248 RTLIL::Wire *current_wire = current_module->wire(str);
1249 if (current_wire->get_bool_attribute(ID::is_interface))
1250 is_interface = true;
1251 // Ignore
1252 }
1253 // If an identifier is found that is not already known, assume that it is an interface:
1254 else if (1) { // FIXME: Check if sv_mode first?
1255 is_interface = true;
1256 }
1257 else {
1258 log_file_error(filename, location.first_line, "Identifier `%s' doesn't map to any signal!\n", str.c_str());
1259 }
1260
1261 if (id2ast->type == AST_MEMORY)
1262 log_file_error(filename, location.first_line, "Identifier `%s' does map to an unexpanded memory!\n", str.c_str());
1263
1264 // If identifier is an interface, create a RTLIL::SigSpec with a dummy wire with a attribute called 'is_interface'
1265 // This makes it possible for the hierarchy pass to see what are interface connections and then replace them
1266 // with the individual signals:
1267 if (is_interface) {
1268 IdString dummy_wire_name = stringf("$dummywireforinterface%s", str.c_str());
1269 RTLIL::Wire *dummy_wire = current_module->wire(dummy_wire_name);
1270 if (!dummy_wire) {
1271 dummy_wire = current_module->addWire(dummy_wire_name);
1272 dummy_wire->set_bool_attribute(ID::is_interface);
1273 }
1274 return dummy_wire;
1275 }
1276
1277 wire = current_module->wires_[str];
1278 chunk.wire = wire;
1279 chunk.width = wire->width;
1280 chunk.offset = 0;
1281
1282 use_const_chunk:
1283 if (children.size() != 0) {
1284 if (children[0]->type != AST_RANGE)
1285 log_file_error(filename, location.first_line, "Single range expected.\n");
1286 int source_width = id2ast->range_left - id2ast->range_right + 1;
1287 int source_offset = id2ast->range_right;
1288 if (!children[0]->range_valid) {
1289 AstNode *left_at_zero_ast = children[0]->children[0]->clone();
1290 AstNode *right_at_zero_ast = children[0]->children.size() >= 2 ? children[0]->children[1]->clone() : left_at_zero_ast->clone();
1291 while (left_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { }
1292 while (right_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { }
1293 if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT)
1294 log_file_error(filename, location.first_line, "Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str());
1295 int width = abs(int(left_at_zero_ast->integer - right_at_zero_ast->integer)) + 1;
1296 AstNode *fake_ast = new AstNode(AST_NONE, clone(), children[0]->children.size() >= 2 ?
1297 children[0]->children[1]->clone() : children[0]->children[0]->clone());
1298 fake_ast->children[0]->delete_children();
1299
1300 int fake_ast_width = 0;
1301 bool fake_ast_sign = true;
1302 fake_ast->children[1]->detectSignWidth(fake_ast_width, fake_ast_sign);
1303 RTLIL::SigSpec shift_val = fake_ast->children[1]->genRTLIL(fake_ast_width, fake_ast_sign);
1304
1305 if (id2ast->range_right != 0) {
1306 shift_val = current_module->Sub(NEW_ID, shift_val, id2ast->range_right, fake_ast_sign);
1307 fake_ast->children[1]->is_signed = true;
1308 }
1309 if (id2ast->range_swapped) {
1310 shift_val = current_module->Sub(NEW_ID, RTLIL::SigSpec(source_width - width), shift_val, fake_ast_sign);
1311 fake_ast->children[1]->is_signed = true;
1312 }
1313 if (GetSize(shift_val) >= 32)
1314 fake_ast->children[1]->is_signed = true;
1315 RTLIL::SigSpec sig = binop2rtlil(fake_ast, ID($shiftx), width, fake_ast->children[0]->genRTLIL(), shift_val);
1316 delete left_at_zero_ast;
1317 delete right_at_zero_ast;
1318 delete fake_ast;
1319 return sig;
1320 } else {
1321 chunk.width = children[0]->range_left - children[0]->range_right + 1;
1322 chunk.offset = children[0]->range_right - source_offset;
1323 if (id2ast->range_swapped)
1324 chunk.offset = (id2ast->range_left - id2ast->range_right + 1) - (chunk.offset + chunk.width);
1325 if (chunk.offset >= source_width || chunk.offset + chunk.width < 0) {
1326 if (chunk.width == 1)
1327 log_file_warning(filename, location.first_line, "Range select out of bounds on signal `%s': Setting result bit to undef.\n",
1328 str.c_str());
1329 else
1330 log_file_warning(filename, location.first_line, "Range select [%d:%d] out of bounds on signal `%s': Setting all %d result bits to undef.\n",
1331 children[0]->range_left, children[0]->range_right, str.c_str(), chunk.width);
1332 chunk = RTLIL::SigChunk(RTLIL::State::Sx, chunk.width);
1333 } else {
1334 if (chunk.width + chunk.offset > source_width) {
1335 add_undef_bits_msb = (chunk.width + chunk.offset) - source_width;
1336 chunk.width -= add_undef_bits_msb;
1337 }
1338 if (chunk.offset < 0) {
1339 add_undef_bits_lsb = -chunk.offset;
1340 chunk.width -= add_undef_bits_lsb;
1341 chunk.offset += add_undef_bits_lsb;
1342 }
1343 if (add_undef_bits_lsb)
1344 log_file_warning(filename, location.first_line, "Range [%d:%d] select out of bounds on signal `%s': Setting %d LSB bits to undef.\n",
1345 children[0]->range_left, children[0]->range_right, str.c_str(), add_undef_bits_lsb);
1346 if (add_undef_bits_msb)
1347 log_file_warning(filename, location.first_line, "Range [%d:%d] select out of bounds on signal `%s': Setting %d MSB bits to undef.\n",
1348 children[0]->range_left, children[0]->range_right, str.c_str(), add_undef_bits_msb);
1349 }
1350 }
1351 }
1352
1353 RTLIL::SigSpec sig = { RTLIL::SigSpec(RTLIL::State::Sx, add_undef_bits_msb), chunk, RTLIL::SigSpec(RTLIL::State::Sx, add_undef_bits_lsb) };
1354
1355 if (genRTLIL_subst_ptr)
1356 sig.replace(*genRTLIL_subst_ptr);
1357
1358 is_signed = children.size() > 0 ? false : id2ast->is_signed && sign_hint;
1359 return sig;
1360 }
1361
1362 // just pass thru the signal. the parent will evaluate the is_signed property and interpret the SigSpec accordingly
1363 case AST_TO_SIGNED:
1364 case AST_TO_UNSIGNED:
1365 case AST_SELFSZ: {
1366 RTLIL::SigSpec sig = children[0]->genRTLIL();
1367 if (sig.size() < width_hint)
1368 sig.extend_u0(width_hint, sign_hint);
1369 is_signed = sign_hint;
1370 return sig;
1371 }
1372
1373 // changing the size of signal can be done directly using RTLIL::SigSpec
1374 case AST_CAST_SIZE: {
1375 RTLIL::SigSpec size = children[0]->genRTLIL();
1376 RTLIL::SigSpec sig = children[1]->genRTLIL();
1377 if (!size.is_fully_const())
1378 log_file_error(filename, location.first_line, "Static cast with non constant expression!\n");
1379 int width = size.as_int();
1380 if (width <= 0)
1381 log_file_error(filename, location.first_line, "Static cast with zero or negative size!\n");
1382 sig.extend_u0(width, sign_hint);
1383 is_signed = sign_hint;
1384 return sig;
1385 }
1386
1387 // concatenation of signals can be done directly using RTLIL::SigSpec
1388 case AST_CONCAT: {
1389 RTLIL::SigSpec sig;
1390 for (auto it = children.begin(); it != children.end(); it++)
1391 sig.append((*it)->genRTLIL());
1392 if (sig.size() < width_hint)
1393 sig.extend_u0(width_hint, false);
1394 return sig;
1395 }
1396
1397 // replication of signals can be done directly using RTLIL::SigSpec
1398 case AST_REPLICATE: {
1399 RTLIL::SigSpec left = children[0]->genRTLIL();
1400 RTLIL::SigSpec right = children[1]->genRTLIL();
1401 if (!left.is_fully_const())
1402 log_file_error(filename, location.first_line, "Left operand of replicate expression is not constant!\n");
1403 int count = left.as_int();
1404 RTLIL::SigSpec sig;
1405 for (int i = 0; i < count; i++)
1406 sig.append(right);
1407 if (sig.size() < width_hint)
1408 sig.extend_u0(width_hint, false);
1409 is_signed = false;
1410 return sig;
1411 }
1412
1413 // generate cells for unary operations: $not, $pos, $neg
1414 if (0) { case AST_BIT_NOT: type_name = ID($not); }
1415 if (0) { case AST_POS: type_name = ID($pos); }
1416 if (0) { case AST_NEG: type_name = ID($neg); }
1417 {
1418 RTLIL::SigSpec arg = children[0]->genRTLIL(width_hint, sign_hint);
1419 is_signed = children[0]->is_signed;
1420 int width = arg.size();
1421 if (width_hint > 0) {
1422 width = width_hint;
1423 widthExtend(this, arg, width, is_signed);
1424 }
1425 return uniop2rtlil(this, type_name, width, arg);
1426 }
1427
1428 // generate cells for binary operations: $and, $or, $xor, $xnor
1429 if (0) { case AST_BIT_AND: type_name = ID($and); }
1430 if (0) { case AST_BIT_OR: type_name = ID($or); }
1431 if (0) { case AST_BIT_XOR: type_name = ID($xor); }
1432 if (0) { case AST_BIT_XNOR: type_name = ID($xnor); }
1433 {
1434 if (width_hint < 0)
1435 detectSignWidth(width_hint, sign_hint);
1436 RTLIL::SigSpec left = children[0]->genRTLIL(width_hint, sign_hint);
1437 RTLIL::SigSpec right = children[1]->genRTLIL(width_hint, sign_hint);
1438 int width = max(left.size(), right.size());
1439 if (width_hint > 0)
1440 width = width_hint;
1441 is_signed = children[0]->is_signed && children[1]->is_signed;
1442 return binop2rtlil(this, type_name, width, left, right);
1443 }
1444
1445 // generate cells for unary operations: $reduce_and, $reduce_or, $reduce_xor, $reduce_xnor
1446 if (0) { case AST_REDUCE_AND: type_name = ID($reduce_and); }
1447 if (0) { case AST_REDUCE_OR: type_name = ID($reduce_or); }
1448 if (0) { case AST_REDUCE_XOR: type_name = ID($reduce_xor); }
1449 if (0) { case AST_REDUCE_XNOR: type_name = ID($reduce_xnor); }
1450 {
1451 RTLIL::SigSpec arg = children[0]->genRTLIL();
1452 RTLIL::SigSpec sig = uniop2rtlil(this, type_name, max(width_hint, 1), arg);
1453 return sig;
1454 }
1455
1456 // generate cells for unary operations: $reduce_bool
1457 // (this is actually just an $reduce_or, but for clarity a different cell type is used)
1458 if (0) { case AST_REDUCE_BOOL: type_name = ID($reduce_bool); }
1459 {
1460 RTLIL::SigSpec arg = children[0]->genRTLIL();
1461 RTLIL::SigSpec sig = arg.size() > 1 ? uniop2rtlil(this, type_name, max(width_hint, 1), arg) : arg;
1462 return sig;
1463 }
1464
1465 // generate cells for binary operations: $shl, $shr, $sshl, $sshr
1466 if (0) { case AST_SHIFT_LEFT: type_name = ID($shl); }
1467 if (0) { case AST_SHIFT_RIGHT: type_name = ID($shr); }
1468 if (0) { case AST_SHIFT_SLEFT: type_name = ID($sshl); }
1469 if (0) { case AST_SHIFT_SRIGHT: type_name = ID($sshr); }
1470 if (0) { case AST_SHIFTX: type_name = ID($shiftx); }
1471 if (0) { case AST_SHIFT: type_name = ID($shift); }
1472 {
1473 if (width_hint < 0)
1474 detectSignWidth(width_hint, sign_hint);
1475 RTLIL::SigSpec left = children[0]->genRTLIL(width_hint, sign_hint);
1476 RTLIL::SigSpec right = children[1]->genRTLIL();
1477 int width = width_hint > 0 ? width_hint : left.size();
1478 is_signed = children[0]->is_signed;
1479 return binop2rtlil(this, type_name, width, left, right);
1480 }
1481
1482 // generate cells for binary operations: $pow
1483 case AST_POW:
1484 {
1485 int right_width;
1486 bool right_signed;
1487 children[1]->detectSignWidth(right_width, right_signed);
1488 if (width_hint < 0)
1489 detectSignWidth(width_hint, sign_hint);
1490 RTLIL::SigSpec left = children[0]->genRTLIL(width_hint, sign_hint);
1491 RTLIL::SigSpec right = children[1]->genRTLIL(right_width, right_signed);
1492 int width = width_hint > 0 ? width_hint : left.size();
1493 is_signed = children[0]->is_signed;
1494 if (!flag_noopt && left.is_fully_const() && left.as_int() == 2 && !right_signed)
1495 return binop2rtlil(this, ID($shl), width, RTLIL::SigSpec(1, left.size()), right);
1496 return binop2rtlil(this, ID($pow), width, left, right);
1497 }
1498
1499 // generate cells for binary operations: $lt, $le, $eq, $ne, $ge, $gt
1500 if (0) { case AST_LT: type_name = ID($lt); }
1501 if (0) { case AST_LE: type_name = ID($le); }
1502 if (0) { case AST_EQ: type_name = ID($eq); }
1503 if (0) { case AST_NE: type_name = ID($ne); }
1504 if (0) { case AST_EQX: type_name = ID($eqx); }
1505 if (0) { case AST_NEX: type_name = ID($nex); }
1506 if (0) { case AST_GE: type_name = ID($ge); }
1507 if (0) { case AST_GT: type_name = ID($gt); }
1508 {
1509 int width = max(width_hint, 1);
1510 width_hint = -1, sign_hint = true;
1511 children[0]->detectSignWidthWorker(width_hint, sign_hint);
1512 children[1]->detectSignWidthWorker(width_hint, sign_hint);
1513 RTLIL::SigSpec left = children[0]->genRTLIL(width_hint, sign_hint);
1514 RTLIL::SigSpec right = children[1]->genRTLIL(width_hint, sign_hint);
1515 RTLIL::SigSpec sig = binop2rtlil(this, type_name, width, left, right);
1516 return sig;
1517 }
1518
1519 // generate cells for binary operations: $add, $sub, $mul, $div, $mod
1520 if (0) { case AST_ADD: type_name = ID($add); }
1521 if (0) { case AST_SUB: type_name = ID($sub); }
1522 if (0) { case AST_MUL: type_name = ID($mul); }
1523 if (0) { case AST_DIV: type_name = ID($div); }
1524 if (0) { case AST_MOD: type_name = ID($mod); }
1525 {
1526 if (width_hint < 0)
1527 detectSignWidth(width_hint, sign_hint);
1528 RTLIL::SigSpec left = children[0]->genRTLIL(width_hint, sign_hint);
1529 RTLIL::SigSpec right = children[1]->genRTLIL(width_hint, sign_hint);
1530 #if 0
1531 int width = max(left.size(), right.size());
1532 if (width > width_hint && width_hint > 0)
1533 width = width_hint;
1534 if (width < width_hint) {
1535 if (type == AST_ADD || type == AST_SUB || type == AST_DIV)
1536 width++;
1537 if (type == AST_SUB && (!children[0]->is_signed || !children[1]->is_signed))
1538 width = width_hint;
1539 if (type == AST_MUL)
1540 width = min(left.size() + right.size(), width_hint);
1541 }
1542 #else
1543 int width = max(max(left.size(), right.size()), width_hint);
1544 #endif
1545 is_signed = children[0]->is_signed && children[1]->is_signed;
1546 return binop2rtlil(this, type_name, width, left, right);
1547 }
1548
1549 // generate cells for binary operations: $logic_and, $logic_or
1550 if (0) { case AST_LOGIC_AND: type_name = ID($logic_and); }
1551 if (0) { case AST_LOGIC_OR: type_name = ID($logic_or); }
1552 {
1553 RTLIL::SigSpec left = children[0]->genRTLIL();
1554 RTLIL::SigSpec right = children[1]->genRTLIL();
1555 return binop2rtlil(this, type_name, max(width_hint, 1), left, right);
1556 }
1557
1558 // generate cells for unary operations: $logic_not
1559 case AST_LOGIC_NOT:
1560 {
1561 RTLIL::SigSpec arg = children[0]->genRTLIL();
1562 return uniop2rtlil(this, ID($logic_not), max(width_hint, 1), arg);
1563 }
1564
1565 // generate multiplexer for ternary operator (aka ?:-operator)
1566 case AST_TERNARY:
1567 {
1568 if (width_hint < 0)
1569 detectSignWidth(width_hint, sign_hint);
1570 is_signed = sign_hint;
1571
1572 RTLIL::SigSpec cond = children[0]->genRTLIL();
1573 RTLIL::SigSpec sig;
1574
1575 if (cond.is_fully_def())
1576 {
1577 if (cond.as_bool()) {
1578 sig = children[1]->genRTLIL(width_hint, sign_hint);
1579 log_assert(is_signed == children[1]->is_signed);
1580 } else {
1581 sig = children[2]->genRTLIL(width_hint, sign_hint);
1582 log_assert(is_signed == children[2]->is_signed);
1583 }
1584
1585 widthExtend(this, sig, sig.size(), is_signed);
1586 }
1587 else
1588 {
1589 RTLIL::SigSpec val1 = children[1]->genRTLIL(width_hint, sign_hint);
1590 RTLIL::SigSpec val2 = children[2]->genRTLIL(width_hint, sign_hint);
1591
1592 if (cond.size() > 1)
1593 cond = uniop2rtlil(this, ID($reduce_bool), 1, cond, false);
1594
1595 int width = max(val1.size(), val2.size());
1596 log_assert(is_signed == children[1]->is_signed);
1597 log_assert(is_signed == children[2]->is_signed);
1598 widthExtend(this, val1, width, is_signed);
1599 widthExtend(this, val2, width, is_signed);
1600
1601 sig = mux2rtlil(this, cond, val1, val2);
1602 }
1603
1604 if (sig.size() < width_hint)
1605 sig.extend_u0(width_hint, sign_hint);
1606 return sig;
1607 }
1608
1609 // generate $memrd cells for memory read ports
1610 case AST_MEMRD:
1611 {
1612 std::stringstream sstr;
1613 sstr << "$memrd$" << str << "$" << filename << ":" << location.first_line << "$" << (autoidx++);
1614
1615 RTLIL::Cell *cell = current_module->addCell(sstr.str(), ID($memrd));
1616 set_src_attr(cell, this);
1617
1618 RTLIL::Wire *wire = current_module->addWire(cell->name.str() + "_DATA", current_module->memories[str]->width);
1619 set_src_attr(wire, this);
1620
1621 int mem_width, mem_size, addr_bits;
1622 is_signed = id2ast->is_signed;
1623 wire->is_signed = is_signed;
1624 id2ast->meminfo(mem_width, mem_size, addr_bits);
1625
1626 RTLIL::SigSpec addr_sig = children[0]->genRTLIL();
1627
1628 cell->setPort(ID::CLK, RTLIL::SigSpec(RTLIL::State::Sx, 1));
1629 cell->setPort(ID::EN, RTLIL::SigSpec(RTLIL::State::Sx, 1));
1630 cell->setPort(ID::ADDR, addr_sig);
1631 cell->setPort(ID::DATA, RTLIL::SigSpec(wire));
1632
1633 cell->parameters[ID::MEMID] = RTLIL::Const(str);
1634 cell->parameters[ID::ABITS] = RTLIL::Const(GetSize(addr_sig));
1635 cell->parameters[ID::WIDTH] = RTLIL::Const(wire->width);
1636
1637 cell->parameters[ID::CLK_ENABLE] = RTLIL::Const(0);
1638 cell->parameters[ID::CLK_POLARITY] = RTLIL::Const(0);
1639 cell->parameters[ID::TRANSPARENT] = RTLIL::Const(0);
1640
1641 if (!sign_hint)
1642 is_signed = false;
1643
1644 return RTLIL::SigSpec(wire);
1645 }
1646
1647 // generate $memwr cells for memory write ports
1648 case AST_MEMWR:
1649 case AST_MEMINIT:
1650 {
1651 std::stringstream sstr;
1652 sstr << (type == AST_MEMWR ? "$memwr$" : "$meminit$") << str << "$" << filename << ":" << location.first_line << "$" << (autoidx++);
1653
1654 RTLIL::Cell *cell = current_module->addCell(sstr.str(), type == AST_MEMWR ? ID($memwr) : ID($meminit));
1655 set_src_attr(cell, this);
1656
1657 int mem_width, mem_size, addr_bits;
1658 id2ast->meminfo(mem_width, mem_size, addr_bits);
1659
1660 int num_words = 1;
1661 if (type == AST_MEMINIT) {
1662 if (children[2]->type != AST_CONSTANT)
1663 log_file_error(filename, location.first_line, "Memory init with non-constant word count!\n");
1664 num_words = int(children[2]->asInt(false));
1665 cell->parameters[ID::WORDS] = RTLIL::Const(num_words);
1666 }
1667
1668 SigSpec addr_sig = children[0]->genRTLIL();
1669
1670 cell->setPort(ID::ADDR, addr_sig);
1671 cell->setPort(ID::DATA, children[1]->genWidthRTLIL(current_module->memories[str]->width * num_words));
1672
1673 cell->parameters[ID::MEMID] = RTLIL::Const(str);
1674 cell->parameters[ID::ABITS] = RTLIL::Const(GetSize(addr_sig));
1675 cell->parameters[ID::WIDTH] = RTLIL::Const(current_module->memories[str]->width);
1676
1677 if (type == AST_MEMWR) {
1678 cell->setPort(ID::CLK, RTLIL::SigSpec(RTLIL::State::Sx, 1));
1679 cell->setPort(ID::EN, children[2]->genRTLIL());
1680 cell->parameters[ID::CLK_ENABLE] = RTLIL::Const(0);
1681 cell->parameters[ID::CLK_POLARITY] = RTLIL::Const(0);
1682 }
1683
1684 cell->parameters[ID::PRIORITY] = RTLIL::Const(autoidx-1);
1685 }
1686 break;
1687
1688 // generate $assert cells
1689 case AST_ASSERT:
1690 case AST_ASSUME:
1691 case AST_LIVE:
1692 case AST_FAIR:
1693 case AST_COVER:
1694 {
1695 IdString celltype;
1696 if (type == AST_ASSERT) celltype = ID($assert);
1697 if (type == AST_ASSUME) celltype = ID($assume);
1698 if (type == AST_LIVE) celltype = ID($live);
1699 if (type == AST_FAIR) celltype = ID($fair);
1700 if (type == AST_COVER) celltype = ID($cover);
1701
1702 log_assert(children.size() == 2);
1703
1704 RTLIL::SigSpec check = children[0]->genRTLIL();
1705 if (GetSize(check) != 1)
1706 check = current_module->ReduceBool(NEW_ID, check);
1707
1708 RTLIL::SigSpec en = children[1]->genRTLIL();
1709 if (GetSize(en) != 1)
1710 en = current_module->ReduceBool(NEW_ID, en);
1711
1712 IdString cellname;
1713 if (str.empty())
1714 cellname = stringf("%s$%s:%d$%d", celltype.c_str(), filename.c_str(), location.first_line, autoidx++);
1715 else
1716 cellname = str;
1717
1718 check_unique_id(current_module, cellname, this, "procedural assertion");
1719 RTLIL::Cell *cell = current_module->addCell(cellname, celltype);
1720 set_src_attr(cell, this);
1721
1722 for (auto &attr : attributes) {
1723 if (attr.second->type != AST_CONSTANT)
1724 log_file_error(filename, location.first_line, "Attribute `%s' with non-constant value!\n", attr.first.c_str());
1725 cell->attributes[attr.first] = attr.second->asAttrConst();
1726 }
1727
1728 cell->setPort(ID::A, check);
1729 cell->setPort(ID::EN, en);
1730 }
1731 break;
1732
1733 // add entries to current_module->connections for assignments (outside of always blocks)
1734 case AST_ASSIGN:
1735 {
1736 RTLIL::SigSpec left = children[0]->genRTLIL();
1737 RTLIL::SigSpec right = children[1]->genWidthRTLIL(left.size());
1738 if (left.has_const()) {
1739 RTLIL::SigSpec new_left, new_right;
1740 for (int i = 0; i < GetSize(left); i++)
1741 if (left[i].wire) {
1742 new_left.append(left[i]);
1743 new_right.append(right[i]);
1744 }
1745 log_file_warning(filename, location.first_line, "Ignoring assignment to constant bits:\n"
1746 " old assignment: %s = %s\n new assignment: %s = %s.\n",
1747 log_signal(left), log_signal(right),
1748 log_signal(new_left), log_signal(new_right));
1749 left = new_left;
1750 right = new_right;
1751 }
1752 current_module->connect(RTLIL::SigSig(left, right));
1753 }
1754 break;
1755
1756 // create an RTLIL::Cell for an AST_CELL
1757 case AST_CELL:
1758 {
1759 int port_counter = 0, para_counter = 0;
1760
1761 RTLIL::IdString id = str;
1762 check_unique_id(current_module, id, this, "cell");
1763 RTLIL::Cell *cell = current_module->addCell(id, "");
1764 set_src_attr(cell, this);
1765 // Set attribute 'module_not_derived' which will be cleared again after the hierarchy pass
1766 cell->set_bool_attribute(ID::module_not_derived);
1767
1768 for (auto it = children.begin(); it != children.end(); it++) {
1769 AstNode *child = *it;
1770 if (child->type == AST_CELLTYPE) {
1771 cell->type = child->str;
1772 if (flag_icells && cell->type.begins_with("\\$"))
1773 cell->type = cell->type.substr(1);
1774 continue;
1775 }
1776 if (child->type == AST_PARASET) {
1777 int extra_const_flags = 0;
1778 IdString paraname = child->str.empty() ? stringf("$%d", ++para_counter) : child->str;
1779 if (child->children[0]->type == AST_REALVALUE) {
1780 log_file_warning(filename, location.first_line, "Replacing floating point parameter %s.%s = %f with string.\n",
1781 log_id(cell), log_id(paraname), child->children[0]->realvalue);
1782 extra_const_flags = RTLIL::CONST_FLAG_REAL;
1783 auto strnode = AstNode::mkconst_str(stringf("%f", child->children[0]->realvalue));
1784 strnode->cloneInto(child->children[0]);
1785 delete strnode;
1786 }
1787 if (child->children[0]->type != AST_CONSTANT)
1788 log_file_error(filename, location.first_line, "Parameter %s.%s with non-constant value!\n",
1789 log_id(cell), log_id(paraname));
1790 cell->parameters[paraname] = child->children[0]->asParaConst();
1791 cell->parameters[paraname].flags |= extra_const_flags;
1792 continue;
1793 }
1794 if (child->type == AST_ARGUMENT) {
1795 RTLIL::SigSpec sig;
1796 if (child->children.size() > 0) {
1797 AstNode *arg = child->children[0];
1798 int local_width_hint = -1;
1799 bool local_sign_hint = false;
1800 // don't inadvertently attempt to detect the width of interfaces
1801 if (arg->type != AST_IDENTIFIER || !arg->id2ast || arg->id2ast->type != AST_CELL)
1802 arg->detectSignWidth(local_width_hint, local_sign_hint);
1803 sig = arg->genRTLIL(local_width_hint, local_sign_hint);
1804 log_assert(local_sign_hint == arg->is_signed);
1805 if (sig.is_wire()) {
1806 // if the resulting SigSpec is a wire, its
1807 // signedness should match that of the AstNode
1808 log_assert(arg->is_signed == sig.as_wire()->is_signed);
1809 } else if (arg->is_signed) {
1810 // non-trivial signed nodes are indirected through
1811 // signed wires to enable sign extension
1812 RTLIL::IdString wire_name = NEW_ID;
1813 RTLIL::Wire *wire = current_module->addWire(wire_name, GetSize(sig));
1814 wire->is_signed = true;
1815 current_module->connect(wire, sig);
1816 sig = wire;
1817 }
1818 }
1819 if (child->str.size() == 0) {
1820 char buf[100];
1821 snprintf(buf, 100, "$%d", ++port_counter);
1822 cell->setPort(buf, sig);
1823 } else {
1824 cell->setPort(child->str, sig);
1825 }
1826 continue;
1827 }
1828 log_abort();
1829 }
1830 for (auto &attr : attributes) {
1831 if (attr.second->type != AST_CONSTANT)
1832 log_file_error(filename, location.first_line, "Attribute `%s' with non-constant value.\n", attr.first.c_str());
1833 cell->attributes[attr.first] = attr.second->asAttrConst();
1834 }
1835 if (cell->type == ID($specify2)) {
1836 int src_width = GetSize(cell->getPort(ID::SRC));
1837 int dst_width = GetSize(cell->getPort(ID::DST));
1838 bool full = cell->getParam(ID::FULL).as_bool();
1839 if (!full && src_width != dst_width)
1840 log_file_error(filename, location.first_line, "Parallel specify SRC width does not match DST width.\n");
1841 cell->setParam(ID::SRC_WIDTH, Const(src_width));
1842 cell->setParam(ID::DST_WIDTH, Const(dst_width));
1843 }
1844 else if (cell->type == ID($specify3)) {
1845 int dat_width = GetSize(cell->getPort(ID::DAT));
1846 int dst_width = GetSize(cell->getPort(ID::DST));
1847 if (dat_width != dst_width)
1848 log_file_error(filename, location.first_line, "Specify DAT width does not match DST width.\n");
1849 int src_width = GetSize(cell->getPort(ID::SRC));
1850 cell->setParam(ID::SRC_WIDTH, Const(src_width));
1851 cell->setParam(ID::DST_WIDTH, Const(dst_width));
1852 }
1853 else if (cell->type == ID($specrule)) {
1854 int src_width = GetSize(cell->getPort(ID::SRC));
1855 int dst_width = GetSize(cell->getPort(ID::DST));
1856 cell->setParam(ID::SRC_WIDTH, Const(src_width));
1857 cell->setParam(ID::DST_WIDTH, Const(dst_width));
1858 }
1859 }
1860 break;
1861
1862 // use ProcessGenerator for always blocks
1863 case AST_ALWAYS: {
1864 AstNode *always = this->clone();
1865 ProcessGenerator generator(always);
1866 ignoreThisSignalsInInitial.append(generator.outputSignals);
1867 delete always;
1868 } break;
1869
1870 case AST_INITIAL: {
1871 AstNode *always = this->clone();
1872 ProcessGenerator generator(always, ignoreThisSignalsInInitial);
1873 delete always;
1874 } break;
1875
1876 case AST_TECALL: {
1877 int sz = children.size();
1878 if (str == "$info") {
1879 if (sz > 0)
1880 log_file_info(filename, location.first_line, "%s.\n", children[0]->str.c_str());
1881 else
1882 log_file_info(filename, location.first_line, "\n");
1883 } else if (str == "$warning") {
1884 if (sz > 0)
1885 log_file_warning(filename, location.first_line, "%s.\n", children[0]->str.c_str());
1886 else
1887 log_file_warning(filename, location.first_line, "\n");
1888 } else if (str == "$error") {
1889 if (sz > 0)
1890 log_file_error(filename, location.first_line, "%s.\n", children[0]->str.c_str());
1891 else
1892 log_file_error(filename, location.first_line, "\n");
1893 } else if (str == "$fatal") {
1894 // TODO: 1st parameter, if exists, is 0,1 or 2, and passed to $finish()
1895 // if no parameter is given, default value is 1
1896 // dollar_finish(sz ? children[0] : 1);
1897 // perhaps create & use log_file_fatal()
1898 if (sz > 0)
1899 log_file_error(filename, location.first_line, "FATAL: %s.\n", children[0]->str.c_str());
1900 else
1901 log_file_error(filename, location.first_line, "FATAL.\n");
1902 } else {
1903 log_file_error(filename, location.first_line, "Unknown elabortoon system task '%s'.\n", str.c_str());
1904 }
1905 } break;
1906
1907 case AST_FCALL: {
1908 if (str == "\\$anyconst" || str == "\\$anyseq" || str == "\\$allconst" || str == "\\$allseq")
1909 {
1910 string myid = stringf("%s$%d", str.c_str() + 1, autoidx++);
1911 int width = width_hint;
1912
1913 if (GetSize(children) > 1)
1914 log_file_error(filename, location.first_line, "System function %s got %d arguments, expected 1 or 0.\n",
1915 RTLIL::unescape_id(str).c_str(), GetSize(children));
1916
1917 if (GetSize(children) == 1) {
1918 if (children[0]->type != AST_CONSTANT)
1919 log_file_error(filename, location.first_line, "System function %s called with non-const argument!\n",
1920 RTLIL::unescape_id(str).c_str());
1921 width = children[0]->asInt(true);
1922 }
1923
1924 if (width <= 0)
1925 log_file_error(filename, location.first_line, "Failed to detect width of %s!\n", RTLIL::unescape_id(str).c_str());
1926
1927 Cell *cell = current_module->addCell(myid, str.substr(1));
1928 set_src_attr(cell, this);
1929 cell->parameters[ID::WIDTH] = width;
1930
1931 if (attributes.count(ID::reg)) {
1932 auto &attr = attributes.at(ID::reg);
1933 if (attr->type != AST_CONSTANT)
1934 log_file_error(filename, location.first_line, "Attribute `reg' with non-constant value!\n");
1935 cell->attributes[ID::reg] = attr->asAttrConst();
1936 }
1937
1938 Wire *wire = current_module->addWire(myid + "_wire", width);
1939 set_src_attr(wire, this);
1940 cell->setPort(ID::Y, wire);
1941
1942 is_signed = sign_hint;
1943 return SigSpec(wire);
1944 }
1945 }
1946 YS_FALLTHROUGH
1947
1948 // everything should have been handled above -> print error if not.
1949 default:
1950 for (auto f : log_files)
1951 current_ast_mod->dumpAst(f, "verilog-ast> ");
1952 type_name = type2str(type);
1953 log_file_error(filename, location.first_line, "Don't know how to generate RTLIL code for %s node!\n", type_name.c_str());
1954 }
1955
1956 return RTLIL::SigSpec();
1957 }
1958
1959 // this is a wrapper for AstNode::genRTLIL() when a specific signal width is requested and/or
1960 // signals must be substituted before being used as input values (used by ProcessGenerator)
1961 // note that this is using some global variables to communicate this special settings to AstNode::genRTLIL().
1962 RTLIL::SigSpec AstNode::genWidthRTLIL(int width, const dict<RTLIL::SigBit, RTLIL::SigBit> *new_subst_ptr)
1963 {
1964 const dict<RTLIL::SigBit, RTLIL::SigBit> *backup_subst_ptr = genRTLIL_subst_ptr;
1965
1966 if (new_subst_ptr)
1967 genRTLIL_subst_ptr = new_subst_ptr;
1968
1969 bool sign_hint = true;
1970 int width_hint = width;
1971 detectSignWidthWorker(width_hint, sign_hint);
1972 RTLIL::SigSpec sig = genRTLIL(width_hint, sign_hint);
1973
1974 genRTLIL_subst_ptr = backup_subst_ptr;
1975
1976 if (width >= 0)
1977 sig.extend_u0(width, is_signed);
1978
1979 return sig;
1980 }
1981
1982 YOSYS_NAMESPACE_END