Generate an RTLIL representation of bind constructs
[yosys.git] / frontends / ast / ast.cc
1 /*
2 * yosys -- Yosys Open SYnthesis Suite
3 *
4 * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
5 * Copyright (C) 2018 Ruben Undheim <ruben.undheim@gmail.com>
6 *
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 *
19 * ---
20 *
21 * This is the AST frontend library.
22 *
23 * The AST frontend library is not a frontend on it's own but provides a
24 * generic abstract syntax tree (AST) abstraction for HDL code and can be
25 * used by HDL frontends. See "ast.h" for an overview of the API and the
26 * Verilog frontend for an usage example.
27 *
28 */
29
30 #include "kernel/yosys.h"
31 #include "libs/sha1/sha1.h"
32 #include "ast.h"
33
34 YOSYS_NAMESPACE_BEGIN
35
36 using namespace AST;
37 using namespace AST_INTERNAL;
38
39 // instantiate global variables (public API)
40 namespace AST {
41 std::string current_filename;
42 void (*set_line_num)(int) = NULL;
43 int (*get_line_num)() = NULL;
44 }
45
46 // instantiate global variables (private API)
47 namespace AST_INTERNAL {
48 bool flag_dump_ast1, flag_dump_ast2, flag_no_dump_ptr, flag_dump_vlog1, flag_dump_vlog2, flag_dump_rtlil, flag_nolatches, flag_nomeminit;
49 bool flag_nomem2reg, flag_mem2reg, flag_noblackbox, flag_lib, flag_nowb, flag_noopt, flag_icells, flag_pwires, flag_autowire;
50 AstNode *current_ast, *current_ast_mod;
51 std::map<std::string, AstNode*> current_scope;
52 const dict<RTLIL::SigBit, RTLIL::SigBit> *genRTLIL_subst_ptr = NULL;
53 RTLIL::SigSpec ignoreThisSignalsInInitial;
54 AstNode *current_always, *current_top_block, *current_block, *current_block_child;
55 Module *current_module;
56 bool current_always_clocked;
57 dict<std::string, int> current_memwr_count;
58 dict<std::string, pool<int>> current_memwr_visible;
59 }
60
61 // convert node types to string
62 std::string AST::type2str(AstNodeType type)
63 {
64 switch (type)
65 {
66 #define X(_item) case _item: return #_item;
67 X(AST_NONE)
68 X(AST_DESIGN)
69 X(AST_MODULE)
70 X(AST_TASK)
71 X(AST_FUNCTION)
72 X(AST_DPI_FUNCTION)
73 X(AST_WIRE)
74 X(AST_MEMORY)
75 X(AST_AUTOWIRE)
76 X(AST_PARAMETER)
77 X(AST_LOCALPARAM)
78 X(AST_DEFPARAM)
79 X(AST_PARASET)
80 X(AST_ARGUMENT)
81 X(AST_RANGE)
82 X(AST_MULTIRANGE)
83 X(AST_CONSTANT)
84 X(AST_REALVALUE)
85 X(AST_CELLTYPE)
86 X(AST_IDENTIFIER)
87 X(AST_PREFIX)
88 X(AST_ASSERT)
89 X(AST_ASSUME)
90 X(AST_LIVE)
91 X(AST_FAIR)
92 X(AST_COVER)
93 X(AST_ENUM)
94 X(AST_ENUM_ITEM)
95 X(AST_FCALL)
96 X(AST_TO_BITS)
97 X(AST_TO_SIGNED)
98 X(AST_TO_UNSIGNED)
99 X(AST_SELFSZ)
100 X(AST_CAST_SIZE)
101 X(AST_CONCAT)
102 X(AST_REPLICATE)
103 X(AST_BIT_NOT)
104 X(AST_BIT_AND)
105 X(AST_BIT_OR)
106 X(AST_BIT_XOR)
107 X(AST_BIT_XNOR)
108 X(AST_REDUCE_AND)
109 X(AST_REDUCE_OR)
110 X(AST_REDUCE_XOR)
111 X(AST_REDUCE_XNOR)
112 X(AST_REDUCE_BOOL)
113 X(AST_SHIFT_LEFT)
114 X(AST_SHIFT_RIGHT)
115 X(AST_SHIFT_SLEFT)
116 X(AST_SHIFT_SRIGHT)
117 X(AST_SHIFTX)
118 X(AST_SHIFT)
119 X(AST_LT)
120 X(AST_LE)
121 X(AST_EQ)
122 X(AST_NE)
123 X(AST_EQX)
124 X(AST_NEX)
125 X(AST_GE)
126 X(AST_GT)
127 X(AST_ADD)
128 X(AST_SUB)
129 X(AST_MUL)
130 X(AST_DIV)
131 X(AST_MOD)
132 X(AST_POW)
133 X(AST_POS)
134 X(AST_NEG)
135 X(AST_LOGIC_AND)
136 X(AST_LOGIC_OR)
137 X(AST_LOGIC_NOT)
138 X(AST_TERNARY)
139 X(AST_MEMRD)
140 X(AST_MEMWR)
141 X(AST_MEMINIT)
142 X(AST_TCALL)
143 X(AST_ASSIGN)
144 X(AST_CELL)
145 X(AST_PRIMITIVE)
146 X(AST_CELLARRAY)
147 X(AST_ALWAYS)
148 X(AST_INITIAL)
149 X(AST_BLOCK)
150 X(AST_ASSIGN_EQ)
151 X(AST_ASSIGN_LE)
152 X(AST_CASE)
153 X(AST_COND)
154 X(AST_CONDX)
155 X(AST_CONDZ)
156 X(AST_DEFAULT)
157 X(AST_FOR)
158 X(AST_WHILE)
159 X(AST_REPEAT)
160 X(AST_GENVAR)
161 X(AST_GENFOR)
162 X(AST_GENIF)
163 X(AST_GENCASE)
164 X(AST_GENBLOCK)
165 X(AST_TECALL)
166 X(AST_POSEDGE)
167 X(AST_NEGEDGE)
168 X(AST_EDGE)
169 X(AST_INTERFACE)
170 X(AST_INTERFACEPORT)
171 X(AST_INTERFACEPORTTYPE)
172 X(AST_MODPORT)
173 X(AST_MODPORTMEMBER)
174 X(AST_PACKAGE)
175 X(AST_WIRETYPE)
176 X(AST_TYPEDEF)
177 X(AST_STRUCT)
178 X(AST_UNION)
179 X(AST_STRUCT_ITEM)
180 X(AST_BIND)
181 #undef X
182 default:
183 log_abort();
184 }
185 }
186
187 // check if attribute exists and has non-zero value
188 bool AstNode::get_bool_attribute(RTLIL::IdString id)
189 {
190 if (attributes.count(id) == 0)
191 return false;
192
193 AstNode *attr = attributes.at(id);
194 if (attr->type != AST_CONSTANT)
195 log_file_error(attr->filename, attr->location.first_line, "Attribute `%s' with non-constant value!\n", id.c_str());
196
197 return attr->integer != 0;
198 }
199
200 // create new node (AstNode constructor)
201 // (the optional child arguments make it easier to create AST trees)
202 AstNode::AstNode(AstNodeType type, AstNode *child1, AstNode *child2, AstNode *child3, AstNode *child4)
203 {
204 static unsigned int hashidx_count = 123456789;
205 hashidx_count = mkhash_xorshift(hashidx_count);
206 hashidx_ = hashidx_count;
207
208 this->type = type;
209 filename = current_filename;
210 is_input = false;
211 is_output = false;
212 is_reg = false;
213 is_logic = false;
214 is_signed = false;
215 is_string = false;
216 is_enum = false;
217 is_wand = false;
218 is_wor = false;
219 is_unsized = false;
220 was_checked = false;
221 range_valid = false;
222 range_swapped = false;
223 is_custom_type = false;
224 port_id = 0;
225 range_left = -1;
226 range_right = 0;
227 integer = 0;
228 realvalue = 0;
229 id2ast = NULL;
230 basic_prep = false;
231 lookahead = false;
232
233 if (child1)
234 children.push_back(child1);
235 if (child2)
236 children.push_back(child2);
237 if (child3)
238 children.push_back(child3);
239 if (child4)
240 children.push_back(child4);
241 }
242
243 // create a (deep recursive) copy of a node
244 AstNode *AstNode::clone() const
245 {
246 AstNode *that = new AstNode;
247 *that = *this;
248 for (auto &it : that->children)
249 it = it->clone();
250 for (auto &it : that->attributes)
251 it.second = it.second->clone();
252 return that;
253 }
254
255 // create a (deep recursive) copy of a node use 'other' as target root node
256 void AstNode::cloneInto(AstNode *other) const
257 {
258 AstNode *tmp = clone();
259 other->delete_children();
260 *other = *tmp;
261 tmp->children.clear();
262 tmp->attributes.clear();
263 delete tmp;
264 }
265
266 // delete all children in this node
267 void AstNode::delete_children()
268 {
269 for (auto &it : children)
270 delete it;
271 children.clear();
272
273 for (auto &it : attributes)
274 delete it.second;
275 attributes.clear();
276 }
277
278 // AstNode destructor
279 AstNode::~AstNode()
280 {
281 delete_children();
282 }
283
284 // create a nice text representation of the node
285 // (traverse tree by recursion, use 'other' pointer for diffing two AST trees)
286 void AstNode::dumpAst(FILE *f, std::string indent) const
287 {
288 if (f == NULL) {
289 for (auto f : log_files)
290 dumpAst(f, indent);
291 return;
292 }
293
294 std::string type_name = type2str(type);
295 fprintf(f, "%s%s <%s>", indent.c_str(), type_name.c_str(), loc_string().c_str());
296
297 if (!flag_no_dump_ptr) {
298 if (id2ast)
299 fprintf(f, " [%p -> %p]", this, id2ast);
300 else
301 fprintf(f, " [%p]", this);
302 }
303
304 if (!str.empty())
305 fprintf(f, " str='%s'", str.c_str());
306 if (!bits.empty()) {
307 fprintf(f, " bits='");
308 for (size_t i = bits.size(); i > 0; i--)
309 fprintf(f, "%c", bits[i-1] == State::S0 ? '0' :
310 bits[i-1] == State::S1 ? '1' :
311 bits[i-1] == RTLIL::Sx ? 'x' :
312 bits[i-1] == RTLIL::Sz ? 'z' : '?');
313 fprintf(f, "'(%d)", GetSize(bits));
314 }
315 if (is_input)
316 fprintf(f, " input");
317 if (is_output)
318 fprintf(f, " output");
319 if (is_logic)
320 fprintf(f, " logic");
321 if (is_reg) // this is an AST dump, not Verilog - if we see "logic reg" that's fine.
322 fprintf(f, " reg");
323 if (is_signed)
324 fprintf(f, " signed");
325 if (is_unsized)
326 fprintf(f, " unsized");
327 if (basic_prep)
328 fprintf(f, " basic_prep");
329 if (lookahead)
330 fprintf(f, " lookahead");
331 if (port_id > 0)
332 fprintf(f, " port=%d", port_id);
333 if (range_valid || range_left != -1 || range_right != 0)
334 fprintf(f, " %srange=[%d:%d]%s", range_swapped ? "swapped_" : "", range_left, range_right, range_valid ? "" : "!");
335 if (integer != 0)
336 fprintf(f, " int=%u", (int)integer);
337 if (realvalue != 0)
338 fprintf(f, " real=%e", realvalue);
339 if (!multirange_dimensions.empty()) {
340 fprintf(f, " multirange=[");
341 for (int v : multirange_dimensions)
342 fprintf(f, " %d", v);
343 fprintf(f, " ]");
344 }
345 if (!multirange_swapped.empty()) {
346 fprintf(f, " multirange_swapped=[");
347 for (auto v : multirange_swapped)
348 fprintf(f, " %d", v);
349 fprintf(f, " ]");
350 }
351 if (is_enum) {
352 fprintf(f, " type=enum");
353 }
354 fprintf(f, "\n");
355
356 for (auto &it : attributes) {
357 fprintf(f, "%s ATTR %s:\n", indent.c_str(), it.first.c_str());
358 it.second->dumpAst(f, indent + " ");
359 }
360
361 for (size_t i = 0; i < children.size(); i++)
362 children[i]->dumpAst(f, indent + " ");
363
364 fflush(f);
365 }
366
367 // helper function for AstNode::dumpVlog()
368 static std::string id2vl(std::string txt)
369 {
370 if (txt.size() > 1 && txt[0] == '\\')
371 txt = txt.substr(1);
372 for (size_t i = 0; i < txt.size(); i++) {
373 if ('A' <= txt[i] && txt[i] <= 'Z') continue;
374 if ('a' <= txt[i] && txt[i] <= 'z') continue;
375 if ('0' <= txt[i] && txt[i] <= '9') continue;
376 if (txt[i] == '_') continue;
377 txt = "\\" + txt + " ";
378 break;
379 }
380 return txt;
381 }
382
383 // dump AST node as Verilog pseudo-code
384 void AstNode::dumpVlog(FILE *f, std::string indent) const
385 {
386 bool first = true;
387 std::string txt;
388 std::vector<AstNode*> rem_children1, rem_children2;
389
390 if (f == NULL) {
391 for (auto f : log_files)
392 dumpVlog(f, indent);
393 return;
394 }
395
396 for (auto &it : attributes) {
397 fprintf(f, "%s" "(* %s = ", indent.c_str(), id2vl(it.first.str()).c_str());
398 it.second->dumpVlog(f, "");
399 fprintf(f, " *)%s", indent.empty() ? "" : "\n");
400 }
401
402 switch (type)
403 {
404 case AST_MODULE:
405 fprintf(f, "%s" "module %s(", indent.c_str(), id2vl(str).c_str());
406 for (auto child : children)
407 if (child->type == AST_WIRE && (child->is_input || child->is_output)) {
408 fprintf(f, "%s%s", first ? "" : ", ", id2vl(child->str).c_str());
409 first = false;
410 }
411 fprintf(f, ");\n");
412
413 for (auto child : children)
414 if (child->type == AST_PARAMETER || child->type == AST_LOCALPARAM || child->type == AST_DEFPARAM)
415 child->dumpVlog(f, indent + " ");
416 else
417 rem_children1.push_back(child);
418
419 for (auto child : rem_children1)
420 if (child->type == AST_WIRE || child->type == AST_AUTOWIRE || child->type == AST_MEMORY)
421 child->dumpVlog(f, indent + " ");
422 else
423 rem_children2.push_back(child);
424 rem_children1.clear();
425
426 for (auto child : rem_children2)
427 if (child->type == AST_TASK || child->type == AST_FUNCTION)
428 child->dumpVlog(f, indent + " ");
429 else
430 rem_children1.push_back(child);
431 rem_children2.clear();
432
433 for (auto child : rem_children1)
434 child->dumpVlog(f, indent + " ");
435 rem_children1.clear();
436
437 fprintf(f, "%s" "endmodule\n", indent.c_str());
438 break;
439
440 case AST_WIRE:
441 if (is_input && is_output)
442 fprintf(f, "%s" "inout", indent.c_str());
443 else if (is_input)
444 fprintf(f, "%s" "input", indent.c_str());
445 else if (is_output)
446 fprintf(f, "%s" "output", indent.c_str());
447 else if (!is_reg)
448 fprintf(f, "%s" "wire", indent.c_str());
449 if (is_reg)
450 fprintf(f, "%s" "reg", (is_input || is_output) ? " " : indent.c_str());
451 if (is_signed)
452 fprintf(f, " signed");
453 for (auto child : children) {
454 fprintf(f, " ");
455 child->dumpVlog(f, "");
456 }
457 fprintf(f, " %s", id2vl(str).c_str());
458 fprintf(f, ";\n");
459 break;
460
461 case AST_MEMORY:
462 fprintf(f, "%s" "memory", indent.c_str());
463 if (is_signed)
464 fprintf(f, " signed");
465 for (auto child : children) {
466 fprintf(f, " ");
467 child->dumpVlog(f, "");
468 if (first)
469 fprintf(f, " %s", id2vl(str).c_str());
470 first = false;
471 }
472 fprintf(f, ";\n");
473 break;
474
475 case AST_RANGE:
476 if (range_valid) {
477 if (range_swapped)
478 fprintf(f, "[%d:%d]", range_right, range_left);
479 else
480 fprintf(f, "[%d:%d]", range_left, range_right);
481 } else {
482 for (auto child : children) {
483 fprintf(f, "%c", first ? '[' : ':');
484 child->dumpVlog(f, "");
485 first = false;
486 }
487 fprintf(f, "]");
488 }
489 break;
490
491 case AST_ALWAYS:
492 fprintf(f, "%s" "always @", indent.c_str());
493 for (auto child : children) {
494 if (child->type != AST_POSEDGE && child->type != AST_NEGEDGE && child->type != AST_EDGE)
495 continue;
496 fprintf(f, first ? "(" : ", ");
497 child->dumpVlog(f, "");
498 first = false;
499 }
500 fprintf(f, first ? "*\n" : ")\n");
501 for (auto child : children) {
502 if (child->type != AST_POSEDGE && child->type != AST_NEGEDGE && child->type != AST_EDGE)
503 child->dumpVlog(f, indent + " ");
504 }
505 break;
506
507 case AST_INITIAL:
508 fprintf(f, "%s" "initial\n", indent.c_str());
509 for (auto child : children) {
510 if (child->type != AST_POSEDGE && child->type != AST_NEGEDGE && child->type != AST_EDGE)
511 child->dumpVlog(f, indent + " ");
512 }
513 break;
514
515 case AST_POSEDGE:
516 case AST_NEGEDGE:
517 case AST_EDGE:
518 if (type == AST_POSEDGE)
519 fprintf(f, "posedge ");
520 if (type == AST_NEGEDGE)
521 fprintf(f, "negedge ");
522 for (auto child : children)
523 child->dumpVlog(f, "");
524 break;
525
526 case AST_IDENTIFIER:
527 fprintf(f, "%s", id2vl(str).c_str());
528 for (auto child : children)
529 child->dumpVlog(f, "");
530 break;
531
532 case AST_CONSTANT:
533 if (!str.empty())
534 fprintf(f, "\"%s\"", str.c_str());
535 else if (bits.size() == 32)
536 fprintf(f, "%d", RTLIL::Const(bits).as_int());
537 else
538 fprintf(f, "%d'b %s", GetSize(bits), RTLIL::Const(bits).as_string().c_str());
539 break;
540
541 case AST_REALVALUE:
542 fprintf(f, "%e", realvalue);
543 break;
544
545 case AST_BLOCK:
546 if (children.size() == 1) {
547 children[0]->dumpVlog(f, indent);
548 } else {
549 fprintf(f, "%s" "begin\n", indent.c_str());
550 for (auto child : children)
551 child->dumpVlog(f, indent + " ");
552 fprintf(f, "%s" "end\n", indent.c_str());
553 }
554 break;
555
556 case AST_CASE:
557 if (children.size() > 1 && children[1]->type == AST_CONDX)
558 fprintf(f, "%s" "casex (", indent.c_str());
559 else if (children.size() > 1 && children[1]->type == AST_CONDZ)
560 fprintf(f, "%s" "casez (", indent.c_str());
561 else
562 fprintf(f, "%s" "case (", indent.c_str());
563 children[0]->dumpVlog(f, "");
564 fprintf(f, ")\n");
565 for (size_t i = 1; i < children.size(); i++) {
566 AstNode *child = children[i];
567 child->dumpVlog(f, indent + " ");
568 }
569 fprintf(f, "%s" "endcase\n", indent.c_str());
570 break;
571
572 case AST_COND:
573 case AST_CONDX:
574 case AST_CONDZ:
575 for (auto child : children) {
576 if (child->type == AST_BLOCK) {
577 fprintf(f, ":\n");
578 child->dumpVlog(f, indent + " ");
579 first = true;
580 } else {
581 fprintf(f, "%s", first ? indent.c_str() : ", ");
582 if (child->type == AST_DEFAULT)
583 fprintf(f, "default");
584 else
585 child->dumpVlog(f, "");
586 first = false;
587 }
588 }
589 break;
590
591 case AST_ASSIGN:
592 fprintf(f, "%sassign ", indent.c_str());
593 children[0]->dumpVlog(f, "");
594 fprintf(f, " = ");
595 children[1]->dumpVlog(f, "");
596 fprintf(f, ";\n");
597 break;
598
599 case AST_ASSIGN_EQ:
600 case AST_ASSIGN_LE:
601 fprintf(f, "%s", indent.c_str());
602 children[0]->dumpVlog(f, "");
603 fprintf(f, " %s ", type == AST_ASSIGN_EQ ? "=" : "<=");
604 children[1]->dumpVlog(f, "");
605 fprintf(f, ";\n");
606 break;
607
608 case AST_CONCAT:
609 fprintf(f, "{");
610 for (int i = GetSize(children)-1; i >= 0; i--) {
611 auto child = children[i];
612 if (!first)
613 fprintf(f, ", ");
614 child->dumpVlog(f, "");
615 first = false;
616 }
617 fprintf(f, "}");
618 break;
619
620 case AST_REPLICATE:
621 fprintf(f, "{");
622 children[0]->dumpVlog(f, "");
623 fprintf(f, "{");
624 children[1]->dumpVlog(f, "");
625 fprintf(f, "}}");
626 break;
627
628 if (0) { case AST_BIT_NOT: txt = "~"; }
629 if (0) { case AST_REDUCE_AND: txt = "&"; }
630 if (0) { case AST_REDUCE_OR: txt = "|"; }
631 if (0) { case AST_REDUCE_XOR: txt = "^"; }
632 if (0) { case AST_REDUCE_XNOR: txt = "~^"; }
633 if (0) { case AST_REDUCE_BOOL: txt = "|"; }
634 if (0) { case AST_POS: txt = "+"; }
635 if (0) { case AST_NEG: txt = "-"; }
636 if (0) { case AST_LOGIC_NOT: txt = "!"; }
637 if (0) { case AST_SELFSZ: txt = "@selfsz@"; }
638 fprintf(f, "%s(", txt.c_str());
639 children[0]->dumpVlog(f, "");
640 fprintf(f, ")");
641 break;
642
643 if (0) { case AST_BIT_AND: txt = "&"; }
644 if (0) { case AST_BIT_OR: txt = "|"; }
645 if (0) { case AST_BIT_XOR: txt = "^"; }
646 if (0) { case AST_BIT_XNOR: txt = "~^"; }
647 if (0) { case AST_SHIFT_LEFT: txt = "<<"; }
648 if (0) { case AST_SHIFT_RIGHT: txt = ">>"; }
649 if (0) { case AST_SHIFT_SLEFT: txt = "<<<"; }
650 if (0) { case AST_SHIFT_SRIGHT: txt = ">>>"; }
651 if (0) { case AST_SHIFTX: txt = "@shiftx@"; }
652 if (0) { case AST_SHIFT: txt = "@shift@"; }
653 if (0) { case AST_LT: txt = "<"; }
654 if (0) { case AST_LE: txt = "<="; }
655 if (0) { case AST_EQ: txt = "=="; }
656 if (0) { case AST_NE: txt = "!="; }
657 if (0) { case AST_EQX: txt = "==="; }
658 if (0) { case AST_NEX: txt = "!=="; }
659 if (0) { case AST_GE: txt = ">="; }
660 if (0) { case AST_GT: txt = ">"; }
661 if (0) { case AST_ADD: txt = "+"; }
662 if (0) { case AST_SUB: txt = "-"; }
663 if (0) { case AST_MUL: txt = "*"; }
664 if (0) { case AST_DIV: txt = "/"; }
665 if (0) { case AST_MOD: txt = "%"; }
666 if (0) { case AST_POW: txt = "**"; }
667 if (0) { case AST_LOGIC_AND: txt = "&&"; }
668 if (0) { case AST_LOGIC_OR: txt = "||"; }
669 fprintf(f, "(");
670 children[0]->dumpVlog(f, "");
671 fprintf(f, ")%s(", txt.c_str());
672 children[1]->dumpVlog(f, "");
673 fprintf(f, ")");
674 break;
675
676 case AST_TERNARY:
677 fprintf(f, "(");
678 children[0]->dumpVlog(f, "");
679 fprintf(f, ") ? (");
680 children[1]->dumpVlog(f, "");
681 fprintf(f, ") : (");
682 children[2]->dumpVlog(f, "");
683 fprintf(f, ")");
684 break;
685
686 default:
687 std::string type_name = type2str(type);
688 fprintf(f, "%s" "/** %s **/%s", indent.c_str(), type_name.c_str(), indent.empty() ? "" : "\n");
689 // dumpAst(f, indent, NULL);
690 }
691
692 fflush(f);
693 }
694
695 // check if two AST nodes are identical
696 bool AstNode::operator==(const AstNode &other) const
697 {
698 if (type != other.type)
699 return false;
700 if (children.size() != other.children.size())
701 return false;
702 if (str != other.str)
703 return false;
704 if (bits != other.bits)
705 return false;
706 if (is_input != other.is_input)
707 return false;
708 if (is_output != other.is_output)
709 return false;
710 if (is_logic != other.is_logic)
711 return false;
712 if (is_reg != other.is_reg)
713 return false;
714 if (is_signed != other.is_signed)
715 return false;
716 if (is_string != other.is_string)
717 return false;
718 if (range_valid != other.range_valid)
719 return false;
720 if (range_swapped != other.range_swapped)
721 return false;
722 if (port_id != other.port_id)
723 return false;
724 if (range_left != other.range_left)
725 return false;
726 if (range_right != other.range_right)
727 return false;
728 if (integer != other.integer)
729 return false;
730 for (size_t i = 0; i < children.size(); i++)
731 if (*children[i] != *other.children[i])
732 return false;
733 return true;
734 }
735
736 // check if two AST nodes are not identical
737 bool AstNode::operator!=(const AstNode &other) const
738 {
739 return !(*this == other);
740 }
741
742 // check if this AST contains the given node
743 bool AstNode::contains(const AstNode *other) const
744 {
745 if (this == other)
746 return true;
747 for (auto child : children)
748 if (child->contains(other))
749 return true;
750 return false;
751 }
752
753 // create an AST node for a constant (using a 32 bit int as value)
754 AstNode *AstNode::mkconst_int(uint32_t v, bool is_signed, int width)
755 {
756 AstNode *node = new AstNode(AST_CONSTANT);
757 node->integer = v;
758 node->is_signed = is_signed;
759 for (int i = 0; i < width; i++) {
760 node->bits.push_back((v & 1) ? State::S1 : State::S0);
761 v = v >> 1;
762 }
763 node->range_valid = true;
764 node->range_left = width-1;
765 node->range_right = 0;
766 return node;
767 }
768
769 // create an AST node for a constant (using a bit vector as value)
770 AstNode *AstNode::mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signed, bool is_unsized)
771 {
772 AstNode *node = new AstNode(AST_CONSTANT);
773 node->is_signed = is_signed;
774 node->bits = v;
775 for (size_t i = 0; i < 32; i++) {
776 if (i < node->bits.size())
777 node->integer |= (node->bits[i] == State::S1) << i;
778 else if (is_signed && !node->bits.empty())
779 node->integer |= (node->bits.back() == State::S1) << i;
780 }
781 node->range_valid = true;
782 node->range_left = node->bits.size()-1;
783 node->range_right = 0;
784 node->is_unsized = is_unsized;
785 return node;
786 }
787
788 AstNode *AstNode::mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signed)
789 {
790 return mkconst_bits(v, is_signed, false);
791 }
792
793 // create an AST node for a constant (using a string in bit vector form as value)
794 AstNode *AstNode::mkconst_str(const std::vector<RTLIL::State> &v)
795 {
796 AstNode *node = mkconst_str(RTLIL::Const(v).decode_string());
797 while (GetSize(node->bits) < GetSize(v))
798 node->bits.push_back(RTLIL::State::S0);
799 log_assert(node->bits == v);
800 return node;
801 }
802
803 // create an AST node for a constant (using a string as value)
804 AstNode *AstNode::mkconst_str(const std::string &str)
805 {
806 std::vector<RTLIL::State> data;
807 data.reserve(str.size() * 8);
808 for (size_t i = 0; i < str.size(); i++) {
809 unsigned char ch = str[str.size() - i - 1];
810 for (int j = 0; j < 8; j++) {
811 data.push_back((ch & 1) ? State::S1 : State::S0);
812 ch = ch >> 1;
813 }
814 }
815 AstNode *node = AstNode::mkconst_bits(data, false);
816 node->is_string = true;
817 node->str = str;
818 return node;
819 }
820
821 bool AstNode::bits_only_01() const
822 {
823 for (auto bit : bits)
824 if (bit != State::S0 && bit != State::S1)
825 return false;
826 return true;
827 }
828
829 RTLIL::Const AstNode::bitsAsUnsizedConst(int width)
830 {
831 RTLIL::State extbit = bits.back();
832 while (width > int(bits.size()))
833 bits.push_back(extbit);
834 return RTLIL::Const(bits);
835 }
836
837 RTLIL::Const AstNode::bitsAsConst(int width, bool is_signed)
838 {
839 std::vector<RTLIL::State> bits = this->bits;
840 if (width >= 0 && width < int(bits.size()))
841 bits.resize(width);
842 if (width >= 0 && width > int(bits.size())) {
843 RTLIL::State extbit = RTLIL::State::S0;
844 if (is_signed && !bits.empty())
845 extbit = bits.back();
846 while (width > int(bits.size()))
847 bits.push_back(extbit);
848 }
849 return RTLIL::Const(bits);
850 }
851
852 RTLIL::Const AstNode::bitsAsConst(int width)
853 {
854 return bitsAsConst(width, is_signed);
855 }
856
857 RTLIL::Const AstNode::asAttrConst()
858 {
859 log_assert(type == AST_CONSTANT);
860
861 RTLIL::Const val;
862 val.bits = bits;
863
864 if (is_string) {
865 val.flags |= RTLIL::CONST_FLAG_STRING;
866 log_assert(val.decode_string() == str);
867 }
868
869 return val;
870 }
871
872 RTLIL::Const AstNode::asParaConst()
873 {
874 RTLIL::Const val = asAttrConst();
875 if (is_signed)
876 val.flags |= RTLIL::CONST_FLAG_SIGNED;
877 return val;
878 }
879
880 bool AstNode::asBool() const
881 {
882 log_assert(type == AST_CONSTANT);
883 for (auto &bit : bits)
884 if (bit == RTLIL::State::S1)
885 return true;
886 return false;
887 }
888
889 int AstNode::isConst() const
890 {
891 if (type == AST_CONSTANT)
892 return 1;
893 if (type == AST_REALVALUE)
894 return 2;
895 return 0;
896 }
897
898 uint64_t AstNode::asInt(bool is_signed)
899 {
900 if (type == AST_CONSTANT)
901 {
902 RTLIL::Const v = bitsAsConst(64, is_signed);
903 uint64_t ret = 0;
904
905 for (int i = 0; i < 64; i++)
906 if (v.bits.at(i) == RTLIL::State::S1)
907 ret |= uint64_t(1) << i;
908
909 return ret;
910 }
911
912 if (type == AST_REALVALUE)
913 return uint64_t(realvalue);
914
915 log_abort();
916 }
917
918 double AstNode::asReal(bool is_signed)
919 {
920 if (type == AST_CONSTANT)
921 {
922 RTLIL::Const val(bits);
923
924 bool is_negative = is_signed && !val.bits.empty() && val.bits.back() == RTLIL::State::S1;
925 if (is_negative)
926 val = const_neg(val, val, false, false, val.bits.size());
927
928 double v = 0;
929 for (size_t i = 0; i < val.bits.size(); i++)
930 // IEEE Std 1800-2012 Par 6.12.2: Individual bits that are x or z in
931 // the net or the variable shall be treated as zero upon conversion.
932 if (val.bits.at(i) == RTLIL::State::S1)
933 v += exp2(i);
934 if (is_negative)
935 v *= -1;
936
937 return v;
938 }
939
940 if (type == AST_REALVALUE)
941 return realvalue;
942
943 log_abort();
944 }
945
946 RTLIL::Const AstNode::realAsConst(int width)
947 {
948 double v = round(realvalue);
949 RTLIL::Const result;
950 #ifdef EMSCRIPTEN
951 if (!isfinite(v)) {
952 #else
953 if (!std::isfinite(v)) {
954 #endif
955 result.bits = std::vector<RTLIL::State>(width, RTLIL::State::Sx);
956 } else {
957 bool is_negative = v < 0;
958 if (is_negative)
959 v *= -1;
960 for (int i = 0; i < width; i++, v /= 2)
961 result.bits.push_back((fmod(floor(v), 2) != 0) ? RTLIL::State::S1 : RTLIL::State::S0);
962 if (is_negative)
963 result = const_neg(result, result, false, false, result.bits.size());
964 }
965 return result;
966 }
967
968 std::string AstNode::loc_string() const
969 {
970 return stringf("%s:%d.%d-%d.%d", filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column);
971 }
972
973 void AST::set_src_attr(RTLIL::AttrObject *obj, const AstNode *ast)
974 {
975 obj->attributes[ID::src] = ast->loc_string();
976 }
977
978 static bool param_has_no_default(const AstNode *param) {
979 const auto &children = param->children;
980 log_assert(param->type == AST_PARAMETER);
981 log_assert(children.size() <= 2);
982 return children.empty() ||
983 (children.size() == 1 && children[0]->type == AST_RANGE);
984 }
985
986 // create and add a new AstModule from an AST_MODULE AST node
987 static void process_module(RTLIL::Design *design, AstNode *ast, bool defer, AstNode *original_ast = NULL, bool quiet = false)
988 {
989 log_assert(current_scope.empty());
990 log_assert(ast->type == AST_MODULE || ast->type == AST_INTERFACE);
991
992 if (defer)
993 log("Storing AST representation for module `%s'.\n", ast->str.c_str());
994 else if (!quiet) {
995 log("Generating RTLIL representation for module `%s'.\n", ast->str.c_str());
996 }
997
998 AstModule *module = new AstModule;
999 current_module = module;
1000
1001 module->ast = NULL;
1002 module->name = ast->str;
1003 set_src_attr(module, ast);
1004 module->set_bool_attribute(ID::cells_not_processed);
1005
1006 current_ast_mod = ast;
1007 AstNode *ast_before_simplify;
1008 if (original_ast != NULL)
1009 ast_before_simplify = original_ast;
1010 else
1011 ast_before_simplify = ast->clone();
1012
1013 if (flag_dump_ast1) {
1014 log("Dumping AST before simplification:\n");
1015 ast->dumpAst(NULL, " ");
1016 log("--- END OF AST DUMP ---\n");
1017 }
1018 if (flag_dump_vlog1) {
1019 log("Dumping Verilog AST before simplification:\n");
1020 ast->dumpVlog(NULL, " ");
1021 log("--- END OF AST DUMP ---\n");
1022 }
1023
1024 if (!defer)
1025 {
1026 for (const AstNode *node : ast->children)
1027 if (node->type == AST_PARAMETER && param_has_no_default(node))
1028 log_file_error(node->filename, node->location.first_line, "Parameter `%s' has no default value and has not been overridden!\n", node->str.c_str());
1029
1030 bool blackbox_module = flag_lib;
1031
1032 if (!blackbox_module && !flag_noblackbox) {
1033 blackbox_module = true;
1034 for (auto child : ast->children) {
1035 if (child->type == AST_WIRE && (child->is_input || child->is_output))
1036 continue;
1037 if (child->type == AST_PARAMETER || child->type == AST_LOCALPARAM)
1038 continue;
1039 if (child->type == AST_CELL && child->children.size() > 0 && child->children[0]->type == AST_CELLTYPE &&
1040 (child->children[0]->str == "$specify2" || child->children[0]->str == "$specify3" || child->children[0]->str == "$specrule"))
1041 continue;
1042 blackbox_module = false;
1043 break;
1044 }
1045 }
1046
1047 // TODO(zachjs): make design available to simplify() in the future
1048 while (ast->simplify(!flag_noopt, false, false, 0, -1, false, false)) { }
1049
1050 if (flag_dump_ast2) {
1051 log("Dumping AST after simplification:\n");
1052 ast->dumpAst(NULL, " ");
1053 log("--- END OF AST DUMP ---\n");
1054 }
1055
1056 if (flag_dump_vlog2) {
1057 log("Dumping Verilog AST after simplification:\n");
1058 ast->dumpVlog(NULL, " ");
1059 log("--- END OF AST DUMP ---\n");
1060 }
1061
1062 if (flag_nowb && ast->attributes.count(ID::whitebox)) {
1063 delete ast->attributes.at(ID::whitebox);
1064 ast->attributes.erase(ID::whitebox);
1065 }
1066
1067 if (ast->attributes.count(ID::lib_whitebox)) {
1068 if (!flag_lib || flag_nowb) {
1069 delete ast->attributes.at(ID::lib_whitebox);
1070 ast->attributes.erase(ID::lib_whitebox);
1071 } else {
1072 if (ast->attributes.count(ID::whitebox)) {
1073 delete ast->attributes.at(ID::whitebox);
1074 ast->attributes.erase(ID::whitebox);
1075 }
1076 AstNode *n = ast->attributes.at(ID::lib_whitebox);
1077 ast->attributes[ID::whitebox] = n;
1078 ast->attributes.erase(ID::lib_whitebox);
1079 }
1080 }
1081
1082 if (!blackbox_module && ast->attributes.count(ID::blackbox)) {
1083 AstNode *n = ast->attributes.at(ID::blackbox);
1084 if (n->type != AST_CONSTANT)
1085 log_file_error(ast->filename, ast->location.first_line, "Got blackbox attribute with non-constant value!\n");
1086 blackbox_module = n->asBool();
1087 }
1088
1089 if (blackbox_module && ast->attributes.count(ID::whitebox)) {
1090 AstNode *n = ast->attributes.at(ID::whitebox);
1091 if (n->type != AST_CONSTANT)
1092 log_file_error(ast->filename, ast->location.first_line, "Got whitebox attribute with non-constant value!\n");
1093 blackbox_module = !n->asBool();
1094 }
1095
1096 if (ast->attributes.count(ID::noblackbox)) {
1097 if (blackbox_module) {
1098 AstNode *n = ast->attributes.at(ID::noblackbox);
1099 if (n->type != AST_CONSTANT)
1100 log_file_error(ast->filename, ast->location.first_line, "Got noblackbox attribute with non-constant value!\n");
1101 blackbox_module = !n->asBool();
1102 }
1103 delete ast->attributes.at(ID::noblackbox);
1104 ast->attributes.erase(ID::noblackbox);
1105 }
1106
1107 if (blackbox_module)
1108 {
1109 if (ast->attributes.count(ID::whitebox)) {
1110 delete ast->attributes.at(ID::whitebox);
1111 ast->attributes.erase(ID::whitebox);
1112 }
1113
1114 if (ast->attributes.count(ID::lib_whitebox)) {
1115 delete ast->attributes.at(ID::lib_whitebox);
1116 ast->attributes.erase(ID::lib_whitebox);
1117 }
1118
1119 std::vector<AstNode*> new_children;
1120 for (auto child : ast->children) {
1121 if (child->type == AST_WIRE && (child->is_input || child->is_output)) {
1122 new_children.push_back(child);
1123 } else if (child->type == AST_PARAMETER) {
1124 new_children.push_back(child);
1125 } else if (child->type == AST_CELL && child->children.size() > 0 && child->children[0]->type == AST_CELLTYPE &&
1126 (child->children[0]->str == "$specify2" || child->children[0]->str == "$specify3" || child->children[0]->str == "$specrule")) {
1127 new_children.push_back(child);
1128 } else {
1129 delete child;
1130 }
1131 }
1132
1133 ast->children.swap(new_children);
1134
1135 if (ast->attributes.count(ID::blackbox) == 0) {
1136 ast->attributes[ID::blackbox] = AstNode::mkconst_int(1, false);
1137 }
1138 }
1139
1140 ignoreThisSignalsInInitial = RTLIL::SigSpec();
1141
1142 for (auto &attr : ast->attributes) {
1143 if (attr.second->type != AST_CONSTANT)
1144 log_file_error(ast->filename, ast->location.first_line, "Attribute `%s' with non-constant value!\n", attr.first.c_str());
1145 module->attributes[attr.first] = attr.second->asAttrConst();
1146 }
1147 for (size_t i = 0; i < ast->children.size(); i++) {
1148 AstNode *node = ast->children[i];
1149 if (node->type == AST_WIRE || node->type == AST_MEMORY)
1150 node->genRTLIL();
1151 }
1152 for (size_t i = 0; i < ast->children.size(); i++) {
1153 AstNode *node = ast->children[i];
1154 if (node->type != AST_WIRE && node->type != AST_MEMORY && node->type != AST_INITIAL)
1155 node->genRTLIL();
1156 }
1157
1158 ignoreThisSignalsInInitial.sort_and_unify();
1159
1160 for (size_t i = 0; i < ast->children.size(); i++) {
1161 AstNode *node = ast->children[i];
1162 if (node->type == AST_INITIAL)
1163 node->genRTLIL();
1164 }
1165
1166 ignoreThisSignalsInInitial = RTLIL::SigSpec();
1167 current_scope.clear();
1168 }
1169 else {
1170 for (auto &attr : ast->attributes) {
1171 if (attr.second->type != AST_CONSTANT)
1172 continue;
1173 module->attributes[attr.first] = attr.second->asAttrConst();
1174 }
1175 }
1176
1177 if (ast->type == AST_INTERFACE)
1178 module->set_bool_attribute(ID::is_interface);
1179 module->ast = ast_before_simplify;
1180 module->nolatches = flag_nolatches;
1181 module->nomeminit = flag_nomeminit;
1182 module->nomem2reg = flag_nomem2reg;
1183 module->mem2reg = flag_mem2reg;
1184 module->noblackbox = flag_noblackbox;
1185 module->lib = flag_lib;
1186 module->nowb = flag_nowb;
1187 module->noopt = flag_noopt;
1188 module->icells = flag_icells;
1189 module->pwires = flag_pwires;
1190 module->autowire = flag_autowire;
1191 module->fixup_ports();
1192
1193 if (flag_dump_rtlil) {
1194 log("Dumping generated RTLIL:\n");
1195 log_module(module);
1196 log("--- END OF RTLIL DUMP ---\n");
1197 }
1198
1199 design->add(current_module);
1200 }
1201
1202 // renames identifiers in tasks and functions within a package
1203 static void rename_in_package_stmts(AstNode *pkg)
1204 {
1205 std::unordered_set<std::string> idents;
1206 for (AstNode *item : pkg->children)
1207 idents.insert(item->str);
1208 std::function<void(AstNode*)> rename =
1209 [&rename, &idents, pkg](AstNode *node) {
1210 for (AstNode *child : node->children) {
1211 if (idents.count(child->str))
1212 child->str = pkg->str + "::" + child->str.substr(1);
1213 rename(child);
1214 }
1215 };
1216 for (AstNode *item : pkg->children)
1217 if (item->type == AST_FUNCTION || item->type == AST_TASK)
1218 rename(item);
1219 }
1220
1221 // create AstModule instances for all modules in the AST tree and add them to 'design'
1222 void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump_ast2, bool no_dump_ptr, bool dump_vlog1, bool dump_vlog2, bool dump_rtlil,
1223 bool nolatches, bool nomeminit, bool nomem2reg, bool mem2reg, bool noblackbox, bool lib, bool nowb, bool noopt, bool icells, bool pwires, bool nooverwrite, bool overwrite, bool defer, bool autowire)
1224 {
1225 current_ast = ast;
1226 current_ast_mod = nullptr;
1227 flag_dump_ast1 = dump_ast1;
1228 flag_dump_ast2 = dump_ast2;
1229 flag_no_dump_ptr = no_dump_ptr;
1230 flag_dump_vlog1 = dump_vlog1;
1231 flag_dump_vlog2 = dump_vlog2;
1232 flag_dump_rtlil = dump_rtlil;
1233 flag_nolatches = nolatches;
1234 flag_nomeminit = nomeminit;
1235 flag_nomem2reg = nomem2reg;
1236 flag_mem2reg = mem2reg;
1237 flag_noblackbox = noblackbox;
1238 flag_lib = lib;
1239 flag_nowb = nowb;
1240 flag_noopt = noopt;
1241 flag_icells = icells;
1242 flag_pwires = pwires;
1243 flag_autowire = autowire;
1244
1245 log_assert(current_ast->type == AST_DESIGN);
1246 for (AstNode *child : current_ast->children)
1247 {
1248 if (child->type == AST_MODULE || child->type == AST_INTERFACE)
1249 {
1250 for (auto n : design->verilog_globals)
1251 child->children.push_back(n->clone());
1252
1253 // append nodes from previous packages using package-qualified names
1254 for (auto &n : design->verilog_packages) {
1255 for (auto &o : n->children) {
1256 AstNode *cloned_node = o->clone();
1257 // log("cloned node %s\n", type2str(cloned_node->type).c_str());
1258 if (cloned_node->type == AST_ENUM) {
1259 for (auto &e : cloned_node->children) {
1260 log_assert(e->type == AST_ENUM_ITEM);
1261 e->str = n->str + std::string("::") + e->str.substr(1);
1262 }
1263 } else {
1264 cloned_node->str = n->str + std::string("::") + cloned_node->str.substr(1);
1265 }
1266 child->children.push_back(cloned_node);
1267 }
1268 }
1269
1270 if (flag_icells && child->str.compare(0, 2, "\\$") == 0)
1271 child->str = child->str.substr(1);
1272
1273 bool defer_local = defer;
1274 if (!defer_local)
1275 for (const AstNode *node : child->children)
1276 if (node->type == AST_PARAMETER && param_has_no_default(node))
1277 {
1278 log("Deferring `%s' because it contains parameter(s) without defaults.\n", child->str.c_str());
1279 defer_local = true;
1280 break;
1281 }
1282
1283
1284 if (defer_local)
1285 child->str = "$abstract" + child->str;
1286
1287 if (design->has(child->str)) {
1288 RTLIL::Module *existing_mod = design->module(child->str);
1289 if (!nooverwrite && !overwrite && !existing_mod->get_blackbox_attribute()) {
1290 log_file_error(child->filename, child->location.first_line, "Re-definition of module `%s'!\n", child->str.c_str());
1291 } else if (nooverwrite) {
1292 log("Ignoring re-definition of module `%s' at %s.\n",
1293 child->str.c_str(), child->loc_string().c_str());
1294 continue;
1295 } else {
1296 log("Replacing existing%s module `%s' at %s.\n",
1297 existing_mod->get_bool_attribute(ID::blackbox) ? " blackbox" : "",
1298 child->str.c_str(), child->loc_string().c_str());
1299 design->remove(existing_mod);
1300 }
1301 }
1302
1303 process_module(design, child, defer_local);
1304 current_ast_mod = nullptr;
1305 }
1306 else if (child->type == AST_PACKAGE) {
1307 // process enum/other declarations
1308 child->simplify(true, false, false, 1, -1, false, false);
1309 rename_in_package_stmts(child);
1310 design->verilog_packages.push_back(child->clone());
1311 current_scope.clear();
1312 }
1313 else if (child->type == AST_BIND) {
1314 // top-level bind construct
1315 for (RTLIL::Binding *binding : child->genBindings())
1316 design->add(binding);
1317 }
1318 else {
1319 // must be global definition
1320 if (child->type == AST_PARAMETER)
1321 child->type = AST_LOCALPARAM; // cannot be overridden
1322 design->verilog_globals.push_back(child->clone());
1323 current_scope.clear();
1324 }
1325 }
1326 }
1327
1328 // AstModule destructor
1329 AstModule::~AstModule()
1330 {
1331 if (ast != NULL)
1332 delete ast;
1333 }
1334
1335
1336 // An interface port with modport is specified like this:
1337 // <interface_name>.<modport_name>
1338 // This function splits the interface_name from the modport_name, and fails if it is not a valid combination
1339 std::pair<std::string,std::string> AST::split_modport_from_type(std::string name_type)
1340 {
1341 std::string interface_type = "";
1342 std::string interface_modport = "";
1343 size_t ndots = std::count(name_type.begin(), name_type.end(), '.');
1344 // Separate the interface instance name from any modports:
1345 if (ndots == 0) { // Does not have modport
1346 interface_type = name_type;
1347 }
1348 else {
1349 std::stringstream name_type_stream(name_type);
1350 std::string segment;
1351 std::vector<std::string> seglist;
1352 while(std::getline(name_type_stream, segment, '.')) {
1353 seglist.push_back(segment);
1354 }
1355 if (ndots == 1) { // Has modport
1356 interface_type = seglist[0];
1357 interface_modport = seglist[1];
1358 }
1359 else { // Erroneous port type
1360 log_error("More than two '.' in signal port type (%s)\n", name_type.c_str());
1361 }
1362 }
1363 return std::pair<std::string,std::string>(interface_type, interface_modport);
1364
1365 }
1366
1367 AstNode * AST::find_modport(AstNode *intf, std::string name)
1368 {
1369 for (auto &ch : intf->children)
1370 if (ch->type == AST_MODPORT)
1371 if (ch->str == name) // Modport found
1372 return ch;
1373 return NULL;
1374 }
1375
1376 // Iterate over all wires in an interface and add them as wires in the AST module:
1377 void AST::explode_interface_port(AstNode *module_ast, RTLIL::Module * intfmodule, std::string intfname, AstNode *modport)
1378 {
1379 for (auto w : intfmodule->wires()){
1380 AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, AstNode::mkconst_int(w->width -1, true), AstNode::mkconst_int(0, true)));
1381 std::string origname = log_id(w->name);
1382 std::string newname = intfname + "." + origname;
1383 wire->str = newname;
1384 if (modport != NULL) {
1385 bool found_in_modport = false;
1386 // Search for the current wire in the wire list for the current modport
1387 for (auto &ch : modport->children) {
1388 if (ch->type == AST_MODPORTMEMBER) {
1389 std::string compare_name = "\\" + origname;
1390 if (ch->str == compare_name) { // Found signal. The modport decides whether it is input or output
1391 found_in_modport = true;
1392 wire->is_input = ch->is_input;
1393 wire->is_output = ch->is_output;
1394 break;
1395 }
1396 }
1397 }
1398 if (found_in_modport) {
1399 module_ast->children.push_back(wire);
1400 }
1401 else { // If not found in modport, do not create port
1402 delete wire;
1403 }
1404 }
1405 else { // If no modport, set inout
1406 wire->is_input = true;
1407 wire->is_output = true;
1408 module_ast->children.push_back(wire);
1409 }
1410 }
1411 }
1412
1413 // When an interface instance is found in a module, the whole RTLIL for the module will be rederived again
1414 // from AST. The interface members are copied into the AST module with the prefix of the interface.
1415 void AstModule::reprocess_module(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Module*> &local_interfaces)
1416 {
1417 loadconfig();
1418
1419 bool is_top = false;
1420 AstNode *new_ast = ast->clone();
1421 for (auto &intf : local_interfaces) {
1422 std::string intfname = intf.first.str();
1423 RTLIL::Module *intfmodule = intf.second;
1424 for (auto w : intfmodule->wires()){
1425 AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, AstNode::mkconst_int(w->width -1, true), AstNode::mkconst_int(0, true)));
1426 std::string newname = log_id(w->name);
1427 newname = intfname + "." + newname;
1428 wire->str = newname;
1429 new_ast->children.push_back(wire);
1430 }
1431 }
1432
1433 AstNode *ast_before_replacing_interface_ports = new_ast->clone();
1434
1435 // Explode all interface ports. Note this will only have an effect on 'top
1436 // level' modules. Other sub-modules will have their interface ports
1437 // exploded via the derive(..) function
1438 for (size_t i =0; i<new_ast->children.size(); i++)
1439 {
1440 AstNode *ch2 = new_ast->children[i];
1441 if (ch2->type == AST_INTERFACEPORT) { // Is an interface port
1442 std::string name_port = ch2->str; // Name of the interface port
1443 if (ch2->children.size() > 0) {
1444 for(size_t j=0; j<ch2->children.size();j++) {
1445 AstNode *ch = ch2->children[j];
1446 if(ch->type == AST_INTERFACEPORTTYPE) { // Found the AST node containing the type of the interface
1447 std::pair<std::string,std::string> res = split_modport_from_type(ch->str);
1448 std::string interface_type = res.first;
1449 std::string interface_modport = res.second; // Is "", if no modport
1450 if (design->module(interface_type) != nullptr) {
1451 // Add a cell to the module corresponding to the interface port such that
1452 // it can further propagated down if needed:
1453 AstNode *celltype_for_intf = new AstNode(AST_CELLTYPE);
1454 celltype_for_intf->str = interface_type;
1455 AstNode *cell_for_intf = new AstNode(AST_CELL, celltype_for_intf);
1456 cell_for_intf->str = name_port + "_inst_from_top_dummy";
1457 new_ast->children.push_back(cell_for_intf);
1458
1459 // Get all members of this non-overridden dummy interface instance:
1460 RTLIL::Module *intfmodule = design->module(interface_type); // All interfaces should at this point in time (assuming
1461 // reprocess_module is called from the hierarchy pass) be
1462 // present in design->modules_
1463 AstModule *ast_module_of_interface = (AstModule*)intfmodule;
1464 std::string interface_modport_compare_str = "\\" + interface_modport;
1465 AstNode *modport = find_modport(ast_module_of_interface->ast, interface_modport_compare_str); // modport == NULL if no modport
1466 // Iterate over all wires in the interface and add them to the module:
1467 explode_interface_port(new_ast, intfmodule, name_port, modport);
1468 }
1469 break;
1470 }
1471 }
1472 }
1473 }
1474 }
1475
1476 // The old module will be deleted. Rename and mark for deletion:
1477 std::string original_name = this->name.str();
1478 std::string changed_name = original_name + "_before_replacing_local_interfaces";
1479 design->rename(this, changed_name);
1480 this->set_bool_attribute(ID::to_delete);
1481
1482 // Check if the module was the top module. If it was, we need to remove the top attribute and put it on the
1483 // new module.
1484 if (this->get_bool_attribute(ID::initial_top)) {
1485 this->attributes.erase(ID::initial_top);
1486 is_top = true;
1487 }
1488
1489 // Generate RTLIL from AST for the new module and add to the design:
1490 process_module(design, new_ast, false, ast_before_replacing_interface_ports);
1491 delete(new_ast);
1492 RTLIL::Module* mod = design->module(original_name);
1493 if (is_top)
1494 mod->set_bool_attribute(ID::top);
1495
1496 // Set the attribute "interfaces_replaced_in_module" so that it does not happen again.
1497 mod->set_bool_attribute(ID::interfaces_replaced_in_module);
1498 }
1499
1500 // create a new parametric module (when needed) and return the name of the generated module - WITH support for interfaces
1501 // This method is used to explode the interface when the interface is a port of the module (not instantiated inside)
1502 RTLIL::IdString AstModule::derive(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> &parameters, const dict<RTLIL::IdString, RTLIL::Module*> &interfaces, const dict<RTLIL::IdString, RTLIL::IdString> &modports, bool /*mayfail*/)
1503 {
1504 AstNode *new_ast = NULL;
1505 std::string modname = derive_common(design, parameters, &new_ast);
1506
1507 // Since interfaces themselves may be instantiated with different parameters,
1508 // "modname" must also take those into account, so that unique modules
1509 // are derived for any variant of interface connections:
1510 std::string interf_info = "";
1511
1512 bool has_interfaces = false;
1513 for(auto &intf : interfaces) {
1514 interf_info += log_id(intf.second->name);
1515 has_interfaces = true;
1516 }
1517
1518 std::string new_modname = modname;
1519 if (has_interfaces)
1520 new_modname += "$interfaces$" + interf_info;
1521
1522
1523 if (!design->has(new_modname)) {
1524 if (!new_ast) {
1525 auto mod = dynamic_cast<AstModule*>(design->module(modname));
1526 new_ast = mod->ast->clone();
1527 }
1528 modname = new_modname;
1529 new_ast->str = modname;
1530
1531 // Iterate over all interfaces which are ports in this module:
1532 for(auto &intf : interfaces) {
1533 RTLIL::Module * intfmodule = intf.second;
1534 std::string intfname = intf.first.str();
1535 // Check if a modport applies for the interface port:
1536 AstNode *modport = NULL;
1537 if (modports.count(intfname) > 0) {
1538 std::string interface_modport = modports.at(intfname).str();
1539 AstModule *ast_module_of_interface = (AstModule*)intfmodule;
1540 AstNode *ast_node_of_interface = ast_module_of_interface->ast;
1541 modport = find_modport(ast_node_of_interface, interface_modport);
1542 }
1543 // Iterate over all wires in the interface and add them to the module:
1544 explode_interface_port(new_ast, intfmodule, intfname, modport);
1545 }
1546
1547 process_module(design, new_ast, false);
1548 design->module(modname)->check();
1549
1550 RTLIL::Module* mod = design->module(modname);
1551
1552 // Now that the interfaces have been exploded, we can delete the dummy port related to every interface.
1553 for(auto &intf : interfaces) {
1554 if(mod->wire(intf.first) != nullptr) {
1555 // Normally, removing wires would be batched together as it's an
1556 // expensive operation, however, in this case doing so would mean
1557 // that a cell with the same name cannot be created (below)...
1558 // Since we won't expect many interfaces to exist in a module,
1559 // we can let this slide...
1560 pool<RTLIL::Wire*> to_remove;
1561 to_remove.insert(mod->wire(intf.first));
1562 mod->remove(to_remove);
1563 mod->fixup_ports();
1564 // We copy the cell of the interface to the sub-module such that it
1565 // can further be found if it is propagated down to sub-sub-modules etc.
1566 RTLIL::Cell *new_subcell = mod->addCell(intf.first, intf.second->name);
1567 new_subcell->set_bool_attribute(ID::is_interface);
1568 }
1569 else {
1570 log_error("No port with matching name found (%s) in %s. Stopping\n", log_id(intf.first), modname.c_str());
1571 }
1572 }
1573
1574 // If any interfaces were replaced, set the attribute 'interfaces_replaced_in_module':
1575 if (interfaces.size() > 0) {
1576 mod->set_bool_attribute(ID::interfaces_replaced_in_module);
1577 }
1578
1579 } else {
1580 modname = new_modname;
1581 log("Found cached RTLIL representation for module `%s'.\n", modname.c_str());
1582 }
1583
1584 delete new_ast;
1585 return modname;
1586 }
1587
1588 // create a new parametric module (when needed) and return the name of the generated module - without support for interfaces
1589 RTLIL::IdString AstModule::derive(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> &parameters, bool /*mayfail*/)
1590 {
1591 bool quiet = lib || attributes.count(ID::blackbox) || attributes.count(ID::whitebox);
1592
1593 AstNode *new_ast = NULL;
1594 std::string modname = derive_common(design, parameters, &new_ast, quiet);
1595
1596 if (!design->has(modname)) {
1597 new_ast->str = modname;
1598 process_module(design, new_ast, false, NULL, quiet);
1599 design->module(modname)->check();
1600 } else if (!quiet) {
1601 log("Found cached RTLIL representation for module `%s'.\n", modname.c_str());
1602 }
1603
1604 delete new_ast;
1605 return modname;
1606 }
1607
1608 static std::string serialize_param_value(const RTLIL::Const &val) {
1609 std::string res;
1610 if (val.flags & RTLIL::ConstFlags::CONST_FLAG_STRING)
1611 res.push_back('t');
1612 if (val.flags & RTLIL::ConstFlags::CONST_FLAG_SIGNED)
1613 res.push_back('s');
1614 if (val.flags & RTLIL::ConstFlags::CONST_FLAG_REAL)
1615 res.push_back('r');
1616 res += stringf("%d", GetSize(val));
1617 res.push_back('\'');
1618 for (int i = GetSize(val) - 1; i >= 0; i--) {
1619 switch (val.bits[i]) {
1620 case RTLIL::State::S0: res.push_back('0'); break;
1621 case RTLIL::State::S1: res.push_back('1'); break;
1622 case RTLIL::State::Sx: res.push_back('x'); break;
1623 case RTLIL::State::Sz: res.push_back('z'); break;
1624 case RTLIL::State::Sa: res.push_back('?'); break;
1625 case RTLIL::State::Sm: res.push_back('m'); break;
1626 }
1627 }
1628 return res;
1629 }
1630
1631 // create a new parametric module (when needed) and return the name of the generated module
1632 std::string AstModule::derive_common(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> &parameters, AstNode **new_ast_out, bool quiet)
1633 {
1634 std::string stripped_name = name.str();
1635
1636 if (stripped_name.compare(0, 9, "$abstract") == 0)
1637 stripped_name = stripped_name.substr(9);
1638
1639 std::string para_info;
1640
1641 int para_counter = 0;
1642 for (const auto child : ast->children) {
1643 if (child->type != AST_PARAMETER)
1644 continue;
1645 para_counter++;
1646 auto it = parameters.find(child->str);
1647 if (it != parameters.end()) {
1648 if (!quiet)
1649 log("Parameter %s = %s\n", child->str.c_str(), log_signal(it->second));
1650 para_info += stringf("%s=%s", child->str.c_str(), serialize_param_value(it->second).c_str());
1651 continue;
1652 }
1653 it = parameters.find(stringf("$%d", para_counter));
1654 if (it != parameters.end()) {
1655 if (!quiet)
1656 log("Parameter %d (%s) = %s\n", para_counter, child->str.c_str(), log_signal(it->second));
1657 para_info += stringf("%s=%s", child->str.c_str(), serialize_param_value(it->second).c_str());
1658 continue;
1659 }
1660 }
1661
1662 std::string modname;
1663 if (parameters.size() == 0)
1664 modname = stripped_name;
1665 else if (para_info.size() > 60)
1666 modname = "$paramod$" + sha1(para_info) + stripped_name;
1667 else
1668 modname = "$paramod" + stripped_name + para_info;
1669
1670 if (design->has(modname))
1671 return modname;
1672
1673 if (!quiet)
1674 log_header(design, "Executing AST frontend in derive mode using pre-parsed AST for module `%s'.\n", stripped_name.c_str());
1675 loadconfig();
1676
1677 pool<IdString> rewritten;
1678 rewritten.reserve(GetSize(parameters));
1679
1680 AstNode *new_ast = ast->clone();
1681 if (!new_ast->attributes.count(ID::hdlname))
1682 new_ast->attributes[ID::hdlname] = AstNode::mkconst_str(stripped_name);
1683
1684 para_counter = 0;
1685 for (auto child : new_ast->children) {
1686 if (child->type != AST_PARAMETER)
1687 continue;
1688 para_counter++;
1689 auto it = parameters.find(child->str);
1690 if (it != parameters.end()) {
1691 if (!quiet)
1692 log("Parameter %s = %s\n", child->str.c_str(), log_signal(it->second));
1693 goto rewrite_parameter;
1694 }
1695 it = parameters.find(stringf("$%d", para_counter));
1696 if (it != parameters.end()) {
1697 if (!quiet)
1698 log("Parameter %d (%s) = %s\n", para_counter, child->str.c_str(), log_signal(it->second));
1699 goto rewrite_parameter;
1700 }
1701 continue;
1702 rewrite_parameter:
1703 if (param_has_no_default(child))
1704 child->children.insert(child->children.begin(), nullptr);
1705 delete child->children.at(0);
1706 if ((it->second.flags & RTLIL::CONST_FLAG_REAL) != 0) {
1707 child->children[0] = new AstNode(AST_REALVALUE);
1708 child->children[0]->realvalue = std::stod(it->second.decode_string());
1709 } else if ((it->second.flags & RTLIL::CONST_FLAG_STRING) != 0)
1710 child->children[0] = AstNode::mkconst_str(it->second.decode_string());
1711 else
1712 child->children[0] = AstNode::mkconst_bits(it->second.bits, (it->second.flags & RTLIL::CONST_FLAG_SIGNED) != 0);
1713 rewritten.insert(it->first);
1714 }
1715
1716 if (GetSize(rewritten) < GetSize(parameters))
1717 for (const auto &param : parameters) {
1718 if (rewritten.count(param.first))
1719 continue;
1720 AstNode *defparam = new AstNode(AST_DEFPARAM, new AstNode(AST_IDENTIFIER));
1721 defparam->children[0]->str = param.first.str();
1722 if ((param.second.flags & RTLIL::CONST_FLAG_STRING) != 0)
1723 defparam->children.push_back(AstNode::mkconst_str(param.second.decode_string()));
1724 else
1725 defparam->children.push_back(AstNode::mkconst_bits(param.second.bits, (param.second.flags & RTLIL::CONST_FLAG_SIGNED) != 0));
1726 new_ast->children.push_back(defparam);
1727 }
1728
1729 (*new_ast_out) = new_ast;
1730 return modname;
1731 }
1732
1733 RTLIL::Module *AstModule::clone() const
1734 {
1735 AstModule *new_mod = new AstModule;
1736 new_mod->name = name;
1737 cloneInto(new_mod);
1738
1739 new_mod->ast = ast->clone();
1740 new_mod->nolatches = nolatches;
1741 new_mod->nomeminit = nomeminit;
1742 new_mod->nomem2reg = nomem2reg;
1743 new_mod->mem2reg = mem2reg;
1744 new_mod->noblackbox = noblackbox;
1745 new_mod->lib = lib;
1746 new_mod->nowb = nowb;
1747 new_mod->noopt = noopt;
1748 new_mod->icells = icells;
1749 new_mod->pwires = pwires;
1750 new_mod->autowire = autowire;
1751
1752 return new_mod;
1753 }
1754
1755 void AstModule::loadconfig() const
1756 {
1757 current_ast = NULL;
1758 flag_dump_ast1 = false;
1759 flag_dump_ast2 = false;
1760 flag_dump_vlog1 = false;
1761 flag_dump_vlog2 = false;
1762 flag_nolatches = nolatches;
1763 flag_nomeminit = nomeminit;
1764 flag_nomem2reg = nomem2reg;
1765 flag_mem2reg = mem2reg;
1766 flag_noblackbox = noblackbox;
1767 flag_lib = lib;
1768 flag_nowb = nowb;
1769 flag_noopt = noopt;
1770 flag_icells = icells;
1771 flag_pwires = pwires;
1772 flag_autowire = autowire;
1773 }
1774
1775 YOSYS_NAMESPACE_END