2 * yosys -- Yosys Open SYnthesis Suite
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 * This is the AST frontend library.
22 * The AST frontend library is not a frontend on it's own but provides a
23 * generic abstract syntax tree (AST) abstraction for HDL code and can be
24 * used by HDL frontends. See "ast.h" for an overview of the API and the
25 * Verilog frontend for an usage example.
29 #include "kernel/log.h"
30 #include "libs/sha1/sha1.h"
38 using namespace AST_INTERNAL
;
40 // instanciate global variables (public API)
42 std::string current_filename
;
43 void (*set_line_num
)(int) = NULL
;
44 int (*get_line_num
)() = NULL
;
47 // instanciate global variables (private API)
48 namespace AST_INTERNAL
{
49 bool flag_dump_ast1
, flag_dump_ast2
, flag_dump_vlog
, flag_nolatches
, flag_nomem2reg
, flag_mem2reg
, flag_lib
, flag_noopt
, flag_icells
, flag_autowire
;
50 AstNode
*current_ast
, *current_ast_mod
;
51 std::map
<std::string
, AstNode
*> current_scope
;
52 RTLIL::SigSpec
*genRTLIL_subst_from
= NULL
;
53 RTLIL::SigSpec
*genRTLIL_subst_to
= NULL
;
54 RTLIL::SigSpec ignoreThisSignalsInInitial
;
55 AstNode
*current_top_block
, *current_block
, *current_block_child
;
56 AstModule
*current_module
;
59 // convert node types to string
60 std::string
AST::type2str(AstNodeType type
)
64 #define X(_item) case _item: return #_item;
157 // check if attribute exists and has non-zero value
158 bool AstNode::get_bool_attribute(RTLIL::IdString id
)
160 if (attributes
.count(id
) == 0)
163 AstNode
*attr
= attributes
.at(id
);
164 if (attr
->type
!= AST_CONSTANT
)
165 log_error("Attribute `%s' with non-constant value at %s:%d!\n",
166 id
.c_str(), attr
->filename
.c_str(), attr
->linenum
);
168 return attr
->integer
!= 0;
171 // create new node (AstNode constructor)
172 // (the optional child arguments make it easier to create AST trees)
173 AstNode::AstNode(AstNodeType type
, AstNode
*child1
, AstNode
*child2
)
176 filename
= current_filename
;
177 linenum
= get_line_num();
192 children
.push_back(child1
);
194 children
.push_back(child2
);
197 // create a (deep recursive) copy of a node
198 AstNode
*AstNode::clone()
200 AstNode
*that
= new AstNode
;
202 for (auto &it
: that
->children
)
204 for (auto &it
: that
->attributes
)
205 it
.second
= it
.second
->clone();
209 // create a (deep recursive) copy of a node use 'other' as target root node
210 void AstNode::cloneInto(AstNode
*other
)
212 AstNode
*tmp
= clone();
213 other
->delete_children();
215 tmp
->children
.clear();
216 tmp
->attributes
.clear();
220 // delete all children in this node
221 void AstNode::delete_children()
223 for (auto &it
: children
)
227 for (auto &it
: attributes
)
232 // AstNode destructor
238 // create a nice text representation of the node
239 // (traverse tree by recursion, use 'other' pointer for diffing two AST trees)
240 void AstNode::dumpAst(FILE *f
, std::string indent
)
243 for (auto f
: log_files
)
248 std::string type_name
= type2str(type
);
249 fprintf(f
, "%s%s <%s:%d>", indent
.c_str(), type_name
.c_str(), filename
.c_str(), linenum
);
252 fprintf(f
, " [%p -> %p]", this, id2ast
);
254 fprintf(f
, " [%p]", this);
257 fprintf(f
, " str='%s'", str
.c_str());
259 fprintf(f
, " bits='");
260 for (size_t i
= bits
.size(); i
> 0; i
--)
261 fprintf(f
, "%c", bits
[i
-1] == RTLIL::S0
? '0' :
262 bits
[i
-1] == RTLIL::S1
? '1' :
263 bits
[i
-1] == RTLIL::Sx
? 'x' :
264 bits
[i
-1] == RTLIL::Sz
? 'z' : '?');
265 fprintf(f
, "'(%zd)", bits
.size());
268 fprintf(f
, " input");
270 fprintf(f
, " output");
274 fprintf(f
, " signed");
276 fprintf(f
, " port=%d", port_id
);
277 if (range_valid
|| range_left
!= -1 || range_right
!= 0)
278 fprintf(f
, " range=[%d:%d]%s", range_left
, range_right
, range_valid
? "" : "!");
280 fprintf(f
, " int=%u", (int)integer
);
283 for (auto &it
: attributes
) {
284 fprintf(f
, "%s ATTR %s:\n", indent
.c_str(), it
.first
.c_str());
285 it
.second
->dumpAst(f
, indent
+ " ");
288 for (size_t i
= 0; i
< children
.size(); i
++)
289 children
[i
]->dumpAst(f
, indent
+ " ");
292 // helper function for AstNode::dumpVlog()
293 static std::string
id2vl(std::string txt
)
295 if (txt
.size() > 1 && txt
[0] == '\\')
297 for (size_t i
= 0; i
< txt
.size(); i
++) {
298 if ('A' <= txt
[i
] && txt
[i
] <= 'Z') continue;
299 if ('a' <= txt
[i
] && txt
[i
] <= 'z') continue;
300 if ('0' <= txt
[i
] && txt
[i
] <= '9') continue;
301 if (txt
[i
] == '_') continue;
302 txt
= "\\" + txt
+ " ";
308 // dump AST node as verilog pseudo-code
309 void AstNode::dumpVlog(FILE *f
, std::string indent
)
313 std::vector
<AstNode
*> rem_children1
, rem_children2
;
316 for (auto f
: log_files
)
321 for (auto &it
: attributes
) {
322 fprintf(f
, "%s" "(* %s = ", indent
.c_str(), id2vl(it
.first
).c_str());
323 it
.second
->dumpVlog(f
, "");
324 fprintf(f
, " *)%s", indent
.empty() ? "" : "\n");
330 fprintf(f
, "%s" "module %s(", indent
.c_str(), id2vl(str
).c_str());
331 for (auto child
: children
)
332 if (child
->type
== AST_WIRE
&& (child
->is_input
|| child
->is_output
)) {
333 fprintf(f
, "%s%s", first
? "" : ", ", id2vl(child
->str
).c_str());
338 for (auto child
: children
)
339 if (child
->type
== AST_PARAMETER
|| child
->type
== AST_LOCALPARAM
|| child
->type
== AST_DEFPARAM
)
340 child
->dumpVlog(f
, indent
+ " ");
342 rem_children1
.push_back(child
);
344 for (auto child
: rem_children1
)
345 if (child
->type
== AST_WIRE
|| child
->type
== AST_AUTOWIRE
|| child
->type
== AST_MEMORY
)
346 child
->dumpVlog(f
, indent
+ " ");
348 rem_children2
.push_back(child
);
349 rem_children1
.clear();
351 for (auto child
: rem_children2
)
352 if (child
->type
== AST_TASK
|| child
->type
== AST_FUNCTION
)
353 child
->dumpVlog(f
, indent
+ " ");
355 rem_children1
.push_back(child
);
356 rem_children2
.clear();
358 for (auto child
: rem_children1
)
359 child
->dumpVlog(f
, indent
+ " ");
360 rem_children1
.clear();
362 fprintf(f
, "%s" "endmodule\n", indent
.c_str());
366 if (is_input
&& is_output
)
367 fprintf(f
, "%s" "inout", indent
.c_str());
369 fprintf(f
, "%s" "input", indent
.c_str());
371 fprintf(f
, "%s" "output", indent
.c_str());
373 fprintf(f
, "%s" "wire", indent
.c_str());
375 fprintf(f
, "%s" "reg", (is_input
|| is_output
) ? " " : indent
.c_str());
377 fprintf(f
, " signed");
378 for (auto child
: children
) {
380 child
->dumpVlog(f
, "");
382 fprintf(f
, " %s", id2vl(str
).c_str());
387 fprintf(f
, "%s" "memory", indent
.c_str());
389 fprintf(f
, " signed");
390 for (auto child
: children
) {
392 child
->dumpVlog(f
, "");
394 fprintf(f
, " %s", id2vl(str
).c_str());
402 fprintf(f
, "[%d:%d]", range_left
, range_right
);
404 for (auto child
: children
) {
405 fprintf(f
, "%c", first
? '[' : ':');
406 child
->dumpVlog(f
, "");
414 fprintf(f
, "%s" "always @(", indent
.c_str());
415 for (auto child
: children
) {
416 if (child
->type
!= AST_POSEDGE
&& child
->type
!= AST_NEGEDGE
&& child
->type
!= AST_EDGE
)
420 child
->dumpVlog(f
, "");
424 for (auto child
: children
) {
425 if (child
->type
!= AST_POSEDGE
&& child
->type
!= AST_NEGEDGE
&& child
->type
!= AST_EDGE
)
426 child
->dumpVlog(f
, indent
+ " ");
431 fprintf(f
, "%s" "initial\n", indent
.c_str());
432 for (auto child
: children
) {
433 if (child
->type
!= AST_POSEDGE
&& child
->type
!= AST_NEGEDGE
&& child
->type
!= AST_EDGE
)
434 child
->dumpVlog(f
, indent
+ " ");
441 if (type
== AST_POSEDGE
)
442 fprintf(f
, "posedge ");
443 if (type
== AST_NEGEDGE
)
444 fprintf(f
, "negedge ");
445 for (auto child
: children
)
446 child
->dumpVlog(f
, "");
450 fprintf(f
, "%s", id2vl(str
).c_str());
451 for (auto child
: children
)
452 child
->dumpVlog(f
, "");
457 fprintf(f
, "\"%s\"", str
.c_str());
458 else if (bits
.size() == 32)
459 fprintf(f
, "%d", RTLIL::Const(bits
).as_int());
461 fprintf(f
, "%zd'b %s", bits
.size(), RTLIL::Const(bits
).as_string().c_str());
465 fprintf(f
, "%e", realvalue
);
469 if (children
.size() == 1) {
470 children
[0]->dumpVlog(f
, indent
);
472 fprintf(f
, "%s" "begin\n", indent
.c_str());
473 for (auto child
: children
)
474 child
->dumpVlog(f
, indent
+ " ");
475 fprintf(f
, "%s" "end\n", indent
.c_str());
480 fprintf(f
, "%s" "case (", indent
.c_str());
481 children
[0]->dumpVlog(f
, "");
483 for (size_t i
= 1; i
< children
.size(); i
++) {
484 AstNode
*child
= children
[i
];
485 child
->dumpVlog(f
, indent
+ " ");
487 fprintf(f
, "%s" "endcase\n", indent
.c_str());
491 for (auto child
: children
) {
492 if (child
->type
== AST_BLOCK
) {
494 child
->dumpVlog(f
, indent
+ " ");
497 fprintf(f
, "%s", first
? indent
.c_str() : ", ");
498 if (child
->type
== AST_DEFAULT
)
499 fprintf(f
, "default");
501 child
->dumpVlog(f
, "");
509 fprintf(f
, "%s", indent
.c_str());
510 children
[0]->dumpVlog(f
, "");
511 fprintf(f
, " %s ", type
== AST_ASSIGN_EQ
? "=" : "<=");
512 children
[1]->dumpVlog(f
, "");
518 for (auto child
: children
) {
521 child
->dumpVlog(f
, "");
529 children
[0]->dumpVlog(f
, "");
531 children
[1]->dumpVlog(f
, "");
535 if (0) { case AST_BIT_NOT
: txt
= "~"; }
536 if (0) { case AST_REDUCE_AND
: txt
= "&"; }
537 if (0) { case AST_REDUCE_OR
: txt
= "|"; }
538 if (0) { case AST_REDUCE_XOR
: txt
= "^"; }
539 if (0) { case AST_REDUCE_XNOR
: txt
= "~^"; }
540 if (0) { case AST_REDUCE_BOOL
: txt
= "|"; }
541 if (0) { case AST_POS
: txt
= "+"; }
542 if (0) { case AST_NEG
: txt
= "-"; }
543 if (0) { case AST_LOGIC_NOT
: txt
= "!"; }
544 fprintf(f
, "%s(", txt
.c_str());
545 children
[0]->dumpVlog(f
, "");
549 if (0) { case AST_BIT_AND
: txt
= "&"; }
550 if (0) { case AST_BIT_OR
: txt
= "|"; }
551 if (0) { case AST_BIT_XOR
: txt
= "^"; }
552 if (0) { case AST_BIT_XNOR
: txt
= "~^"; }
553 if (0) { case AST_SHIFT_LEFT
: txt
= "<<"; }
554 if (0) { case AST_SHIFT_RIGHT
: txt
= ">>"; }
555 if (0) { case AST_SHIFT_SLEFT
: txt
= "<<<"; }
556 if (0) { case AST_SHIFT_SRIGHT
: txt
= ">>>"; }
557 if (0) { case AST_LT
: txt
= "<"; }
558 if (0) { case AST_LE
: txt
= "<="; }
559 if (0) { case AST_EQ
: txt
= "=="; }
560 if (0) { case AST_NE
: txt
= "!="; }
561 if (0) { case AST_EQX
: txt
= "==="; }
562 if (0) { case AST_NEX
: txt
= "!=="; }
563 if (0) { case AST_GE
: txt
= ">="; }
564 if (0) { case AST_GT
: txt
= ">"; }
565 if (0) { case AST_ADD
: txt
= "+"; }
566 if (0) { case AST_SUB
: txt
= "-"; }
567 if (0) { case AST_MUL
: txt
= "*"; }
568 if (0) { case AST_DIV
: txt
= "/"; }
569 if (0) { case AST_MOD
: txt
= "%"; }
570 if (0) { case AST_POW
: txt
= "**"; }
571 if (0) { case AST_LOGIC_AND
: txt
= "&&"; }
572 if (0) { case AST_LOGIC_OR
: txt
= "||"; }
574 children
[0]->dumpVlog(f
, "");
575 fprintf(f
, ")%s(", txt
.c_str());
576 children
[1]->dumpVlog(f
, "");
582 children
[0]->dumpVlog(f
, "");
584 children
[1]->dumpVlog(f
, "");
586 children
[2]->dumpVlog(f
, "");
591 std::string type_name
= type2str(type
);
592 fprintf(f
, "%s" "/** %s **/%s", indent
.c_str(), type_name
.c_str(), indent
.empty() ? "" : "\n");
593 // dumpAst(f, indent, NULL);
597 // check if two AST nodes are identical
598 bool AstNode::operator==(const AstNode
&other
) const
600 if (type
!= other
.type
)
602 if (children
.size() != other
.children
.size())
604 if (str
!= other
.str
)
606 if (bits
!= other
.bits
)
608 if (is_input
!= other
.is_input
)
610 if (is_output
!= other
.is_output
)
612 if (is_reg
!= other
.is_reg
)
614 if (is_signed
!= other
.is_signed
)
616 if (is_string
!= other
.is_string
)
618 if (range_valid
!= other
.range_valid
)
620 if (port_id
!= other
.port_id
)
622 if (range_left
!= other
.range_left
)
624 if (range_right
!= other
.range_right
)
626 if (integer
!= other
.integer
)
628 for (size_t i
= 0; i
< children
.size(); i
++)
629 if (*children
[i
] != *other
.children
[i
])
634 // check if two AST nodes are not identical
635 bool AstNode::operator!=(const AstNode
&other
) const
637 return !(*this == other
);
640 // check if this AST contains the given node
641 bool AstNode::contains(const AstNode
*other
) const
645 for (auto child
: children
)
646 if (child
->contains(other
))
651 // create an AST node for a constant (using a 32 bit int as value)
652 AstNode
*AstNode::mkconst_int(uint32_t v
, bool is_signed
, int width
)
654 AstNode
*node
= new AstNode(AST_CONSTANT
);
656 node
->is_signed
= is_signed
;
657 for (int i
= 0; i
< width
; i
++) {
658 node
->bits
.push_back((v
& 1) ? RTLIL::S1
: RTLIL::S0
);
661 node
->range_valid
= true;
662 node
->range_left
= width
-1;
663 node
->range_right
= 0;
667 // create an AST node for a constant (using a bit vector as value)
668 AstNode
*AstNode::mkconst_bits(const std::vector
<RTLIL::State
> &v
, bool is_signed
)
670 AstNode
*node
= new AstNode(AST_CONSTANT
);
671 node
->is_signed
= is_signed
;
673 for (size_t i
= 0; i
< 32; i
++) {
674 if (i
< node
->bits
.size())
675 node
->integer
|= (node
->bits
[i
] == RTLIL::S1
) << i
;
677 node
->integer
|= (node
->bits
.back() == RTLIL::S1
) << i
;
679 node
->range_valid
= true;
680 node
->range_left
= node
->bits
.size()-1;
681 node
->range_right
= 0;
685 // create an AST node for a constant (using a string in bit vector form as value)
686 AstNode
*AstNode::mkconst_str(const std::vector
<RTLIL::State
> &v
)
688 AstNode
*node
= mkconst_str(RTLIL::Const(v
).decode_string());
689 log_assert(node
->bits
== v
);
693 // create an AST node for a constant (using a string as value)
694 AstNode
*AstNode::mkconst_str(const std::string
&str
)
696 std::vector
<RTLIL::State
> data
;
697 data
.reserve(str
.size() * 8);
698 for (size_t i
= 0; i
< str
.size(); i
++) {
699 unsigned char ch
= str
[str
.size() - i
- 1];
700 for (int j
= 0; j
< 8; j
++) {
701 data
.push_back((ch
& 1) ? RTLIL::S1
: RTLIL::S0
);
705 AstNode
*node
= AstNode::mkconst_bits(data
, false);
706 node
->is_string
= true;
711 RTLIL::Const
AstNode::bitsAsConst(int width
, bool is_signed
)
713 std::vector
<RTLIL::State
> bits
= this->bits
;
714 if (width
>= 0 && width
< int(bits
.size()))
716 if (width
>= 0 && width
> int(bits
.size())) {
717 RTLIL::State extbit
= RTLIL::State::S0
;
718 if (is_signed
&& !bits
.empty())
719 extbit
= bits
.back();
720 while (width
> int(bits
.size()))
721 bits
.push_back(extbit
);
723 return RTLIL::Const(bits
);
726 RTLIL::Const
AstNode::bitsAsConst(int width
)
728 return bitsAsConst(width
, is_signed
);
731 RTLIL::Const
AstNode::asAttrConst()
733 log_assert(type
== AST_CONSTANT
);
739 val
.flags
|= RTLIL::CONST_FLAG_STRING
;
740 log_assert(val
.decode_string() == str
);
746 RTLIL::Const
AstNode::asParaConst()
748 RTLIL::Const val
= asAttrConst();
750 val
.flags
|= RTLIL::CONST_FLAG_SIGNED
;
754 bool AstNode::asBool()
756 log_assert(type
== AST_CONSTANT
);
757 for (auto &bit
: bits
)
758 if (bit
== RTLIL::State::S1
)
763 int AstNode::isConst()
765 if (type
== AST_CONSTANT
)
767 if (type
== AST_REALVALUE
)
772 double AstNode::asReal(bool is_signed
)
774 if (type
== AST_CONSTANT
) {
778 double p
= exp2(val
.bits
.size()-32);
779 if (val
.bits
.size() > 32)
780 val
.bits
.erase(val
.bits
.begin(), val
.bits
.begin()+(val
.bits
.size()-32));
781 int32_t v
= val
.as_int() << (32-val
.bits
.size());
785 return uint32_t(v
) * p
;
787 if (type
== AST_REALVALUE
)
792 // create a new AstModule from an AST_MODULE AST node
793 static AstModule
* process_module(AstNode
*ast
, bool defer
)
795 assert(ast
->type
== AST_MODULE
);
798 log("Storing AST representation for module `%s'.\n", ast
->str
.c_str());
800 log("Generating RTLIL representation for module `%s'.\n", ast
->str
.c_str());
802 current_module
= new AstModule
;
803 current_module
->ast
= NULL
;
804 current_module
->name
= ast
->str
;
805 current_module
->attributes
["\\src"] = stringf("%s:%d", ast
->filename
.c_str(), ast
->linenum
);
807 current_ast_mod
= ast
;
808 AstNode
*ast_before_simplify
= ast
->clone();
810 if (flag_dump_ast1
) {
811 log("Dumping verilog AST before simplification:\n");
812 ast
->dumpAst(NULL
, " ");
813 log("--- END OF AST DUMP ---\n");
818 while (ast
->simplify(!flag_noopt
, false, false, 0, -1, false, false)) { }
820 if (flag_dump_ast2
) {
821 log("Dumping verilog AST after simplification:\n");
822 ast
->dumpAst(NULL
, " ");
823 log("--- END OF AST DUMP ---\n");
826 if (flag_dump_vlog
) {
827 log("Dumping verilog AST (as requested by dump_vlog option):\n");
828 ast
->dumpVlog(NULL
, " ");
829 log("--- END OF AST DUMP ---\n");
833 std::vector
<AstNode
*> new_children
;
834 for (auto child
: ast
->children
) {
835 if (child
->type
== AST_WIRE
&& (child
->is_input
|| child
->is_output
))
836 new_children
.push_back(child
);
840 ast
->children
.swap(new_children
);
841 ast
->attributes
["\\blackbox"] = AstNode::mkconst_int(1, false);
844 ignoreThisSignalsInInitial
= RTLIL::SigSpec();
846 for (auto &attr
: ast
->attributes
) {
847 if (attr
.second
->type
!= AST_CONSTANT
)
848 log_error("Attribute `%s' with non-constant value at %s:%d!\n",
849 attr
.first
.c_str(), ast
->filename
.c_str(), ast
->linenum
);
850 current_module
->attributes
[attr
.first
] = attr
.second
->asAttrConst();
852 for (size_t i
= 0; i
< ast
->children
.size(); i
++) {
853 AstNode
*node
= ast
->children
[i
];
854 if (node
->type
== AST_WIRE
|| node
->type
== AST_MEMORY
)
857 for (size_t i
= 0; i
< ast
->children
.size(); i
++) {
858 AstNode
*node
= ast
->children
[i
];
859 if (node
->type
!= AST_WIRE
&& node
->type
!= AST_MEMORY
&& node
->type
!= AST_INITIAL
)
863 ignoreThisSignalsInInitial
.sort_and_unify();
865 for (size_t i
= 0; i
< ast
->children
.size(); i
++) {
866 AstNode
*node
= ast
->children
[i
];
867 if (node
->type
== AST_INITIAL
)
871 ignoreThisSignalsInInitial
= RTLIL::SigSpec();
874 current_module
->ast
= ast_before_simplify
;
875 current_module
->nolatches
= flag_nolatches
;
876 current_module
->nomem2reg
= flag_nomem2reg
;
877 current_module
->mem2reg
= flag_mem2reg
;
878 current_module
->lib
= flag_lib
;
879 current_module
->noopt
= flag_noopt
;
880 current_module
->icells
= flag_icells
;
881 current_module
->autowire
= flag_autowire
;
882 return current_module
;
885 // create AstModule instances for all modules in the AST tree and add them to 'design'
886 void AST::process(RTLIL::Design
*design
, AstNode
*ast
, bool dump_ast1
, bool dump_ast2
, bool dump_vlog
, bool nolatches
, bool nomem2reg
, bool mem2reg
, bool lib
, bool noopt
, bool icells
, bool ignore_redef
, bool defer
, bool autowire
)
889 flag_dump_ast1
= dump_ast1
;
890 flag_dump_ast2
= dump_ast2
;
891 flag_dump_vlog
= dump_vlog
;
892 flag_nolatches
= nolatches
;
893 flag_nomem2reg
= nomem2reg
;
894 flag_mem2reg
= mem2reg
;
897 flag_icells
= icells
;
898 flag_autowire
= autowire
;
900 assert(current_ast
->type
== AST_DESIGN
);
901 for (auto it
= current_ast
->children
.begin(); it
!= current_ast
->children
.end(); it
++) {
902 if (flag_icells
&& (*it
)->str
.substr(0, 2) == "\\$")
903 (*it
)->str
= (*it
)->str
.substr(1);
905 (*it
)->str
= "$abstract" + (*it
)->str
;
906 if (design
->modules
.count((*it
)->str
)) {
908 log_error("Re-definition of module `%s' at %s:%d!\n",
909 (*it
)->str
.c_str(), (*it
)->filename
.c_str(), (*it
)->linenum
);
910 log_error("Ignoring re-definition of module `%s' at %s:%d!\n",
911 (*it
)->str
.c_str(), (*it
)->filename
.c_str(), (*it
)->linenum
);
914 design
->modules
[(*it
)->str
] = process_module(*it
, defer
);
918 // AstModule destructor
919 AstModule::~AstModule()
925 // create a new parametric module (when needed) and return the name of the generated module
926 RTLIL::IdString
AstModule::derive(RTLIL::Design
*design
, std::map
<RTLIL::IdString
, RTLIL::Const
> parameters
)
928 std::string stripped_name
= name
;
930 if (stripped_name
.substr(0, 9) == "$abstract")
931 stripped_name
= stripped_name
.substr(9);
933 log_header("Executing AST frontend in derive mode using pre-parsed AST for module `%s'.\n", stripped_name
.c_str());
936 flag_dump_ast1
= false;
937 flag_dump_ast2
= false;
938 flag_dump_vlog
= false;
939 flag_nolatches
= nolatches
;
940 flag_nomem2reg
= nomem2reg
;
941 flag_mem2reg
= mem2reg
;
944 flag_icells
= icells
;
945 flag_autowire
= autowire
;
946 use_internal_line_num();
948 std::string para_info
;
949 std::vector
<unsigned char> hash_data
;
950 hash_data
.insert(hash_data
.end(), stripped_name
.begin(), stripped_name
.end());
951 hash_data
.push_back(0);
953 AstNode
*new_ast
= ast
->clone();
955 int para_counter
= 0;
956 int orig_parameters_n
= parameters
.size();
957 for (auto it
= new_ast
->children
.begin(); it
!= new_ast
->children
.end(); it
++) {
958 AstNode
*child
= *it
;
959 if (child
->type
!= AST_PARAMETER
)
962 std::string para_id
= child
->str
;
963 if (parameters
.count(para_id
) > 0) {
964 log("Parameter %s = %s\n", child
->str
.c_str(), log_signal(RTLIL::SigSpec(parameters
[child
->str
])));
966 para_info
+= stringf("%s=%s", child
->str
.c_str(), log_signal(RTLIL::SigSpec(parameters
[para_id
])));
967 delete child
->children
.at(0);
968 child
->children
[0] = AstNode::mkconst_bits(parameters
[para_id
].bits
, (parameters
[para_id
].flags
& RTLIL::CONST_FLAG_SIGNED
) != 0);
969 hash_data
.insert(hash_data
.end(), child
->str
.begin(), child
->str
.end());
970 hash_data
.push_back(0);
971 hash_data
.insert(hash_data
.end(), parameters
[para_id
].bits
.begin(), parameters
[para_id
].bits
.end());
972 hash_data
.push_back(0xff);
973 parameters
.erase(para_id
);
976 para_id
= stringf("$%d", para_counter
);
977 if (parameters
.count(para_id
) > 0) {
978 log("Parameter %d (%s) = %s\n", para_counter
, child
->str
.c_str(), log_signal(RTLIL::SigSpec(parameters
[para_id
])));
979 goto rewrite_parameter
;
982 if (parameters
.size() > 0)
983 log_error("Requested parameter `%s' does not exist in module `%s'!\n", parameters
.begin()->first
.c_str(), stripped_name
.c_str());
987 if (orig_parameters_n
== 0)
989 modname
= stripped_name
;
992 if (para_info
.size() > 60)
994 unsigned char hash
[20];
995 unsigned char *hash_data2
= new unsigned char[hash_data
.size()];
996 for (size_t i
= 0; i
< hash_data
.size(); i
++)
997 hash_data2
[i
] = hash_data
[i
];
998 sha1::calc(hash_data2
, hash_data
.size(), hash
);
1002 sha1::toHexString(hash
, hexstring
);
1004 modname
= "$paramod$" + std::string(hexstring
) + stripped_name
;
1008 modname
= "$paramod" + stripped_name
+ para_info
;
1011 if (design
->modules
.count(modname
) == 0) {
1012 new_ast
->str
= modname
;
1013 design
->modules
[modname
] = process_module(new_ast
, false);
1014 design
->modules
[modname
]->check();
1016 log("Found cached RTLIL representation for module `%s'.\n", modname
.c_str());
1023 RTLIL::Module
*AstModule::clone() const
1025 AstModule
*new_mod
= new AstModule
;
1028 new_mod
->ast
= ast
->clone();
1029 new_mod
->nolatches
= nolatches
;
1030 new_mod
->nomem2reg
= nomem2reg
;
1031 new_mod
->mem2reg
= mem2reg
;
1033 new_mod
->noopt
= noopt
;
1034 new_mod
->icells
= icells
;
1035 new_mod
->autowire
= autowire
;
1040 // internal dummy line number callbacks
1042 int internal_line_num
;
1043 void internal_set_line_num(int n
) {
1044 internal_line_num
= n
;
1046 int internal_get_line_num() {
1047 return internal_line_num
;
1051 // use internal dummy line number callbacks
1052 void AST::use_internal_line_num()
1054 set_line_num
= &internal_set_line_num
;
1055 get_line_num
= &internal_get_line_num
;