mirror of https://github.com/YosysHQ/yosys.git
mem2reg: tolerate out of bounds constant accesses
This brings the mem2reg behavior in line with the nomem2reg behavior.
This commit is contained in:
parent
d9f11bb7a6
commit
c79fbfe0a1
|
@ -1762,7 +1762,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
|
|||
}
|
||||
|
||||
// split memory access with bit select to individual statements
|
||||
if (type == AST_IDENTIFIER && children.size() == 2 && children[0]->type == AST_RANGE && children[1]->type == AST_RANGE && !in_lvalue)
|
||||
if (type == AST_IDENTIFIER && children.size() == 2 && children[0]->type == AST_RANGE && children[1]->type == AST_RANGE && !in_lvalue && stage == 2)
|
||||
{
|
||||
if (id2ast == NULL || id2ast->type != AST_MEMORY || children[0]->children.size() != 1)
|
||||
log_file_error(filename, location.first_line, "Invalid bit-select on memory access!\n");
|
||||
|
@ -4501,11 +4501,48 @@ bool AstNode::mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod,
|
|||
if (children[0]->children[0]->type == AST_CONSTANT)
|
||||
{
|
||||
int id = children[0]->children[0]->integer;
|
||||
str = stringf("%s[%d]", str.c_str(), id);
|
||||
int left = id2ast->children[1]->children[0]->integer;
|
||||
int right = id2ast->children[1]->children[1]->integer;
|
||||
bool valid_const_access =
|
||||
(left <= id && id <= right) ||
|
||||
(right <= id && id <= left);
|
||||
if (valid_const_access)
|
||||
{
|
||||
str = stringf("%s[%d]", str.c_str(), id);
|
||||
delete_children();
|
||||
range_valid = false;
|
||||
id2ast = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
int width;
|
||||
if (bit_part_sel)
|
||||
{
|
||||
bit_part_sel->dumpAst(nullptr, "? ");
|
||||
if (bit_part_sel->children.size() == 1)
|
||||
width = 0;
|
||||
else
|
||||
width = bit_part_sel->children[0]->integer -
|
||||
bit_part_sel->children[1]->integer;
|
||||
delete bit_part_sel;
|
||||
bit_part_sel = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
width = id2ast->children[0]->children[0]->integer -
|
||||
id2ast->children[0]->children[1]->integer;
|
||||
}
|
||||
width = abs(width) + 1;
|
||||
|
||||
delete_children();
|
||||
range_valid = false;
|
||||
id2ast = NULL;
|
||||
delete_children();
|
||||
|
||||
std::vector<RTLIL::State> x_bits;
|
||||
for (int i = 0; i < width; i++)
|
||||
x_bits.push_back(RTLIL::State::Sx);
|
||||
AstNode *constant = AstNode::mkconst_bits(x_bits, false);
|
||||
constant->cloneInto(this);
|
||||
delete constant;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
module top(
|
||||
input clk,
|
||||
input wire [1:0] sel,
|
||||
input wire [7:0] base,
|
||||
output reg [7:0] line
|
||||
);
|
||||
reg [0:7] mem [0:2];
|
||||
|
||||
generate
|
||||
genvar i;
|
||||
for (i = 0; i < 4; i = i + 1) begin : gen
|
||||
always @(posedge clk)
|
||||
mem[i] <= i == 0 ? base : mem[i - 1] + 1;
|
||||
end
|
||||
endgenerate
|
||||
|
||||
always @(posedge clk)
|
||||
line = mem[sel];
|
||||
endmodule
|
|
@ -0,0 +1,27 @@
|
|||
module top;
|
||||
reg [0:7] mem [0:2];
|
||||
|
||||
initial mem[1] = '1;
|
||||
wire [31:0] a, b, c, d;
|
||||
assign a = mem[1];
|
||||
assign b = mem[-1];
|
||||
assign c = mem[-1][0];
|
||||
assign d = mem[-1][0:1];
|
||||
|
||||
always @* begin
|
||||
|
||||
assert ($countbits(a, '0) == 24);
|
||||
assert ($countbits(a, '1) == 8);
|
||||
assert ($countbits(a, 'x) == 0);
|
||||
|
||||
assert ($countbits(b, '0) == 24);
|
||||
assert ($countbits(b, 'x) == 8);
|
||||
|
||||
assert ($countbits(c, '0) == 31);
|
||||
assert ($countbits(c, 'x) == 1);
|
||||
|
||||
assert ($countbits(d, '0) == 30);
|
||||
assert ($countbits(d, 'x) == 2);
|
||||
|
||||
end
|
||||
endmodule
|
|
@ -0,0 +1,6 @@
|
|||
read_verilog -sv -mem2reg mem_bounds.sv
|
||||
proc
|
||||
flatten
|
||||
opt -full
|
||||
select -module top
|
||||
sat -verify -seq 1 -tempinduct -prove-asserts -show-all -enable_undef
|
Loading…
Reference in New Issue