mem.v 2.45 KB
// mem.v
// common memory/cpu tasks;
// :set tabstop=4

// monitor memory backdoor;

reg mem_mon;
reg mirror;

initial
begin
	$display("%M: ri_model memory backdoor");
	mem_mon = $test$plusargs("mem_mon");
	mirror = 0;
end

// make single byte mask from address and size;

function [31:0] sgl_mask;
	input [1:0] addr;		// requests address;
	input [1:0] size;		// request size;
	reg [31:0] mask;		// data compare mask;
	begin
		case({size,addr})
			4'b0000: mask = 32'hff000000;
			4'b0001: mask = 32'h00ff0000;
			4'b0010: mask = 32'h0000ff00;
			4'b0011: mask = 32'h000000ff;
			4'b0100: mask = 32'hffff0000;
			4'b0110: mask = 32'h0000ffff;
			4'b1000: mask = 32'hffffff00;
			4'b1001: mask = 32'h00ffffff;
			4'b1100: mask = 32'hffffffff;
			default: begin
					mask = 32'h00000000;
					$display("ERROR: %t: %M: illegal addr %b, size %b", $time, addr, size);
				end
		endcase
		sgl_mask = mask;
	end
endfunction

// check memory address;
// 0x8000_0000 ... 0xffff_ffff  x64 high space, 2GBytes;
// 0x0100_0000 ... 0x02ff_ffff  x64 low space, 32MBytes;
// 0x0000_0000 ... 0x00ff_ffff  x36 space, lower 16MBytes;

task mem_check_addr;
	input [31:0] addr;	// address, possibly mirrored;
	input mirror;		// enable mirror mapping;
	output x36;			// is a x36 address;
	output valid;		// address is valid;
	reg [31:24] spc;
	integer size;
	begin
		spc = addr[31:24];
		valid = 0;
		if(spc === 'h00) begin
			valid = 1;
			x36 = 1;
		end else if((spc === 'h01) | (spc === 'h02)) begin
			valid = 1;
			x36 = 0;
			addr[31:24] = addr[31:24] - 1;
		end else if(spc[31] === 1) begin
			valid = (spc[31:30] == 2'b10);
			x36 = 0;
			addr[31] = 0;
		end
		if(valid) begin
			size = MEM_SIZE;
			if(x36)
				size = size >> 1;
			if(!mirror & (addr >= size))
				valid = 0;
		end
		if( !valid)
			$display("ERROR: %t: ri: addr 0x%h outside memory", $time, addr);
	end
endtask

task mem_check9;
	input [31:0] addr;
	input [31:0] words;
	integer i;
	reg [31:0] check_addr;
	reg [31:0] word0, word1;
	
	begin
		check_addr = addr & 32'hFFFFFFFC;
		if (addr < 32'h01000000) begin /* x36 space */
			for (i=0; i< words; i=i+1) begin
				mem_sread(check_addr, 3, word0);
				mem_sread(((check_addr<<1) | 32'h01000000) + 4, 3, word1);
				if (word0[0] !== word1[0] || word0[0] != word1[8] ||
					word0[16] !== word1[16] || word0[16] != word1[24]) begin
						$display("ERROR: %t 9th bits wrong 0x%x <0x%x> at", 
								 $time, word0, word1, check_addr );
				end
				check_addr = check_addr + 4;
			end
		end
	end
endtask