mem_ri_model.v 4.7 KB
// mem_ri_model.v v1 Frank Berndt
// memory backdoor tasks to ri_model;
// supposed to be included on top level simulation;
// :set tabstop=4

// below tasks are compatible with the cpu bus interface task;
// this allows running with either of them to setup or check memory;

// single write to memory backdoor;
// extent bits are set to x in x36 space;

task mem_swrite;
	input [31:0] addr;
	input [1:0] size;
	input [31:0] data;

	reg x36, valid;
	reg [31:0] mask;
	reg [63:0] mdata;
	reg lhw;
	begin
		if(mem_mon)
			$display("%t: %M: addr 0x%h data 0x%h", $time, addr, data);
		mem_check_addr(addr, x36, valid);
		if(valid) begin
			mask = sgl_mask(addr[1:0], size);
			if(x36) begin
				addr = addr >> 2;
				mdata = vsim.bb.bcp.ri.mem[addr];
				mdata[63:32] = (mdata[63:32] & ~mask) | (data & mask);
				mdata[31:0] = 32'bx;
				vsim.bb.bcp.ri.mem[addr] = mdata;
			end else begin
				lhw = addr[2];
				addr = addr >> 3;
				mdata = vsim.bb.bcp.ri.mem[addr];
				if(lhw)
					mdata[31:0] = (mdata[31:0] & ~mask) | (data & mask);
				else
					mdata[63:32] = (mdata[63:32] & ~mask) | (data & mask);
				vsim.bb.bcp.ri.mem[addr] = mdata;
			end
		end
	end
endtask

// block write to memory backdoor;
// extent bits are set to x in x36 space;

task mem_bwrite;
	input [31:0] addr;
	input [1:0] size;
	input [31:0] d0, d1, d2, d3, d4, d5, d6, d7;

	reg x36, valid;
	begin
		if(mem_mon)
			$display("%t: %M: addr 0x%h size %b", $time, addr, size);
		case(size)
			2'b00, 2'b01, 2'b10: ;
			default:
				$display("ERROR: %t: %M: illegal size", $time, size);
		endcase
		mem_check_addr(addr, x36, valid);
		if(valid) begin
			d0 = d0 & 32'hffff_ffff;     // make z to x
			d1 = d1 & 32'hffff_ffff;
			d2 = d2 & 32'hffff_ffff;
			d3 = d3 & 32'hffff_ffff;
			d4 = d4 & 32'hffff_ffff;
			d5 = d5 & 32'hffff_ffff;
			d6 = d6 & 32'hffff_ffff;
			d7 = d7 & 32'hffff_ffff;
			if(x36) begin
				addr = addr >> 2;
				vsim.bb.bcp.ri.mem[addr+0] = { d0, 32'bx };
				vsim.bb.bcp.ri.mem[addr+1] = { d1, 32'bx };
				if(|size) begin
					vsim.bb.bcp.ri.mem[addr+2] = { d2, 32'bx };
					vsim.bb.bcp.ri.mem[addr+3] = { d3, 32'bx };
				end
				if(size[1]) begin
					vsim.bb.bcp.ri.mem[addr+4] = { d4, 32'bx };
					vsim.bb.bcp.ri.mem[addr+5] = { d5, 32'bx };
					vsim.bb.bcp.ri.mem[addr+6] = { d6, 32'bx };
					vsim.bb.bcp.ri.mem[addr+7] = { d7, 32'bx };
				end
			end else begin
				addr = addr >> 3;
				vsim.bb.bcp.ri.mem[addr+0] = { d0, d1 };
				if(|size)
					vsim.bb.bcp.ri.mem[addr+1] = { d2, d3 };
				if(size[1]) begin
					vsim.bb.bcp.ri.mem[addr+2] = { d4, d5 };
					vsim.bb.bcp.ri.mem[addr+3] = { d6, d7 };
				end
			end
		end
	end
endtask

// single read from memory backdoor;
// extent bits are ignored in x36 space;

task mem_sread;
	input [31:0] addr;
	input [1:0] size;
	output [31:0] data;

	reg x36, valid;
	reg [31:0] baddr;
	reg [31:0] mask;
	reg [63:0] mdata;
	reg lhw;
	begin
		baddr = addr;
		mem_check_addr(addr, x36, valid);
		data = 32'bx;
		if(valid) begin
			mask = sgl_mask(addr[1:0], size);
			if(x36) begin
				addr = addr >> 2;
				mdata = vsim.bb.bcp.ri.mem[addr];
				data = mdata[63:32];
			end else begin
				lhw = addr[2];
				addr = addr >> 3;
				mdata = vsim.bb.bcp.ri.mem[addr];
				data = lhw? mdata[31:0] : mdata[63:32];
			end
			data = (data & mask) | (32'bx & ~mask);
		end
		if(mem_mon)
			$display("%t: %M: addr 0x%h data 0x%h", $time, baddr, data);
	end
endtask

// block read from memory backdoor;
// extent bits are ignored in x36 space;

task mem_bread;
	input [31:0] addr;
	input [1:0] size;
	output [31:0] d0, d1, d2, d3, d4, d5, d6, d7;

	reg x36, valid;
	reg [31:0] baddr;
	reg [31:0] dummy;
	begin
		baddr = addr;
		case(size)
			2'b00, 2'b01, 2'b10: ;
			default:
				$display("ERROR: %t: %M: illegal size", $time, size);
		endcase
		mem_check_addr(addr, x36, valid);
		d0 = 32'bx;
		d1 = 32'bx;
		d2 = 32'bx;
		d3 = 32'bx;
		d4 = 32'bx;
		d5 = 32'bx;
		d6 = 32'bx;
		d7 = 32'bx;
		if(valid) begin
			if(x36) begin
				addr = addr >> 2;
				{ d0, dummy } = vsim.bb.bcp.ri.mem[addr+0];
				{ d1, dummy } = vsim.bb.bcp.ri.mem[addr+1];
				if(|size) begin
					{ d2, dummy } = vsim.bb.bcp.ri.mem[addr+2];
					{ d3, dummy } = vsim.bb.bcp.ri.mem[addr+3];
				end
				if(size[1]) begin
					{ d4, dummy } = vsim.bb.bcp.ri.mem[addr+4];
					{ d5, dummy } = vsim.bb.bcp.ri.mem[addr+5];
					{ d6, dummy } = vsim.bb.bcp.ri.mem[addr+6];
					{ d7, dummy } = vsim.bb.bcp.ri.mem[addr+7];
				end
			end else begin
				addr = addr >> 3;
				{ d0, d1 } = vsim.bb.bcp.ri.mem[addr+0];
				if(|size)
					{ d2, d3 } = vsim.bb.bcp.ri.mem[addr+1];
				if(size[1]) begin
					{ d4, d5 } = vsim.bb.bcp.ri.mem[addr+2];
					{ d6, d7 } = vsim.bb.bcp.ri.mem[addr+3];
				end
			end
		end
		if(mem_mon)
			$display("%t: %M: addr 0x%h size %b", $time, baddr, size);
	end
endtask