2 * yosys -- Yosys Open SYnthesis Suite
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 * This is the AST frontend library.
22 * The AST frontend library is not a frontend on it's own but provides a
23 * generic abstract syntax tree (AST) abstraction for HDL code and can be
24 * used by HDL frontends. See "ast.h" for an overview of the API and the
25 * Verilog frontend for an usage example.
29 #include "kernel/yosys.h"
30 #include "libs/sha1/sha1.h"
36 using namespace AST_INTERNAL
;
38 // instanciate global variables (public API)
40 std::string current_filename
;
41 void (*set_line_num
)(int) = NULL
;
42 int (*get_line_num
)() = NULL
;
45 // instanciate global variables (private API)
46 namespace AST_INTERNAL
{
47 bool flag_dump_ast1
, flag_dump_ast2
, flag_dump_vlog
, flag_dump_rtlil
, flag_nolatches
, flag_nomeminit
;
48 bool flag_nomem2reg
, flag_mem2reg
, flag_lib
, flag_noopt
, flag_icells
, flag_autowire
;
49 AstNode
*current_ast
, *current_ast_mod
;
50 std::map
<std::string
, AstNode
*> current_scope
;
51 const dict
<RTLIL::SigBit
, RTLIL::SigBit
> *genRTLIL_subst_ptr
= NULL
;
52 RTLIL::SigSpec ignoreThisSignalsInInitial
;
53 AstNode
*current_always
, *current_top_block
, *current_block
, *current_block_child
;
54 AstModule
*current_module
;
55 bool current_always_clocked
;
58 // convert node types to string
59 std::string
AST::type2str(AstNodeType type
)
63 #define X(_item) case _item: return #_item;
163 // check if attribute exists and has non-zero value
164 bool AstNode::get_bool_attribute(RTLIL::IdString id
)
166 if (attributes
.count(id
) == 0)
169 AstNode
*attr
= attributes
.at(id
);
170 if (attr
->type
!= AST_CONSTANT
)
171 log_error("Attribute `%s' with non-constant value at %s:%d!\n",
172 id
.c_str(), attr
->filename
.c_str(), attr
->linenum
);
174 return attr
->integer
!= 0;
177 // create new node (AstNode constructor)
178 // (the optional child arguments make it easier to create AST trees)
179 AstNode::AstNode(AstNodeType type
, AstNode
*child1
, AstNode
*child2
, AstNode
*child3
)
181 static unsigned int hashidx_count
= 123456789;
182 hashidx_count
= mkhash_xorshift(hashidx_count
);
183 hashidx_
= hashidx_count
;
186 filename
= current_filename
;
187 linenum
= get_line_num();
194 range_swapped
= false;
204 children
.push_back(child1
);
206 children
.push_back(child2
);
208 children
.push_back(child3
);
211 // create a (deep recursive) copy of a node
212 AstNode
*AstNode::clone()
214 AstNode
*that
= new AstNode
;
216 for (auto &it
: that
->children
)
218 for (auto &it
: that
->attributes
)
219 it
.second
= it
.second
->clone();
223 // create a (deep recursive) copy of a node use 'other' as target root node
224 void AstNode::cloneInto(AstNode
*other
)
226 AstNode
*tmp
= clone();
227 other
->delete_children();
229 tmp
->children
.clear();
230 tmp
->attributes
.clear();
234 // delete all children in this node
235 void AstNode::delete_children()
237 for (auto &it
: children
)
241 for (auto &it
: attributes
)
246 // AstNode destructor
252 // create a nice text representation of the node
253 // (traverse tree by recursion, use 'other' pointer for diffing two AST trees)
254 void AstNode::dumpAst(FILE *f
, std::string indent
)
257 for (auto f
: log_files
)
262 std::string type_name
= type2str(type
);
263 fprintf(f
, "%s%s <%s:%d>", indent
.c_str(), type_name
.c_str(), filename
.c_str(), linenum
);
266 fprintf(f
, " [%p -> %p]", this, id2ast
);
268 fprintf(f
, " [%p]", this);
271 fprintf(f
, " str='%s'", str
.c_str());
273 fprintf(f
, " bits='");
274 for (size_t i
= bits
.size(); i
> 0; i
--)
275 fprintf(f
, "%c", bits
[i
-1] == RTLIL::S0
? '0' :
276 bits
[i
-1] == RTLIL::S1
? '1' :
277 bits
[i
-1] == RTLIL::Sx
? 'x' :
278 bits
[i
-1] == RTLIL::Sz
? 'z' : '?');
279 fprintf(f
, "'(%d)", GetSize(bits
));
282 fprintf(f
, " input");
284 fprintf(f
, " output");
288 fprintf(f
, " signed");
290 fprintf(f
, " port=%d", port_id
);
291 if (range_valid
|| range_left
!= -1 || range_right
!= 0)
292 fprintf(f
, " %srange=[%d:%d]%s", range_swapped
? "swapped_" : "", range_left
, range_right
, range_valid
? "" : "!");
294 fprintf(f
, " int=%u", (int)integer
);
296 fprintf(f
, " real=%e", realvalue
);
297 if (!multirange_dimensions
.empty()) {
298 fprintf(f
, " multirange=[");
299 for (int v
: multirange_dimensions
)
300 fprintf(f
, " %d", v
);
305 for (auto &it
: attributes
) {
306 fprintf(f
, "%s ATTR %s:\n", indent
.c_str(), it
.first
.c_str());
307 it
.second
->dumpAst(f
, indent
+ " ");
310 for (size_t i
= 0; i
< children
.size(); i
++)
311 children
[i
]->dumpAst(f
, indent
+ " ");
316 // helper function for AstNode::dumpVlog()
317 static std::string
id2vl(std::string txt
)
319 if (txt
.size() > 1 && txt
[0] == '\\')
321 for (size_t i
= 0; i
< txt
.size(); i
++) {
322 if ('A' <= txt
[i
] && txt
[i
] <= 'Z') continue;
323 if ('a' <= txt
[i
] && txt
[i
] <= 'z') continue;
324 if ('0' <= txt
[i
] && txt
[i
] <= '9') continue;
325 if (txt
[i
] == '_') continue;
326 txt
= "\\" + txt
+ " ";
332 // dump AST node as Verilog pseudo-code
333 void AstNode::dumpVlog(FILE *f
, std::string indent
)
337 std::vector
<AstNode
*> rem_children1
, rem_children2
;
340 for (auto f
: log_files
)
345 for (auto &it
: attributes
) {
346 fprintf(f
, "%s" "(* %s = ", indent
.c_str(), id2vl(it
.first
.str()).c_str());
347 it
.second
->dumpVlog(f
, "");
348 fprintf(f
, " *)%s", indent
.empty() ? "" : "\n");
354 fprintf(f
, "%s" "module %s(", indent
.c_str(), id2vl(str
).c_str());
355 for (auto child
: children
)
356 if (child
->type
== AST_WIRE
&& (child
->is_input
|| child
->is_output
)) {
357 fprintf(f
, "%s%s", first
? "" : ", ", id2vl(child
->str
).c_str());
362 for (auto child
: children
)
363 if (child
->type
== AST_PARAMETER
|| child
->type
== AST_LOCALPARAM
|| child
->type
== AST_DEFPARAM
)
364 child
->dumpVlog(f
, indent
+ " ");
366 rem_children1
.push_back(child
);
368 for (auto child
: rem_children1
)
369 if (child
->type
== AST_WIRE
|| child
->type
== AST_AUTOWIRE
|| child
->type
== AST_MEMORY
)
370 child
->dumpVlog(f
, indent
+ " ");
372 rem_children2
.push_back(child
);
373 rem_children1
.clear();
375 for (auto child
: rem_children2
)
376 if (child
->type
== AST_TASK
|| child
->type
== AST_FUNCTION
)
377 child
->dumpVlog(f
, indent
+ " ");
379 rem_children1
.push_back(child
);
380 rem_children2
.clear();
382 for (auto child
: rem_children1
)
383 child
->dumpVlog(f
, indent
+ " ");
384 rem_children1
.clear();
386 fprintf(f
, "%s" "endmodule\n", indent
.c_str());
390 if (is_input
&& is_output
)
391 fprintf(f
, "%s" "inout", indent
.c_str());
393 fprintf(f
, "%s" "input", indent
.c_str());
395 fprintf(f
, "%s" "output", indent
.c_str());
397 fprintf(f
, "%s" "wire", indent
.c_str());
399 fprintf(f
, "%s" "reg", (is_input
|| is_output
) ? " " : indent
.c_str());
401 fprintf(f
, " signed");
402 for (auto child
: children
) {
404 child
->dumpVlog(f
, "");
406 fprintf(f
, " %s", id2vl(str
).c_str());
411 fprintf(f
, "%s" "memory", indent
.c_str());
413 fprintf(f
, " signed");
414 for (auto child
: children
) {
416 child
->dumpVlog(f
, "");
418 fprintf(f
, " %s", id2vl(str
).c_str());
426 fprintf(f
, "[%d:%d]", range_left
, range_right
);
428 for (auto child
: children
) {
429 fprintf(f
, "%c", first
? '[' : ':');
430 child
->dumpVlog(f
, "");
438 fprintf(f
, "%s" "always @", indent
.c_str());
439 for (auto child
: children
) {
440 if (child
->type
!= AST_POSEDGE
&& child
->type
!= AST_NEGEDGE
&& child
->type
!= AST_EDGE
)
442 fprintf(f
, first
? "(" : ", ");
443 child
->dumpVlog(f
, "");
446 fprintf(f
, first
? "*\n" : ")\n");
447 for (auto child
: children
) {
448 if (child
->type
!= AST_POSEDGE
&& child
->type
!= AST_NEGEDGE
&& child
->type
!= AST_EDGE
)
449 child
->dumpVlog(f
, indent
+ " ");
454 fprintf(f
, "%s" "initial\n", indent
.c_str());
455 for (auto child
: children
) {
456 if (child
->type
!= AST_POSEDGE
&& child
->type
!= AST_NEGEDGE
&& child
->type
!= AST_EDGE
)
457 child
->dumpVlog(f
, indent
+ " ");
464 if (type
== AST_POSEDGE
)
465 fprintf(f
, "posedge ");
466 if (type
== AST_NEGEDGE
)
467 fprintf(f
, "negedge ");
468 for (auto child
: children
)
469 child
->dumpVlog(f
, "");
473 fprintf(f
, "%s", id2vl(str
).c_str());
474 for (auto child
: children
)
475 child
->dumpVlog(f
, "");
480 fprintf(f
, "\"%s\"", str
.c_str());
481 else if (bits
.size() == 32)
482 fprintf(f
, "%d", RTLIL::Const(bits
).as_int());
484 fprintf(f
, "%d'b %s", GetSize(bits
), RTLIL::Const(bits
).as_string().c_str());
488 fprintf(f
, "%e", realvalue
);
492 if (children
.size() == 1) {
493 children
[0]->dumpVlog(f
, indent
);
495 fprintf(f
, "%s" "begin\n", indent
.c_str());
496 for (auto child
: children
)
497 child
->dumpVlog(f
, indent
+ " ");
498 fprintf(f
, "%s" "end\n", indent
.c_str());
503 if (!children
.empty() && children
[0]->type
== AST_CONDX
)
504 fprintf(f
, "%s" "casex (", indent
.c_str());
505 else if (!children
.empty() && children
[0]->type
== AST_CONDZ
)
506 fprintf(f
, "%s" "casez (", indent
.c_str());
508 fprintf(f
, "%s" "case (", indent
.c_str());
509 children
[0]->dumpVlog(f
, "");
511 for (size_t i
= 1; i
< children
.size(); i
++) {
512 AstNode
*child
= children
[i
];
513 child
->dumpVlog(f
, indent
+ " ");
515 fprintf(f
, "%s" "endcase\n", indent
.c_str());
521 for (auto child
: children
) {
522 if (child
->type
== AST_BLOCK
) {
524 child
->dumpVlog(f
, indent
+ " ");
527 fprintf(f
, "%s", first
? indent
.c_str() : ", ");
528 if (child
->type
== AST_DEFAULT
)
529 fprintf(f
, "default");
531 child
->dumpVlog(f
, "");
538 fprintf(f
, "%sassign ", indent
.c_str());
539 children
[0]->dumpVlog(f
, "");
541 children
[1]->dumpVlog(f
, "");
547 fprintf(f
, "%s", indent
.c_str());
548 children
[0]->dumpVlog(f
, "");
549 fprintf(f
, " %s ", type
== AST_ASSIGN_EQ
? "=" : "<=");
550 children
[1]->dumpVlog(f
, "");
556 for (auto child
: children
) {
559 child
->dumpVlog(f
, "");
567 children
[0]->dumpVlog(f
, "");
569 children
[1]->dumpVlog(f
, "");
573 if (0) { case AST_BIT_NOT
: txt
= "~"; }
574 if (0) { case AST_REDUCE_AND
: txt
= "&"; }
575 if (0) { case AST_REDUCE_OR
: txt
= "|"; }
576 if (0) { case AST_REDUCE_XOR
: txt
= "^"; }
577 if (0) { case AST_REDUCE_XNOR
: txt
= "~^"; }
578 if (0) { case AST_REDUCE_BOOL
: txt
= "|"; }
579 if (0) { case AST_POS
: txt
= "+"; }
580 if (0) { case AST_NEG
: txt
= "-"; }
581 if (0) { case AST_LOGIC_NOT
: txt
= "!"; }
582 fprintf(f
, "%s(", txt
.c_str());
583 children
[0]->dumpVlog(f
, "");
587 if (0) { case AST_BIT_AND
: txt
= "&"; }
588 if (0) { case AST_BIT_OR
: txt
= "|"; }
589 if (0) { case AST_BIT_XOR
: txt
= "^"; }
590 if (0) { case AST_BIT_XNOR
: txt
= "~^"; }
591 if (0) { case AST_SHIFT_LEFT
: txt
= "<<"; }
592 if (0) { case AST_SHIFT_RIGHT
: txt
= ">>"; }
593 if (0) { case AST_SHIFT_SLEFT
: txt
= "<<<"; }
594 if (0) { case AST_SHIFT_SRIGHT
: txt
= ">>>"; }
595 if (0) { case AST_LT
: txt
= "<"; }
596 if (0) { case AST_LE
: txt
= "<="; }
597 if (0) { case AST_EQ
: txt
= "=="; }
598 if (0) { case AST_NE
: txt
= "!="; }
599 if (0) { case AST_EQX
: txt
= "==="; }
600 if (0) { case AST_NEX
: txt
= "!=="; }
601 if (0) { case AST_GE
: txt
= ">="; }
602 if (0) { case AST_GT
: txt
= ">"; }
603 if (0) { case AST_ADD
: txt
= "+"; }
604 if (0) { case AST_SUB
: txt
= "-"; }
605 if (0) { case AST_MUL
: txt
= "*"; }
606 if (0) { case AST_DIV
: txt
= "/"; }
607 if (0) { case AST_MOD
: txt
= "%"; }
608 if (0) { case AST_POW
: txt
= "**"; }
609 if (0) { case AST_LOGIC_AND
: txt
= "&&"; }
610 if (0) { case AST_LOGIC_OR
: txt
= "||"; }
612 children
[0]->dumpVlog(f
, "");
613 fprintf(f
, ")%s(", txt
.c_str());
614 children
[1]->dumpVlog(f
, "");
620 children
[0]->dumpVlog(f
, "");
622 children
[1]->dumpVlog(f
, "");
624 children
[2]->dumpVlog(f
, "");
629 std::string type_name
= type2str(type
);
630 fprintf(f
, "%s" "/** %s **/%s", indent
.c_str(), type_name
.c_str(), indent
.empty() ? "" : "\n");
631 // dumpAst(f, indent, NULL);
637 // check if two AST nodes are identical
638 bool AstNode::operator==(const AstNode
&other
) const
640 if (type
!= other
.type
)
642 if (children
.size() != other
.children
.size())
644 if (str
!= other
.str
)
646 if (bits
!= other
.bits
)
648 if (is_input
!= other
.is_input
)
650 if (is_output
!= other
.is_output
)
652 if (is_reg
!= other
.is_reg
)
654 if (is_signed
!= other
.is_signed
)
656 if (is_string
!= other
.is_string
)
658 if (range_valid
!= other
.range_valid
)
660 if (range_swapped
!= other
.range_swapped
)
662 if (port_id
!= other
.port_id
)
664 if (range_left
!= other
.range_left
)
666 if (range_right
!= other
.range_right
)
668 if (integer
!= other
.integer
)
670 for (size_t i
= 0; i
< children
.size(); i
++)
671 if (*children
[i
] != *other
.children
[i
])
676 // check if two AST nodes are not identical
677 bool AstNode::operator!=(const AstNode
&other
) const
679 return !(*this == other
);
682 // check if this AST contains the given node
683 bool AstNode::contains(const AstNode
*other
) const
687 for (auto child
: children
)
688 if (child
->contains(other
))
693 // create an AST node for a constant (using a 32 bit int as value)
694 AstNode
*AstNode::mkconst_int(uint32_t v
, bool is_signed
, int width
)
696 AstNode
*node
= new AstNode(AST_CONSTANT
);
698 node
->is_signed
= is_signed
;
699 for (int i
= 0; i
< width
; i
++) {
700 node
->bits
.push_back((v
& 1) ? RTLIL::S1
: RTLIL::S0
);
703 node
->range_valid
= true;
704 node
->range_left
= width
-1;
705 node
->range_right
= 0;
709 // create an AST node for a constant (using a bit vector as value)
710 AstNode
*AstNode::mkconst_bits(const std::vector
<RTLIL::State
> &v
, bool is_signed
)
712 AstNode
*node
= new AstNode(AST_CONSTANT
);
713 node
->is_signed
= is_signed
;
715 for (size_t i
= 0; i
< 32; i
++) {
716 if (i
< node
->bits
.size())
717 node
->integer
|= (node
->bits
[i
] == RTLIL::S1
) << i
;
718 else if (is_signed
&& !node
->bits
.empty())
719 node
->integer
|= (node
->bits
.back() == RTLIL::S1
) << i
;
721 node
->range_valid
= true;
722 node
->range_left
= node
->bits
.size()-1;
723 node
->range_right
= 0;
727 // create an AST node for a constant (using a string in bit vector form as value)
728 AstNode
*AstNode::mkconst_str(const std::vector
<RTLIL::State
> &v
)
730 AstNode
*node
= mkconst_str(RTLIL::Const(v
).decode_string());
731 while (GetSize(node
->bits
) < GetSize(v
))
732 node
->bits
.push_back(RTLIL::State::S0
);
733 log_assert(node
->bits
== v
);
737 // create an AST node for a constant (using a string as value)
738 AstNode
*AstNode::mkconst_str(const std::string
&str
)
740 std::vector
<RTLIL::State
> data
;
741 data
.reserve(str
.size() * 8);
742 for (size_t i
= 0; i
< str
.size(); i
++) {
743 unsigned char ch
= str
[str
.size() - i
- 1];
744 for (int j
= 0; j
< 8; j
++) {
745 data
.push_back((ch
& 1) ? RTLIL::S1
: RTLIL::S0
);
749 AstNode
*node
= AstNode::mkconst_bits(data
, false);
750 node
->is_string
= true;
755 bool AstNode::bits_only_01()
757 for (auto bit
: bits
)
758 if (bit
!= RTLIL::S0
&& bit
!= RTLIL::S1
)
763 RTLIL::Const
AstNode::bitsAsConst(int width
, bool is_signed
)
765 std::vector
<RTLIL::State
> bits
= this->bits
;
766 if (width
>= 0 && width
< int(bits
.size()))
768 if (width
>= 0 && width
> int(bits
.size())) {
769 RTLIL::State extbit
= RTLIL::State::S0
;
770 if (is_signed
&& !bits
.empty())
771 extbit
= bits
.back();
772 while (width
> int(bits
.size()))
773 bits
.push_back(extbit
);
775 return RTLIL::Const(bits
);
778 RTLIL::Const
AstNode::bitsAsConst(int width
)
780 return bitsAsConst(width
, is_signed
);
783 RTLIL::Const
AstNode::asAttrConst()
785 log_assert(type
== AST_CONSTANT
);
791 val
.flags
|= RTLIL::CONST_FLAG_STRING
;
792 log_assert(val
.decode_string() == str
);
798 RTLIL::Const
AstNode::asParaConst()
800 RTLIL::Const val
= asAttrConst();
802 val
.flags
|= RTLIL::CONST_FLAG_SIGNED
;
806 bool AstNode::asBool()
808 log_assert(type
== AST_CONSTANT
);
809 for (auto &bit
: bits
)
810 if (bit
== RTLIL::State::S1
)
815 int AstNode::isConst()
817 if (type
== AST_CONSTANT
)
819 if (type
== AST_REALVALUE
)
824 uint64_t AstNode::asInt(bool is_signed
)
826 if (type
== AST_CONSTANT
)
828 RTLIL::Const v
= bitsAsConst(64, is_signed
);
831 for (int i
= 0; i
< 64; i
++)
832 if (v
.bits
.at(i
) == RTLIL::State::S1
)
833 ret
|= uint64_t(1) << i
;
838 if (type
== AST_REALVALUE
)
839 return uint64_t(realvalue
);
844 double AstNode::asReal(bool is_signed
)
846 if (type
== AST_CONSTANT
)
848 RTLIL::Const
val(bits
);
850 bool is_negative
= is_signed
&& !val
.bits
.empty() && val
.bits
.back() == RTLIL::State::S1
;
852 val
= const_neg(val
, val
, false, false, val
.bits
.size());
855 for (size_t i
= 0; i
< val
.bits
.size(); i
++)
856 // IEEE Std 1800-2012 Par 6.12.2: Individual bits that are x or z in
857 // the net or the variable shall be treated as zero upon conversion.
858 if (val
.bits
.at(i
) == RTLIL::State::S1
)
866 if (type
== AST_REALVALUE
)
872 RTLIL::Const
AstNode::realAsConst(int width
)
874 double v
= round(realvalue
);
879 if (!std::isfinite(v
)) {
881 result
.bits
= std::vector
<RTLIL::State
>(width
, RTLIL::State::Sx
);
883 bool is_negative
= v
< 0;
886 for (int i
= 0; i
< width
; i
++, v
/= 2)
887 result
.bits
.push_back((fmod(floor(v
), 2) != 0) ? RTLIL::State::S1
: RTLIL::State::S0
);
889 result
= const_neg(result
, result
, false, false, result
.bits
.size());
894 // create a new AstModule from an AST_MODULE AST node
895 static AstModule
* process_module(AstNode
*ast
, bool defer
)
897 log_assert(ast
->type
== AST_MODULE
);
900 log("Storing AST representation for module `%s'.\n", ast
->str
.c_str());
902 log("Generating RTLIL representation for module `%s'.\n", ast
->str
.c_str());
904 current_module
= new AstModule
;
905 current_module
->ast
= NULL
;
906 current_module
->name
= ast
->str
;
907 current_module
->attributes
["\\src"] = stringf("%s:%d", ast
->filename
.c_str(), ast
->linenum
);
909 current_ast_mod
= ast
;
910 AstNode
*ast_before_simplify
= ast
->clone();
912 if (flag_dump_ast1
) {
913 log("Dumping Verilog AST before simplification:\n");
914 ast
->dumpAst(NULL
, " ");
915 log("--- END OF AST DUMP ---\n");
920 while (ast
->simplify(!flag_noopt
, false, false, 0, -1, false, false)) { }
922 if (flag_dump_ast2
) {
923 log("Dumping Verilog AST after simplification:\n");
924 ast
->dumpAst(NULL
, " ");
925 log("--- END OF AST DUMP ---\n");
928 if (flag_dump_vlog
) {
929 log("Dumping Verilog AST (as requested by dump_vlog option):\n");
930 ast
->dumpVlog(NULL
, " ");
931 log("--- END OF AST DUMP ---\n");
935 std::vector
<AstNode
*> new_children
;
936 for (auto child
: ast
->children
) {
937 if (child
->type
== AST_WIRE
&& (child
->is_input
|| child
->is_output
))
938 new_children
.push_back(child
);
942 ast
->children
.swap(new_children
);
943 ast
->attributes
["\\blackbox"] = AstNode::mkconst_int(1, false);
946 ignoreThisSignalsInInitial
= RTLIL::SigSpec();
948 for (auto &attr
: ast
->attributes
) {
949 if (attr
.second
->type
!= AST_CONSTANT
)
950 log_error("Attribute `%s' with non-constant value at %s:%d!\n",
951 attr
.first
.c_str(), ast
->filename
.c_str(), ast
->linenum
);
952 current_module
->attributes
[attr
.first
] = attr
.second
->asAttrConst();
954 for (size_t i
= 0; i
< ast
->children
.size(); i
++) {
955 AstNode
*node
= ast
->children
[i
];
956 if (node
->type
== AST_WIRE
|| node
->type
== AST_MEMORY
)
959 for (size_t i
= 0; i
< ast
->children
.size(); i
++) {
960 AstNode
*node
= ast
->children
[i
];
961 if (node
->type
!= AST_WIRE
&& node
->type
!= AST_MEMORY
&& node
->type
!= AST_INITIAL
)
965 ignoreThisSignalsInInitial
.sort_and_unify();
967 for (size_t i
= 0; i
< ast
->children
.size(); i
++) {
968 AstNode
*node
= ast
->children
[i
];
969 if (node
->type
== AST_INITIAL
)
973 ignoreThisSignalsInInitial
= RTLIL::SigSpec();
976 current_module
->ast
= ast_before_simplify
;
977 current_module
->nolatches
= flag_nolatches
;
978 current_module
->nomeminit
= flag_nomeminit
;
979 current_module
->nomem2reg
= flag_nomem2reg
;
980 current_module
->mem2reg
= flag_mem2reg
;
981 current_module
->lib
= flag_lib
;
982 current_module
->noopt
= flag_noopt
;
983 current_module
->icells
= flag_icells
;
984 current_module
->autowire
= flag_autowire
;
985 current_module
->fixup_ports();
987 if (flag_dump_rtlil
) {
988 log("Dumping generated RTLIL:\n");
989 log_module(current_module
);
990 log("--- END OF RTLIL DUMP ---\n");
993 return current_module
;
996 // create AstModule instances for all modules in the AST tree and add them to 'design'
997 void AST::process(RTLIL::Design
*design
, AstNode
*ast
, bool dump_ast1
, bool dump_ast2
, bool dump_vlog
, bool dump_rtlil
,
998 bool nolatches
, bool nomeminit
, bool nomem2reg
, bool mem2reg
, bool lib
, bool noopt
, bool icells
, bool ignore_redef
, bool defer
, bool autowire
)
1001 flag_dump_ast1
= dump_ast1
;
1002 flag_dump_ast2
= dump_ast2
;
1003 flag_dump_vlog
= dump_vlog
;
1004 flag_dump_rtlil
= dump_rtlil
;
1005 flag_nolatches
= nolatches
;
1006 flag_nomeminit
= nomeminit
;
1007 flag_nomem2reg
= nomem2reg
;
1008 flag_mem2reg
= mem2reg
;
1011 flag_icells
= icells
;
1012 flag_autowire
= autowire
;
1014 std::vector
<AstNode
*> global_decls
;
1016 log_assert(current_ast
->type
== AST_DESIGN
);
1017 for (auto it
= current_ast
->children
.begin(); it
!= current_ast
->children
.end(); it
++)
1019 if ((*it
)->type
== AST_MODULE
)
1021 for (auto n
: global_decls
)
1022 (*it
)->children
.push_back(n
->clone());
1024 for (auto n
: design
->verilog_packages
){
1025 for (auto o
: n
->children
) {
1026 AstNode
*cloned_node
= o
->clone();
1027 cloned_node
->str
= n
->str
+ std::string("::") + cloned_node
->str
.substr(1);
1028 (*it
)->children
.push_back(cloned_node
);
1032 if (flag_icells
&& (*it
)->str
.substr(0, 2) == "\\$")
1033 (*it
)->str
= (*it
)->str
.substr(1);
1036 (*it
)->str
= "$abstract" + (*it
)->str
;
1038 if (design
->has((*it
)->str
)) {
1040 log_error("Re-definition of module `%s' at %s:%d!\n",
1041 (*it
)->str
.c_str(), (*it
)->filename
.c_str(), (*it
)->linenum
);
1042 log("Ignoring re-definition of module `%s' at %s:%d!\n",
1043 (*it
)->str
.c_str(), (*it
)->filename
.c_str(), (*it
)->linenum
);
1047 design
->add(process_module(*it
, defer
));
1049 else if ((*it
)->type
== AST_PACKAGE
)
1050 design
->verilog_packages
.push_back((*it
)->clone());
1052 global_decls
.push_back(*it
);
1056 // AstModule destructor
1057 AstModule::~AstModule()
1063 // create a new parametric module (when needed) and return the name of the generated module
1064 RTLIL::IdString
AstModule::derive(RTLIL::Design
*design
, dict
<RTLIL::IdString
, RTLIL::Const
> parameters
)
1066 std::string stripped_name
= name
.str();
1068 if (stripped_name
.substr(0, 9) == "$abstract")
1069 stripped_name
= stripped_name
.substr(9);
1071 log_header(design
, "Executing AST frontend in derive mode using pre-parsed AST for module `%s'.\n", stripped_name
.c_str());
1074 flag_dump_ast1
= false;
1075 flag_dump_ast2
= false;
1076 flag_dump_vlog
= false;
1077 flag_nolatches
= nolatches
;
1078 flag_nomeminit
= nomeminit
;
1079 flag_nomem2reg
= nomem2reg
;
1080 flag_mem2reg
= mem2reg
;
1083 flag_icells
= icells
;
1084 flag_autowire
= autowire
;
1085 use_internal_line_num();
1087 std::string para_info
;
1088 AstNode
*new_ast
= ast
->clone();
1090 int para_counter
= 0;
1091 int orig_parameters_n
= parameters
.size();
1092 for (auto it
= new_ast
->children
.begin(); it
!= new_ast
->children
.end(); it
++) {
1093 AstNode
*child
= *it
;
1094 if (child
->type
!= AST_PARAMETER
)
1097 std::string para_id
= child
->str
;
1098 if (parameters
.count(para_id
) > 0) {
1099 log("Parameter %s = %s\n", child
->str
.c_str(), log_signal(RTLIL::SigSpec(parameters
[child
->str
])));
1101 para_info
+= stringf("%s=%s", child
->str
.c_str(), log_signal(RTLIL::SigSpec(parameters
[para_id
])));
1102 delete child
->children
.at(0);
1103 child
->children
[0] = AstNode::mkconst_bits(parameters
[para_id
].bits
, (parameters
[para_id
].flags
& RTLIL::CONST_FLAG_SIGNED
) != 0);
1104 parameters
.erase(para_id
);
1107 para_id
= stringf("$%d", para_counter
);
1108 if (parameters
.count(para_id
) > 0) {
1109 log("Parameter %d (%s) = %s\n", para_counter
, child
->str
.c_str(), log_signal(RTLIL::SigSpec(parameters
[para_id
])));
1110 goto rewrite_parameter
;
1113 if (parameters
.size() > 0)
1114 log_error("Requested parameter `%s' does not exist in module `%s'!\n", parameters
.begin()->first
.c_str(), stripped_name
.c_str());
1116 std::string modname
;
1118 if (orig_parameters_n
== 0)
1119 modname
= stripped_name
;
1120 else if (para_info
.size() > 60)
1121 modname
= "$paramod$" + sha1(para_info
) + stripped_name
;
1123 modname
= "$paramod" + stripped_name
+ para_info
;
1125 if (!design
->has(modname
)) {
1126 new_ast
->str
= modname
;
1127 design
->add(process_module(new_ast
, false));
1128 design
->module(modname
)->check();
1130 log("Found cached RTLIL representation for module `%s'.\n", modname
.c_str());
1137 RTLIL::Module
*AstModule::clone() const
1139 AstModule
*new_mod
= new AstModule
;
1140 new_mod
->name
= name
;
1143 new_mod
->ast
= ast
->clone();
1144 new_mod
->nolatches
= nolatches
;
1145 new_mod
->nomeminit
= nomeminit
;
1146 new_mod
->nomem2reg
= nomem2reg
;
1147 new_mod
->mem2reg
= mem2reg
;
1149 new_mod
->noopt
= noopt
;
1150 new_mod
->icells
= icells
;
1151 new_mod
->autowire
= autowire
;
1156 // internal dummy line number callbacks
1158 int internal_line_num
;
1159 void internal_set_line_num(int n
) {
1160 internal_line_num
= n
;
1162 int internal_get_line_num() {
1163 return internal_line_num
;
1167 // use internal dummy line number callbacks
1168 void AST::use_internal_line_num()
1170 set_line_num
= &internal_set_line_num
;
1171 get_line_num
= &internal_get_line_num
;