mirror of https://github.com/YosysHQ/yosys.git
Merge pull request #2594 from zachjs/func-arg-width
verilog: fix sizing of constant args for tasks/functions
This commit is contained in:
commit
ad2960adb7
|
@ -263,7 +263,13 @@ namespace AST
|
||||||
bool detect_latch(const std::string &var);
|
bool detect_latch(const std::string &var);
|
||||||
|
|
||||||
// additional functionality for evaluating constant functions
|
// additional functionality for evaluating constant functions
|
||||||
struct varinfo_t { RTLIL::Const val; int offset; bool is_signed; };
|
struct varinfo_t {
|
||||||
|
RTLIL::Const val;
|
||||||
|
int offset;
|
||||||
|
bool is_signed;
|
||||||
|
AstNode *arg = nullptr;
|
||||||
|
bool explicitly_sized;
|
||||||
|
};
|
||||||
bool has_const_only_constructs();
|
bool has_const_only_constructs();
|
||||||
bool replace_variables(std::map<std::string, varinfo_t> &variables, AstNode *fcall, bool must_succeed);
|
bool replace_variables(std::map<std::string, varinfo_t> &variables, AstNode *fcall, bool must_succeed);
|
||||||
AstNode *eval_const_function(AstNode *fcall, bool must_succeed);
|
AstNode *eval_const_function(AstNode *fcall, bool must_succeed);
|
||||||
|
|
|
@ -3403,6 +3403,8 @@ skip_dynamic_range_lvalue_expansion:;
|
||||||
range->children.push_back(mkconst_int(0, true));
|
range->children.push_back(mkconst_int(0, true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// updates the sizing
|
||||||
|
while (wire->simplify(true, false, false, 1, -1, false, false)) { }
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
AstNode *wire_id = new AstNode(AST_IDENTIFIER);
|
AstNode *wire_id = new AstNode(AST_IDENTIFIER);
|
||||||
|
@ -4603,17 +4605,29 @@ AstNode *AstNode::eval_const_function(AstNode *fcall, bool must_succeed)
|
||||||
log_file_error(stmt->filename, stmt->location.first_line, "Can't determine size of variable %s\n%s:%d.%d-%d.%d: ... called from here.\n",
|
log_file_error(stmt->filename, stmt->location.first_line, "Can't determine size of variable %s\n%s:%d.%d-%d.%d: ... called from here.\n",
|
||||||
stmt->str.c_str(), fcall->filename.c_str(), fcall->location.first_line, fcall->location.first_column, fcall->location.last_line, fcall->location.last_column);
|
stmt->str.c_str(), fcall->filename.c_str(), fcall->location.first_line, fcall->location.first_column, fcall->location.last_line, fcall->location.last_column);
|
||||||
}
|
}
|
||||||
variables[stmt->str].val = RTLIL::Const(RTLIL::State::Sx, abs(stmt->range_left - stmt->range_right)+1);
|
AstNode::varinfo_t &variable = variables[stmt->str];
|
||||||
variables[stmt->str].offset = min(stmt->range_left, stmt->range_right);
|
int width = abs(stmt->range_left - stmt->range_right) + 1;
|
||||||
variables[stmt->str].is_signed = stmt->is_signed;
|
// if this variable has already been declared as an input, check the
|
||||||
|
// sizes match if it already had an explicit size
|
||||||
|
if (variable.arg && variable.explicitly_sized && variable.val.size() != width) {
|
||||||
|
log_file_error(filename, location.first_line, "Incompatible re-declaration of constant function wire %s.\n", stmt->str.c_str());
|
||||||
|
}
|
||||||
|
variable.val = RTLIL::Const(RTLIL::State::Sx, width);
|
||||||
|
variable.offset = min(stmt->range_left, stmt->range_right);
|
||||||
|
variable.is_signed = stmt->is_signed;
|
||||||
|
variable.explicitly_sized = stmt->children.size() &&
|
||||||
|
stmt->children.back()->type == AST_RANGE;
|
||||||
|
// identify the argument corresponding to this wire, if applicable
|
||||||
if (stmt->is_input && argidx < fcall->children.size()) {
|
if (stmt->is_input && argidx < fcall->children.size()) {
|
||||||
int width = variables[stmt->str].val.bits.size();
|
variable.arg = fcall->children.at(argidx++);
|
||||||
auto* arg_node = fcall->children.at(argidx++);
|
}
|
||||||
if (arg_node->type == AST_CONSTANT) {
|
// load the constant arg's value into this variable
|
||||||
variables[stmt->str].val = arg_node->bitsAsConst(width);
|
if (variable.arg) {
|
||||||
|
if (variable.arg->type == AST_CONSTANT) {
|
||||||
|
variable.val = variable.arg->bitsAsConst(width);
|
||||||
} else {
|
} else {
|
||||||
log_assert(arg_node->type == AST_REALVALUE);
|
log_assert(variable.arg->type == AST_REALVALUE);
|
||||||
variables[stmt->str].val = arg_node->realAsConst(width);
|
variable.val = variable.arg->realAsConst(width);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
current_scope[stmt->str] = stmt;
|
current_scope[stmt->str] = stmt;
|
||||||
|
|
|
@ -20,11 +20,11 @@ module top;
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function automatic [31:0] operation2;
|
function automatic [31:0] operation2;
|
||||||
input [4:0] var;
|
input [4:0] inp;
|
||||||
input integer num;
|
input integer num;
|
||||||
begin
|
begin
|
||||||
var[0] = var[0] ^ 1;
|
inp[0] = inp[0] ^ 1;
|
||||||
operation2 = num * var;
|
operation2 = num * inp;
|
||||||
end
|
end
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
@ -79,15 +79,14 @@ module top;
|
||||||
wire [31:0] x5;
|
wire [31:0] x5;
|
||||||
assign x5 = operation5(64);
|
assign x5 = operation5(64);
|
||||||
|
|
||||||
// `define VERIFY
|
always_comb begin
|
||||||
`ifdef VERIFY
|
assert(a == 2);
|
||||||
assert property (a == 2);
|
assert(A == 3);
|
||||||
assert property (A == 3);
|
assert(x1 == 16);
|
||||||
assert property (x1 == 16);
|
assert(x1b == 16);
|
||||||
assert property (x1b == 16);
|
assert(x2 == 4);
|
||||||
assert property (x2 == 4);
|
assert(x3 == 16);
|
||||||
assert property (x3 == 16);
|
assert(x4 == a << 1);
|
||||||
assert property (x4 == a << 1);
|
assert(x5 == 64);
|
||||||
assert property (x5 == 64);
|
end
|
||||||
`endif
|
|
||||||
endmodule
|
endmodule
|
|
@ -1 +1,6 @@
|
||||||
read_verilog const_arg_loop.v
|
read_verilog -sv const_arg_loop.sv
|
||||||
|
hierarchy
|
||||||
|
proc
|
||||||
|
opt -full
|
||||||
|
select -module top
|
||||||
|
sat -verify -seq 1 -tempinduct -prove-asserts -show-all
|
||||||
|
|
|
@ -62,26 +62,25 @@ module top(out);
|
||||||
localparam signed Y = $floor(W / X);
|
localparam signed Y = $floor(W / X);
|
||||||
localparam signed Z = negate($floor(W / X));
|
localparam signed Z = negate($floor(W / X));
|
||||||
|
|
||||||
// `define VERIFY
|
always_comb begin
|
||||||
`ifdef VERIFY
|
assert(a1 == 0);
|
||||||
assert property (a1 == 0);
|
assert(a2 == 0);
|
||||||
assert property (a2 == 0);
|
assert(a3 == "BAR");
|
||||||
assert property (a3 == "BAR");
|
assert(a4 == 0);
|
||||||
assert property (a4 == 0);
|
assert(b1 == "FOO");
|
||||||
assert property (b1 == "FOO");
|
assert(b2 == "FOO");
|
||||||
assert property (b2 == "FOO");
|
assert(b3 == 0);
|
||||||
assert property (b3 == 0);
|
assert(b4 == "HI");
|
||||||
assert property (b4 == "HI");
|
assert(c1 == 1);
|
||||||
assert property (c1 == 1);
|
assert(c2 == 1);
|
||||||
assert property (c2 == 1);
|
assert(c3 == 0);
|
||||||
assert property (c3 == 0);
|
assert(c4 == 0);
|
||||||
assert property (c4 == 0);
|
assert(d1 == 0);
|
||||||
assert property (d1 == 0);
|
assert(d2 == 0);
|
||||||
assert property (d2 == 0);
|
assert(d3 == 1);
|
||||||
assert property (d3 == 1);
|
assert(d4 == 1);
|
||||||
assert property (d4 == 1);
|
|
||||||
|
|
||||||
assert property (Y == 3);
|
assert(Y == 3);
|
||||||
assert property (Z == ~3);
|
assert(Z == ~3);
|
||||||
`endif
|
end
|
||||||
endmodule
|
endmodule
|
|
@ -1 +1,7 @@
|
||||||
read_verilog const_func.v
|
read_verilog -sv const_func.sv
|
||||||
|
hierarchy
|
||||||
|
proc
|
||||||
|
flatten
|
||||||
|
opt -full
|
||||||
|
select -module top
|
||||||
|
sat -verify -seq 1 -tempinduct -prove-asserts -show-all
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
logger -expect error "Incompatible re-declaration of wire" 1
|
||||||
|
read_verilog -sv <<EOT
|
||||||
|
module top;
|
||||||
|
function automatic integer f;
|
||||||
|
input [0:0] inp;
|
||||||
|
integer inp;
|
||||||
|
f = inp;
|
||||||
|
endfunction
|
||||||
|
integer x, y;
|
||||||
|
initial x = f(y);
|
||||||
|
endmodule
|
||||||
|
EOT
|
|
@ -0,0 +1,12 @@
|
||||||
|
logger -expect error "Incompatible re-declaration of constant function wire" 1
|
||||||
|
read_verilog -sv <<EOT
|
||||||
|
module top;
|
||||||
|
function automatic integer f;
|
||||||
|
input [0:0] inp;
|
||||||
|
integer inp;
|
||||||
|
f = inp;
|
||||||
|
endfunction
|
||||||
|
integer x;
|
||||||
|
initial x = f(0);
|
||||||
|
endmodule
|
||||||
|
EOT
|
|
@ -0,0 +1,12 @@
|
||||||
|
logger -expect error "Incompatible re-declaration of wire" 1
|
||||||
|
read_verilog -sv <<EOT
|
||||||
|
module top;
|
||||||
|
function automatic integer f;
|
||||||
|
input [1:0] inp;
|
||||||
|
integer inp;
|
||||||
|
f = inp;
|
||||||
|
endfunction
|
||||||
|
integer x, y;
|
||||||
|
initial x = f(y);
|
||||||
|
endmodule
|
||||||
|
EOT
|
|
@ -0,0 +1,12 @@
|
||||||
|
logger -expect error "Incompatible re-declaration of constant function wire" 1
|
||||||
|
read_verilog -sv <<EOT
|
||||||
|
module top;
|
||||||
|
function automatic integer f;
|
||||||
|
input [1:0] inp;
|
||||||
|
integer inp;
|
||||||
|
f = inp;
|
||||||
|
endfunction
|
||||||
|
integer x;
|
||||||
|
initial x = f(0);
|
||||||
|
endmodule
|
||||||
|
EOT
|
Loading…
Reference in New Issue