mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-11-04 13:29:12 +00:00 
			
		
		
		
	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
					
				
					 4 changed files with 94 additions and 5 deletions
				
			
		| 
						 | 
				
			
			@ -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
 | 
			
		||||
		{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										19
									
								
								tests/simple/mem2reg_bounds_tern.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								tests/simple/mem2reg_bounds_tern.v
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -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
 | 
			
		||||
							
								
								
									
										27
									
								
								tests/verilog/mem_bounds.sv
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								tests/verilog/mem_bounds.sv
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -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
 | 
			
		||||
							
								
								
									
										6
									
								
								tests/verilog/mem_bounds.ys
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								tests/verilog/mem_bounds.ys
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -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…
	
	Add table
		Add a link
		
	
		Reference in a new issue