blob: 1204a66f61fafb292c598bc8f5ee7e7357eaa118 [file] [log] [blame]
//
// -------------------------------------------------------------
// Copyright 2004-2008 Synopsys, Inc.
// All Rights Reserved Worldwide
//
// Licensed under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of
// the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in
// writing, software distributed under the License is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See
// the License for the specific language governing
// permissions and limitations under the License.
// -------------------------------------------------------------
//
//
// ECC-protected memory model extension for RAL
//
// This example assumes 32 bits of user data and 4 bits of ECC code
// stored in a memory with 36-bit addressable words.
//
`include "vmm_ral.sv"
//
// Compute ECC code
//
class ecc_32_4;
virtual function bit [3:0] compute(bit [31:0] data);
compute = {^data[31:24],
^data[23:16],
^data[15: 8],
^data[ 7: 0]};
endfunction: compute
endclass: ecc_32_4
//
// Memory callback extension implementing ECC error injection.
// Errors can be injected when a memory location is written
// (i.e. the ECC error will be reported every time the location
// is read back) or it can be injected when a memory location is
// read (i.e. the ECC error may or may not be reported when the
// same location is subsequently read).
//
// This error injection model supports only single-bit errors, in
// either the data or ECC code itself.
//
// By default, errors are not injected. Errors can be injected at
// a specified rate by setting the 'error_rate' value to non-zero.
// A value of 'hFF indicates 100% error rate.
//
// This callback class works in tandem with the backdoor access
// class to allow direct access to the ECC code via the the backdoor.
// See ecc_mem0_bkdr class below.
//
class ecc_mem0_cb extends vmm_ral_mem_callbacks;
bit [7:0] error_rate = 0;
rand bit error_on_write;
rand bit error_on_read;
rand bit [6:0] error_on_bit;
static local ecc_32_4 ecc = new;
local bit [35:0] ecc_rdat;
constraint valid {
error_on_bit < 36;
}
constraint write_error_rate {
error_on_write dist {0 :/ (255 - error_rate),
1 :/ error_rate};
}
constraint read_error_rate {
error_on_read dist {0 :/ (255 - error_rate),
1 :/ error_rate};
}
virtual task post_write(vmm_ral_mem mem,
bit [63:0] offset,
bit [63:0] wdat,
vmm_ral::path_e path,
string domain,
ref vmm_rw::status_e status);
bit [35:0] ecc_wdat;
// No point in injecting random ECC error on write if
// writing via backdoor WITH an ECC error
if (path == vmm_ral::BACKDOOR && wdat[35:32] != 4'b0000) begin
this.error_on_write = 1;
return;
end
ecc_wdat = {this.ecc.compute(wdat), wdat[31:0]};
this.randomize();
if (this.error_on_write) begin
ecc_wdat ^= 1'b1 << error_on_bit;
end
tb_top.dut.mem0[offset] = ecc_wdat;
endtask: post_write
virtual task pre_read(vmm_ral_mem mem,
ref bit [63:0] offset,
ref vmm_ral::path_e path,
ref string domain);
// No point in injecting ECC error on read if
// reading via backdoor...
if (path == vmm_ral::BACKDOOR) begin
this.error_on_read = 0;
return;
end
this.randomize();
if (this.error_on_read) begin
ecc_rdat = tb_top.dut.mem0[offset];
tb_top.dut.mem0[offset] = ecc_rdat ^ (1'b1 << error_on_bit);
end
endtask: pre_read
virtual task post_read(input vmm_ral_mem mem,
input bit [63:0] offset,
ref bit [63:0] rdat,
input vmm_ral::path_e path,
input string domain,
ref vmm_rw::status_e status);
// Remove the ECC error at the end of the read
if (this.error_on_read) begin
tb_top.dut.mem0[offset] = ecc_rdat;
end
endtask: post_read
endclass: ecc_mem0_cb
//
// Backdoor accesses can include ECC information because
// the data value is always transfered as 64 bits.
// If the ECC-protected memory has addressable locations
// that are less than 64 bits, the additional bits can be used
// to carry the ECC information. In this example, the 32 bit
// data values are concatenated with a 4-bit ECC code yielding
// 36 bit transfers.
//
// The ECC information is represented using a validity
// indicator, not the ECC value. If the bit is cleared, the
// corresponding ECC bit is valid. If the bit is set, the
// corresponding ECC bit is invalid or will be corrupted.
//
// Note that backdoor accesses are subjected to the memory
// callbacks (see ecc_mem0_cb class above) before they are
// physically executed in this backdoor access class.
//
class ecc_mem0_backdoor extends vmm_ral_mem_backdoor;
static local ecc_32_4 ecc = new;
virtual task write(output vmm_rw::status_e status,
input bit [63:0] offset,
input bit [63:0] data,
input int data_id,
input int scenario_id,
input int stream_id);
// Corrupt ECC bit if it is set in the data to write
data[35:32] = this.ecc.compute(data[31:0]) ^ data[35:32];
tb_top.dut.mem0[offset] = data;
status = vmm_rw::IS_OK;
endtask: write
virtual task read(output vmm_rw::status_e status,
input bit [63:0] offset,
output bit [63:0] data,
input int data_id,
input int scenario_id,
input int stream_id);
// Report invalid ECC bits
data = tb_top.dut.mem0[offset];
data[35:32] = this.ecc.compute(data[31:0]) ^ data[35:32];
status = vmm_rw::IS_OK;
endtask: read
endclass: ecc_mem0_backdoor
//
// Fake DUT to enable error-free compilation
//
module dut();
reg [35:0] mem0[1023];
endmodule
module tb_top();
dut dut();
endmodule