mirror of https://github.com/YosysHQ/yosys.git
verilog: improved support for recursive functions
This commit is contained in:
parent
48d0aeb094
commit
2085d9a55d
|
@ -250,6 +250,7 @@ namespace AST
|
|||
// simplify() creates a simpler AST by unrolling for-loops, expanding generate blocks, etc.
|
||||
// it also sets the id2ast pointers so that identifier lookups are fast in genRTLIL()
|
||||
bool simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, int width_hint, bool sign_hint, bool in_param);
|
||||
void replace_result_wire_name_in_function(const std::string &from, const std::string &to);
|
||||
AstNode *readmem(bool is_readmemh, std::string mem_filename, AstNode *memory, int start_addr, int finish_addr, bool unconditional_init);
|
||||
void expand_genblock(std::string index_var, std::string prefix, std::map<std::string, std::string> &name_map, bool original_scope = true);
|
||||
void replace_ids(const std::string &prefix, const std::map<std::string, std::string> &rules);
|
||||
|
@ -264,6 +265,7 @@ namespace AST
|
|||
// additional functionality for evaluating constant functions
|
||||
struct varinfo_t { RTLIL::Const val; int offset; bool is_signed; };
|
||||
bool has_const_only_constructs(bool &recommend_const_eval);
|
||||
bool has_const_only_constructs(std::set<std::string>& visited, bool &recommend_const_eval);
|
||||
void replace_variables(std::map<std::string, varinfo_t> &variables, AstNode *fcall);
|
||||
AstNode *eval_const_function(AstNode *fcall);
|
||||
bool is_simple_const_expr();
|
||||
|
|
|
@ -3175,6 +3175,8 @@ skip_dynamic_range_lvalue_expansion:;
|
|||
|
||||
if (all_args_const) {
|
||||
AstNode *func_workspace = current_scope[str]->clone();
|
||||
func_workspace->str = NEW_ID.str();
|
||||
func_workspace->replace_result_wire_name_in_function(str, func_workspace->str);
|
||||
newNode = func_workspace->eval_const_function(this);
|
||||
delete func_workspace;
|
||||
goto apply_newNode;
|
||||
|
@ -3714,12 +3716,12 @@ apply_newNode:
|
|||
return did_something;
|
||||
}
|
||||
|
||||
static void replace_result_wire_name_in_function(AstNode *node, std::string &from, std::string &to)
|
||||
void AstNode::replace_result_wire_name_in_function(const std::string &from, const std::string &to)
|
||||
{
|
||||
for (auto &it : node->children)
|
||||
replace_result_wire_name_in_function(it, from, to);
|
||||
if (node->str == from)
|
||||
node->str = to;
|
||||
for (AstNode *child : children)
|
||||
child->replace_result_wire_name_in_function(from, to);
|
||||
if (str == from && type != AST_FCALL && type != AST_TCALL)
|
||||
str = to;
|
||||
}
|
||||
|
||||
// replace a readmem[bh] TCALL ast node with a block of memory assignments
|
||||
|
@ -3912,7 +3914,7 @@ void AstNode::expand_genblock(std::string index_var, std::string prefix, std::ma
|
|||
|
||||
name_map[child->str] = new_name;
|
||||
if (child->type == AST_FUNCTION)
|
||||
replace_result_wire_name_in_function(child, child->str, new_name);
|
||||
child->replace_result_wire_name_in_function(child->str, new_name);
|
||||
else
|
||||
child->str = new_name;
|
||||
current_scope[new_name] = child;
|
||||
|
@ -4492,15 +4494,31 @@ bool AstNode::detect_latch(const std::string &var)
|
|||
|
||||
bool AstNode::has_const_only_constructs(bool &recommend_const_eval)
|
||||
{
|
||||
std::set<std::string> visited;
|
||||
return has_const_only_constructs(visited, recommend_const_eval);
|
||||
}
|
||||
|
||||
bool AstNode::has_const_only_constructs(std::set<std::string>& visited, bool &recommend_const_eval)
|
||||
{
|
||||
if (type == AST_FUNCTION || type == AST_TASK)
|
||||
{
|
||||
if (visited.count(str))
|
||||
{
|
||||
recommend_const_eval = true;
|
||||
return false;
|
||||
}
|
||||
visited.insert(str);
|
||||
}
|
||||
|
||||
if (type == AST_FOR)
|
||||
recommend_const_eval = true;
|
||||
if (type == AST_WHILE || type == AST_REPEAT)
|
||||
return true;
|
||||
if (type == AST_FCALL && current_scope.count(str))
|
||||
if (current_scope[str]->has_const_only_constructs(recommend_const_eval))
|
||||
if (current_scope[str]->has_const_only_constructs(visited, recommend_const_eval))
|
||||
return true;
|
||||
for (auto child : children)
|
||||
if (child->AstNode::has_const_only_constructs(recommend_const_eval))
|
||||
if (child->AstNode::has_const_only_constructs(visited, recommend_const_eval))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
module gate(
|
||||
off, fib0, fib1, fib2, fib3, fib4, fib5, fib6, fib7, fib8, fib9
|
||||
);
|
||||
input wire signed [31:0] off;
|
||||
|
||||
function automatic integer fib(
|
||||
input integer k
|
||||
);
|
||||
if (k == 0)
|
||||
fib = 0;
|
||||
else if (k == 1)
|
||||
fib = 1;
|
||||
else
|
||||
fib = fib(k - 1) + fib(k - 2);
|
||||
endfunction
|
||||
|
||||
function automatic integer fib_wrap(
|
||||
input integer k,
|
||||
output integer o
|
||||
);
|
||||
o = off + fib(k);
|
||||
endfunction
|
||||
|
||||
output integer fib0;
|
||||
output integer fib1;
|
||||
output integer fib2;
|
||||
output integer fib3;
|
||||
output integer fib4;
|
||||
output integer fib5;
|
||||
output integer fib6;
|
||||
output integer fib7;
|
||||
output integer fib8;
|
||||
output integer fib9;
|
||||
|
||||
initial begin : blk
|
||||
integer unused;
|
||||
unused = fib_wrap(0, fib0);
|
||||
unused = fib_wrap(1, fib1);
|
||||
unused = fib_wrap(2, fib2);
|
||||
unused = fib_wrap(3, fib3);
|
||||
unused = fib_wrap(4, fib4);
|
||||
unused = fib_wrap(5, fib5);
|
||||
unused = fib_wrap(6, fib6);
|
||||
unused = fib_wrap(7, fib7);
|
||||
unused = fib_wrap(8, fib8);
|
||||
unused = fib_wrap(9, fib9);
|
||||
end
|
||||
endmodule
|
||||
|
||||
module gold(
|
||||
off, fib0, fib1, fib2, fib3, fib4, fib5, fib6, fib7, fib8, fib9
|
||||
);
|
||||
input wire signed [31:0] off;
|
||||
|
||||
output integer fib0 = off + 0;
|
||||
output integer fib1 = off + 1;
|
||||
output integer fib2 = off + 1;
|
||||
output integer fib3 = off + 2;
|
||||
output integer fib4 = off + 3;
|
||||
output integer fib5 = off + 5;
|
||||
output integer fib6 = off + 8;
|
||||
output integer fib7 = off + 13;
|
||||
output integer fib8 = off + 21;
|
||||
output integer fib9 = off + 34;
|
||||
endmodule
|
|
@ -0,0 +1,6 @@
|
|||
read_verilog fib.v
|
||||
hierarchy
|
||||
proc
|
||||
equiv_make gold gate equiv
|
||||
equiv_simple
|
||||
equiv_status -assert
|
Loading…
Reference in New Issue