2 * yosys -- Yosys Open SYnthesis Suite
4 * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
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 Module
*current_module
;
56 bool current_always_clocked
;
57 dict
<std::string
, int> current_memwr_count
;
58 dict
<std::string
, pool
<int>> current_memwr_visible
;
61 // convert node types to string
62 std::string
AST::type2str(AstNodeType type
)
66 #define X(_item) case _item: return #_item;
171 X(AST_INTERFACEPORTTYPE
)
187 // check if attribute exists and has non-zero value
188 bool AstNode::get_bool_attribute(RTLIL::IdString id
)
190 if (attributes
.count(id
) == 0)
193 AstNode
*attr
= attributes
.at(id
);
194 if (attr
->type
!= AST_CONSTANT
)
195 log_file_error(attr
->filename
, attr
->location
.first_line
, "Attribute `%s' with non-constant value!\n", id
.c_str());
197 return attr
->integer
!= 0;
200 // create new node (AstNode constructor)
201 // (the optional child arguments make it easier to create AST trees)
202 AstNode::AstNode(AstNodeType type
, AstNode
*child1
, AstNode
*child2
, AstNode
*child3
, AstNode
*child4
)
204 static unsigned int hashidx_count
= 123456789;
205 hashidx_count
= mkhash_xorshift(hashidx_count
);
206 hashidx_
= hashidx_count
;
209 filename
= current_filename
;
222 range_swapped
= false;
223 is_custom_type
= false;
234 children
.push_back(child1
);
236 children
.push_back(child2
);
238 children
.push_back(child3
);
240 children
.push_back(child4
);
243 // create a (deep recursive) copy of a node
244 AstNode
*AstNode::clone() const
246 AstNode
*that
= new AstNode
;
248 for (auto &it
: that
->children
)
250 for (auto &it
: that
->attributes
)
251 it
.second
= it
.second
->clone();
255 // create a (deep recursive) copy of a node use 'other' as target root node
256 void AstNode::cloneInto(AstNode
*other
) const
258 AstNode
*tmp
= clone();
259 other
->delete_children();
261 tmp
->children
.clear();
262 tmp
->attributes
.clear();
266 // delete all children in this node
267 void AstNode::delete_children()
269 for (auto &it
: children
)
273 for (auto &it
: attributes
)
278 // AstNode destructor
284 // create a nice text representation of the node
285 // (traverse tree by recursion, use 'other' pointer for diffing two AST trees)
286 void AstNode::dumpAst(FILE *f
, std::string indent
) const
289 for (auto f
: log_files
)
294 std::string type_name
= type2str(type
);
295 fprintf(f
, "%s%s <%s>", indent
.c_str(), type_name
.c_str(), loc_string().c_str());
297 if (!flag_no_dump_ptr
) {
299 fprintf(f
, " [%p -> %p]", this, id2ast
);
301 fprintf(f
, " [%p]", this);
305 fprintf(f
, " str='%s'", str
.c_str());
307 fprintf(f
, " bits='");
308 for (size_t i
= bits
.size(); i
> 0; i
--)
309 fprintf(f
, "%c", bits
[i
-1] == State::S0
? '0' :
310 bits
[i
-1] == State::S1
? '1' :
311 bits
[i
-1] == RTLIL::Sx
? 'x' :
312 bits
[i
-1] == RTLIL::Sz
? 'z' : '?');
313 fprintf(f
, "'(%d)", GetSize(bits
));
316 fprintf(f
, " input");
318 fprintf(f
, " output");
320 fprintf(f
, " logic");
321 if (is_reg
) // this is an AST dump, not Verilog - if we see "logic reg" that's fine.
324 fprintf(f
, " signed");
326 fprintf(f
, " unsized");
328 fprintf(f
, " basic_prep");
330 fprintf(f
, " lookahead");
332 fprintf(f
, " port=%d", port_id
);
333 if (range_valid
|| range_left
!= -1 || range_right
!= 0)
334 fprintf(f
, " %srange=[%d:%d]%s", range_swapped
? "swapped_" : "", range_left
, range_right
, range_valid
? "" : "!");
336 fprintf(f
, " int=%u", (int)integer
);
338 fprintf(f
, " real=%e", realvalue
);
339 if (!multirange_dimensions
.empty()) {
340 fprintf(f
, " multirange=[");
341 for (int v
: multirange_dimensions
)
342 fprintf(f
, " %d", v
);
345 if (!multirange_swapped
.empty()) {
346 fprintf(f
, " multirange_swapped=[");
347 for (auto v
: multirange_swapped
)
348 fprintf(f
, " %d", v
);
352 fprintf(f
, " type=enum");
356 for (auto &it
: attributes
) {
357 fprintf(f
, "%s ATTR %s:\n", indent
.c_str(), it
.first
.c_str());
358 it
.second
->dumpAst(f
, indent
+ " ");
361 for (size_t i
= 0; i
< children
.size(); i
++)
362 children
[i
]->dumpAst(f
, indent
+ " ");
367 // helper function for AstNode::dumpVlog()
368 static std::string
id2vl(std::string txt
)
370 if (txt
.size() > 1 && txt
[0] == '\\')
372 for (size_t i
= 0; i
< txt
.size(); i
++) {
373 if ('A' <= txt
[i
] && txt
[i
] <= 'Z') continue;
374 if ('a' <= txt
[i
] && txt
[i
] <= 'z') continue;
375 if ('0' <= txt
[i
] && txt
[i
] <= '9') continue;
376 if (txt
[i
] == '_') continue;
377 txt
= "\\" + txt
+ " ";
383 // dump AST node as Verilog pseudo-code
384 void AstNode::dumpVlog(FILE *f
, std::string indent
) const
388 std::vector
<AstNode
*> rem_children1
, rem_children2
;
391 for (auto f
: log_files
)
396 for (auto &it
: attributes
) {
397 fprintf(f
, "%s" "(* %s = ", indent
.c_str(), id2vl(it
.first
.str()).c_str());
398 it
.second
->dumpVlog(f
, "");
399 fprintf(f
, " *)%s", indent
.empty() ? "" : "\n");
405 fprintf(f
, "%s" "module %s(", indent
.c_str(), id2vl(str
).c_str());
406 for (auto child
: children
)
407 if (child
->type
== AST_WIRE
&& (child
->is_input
|| child
->is_output
)) {
408 fprintf(f
, "%s%s", first
? "" : ", ", id2vl(child
->str
).c_str());
413 for (auto child
: children
)
414 if (child
->type
== AST_PARAMETER
|| child
->type
== AST_LOCALPARAM
|| child
->type
== AST_DEFPARAM
)
415 child
->dumpVlog(f
, indent
+ " ");
417 rem_children1
.push_back(child
);
419 for (auto child
: rem_children1
)
420 if (child
->type
== AST_WIRE
|| child
->type
== AST_AUTOWIRE
|| child
->type
== AST_MEMORY
)
421 child
->dumpVlog(f
, indent
+ " ");
423 rem_children2
.push_back(child
);
424 rem_children1
.clear();
426 for (auto child
: rem_children2
)
427 if (child
->type
== AST_TASK
|| child
->type
== AST_FUNCTION
)
428 child
->dumpVlog(f
, indent
+ " ");
430 rem_children1
.push_back(child
);
431 rem_children2
.clear();
433 for (auto child
: rem_children1
)
434 child
->dumpVlog(f
, indent
+ " ");
435 rem_children1
.clear();
437 fprintf(f
, "%s" "endmodule\n", indent
.c_str());
441 if (is_input
&& is_output
)
442 fprintf(f
, "%s" "inout", indent
.c_str());
444 fprintf(f
, "%s" "input", indent
.c_str());
446 fprintf(f
, "%s" "output", indent
.c_str());
448 fprintf(f
, "%s" "wire", indent
.c_str());
450 fprintf(f
, "%s" "reg", (is_input
|| is_output
) ? " " : indent
.c_str());
452 fprintf(f
, " signed");
453 for (auto child
: children
) {
455 child
->dumpVlog(f
, "");
457 fprintf(f
, " %s", id2vl(str
).c_str());
462 fprintf(f
, "%s" "memory", indent
.c_str());
464 fprintf(f
, " signed");
465 for (auto child
: children
) {
467 child
->dumpVlog(f
, "");
469 fprintf(f
, " %s", id2vl(str
).c_str());
478 fprintf(f
, "[%d:%d]", range_right
, range_left
);
480 fprintf(f
, "[%d:%d]", range_left
, range_right
);
482 for (auto child
: children
) {
483 fprintf(f
, "%c", first
? '[' : ':');
484 child
->dumpVlog(f
, "");
492 fprintf(f
, "%s" "always @", indent
.c_str());
493 for (auto child
: children
) {
494 if (child
->type
!= AST_POSEDGE
&& child
->type
!= AST_NEGEDGE
&& child
->type
!= AST_EDGE
)
496 fprintf(f
, first
? "(" : ", ");
497 child
->dumpVlog(f
, "");
500 fprintf(f
, first
? "*\n" : ")\n");
501 for (auto child
: children
) {
502 if (child
->type
!= AST_POSEDGE
&& child
->type
!= AST_NEGEDGE
&& child
->type
!= AST_EDGE
)
503 child
->dumpVlog(f
, indent
+ " ");
508 fprintf(f
, "%s" "initial\n", indent
.c_str());
509 for (auto child
: children
) {
510 if (child
->type
!= AST_POSEDGE
&& child
->type
!= AST_NEGEDGE
&& child
->type
!= AST_EDGE
)
511 child
->dumpVlog(f
, indent
+ " ");
518 if (type
== AST_POSEDGE
)
519 fprintf(f
, "posedge ");
520 if (type
== AST_NEGEDGE
)
521 fprintf(f
, "negedge ");
522 for (auto child
: children
)
523 child
->dumpVlog(f
, "");
527 fprintf(f
, "%s", id2vl(str
).c_str());
528 for (auto child
: children
)
529 child
->dumpVlog(f
, "");
534 fprintf(f
, "\"%s\"", str
.c_str());
535 else if (bits
.size() == 32)
536 fprintf(f
, "%d", RTLIL::Const(bits
).as_int());
538 fprintf(f
, "%d'b %s", GetSize(bits
), RTLIL::Const(bits
).as_string().c_str());
542 fprintf(f
, "%e", realvalue
);
546 if (children
.size() == 1) {
547 children
[0]->dumpVlog(f
, indent
);
549 fprintf(f
, "%s" "begin\n", indent
.c_str());
550 for (auto child
: children
)
551 child
->dumpVlog(f
, indent
+ " ");
552 fprintf(f
, "%s" "end\n", indent
.c_str());
557 if (children
.size() > 1 && children
[1]->type
== AST_CONDX
)
558 fprintf(f
, "%s" "casex (", indent
.c_str());
559 else if (children
.size() > 1 && children
[1]->type
== AST_CONDZ
)
560 fprintf(f
, "%s" "casez (", indent
.c_str());
562 fprintf(f
, "%s" "case (", indent
.c_str());
563 children
[0]->dumpVlog(f
, "");
565 for (size_t i
= 1; i
< children
.size(); i
++) {
566 AstNode
*child
= children
[i
];
567 child
->dumpVlog(f
, indent
+ " ");
569 fprintf(f
, "%s" "endcase\n", indent
.c_str());
575 for (auto child
: children
) {
576 if (child
->type
== AST_BLOCK
) {
578 child
->dumpVlog(f
, indent
+ " ");
581 fprintf(f
, "%s", first
? indent
.c_str() : ", ");
582 if (child
->type
== AST_DEFAULT
)
583 fprintf(f
, "default");
585 child
->dumpVlog(f
, "");
592 fprintf(f
, "%sassign ", indent
.c_str());
593 children
[0]->dumpVlog(f
, "");
595 children
[1]->dumpVlog(f
, "");
601 fprintf(f
, "%s", indent
.c_str());
602 children
[0]->dumpVlog(f
, "");
603 fprintf(f
, " %s ", type
== AST_ASSIGN_EQ
? "=" : "<=");
604 children
[1]->dumpVlog(f
, "");
610 for (int i
= GetSize(children
)-1; i
>= 0; i
--) {
611 auto child
= children
[i
];
614 child
->dumpVlog(f
, "");
622 children
[0]->dumpVlog(f
, "");
624 children
[1]->dumpVlog(f
, "");
628 if (0) { case AST_BIT_NOT
: txt
= "~"; }
629 if (0) { case AST_REDUCE_AND
: txt
= "&"; }
630 if (0) { case AST_REDUCE_OR
: txt
= "|"; }
631 if (0) { case AST_REDUCE_XOR
: txt
= "^"; }
632 if (0) { case AST_REDUCE_XNOR
: txt
= "~^"; }
633 if (0) { case AST_REDUCE_BOOL
: txt
= "|"; }
634 if (0) { case AST_POS
: txt
= "+"; }
635 if (0) { case AST_NEG
: txt
= "-"; }
636 if (0) { case AST_LOGIC_NOT
: txt
= "!"; }
637 if (0) { case AST_SELFSZ
: txt
= "@selfsz@"; }
638 fprintf(f
, "%s(", txt
.c_str());
639 children
[0]->dumpVlog(f
, "");
643 if (0) { case AST_BIT_AND
: txt
= "&"; }
644 if (0) { case AST_BIT_OR
: txt
= "|"; }
645 if (0) { case AST_BIT_XOR
: txt
= "^"; }
646 if (0) { case AST_BIT_XNOR
: txt
= "~^"; }
647 if (0) { case AST_SHIFT_LEFT
: txt
= "<<"; }
648 if (0) { case AST_SHIFT_RIGHT
: txt
= ">>"; }
649 if (0) { case AST_SHIFT_SLEFT
: txt
= "<<<"; }
650 if (0) { case AST_SHIFT_SRIGHT
: txt
= ">>>"; }
651 if (0) { case AST_SHIFTX
: txt
= "@shiftx@"; }
652 if (0) { case AST_SHIFT
: txt
= "@shift@"; }
653 if (0) { case AST_LT
: txt
= "<"; }
654 if (0) { case AST_LE
: txt
= "<="; }
655 if (0) { case AST_EQ
: txt
= "=="; }
656 if (0) { case AST_NE
: txt
= "!="; }
657 if (0) { case AST_EQX
: txt
= "==="; }
658 if (0) { case AST_NEX
: txt
= "!=="; }
659 if (0) { case AST_GE
: txt
= ">="; }
660 if (0) { case AST_GT
: txt
= ">"; }
661 if (0) { case AST_ADD
: txt
= "+"; }
662 if (0) { case AST_SUB
: txt
= "-"; }
663 if (0) { case AST_MUL
: txt
= "*"; }
664 if (0) { case AST_DIV
: txt
= "/"; }
665 if (0) { case AST_MOD
: txt
= "%"; }
666 if (0) { case AST_POW
: txt
= "**"; }
667 if (0) { case AST_LOGIC_AND
: txt
= "&&"; }
668 if (0) { case AST_LOGIC_OR
: txt
= "||"; }
670 children
[0]->dumpVlog(f
, "");
671 fprintf(f
, ")%s(", txt
.c_str());
672 children
[1]->dumpVlog(f
, "");
678 children
[0]->dumpVlog(f
, "");
680 children
[1]->dumpVlog(f
, "");
682 children
[2]->dumpVlog(f
, "");
687 std::string type_name
= type2str(type
);
688 fprintf(f
, "%s" "/** %s **/%s", indent
.c_str(), type_name
.c_str(), indent
.empty() ? "" : "\n");
689 // dumpAst(f, indent, NULL);
695 // check if two AST nodes are identical
696 bool AstNode::operator==(const AstNode
&other
) const
698 if (type
!= other
.type
)
700 if (children
.size() != other
.children
.size())
702 if (str
!= other
.str
)
704 if (bits
!= other
.bits
)
706 if (is_input
!= other
.is_input
)
708 if (is_output
!= other
.is_output
)
710 if (is_logic
!= other
.is_logic
)
712 if (is_reg
!= other
.is_reg
)
714 if (is_signed
!= other
.is_signed
)
716 if (is_string
!= other
.is_string
)
718 if (range_valid
!= other
.range_valid
)
720 if (range_swapped
!= other
.range_swapped
)
722 if (port_id
!= other
.port_id
)
724 if (range_left
!= other
.range_left
)
726 if (range_right
!= other
.range_right
)
728 if (integer
!= other
.integer
)
730 for (size_t i
= 0; i
< children
.size(); i
++)
731 if (*children
[i
] != *other
.children
[i
])
736 // check if two AST nodes are not identical
737 bool AstNode::operator!=(const AstNode
&other
) const
739 return !(*this == other
);
742 // check if this AST contains the given node
743 bool AstNode::contains(const AstNode
*other
) const
747 for (auto child
: children
)
748 if (child
->contains(other
))
753 // create an AST node for a constant (using a 32 bit int as value)
754 AstNode
*AstNode::mkconst_int(uint32_t v
, bool is_signed
, int width
)
756 AstNode
*node
= new AstNode(AST_CONSTANT
);
758 node
->is_signed
= is_signed
;
759 for (int i
= 0; i
< width
; i
++) {
760 node
->bits
.push_back((v
& 1) ? State::S1
: State::S0
);
763 node
->range_valid
= true;
764 node
->range_left
= width
-1;
765 node
->range_right
= 0;
769 // create an AST node for a constant (using a bit vector as value)
770 AstNode
*AstNode::mkconst_bits(const std::vector
<RTLIL::State
> &v
, bool is_signed
, bool is_unsized
)
772 AstNode
*node
= new AstNode(AST_CONSTANT
);
773 node
->is_signed
= is_signed
;
775 for (size_t i
= 0; i
< 32; i
++) {
776 if (i
< node
->bits
.size())
777 node
->integer
|= (node
->bits
[i
] == State::S1
) << i
;
778 else if (is_signed
&& !node
->bits
.empty())
779 node
->integer
|= (node
->bits
.back() == State::S1
) << i
;
781 node
->range_valid
= true;
782 node
->range_left
= node
->bits
.size()-1;
783 node
->range_right
= 0;
784 node
->is_unsized
= is_unsized
;
788 AstNode
*AstNode::mkconst_bits(const std::vector
<RTLIL::State
> &v
, bool is_signed
)
790 return mkconst_bits(v
, is_signed
, false);
793 // create an AST node for a constant (using a string in bit vector form as value)
794 AstNode
*AstNode::mkconst_str(const std::vector
<RTLIL::State
> &v
)
796 AstNode
*node
= mkconst_str(RTLIL::Const(v
).decode_string());
797 while (GetSize(node
->bits
) < GetSize(v
))
798 node
->bits
.push_back(RTLIL::State::S0
);
799 log_assert(node
->bits
== v
);
803 // create an AST node for a constant (using a string as value)
804 AstNode
*AstNode::mkconst_str(const std::string
&str
)
806 std::vector
<RTLIL::State
> data
;
807 data
.reserve(str
.size() * 8);
808 for (size_t i
= 0; i
< str
.size(); i
++) {
809 unsigned char ch
= str
[str
.size() - i
- 1];
810 for (int j
= 0; j
< 8; j
++) {
811 data
.push_back((ch
& 1) ? State::S1
: State::S0
);
815 AstNode
*node
= AstNode::mkconst_bits(data
, false);
816 node
->is_string
= true;
821 bool AstNode::bits_only_01() const
823 for (auto bit
: bits
)
824 if (bit
!= State::S0
&& bit
!= State::S1
)
829 RTLIL::Const
AstNode::bitsAsUnsizedConst(int width
)
831 RTLIL::State extbit
= bits
.back();
832 while (width
> int(bits
.size()))
833 bits
.push_back(extbit
);
834 return RTLIL::Const(bits
);
837 RTLIL::Const
AstNode::bitsAsConst(int width
, bool is_signed
)
839 std::vector
<RTLIL::State
> bits
= this->bits
;
840 if (width
>= 0 && width
< int(bits
.size()))
842 if (width
>= 0 && width
> int(bits
.size())) {
843 RTLIL::State extbit
= RTLIL::State::S0
;
844 if (is_signed
&& !bits
.empty())
845 extbit
= bits
.back();
846 while (width
> int(bits
.size()))
847 bits
.push_back(extbit
);
849 return RTLIL::Const(bits
);
852 RTLIL::Const
AstNode::bitsAsConst(int width
)
854 return bitsAsConst(width
, is_signed
);
857 RTLIL::Const
AstNode::asAttrConst()
859 log_assert(type
== AST_CONSTANT
);
865 val
.flags
|= RTLIL::CONST_FLAG_STRING
;
866 log_assert(val
.decode_string() == str
);
872 RTLIL::Const
AstNode::asParaConst()
874 RTLIL::Const val
= asAttrConst();
876 val
.flags
|= RTLIL::CONST_FLAG_SIGNED
;
880 bool AstNode::asBool() const
882 log_assert(type
== AST_CONSTANT
);
883 for (auto &bit
: bits
)
884 if (bit
== RTLIL::State::S1
)
889 int AstNode::isConst() const
891 if (type
== AST_CONSTANT
)
893 if (type
== AST_REALVALUE
)
898 uint64_t AstNode::asInt(bool is_signed
)
900 if (type
== AST_CONSTANT
)
902 RTLIL::Const v
= bitsAsConst(64, is_signed
);
905 for (int i
= 0; i
< 64; i
++)
906 if (v
.bits
.at(i
) == RTLIL::State::S1
)
907 ret
|= uint64_t(1) << i
;
912 if (type
== AST_REALVALUE
)
913 return uint64_t(realvalue
);
918 double AstNode::asReal(bool is_signed
)
920 if (type
== AST_CONSTANT
)
922 RTLIL::Const
val(bits
);
924 bool is_negative
= is_signed
&& !val
.bits
.empty() && val
.bits
.back() == RTLIL::State::S1
;
926 val
= const_neg(val
, val
, false, false, val
.bits
.size());
929 for (size_t i
= 0; i
< val
.bits
.size(); i
++)
930 // IEEE Std 1800-2012 Par 6.12.2: Individual bits that are x or z in
931 // the net or the variable shall be treated as zero upon conversion.
932 if (val
.bits
.at(i
) == RTLIL::State::S1
)
940 if (type
== AST_REALVALUE
)
946 RTLIL::Const
AstNode::realAsConst(int width
)
948 double v
= round(realvalue
);
953 if (!std::isfinite(v
)) {
955 result
.bits
= std::vector
<RTLIL::State
>(width
, RTLIL::State::Sx
);
957 bool is_negative
= v
< 0;
960 for (int i
= 0; i
< width
; i
++, v
/= 2)
961 result
.bits
.push_back((fmod(floor(v
), 2) != 0) ? RTLIL::State::S1
: RTLIL::State::S0
);
963 result
= const_neg(result
, result
, false, false, result
.bits
.size());
968 std::string
AstNode::loc_string() const
970 return stringf("%s:%d.%d-%d.%d", filename
.c_str(), location
.first_line
, location
.first_column
, location
.last_line
, location
.last_column
);
973 void AST::set_src_attr(RTLIL::AttrObject
*obj
, const AstNode
*ast
)
975 obj
->attributes
[ID::src
] = ast
->loc_string();
978 static bool param_has_no_default(const AstNode
*param
) {
979 const auto &children
= param
->children
;
980 log_assert(param
->type
== AST_PARAMETER
);
981 log_assert(children
.size() <= 2);
982 return children
.empty() ||
983 (children
.size() == 1 && children
[0]->type
== AST_RANGE
);
986 // create and add a new AstModule from an AST_MODULE AST node
987 static void process_module(RTLIL::Design
*design
, AstNode
*ast
, bool defer
, AstNode
*original_ast
= NULL
, bool quiet
= false)
989 log_assert(current_scope
.empty());
990 log_assert(ast
->type
== AST_MODULE
|| ast
->type
== AST_INTERFACE
);
993 log("Storing AST representation for module `%s'.\n", ast
->str
.c_str());
995 log("Generating RTLIL representation for module `%s'.\n", ast
->str
.c_str());
998 AstModule
*module
= new AstModule
;
999 current_module
= module
;
1002 module
->name
= ast
->str
;
1003 set_src_attr(module
, ast
);
1004 module
->set_bool_attribute(ID::cells_not_processed
);
1006 current_ast_mod
= ast
;
1007 AstNode
*ast_before_simplify
;
1008 if (original_ast
!= NULL
)
1009 ast_before_simplify
= original_ast
;
1011 ast_before_simplify
= ast
->clone();
1013 if (flag_dump_ast1
) {
1014 log("Dumping AST before simplification:\n");
1015 ast
->dumpAst(NULL
, " ");
1016 log("--- END OF AST DUMP ---\n");
1018 if (flag_dump_vlog1
) {
1019 log("Dumping Verilog AST before simplification:\n");
1020 ast
->dumpVlog(NULL
, " ");
1021 log("--- END OF AST DUMP ---\n");
1026 for (const AstNode
*node
: ast
->children
)
1027 if (node
->type
== AST_PARAMETER
&& param_has_no_default(node
))
1028 log_file_error(node
->filename
, node
->location
.first_line
, "Parameter `%s' has no default value and has not been overridden!\n", node
->str
.c_str());
1030 bool blackbox_module
= flag_lib
;
1032 if (!blackbox_module
&& !flag_noblackbox
) {
1033 blackbox_module
= true;
1034 for (auto child
: ast
->children
) {
1035 if (child
->type
== AST_WIRE
&& (child
->is_input
|| child
->is_output
))
1037 if (child
->type
== AST_PARAMETER
|| child
->type
== AST_LOCALPARAM
)
1039 if (child
->type
== AST_CELL
&& child
->children
.size() > 0 && child
->children
[0]->type
== AST_CELLTYPE
&&
1040 (child
->children
[0]->str
== "$specify2" || child
->children
[0]->str
== "$specify3" || child
->children
[0]->str
== "$specrule"))
1042 blackbox_module
= false;
1047 // TODO(zachjs): make design available to simplify() in the future
1048 while (ast
->simplify(!flag_noopt
, false, false, 0, -1, false, false)) { }
1050 if (flag_dump_ast2
) {
1051 log("Dumping AST after simplification:\n");
1052 ast
->dumpAst(NULL
, " ");
1053 log("--- END OF AST DUMP ---\n");
1056 if (flag_dump_vlog2
) {
1057 log("Dumping Verilog AST after simplification:\n");
1058 ast
->dumpVlog(NULL
, " ");
1059 log("--- END OF AST DUMP ---\n");
1062 if (flag_nowb
&& ast
->attributes
.count(ID::whitebox
)) {
1063 delete ast
->attributes
.at(ID::whitebox
);
1064 ast
->attributes
.erase(ID::whitebox
);
1067 if (ast
->attributes
.count(ID::lib_whitebox
)) {
1068 if (!flag_lib
|| flag_nowb
) {
1069 delete ast
->attributes
.at(ID::lib_whitebox
);
1070 ast
->attributes
.erase(ID::lib_whitebox
);
1072 if (ast
->attributes
.count(ID::whitebox
)) {
1073 delete ast
->attributes
.at(ID::whitebox
);
1074 ast
->attributes
.erase(ID::whitebox
);
1076 AstNode
*n
= ast
->attributes
.at(ID::lib_whitebox
);
1077 ast
->attributes
[ID::whitebox
] = n
;
1078 ast
->attributes
.erase(ID::lib_whitebox
);
1082 if (!blackbox_module
&& ast
->attributes
.count(ID::blackbox
)) {
1083 AstNode
*n
= ast
->attributes
.at(ID::blackbox
);
1084 if (n
->type
!= AST_CONSTANT
)
1085 log_file_error(ast
->filename
, ast
->location
.first_line
, "Got blackbox attribute with non-constant value!\n");
1086 blackbox_module
= n
->asBool();
1089 if (blackbox_module
&& ast
->attributes
.count(ID::whitebox
)) {
1090 AstNode
*n
= ast
->attributes
.at(ID::whitebox
);
1091 if (n
->type
!= AST_CONSTANT
)
1092 log_file_error(ast
->filename
, ast
->location
.first_line
, "Got whitebox attribute with non-constant value!\n");
1093 blackbox_module
= !n
->asBool();
1096 if (ast
->attributes
.count(ID::noblackbox
)) {
1097 if (blackbox_module
) {
1098 AstNode
*n
= ast
->attributes
.at(ID::noblackbox
);
1099 if (n
->type
!= AST_CONSTANT
)
1100 log_file_error(ast
->filename
, ast
->location
.first_line
, "Got noblackbox attribute with non-constant value!\n");
1101 blackbox_module
= !n
->asBool();
1103 delete ast
->attributes
.at(ID::noblackbox
);
1104 ast
->attributes
.erase(ID::noblackbox
);
1107 if (blackbox_module
)
1109 if (ast
->attributes
.count(ID::whitebox
)) {
1110 delete ast
->attributes
.at(ID::whitebox
);
1111 ast
->attributes
.erase(ID::whitebox
);
1114 if (ast
->attributes
.count(ID::lib_whitebox
)) {
1115 delete ast
->attributes
.at(ID::lib_whitebox
);
1116 ast
->attributes
.erase(ID::lib_whitebox
);
1119 std::vector
<AstNode
*> new_children
;
1120 for (auto child
: ast
->children
) {
1121 if (child
->type
== AST_WIRE
&& (child
->is_input
|| child
->is_output
)) {
1122 new_children
.push_back(child
);
1123 } else if (child
->type
== AST_PARAMETER
) {
1124 new_children
.push_back(child
);
1125 } else if (child
->type
== AST_CELL
&& child
->children
.size() > 0 && child
->children
[0]->type
== AST_CELLTYPE
&&
1126 (child
->children
[0]->str
== "$specify2" || child
->children
[0]->str
== "$specify3" || child
->children
[0]->str
== "$specrule")) {
1127 new_children
.push_back(child
);
1133 ast
->children
.swap(new_children
);
1135 if (ast
->attributes
.count(ID::blackbox
) == 0) {
1136 ast
->attributes
[ID::blackbox
] = AstNode::mkconst_int(1, false);
1140 ignoreThisSignalsInInitial
= RTLIL::SigSpec();
1142 for (auto &attr
: ast
->attributes
) {
1143 if (attr
.second
->type
!= AST_CONSTANT
)
1144 log_file_error(ast
->filename
, ast
->location
.first_line
, "Attribute `%s' with non-constant value!\n", attr
.first
.c_str());
1145 module
->attributes
[attr
.first
] = attr
.second
->asAttrConst();
1147 for (size_t i
= 0; i
< ast
->children
.size(); i
++) {
1148 AstNode
*node
= ast
->children
[i
];
1149 if (node
->type
== AST_WIRE
|| node
->type
== AST_MEMORY
)
1152 for (size_t i
= 0; i
< ast
->children
.size(); i
++) {
1153 AstNode
*node
= ast
->children
[i
];
1154 if (node
->type
!= AST_WIRE
&& node
->type
!= AST_MEMORY
&& node
->type
!= AST_INITIAL
)
1158 ignoreThisSignalsInInitial
.sort_and_unify();
1160 for (size_t i
= 0; i
< ast
->children
.size(); i
++) {
1161 AstNode
*node
= ast
->children
[i
];
1162 if (node
->type
== AST_INITIAL
)
1166 ignoreThisSignalsInInitial
= RTLIL::SigSpec();
1167 current_scope
.clear();
1170 for (auto &attr
: ast
->attributes
) {
1171 if (attr
.second
->type
!= AST_CONSTANT
)
1173 module
->attributes
[attr
.first
] = attr
.second
->asAttrConst();
1177 if (ast
->type
== AST_INTERFACE
)
1178 module
->set_bool_attribute(ID::is_interface
);
1179 module
->ast
= ast_before_simplify
;
1180 module
->nolatches
= flag_nolatches
;
1181 module
->nomeminit
= flag_nomeminit
;
1182 module
->nomem2reg
= flag_nomem2reg
;
1183 module
->mem2reg
= flag_mem2reg
;
1184 module
->noblackbox
= flag_noblackbox
;
1185 module
->lib
= flag_lib
;
1186 module
->nowb
= flag_nowb
;
1187 module
->noopt
= flag_noopt
;
1188 module
->icells
= flag_icells
;
1189 module
->pwires
= flag_pwires
;
1190 module
->autowire
= flag_autowire
;
1191 module
->fixup_ports();
1193 if (flag_dump_rtlil
) {
1194 log("Dumping generated RTLIL:\n");
1196 log("--- END OF RTLIL DUMP ---\n");
1199 design
->add(current_module
);
1202 // renames identifiers in tasks and functions within a package
1203 static void rename_in_package_stmts(AstNode
*pkg
)
1205 std::unordered_set
<std::string
> idents
;
1206 for (AstNode
*item
: pkg
->children
)
1207 idents
.insert(item
->str
);
1208 std::function
<void(AstNode
*)> rename
=
1209 [&rename
, &idents
, pkg
](AstNode
*node
) {
1210 for (AstNode
*child
: node
->children
) {
1211 if (idents
.count(child
->str
))
1212 child
->str
= pkg
->str
+ "::" + child
->str
.substr(1);
1216 for (AstNode
*item
: pkg
->children
)
1217 if (item
->type
== AST_FUNCTION
|| item
->type
== AST_TASK
)
1221 // create AstModule instances for all modules in the AST tree and add them to 'design'
1222 void AST::process(RTLIL::Design
*design
, AstNode
*ast
, bool dump_ast1
, bool dump_ast2
, bool no_dump_ptr
, bool dump_vlog1
, bool dump_vlog2
, bool dump_rtlil
,
1223 bool nolatches
, bool nomeminit
, bool nomem2reg
, bool mem2reg
, bool noblackbox
, bool lib
, bool nowb
, bool noopt
, bool icells
, bool pwires
, bool nooverwrite
, bool overwrite
, bool defer
, bool autowire
)
1226 current_ast_mod
= nullptr;
1227 flag_dump_ast1
= dump_ast1
;
1228 flag_dump_ast2
= dump_ast2
;
1229 flag_no_dump_ptr
= no_dump_ptr
;
1230 flag_dump_vlog1
= dump_vlog1
;
1231 flag_dump_vlog2
= dump_vlog2
;
1232 flag_dump_rtlil
= dump_rtlil
;
1233 flag_nolatches
= nolatches
;
1234 flag_nomeminit
= nomeminit
;
1235 flag_nomem2reg
= nomem2reg
;
1236 flag_mem2reg
= mem2reg
;
1237 flag_noblackbox
= noblackbox
;
1241 flag_icells
= icells
;
1242 flag_pwires
= pwires
;
1243 flag_autowire
= autowire
;
1245 log_assert(current_ast
->type
== AST_DESIGN
);
1246 for (AstNode
*child
: current_ast
->children
)
1248 if (child
->type
== AST_MODULE
|| child
->type
== AST_INTERFACE
)
1250 for (auto n
: design
->verilog_globals
)
1251 child
->children
.push_back(n
->clone());
1253 // append nodes from previous packages using package-qualified names
1254 for (auto &n
: design
->verilog_packages
) {
1255 for (auto &o
: n
->children
) {
1256 AstNode
*cloned_node
= o
->clone();
1257 // log("cloned node %s\n", type2str(cloned_node->type).c_str());
1258 if (cloned_node
->type
== AST_ENUM
) {
1259 for (auto &e
: cloned_node
->children
) {
1260 log_assert(e
->type
== AST_ENUM_ITEM
);
1261 e
->str
= n
->str
+ std::string("::") + e
->str
.substr(1);
1264 cloned_node
->str
= n
->str
+ std::string("::") + cloned_node
->str
.substr(1);
1266 child
->children
.push_back(cloned_node
);
1270 if (flag_icells
&& child
->str
.compare(0, 2, "\\$") == 0)
1271 child
->str
= child
->str
.substr(1);
1273 bool defer_local
= defer
;
1275 for (const AstNode
*node
: child
->children
)
1276 if (node
->type
== AST_PARAMETER
&& param_has_no_default(node
))
1278 log("Deferring `%s' because it contains parameter(s) without defaults.\n", child
->str
.c_str());
1285 child
->str
= "$abstract" + child
->str
;
1287 if (design
->has(child
->str
)) {
1288 RTLIL::Module
*existing_mod
= design
->module(child
->str
);
1289 if (!nooverwrite
&& !overwrite
&& !existing_mod
->get_blackbox_attribute()) {
1290 log_file_error(child
->filename
, child
->location
.first_line
, "Re-definition of module `%s'!\n", child
->str
.c_str());
1291 } else if (nooverwrite
) {
1292 log("Ignoring re-definition of module `%s' at %s.\n",
1293 child
->str
.c_str(), child
->loc_string().c_str());
1296 log("Replacing existing%s module `%s' at %s.\n",
1297 existing_mod
->get_bool_attribute(ID::blackbox
) ? " blackbox" : "",
1298 child
->str
.c_str(), child
->loc_string().c_str());
1299 design
->remove(existing_mod
);
1303 process_module(design
, child
, defer_local
);
1304 current_ast_mod
= nullptr;
1306 else if (child
->type
== AST_PACKAGE
) {
1307 // process enum/other declarations
1308 child
->simplify(true, false, false, 1, -1, false, false);
1309 rename_in_package_stmts(child
);
1310 design
->verilog_packages
.push_back(child
->clone());
1311 current_scope
.clear();
1313 else if (child
->type
== AST_BIND
) {
1314 // top-level bind construct
1315 for (RTLIL::Binding
*binding
: child
->genBindings())
1316 design
->add(binding
);
1319 // must be global definition
1320 if (child
->type
== AST_PARAMETER
)
1321 child
->type
= AST_LOCALPARAM
; // cannot be overridden
1322 design
->verilog_globals
.push_back(child
->clone());
1323 current_scope
.clear();
1328 // AstModule destructor
1329 AstModule::~AstModule()
1336 // An interface port with modport is specified like this:
1337 // <interface_name>.<modport_name>
1338 // This function splits the interface_name from the modport_name, and fails if it is not a valid combination
1339 std::pair
<std::string
,std::string
> AST::split_modport_from_type(std::string name_type
)
1341 std::string interface_type
= "";
1342 std::string interface_modport
= "";
1343 size_t ndots
= std::count(name_type
.begin(), name_type
.end(), '.');
1344 // Separate the interface instance name from any modports:
1345 if (ndots
== 0) { // Does not have modport
1346 interface_type
= name_type
;
1349 std::stringstream
name_type_stream(name_type
);
1350 std::string segment
;
1351 std::vector
<std::string
> seglist
;
1352 while(std::getline(name_type_stream
, segment
, '.')) {
1353 seglist
.push_back(segment
);
1355 if (ndots
== 1) { // Has modport
1356 interface_type
= seglist
[0];
1357 interface_modport
= seglist
[1];
1359 else { // Erroneous port type
1360 log_error("More than two '.' in signal port type (%s)\n", name_type
.c_str());
1363 return std::pair
<std::string
,std::string
>(interface_type
, interface_modport
);
1367 AstNode
* AST::find_modport(AstNode
*intf
, std::string name
)
1369 for (auto &ch
: intf
->children
)
1370 if (ch
->type
== AST_MODPORT
)
1371 if (ch
->str
== name
) // Modport found
1376 // Iterate over all wires in an interface and add them as wires in the AST module:
1377 void AST::explode_interface_port(AstNode
*module_ast
, RTLIL::Module
* intfmodule
, std::string intfname
, AstNode
*modport
)
1379 for (auto w
: intfmodule
->wires()){
1380 AstNode
*wire
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, AstNode::mkconst_int(w
->width
-1, true), AstNode::mkconst_int(0, true)));
1381 std::string origname
= log_id(w
->name
);
1382 std::string newname
= intfname
+ "." + origname
;
1383 wire
->str
= newname
;
1384 if (modport
!= NULL
) {
1385 bool found_in_modport
= false;
1386 // Search for the current wire in the wire list for the current modport
1387 for (auto &ch
: modport
->children
) {
1388 if (ch
->type
== AST_MODPORTMEMBER
) {
1389 std::string compare_name
= "\\" + origname
;
1390 if (ch
->str
== compare_name
) { // Found signal. The modport decides whether it is input or output
1391 found_in_modport
= true;
1392 wire
->is_input
= ch
->is_input
;
1393 wire
->is_output
= ch
->is_output
;
1398 if (found_in_modport
) {
1399 module_ast
->children
.push_back(wire
);
1401 else { // If not found in modport, do not create port
1405 else { // If no modport, set inout
1406 wire
->is_input
= true;
1407 wire
->is_output
= true;
1408 module_ast
->children
.push_back(wire
);
1413 // When an interface instance is found in a module, the whole RTLIL for the module will be rederived again
1414 // from AST. The interface members are copied into the AST module with the prefix of the interface.
1415 void AstModule::reprocess_module(RTLIL::Design
*design
, const dict
<RTLIL::IdString
, RTLIL::Module
*> &local_interfaces
)
1419 bool is_top
= false;
1420 AstNode
*new_ast
= ast
->clone();
1421 for (auto &intf
: local_interfaces
) {
1422 std::string intfname
= intf
.first
.str();
1423 RTLIL::Module
*intfmodule
= intf
.second
;
1424 for (auto w
: intfmodule
->wires()){
1425 AstNode
*wire
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, AstNode::mkconst_int(w
->width
-1, true), AstNode::mkconst_int(0, true)));
1426 std::string newname
= log_id(w
->name
);
1427 newname
= intfname
+ "." + newname
;
1428 wire
->str
= newname
;
1429 new_ast
->children
.push_back(wire
);
1433 AstNode
*ast_before_replacing_interface_ports
= new_ast
->clone();
1435 // Explode all interface ports. Note this will only have an effect on 'top
1436 // level' modules. Other sub-modules will have their interface ports
1437 // exploded via the derive(..) function
1438 for (size_t i
=0; i
<new_ast
->children
.size(); i
++)
1440 AstNode
*ch2
= new_ast
->children
[i
];
1441 if (ch2
->type
== AST_INTERFACEPORT
) { // Is an interface port
1442 std::string name_port
= ch2
->str
; // Name of the interface port
1443 if (ch2
->children
.size() > 0) {
1444 for(size_t j
=0; j
<ch2
->children
.size();j
++) {
1445 AstNode
*ch
= ch2
->children
[j
];
1446 if(ch
->type
== AST_INTERFACEPORTTYPE
) { // Found the AST node containing the type of the interface
1447 std::pair
<std::string
,std::string
> res
= split_modport_from_type(ch
->str
);
1448 std::string interface_type
= res
.first
;
1449 std::string interface_modport
= res
.second
; // Is "", if no modport
1450 if (design
->module(interface_type
) != nullptr) {
1451 // Add a cell to the module corresponding to the interface port such that
1452 // it can further propagated down if needed:
1453 AstNode
*celltype_for_intf
= new AstNode(AST_CELLTYPE
);
1454 celltype_for_intf
->str
= interface_type
;
1455 AstNode
*cell_for_intf
= new AstNode(AST_CELL
, celltype_for_intf
);
1456 cell_for_intf
->str
= name_port
+ "_inst_from_top_dummy";
1457 new_ast
->children
.push_back(cell_for_intf
);
1459 // Get all members of this non-overridden dummy interface instance:
1460 RTLIL::Module
*intfmodule
= design
->module(interface_type
); // All interfaces should at this point in time (assuming
1461 // reprocess_module is called from the hierarchy pass) be
1462 // present in design->modules_
1463 AstModule
*ast_module_of_interface
= (AstModule
*)intfmodule
;
1464 std::string interface_modport_compare_str
= "\\" + interface_modport
;
1465 AstNode
*modport
= find_modport(ast_module_of_interface
->ast
, interface_modport_compare_str
); // modport == NULL if no modport
1466 // Iterate over all wires in the interface and add them to the module:
1467 explode_interface_port(new_ast
, intfmodule
, name_port
, modport
);
1476 // The old module will be deleted. Rename and mark for deletion:
1477 std::string original_name
= this->name
.str();
1478 std::string changed_name
= original_name
+ "_before_replacing_local_interfaces";
1479 design
->rename(this, changed_name
);
1480 this->set_bool_attribute(ID::to_delete
);
1482 // Check if the module was the top module. If it was, we need to remove the top attribute and put it on the
1484 if (this->get_bool_attribute(ID::initial_top
)) {
1485 this->attributes
.erase(ID::initial_top
);
1489 // Generate RTLIL from AST for the new module and add to the design:
1490 process_module(design
, new_ast
, false, ast_before_replacing_interface_ports
);
1492 RTLIL::Module
* mod
= design
->module(original_name
);
1494 mod
->set_bool_attribute(ID::top
);
1496 // Set the attribute "interfaces_replaced_in_module" so that it does not happen again.
1497 mod
->set_bool_attribute(ID::interfaces_replaced_in_module
);
1500 // create a new parametric module (when needed) and return the name of the generated module - WITH support for interfaces
1501 // This method is used to explode the interface when the interface is a port of the module (not instantiated inside)
1502 RTLIL::IdString
AstModule::derive(RTLIL::Design
*design
, const dict
<RTLIL::IdString
, RTLIL::Const
> ¶meters
, const dict
<RTLIL::IdString
, RTLIL::Module
*> &interfaces
, const dict
<RTLIL::IdString
, RTLIL::IdString
> &modports
, bool /*mayfail*/)
1504 AstNode
*new_ast
= NULL
;
1505 std::string modname
= derive_common(design
, parameters
, &new_ast
);
1507 // Since interfaces themselves may be instantiated with different parameters,
1508 // "modname" must also take those into account, so that unique modules
1509 // are derived for any variant of interface connections:
1510 std::string interf_info
= "";
1512 bool has_interfaces
= false;
1513 for(auto &intf
: interfaces
) {
1514 interf_info
+= log_id(intf
.second
->name
);
1515 has_interfaces
= true;
1518 std::string new_modname
= modname
;
1520 new_modname
+= "$interfaces$" + interf_info
;
1523 if (!design
->has(new_modname
)) {
1525 auto mod
= dynamic_cast<AstModule
*>(design
->module(modname
));
1526 new_ast
= mod
->ast
->clone();
1528 modname
= new_modname
;
1529 new_ast
->str
= modname
;
1531 // Iterate over all interfaces which are ports in this module:
1532 for(auto &intf
: interfaces
) {
1533 RTLIL::Module
* intfmodule
= intf
.second
;
1534 std::string intfname
= intf
.first
.str();
1535 // Check if a modport applies for the interface port:
1536 AstNode
*modport
= NULL
;
1537 if (modports
.count(intfname
) > 0) {
1538 std::string interface_modport
= modports
.at(intfname
).str();
1539 AstModule
*ast_module_of_interface
= (AstModule
*)intfmodule
;
1540 AstNode
*ast_node_of_interface
= ast_module_of_interface
->ast
;
1541 modport
= find_modport(ast_node_of_interface
, interface_modport
);
1543 // Iterate over all wires in the interface and add them to the module:
1544 explode_interface_port(new_ast
, intfmodule
, intfname
, modport
);
1547 process_module(design
, new_ast
, false);
1548 design
->module(modname
)->check();
1550 RTLIL::Module
* mod
= design
->module(modname
);
1552 // Now that the interfaces have been exploded, we can delete the dummy port related to every interface.
1553 for(auto &intf
: interfaces
) {
1554 if(mod
->wire(intf
.first
) != nullptr) {
1555 // Normally, removing wires would be batched together as it's an
1556 // expensive operation, however, in this case doing so would mean
1557 // that a cell with the same name cannot be created (below)...
1558 // Since we won't expect many interfaces to exist in a module,
1559 // we can let this slide...
1560 pool
<RTLIL::Wire
*> to_remove
;
1561 to_remove
.insert(mod
->wire(intf
.first
));
1562 mod
->remove(to_remove
);
1564 // We copy the cell of the interface to the sub-module such that it
1565 // can further be found if it is propagated down to sub-sub-modules etc.
1566 RTLIL::Cell
*new_subcell
= mod
->addCell(intf
.first
, intf
.second
->name
);
1567 new_subcell
->set_bool_attribute(ID::is_interface
);
1570 log_error("No port with matching name found (%s) in %s. Stopping\n", log_id(intf
.first
), modname
.c_str());
1574 // If any interfaces were replaced, set the attribute 'interfaces_replaced_in_module':
1575 if (interfaces
.size() > 0) {
1576 mod
->set_bool_attribute(ID::interfaces_replaced_in_module
);
1580 modname
= new_modname
;
1581 log("Found cached RTLIL representation for module `%s'.\n", modname
.c_str());
1588 // create a new parametric module (when needed) and return the name of the generated module - without support for interfaces
1589 RTLIL::IdString
AstModule::derive(RTLIL::Design
*design
, const dict
<RTLIL::IdString
, RTLIL::Const
> ¶meters
, bool /*mayfail*/)
1591 bool quiet
= lib
|| attributes
.count(ID::blackbox
) || attributes
.count(ID::whitebox
);
1593 AstNode
*new_ast
= NULL
;
1594 std::string modname
= derive_common(design
, parameters
, &new_ast
, quiet
);
1596 if (!design
->has(modname
)) {
1597 new_ast
->str
= modname
;
1598 process_module(design
, new_ast
, false, NULL
, quiet
);
1599 design
->module(modname
)->check();
1600 } else if (!quiet
) {
1601 log("Found cached RTLIL representation for module `%s'.\n", modname
.c_str());
1608 static std::string
serialize_param_value(const RTLIL::Const
&val
) {
1610 if (val
.flags
& RTLIL::ConstFlags::CONST_FLAG_STRING
)
1612 if (val
.flags
& RTLIL::ConstFlags::CONST_FLAG_SIGNED
)
1614 if (val
.flags
& RTLIL::ConstFlags::CONST_FLAG_REAL
)
1616 res
+= stringf("%d", GetSize(val
));
1617 res
.push_back('\'');
1618 for (int i
= GetSize(val
) - 1; i
>= 0; i
--) {
1619 switch (val
.bits
[i
]) {
1620 case RTLIL::State::S0
: res
.push_back('0'); break;
1621 case RTLIL::State::S1
: res
.push_back('1'); break;
1622 case RTLIL::State::Sx
: res
.push_back('x'); break;
1623 case RTLIL::State::Sz
: res
.push_back('z'); break;
1624 case RTLIL::State::Sa
: res
.push_back('?'); break;
1625 case RTLIL::State::Sm
: res
.push_back('m'); break;
1631 // create a new parametric module (when needed) and return the name of the generated module
1632 std::string
AstModule::derive_common(RTLIL::Design
*design
, const dict
<RTLIL::IdString
, RTLIL::Const
> ¶meters
, AstNode
**new_ast_out
, bool quiet
)
1634 std::string stripped_name
= name
.str();
1636 if (stripped_name
.compare(0, 9, "$abstract") == 0)
1637 stripped_name
= stripped_name
.substr(9);
1639 std::string para_info
;
1641 int para_counter
= 0;
1642 for (const auto child
: ast
->children
) {
1643 if (child
->type
!= AST_PARAMETER
)
1646 auto it
= parameters
.find(child
->str
);
1647 if (it
!= parameters
.end()) {
1649 log("Parameter %s = %s\n", child
->str
.c_str(), log_signal(it
->second
));
1650 para_info
+= stringf("%s=%s", child
->str
.c_str(), serialize_param_value(it
->second
).c_str());
1653 it
= parameters
.find(stringf("$%d", para_counter
));
1654 if (it
!= parameters
.end()) {
1656 log("Parameter %d (%s) = %s\n", para_counter
, child
->str
.c_str(), log_signal(it
->second
));
1657 para_info
+= stringf("%s=%s", child
->str
.c_str(), serialize_param_value(it
->second
).c_str());
1662 std::string modname
;
1663 if (parameters
.size() == 0)
1664 modname
= stripped_name
;
1665 else if (para_info
.size() > 60)
1666 modname
= "$paramod$" + sha1(para_info
) + stripped_name
;
1668 modname
= "$paramod" + stripped_name
+ para_info
;
1670 if (design
->has(modname
))
1674 log_header(design
, "Executing AST frontend in derive mode using pre-parsed AST for module `%s'.\n", stripped_name
.c_str());
1677 pool
<IdString
> rewritten
;
1678 rewritten
.reserve(GetSize(parameters
));
1680 AstNode
*new_ast
= ast
->clone();
1681 if (!new_ast
->attributes
.count(ID::hdlname
))
1682 new_ast
->attributes
[ID::hdlname
] = AstNode::mkconst_str(stripped_name
);
1685 for (auto child
: new_ast
->children
) {
1686 if (child
->type
!= AST_PARAMETER
)
1689 auto it
= parameters
.find(child
->str
);
1690 if (it
!= parameters
.end()) {
1692 log("Parameter %s = %s\n", child
->str
.c_str(), log_signal(it
->second
));
1693 goto rewrite_parameter
;
1695 it
= parameters
.find(stringf("$%d", para_counter
));
1696 if (it
!= parameters
.end()) {
1698 log("Parameter %d (%s) = %s\n", para_counter
, child
->str
.c_str(), log_signal(it
->second
));
1699 goto rewrite_parameter
;
1703 if (param_has_no_default(child
))
1704 child
->children
.insert(child
->children
.begin(), nullptr);
1705 delete child
->children
.at(0);
1706 if ((it
->second
.flags
& RTLIL::CONST_FLAG_REAL
) != 0) {
1707 child
->children
[0] = new AstNode(AST_REALVALUE
);
1708 child
->children
[0]->realvalue
= std::stod(it
->second
.decode_string());
1709 } else if ((it
->second
.flags
& RTLIL::CONST_FLAG_STRING
) != 0)
1710 child
->children
[0] = AstNode::mkconst_str(it
->second
.decode_string());
1712 child
->children
[0] = AstNode::mkconst_bits(it
->second
.bits
, (it
->second
.flags
& RTLIL::CONST_FLAG_SIGNED
) != 0);
1713 rewritten
.insert(it
->first
);
1716 if (GetSize(rewritten
) < GetSize(parameters
))
1717 for (const auto ¶m
: parameters
) {
1718 if (rewritten
.count(param
.first
))
1720 AstNode
*defparam
= new AstNode(AST_DEFPARAM
, new AstNode(AST_IDENTIFIER
));
1721 defparam
->children
[0]->str
= param
.first
.str();
1722 if ((param
.second
.flags
& RTLIL::CONST_FLAG_STRING
) != 0)
1723 defparam
->children
.push_back(AstNode::mkconst_str(param
.second
.decode_string()));
1725 defparam
->children
.push_back(AstNode::mkconst_bits(param
.second
.bits
, (param
.second
.flags
& RTLIL::CONST_FLAG_SIGNED
) != 0));
1726 new_ast
->children
.push_back(defparam
);
1729 (*new_ast_out
) = new_ast
;
1733 RTLIL::Module
*AstModule::clone() const
1735 AstModule
*new_mod
= new AstModule
;
1736 new_mod
->name
= name
;
1739 new_mod
->ast
= ast
->clone();
1740 new_mod
->nolatches
= nolatches
;
1741 new_mod
->nomeminit
= nomeminit
;
1742 new_mod
->nomem2reg
= nomem2reg
;
1743 new_mod
->mem2reg
= mem2reg
;
1744 new_mod
->noblackbox
= noblackbox
;
1746 new_mod
->nowb
= nowb
;
1747 new_mod
->noopt
= noopt
;
1748 new_mod
->icells
= icells
;
1749 new_mod
->pwires
= pwires
;
1750 new_mod
->autowire
= autowire
;
1755 void AstModule::loadconfig() const
1758 flag_dump_ast1
= false;
1759 flag_dump_ast2
= false;
1760 flag_dump_vlog1
= false;
1761 flag_dump_vlog2
= false;
1762 flag_nolatches
= nolatches
;
1763 flag_nomeminit
= nomeminit
;
1764 flag_nomem2reg
= nomem2reg
;
1765 flag_mem2reg
= mem2reg
;
1766 flag_noblackbox
= noblackbox
;
1770 flag_icells
= icells
;
1771 flag_pwires
= pwires
;
1772 flag_autowire
= autowire
;