391e0a4442cf64a699bf7064e16891e604d3ebec
2 * yosys -- Yosys Open SYnthesis Suite
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
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.
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.
20 * This is the AST frontend library.
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.
29 #include "kernel/log.h"
30 #include "libs/sha1/sha1.h"
38 using namespace AST_INTERNAL
;
40 // instanciate global variables (public API)
42 std::string current_filename
;
43 void (*set_line_num
)(int) = NULL
;
44 int (*get_line_num
)() = NULL
;
47 // instanciate global variables (private API)
48 namespace AST_INTERNAL
{
49 bool flag_dump_ast
, flag_dump_ast_diff
, flag_dump_vlog
, flag_nolatches
, flag_nomem2reg
, flag_mem2reg
, flag_lib
;
50 AstNode
*current_ast
, *current_ast_mod
;
51 std::map
<std::string
, AstNode
*> current_scope
;
52 RTLIL::SigSpec
*genRTLIL_subst_from
= NULL
;
53 RTLIL::SigSpec
*genRTLIL_subst_to
= NULL
;
54 AstNode
*current_top_block
, *current_block
, *current_block_child
;
55 AstModule
*current_module
;
58 // convert node types to string
59 std::string
AST::type2str(AstNodeType type
)
63 #define X(_item) case _item: return #_item;
142 assert(!"Missing enum to string def in AST::type2str().");
147 // create new node (AstNode constructor)
148 // (the optional child arguments make it easier to create AST trees)
149 AstNode::AstNode(AstNodeType type
, AstNode
*child1
, AstNode
*child2
)
152 filename
= current_filename
;
153 linenum
= get_line_num();
166 children
.push_back(child1
);
168 children
.push_back(child2
);
171 // create a (deep recursive) copy of a node
172 AstNode
*AstNode::clone()
174 AstNode
*that
= new AstNode
;
176 for (auto &it
: that
->children
)
178 for (auto &it
: that
->attributes
)
179 it
.second
= it
.second
->clone();
183 // create a (deep recursive) copy of a node use 'other' as target root node
184 void AstNode::cloneInto(AstNode
*other
)
186 AstNode
*tmp
= clone();
187 other
->delete_children();
189 tmp
->children
.clear();
190 tmp
->attributes
.clear();
194 // delete all children in this node
195 void AstNode::delete_children()
197 for (auto &it
: children
)
201 for (auto &it
: attributes
)
206 // AstNode destructor
212 // create a nice text representation of the node
213 // (traverse tree by recursion, use 'other' pointer for diffing two AST trees)
214 void AstNode::dumpAst(FILE *f
, std::string indent
, AstNode
*other
)
217 for (auto f
: log_files
)
218 dumpAst(f
, indent
, other
);
222 if (type
!= other
->type
)
223 goto found_diff_to_other
;
224 if (children
.size() != other
->children
.size())
225 goto found_diff_to_other
;
226 if (str
!= other
->str
)
227 goto found_diff_to_other
;
228 if (bits
!= other
->bits
)
229 goto found_diff_to_other
;
230 if (is_input
!= other
->is_input
)
231 goto found_diff_to_other
;
232 if (is_output
!= other
->is_output
)
233 goto found_diff_to_other
;
234 if (is_reg
!= other
->is_reg
)
235 goto found_diff_to_other
;
236 if (is_signed
!= other
->is_signed
)
237 goto found_diff_to_other
;
238 if (range_valid
!= other
->range_valid
)
239 goto found_diff_to_other
;
240 if (port_id
!= other
->port_id
)
241 goto found_diff_to_other
;
242 if (range_left
!= other
->range_left
)
243 goto found_diff_to_other
;
244 if (range_right
!= other
->range_right
)
245 goto found_diff_to_other
;
246 if (integer
!= other
->integer
)
247 goto found_diff_to_other
;
250 other
->dumpAst(f
, indent
+ "- ");
251 this->dumpAst(f
, indent
+ "+ ");
256 std::string type_name
= type2str(type
);
257 fprintf(f
, "%s%s <%s:%d>", indent
.c_str(), type_name
.c_str(), filename
.c_str(), linenum
);
259 fprintf(f
, " str='%s'", str
.c_str());
261 fprintf(f
, " bits='");
262 for (size_t i
= bits
.size(); i
> 0; i
--)
263 fprintf(f
, "%c", bits
[i
-1] == RTLIL::S0
? '0' :
264 bits
[i
-1] == RTLIL::S1
? '1' :
265 bits
[i
-1] == RTLIL::Sx
? 'x' :
266 bits
[i
-1] == RTLIL::Sz
? 'z' : '?');
267 fprintf(f
, "'(%zd)", bits
.size());
270 fprintf(f
, " input");
272 fprintf(f
, " output");
276 fprintf(f
, " signed");
278 fprintf(f
, " port=%d", port_id
);
279 if (range_valid
|| range_left
!= -1 || range_right
!= 0)
280 fprintf(f
, " range=[%d:%d]%s", range_left
, range_right
, range_valid
? "" : "!");
282 fprintf(f
, " int=%u", (int)integer
);
285 for (size_t i
= 0; i
< children
.size(); i
++)
286 children
[i
]->dumpAst(f
, indent
+ " ", other
? other
->children
[i
] : NULL
);
289 // helper function for AstNode::dumpVlog()
290 static std::string
id2vl(std::string txt
)
292 if (txt
.size() > 1 && txt
[0] == '\\')
294 for (size_t i
= 0; i
< txt
.size(); i
++) {
295 if ('A' <= txt
[i
] && txt
[i
] <= 'Z') continue;
296 if ('a' <= txt
[i
] && txt
[i
] <= 'z') continue;
297 if ('0' <= txt
[i
] && txt
[i
] <= '9') continue;
298 if (txt
[i
] == '_') continue;
299 txt
= "\\" + txt
+ " ";
305 // dump AST node as verilog pseudo-code
306 void AstNode::dumpVlog(FILE *f
, std::string indent
)
310 std::vector
<AstNode
*> rem_children1
, rem_children2
;
313 for (auto f
: log_files
)
321 fprintf(f
, "%s" "module %s(", indent
.c_str(), id2vl(str
).c_str());
322 for (auto child
: children
)
323 if (child
->type
== AST_WIRE
&& (child
->is_input
|| child
->is_output
)) {
324 fprintf(f
, "%s%s", first
? "" : ", ", id2vl(child
->str
).c_str());
329 for (auto child
: children
)
330 if (child
->type
== AST_PARAMETER
|| child
->type
== AST_LOCALPARAM
)
331 child
->dumpVlog(f
, indent
+ " ");
333 rem_children1
.push_back(child
);
335 for (auto child
: rem_children1
)
336 if (child
->type
== AST_WIRE
|| child
->type
== AST_AUTOWIRE
|| child
->type
== AST_MEMORY
)
337 child
->dumpVlog(f
, indent
+ " ");
339 rem_children2
.push_back(child
);
340 rem_children1
.clear();
342 for (auto child
: rem_children2
)
343 if (child
->type
== AST_TASK
|| child
->type
== AST_FUNCTION
)
344 child
->dumpVlog(f
, indent
+ " ");
346 rem_children1
.push_back(child
);
347 rem_children2
.clear();
349 for (auto child
: rem_children1
)
350 child
->dumpVlog(f
, indent
+ " ");
351 rem_children1
.clear();
353 fprintf(f
, "%s" "endmodule\n", indent
.c_str());
357 if (is_input
&& is_output
)
358 fprintf(f
, "%s" "inout", indent
.c_str());
360 fprintf(f
, "%s" "input", indent
.c_str());
362 fprintf(f
, "%s" "output", indent
.c_str());
364 fprintf(f
, "%s" "wire", indent
.c_str());
366 fprintf(f
, "%s" "reg", (is_input
|| is_output
) ? " " : indent
.c_str());
368 fprintf(f
, " signed");
369 for (auto child
: children
) {
371 child
->dumpVlog(f
, "");
373 fprintf(f
, " %s", id2vl(str
).c_str());
378 fprintf(f
, "%s" "memory", indent
.c_str());
380 fprintf(f
, " signed");
381 for (auto child
: children
) {
383 child
->dumpVlog(f
, "");
385 fprintf(f
, " %s", id2vl(str
).c_str());
393 fprintf(f
, "[%d:%d]", range_left
, range_right
);
395 for (auto child
: children
) {
396 fprintf(f
, "%c", first
? '[' : ':');
397 child
->dumpVlog(f
, "");
405 fprintf(f
, "%s" "always @(", indent
.c_str());
406 for (auto child
: children
) {
407 if (child
->type
!= AST_POSEDGE
&& child
->type
!= AST_NEGEDGE
&& child
->type
!= AST_EDGE
)
411 child
->dumpVlog(f
, "");
415 for (auto child
: children
) {
416 if (child
->type
!= AST_POSEDGE
&& child
->type
!= AST_NEGEDGE
&& child
->type
!= AST_EDGE
)
417 child
->dumpVlog(f
, indent
+ " ");
422 fprintf(f
, "%s" "initial\n", indent
.c_str());
423 for (auto child
: children
) {
424 if (child
->type
!= AST_POSEDGE
&& child
->type
!= AST_NEGEDGE
&& child
->type
!= AST_EDGE
)
425 child
->dumpVlog(f
, indent
+ " ");
432 if (type
== AST_POSEDGE
)
433 fprintf(f
, "posedge ");
434 if (type
== AST_NEGEDGE
)
435 fprintf(f
, "negedge ");
436 for (auto child
: children
)
437 child
->dumpVlog(f
, "");
441 fprintf(f
, "%s", id2vl(str
).c_str());
442 for (auto child
: children
)
443 child
->dumpVlog(f
, "");
448 fprintf(f
, "\"%s\"", str
.c_str());
449 else if (bits
.size() == 32)
450 fprintf(f
, "%d", RTLIL::Const(bits
).as_int());
452 fprintf(f
, "%zd'b %s", bits
.size(), RTLIL::Const(bits
).as_string().c_str());
456 if (children
.size() == 1) {
457 children
[0]->dumpVlog(f
, indent
);
459 fprintf(f
, "%s" "begin\n", indent
.c_str());
460 for (auto child
: children
)
461 child
->dumpVlog(f
, indent
+ " ");
462 fprintf(f
, "%s" "end\n", indent
.c_str());
467 fprintf(f
, "%s" "case (", indent
.c_str());
468 children
[0]->dumpVlog(f
, "");
470 for (size_t i
= 1; i
< children
.size(); i
++) {
471 AstNode
*child
= children
[i
];
472 child
->dumpVlog(f
, indent
+ " ");
474 fprintf(f
, "%s" "endcase\n", indent
.c_str());
478 for (auto child
: children
) {
479 if (child
->type
== AST_BLOCK
) {
481 child
->dumpVlog(f
, indent
+ " ");
484 fprintf(f
, "%s", first
? indent
.c_str() : ", ");
485 if (child
->type
== AST_DEFAULT
)
486 fprintf(f
, "default");
488 child
->dumpVlog(f
, "");
496 fprintf(f
, "%s", indent
.c_str());
497 children
[0]->dumpVlog(f
, "");
498 fprintf(f
, " %s ", type
== AST_ASSIGN_EQ
? "=" : "<=");
499 children
[1]->dumpVlog(f
, "");
505 for (auto child
: children
) {
508 child
->dumpVlog(f
, "");
516 children
[0]->dumpVlog(f
, "");
518 children
[1]->dumpVlog(f
, "");
522 if (0) { case AST_BIT_NOT
: txt
= "~"; }
523 if (0) { case AST_REDUCE_AND
: txt
= "&"; }
524 if (0) { case AST_REDUCE_OR
: txt
= "|"; }
525 if (0) { case AST_REDUCE_XOR
: txt
= "^"; }
526 if (0) { case AST_REDUCE_XNOR
: txt
= "~^"; }
527 if (0) { case AST_REDUCE_BOOL
: txt
= "|"; }
528 if (0) { case AST_POS
: txt
= "+"; }
529 if (0) { case AST_NEG
: txt
= "-"; }
530 if (0) { case AST_LOGIC_NOT
: txt
= "!"; }
531 fprintf(f
, "%s(", txt
.c_str());
532 children
[0]->dumpVlog(f
, "");
536 if (0) { case AST_BIT_AND
: txt
= "&"; }
537 if (0) { case AST_BIT_OR
: txt
= "|"; }
538 if (0) { case AST_BIT_XOR
: txt
= "^"; }
539 if (0) { case AST_BIT_XNOR
: txt
= "~^"; }
540 if (0) { case AST_SHIFT_LEFT
: txt
= "<<"; }
541 if (0) { case AST_SHIFT_RIGHT
: txt
= ">>"; }
542 if (0) { case AST_SHIFT_SLEFT
: txt
= "<<<"; }
543 if (0) { case AST_SHIFT_SRIGHT
: txt
= ">>>"; }
544 if (0) { case AST_LT
: txt
= "<"; }
545 if (0) { case AST_LE
: txt
= "<="; }
546 if (0) { case AST_EQ
: txt
= "=="; }
547 if (0) { case AST_NE
: txt
= "!="; }
548 if (0) { case AST_GE
: txt
= ">="; }
549 if (0) { case AST_GT
: txt
= ">"; }
550 if (0) { case AST_ADD
: txt
= "+"; }
551 if (0) { case AST_SUB
: txt
= "-"; }
552 if (0) { case AST_MUL
: txt
= "*"; }
553 if (0) { case AST_DIV
: txt
= "/"; }
554 if (0) { case AST_MOD
: txt
= "%"; }
555 if (0) { case AST_POW
: txt
= "**"; }
556 if (0) { case AST_LOGIC_AND
: txt
= "&&"; }
557 if (0) { case AST_LOGIC_OR
: txt
= "||"; }
559 children
[0]->dumpVlog(f
, "");
560 fprintf(f
, ")%s(", txt
.c_str());
561 children
[1]->dumpVlog(f
, "");
567 children
[0]->dumpVlog(f
, "");
569 children
[1]->dumpVlog(f
, "");
571 children
[2]->dumpVlog(f
, "");
576 std::string type_name
= type2str(type
);
577 fprintf(f
, "%s" "/** %s **/%s", indent
.c_str(), type_name
.c_str(), indent
.empty() ? "" : "\n");
578 // dumpAst(f, indent, NULL);
582 // check if two AST nodes are identical
583 bool AstNode::operator==(const AstNode
&other
) const
585 if (type
!= other
.type
)
587 if (children
.size() != other
.children
.size())
589 if (str
!= other
.str
)
591 if (bits
!= other
.bits
)
593 if (is_input
!= other
.is_input
)
595 if (is_output
!= other
.is_output
)
597 if (is_reg
!= other
.is_reg
)
599 if (is_signed
!= other
.is_signed
)
601 if (range_valid
!= other
.range_valid
)
603 if (port_id
!= other
.port_id
)
605 if (range_left
!= other
.range_left
)
607 if (range_right
!= other
.range_right
)
609 if (integer
!= other
.integer
)
611 for (size_t i
= 0; i
< children
.size(); i
++)
612 if (*children
[i
] != *other
.children
[i
])
617 // check if two AST nodes are not identical
618 bool AstNode::operator!=(const AstNode
&other
) const
620 return !(*this == other
);
623 // check if this AST contains the given node
624 bool AstNode::contains(const AstNode
*other
) const
628 for (auto child
: children
)
629 if (child
->contains(other
))
634 // create an AST node for a constant (using a 32 bit int as value)
635 AstNode
*AstNode::mkconst_int(uint32_t v
, bool is_signed
, int width
)
637 AstNode
*node
= new AstNode(AST_CONSTANT
);
639 node
->is_signed
= is_signed
;
640 for (int i
= 0; i
< width
; i
++) {
641 node
->bits
.push_back((v
& 1) ? RTLIL::S1
: RTLIL::S0
);
644 node
->range_valid
= true;
645 node
->range_left
= width
-1;
646 node
->range_right
= 0;
650 // create an AST node for a constant (using a bit vector as value)
651 AstNode
*AstNode::mkconst_bits(const std::vector
<RTLIL::State
> &v
, bool is_signed
)
653 AstNode
*node
= new AstNode(AST_CONSTANT
);
654 node
->is_signed
= is_signed
;
656 for (size_t i
= 0; i
< 32; i
++) {
657 if (i
< node
->bits
.size())
658 node
->integer
|= (node
->bits
[i
] == RTLIL::S1
) << i
;
660 node
->integer
|= (node
->bits
.back() == RTLIL::S1
) << i
;
662 node
->range_valid
= true;
663 node
->range_left
= node
->bits
.size();
664 node
->range_right
= 0;
668 // create a new AstModule from an AST_MODULE AST node
669 static AstModule
* process_module(AstNode
*ast
)
671 assert(ast
->type
== AST_MODULE
);
672 log("Generating RTLIL representation for module `%s'.\n", ast
->str
.c_str());
674 current_ast_mod
= ast
;
675 AstNode
*ast_before_simplify
= ast
->clone();
677 while (ast
->simplify(false, false, false, 0)) { }
680 log("Dumping verilog AST (as requested by %s option):\n", flag_dump_ast_diff
? "dump_ast_diff" : "dump_ast");
681 ast
->dumpAst(NULL
, " ", flag_dump_ast_diff
? ast_before_simplify
: NULL
);
682 log("--- END OF AST DUMP ---\n");
685 if (flag_dump_vlog
) {
686 log("Dumping verilog AST (as requested by dump_vlog option):\n");
687 ast
->dumpVlog(NULL
, " ");
688 log("--- END OF AST DUMP ---\n");
692 std::vector
<AstNode
*> new_children
;
693 for (auto child
: ast
->children
) {
694 if (child
->type
== AST_WIRE
&& (child
->is_input
|| child
->is_output
))
695 new_children
.push_back(child
);
699 ast
->children
.swap(new_children
);
700 ast
->attributes
["\\placeholder"] = AstNode::mkconst_int(0, false, 0);
703 current_module
= new AstModule
;
704 current_module
->ast
= NULL
;
705 current_module
->name
= ast
->str
;
706 current_module
->attributes
["\\src"] = stringf("%s:%d", ast
->filename
.c_str(), ast
->linenum
);
707 for (auto &attr
: ast
->attributes
) {
708 if (attr
.second
->type
!= AST_CONSTANT
)
709 log_error("Attribute `%s' with non-constant value at %s:%d!\n",
710 attr
.first
.c_str(), ast
->filename
.c_str(), ast
->linenum
);
711 current_module
->attributes
[attr
.first
].str
= attr
.second
->str
;
712 current_module
->attributes
[attr
.first
].bits
= attr
.second
->bits
;
714 for (size_t i
= 0; i
< ast
->children
.size(); i
++) {
715 AstNode
*node
= ast
->children
[i
];
716 if (node
->type
== AST_WIRE
|| node
->type
== AST_MEMORY
)
719 for (size_t i
= 0; i
< ast
->children
.size(); i
++) {
720 AstNode
*node
= ast
->children
[i
];
721 if (node
->type
!= AST_WIRE
&& node
->type
!= AST_MEMORY
)
725 current_module
->ast
= ast_before_simplify
;
726 current_module
->nolatches
= flag_nolatches
;
727 current_module
->nomem2reg
= flag_nomem2reg
;
728 current_module
->mem2reg
= flag_mem2reg
;
729 current_module
->lib
= flag_lib
;
730 return current_module
;
733 // create AstModule instances for all modules in the AST tree and add them to 'design'
734 void AST::process(RTLIL::Design
*design
, AstNode
*ast
, bool dump_ast
, bool dump_ast_diff
, bool dump_vlog
, bool nolatches
, bool nomem2reg
, bool mem2reg
, bool lib
)
737 flag_dump_ast
= dump_ast
;
738 flag_dump_ast_diff
= dump_ast_diff
;
739 flag_dump_vlog
= dump_vlog
;
740 flag_nolatches
= nolatches
;
741 flag_nomem2reg
= nomem2reg
;
742 flag_mem2reg
= mem2reg
;
745 assert(current_ast
->type
== AST_DESIGN
);
746 for (auto it
= current_ast
->children
.begin(); it
!= current_ast
->children
.end(); it
++) {
747 if (design
->modules
.count((*it
)->str
) != 0)
748 log_error("Re-definition of module `%s' at %s:%d!\n",
749 (*it
)->str
.c_str(), (*it
)->filename
.c_str(), (*it
)->linenum
);
750 design
->modules
[(*it
)->str
] = process_module(*it
);
754 // AstModule destructor
755 AstModule::~AstModule()
761 // create a new parametric module (when needed) and return the name of the generated module
762 RTLIL::IdString
AstModule::derive(RTLIL::Design
*design
, std::map
<RTLIL::IdString
, RTLIL::Const
> parameters
)
764 log_header("Executing AST frontend in derive mode using pre-parsed AST for module `%s'.\n", name
.c_str());
767 flag_dump_ast
= false;
768 flag_dump_ast_diff
= false;
769 flag_dump_vlog
= false;
770 flag_nolatches
= nolatches
;
771 flag_nomem2reg
= nomem2reg
;
772 flag_mem2reg
= mem2reg
;
774 use_internal_line_num();
776 std::vector
<unsigned char> hash_data
;
777 hash_data
.insert(hash_data
.end(), name
.begin(), name
.end());
778 hash_data
.push_back(0);
780 AstNode
*new_ast
= ast
->clone();
782 int para_counter
= 0;
783 for (auto it
= new_ast
->children
.begin(); it
!= new_ast
->children
.end(); it
++) {
784 AstNode
*child
= *it
;
785 if (child
->type
!= AST_PARAMETER
)
788 std::string para_id
= child
->str
;
789 if (parameters
.count(child
->str
) > 0) {
790 log("Parameter %s = %s\n", child
->str
.c_str(), log_signal(RTLIL::SigSpec(parameters
[child
->str
])));
792 child
->delete_children();
793 child
->children
.push_back(AstNode::mkconst_bits(parameters
[para_id
].bits
, false));
794 hash_data
.insert(hash_data
.end(), child
->str
.begin(), child
->str
.end());
795 hash_data
.push_back(0);
796 hash_data
.insert(hash_data
.end(), parameters
[para_id
].bits
.begin(), parameters
[para_id
].bits
.end());
797 hash_data
.push_back(0xff);
798 parameters
.erase(para_id
);
802 snprintf(buf
, 100, "$%d", para_counter
);
803 if (parameters
.count(buf
) > 0) {
805 log("Parameter %d (%s) = %s\n", para_counter
, child
->str
.c_str(), log_signal(RTLIL::SigSpec(parameters
[para_id
])));
806 goto rewrite_parameter
;
809 if (parameters
.size() > 0)
810 log_error("Requested parameter `%s' does not exist in module `%s'!\n", parameters
.begin()->first
.c_str(), name
.c_str());
812 unsigned char hash
[20];
813 unsigned char *hash_data2
= new unsigned char[hash_data
.size()];
814 for (size_t i
= 0; i
< hash_data
.size(); i
++)
815 hash_data2
[i
] = hash_data
[i
];
816 sha1::calc(hash_data2
, hash_data
.size(), hash
);
820 sha1::toHexString(hash
, hexstring
);
822 std::string modname
= "$paramod$" + std::string(hexstring
) + "$" + name
;
824 if (design
->modules
.count(modname
) == 0) {
825 new_ast
->str
= modname
;
826 design
->modules
[modname
] = process_module(new_ast
);
828 log("Found cached RTLIL representation for module `%s'.\n", modname
.c_str());
835 // recompile a module from AST with updated widths for auto-wires
836 // (auto-wires are wires that are used but not declared an thus have an automatically determined width)
837 void AstModule::update_auto_wires(std::map
<RTLIL::IdString
, int> auto_sizes
)
839 log_header("Executing AST frontend in update_auto_wires mode using pre-parsed AST for module `%s'.\n", name
.c_str());
842 flag_dump_ast
= false;
843 flag_dump_ast_diff
= false;
844 flag_dump_vlog
= false;
845 flag_nolatches
= nolatches
;
846 flag_nomem2reg
= nomem2reg
;
847 flag_mem2reg
= mem2reg
;
849 use_internal_line_num();
851 for (auto it
= auto_sizes
.begin(); it
!= auto_sizes
.end(); it
++) {
852 log("Adding extra wire declaration to AST: wire [%d:0] %s\n", it
->second
- 1, it
->first
.c_str());
853 AstNode
*wire
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, AstNode::mkconst_int(it
->second
- 1, true), AstNode::mkconst_int(0, true)));
854 wire
->str
= it
->first
;
855 ast
->children
.insert(ast
->children
.begin(), wire
);
858 AstModule
*newmod
= process_module(ast
);
864 wires
.swap(newmod
->wires
);
865 cells
.swap(newmod
->cells
);
866 processes
.swap(newmod
->processes
);
867 connections
.swap(newmod
->connections
);
868 attributes
.swap(newmod
->attributes
);
872 // internal dummy line number callbacks
874 int internal_line_num
;
875 void internal_set_line_num(int n
) {
876 internal_line_num
= n
;
878 int internal_get_line_num() {
879 return internal_line_num
;
883 // use internal dummy line number callbacks
884 void AST::use_internal_line_num()
886 set_line_num
= &internal_set_line_num
;
887 get_line_num
= &internal_get_line_num
;