2 * yosys -- Yosys Open SYnthesis Suite
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
5 * Copyright (C) 2018 Ruben Undheim <ruben.undheim@gmail.com>
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.
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.
21 * This is the AST frontend library.
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.
30 #include "kernel/yosys.h"
31 #include "libs/sha1/sha1.h"
37 using namespace AST_INTERNAL
;
39 // instantiate global variables (public API)
41 std::string current_filename
;
42 void (*set_line_num
)(int) = NULL
;
43 int (*get_line_num
)() = NULL
;
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 AstModule
*current_module
;
56 bool current_always_clocked
;
59 // convert node types to string
60 std::string
AST::type2str(AstNodeType type
)
64 #define X(_item) case _item: return #_item;
168 // check if attribute exists and has non-zero value
169 bool AstNode::get_bool_attribute(RTLIL::IdString id
)
171 if (attributes
.count(id
) == 0)
174 AstNode
*attr
= attributes
.at(id
);
175 if (attr
->type
!= AST_CONSTANT
)
176 log_file_error(attr
->filename
, attr
->linenum
, "Attribute `%s' with non-constant value!\n", id
.c_str());
178 return attr
->integer
!= 0;
181 // create new node (AstNode constructor)
182 // (the optional child arguments make it easier to create AST trees)
183 AstNode::AstNode(AstNodeType type
, AstNode
*child1
, AstNode
*child2
, AstNode
*child3
)
185 static unsigned int hashidx_count
= 123456789;
186 hashidx_count
= mkhash_xorshift(hashidx_count
);
187 hashidx_
= hashidx_count
;
190 filename
= current_filename
;
191 linenum
= get_line_num();
203 range_swapped
= false;
213 children
.push_back(child1
);
215 children
.push_back(child2
);
217 children
.push_back(child3
);
220 // create a (deep recursive) copy of a node
221 AstNode
*AstNode::clone() const
223 AstNode
*that
= new AstNode
;
225 for (auto &it
: that
->children
)
227 for (auto &it
: that
->attributes
)
228 it
.second
= it
.second
->clone();
232 // create a (deep recursive) copy of a node use 'other' as target root node
233 void AstNode::cloneInto(AstNode
*other
) const
235 AstNode
*tmp
= clone();
236 other
->delete_children();
238 tmp
->children
.clear();
239 tmp
->attributes
.clear();
243 // delete all children in this node
244 void AstNode::delete_children()
246 for (auto &it
: children
)
250 for (auto &it
: attributes
)
255 // AstNode destructor
261 // create a nice text representation of the node
262 // (traverse tree by recursion, use 'other' pointer for diffing two AST trees)
263 void AstNode::dumpAst(FILE *f
, std::string indent
) const
266 for (auto f
: log_files
)
271 std::string type_name
= type2str(type
);
272 fprintf(f
, "%s%s <%s:%d>", indent
.c_str(), type_name
.c_str(), filename
.c_str(), linenum
);
274 if (!flag_no_dump_ptr
) {
276 fprintf(f
, " [%p -> %p]", this, id2ast
);
278 fprintf(f
, " [%p]", this);
282 fprintf(f
, " str='%s'", str
.c_str());
284 fprintf(f
, " bits='");
285 for (size_t i
= bits
.size(); i
> 0; i
--)
286 fprintf(f
, "%c", bits
[i
-1] == RTLIL::S0
? '0' :
287 bits
[i
-1] == RTLIL::S1
? '1' :
288 bits
[i
-1] == RTLIL::Sx
? 'x' :
289 bits
[i
-1] == RTLIL::Sz
? 'z' : '?');
290 fprintf(f
, "'(%d)", GetSize(bits
));
293 fprintf(f
, " input");
295 fprintf(f
, " output");
297 fprintf(f
, " logic");
298 if (is_reg
) // this is an AST dump, not Verilog - if we see "logic reg" that's fine.
301 fprintf(f
, " signed");
303 fprintf(f
, " port=%d", port_id
);
304 if (range_valid
|| range_left
!= -1 || range_right
!= 0)
305 fprintf(f
, " %srange=[%d:%d]%s", range_swapped
? "swapped_" : "", range_left
, range_right
, range_valid
? "" : "!");
307 fprintf(f
, " int=%u", (int)integer
);
309 fprintf(f
, " real=%e", realvalue
);
310 if (!multirange_dimensions
.empty()) {
311 fprintf(f
, " multirange=[");
312 for (int v
: multirange_dimensions
)
313 fprintf(f
, " %d", v
);
318 for (auto &it
: attributes
) {
319 fprintf(f
, "%s ATTR %s:\n", indent
.c_str(), it
.first
.c_str());
320 it
.second
->dumpAst(f
, indent
+ " ");
323 for (size_t i
= 0; i
< children
.size(); i
++)
324 children
[i
]->dumpAst(f
, indent
+ " ");
329 // helper function for AstNode::dumpVlog()
330 static std::string
id2vl(std::string txt
)
332 if (txt
.size() > 1 && txt
[0] == '\\')
334 for (size_t i
= 0; i
< txt
.size(); i
++) {
335 if ('A' <= txt
[i
] && txt
[i
] <= 'Z') continue;
336 if ('a' <= txt
[i
] && txt
[i
] <= 'z') continue;
337 if ('0' <= txt
[i
] && txt
[i
] <= '9') continue;
338 if (txt
[i
] == '_') continue;
339 txt
= "\\" + txt
+ " ";
345 // dump AST node as Verilog pseudo-code
346 void AstNode::dumpVlog(FILE *f
, std::string indent
) const
350 std::vector
<AstNode
*> rem_children1
, rem_children2
;
353 for (auto f
: log_files
)
358 for (auto &it
: attributes
) {
359 fprintf(f
, "%s" "(* %s = ", indent
.c_str(), id2vl(it
.first
.str()).c_str());
360 it
.second
->dumpVlog(f
, "");
361 fprintf(f
, " *)%s", indent
.empty() ? "" : "\n");
367 fprintf(f
, "%s" "module %s(", indent
.c_str(), id2vl(str
).c_str());
368 for (auto child
: children
)
369 if (child
->type
== AST_WIRE
&& (child
->is_input
|| child
->is_output
)) {
370 fprintf(f
, "%s%s", first
? "" : ", ", id2vl(child
->str
).c_str());
375 for (auto child
: children
)
376 if (child
->type
== AST_PARAMETER
|| child
->type
== AST_LOCALPARAM
|| child
->type
== AST_DEFPARAM
)
377 child
->dumpVlog(f
, indent
+ " ");
379 rem_children1
.push_back(child
);
381 for (auto child
: rem_children1
)
382 if (child
->type
== AST_WIRE
|| child
->type
== AST_AUTOWIRE
|| child
->type
== AST_MEMORY
)
383 child
->dumpVlog(f
, indent
+ " ");
385 rem_children2
.push_back(child
);
386 rem_children1
.clear();
388 for (auto child
: rem_children2
)
389 if (child
->type
== AST_TASK
|| child
->type
== AST_FUNCTION
)
390 child
->dumpVlog(f
, indent
+ " ");
392 rem_children1
.push_back(child
);
393 rem_children2
.clear();
395 for (auto child
: rem_children1
)
396 child
->dumpVlog(f
, indent
+ " ");
397 rem_children1
.clear();
399 fprintf(f
, "%s" "endmodule\n", indent
.c_str());
403 if (is_input
&& is_output
)
404 fprintf(f
, "%s" "inout", indent
.c_str());
406 fprintf(f
, "%s" "input", indent
.c_str());
408 fprintf(f
, "%s" "output", indent
.c_str());
410 fprintf(f
, "%s" "wire", indent
.c_str());
412 fprintf(f
, "%s" "reg", (is_input
|| is_output
) ? " " : indent
.c_str());
414 fprintf(f
, " signed");
415 for (auto child
: children
) {
417 child
->dumpVlog(f
, "");
419 fprintf(f
, " %s", id2vl(str
).c_str());
424 fprintf(f
, "%s" "memory", indent
.c_str());
426 fprintf(f
, " signed");
427 for (auto child
: children
) {
429 child
->dumpVlog(f
, "");
431 fprintf(f
, " %s", id2vl(str
).c_str());
440 fprintf(f
, "[%d:%d]", range_right
, range_left
);
442 fprintf(f
, "[%d:%d]", range_left
, range_right
);
444 for (auto child
: children
) {
445 fprintf(f
, "%c", first
? '[' : ':');
446 child
->dumpVlog(f
, "");
454 fprintf(f
, "%s" "always @", indent
.c_str());
455 for (auto child
: children
) {
456 if (child
->type
!= AST_POSEDGE
&& child
->type
!= AST_NEGEDGE
&& child
->type
!= AST_EDGE
)
458 fprintf(f
, first
? "(" : ", ");
459 child
->dumpVlog(f
, "");
462 fprintf(f
, first
? "*\n" : ")\n");
463 for (auto child
: children
) {
464 if (child
->type
!= AST_POSEDGE
&& child
->type
!= AST_NEGEDGE
&& child
->type
!= AST_EDGE
)
465 child
->dumpVlog(f
, indent
+ " ");
470 fprintf(f
, "%s" "initial\n", indent
.c_str());
471 for (auto child
: children
) {
472 if (child
->type
!= AST_POSEDGE
&& child
->type
!= AST_NEGEDGE
&& child
->type
!= AST_EDGE
)
473 child
->dumpVlog(f
, indent
+ " ");
480 if (type
== AST_POSEDGE
)
481 fprintf(f
, "posedge ");
482 if (type
== AST_NEGEDGE
)
483 fprintf(f
, "negedge ");
484 for (auto child
: children
)
485 child
->dumpVlog(f
, "");
489 fprintf(f
, "%s", id2vl(str
).c_str());
490 for (auto child
: children
)
491 child
->dumpVlog(f
, "");
496 fprintf(f
, "\"%s\"", str
.c_str());
497 else if (bits
.size() == 32)
498 fprintf(f
, "%d", RTLIL::Const(bits
).as_int());
500 fprintf(f
, "%d'b %s", GetSize(bits
), RTLIL::Const(bits
).as_string().c_str());
504 fprintf(f
, "%e", realvalue
);
508 if (children
.size() == 1) {
509 children
[0]->dumpVlog(f
, indent
);
511 fprintf(f
, "%s" "begin\n", indent
.c_str());
512 for (auto child
: children
)
513 child
->dumpVlog(f
, indent
+ " ");
514 fprintf(f
, "%s" "end\n", indent
.c_str());
519 if (!children
.empty() && children
[0]->type
== AST_CONDX
)
520 fprintf(f
, "%s" "casex (", indent
.c_str());
521 else if (!children
.empty() && children
[0]->type
== AST_CONDZ
)
522 fprintf(f
, "%s" "casez (", indent
.c_str());
524 fprintf(f
, "%s" "case (", indent
.c_str());
525 children
[0]->dumpVlog(f
, "");
527 for (size_t i
= 1; i
< children
.size(); i
++) {
528 AstNode
*child
= children
[i
];
529 child
->dumpVlog(f
, indent
+ " ");
531 fprintf(f
, "%s" "endcase\n", indent
.c_str());
537 for (auto child
: children
) {
538 if (child
->type
== AST_BLOCK
) {
540 child
->dumpVlog(f
, indent
+ " ");
543 fprintf(f
, "%s", first
? indent
.c_str() : ", ");
544 if (child
->type
== AST_DEFAULT
)
545 fprintf(f
, "default");
547 child
->dumpVlog(f
, "");
554 fprintf(f
, "%sassign ", indent
.c_str());
555 children
[0]->dumpVlog(f
, "");
557 children
[1]->dumpVlog(f
, "");
563 fprintf(f
, "%s", indent
.c_str());
564 children
[0]->dumpVlog(f
, "");
565 fprintf(f
, " %s ", type
== AST_ASSIGN_EQ
? "=" : "<=");
566 children
[1]->dumpVlog(f
, "");
572 for (int i
= GetSize(children
)-1; i
>= 0; i
--) {
573 auto child
= children
[i
];
576 child
->dumpVlog(f
, "");
584 children
[0]->dumpVlog(f
, "");
586 children
[1]->dumpVlog(f
, "");
590 if (0) { case AST_BIT_NOT
: txt
= "~"; }
591 if (0) { case AST_REDUCE_AND
: txt
= "&"; }
592 if (0) { case AST_REDUCE_OR
: txt
= "|"; }
593 if (0) { case AST_REDUCE_XOR
: txt
= "^"; }
594 if (0) { case AST_REDUCE_XNOR
: txt
= "~^"; }
595 if (0) { case AST_REDUCE_BOOL
: txt
= "|"; }
596 if (0) { case AST_POS
: txt
= "+"; }
597 if (0) { case AST_NEG
: txt
= "-"; }
598 if (0) { case AST_LOGIC_NOT
: txt
= "!"; }
599 fprintf(f
, "%s(", txt
.c_str());
600 children
[0]->dumpVlog(f
, "");
604 if (0) { case AST_BIT_AND
: txt
= "&"; }
605 if (0) { case AST_BIT_OR
: txt
= "|"; }
606 if (0) { case AST_BIT_XOR
: txt
= "^"; }
607 if (0) { case AST_BIT_XNOR
: txt
= "~^"; }
608 if (0) { case AST_SHIFT_LEFT
: txt
= "<<"; }
609 if (0) { case AST_SHIFT_RIGHT
: txt
= ">>"; }
610 if (0) { case AST_SHIFT_SLEFT
: txt
= "<<<"; }
611 if (0) { case AST_SHIFT_SRIGHT
: txt
= ">>>"; }
612 if (0) { case AST_LT
: txt
= "<"; }
613 if (0) { case AST_LE
: txt
= "<="; }
614 if (0) { case AST_EQ
: txt
= "=="; }
615 if (0) { case AST_NE
: txt
= "!="; }
616 if (0) { case AST_EQX
: txt
= "==="; }
617 if (0) { case AST_NEX
: txt
= "!=="; }
618 if (0) { case AST_GE
: txt
= ">="; }
619 if (0) { case AST_GT
: txt
= ">"; }
620 if (0) { case AST_ADD
: txt
= "+"; }
621 if (0) { case AST_SUB
: txt
= "-"; }
622 if (0) { case AST_MUL
: txt
= "*"; }
623 if (0) { case AST_DIV
: txt
= "/"; }
624 if (0) { case AST_MOD
: txt
= "%"; }
625 if (0) { case AST_POW
: txt
= "**"; }
626 if (0) { case AST_LOGIC_AND
: txt
= "&&"; }
627 if (0) { case AST_LOGIC_OR
: txt
= "||"; }
629 children
[0]->dumpVlog(f
, "");
630 fprintf(f
, ")%s(", txt
.c_str());
631 children
[1]->dumpVlog(f
, "");
637 children
[0]->dumpVlog(f
, "");
639 children
[1]->dumpVlog(f
, "");
641 children
[2]->dumpVlog(f
, "");
646 std::string type_name
= type2str(type
);
647 fprintf(f
, "%s" "/** %s **/%s", indent
.c_str(), type_name
.c_str(), indent
.empty() ? "" : "\n");
648 // dumpAst(f, indent, NULL);
654 // check if two AST nodes are identical
655 bool AstNode::operator==(const AstNode
&other
) const
657 if (type
!= other
.type
)
659 if (children
.size() != other
.children
.size())
661 if (str
!= other
.str
)
663 if (bits
!= other
.bits
)
665 if (is_input
!= other
.is_input
)
667 if (is_output
!= other
.is_output
)
669 if (is_logic
!= other
.is_logic
)
671 if (is_reg
!= other
.is_reg
)
673 if (is_signed
!= other
.is_signed
)
675 if (is_string
!= other
.is_string
)
677 if (range_valid
!= other
.range_valid
)
679 if (range_swapped
!= other
.range_swapped
)
681 if (port_id
!= other
.port_id
)
683 if (range_left
!= other
.range_left
)
685 if (range_right
!= other
.range_right
)
687 if (integer
!= other
.integer
)
689 for (size_t i
= 0; i
< children
.size(); i
++)
690 if (*children
[i
] != *other
.children
[i
])
695 // check if two AST nodes are not identical
696 bool AstNode::operator!=(const AstNode
&other
) const
698 return !(*this == other
);
701 // check if this AST contains the given node
702 bool AstNode::contains(const AstNode
*other
) const
706 for (auto child
: children
)
707 if (child
->contains(other
))
712 // create an AST node for a constant (using a 32 bit int as value)
713 AstNode
*AstNode::mkconst_int(uint32_t v
, bool is_signed
, int width
)
715 AstNode
*node
= new AstNode(AST_CONSTANT
);
717 node
->is_signed
= is_signed
;
718 for (int i
= 0; i
< width
; i
++) {
719 node
->bits
.push_back((v
& 1) ? RTLIL::S1
: RTLIL::S0
);
722 node
->range_valid
= true;
723 node
->range_left
= width
-1;
724 node
->range_right
= 0;
728 // create an AST node for a constant (using a bit vector as value)
729 AstNode
*AstNode::mkconst_bits(const std::vector
<RTLIL::State
> &v
, bool is_signed
, bool is_unsized
)
731 AstNode
*node
= new AstNode(AST_CONSTANT
);
732 node
->is_signed
= is_signed
;
734 for (size_t i
= 0; i
< 32; i
++) {
735 if (i
< node
->bits
.size())
736 node
->integer
|= (node
->bits
[i
] == RTLIL::S1
) << i
;
737 else if (is_signed
&& !node
->bits
.empty())
738 node
->integer
|= (node
->bits
.back() == RTLIL::S1
) << i
;
740 node
->range_valid
= true;
741 node
->range_left
= node
->bits
.size()-1;
742 node
->range_right
= 0;
743 node
->is_unsized
= is_unsized
;
747 AstNode
*AstNode::mkconst_bits(const std::vector
<RTLIL::State
> &v
, bool is_signed
)
749 return mkconst_bits(v
, is_signed
, false);
752 // create an AST node for a constant (using a string in bit vector form as value)
753 AstNode
*AstNode::mkconst_str(const std::vector
<RTLIL::State
> &v
)
755 AstNode
*node
= mkconst_str(RTLIL::Const(v
).decode_string());
756 while (GetSize(node
->bits
) < GetSize(v
))
757 node
->bits
.push_back(RTLIL::State::S0
);
758 log_assert(node
->bits
== v
);
762 // create an AST node for a constant (using a string as value)
763 AstNode
*AstNode::mkconst_str(const std::string
&str
)
765 std::vector
<RTLIL::State
> data
;
766 data
.reserve(str
.size() * 8);
767 for (size_t i
= 0; i
< str
.size(); i
++) {
768 unsigned char ch
= str
[str
.size() - i
- 1];
769 for (int j
= 0; j
< 8; j
++) {
770 data
.push_back((ch
& 1) ? RTLIL::S1
: RTLIL::S0
);
774 AstNode
*node
= AstNode::mkconst_bits(data
, false);
775 node
->is_string
= true;
780 bool AstNode::bits_only_01() const
782 for (auto bit
: bits
)
783 if (bit
!= RTLIL::S0
&& bit
!= RTLIL::S1
)
788 RTLIL::Const
AstNode::bitsAsUnsizedConst(int width
)
790 RTLIL::State extbit
= bits
.back();
791 while (width
> int(bits
.size()))
792 bits
.push_back(extbit
);
793 return RTLIL::Const(bits
);
796 RTLIL::Const
AstNode::bitsAsConst(int width
, bool is_signed
)
798 std::vector
<RTLIL::State
> bits
= this->bits
;
799 if (width
>= 0 && width
< int(bits
.size()))
801 if (width
>= 0 && width
> int(bits
.size())) {
802 RTLIL::State extbit
= RTLIL::State::S0
;
803 if (is_signed
&& !bits
.empty())
804 extbit
= bits
.back();
805 while (width
> int(bits
.size()))
806 bits
.push_back(extbit
);
808 return RTLIL::Const(bits
);
811 RTLIL::Const
AstNode::bitsAsConst(int width
)
813 return bitsAsConst(width
, is_signed
);
816 RTLIL::Const
AstNode::asAttrConst()
818 log_assert(type
== AST_CONSTANT
);
824 val
.flags
|= RTLIL::CONST_FLAG_STRING
;
825 log_assert(val
.decode_string() == str
);
831 RTLIL::Const
AstNode::asParaConst()
833 RTLIL::Const val
= asAttrConst();
835 val
.flags
|= RTLIL::CONST_FLAG_SIGNED
;
839 bool AstNode::asBool() const
841 log_assert(type
== AST_CONSTANT
);
842 for (auto &bit
: bits
)
843 if (bit
== RTLIL::State::S1
)
848 int AstNode::isConst() const
850 if (type
== AST_CONSTANT
)
852 if (type
== AST_REALVALUE
)
857 uint64_t AstNode::asInt(bool is_signed
)
859 if (type
== AST_CONSTANT
)
861 RTLIL::Const v
= bitsAsConst(64, is_signed
);
864 for (int i
= 0; i
< 64; i
++)
865 if (v
.bits
.at(i
) == RTLIL::State::S1
)
866 ret
|= uint64_t(1) << i
;
871 if (type
== AST_REALVALUE
)
872 return uint64_t(realvalue
);
877 double AstNode::asReal(bool is_signed
)
879 if (type
== AST_CONSTANT
)
881 RTLIL::Const
val(bits
);
883 bool is_negative
= is_signed
&& !val
.bits
.empty() && val
.bits
.back() == RTLIL::State::S1
;
885 val
= const_neg(val
, val
, false, false, val
.bits
.size());
888 for (size_t i
= 0; i
< val
.bits
.size(); i
++)
889 // IEEE Std 1800-2012 Par 6.12.2: Individual bits that are x or z in
890 // the net or the variable shall be treated as zero upon conversion.
891 if (val
.bits
.at(i
) == RTLIL::State::S1
)
899 if (type
== AST_REALVALUE
)
905 RTLIL::Const
AstNode::realAsConst(int width
)
907 double v
= round(realvalue
);
912 if (!std::isfinite(v
)) {
914 result
.bits
= std::vector
<RTLIL::State
>(width
, RTLIL::State::Sx
);
916 bool is_negative
= v
< 0;
919 for (int i
= 0; i
< width
; i
++, v
/= 2)
920 result
.bits
.push_back((fmod(floor(v
), 2) != 0) ? RTLIL::State::S1
: RTLIL::State::S0
);
922 result
= const_neg(result
, result
, false, false, result
.bits
.size());
927 // create a new AstModule from an AST_MODULE AST node
928 static AstModule
* process_module(AstNode
*ast
, bool defer
, AstNode
*original_ast
= NULL
)
930 log_assert(ast
->type
== AST_MODULE
|| ast
->type
== AST_INTERFACE
);
933 log("Storing AST representation for module `%s'.\n", ast
->str
.c_str());
935 log("Generating RTLIL representation for module `%s'.\n", ast
->str
.c_str());
937 current_module
= new AstModule
;
938 current_module
->ast
= NULL
;
939 current_module
->name
= ast
->str
;
940 current_module
->attributes
["\\src"] = stringf("%s:%d", ast
->filename
.c_str(), ast
->linenum
);
941 current_module
->set_bool_attribute("\\cells_not_processed");
943 current_ast_mod
= ast
;
944 AstNode
*ast_before_simplify
;
945 if (original_ast
!= NULL
)
946 ast_before_simplify
= original_ast
;
948 ast_before_simplify
= ast
->clone();
950 if (flag_dump_ast1
) {
951 log("Dumping AST before simplification:\n");
952 ast
->dumpAst(NULL
, " ");
953 log("--- END OF AST DUMP ---\n");
955 if (flag_dump_vlog1
) {
956 log("Dumping Verilog AST before simplification:\n");
957 ast
->dumpVlog(NULL
, " ");
958 log("--- END OF AST DUMP ---\n");
963 bool blackbox_module
= flag_lib
;
965 if (!blackbox_module
&& !flag_noblackbox
) {
966 blackbox_module
= true;
967 for (auto child
: ast
->children
) {
968 if (child
->type
== AST_WIRE
&& (child
->is_input
|| child
->is_output
))
970 if (child
->type
== AST_PARAMETER
|| child
->type
== AST_LOCALPARAM
)
972 if (child
->type
== AST_CELL
&& child
->children
.size() > 0 && child
->children
[0]->type
== AST_CELLTYPE
&&
973 (child
->children
[0]->str
== "$specify2" || child
->children
[0]->str
== "$specify3" || child
->children
[0]->str
== "$specrule"))
975 blackbox_module
= false;
980 while (ast
->simplify(!flag_noopt
, false, false, 0, -1, false, false)) { }
982 if (flag_dump_ast2
) {
983 log("Dumping AST after simplification:\n");
984 ast
->dumpAst(NULL
, " ");
985 log("--- END OF AST DUMP ---\n");
988 if (flag_dump_vlog2
) {
989 log("Dumping Verilog AST after simplification:\n");
990 ast
->dumpVlog(NULL
, " ");
991 log("--- END OF AST DUMP ---\n");
994 if (flag_nowb
&& ast
->attributes
.count("\\whitebox")) {
995 delete ast
->attributes
.at("\\whitebox");
996 ast
->attributes
.erase("\\whitebox");
999 if (ast
->attributes
.count("\\lib_whitebox")) {
1000 if (!flag_lib
|| flag_nowb
) {
1001 delete ast
->attributes
.at("\\lib_whitebox");
1002 ast
->attributes
.erase("\\lib_whitebox");
1004 if (ast
->attributes
.count("\\whitebox")) {
1005 delete ast
->attributes
.at("\\whitebox");
1006 ast
->attributes
.erase("\\whitebox");
1008 AstNode
*n
= ast
->attributes
.at("\\lib_whitebox");
1009 ast
->attributes
["\\whitebox"] = n
;
1010 ast
->attributes
.erase("\\lib_whitebox");
1014 if (!blackbox_module
&& ast
->attributes
.count("\\blackbox")) {
1015 AstNode
*n
= ast
->attributes
.at("\\blackbox");
1016 if (n
->type
!= AST_CONSTANT
)
1017 log_file_error(ast
->filename
, ast
->linenum
, "Got blackbox attribute with non-constant value!\n");
1018 blackbox_module
= n
->asBool();
1021 if (blackbox_module
&& ast
->attributes
.count("\\whitebox")) {
1022 AstNode
*n
= ast
->attributes
.at("\\whitebox");
1023 if (n
->type
!= AST_CONSTANT
)
1024 log_file_error(ast
->filename
, ast
->linenum
, "Got whitebox attribute with non-constant value!\n");
1025 blackbox_module
= !n
->asBool();
1028 if (ast
->attributes
.count("\\noblackbox")) {
1029 if (blackbox_module
) {
1030 AstNode
*n
= ast
->attributes
.at("\\noblackbox");
1031 if (n
->type
!= AST_CONSTANT
)
1032 log_file_error(ast
->filename
, ast
->linenum
, "Got noblackbox attribute with non-constant value!\n");
1033 blackbox_module
= !n
->asBool();
1035 delete ast
->attributes
.at("\\noblackbox");
1036 ast
->attributes
.erase("\\noblackbox");
1039 if (blackbox_module
)
1041 if (ast
->attributes
.count("\\whitebox")) {
1042 delete ast
->attributes
.at("\\whitebox");
1043 ast
->attributes
.erase("\\whitebox");
1046 if (ast
->attributes
.count("\\lib_whitebox")) {
1047 delete ast
->attributes
.at("\\lib_whitebox");
1048 ast
->attributes
.erase("\\lib_whitebox");
1051 std::vector
<AstNode
*> new_children
;
1052 for (auto child
: ast
->children
) {
1053 if (child
->type
== AST_WIRE
&& (child
->is_input
|| child
->is_output
)) {
1054 new_children
.push_back(child
);
1055 } else if (child
->type
== AST_PARAMETER
) {
1056 child
->delete_children();
1057 child
->children
.push_back(AstNode::mkconst_int(0, false, 0));
1058 new_children
.push_back(child
);
1059 } else if (child
->type
== AST_CELL
&& child
->children
.size() > 0 && child
->children
[0]->type
== AST_CELLTYPE
&&
1060 (child
->children
[0]->str
== "$specify2" || child
->children
[0]->str
== "$specify3" || child
->children
[0]->str
== "$specrule")) {
1061 new_children
.push_back(child
);
1067 ast
->children
.swap(new_children
);
1069 if (ast
->attributes
.count("\\blackbox") == 0) {
1070 ast
->attributes
["\\blackbox"] = AstNode::mkconst_int(1, false);
1074 ignoreThisSignalsInInitial
= RTLIL::SigSpec();
1076 for (auto &attr
: ast
->attributes
) {
1077 if (attr
.second
->type
!= AST_CONSTANT
)
1078 log_file_error(ast
->filename
, ast
->linenum
, "Attribute `%s' with non-constant value!\n", attr
.first
.c_str());
1079 current_module
->attributes
[attr
.first
] = attr
.second
->asAttrConst();
1081 for (size_t i
= 0; i
< ast
->children
.size(); i
++) {
1082 AstNode
*node
= ast
->children
[i
];
1083 if (node
->type
== AST_WIRE
|| node
->type
== AST_MEMORY
)
1086 for (size_t i
= 0; i
< ast
->children
.size(); i
++) {
1087 AstNode
*node
= ast
->children
[i
];
1088 if (node
->type
!= AST_WIRE
&& node
->type
!= AST_MEMORY
&& node
->type
!= AST_INITIAL
)
1092 ignoreThisSignalsInInitial
.sort_and_unify();
1094 for (size_t i
= 0; i
< ast
->children
.size(); i
++) {
1095 AstNode
*node
= ast
->children
[i
];
1096 if (node
->type
== AST_INITIAL
)
1100 ignoreThisSignalsInInitial
= RTLIL::SigSpec();
1103 if (ast
->type
== AST_INTERFACE
)
1104 current_module
->set_bool_attribute("\\is_interface");
1105 current_module
->ast
= ast_before_simplify
;
1106 current_module
->nolatches
= flag_nolatches
;
1107 current_module
->nomeminit
= flag_nomeminit
;
1108 current_module
->nomem2reg
= flag_nomem2reg
;
1109 current_module
->mem2reg
= flag_mem2reg
;
1110 current_module
->noblackbox
= flag_noblackbox
;
1111 current_module
->lib
= flag_lib
;
1112 current_module
->nowb
= flag_nowb
;
1113 current_module
->noopt
= flag_noopt
;
1114 current_module
->icells
= flag_icells
;
1115 current_module
->pwires
= flag_pwires
;
1116 current_module
->autowire
= flag_autowire
;
1117 current_module
->fixup_ports();
1119 if (flag_dump_rtlil
) {
1120 log("Dumping generated RTLIL:\n");
1121 log_module(current_module
);
1122 log("--- END OF RTLIL DUMP ---\n");
1125 return current_module
;
1128 // create AstModule instances for all modules in the AST tree and add them to 'design'
1129 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
,
1130 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
)
1133 flag_dump_ast1
= dump_ast1
;
1134 flag_dump_ast2
= dump_ast2
;
1135 flag_no_dump_ptr
= no_dump_ptr
;
1136 flag_dump_vlog1
= dump_vlog1
;
1137 flag_dump_vlog2
= dump_vlog2
;
1138 flag_dump_rtlil
= dump_rtlil
;
1139 flag_nolatches
= nolatches
;
1140 flag_nomeminit
= nomeminit
;
1141 flag_nomem2reg
= nomem2reg
;
1142 flag_mem2reg
= mem2reg
;
1143 flag_noblackbox
= noblackbox
;
1147 flag_icells
= icells
;
1148 flag_pwires
= pwires
;
1149 flag_autowire
= autowire
;
1151 log_assert(current_ast
->type
== AST_DESIGN
);
1152 for (auto it
= current_ast
->children
.begin(); it
!= current_ast
->children
.end(); it
++)
1154 if ((*it
)->type
== AST_MODULE
|| (*it
)->type
== AST_INTERFACE
)
1156 for (auto n
: design
->verilog_globals
)
1157 (*it
)->children
.push_back(n
->clone());
1159 for (auto n
: design
->verilog_packages
){
1160 for (auto o
: n
->children
) {
1161 AstNode
*cloned_node
= o
->clone();
1162 cloned_node
->str
= n
->str
+ std::string("::") + cloned_node
->str
.substr(1);
1163 (*it
)->children
.push_back(cloned_node
);
1167 if (flag_icells
&& (*it
)->str
.substr(0, 2) == "\\$")
1168 (*it
)->str
= (*it
)->str
.substr(1);
1171 (*it
)->str
= "$abstract" + (*it
)->str
;
1173 if (design
->has((*it
)->str
)) {
1174 RTLIL::Module
*existing_mod
= design
->module((*it
)->str
);
1175 if (!nooverwrite
&& !overwrite
&& !existing_mod
->get_bool_attribute("\\blackbox")) {
1176 log_file_error((*it
)->filename
, (*it
)->linenum
, "Re-definition of module `%s'!\n", (*it
)->str
.c_str());
1177 } else if (nooverwrite
) {
1178 log("Ignoring re-definition of module `%s' at %s:%d.\n",
1179 (*it
)->str
.c_str(), (*it
)->filename
.c_str(), (*it
)->linenum
);
1182 log("Replacing existing%s module `%s' at %s:%d.\n",
1183 existing_mod
->get_bool_attribute("\\blackbox") ? " blackbox" : "",
1184 (*it
)->str
.c_str(), (*it
)->filename
.c_str(), (*it
)->linenum
);
1185 design
->remove(existing_mod
);
1189 design
->add(process_module(*it
, defer
));
1191 else if ((*it
)->type
== AST_PACKAGE
)
1192 design
->verilog_packages
.push_back((*it
)->clone());
1194 design
->verilog_globals
.push_back((*it
)->clone());
1198 // AstModule destructor
1199 AstModule::~AstModule()
1206 // An interface port with modport is specified like this:
1207 // <interface_name>.<modport_name>
1208 // This function splits the interface_name from the modport_name, and fails if it is not a valid combination
1209 std::pair
<std::string
,std::string
> AST::split_modport_from_type(std::string name_type
)
1211 std::string interface_type
= "";
1212 std::string interface_modport
= "";
1213 size_t ndots
= std::count(name_type
.begin(), name_type
.end(), '.');
1214 // Separate the interface instance name from any modports:
1215 if (ndots
== 0) { // Does not have modport
1216 interface_type
= name_type
;
1219 std::stringstream
name_type_stream(name_type
);
1220 std::string segment
;
1221 std::vector
<std::string
> seglist
;
1222 while(std::getline(name_type_stream
, segment
, '.')) {
1223 seglist
.push_back(segment
);
1225 if (ndots
== 1) { // Has modport
1226 interface_type
= seglist
[0];
1227 interface_modport
= seglist
[1];
1229 else { // Erroneous port type
1230 log_error("More than two '.' in signal port type (%s)\n", name_type
.c_str());
1233 return std::pair
<std::string
,std::string
>(interface_type
, interface_modport
);
1237 AstNode
* AST::find_modport(AstNode
*intf
, std::string name
)
1239 for (auto &ch
: intf
->children
)
1240 if (ch
->type
== AST_MODPORT
)
1241 if (ch
->str
== name
) // Modport found
1246 // Iterate over all wires in an interface and add them as wires in the AST module:
1247 void AST::explode_interface_port(AstNode
*module_ast
, RTLIL::Module
* intfmodule
, std::string intfname
, AstNode
*modport
)
1249 for (auto &wire_it
: intfmodule
->wires_
){
1250 AstNode
*wire
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, AstNode::mkconst_int(wire_it
.second
->width
-1, true), AstNode::mkconst_int(0, true)));
1251 std::string origname
= log_id(wire_it
.first
);
1252 std::string newname
= intfname
+ "." + origname
;
1253 wire
->str
= newname
;
1254 if (modport
!= NULL
) {
1255 bool found_in_modport
= false;
1256 // Search for the current wire in the wire list for the current modport
1257 for (auto &ch
: modport
->children
) {
1258 if (ch
->type
== AST_MODPORTMEMBER
) {
1259 std::string compare_name
= "\\" + origname
;
1260 if (ch
->str
== compare_name
) { // Found signal. The modport decides whether it is input or output
1261 found_in_modport
= true;
1262 wire
->is_input
= ch
->is_input
;
1263 wire
->is_output
= ch
->is_output
;
1268 if (found_in_modport
) {
1269 module_ast
->children
.push_back(wire
);
1271 else { // If not found in modport, do not create port
1275 else { // If no modport, set inout
1276 wire
->is_input
= true;
1277 wire
->is_output
= true;
1278 module_ast
->children
.push_back(wire
);
1283 // When an interface instance is found in a module, the whole RTLIL for the module will be rederived again
1284 // from AST. The interface members are copied into the AST module with the prefix of the interface.
1285 void AstModule::reprocess_module(RTLIL::Design
*design
, dict
<RTLIL::IdString
, RTLIL::Module
*> local_interfaces
)
1287 bool is_top
= false;
1288 AstNode
*new_ast
= ast
->clone();
1289 for (auto &intf
: local_interfaces
) {
1290 std::string intfname
= intf
.first
.str();
1291 RTLIL::Module
*intfmodule
= intf
.second
;
1292 for (auto &wire_it
: intfmodule
->wires_
){
1293 AstNode
*wire
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, AstNode::mkconst_int(wire_it
.second
->width
-1, true), AstNode::mkconst_int(0, true)));
1294 std::string newname
= log_id(wire_it
.first
);
1295 newname
= intfname
+ "." + newname
;
1296 wire
->str
= newname
;
1297 new_ast
->children
.push_back(wire
);
1301 AstNode
*ast_before_replacing_interface_ports
= new_ast
->clone();
1303 // Explode all interface ports. Note this will only have an effect on 'top
1304 // level' modules. Other sub-modules will have their interface ports
1305 // exploded via the derive(..) function
1306 for (size_t i
=0; i
<new_ast
->children
.size(); i
++)
1308 AstNode
*ch2
= new_ast
->children
[i
];
1309 if (ch2
->type
== AST_INTERFACEPORT
) { // Is an interface port
1310 std::string name_port
= ch2
->str
; // Name of the interface port
1311 if (ch2
->children
.size() > 0) {
1312 for(size_t j
=0; j
<ch2
->children
.size();j
++) {
1313 AstNode
*ch
= ch2
->children
[j
];
1314 if(ch
->type
== AST_INTERFACEPORTTYPE
) { // Found the AST node containing the type of the interface
1315 std::pair
<std::string
,std::string
> res
= split_modport_from_type(ch
->str
);
1316 std::string interface_type
= res
.first
;
1317 std::string interface_modport
= res
.second
; // Is "", if no modport
1318 if (design
->modules_
.count(interface_type
) > 0) {
1319 // Add a cell to the module corresponding to the interface port such that
1320 // it can further propagated down if needed:
1321 AstNode
*celltype_for_intf
= new AstNode(AST_CELLTYPE
);
1322 celltype_for_intf
->str
= interface_type
;
1323 AstNode
*cell_for_intf
= new AstNode(AST_CELL
, celltype_for_intf
);
1324 cell_for_intf
->str
= name_port
+ "_inst_from_top_dummy";
1325 new_ast
->children
.push_back(cell_for_intf
);
1327 // Get all members of this non-overridden dummy interface instance:
1328 RTLIL::Module
*intfmodule
= design
->modules_
[interface_type
]; // All interfaces should at this point in time (assuming
1329 // reprocess_module is called from the hierarchy pass) be
1330 // present in design->modules_
1331 AstModule
*ast_module_of_interface
= (AstModule
*)intfmodule
;
1332 std::string interface_modport_compare_str
= "\\" + interface_modport
;
1333 AstNode
*modport
= find_modport(ast_module_of_interface
->ast
, interface_modport_compare_str
); // modport == NULL if no modport
1334 // Iterate over all wires in the interface and add them to the module:
1335 explode_interface_port(new_ast
, intfmodule
, name_port
, modport
);
1344 // The old module will be deleted. Rename and mark for deletion:
1345 std::string original_name
= this->name
.str();
1346 std::string changed_name
= original_name
+ "_before_replacing_local_interfaces";
1347 design
->rename(this, changed_name
);
1348 this->set_bool_attribute("\\to_delete");
1350 // Check if the module was the top module. If it was, we need to remove the top attribute and put it on the
1352 if (this->get_bool_attribute("\\initial_top")) {
1353 this->attributes
.erase("\\initial_top");
1357 // Generate RTLIL from AST for the new module and add to the design:
1358 AstModule
*newmod
= process_module(new_ast
, false, ast_before_replacing_interface_ports
);
1360 design
->add(newmod
);
1361 RTLIL::Module
* mod
= design
->module(original_name
);
1363 mod
->set_bool_attribute("\\top");
1365 // Set the attribute "interfaces_replaced_in_module" so that it does not happen again.
1366 mod
->set_bool_attribute("\\interfaces_replaced_in_module");
1369 // create a new parametric module (when needed) and return the name of the generated module - WITH support for interfaces
1370 // This method is used to explode the interface when the interface is a port of the module (not instantiated inside)
1371 RTLIL::IdString
AstModule::derive(RTLIL::Design
*design
, dict
<RTLIL::IdString
, RTLIL::Const
> parameters
, dict
<RTLIL::IdString
, RTLIL::Module
*> interfaces
, dict
<RTLIL::IdString
, RTLIL::IdString
> modports
, bool mayfail
)
1373 AstNode
*new_ast
= NULL
;
1374 std::string modname
= derive_common(design
, parameters
, &new_ast
, mayfail
);
1376 // Since interfaces themselves may be instantiated with different parameters,
1377 // "modname" must also take those into account, so that unique modules
1378 // are derived for any variant of interface connections:
1379 std::string interf_info
= "";
1381 bool has_interfaces
= false;
1382 for(auto &intf
: interfaces
) {
1383 interf_info
+= log_id(intf
.second
->name
);
1384 has_interfaces
= true;
1388 modname
+= "$interfaces$" + interf_info
;
1391 if (!design
->has(modname
)) {
1392 new_ast
->str
= modname
;
1394 // Iterate over all interfaces which are ports in this module:
1395 for(auto &intf
: interfaces
) {
1396 RTLIL::Module
* intfmodule
= intf
.second
;
1397 std::string intfname
= intf
.first
.str();
1398 // Check if a modport applies for the interface port:
1399 AstNode
*modport
= NULL
;
1400 if (modports
.count(intfname
) > 0) {
1401 std::string interface_modport
= modports
.at(intfname
).str();
1402 AstModule
*ast_module_of_interface
= (AstModule
*)intfmodule
;
1403 AstNode
*ast_node_of_interface
= ast_module_of_interface
->ast
;
1404 modport
= find_modport(ast_node_of_interface
, interface_modport
);
1406 // Iterate over all wires in the interface and add them to the module:
1407 explode_interface_port(new_ast
, intfmodule
, intfname
, modport
);
1410 design
->add(process_module(new_ast
, false));
1411 design
->module(modname
)->check();
1413 RTLIL::Module
* mod
= design
->module(modname
);
1415 // Now that the interfaces have been exploded, we can delete the dummy port related to every interface.
1416 for(auto &intf
: interfaces
) {
1417 if(mod
->wires_
.count(intf
.first
)) {
1418 mod
->wires_
.erase(intf
.first
);
1420 // We copy the cell of the interface to the sub-module such that it can further be found if it is propagated
1421 // down to sub-sub-modules etc.
1422 RTLIL::Cell
* new_subcell
= mod
->addCell(intf
.first
, intf
.second
->name
);
1423 new_subcell
->set_bool_attribute("\\is_interface");
1426 log_error("No port with matching name found (%s) in %s. Stopping\n", log_id(intf
.first
), modname
.c_str());
1430 // If any interfaces were replaced, set the attribute 'interfaces_replaced_in_module':
1431 if (interfaces
.size() > 0) {
1432 mod
->set_bool_attribute("\\interfaces_replaced_in_module");
1436 log("Found cached RTLIL representation for module `%s'.\n", modname
.c_str());
1443 // create a new parametric module (when needed) and return the name of the generated module - without support for interfaces
1444 RTLIL::IdString
AstModule::derive(RTLIL::Design
*design
, dict
<RTLIL::IdString
, RTLIL::Const
> parameters
, bool mayfail
)
1446 AstNode
*new_ast
= NULL
;
1447 std::string modname
= derive_common(design
, parameters
, &new_ast
, mayfail
);
1449 if (!design
->has(modname
)) {
1450 new_ast
->str
= modname
;
1451 design
->add(process_module(new_ast
, false));
1452 design
->module(modname
)->check();
1454 log("Found cached RTLIL representation for module `%s'.\n", modname
.c_str());
1461 // create a new parametric module (when needed) and return the name of the generated module
1462 std::string
AstModule::derive_common(RTLIL::Design
*design
, dict
<RTLIL::IdString
, RTLIL::Const
> parameters
, AstNode
**new_ast_out
, bool)
1464 std::string stripped_name
= name
.str();
1466 if (stripped_name
.substr(0, 9) == "$abstract")
1467 stripped_name
= stripped_name
.substr(9);
1469 log_header(design
, "Executing AST frontend in derive mode using pre-parsed AST for module `%s'.\n", stripped_name
.c_str());
1472 flag_dump_ast1
= false;
1473 flag_dump_ast2
= false;
1474 flag_dump_vlog1
= false;
1475 flag_dump_vlog2
= false;
1476 flag_nolatches
= nolatches
;
1477 flag_nomeminit
= nomeminit
;
1478 flag_nomem2reg
= nomem2reg
;
1479 flag_mem2reg
= mem2reg
;
1480 flag_noblackbox
= noblackbox
;
1484 flag_icells
= icells
;
1485 flag_pwires
= pwires
;
1486 flag_autowire
= autowire
;
1487 use_internal_line_num();
1489 std::string para_info
;
1490 AstNode
*new_ast
= ast
->clone();
1492 int para_counter
= 0;
1493 int orig_parameters_n
= parameters
.size();
1494 for (auto it
= new_ast
->children
.begin(); it
!= new_ast
->children
.end(); it
++) {
1495 AstNode
*child
= *it
;
1496 if (child
->type
!= AST_PARAMETER
)
1499 std::string para_id
= child
->str
;
1500 if (parameters
.count(para_id
) > 0) {
1501 log("Parameter %s = %s\n", child
->str
.c_str(), log_signal(RTLIL::SigSpec(parameters
[child
->str
])));
1503 para_info
+= stringf("%s=%s", child
->str
.c_str(), log_signal(RTLIL::SigSpec(parameters
[para_id
])));
1504 delete child
->children
.at(0);
1505 if ((parameters
[para_id
].flags
& RTLIL::CONST_FLAG_STRING
) != 0)
1506 child
->children
[0] = AstNode::mkconst_str(parameters
[para_id
].decode_string());
1508 child
->children
[0] = AstNode::mkconst_bits(parameters
[para_id
].bits
, (parameters
[para_id
].flags
& RTLIL::CONST_FLAG_SIGNED
) != 0);
1509 parameters
.erase(para_id
);
1512 para_id
= stringf("$%d", para_counter
);
1513 if (parameters
.count(para_id
) > 0) {
1514 log("Parameter %d (%s) = %s\n", para_counter
, child
->str
.c_str(), log_signal(RTLIL::SigSpec(parameters
[para_id
])));
1515 goto rewrite_parameter
;
1519 for (auto param
: parameters
) {
1520 AstNode
*defparam
= new AstNode(AST_DEFPARAM
, new AstNode(AST_IDENTIFIER
));
1521 defparam
->children
[0]->str
= param
.first
.str();
1522 if ((param
.second
.flags
& RTLIL::CONST_FLAG_STRING
) != 0)
1523 defparam
->children
.push_back(AstNode::mkconst_str(param
.second
.decode_string()));
1525 defparam
->children
.push_back(AstNode::mkconst_bits(param
.second
.bits
, (param
.second
.flags
& RTLIL::CONST_FLAG_SIGNED
) != 0));
1526 new_ast
->children
.push_back(defparam
);
1529 std::string modname
;
1531 if (orig_parameters_n
== 0)
1532 modname
= stripped_name
;
1533 else if (para_info
.size() > 60)
1534 modname
= "$paramod$" + sha1(para_info
) + stripped_name
;
1536 modname
= "$paramod" + stripped_name
+ para_info
;
1539 (*new_ast_out
) = new_ast
;
1543 RTLIL::Module
*AstModule::clone() const
1545 AstModule
*new_mod
= new AstModule
;
1546 new_mod
->name
= name
;
1549 new_mod
->ast
= ast
->clone();
1550 new_mod
->nolatches
= nolatches
;
1551 new_mod
->nomeminit
= nomeminit
;
1552 new_mod
->nomem2reg
= nomem2reg
;
1553 new_mod
->mem2reg
= mem2reg
;
1555 new_mod
->noopt
= noopt
;
1556 new_mod
->icells
= icells
;
1557 new_mod
->pwires
= pwires
;
1558 new_mod
->autowire
= autowire
;
1563 // internal dummy line number callbacks
1565 int internal_line_num
;
1566 void internal_set_line_num(int n
) {
1567 internal_line_num
= n
;
1569 int internal_get_line_num() {
1570 return internal_line_num
;
1574 // use internal dummy line number callbacks
1575 void AST::use_internal_line_num()
1577 set_line_num
= &internal_set_line_num
;
1578 get_line_num
= &internal_get_line_num
;