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_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;
167 // check if attribute exists and has non-zero value
168 bool AstNode::get_bool_attribute(RTLIL::IdString id
)
170 if (attributes
.count(id
) == 0)
173 AstNode
*attr
= attributes
.at(id
);
174 if (attr
->type
!= AST_CONSTANT
)
175 log_file_error(attr
->filename
, attr
->linenum
, "Attribute `%s' with non-constant value!\n", id
.c_str());
177 return attr
->integer
!= 0;
180 // create new node (AstNode constructor)
181 // (the optional child arguments make it easier to create AST trees)
182 AstNode::AstNode(AstNodeType type
, AstNode
*child1
, AstNode
*child2
, AstNode
*child3
)
184 static unsigned int hashidx_count
= 123456789;
185 hashidx_count
= mkhash_xorshift(hashidx_count
);
186 hashidx_
= hashidx_count
;
189 filename
= current_filename
;
190 linenum
= get_line_num();
199 range_swapped
= false;
209 children
.push_back(child1
);
211 children
.push_back(child2
);
213 children
.push_back(child3
);
216 // create a (deep recursive) copy of a node
217 AstNode
*AstNode::clone() const
219 AstNode
*that
= new AstNode
;
221 for (auto &it
: that
->children
)
223 for (auto &it
: that
->attributes
)
224 it
.second
= it
.second
->clone();
228 // create a (deep recursive) copy of a node use 'other' as target root node
229 void AstNode::cloneInto(AstNode
*other
) const
231 AstNode
*tmp
= clone();
232 other
->delete_children();
234 tmp
->children
.clear();
235 tmp
->attributes
.clear();
239 // delete all children in this node
240 void AstNode::delete_children()
242 for (auto &it
: children
)
246 for (auto &it
: attributes
)
251 // AstNode destructor
257 // create a nice text representation of the node
258 // (traverse tree by recursion, use 'other' pointer for diffing two AST trees)
259 void AstNode::dumpAst(FILE *f
, std::string indent
) const
262 for (auto f
: log_files
)
267 std::string type_name
= type2str(type
);
268 fprintf(f
, "%s%s <%s:%d>", indent
.c_str(), type_name
.c_str(), filename
.c_str(), linenum
);
270 if (!flag_no_dump_ptr
) {
272 fprintf(f
, " [%p -> %p]", this, id2ast
);
274 fprintf(f
, " [%p]", this);
278 fprintf(f
, " str='%s'", str
.c_str());
280 fprintf(f
, " bits='");
281 for (size_t i
= bits
.size(); i
> 0; i
--)
282 fprintf(f
, "%c", bits
[i
-1] == RTLIL::S0
? '0' :
283 bits
[i
-1] == RTLIL::S1
? '1' :
284 bits
[i
-1] == RTLIL::Sx
? 'x' :
285 bits
[i
-1] == RTLIL::Sz
? 'z' : '?');
286 fprintf(f
, "'(%d)", GetSize(bits
));
289 fprintf(f
, " input");
291 fprintf(f
, " output");
293 fprintf(f
, " logic");
294 if (is_reg
) // this is an AST dump, not Verilog - if we see "logic reg" that's fine.
297 fprintf(f
, " signed");
299 fprintf(f
, " port=%d", port_id
);
300 if (range_valid
|| range_left
!= -1 || range_right
!= 0)
301 fprintf(f
, " %srange=[%d:%d]%s", range_swapped
? "swapped_" : "", range_left
, range_right
, range_valid
? "" : "!");
303 fprintf(f
, " int=%u", (int)integer
);
305 fprintf(f
, " real=%e", realvalue
);
306 if (!multirange_dimensions
.empty()) {
307 fprintf(f
, " multirange=[");
308 for (int v
: multirange_dimensions
)
309 fprintf(f
, " %d", v
);
314 for (auto &it
: attributes
) {
315 fprintf(f
, "%s ATTR %s:\n", indent
.c_str(), it
.first
.c_str());
316 it
.second
->dumpAst(f
, indent
+ " ");
319 for (size_t i
= 0; i
< children
.size(); i
++)
320 children
[i
]->dumpAst(f
, indent
+ " ");
325 // helper function for AstNode::dumpVlog()
326 static std::string
id2vl(std::string txt
)
328 if (txt
.size() > 1 && txt
[0] == '\\')
330 for (size_t i
= 0; i
< txt
.size(); i
++) {
331 if ('A' <= txt
[i
] && txt
[i
] <= 'Z') continue;
332 if ('a' <= txt
[i
] && txt
[i
] <= 'z') continue;
333 if ('0' <= txt
[i
] && txt
[i
] <= '9') continue;
334 if (txt
[i
] == '_') continue;
335 txt
= "\\" + txt
+ " ";
341 // dump AST node as Verilog pseudo-code
342 void AstNode::dumpVlog(FILE *f
, std::string indent
) const
346 std::vector
<AstNode
*> rem_children1
, rem_children2
;
349 for (auto f
: log_files
)
354 for (auto &it
: attributes
) {
355 fprintf(f
, "%s" "(* %s = ", indent
.c_str(), id2vl(it
.first
.str()).c_str());
356 it
.second
->dumpVlog(f
, "");
357 fprintf(f
, " *)%s", indent
.empty() ? "" : "\n");
363 fprintf(f
, "%s" "module %s(", indent
.c_str(), id2vl(str
).c_str());
364 for (auto child
: children
)
365 if (child
->type
== AST_WIRE
&& (child
->is_input
|| child
->is_output
)) {
366 fprintf(f
, "%s%s", first
? "" : ", ", id2vl(child
->str
).c_str());
371 for (auto child
: children
)
372 if (child
->type
== AST_PARAMETER
|| child
->type
== AST_LOCALPARAM
|| child
->type
== AST_DEFPARAM
)
373 child
->dumpVlog(f
, indent
+ " ");
375 rem_children1
.push_back(child
);
377 for (auto child
: rem_children1
)
378 if (child
->type
== AST_WIRE
|| child
->type
== AST_AUTOWIRE
|| child
->type
== AST_MEMORY
)
379 child
->dumpVlog(f
, indent
+ " ");
381 rem_children2
.push_back(child
);
382 rem_children1
.clear();
384 for (auto child
: rem_children2
)
385 if (child
->type
== AST_TASK
|| child
->type
== AST_FUNCTION
)
386 child
->dumpVlog(f
, indent
+ " ");
388 rem_children1
.push_back(child
);
389 rem_children2
.clear();
391 for (auto child
: rem_children1
)
392 child
->dumpVlog(f
, indent
+ " ");
393 rem_children1
.clear();
395 fprintf(f
, "%s" "endmodule\n", indent
.c_str());
399 if (is_input
&& is_output
)
400 fprintf(f
, "%s" "inout", indent
.c_str());
402 fprintf(f
, "%s" "input", indent
.c_str());
404 fprintf(f
, "%s" "output", indent
.c_str());
406 fprintf(f
, "%s" "wire", indent
.c_str());
408 fprintf(f
, "%s" "reg", (is_input
|| is_output
) ? " " : indent
.c_str());
410 fprintf(f
, " signed");
411 for (auto child
: children
) {
413 child
->dumpVlog(f
, "");
415 fprintf(f
, " %s", id2vl(str
).c_str());
420 fprintf(f
, "%s" "memory", indent
.c_str());
422 fprintf(f
, " signed");
423 for (auto child
: children
) {
425 child
->dumpVlog(f
, "");
427 fprintf(f
, " %s", id2vl(str
).c_str());
436 fprintf(f
, "[%d:%d]", range_right
, range_left
);
438 fprintf(f
, "[%d:%d]", range_left
, range_right
);
440 for (auto child
: children
) {
441 fprintf(f
, "%c", first
? '[' : ':');
442 child
->dumpVlog(f
, "");
450 fprintf(f
, "%s" "always @", indent
.c_str());
451 for (auto child
: children
) {
452 if (child
->type
!= AST_POSEDGE
&& child
->type
!= AST_NEGEDGE
&& child
->type
!= AST_EDGE
)
454 fprintf(f
, first
? "(" : ", ");
455 child
->dumpVlog(f
, "");
458 fprintf(f
, first
? "*\n" : ")\n");
459 for (auto child
: children
) {
460 if (child
->type
!= AST_POSEDGE
&& child
->type
!= AST_NEGEDGE
&& child
->type
!= AST_EDGE
)
461 child
->dumpVlog(f
, indent
+ " ");
466 fprintf(f
, "%s" "initial\n", indent
.c_str());
467 for (auto child
: children
) {
468 if (child
->type
!= AST_POSEDGE
&& child
->type
!= AST_NEGEDGE
&& child
->type
!= AST_EDGE
)
469 child
->dumpVlog(f
, indent
+ " ");
476 if (type
== AST_POSEDGE
)
477 fprintf(f
, "posedge ");
478 if (type
== AST_NEGEDGE
)
479 fprintf(f
, "negedge ");
480 for (auto child
: children
)
481 child
->dumpVlog(f
, "");
485 fprintf(f
, "%s", id2vl(str
).c_str());
486 for (auto child
: children
)
487 child
->dumpVlog(f
, "");
492 fprintf(f
, "\"%s\"", str
.c_str());
493 else if (bits
.size() == 32)
494 fprintf(f
, "%d", RTLIL::Const(bits
).as_int());
496 fprintf(f
, "%d'b %s", GetSize(bits
), RTLIL::Const(bits
).as_string().c_str());
500 fprintf(f
, "%e", realvalue
);
504 if (children
.size() == 1) {
505 children
[0]->dumpVlog(f
, indent
);
507 fprintf(f
, "%s" "begin\n", indent
.c_str());
508 for (auto child
: children
)
509 child
->dumpVlog(f
, indent
+ " ");
510 fprintf(f
, "%s" "end\n", indent
.c_str());
515 if (!children
.empty() && children
[0]->type
== AST_CONDX
)
516 fprintf(f
, "%s" "casex (", indent
.c_str());
517 else if (!children
.empty() && children
[0]->type
== AST_CONDZ
)
518 fprintf(f
, "%s" "casez (", indent
.c_str());
520 fprintf(f
, "%s" "case (", indent
.c_str());
521 children
[0]->dumpVlog(f
, "");
523 for (size_t i
= 1; i
< children
.size(); i
++) {
524 AstNode
*child
= children
[i
];
525 child
->dumpVlog(f
, indent
+ " ");
527 fprintf(f
, "%s" "endcase\n", indent
.c_str());
533 for (auto child
: children
) {
534 if (child
->type
== AST_BLOCK
) {
536 child
->dumpVlog(f
, indent
+ " ");
539 fprintf(f
, "%s", first
? indent
.c_str() : ", ");
540 if (child
->type
== AST_DEFAULT
)
541 fprintf(f
, "default");
543 child
->dumpVlog(f
, "");
550 fprintf(f
, "%sassign ", indent
.c_str());
551 children
[0]->dumpVlog(f
, "");
553 children
[1]->dumpVlog(f
, "");
559 fprintf(f
, "%s", indent
.c_str());
560 children
[0]->dumpVlog(f
, "");
561 fprintf(f
, " %s ", type
== AST_ASSIGN_EQ
? "=" : "<=");
562 children
[1]->dumpVlog(f
, "");
568 for (int i
= GetSize(children
)-1; i
>= 0; i
--) {
569 auto child
= children
[i
];
572 child
->dumpVlog(f
, "");
580 children
[0]->dumpVlog(f
, "");
582 children
[1]->dumpVlog(f
, "");
586 if (0) { case AST_BIT_NOT
: txt
= "~"; }
587 if (0) { case AST_REDUCE_AND
: txt
= "&"; }
588 if (0) { case AST_REDUCE_OR
: txt
= "|"; }
589 if (0) { case AST_REDUCE_XOR
: txt
= "^"; }
590 if (0) { case AST_REDUCE_XNOR
: txt
= "~^"; }
591 if (0) { case AST_REDUCE_BOOL
: txt
= "|"; }
592 if (0) { case AST_POS
: txt
= "+"; }
593 if (0) { case AST_NEG
: txt
= "-"; }
594 if (0) { case AST_LOGIC_NOT
: txt
= "!"; }
595 fprintf(f
, "%s(", txt
.c_str());
596 children
[0]->dumpVlog(f
, "");
600 if (0) { case AST_BIT_AND
: txt
= "&"; }
601 if (0) { case AST_BIT_OR
: txt
= "|"; }
602 if (0) { case AST_BIT_XOR
: txt
= "^"; }
603 if (0) { case AST_BIT_XNOR
: txt
= "~^"; }
604 if (0) { case AST_SHIFT_LEFT
: txt
= "<<"; }
605 if (0) { case AST_SHIFT_RIGHT
: txt
= ">>"; }
606 if (0) { case AST_SHIFT_SLEFT
: txt
= "<<<"; }
607 if (0) { case AST_SHIFT_SRIGHT
: txt
= ">>>"; }
608 if (0) { case AST_LT
: txt
= "<"; }
609 if (0) { case AST_LE
: txt
= "<="; }
610 if (0) { case AST_EQ
: txt
= "=="; }
611 if (0) { case AST_NE
: txt
= "!="; }
612 if (0) { case AST_EQX
: txt
= "==="; }
613 if (0) { case AST_NEX
: txt
= "!=="; }
614 if (0) { case AST_GE
: txt
= ">="; }
615 if (0) { case AST_GT
: txt
= ">"; }
616 if (0) { case AST_ADD
: txt
= "+"; }
617 if (0) { case AST_SUB
: txt
= "-"; }
618 if (0) { case AST_MUL
: txt
= "*"; }
619 if (0) { case AST_DIV
: txt
= "/"; }
620 if (0) { case AST_MOD
: txt
= "%"; }
621 if (0) { case AST_POW
: txt
= "**"; }
622 if (0) { case AST_LOGIC_AND
: txt
= "&&"; }
623 if (0) { case AST_LOGIC_OR
: txt
= "||"; }
625 children
[0]->dumpVlog(f
, "");
626 fprintf(f
, ")%s(", txt
.c_str());
627 children
[1]->dumpVlog(f
, "");
633 children
[0]->dumpVlog(f
, "");
635 children
[1]->dumpVlog(f
, "");
637 children
[2]->dumpVlog(f
, "");
642 std::string type_name
= type2str(type
);
643 fprintf(f
, "%s" "/** %s **/%s", indent
.c_str(), type_name
.c_str(), indent
.empty() ? "" : "\n");
644 // dumpAst(f, indent, NULL);
650 // check if two AST nodes are identical
651 bool AstNode::operator==(const AstNode
&other
) const
653 if (type
!= other
.type
)
655 if (children
.size() != other
.children
.size())
657 if (str
!= other
.str
)
659 if (bits
!= other
.bits
)
661 if (is_input
!= other
.is_input
)
663 if (is_output
!= other
.is_output
)
665 if (is_logic
!= other
.is_logic
)
667 if (is_reg
!= other
.is_reg
)
669 if (is_signed
!= other
.is_signed
)
671 if (is_string
!= other
.is_string
)
673 if (range_valid
!= other
.range_valid
)
675 if (range_swapped
!= other
.range_swapped
)
677 if (port_id
!= other
.port_id
)
679 if (range_left
!= other
.range_left
)
681 if (range_right
!= other
.range_right
)
683 if (integer
!= other
.integer
)
685 for (size_t i
= 0; i
< children
.size(); i
++)
686 if (*children
[i
] != *other
.children
[i
])
691 // check if two AST nodes are not identical
692 bool AstNode::operator!=(const AstNode
&other
) const
694 return !(*this == other
);
697 // check if this AST contains the given node
698 bool AstNode::contains(const AstNode
*other
) const
702 for (auto child
: children
)
703 if (child
->contains(other
))
708 // create an AST node for a constant (using a 32 bit int as value)
709 AstNode
*AstNode::mkconst_int(uint32_t v
, bool is_signed
, int width
)
711 AstNode
*node
= new AstNode(AST_CONSTANT
);
713 node
->is_signed
= is_signed
;
714 for (int i
= 0; i
< width
; i
++) {
715 node
->bits
.push_back((v
& 1) ? RTLIL::S1
: RTLIL::S0
);
718 node
->range_valid
= true;
719 node
->range_left
= width
-1;
720 node
->range_right
= 0;
724 // create an AST node for a constant (using a bit vector as value)
725 AstNode
*AstNode::mkconst_bits(const std::vector
<RTLIL::State
> &v
, bool is_signed
)
727 AstNode
*node
= new AstNode(AST_CONSTANT
);
728 node
->is_signed
= is_signed
;
730 for (size_t i
= 0; i
< 32; i
++) {
731 if (i
< node
->bits
.size())
732 node
->integer
|= (node
->bits
[i
] == RTLIL::S1
) << i
;
733 else if (is_signed
&& !node
->bits
.empty())
734 node
->integer
|= (node
->bits
.back() == RTLIL::S1
) << i
;
736 node
->range_valid
= true;
737 node
->range_left
= node
->bits
.size()-1;
738 node
->range_right
= 0;
742 // create an AST node for a constant (using a string in bit vector form as value)
743 AstNode
*AstNode::mkconst_str(const std::vector
<RTLIL::State
> &v
)
745 AstNode
*node
= mkconst_str(RTLIL::Const(v
).decode_string());
746 while (GetSize(node
->bits
) < GetSize(v
))
747 node
->bits
.push_back(RTLIL::State::S0
);
748 log_assert(node
->bits
== v
);
752 // create an AST node for a constant (using a string as value)
753 AstNode
*AstNode::mkconst_str(const std::string
&str
)
755 std::vector
<RTLIL::State
> data
;
756 data
.reserve(str
.size() * 8);
757 for (size_t i
= 0; i
< str
.size(); i
++) {
758 unsigned char ch
= str
[str
.size() - i
- 1];
759 for (int j
= 0; j
< 8; j
++) {
760 data
.push_back((ch
& 1) ? RTLIL::S1
: RTLIL::S0
);
764 AstNode
*node
= AstNode::mkconst_bits(data
, false);
765 node
->is_string
= true;
770 bool AstNode::bits_only_01() const
772 for (auto bit
: bits
)
773 if (bit
!= RTLIL::S0
&& bit
!= RTLIL::S1
)
778 RTLIL::Const
AstNode::bitsAsConst(int width
, bool is_signed
)
780 std::vector
<RTLIL::State
> bits
= this->bits
;
781 if (width
>= 0 && width
< int(bits
.size()))
783 if (width
>= 0 && width
> int(bits
.size())) {
784 RTLIL::State extbit
= RTLIL::State::S0
;
785 if (is_signed
&& !bits
.empty())
786 extbit
= bits
.back();
787 while (width
> int(bits
.size()))
788 bits
.push_back(extbit
);
790 return RTLIL::Const(bits
);
793 RTLIL::Const
AstNode::bitsAsConst(int width
)
795 return bitsAsConst(width
, is_signed
);
798 RTLIL::Const
AstNode::asAttrConst()
800 log_assert(type
== AST_CONSTANT
);
806 val
.flags
|= RTLIL::CONST_FLAG_STRING
;
807 log_assert(val
.decode_string() == str
);
813 RTLIL::Const
AstNode::asParaConst()
815 RTLIL::Const val
= asAttrConst();
817 val
.flags
|= RTLIL::CONST_FLAG_SIGNED
;
821 bool AstNode::asBool() const
823 log_assert(type
== AST_CONSTANT
);
824 for (auto &bit
: bits
)
825 if (bit
== RTLIL::State::S1
)
830 int AstNode::isConst() const
832 if (type
== AST_CONSTANT
)
834 if (type
== AST_REALVALUE
)
839 uint64_t AstNode::asInt(bool is_signed
)
841 if (type
== AST_CONSTANT
)
843 RTLIL::Const v
= bitsAsConst(64, is_signed
);
846 for (int i
= 0; i
< 64; i
++)
847 if (v
.bits
.at(i
) == RTLIL::State::S1
)
848 ret
|= uint64_t(1) << i
;
853 if (type
== AST_REALVALUE
)
854 return uint64_t(realvalue
);
859 double AstNode::asReal(bool is_signed
)
861 if (type
== AST_CONSTANT
)
863 RTLIL::Const
val(bits
);
865 bool is_negative
= is_signed
&& !val
.bits
.empty() && val
.bits
.back() == RTLIL::State::S1
;
867 val
= const_neg(val
, val
, false, false, val
.bits
.size());
870 for (size_t i
= 0; i
< val
.bits
.size(); i
++)
871 // IEEE Std 1800-2012 Par 6.12.2: Individual bits that are x or z in
872 // the net or the variable shall be treated as zero upon conversion.
873 if (val
.bits
.at(i
) == RTLIL::State::S1
)
881 if (type
== AST_REALVALUE
)
887 RTLIL::Const
AstNode::realAsConst(int width
)
889 double v
= round(realvalue
);
894 if (!std::isfinite(v
)) {
896 result
.bits
= std::vector
<RTLIL::State
>(width
, RTLIL::State::Sx
);
898 bool is_negative
= v
< 0;
901 for (int i
= 0; i
< width
; i
++, v
/= 2)
902 result
.bits
.push_back((fmod(floor(v
), 2) != 0) ? RTLIL::State::S1
: RTLIL::State::S0
);
904 result
= const_neg(result
, result
, false, false, result
.bits
.size());
909 // create a new AstModule from an AST_MODULE AST node
910 static AstModule
* process_module(AstNode
*ast
, bool defer
, AstNode
*original_ast
= NULL
)
912 log_assert(ast
->type
== AST_MODULE
|| ast
->type
== AST_INTERFACE
);
915 log("Storing AST representation for module `%s'.\n", ast
->str
.c_str());
917 log("Generating RTLIL representation for module `%s'.\n", ast
->str
.c_str());
919 current_module
= new AstModule
;
920 current_module
->ast
= NULL
;
921 current_module
->name
= ast
->str
;
922 current_module
->attributes
["\\src"] = stringf("%s:%d", ast
->filename
.c_str(), ast
->linenum
);
923 current_module
->set_bool_attribute("\\cells_not_processed");
925 current_ast_mod
= ast
;
926 AstNode
*ast_before_simplify
;
927 if (original_ast
!= NULL
)
928 ast_before_simplify
= original_ast
;
930 ast_before_simplify
= ast
->clone();
932 if (flag_dump_ast1
) {
933 log("Dumping AST before simplification:\n");
934 ast
->dumpAst(NULL
, " ");
935 log("--- END OF AST DUMP ---\n");
937 if (flag_dump_vlog1
) {
938 log("Dumping Verilog AST before simplification:\n");
939 ast
->dumpVlog(NULL
, " ");
940 log("--- END OF AST DUMP ---\n");
945 bool blackbox_module
= flag_lib
;
947 if (!blackbox_module
&& !flag_noblackbox
) {
948 blackbox_module
= true;
949 for (auto child
: ast
->children
) {
950 if (child
->type
== AST_WIRE
&& (child
->is_input
|| child
->is_output
))
952 if (child
->type
== AST_PARAMETER
|| child
->type
== AST_LOCALPARAM
)
954 if (child
->type
== AST_CELL
&& child
->children
.size() > 0 && child
->children
[0]->type
== AST_CELLTYPE
&&
955 (child
->children
[0]->str
== "$specify2" || child
->children
[0]->str
== "$specify3" || child
->children
[0]->str
== "$specrule"))
957 blackbox_module
= false;
962 while (ast
->simplify(!flag_noopt
, false, false, 0, -1, false, false)) { }
964 if (flag_dump_ast2
) {
965 log("Dumping AST after simplification:\n");
966 ast
->dumpAst(NULL
, " ");
967 log("--- END OF AST DUMP ---\n");
970 if (flag_dump_vlog2
) {
971 log("Dumping Verilog AST after simplification:\n");
972 ast
->dumpVlog(NULL
, " ");
973 log("--- END OF AST DUMP ---\n");
976 if (flag_nowb
&& ast
->attributes
.count("\\whitebox")) {
977 delete ast
->attributes
.at("\\whitebox");
978 ast
->attributes
.erase("\\whitebox");
981 if (ast
->attributes
.count("\\lib_whitebox")) {
982 if (!flag_lib
|| flag_nowb
) {
983 delete ast
->attributes
.at("\\lib_whitebox");
984 ast
->attributes
.erase("\\lib_whitebox");
986 if (ast
->attributes
.count("\\whitebox")) {
987 delete ast
->attributes
.at("\\whitebox");
988 ast
->attributes
.erase("\\whitebox");
990 AstNode
*n
= ast
->attributes
.at("\\lib_whitebox");
991 ast
->attributes
["\\whitebox"] = n
;
992 ast
->attributes
.erase("\\lib_whitebox");
996 if (!blackbox_module
&& ast
->attributes
.count("\\blackbox")) {
997 AstNode
*n
= ast
->attributes
.at("\\blackbox");
998 if (n
->type
!= AST_CONSTANT
)
999 log_file_error(ast
->filename
, ast
->linenum
, "Got blackbox attribute with non-constant value!\n");
1000 blackbox_module
= n
->asBool();
1003 if (blackbox_module
&& ast
->attributes
.count("\\whitebox")) {
1004 AstNode
*n
= ast
->attributes
.at("\\whitebox");
1005 if (n
->type
!= AST_CONSTANT
)
1006 log_file_error(ast
->filename
, ast
->linenum
, "Got whitebox attribute with non-constant value!\n");
1007 blackbox_module
= !n
->asBool();
1010 if (ast
->attributes
.count("\\noblackbox")) {
1011 if (blackbox_module
) {
1012 AstNode
*n
= ast
->attributes
.at("\\noblackbox");
1013 if (n
->type
!= AST_CONSTANT
)
1014 log_file_error(ast
->filename
, ast
->linenum
, "Got noblackbox attribute with non-constant value!\n");
1015 blackbox_module
= !n
->asBool();
1017 delete ast
->attributes
.at("\\noblackbox");
1018 ast
->attributes
.erase("\\noblackbox");
1021 if (blackbox_module
)
1023 if (ast
->attributes
.count("\\whitebox")) {
1024 delete ast
->attributes
.at("\\whitebox");
1025 ast
->attributes
.erase("\\whitebox");
1028 if (ast
->attributes
.count("\\lib_whitebox")) {
1029 delete ast
->attributes
.at("\\lib_whitebox");
1030 ast
->attributes
.erase("\\lib_whitebox");
1033 std::vector
<AstNode
*> new_children
;
1034 for (auto child
: ast
->children
) {
1035 if (child
->type
== AST_WIRE
&& (child
->is_input
|| child
->is_output
)) {
1036 new_children
.push_back(child
);
1037 } else if (child
->type
== AST_PARAMETER
) {
1038 child
->delete_children();
1039 child
->children
.push_back(AstNode::mkconst_int(0, false, 0));
1040 new_children
.push_back(child
);
1041 } else if (child
->type
== AST_CELL
&& child
->children
.size() > 0 && child
->children
[0]->type
== AST_CELLTYPE
&&
1042 (child
->children
[0]->str
== "$specify2" || child
->children
[0]->str
== "$specify3" || child
->children
[0]->str
== "$specrule")) {
1043 new_children
.push_back(child
);
1049 ast
->children
.swap(new_children
);
1051 if (ast
->attributes
.count("\\blackbox") == 0) {
1052 ast
->attributes
["\\blackbox"] = AstNode::mkconst_int(1, false);
1056 ignoreThisSignalsInInitial
= RTLIL::SigSpec();
1058 for (auto &attr
: ast
->attributes
) {
1059 if (attr
.second
->type
!= AST_CONSTANT
)
1060 log_file_error(ast
->filename
, ast
->linenum
, "Attribute `%s' with non-constant value!\n", attr
.first
.c_str());
1061 current_module
->attributes
[attr
.first
] = attr
.second
->asAttrConst();
1063 for (size_t i
= 0; i
< ast
->children
.size(); i
++) {
1064 AstNode
*node
= ast
->children
[i
];
1065 if (node
->type
== AST_WIRE
|| node
->type
== AST_MEMORY
)
1068 for (size_t i
= 0; i
< ast
->children
.size(); i
++) {
1069 AstNode
*node
= ast
->children
[i
];
1070 if (node
->type
!= AST_WIRE
&& node
->type
!= AST_MEMORY
&& node
->type
!= AST_INITIAL
)
1074 ignoreThisSignalsInInitial
.sort_and_unify();
1076 for (size_t i
= 0; i
< ast
->children
.size(); i
++) {
1077 AstNode
*node
= ast
->children
[i
];
1078 if (node
->type
== AST_INITIAL
)
1082 ignoreThisSignalsInInitial
= RTLIL::SigSpec();
1085 if (ast
->type
== AST_INTERFACE
)
1086 current_module
->set_bool_attribute("\\is_interface");
1087 current_module
->ast
= ast_before_simplify
;
1088 current_module
->nolatches
= flag_nolatches
;
1089 current_module
->nomeminit
= flag_nomeminit
;
1090 current_module
->nomem2reg
= flag_nomem2reg
;
1091 current_module
->mem2reg
= flag_mem2reg
;
1092 current_module
->noblackbox
= flag_noblackbox
;
1093 current_module
->lib
= flag_lib
;
1094 current_module
->nowb
= flag_nowb
;
1095 current_module
->noopt
= flag_noopt
;
1096 current_module
->icells
= flag_icells
;
1097 current_module
->autowire
= flag_autowire
;
1098 current_module
->fixup_ports();
1100 if (flag_dump_rtlil
) {
1101 log("Dumping generated RTLIL:\n");
1102 log_module(current_module
);
1103 log("--- END OF RTLIL DUMP ---\n");
1106 return current_module
;
1109 // create AstModule instances for all modules in the AST tree and add them to 'design'
1110 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
,
1111 bool nolatches
, bool nomeminit
, bool nomem2reg
, bool mem2reg
, bool noblackbox
, bool lib
, bool nowb
, bool noopt
, bool icells
, bool nooverwrite
, bool overwrite
, bool defer
, bool autowire
)
1114 flag_dump_ast1
= dump_ast1
;
1115 flag_dump_ast2
= dump_ast2
;
1116 flag_no_dump_ptr
= no_dump_ptr
;
1117 flag_dump_vlog1
= dump_vlog1
;
1118 flag_dump_vlog2
= dump_vlog2
;
1119 flag_dump_rtlil
= dump_rtlil
;
1120 flag_nolatches
= nolatches
;
1121 flag_nomeminit
= nomeminit
;
1122 flag_nomem2reg
= nomem2reg
;
1123 flag_mem2reg
= mem2reg
;
1124 flag_noblackbox
= noblackbox
;
1128 flag_icells
= icells
;
1129 flag_autowire
= autowire
;
1131 log_assert(current_ast
->type
== AST_DESIGN
);
1132 for (auto it
= current_ast
->children
.begin(); it
!= current_ast
->children
.end(); it
++)
1134 if ((*it
)->type
== AST_MODULE
|| (*it
)->type
== AST_INTERFACE
)
1136 for (auto n
: design
->verilog_globals
)
1137 (*it
)->children
.push_back(n
->clone());
1139 for (auto n
: design
->verilog_packages
){
1140 for (auto o
: n
->children
) {
1141 AstNode
*cloned_node
= o
->clone();
1142 cloned_node
->str
= n
->str
+ std::string("::") + cloned_node
->str
.substr(1);
1143 (*it
)->children
.push_back(cloned_node
);
1147 if (flag_icells
&& (*it
)->str
.substr(0, 2) == "\\$")
1148 (*it
)->str
= (*it
)->str
.substr(1);
1151 (*it
)->str
= "$abstract" + (*it
)->str
;
1153 if (design
->has((*it
)->str
)) {
1154 RTLIL::Module
*existing_mod
= design
->module((*it
)->str
);
1155 if (!nooverwrite
&& !overwrite
&& !existing_mod
->get_bool_attribute("\\blackbox")) {
1156 log_file_error((*it
)->filename
, (*it
)->linenum
, "Re-definition of module `%s'!\n", (*it
)->str
.c_str());
1157 } else if (nooverwrite
) {
1158 log("Ignoring re-definition of module `%s' at %s:%d.\n",
1159 (*it
)->str
.c_str(), (*it
)->filename
.c_str(), (*it
)->linenum
);
1162 log("Replacing existing%s module `%s' at %s:%d.\n",
1163 existing_mod
->get_bool_attribute("\\blackbox") ? " blackbox" : "",
1164 (*it
)->str
.c_str(), (*it
)->filename
.c_str(), (*it
)->linenum
);
1165 design
->remove(existing_mod
);
1169 design
->add(process_module(*it
, defer
));
1171 else if ((*it
)->type
== AST_PACKAGE
)
1172 design
->verilog_packages
.push_back((*it
)->clone());
1174 design
->verilog_globals
.push_back((*it
)->clone());
1178 // AstModule destructor
1179 AstModule::~AstModule()
1186 // An interface port with modport is specified like this:
1187 // <interface_name>.<modport_name>
1188 // This function splits the interface_name from the modport_name, and fails if it is not a valid combination
1189 std::pair
<std::string
,std::string
> AST::split_modport_from_type(std::string name_type
)
1191 std::string interface_type
= "";
1192 std::string interface_modport
= "";
1193 size_t ndots
= std::count(name_type
.begin(), name_type
.end(), '.');
1194 // Separate the interface instance name from any modports:
1195 if (ndots
== 0) { // Does not have modport
1196 interface_type
= name_type
;
1199 std::stringstream
name_type_stream(name_type
);
1200 std::string segment
;
1201 std::vector
<std::string
> seglist
;
1202 while(std::getline(name_type_stream
, segment
, '.')) {
1203 seglist
.push_back(segment
);
1205 if (ndots
== 1) { // Has modport
1206 interface_type
= seglist
[0];
1207 interface_modport
= seglist
[1];
1209 else { // Erroneous port type
1210 log_error("More than two '.' in signal port type (%s)\n", name_type
.c_str());
1213 return std::pair
<std::string
,std::string
>(interface_type
, interface_modport
);
1217 AstNode
* AST::find_modport(AstNode
*intf
, std::string name
)
1219 for (auto &ch
: intf
->children
)
1220 if (ch
->type
== AST_MODPORT
)
1221 if (ch
->str
== name
) // Modport found
1226 // Iterate over all wires in an interface and add them as wires in the AST module:
1227 void AST::explode_interface_port(AstNode
*module_ast
, RTLIL::Module
* intfmodule
, std::string intfname
, AstNode
*modport
)
1229 for (auto &wire_it
: intfmodule
->wires_
){
1230 AstNode
*wire
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, AstNode::mkconst_int(wire_it
.second
->width
-1, true), AstNode::mkconst_int(0, true)));
1231 std::string origname
= log_id(wire_it
.first
);
1232 std::string newname
= intfname
+ "." + origname
;
1233 wire
->str
= newname
;
1234 if (modport
!= NULL
) {
1235 bool found_in_modport
= false;
1236 // Search for the current wire in the wire list for the current modport
1237 for (auto &ch
: modport
->children
) {
1238 if (ch
->type
== AST_MODPORTMEMBER
) {
1239 std::string compare_name
= "\\" + origname
;
1240 if (ch
->str
== compare_name
) { // Found signal. The modport decides whether it is input or output
1241 found_in_modport
= true;
1242 wire
->is_input
= ch
->is_input
;
1243 wire
->is_output
= ch
->is_output
;
1248 if (found_in_modport
) {
1249 module_ast
->children
.push_back(wire
);
1251 else { // If not found in modport, do not create port
1255 else { // If no modport, set inout
1256 wire
->is_input
= true;
1257 wire
->is_output
= true;
1258 module_ast
->children
.push_back(wire
);
1263 // When an interface instance is found in a module, the whole RTLIL for the module will be rederived again
1264 // from AST. The interface members are copied into the AST module with the prefix of the interface.
1265 void AstModule::reprocess_module(RTLIL::Design
*design
, dict
<RTLIL::IdString
, RTLIL::Module
*> local_interfaces
)
1267 bool is_top
= false;
1268 AstNode
*new_ast
= ast
->clone();
1269 for (auto &intf
: local_interfaces
) {
1270 std::string intfname
= intf
.first
.str();
1271 RTLIL::Module
*intfmodule
= intf
.second
;
1272 for (auto &wire_it
: intfmodule
->wires_
){
1273 AstNode
*wire
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, AstNode::mkconst_int(wire_it
.second
->width
-1, true), AstNode::mkconst_int(0, true)));
1274 std::string newname
= log_id(wire_it
.first
);
1275 newname
= intfname
+ "." + newname
;
1276 wire
->str
= newname
;
1277 new_ast
->children
.push_back(wire
);
1281 AstNode
*ast_before_replacing_interface_ports
= new_ast
->clone();
1283 // Explode all interface ports. Note this will only have an effect on 'top
1284 // level' modules. Other sub-modules will have their interface ports
1285 // exploded via the derive(..) function
1286 for (size_t i
=0; i
<new_ast
->children
.size(); i
++)
1288 AstNode
*ch2
= new_ast
->children
[i
];
1289 if (ch2
->type
== AST_INTERFACEPORT
) { // Is an interface port
1290 std::string name_port
= ch2
->str
; // Name of the interface port
1291 if (ch2
->children
.size() > 0) {
1292 for(size_t j
=0; j
<ch2
->children
.size();j
++) {
1293 AstNode
*ch
= ch2
->children
[j
];
1294 if(ch
->type
== AST_INTERFACEPORTTYPE
) { // Found the AST node containing the type of the interface
1295 std::pair
<std::string
,std::string
> res
= split_modport_from_type(ch
->str
);
1296 std::string interface_type
= res
.first
;
1297 std::string interface_modport
= res
.second
; // Is "", if no modport
1298 if (design
->modules_
.count(interface_type
) > 0) {
1299 // Add a cell to the module corresponding to the interface port such that
1300 // it can further propagated down if needed:
1301 AstNode
*celltype_for_intf
= new AstNode(AST_CELLTYPE
);
1302 celltype_for_intf
->str
= interface_type
;
1303 AstNode
*cell_for_intf
= new AstNode(AST_CELL
, celltype_for_intf
);
1304 cell_for_intf
->str
= name_port
+ "_inst_from_top_dummy";
1305 new_ast
->children
.push_back(cell_for_intf
);
1307 // Get all members of this non-overridden dummy interface instance:
1308 RTLIL::Module
*intfmodule
= design
->modules_
[interface_type
]; // All interfaces should at this point in time (assuming
1309 // reprocess_module is called from the hierarchy pass) be
1310 // present in design->modules_
1311 AstModule
*ast_module_of_interface
= (AstModule
*)intfmodule
;
1312 std::string interface_modport_compare_str
= "\\" + interface_modport
;
1313 AstNode
*modport
= find_modport(ast_module_of_interface
->ast
, interface_modport_compare_str
); // modport == NULL if no modport
1314 // Iterate over all wires in the interface and add them to the module:
1315 explode_interface_port(new_ast
, intfmodule
, name_port
, modport
);
1324 // The old module will be deleted. Rename and mark for deletion:
1325 std::string original_name
= this->name
.str();
1326 std::string changed_name
= original_name
+ "_before_replacing_local_interfaces";
1327 design
->rename(this, changed_name
);
1328 this->set_bool_attribute("\\to_delete");
1330 // Check if the module was the top module. If it was, we need to remove the top attribute and put it on the
1332 if (this->get_bool_attribute("\\initial_top")) {
1333 this->attributes
.erase("\\initial_top");
1337 // Generate RTLIL from AST for the new module and add to the design:
1338 AstModule
*newmod
= process_module(new_ast
, false, ast_before_replacing_interface_ports
);
1340 design
->add(newmod
);
1341 RTLIL::Module
* mod
= design
->module(original_name
);
1343 mod
->set_bool_attribute("\\top");
1345 // Set the attribute "interfaces_replaced_in_module" so that it does not happen again.
1346 mod
->set_bool_attribute("\\interfaces_replaced_in_module");
1349 // create a new parametric module (when needed) and return the name of the generated module - WITH support for interfaces
1350 // This method is used to explode the interface when the interface is a port of the module (not instantiated inside)
1351 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
)
1353 AstNode
*new_ast
= NULL
;
1354 std::string modname
= derive_common(design
, parameters
, &new_ast
, mayfail
);
1356 // Since interfaces themselves may be instantiated with different parameters,
1357 // "modname" must also take those into account, so that unique modules
1358 // are derived for any variant of interface connections:
1359 std::string interf_info
= "";
1361 bool has_interfaces
= false;
1362 for(auto &intf
: interfaces
) {
1363 interf_info
+= log_id(intf
.second
->name
);
1364 has_interfaces
= true;
1368 modname
+= "$interfaces$" + interf_info
;
1371 if (!design
->has(modname
)) {
1372 new_ast
->str
= modname
;
1374 // Iterate over all interfaces which are ports in this module:
1375 for(auto &intf
: interfaces
) {
1376 RTLIL::Module
* intfmodule
= intf
.second
;
1377 std::string intfname
= intf
.first
.str();
1378 // Check if a modport applies for the interface port:
1379 AstNode
*modport
= NULL
;
1380 if (modports
.count(intfname
) > 0) {
1381 std::string interface_modport
= modports
.at(intfname
).str();
1382 AstModule
*ast_module_of_interface
= (AstModule
*)intfmodule
;
1383 AstNode
*ast_node_of_interface
= ast_module_of_interface
->ast
;
1384 modport
= find_modport(ast_node_of_interface
, interface_modport
);
1386 // Iterate over all wires in the interface and add them to the module:
1387 explode_interface_port(new_ast
, intfmodule
, intfname
, modport
);
1390 design
->add(process_module(new_ast
, false));
1391 design
->module(modname
)->check();
1393 RTLIL::Module
* mod
= design
->module(modname
);
1395 // Now that the interfaces have been exploded, we can delete the dummy port related to every interface.
1396 for(auto &intf
: interfaces
) {
1397 if(mod
->wires_
.count(intf
.first
)) {
1398 mod
->wires_
.erase(intf
.first
);
1400 // We copy the cell of the interface to the sub-module such that it can further be found if it is propagated
1401 // down to sub-sub-modules etc.
1402 RTLIL::Cell
* new_subcell
= mod
->addCell(intf
.first
, intf
.second
->name
);
1403 new_subcell
->set_bool_attribute("\\is_interface");
1406 log_error("No port with matching name found (%s) in %s. Stopping\n", log_id(intf
.first
), modname
.c_str());
1410 // If any interfaces were replaced, set the attribute 'interfaces_replaced_in_module':
1411 if (interfaces
.size() > 0) {
1412 mod
->set_bool_attribute("\\interfaces_replaced_in_module");
1416 log("Found cached RTLIL representation for module `%s'.\n", modname
.c_str());
1423 // create a new parametric module (when needed) and return the name of the generated module - without support for interfaces
1424 RTLIL::IdString
AstModule::derive(RTLIL::Design
*design
, dict
<RTLIL::IdString
, RTLIL::Const
> parameters
, bool mayfail
)
1426 AstNode
*new_ast
= NULL
;
1427 std::string modname
= derive_common(design
, parameters
, &new_ast
, mayfail
);
1429 if (!design
->has(modname
)) {
1430 new_ast
->str
= modname
;
1431 design
->add(process_module(new_ast
, false));
1432 design
->module(modname
)->check();
1434 log("Found cached RTLIL representation for module `%s'.\n", modname
.c_str());
1441 // create a new parametric module (when needed) and return the name of the generated module
1442 std::string
AstModule::derive_common(RTLIL::Design
*design
, dict
<RTLIL::IdString
, RTLIL::Const
> parameters
, AstNode
**new_ast_out
, bool)
1444 std::string stripped_name
= name
.str();
1446 if (stripped_name
.substr(0, 9) == "$abstract")
1447 stripped_name
= stripped_name
.substr(9);
1449 log_header(design
, "Executing AST frontend in derive mode using pre-parsed AST for module `%s'.\n", stripped_name
.c_str());
1452 flag_dump_ast1
= false;
1453 flag_dump_ast2
= false;
1454 flag_dump_vlog1
= false;
1455 flag_dump_vlog2
= false;
1456 flag_nolatches
= nolatches
;
1457 flag_nomeminit
= nomeminit
;
1458 flag_nomem2reg
= nomem2reg
;
1459 flag_mem2reg
= mem2reg
;
1460 flag_noblackbox
= noblackbox
;
1464 flag_icells
= icells
;
1465 flag_autowire
= autowire
;
1466 use_internal_line_num();
1468 std::string para_info
;
1469 AstNode
*new_ast
= ast
->clone();
1471 int para_counter
= 0;
1472 int orig_parameters_n
= parameters
.size();
1473 for (auto it
= new_ast
->children
.begin(); it
!= new_ast
->children
.end(); it
++) {
1474 AstNode
*child
= *it
;
1475 if (child
->type
!= AST_PARAMETER
)
1478 std::string para_id
= child
->str
;
1479 if (parameters
.count(para_id
) > 0) {
1480 log("Parameter %s = %s\n", child
->str
.c_str(), log_signal(RTLIL::SigSpec(parameters
[child
->str
])));
1482 para_info
+= stringf("%s=%s", child
->str
.c_str(), log_signal(RTLIL::SigSpec(parameters
[para_id
])));
1483 delete child
->children
.at(0);
1484 if ((parameters
[para_id
].flags
& RTLIL::CONST_FLAG_STRING
) != 0)
1485 child
->children
[0] = AstNode::mkconst_str(parameters
[para_id
].decode_string());
1487 child
->children
[0] = AstNode::mkconst_bits(parameters
[para_id
].bits
, (parameters
[para_id
].flags
& RTLIL::CONST_FLAG_SIGNED
) != 0);
1488 parameters
.erase(para_id
);
1491 para_id
= stringf("$%d", para_counter
);
1492 if (parameters
.count(para_id
) > 0) {
1493 log("Parameter %d (%s) = %s\n", para_counter
, child
->str
.c_str(), log_signal(RTLIL::SigSpec(parameters
[para_id
])));
1494 goto rewrite_parameter
;
1498 for (auto param
: parameters
) {
1499 AstNode
*defparam
= new AstNode(AST_DEFPARAM
, new AstNode(AST_IDENTIFIER
));
1500 defparam
->children
[0]->str
= param
.first
.str();
1501 if ((param
.second
.flags
& RTLIL::CONST_FLAG_STRING
) != 0)
1502 defparam
->children
.push_back(AstNode::mkconst_str(param
.second
.decode_string()));
1504 defparam
->children
.push_back(AstNode::mkconst_bits(param
.second
.bits
, (param
.second
.flags
& RTLIL::CONST_FLAG_SIGNED
) != 0));
1505 new_ast
->children
.push_back(defparam
);
1508 std::string modname
;
1510 if (orig_parameters_n
== 0)
1511 modname
= stripped_name
;
1512 else if (para_info
.size() > 60)
1513 modname
= "$paramod$" + sha1(para_info
) + stripped_name
;
1515 modname
= "$paramod" + stripped_name
+ para_info
;
1518 (*new_ast_out
) = new_ast
;
1522 RTLIL::Module
*AstModule::clone() const
1524 AstModule
*new_mod
= new AstModule
;
1525 new_mod
->name
= name
;
1528 new_mod
->ast
= ast
->clone();
1529 new_mod
->nolatches
= nolatches
;
1530 new_mod
->nomeminit
= nomeminit
;
1531 new_mod
->nomem2reg
= nomem2reg
;
1532 new_mod
->mem2reg
= mem2reg
;
1534 new_mod
->noopt
= noopt
;
1535 new_mod
->icells
= icells
;
1536 new_mod
->autowire
= autowire
;
1541 // internal dummy line number callbacks
1543 int internal_line_num
;
1544 void internal_set_line_num(int n
) {
1545 internal_line_num
= n
;
1547 int internal_get_line_num() {
1548 return internal_line_num
;
1552 // use internal dummy line number callbacks
1553 void AST::use_internal_line_num()
1555 set_line_num
= &internal_set_line_num
;
1556 get_line_num
= &internal_get_line_num
;