Fixed bug with memories that do not have a down-to-zero data width
authorClifford Wolf <clifford@clifford.at>
Mon, 22 Aug 2016 12:27:46 +0000 (14:27 +0200)
committerClifford Wolf <clifford@clifford.at>
Mon, 22 Aug 2016 12:27:46 +0000 (14:27 +0200)
frontends/ast/simplify.cc
tests/simple/memory.v

index c957389c342a5f1e17c0f8ffeeb020753cb0e155..a8fea821116dc19dd57f3c6d8198f595070ac2ca 100644 (file)
@@ -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)
index 61b36e79a25bf8c9b1cc8c19ac482c59ea1db82f..f38bdafd3ebf0046005952f6f8baa3512a9c5af0 100644 (file)
@@ -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
+