Merge pull request #937 from larsclausen/continue-break-const-func
Support continue/break in constant functions
This commit is contained in:
commit
3780cb2da2
|
|
@ -0,0 +1,39 @@
|
|||
// Check that break and continue are supported in constant functions in for
|
||||
// loops
|
||||
|
||||
module test;
|
||||
|
||||
function automatic integer f1(integer x);
|
||||
integer j = 0;
|
||||
for (integer i = 0; i < 10; i++) begin
|
||||
if (i >= x) begin
|
||||
break;
|
||||
end
|
||||
j++;
|
||||
end
|
||||
return j;
|
||||
endfunction
|
||||
|
||||
function automatic integer f2(integer x);
|
||||
integer j = 0;
|
||||
for (integer i = 0; i < x; i++) begin
|
||||
if (i % 2 == 0) begin
|
||||
continue;
|
||||
end
|
||||
j++;
|
||||
end
|
||||
return j;
|
||||
endfunction
|
||||
|
||||
reg [f1(3):0] x;
|
||||
reg [f2(6):0] y;
|
||||
|
||||
initial begin
|
||||
if ($bits(x) === 4 && $bits(y) === 4) begin
|
||||
$display("PASSED");
|
||||
end else begin
|
||||
$display("FAILED");
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
// Check that break and continue are supported in constant functions in while
|
||||
// loops
|
||||
|
||||
module test;
|
||||
|
||||
function automatic integer f1(integer x);
|
||||
integer j = 0;
|
||||
integer i = 0;
|
||||
while (i < 10) begin
|
||||
if (i >= x) begin
|
||||
break;
|
||||
end
|
||||
j++;
|
||||
i++;
|
||||
end
|
||||
return j;
|
||||
endfunction
|
||||
|
||||
function automatic integer f2(integer x);
|
||||
integer j = 0;
|
||||
integer i = 0;
|
||||
while (i < x) begin
|
||||
i++;
|
||||
if (i % 2 == 0) begin
|
||||
continue;
|
||||
end
|
||||
j++;
|
||||
end
|
||||
return j;
|
||||
endfunction
|
||||
|
||||
reg [f1(3):0] x;
|
||||
reg [f2(6):0] y;
|
||||
|
||||
initial begin
|
||||
if ($bits(x) === 4 && $bits(y) === 4) begin
|
||||
$display("PASSED");
|
||||
end else begin
|
||||
$display("FAILED");
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
// Check that break and continue are supported in constant functions in repeat
|
||||
// loops
|
||||
|
||||
module test;
|
||||
|
||||
function automatic integer f1(integer x);
|
||||
integer j = 0;
|
||||
repeat(10) begin
|
||||
if (j >= x) begin
|
||||
break;
|
||||
end
|
||||
j++;
|
||||
end
|
||||
return j;
|
||||
endfunction
|
||||
|
||||
function automatic integer f2(integer x);
|
||||
integer j = 0;
|
||||
integer i = 0;
|
||||
repeat(x) begin
|
||||
i++;
|
||||
if (i % 2 == 0) begin
|
||||
continue;
|
||||
end
|
||||
j++;
|
||||
end
|
||||
return j;
|
||||
endfunction
|
||||
|
||||
reg [f1(3):0] x;
|
||||
reg [f2(6):0] y;
|
||||
|
||||
initial begin
|
||||
if ($bits(x) === 4 && $bits(y) === 4) begin
|
||||
$display("PASSED");
|
||||
end else begin
|
||||
$display("FAILED");
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
// Check that break and continue are supported in constant functions in do-while
|
||||
// loops
|
||||
|
||||
module test;
|
||||
|
||||
function automatic integer f1(integer x);
|
||||
integer j = 0;
|
||||
integer i = 0;
|
||||
do begin
|
||||
if (i >= x) begin
|
||||
break;
|
||||
end
|
||||
j++;
|
||||
i++;
|
||||
end while (i < 10);
|
||||
return j;
|
||||
endfunction
|
||||
|
||||
function automatic integer f2(integer x);
|
||||
integer j = 0;
|
||||
integer i = 0;
|
||||
do begin
|
||||
i++;
|
||||
if (i % 2 == 0) begin
|
||||
continue;
|
||||
end
|
||||
j++;
|
||||
end while (i < x);
|
||||
return j;
|
||||
endfunction
|
||||
|
||||
reg [f1(3):0] x;
|
||||
reg [f2(6):0] y;
|
||||
|
||||
initial begin
|
||||
if ($bits(x) === 4 && $bits(y) === 4) begin
|
||||
$display("PASSED");
|
||||
end else begin
|
||||
$display("FAILED");
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
// Check that break and continue are supported in constant functions in forever
|
||||
// loops
|
||||
|
||||
module test;
|
||||
|
||||
function automatic integer f(integer x);
|
||||
integer j = 0;
|
||||
integer i = 0;
|
||||
forever begin
|
||||
i++;
|
||||
if (i == x) begin
|
||||
break;
|
||||
end
|
||||
if (i % 2 == 0) begin
|
||||
continue;
|
||||
end
|
||||
j++;
|
||||
end
|
||||
return j;
|
||||
endfunction
|
||||
|
||||
reg [f(10):0] x;
|
||||
|
||||
initial begin
|
||||
if ($bits(x) === 6) begin
|
||||
$display("PASSED");
|
||||
end else begin
|
||||
$display("FAILED");
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
|
@ -10,6 +10,11 @@ case2 vvp_tests/case2.json
|
|||
case2-S vvp_tests/case2-S.json
|
||||
case3 vvp_tests/case3.json
|
||||
casex_synth vvp_tests/casex_synth.json
|
||||
constfunc16 vvp_tests/constfunc16.json
|
||||
constfunc17 vvp_tests/constfunc17.json
|
||||
constfunc18 vvp_tests/constfunc18.json
|
||||
constfunc19 vvp_tests/constfunc19.json
|
||||
constfunc20 vvp_tests/constfunc20.json
|
||||
dffsynth vvp_tests/dffsynth.json
|
||||
dffsynth-S vvp_tests/dffsynth-S.json
|
||||
dffsynth2 vvp_tests/dffsynth2.json
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"type" : "normal",
|
||||
"source" : "constfunc16.v",
|
||||
"iverilog-args" : [ "-g2009" ]
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"type" : "normal",
|
||||
"source" : "constfunc17.v",
|
||||
"iverilog-args" : [ "-g2009" ]
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"type" : "normal",
|
||||
"source" : "constfunc18.v",
|
||||
"iverilog-args" : [ "-g2009" ]
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"type" : "normal",
|
||||
"source" : "constfunc19.v",
|
||||
"iverilog-args" : [ "-g2009" ]
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"type" : "normal",
|
||||
"source" : "constfunc20.v",
|
||||
"iverilog-args" : [ "-g2009" ]
|
||||
}
|
||||
|
|
@ -32,6 +32,8 @@ using namespace std;
|
|||
* to the target block.
|
||||
*/
|
||||
static const NetScope*disable = 0;
|
||||
static bool loop_break;
|
||||
static bool loop_continue;
|
||||
|
||||
static NetExpr* fix_assign_value(const NetNet*lhs, NetExpr*rhs)
|
||||
{
|
||||
|
|
@ -534,7 +536,7 @@ bool NetBlock::evaluate_function(const LineInfo&loc,
|
|||
|
||||
bool cur_flag = cur->evaluate_function(loc, use_context_map);
|
||||
flag = flag && cur_flag;
|
||||
} while (cur != last_ && !disable);
|
||||
} while (cur != last_ && !disable && !loop_break && !loop_continue);
|
||||
|
||||
if (debug_eval_tree) {
|
||||
cerr << get_fileline() << ": NetBlock::evaluate_function: "
|
||||
|
|
@ -710,6 +712,30 @@ bool NetDisable::evaluate_function(const LineInfo&,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool NetBreak::evaluate_function(const LineInfo&,
|
||||
map<perm_string, LocalVar>&) const
|
||||
{
|
||||
loop_break = true;
|
||||
|
||||
if (debug_eval_tree) {
|
||||
cerr << get_fileline() << ": NetBreak::evaluate_function" << endl;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetContinue::evaluate_function(const LineInfo&,
|
||||
map<perm_string, LocalVar>&) const
|
||||
{
|
||||
loop_continue = true;
|
||||
|
||||
if (debug_eval_tree) {
|
||||
cerr << get_fileline() << ": NetContinue::evaluate_function" << endl;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetDoWhile::evaluate_function(const LineInfo&loc,
|
||||
map<perm_string,LocalVar>&context_map) const
|
||||
{
|
||||
|
|
@ -726,6 +752,13 @@ bool NetDoWhile::evaluate_function(const LineInfo&loc,
|
|||
if (! flag)
|
||||
break;
|
||||
|
||||
if (loop_break) {
|
||||
loop_break = false;
|
||||
break;
|
||||
}
|
||||
|
||||
loop_continue = false;
|
||||
|
||||
// Evaluate the condition expression to try and get the
|
||||
// condition for the loop.
|
||||
NetExpr*cond = cond_->evaluate_function(loc, context_map);
|
||||
|
|
@ -765,6 +798,13 @@ bool NetForever::evaluate_function(const LineInfo&loc,
|
|||
|
||||
while (flag && !disable) {
|
||||
flag = flag && statement_->evaluate_function(loc, context_map);
|
||||
|
||||
if (loop_break) {
|
||||
loop_break = false;
|
||||
break;
|
||||
}
|
||||
|
||||
loop_continue = false;
|
||||
}
|
||||
|
||||
if (debug_eval_tree) {
|
||||
|
|
@ -818,6 +858,13 @@ bool NetForLoop::evaluate_function(const LineInfo&loc,
|
|||
if (disable)
|
||||
break;
|
||||
|
||||
if (loop_break) {
|
||||
loop_break = false;
|
||||
break;
|
||||
}
|
||||
|
||||
loop_continue = false;
|
||||
|
||||
tmp_flag = step_statement_->evaluate_function(loc, context_map);
|
||||
flag &= tmp_flag;
|
||||
}
|
||||
|
|
@ -854,6 +901,13 @@ bool NetRepeat::evaluate_function(const LineInfo&loc,
|
|||
while ((count > 0) && flag && !disable) {
|
||||
flag = flag && statement_->evaluate_function(loc, context_map);
|
||||
count -= 1;
|
||||
|
||||
if (loop_break) {
|
||||
loop_break = false;
|
||||
break;
|
||||
}
|
||||
|
||||
loop_continue = false;
|
||||
}
|
||||
|
||||
if (debug_eval_tree) {
|
||||
|
|
@ -905,6 +959,13 @@ bool NetWhile::evaluate_function(const LineInfo&loc,
|
|||
bool tmp_flag = proc_->evaluate_function(loc, context_map);
|
||||
if (! tmp_flag)
|
||||
flag = false;
|
||||
|
||||
if (loop_break) {
|
||||
loop_break = false;
|
||||
break;
|
||||
}
|
||||
|
||||
loop_continue = false;
|
||||
}
|
||||
|
||||
if (debug_eval_tree) {
|
||||
|
|
|
|||
|
|
@ -3068,6 +3068,8 @@ class NetBreak : public NetProc {
|
|||
public:
|
||||
virtual void dump(std::ostream&, unsigned ind) const;
|
||||
virtual bool emit_proc(struct target_t*) const;
|
||||
bool evaluate_function(const LineInfo &loc,
|
||||
std::map<perm_string,LocalVar> &ctx) const final;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -3222,6 +3224,8 @@ class NetContinue : public NetProc {
|
|||
public:
|
||||
virtual void dump(std::ostream&, unsigned ind) const;
|
||||
virtual bool emit_proc(struct target_t*) const;
|
||||
bool evaluate_function(const LineInfo &loc,
|
||||
std::map<perm_string,LocalVar> &ctx) const final;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
|||
Loading…
Reference in New Issue