mirror of https://github.com/YosysHQ/yosys.git
verilog: fix const func eval with upto variables
This commit is contained in:
parent
ca876e7c12
commit
90bb47d181
|
@ -5,6 +5,10 @@ List of major changes and improvements between releases
|
||||||
Yosys 0.14 .. Yosys 0.14-dev
|
Yosys 0.14 .. Yosys 0.14-dev
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
|
* Verilog
|
||||||
|
- Fixed evaluation of constant functions with variables or arguments with
|
||||||
|
reversed dimensions
|
||||||
|
|
||||||
Yosys 0.13 .. Yosys 0.14
|
Yosys 0.13 .. Yosys 0.14
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
|
|
|
@ -268,6 +268,7 @@ namespace AST
|
||||||
struct varinfo_t {
|
struct varinfo_t {
|
||||||
RTLIL::Const val;
|
RTLIL::Const val;
|
||||||
int offset;
|
int offset;
|
||||||
|
bool range_swapped;
|
||||||
bool is_signed;
|
bool is_signed;
|
||||||
AstNode *arg = nullptr;
|
AstNode *arg = nullptr;
|
||||||
bool explicitly_sized;
|
bool explicitly_sized;
|
||||||
|
|
|
@ -5134,6 +5134,8 @@ bool AstNode::replace_variables(std::map<std::string, AstNode::varinfo_t> &varia
|
||||||
width = min(std::abs(children.at(0)->range_left - children.at(0)->range_right) + 1, width);
|
width = min(std::abs(children.at(0)->range_left - children.at(0)->range_right) + 1, width);
|
||||||
}
|
}
|
||||||
offset -= variables.at(str).offset;
|
offset -= variables.at(str).offset;
|
||||||
|
if (variables.at(str).range_swapped)
|
||||||
|
offset = -offset;
|
||||||
std::vector<RTLIL::State> &var_bits = variables.at(str).val.bits;
|
std::vector<RTLIL::State> &var_bits = variables.at(str).val.bits;
|
||||||
std::vector<RTLIL::State> new_bits(var_bits.begin() + offset, var_bits.begin() + offset + width);
|
std::vector<RTLIL::State> new_bits(var_bits.begin() + offset, var_bits.begin() + offset + width);
|
||||||
AstNode *newNode = mkconst_bits(new_bits, variables.at(str).is_signed);
|
AstNode *newNode = mkconst_bits(new_bits, variables.at(str).is_signed);
|
||||||
|
@ -5191,7 +5193,8 @@ AstNode *AstNode::eval_const_function(AstNode *fcall, bool must_succeed)
|
||||||
log_file_error(filename, location.first_line, "Incompatible re-declaration of constant function wire %s.\n", stmt->str.c_str());
|
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.val = RTLIL::Const(RTLIL::State::Sx, width);
|
||||||
variable.offset = min(stmt->range_left, stmt->range_right);
|
variable.offset = stmt->range_swapped ? stmt->range_left : stmt->range_right;
|
||||||
|
variable.range_swapped = stmt->range_swapped;
|
||||||
variable.is_signed = stmt->is_signed;
|
variable.is_signed = stmt->is_signed;
|
||||||
variable.explicitly_sized = stmt->children.size() &&
|
variable.explicitly_sized = stmt->children.size() &&
|
||||||
stmt->children.back()->type == AST_RANGE;
|
stmt->children.back()->type == AST_RANGE;
|
||||||
|
@ -5276,8 +5279,12 @@ AstNode *AstNode::eval_const_function(AstNode *fcall, bool must_succeed)
|
||||||
int width = std::abs(range->range_left - range->range_right) + 1;
|
int width = std::abs(range->range_left - range->range_right) + 1;
|
||||||
varinfo_t &v = variables[stmt->children.at(0)->str];
|
varinfo_t &v = variables[stmt->children.at(0)->str];
|
||||||
RTLIL::Const r = stmt->children.at(1)->bitsAsConst(v.val.bits.size());
|
RTLIL::Const r = stmt->children.at(1)->bitsAsConst(v.val.bits.size());
|
||||||
for (int i = 0; i < width; i++)
|
for (int i = 0; i < width; i++) {
|
||||||
v.val.bits.at(i+offset-v.offset) = r.bits.at(i);
|
int index = i + offset - v.offset;
|
||||||
|
if (v.range_swapped)
|
||||||
|
index = -index;
|
||||||
|
v.val.bits.at(index) = r.bits.at(i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
delete block->children.front();
|
delete block->children.front();
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
`default_nettype none
|
||||||
|
|
||||||
|
module evil;
|
||||||
|
parameter HI = 3;
|
||||||
|
parameter LO = 0;
|
||||||
|
parameter SPAN = 1;
|
||||||
|
parameter [HI:LO] A_VAL = 4'b0110;
|
||||||
|
parameter [HI:LO] B_VAL = 4'b1100;
|
||||||
|
parameter [2:0] SWAPS = 0;
|
||||||
|
|
||||||
|
localparam D_LEFT = !(SWAPS[0]) ? HI : LO;
|
||||||
|
localparam D_RIGHT = (SWAPS[0]) ? HI : LO;
|
||||||
|
localparam E_LEFT = !(SWAPS[1]) ? HI : LO;
|
||||||
|
localparam E_RIGHT = (SWAPS[1]) ? HI : LO;
|
||||||
|
localparam F_LEFT = !(SWAPS[2]) ? HI : LO;
|
||||||
|
localparam F_RIGHT = (SWAPS[2]) ? HI : LO;
|
||||||
|
|
||||||
|
localparam [HI:LO] A_CONST = A_VAL;
|
||||||
|
localparam [HI:LO] B_CONST = B_VAL;
|
||||||
|
localparam [HI:LO] C_CONST = F(A_CONST, B_CONST);
|
||||||
|
|
||||||
|
reg [HI:LO] C_WIRE, C_FUNC;
|
||||||
|
always @* begin
|
||||||
|
assert (C_CONST == C_WIRE);
|
||||||
|
assert (C_CONST == C_FUNC);
|
||||||
|
end
|
||||||
|
|
||||||
|
initial begin : blk
|
||||||
|
reg [HI:LO] A_WIRE;
|
||||||
|
reg [HI:LO] B_WIRE;
|
||||||
|
reg [D_LEFT:D_RIGHT] D;
|
||||||
|
reg [E_LEFT:E_RIGHT] E;
|
||||||
|
reg [F_LEFT:F_RIGHT] F_WIRE;
|
||||||
|
reg [31:0] i;
|
||||||
|
A_WIRE = A_VAL;
|
||||||
|
B_WIRE = B_VAL;
|
||||||
|
D = A_WIRE;
|
||||||
|
E = B_WIRE;
|
||||||
|
F_WIRE = 0;
|
||||||
|
for (i = LO; i + SPAN < HI; i = i + SPAN)
|
||||||
|
if (SPAN == 1)
|
||||||
|
F_WIRE[i] = D[i] && E[i];
|
||||||
|
else
|
||||||
|
F_WIRE[i+:SPAN] = D[i+:SPAN] && E[i+:SPAN];
|
||||||
|
C_WIRE = F_WIRE;
|
||||||
|
C_FUNC = F(A_WIRE, B_WIRE);
|
||||||
|
end
|
||||||
|
|
||||||
|
function automatic [F_LEFT:F_RIGHT] F(
|
||||||
|
input [D_LEFT:D_RIGHT] D,
|
||||||
|
input [E_LEFT:E_RIGHT] E);
|
||||||
|
reg [31:0] i;
|
||||||
|
F = 0;
|
||||||
|
for (i = LO; i + SPAN < HI; i = i + SPAN)
|
||||||
|
if (SPAN == 1)
|
||||||
|
F[i] = D[i] && E[i];
|
||||||
|
else
|
||||||
|
F[i+:SPAN] = D[i+:SPAN] && E[i+:SPAN];
|
||||||
|
endfunction
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module top;
|
||||||
|
for (genvar hi = 0; hi < 3; hi++)
|
||||||
|
for (genvar lo = 0; lo <= hi; lo++)
|
||||||
|
for (genvar span = 1; span <= hi - lo + 1; span++)
|
||||||
|
for (genvar a_val = 0; a_val < 2 ** (hi - lo + 1); a_val++)
|
||||||
|
for (genvar b_val = 0; b_val < 2 ** (hi - lo + 1); b_val++)
|
||||||
|
for (genvar swaps = 0; swaps < 2 ** 3; swaps++)
|
||||||
|
evil #(
|
||||||
|
.HI(hi),
|
||||||
|
.LO(lo),
|
||||||
|
.SPAN(span),
|
||||||
|
.A_VAL(a_val),
|
||||||
|
.B_VAL(b_val),
|
||||||
|
.SWAPS(swaps)
|
||||||
|
) e();
|
||||||
|
endmodule
|
|
@ -0,0 +1,7 @@
|
||||||
|
read_verilog -sv func_upto.sv
|
||||||
|
hierarchy -top top
|
||||||
|
proc
|
||||||
|
flatten
|
||||||
|
opt -full
|
||||||
|
select -module top
|
||||||
|
sat -verify -seq 1 -prove-asserts -enable_undef
|
Loading…
Reference in New Issue