aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClifford Wolf <clifford@clifford.at>2016-08-22 14:27:46 +0200
committerClifford Wolf <clifford@clifford.at>2016-08-22 14:27:46 +0200
commit450f6f59b494af14014f0cbe93df4ceca0eecd76 (patch)
tree783ba57115992f646da109c722237060d8033689
parentcad40fc87449e69a086a627bfb25aa49ae400753 (diff)
downloadyosys-450f6f59b494af14014f0cbe93df4ceca0eecd76.tar.gz
yosys-450f6f59b494af14014f0cbe93df4ceca0eecd76.tar.bz2
yosys-450f6f59b494af14014f0cbe93df4ceca0eecd76.zip
Fixed bug with memories that do not have a down-to-zero data width
-rw-r--r--frontends/ast/simplify.cc15
-rw-r--r--tests/simple/memory.v30
2 files changed, 43 insertions, 2 deletions
diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc
index c957389c3..a8fea8211 100644
--- a/frontends/ast/simplify.cc
+++ b/frontends/ast/simplify.cc
@@ -883,11 +883,14 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
int mem_width, mem_size, addr_bits;
id2ast->meminfo(mem_width, mem_size, addr_bits);
+ int data_range_left = id2ast->children[0]->range_left;
+ int data_range_right = id2ast->children[0]->range_right;
+
std::stringstream sstr;
- sstr << "$mem2bits$" << children[0]->str << "$" << filename << ":" << linenum << "$" << (autoidx++);
+ sstr << "$mem2bits$" << str << "$" << filename << ":" << linenum << "$" << (autoidx++);
std::string wire_id = sstr.str();
- AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(mem_width-1, true), mkconst_int(0, true)));
+ AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(data_range_left, true), mkconst_int(data_range_right, true)));
wire->str = wire_id;
if (current_block)
wire->attributes["\\nosync"] = AstNode::mkconst_int(1, false);
@@ -1491,6 +1494,10 @@ skip_dynamic_range_lvalue_expansion:;
int mem_width, mem_size, addr_bits;
children[0]->id2ast->meminfo(mem_width, mem_size, addr_bits);
+ int data_range_left = children[0]->id2ast->children[0]->range_left;
+ int data_range_right = children[0]->id2ast->children[0]->range_right;
+ int mem_data_range_offset = std::min(data_range_left, data_range_right);
+
int addr_width_hint = -1;
bool addr_sign_hint = true;
children[0]->children[0]->children[0]->detectSignWidthWorker(addr_width_hint, addr_sign_hint);
@@ -1553,6 +1560,7 @@ skip_dynamic_range_lvalue_expansion:;
{
int offset = children[0]->children[1]->range_right;
int width = children[0]->children[1]->range_left - offset + 1;
+ offset -= mem_data_range_offset;
std::vector<RTLIL::State> padding_x(offset, RTLIL::State::Sx);
@@ -1574,6 +1582,9 @@ skip_dynamic_range_lvalue_expansion:;
AstNode *right_at_zero_ast = the_range->children.size() >= 2 ? the_range->children[1]->clone() : left_at_zero_ast->clone();
AstNode *offset_ast = right_at_zero_ast->clone();
+ if (mem_data_range_offset)
+ offset_ast = new AstNode(AST_SUB, offset_ast, mkconst_int(mem_data_range_offset, true));
+
while (left_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { }
while (right_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { }
if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT)
diff --git a/tests/simple/memory.v b/tests/simple/memory.v
index 61b36e79a..f38bdafd3 100644
--- a/tests/simple/memory.v
+++ b/tests/simple/memory.v
@@ -277,3 +277,33 @@ module memtest12 (
{ram[adr], q} <= {din, ram[adr]};
endmodule
+// ----------------------------------------------------------
+
+module memtest13 (
+ input clk, rst,
+ input [1:0] a1, a2, a3, a4, a5, a6,
+ input [3:0] off1, off2,
+ input [31:5] din1,
+ input [3:0] din2, din3,
+ output reg [3:0] dout1, dout2,
+ output reg [31:5] dout3
+);
+ reg [31:5] mem [0:3];
+
+ always @(posedge clk) begin
+ if (rst) begin
+ mem[0] <= 0;
+ mem[1] <= 0;
+ mem[2] <= 0;
+ mem[3] <= 0;
+ end else begin
+ mem[a1] <= din1;
+ mem[a2][14:11] <= din2;
+ mem[a3][5 + off1 +: 4] <= din3;
+ dout1 <= mem[a4][12:9];
+ dout2 <= mem[a5][5 + off2 +: 4];
+ dout3 <= mem[a6];
+ end
+ end
+endmodule
+