Fix memory error test logic (#344)

This commit is contained in:
udinator 2019-09-23 15:32:20 -07:00 committed by GitHub
parent 83d2185c9b
commit 717bf1ae02
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 109 additions and 56 deletions

View file

@ -7,6 +7,7 @@
// ---------------------------------------------
`include "core_ibex_dut_probe_if.sv"
`include "core_ibex_rvfi_if.sv"
package core_ibex_env_pkg;

27
dv/uvm/env/core_ibex_rvfi_if.sv vendored Normal file
View file

@ -0,0 +1,27 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
// Interface to probe Ibex RVFI interface
interface core_ibex_rvfi_if(input logic clk);
logic valid;
logic [63:0] order;
logic [31:0] insn;
logic trap;
logic halt;
logic intr;
logic [1:0] mode;
logic [4:0] rs1_addr;
logic [4:0] rs2_addr;
logic [31:0] rs1_rdata;
logic [31:0] rs2_rdata;
logic [4:0] rd_addr;
logic [31:0] rd_wdata;
logic [31:0] pc_rdata;
logic [31:0] pc_wdata;
logic [31:0] mem_addr;
logic [3:0] mem_rmask;
logic [3:0] mem_wmask;
logic [31:0] mem_rdata;
logic [31:0] mem_wdata;
endinterface

View file

@ -20,6 +20,9 @@ module core_ibex_tb_top;
// DUT probe interface
core_ibex_dut_probe_if dut_if(.clk(clk));
// RVFI interface
core_ibex_rvfi_if rvfi_if(.clk(clk));
// TODO(taliu) Resolve the tied-off ports
ibex_core_tracing #(.DmHaltAddr(`BOOT_ADDR + 'h0),
.DmExceptionAddr(`BOOT_ADDR + 'h4)) dut (
@ -46,40 +49,57 @@ module core_ibex_tb_top;
);
// Data load/store vif connection
assign data_mem_vif.clock = clk;
assign data_mem_vif.reset = ~rst_n;
assign data_mem_vif.request = dut.data_req_o;
assign data_mem_vif.we = dut.data_we_o;
assign data_mem_vif.be = dut.data_be_o;
assign data_mem_vif.addr = dut.data_addr_o;
assign data_mem_vif.wdata = dut.data_wdata_o;
assign data_mem_vif.clock = clk;
assign data_mem_vif.reset = ~rst_n;
assign data_mem_vif.request = dut.data_req_o;
assign data_mem_vif.we = dut.data_we_o;
assign data_mem_vif.be = dut.data_be_o;
assign data_mem_vif.addr = dut.data_addr_o;
assign data_mem_vif.wdata = dut.data_wdata_o;
// Instruction fetch vif connnection
assign instr_mem_vif.clock = clk;
assign instr_mem_vif.reset = ~rst_n;
assign instr_mem_vif.request = dut.instr_req_o;
assign instr_mem_vif.we = 0;
assign instr_mem_vif.be = 0;
assign instr_mem_vif.wdata = 0;
assign instr_mem_vif.addr = dut.instr_addr_o;
initial begin
// IRQ interface
force irq_vif.clock = clk;
force irq_vif.reset = ~rst_n;
end
assign dut_if.ecall = dut.u_ibex_core.id_stage_i.ecall_insn_dec;
assign dut_if.wfi = dut.u_ibex_core.id_stage_i.wfi_insn_dec;
assign dut_if.ebreak = dut.u_ibex_core.id_stage_i.ebrk_insn;
assign dut_if.illegal_instr = dut.u_ibex_core.id_stage_i.illegal_insn_dec;
assign dut_if.dret = dut.u_ibex_core.id_stage_i.dret_insn_dec;
assign dut_if.mret = dut.u_ibex_core.id_stage_i.mret_insn_dec;
assign dut_if.core_sleep = dut.u_ibex_core.core_sleep_o;
assign instr_mem_vif.clock = clk;
assign instr_mem_vif.reset = ~rst_n;
assign instr_mem_vif.request = dut.instr_req_o;
assign instr_mem_vif.we = 0;
assign instr_mem_vif.be = 0;
assign instr_mem_vif.wdata = 0;
assign instr_mem_vif.addr = dut.instr_addr_o;
// RVFI interface connections
assign rvfi_if.valid = dut.rvfi_valid;
assign rvfi_if.order = dut.rvfi_order;
assign rvfi_if.insn = dut.rvfi_insn;
assign rvfi_if.trap = dut.rvfi_trap;
assign rvfi_if.intr = dut.rvfi_intr;
assign rvfi_if.mode = dut.rvfi_mode;
assign rvfi_if.rs1_addr = dut.rvfi_rs1_addr;
assign rvfi_if.rs2_addr = dut.rvfi_rs2_addr;
assign rvfi_if.rs1_rdata = dut.rvfi_rs1_rdata;
assign rvfi_if.rs2_rdata = dut.rvfi_rs2_rdata;
assign rvfi_if.rd_addr = dut.rvfi_rd_addr;
assign rvfi_if.rd_wdata = dut.rvfi_rd_wdata;
assign rvfi_if.pc_rdata = dut.rvfi_pc_rdata;
assign rvfi_if_pc_wdata = dut.rvfi_pc_wdata;
assign rvfi_if.mem_addr = dut.rvfi_mem_addr;
assign rvfi_if.mem_rmask = dut.rvfi_mem_rmask;
assign rvfi_if.mem_rdata = dut.rvfi_mem_rdata;
assign rvfi_if.mem_wdata = dut.rvfi_mem_wdata;
// Irq interface connections
assign irq_vif.clock = clk;
assign irq_vif.reset = ~rst_n;
// Dut_if interface connections
assign dut_if.ecall = dut.u_ibex_core.id_stage_i.ecall_insn_dec;
assign dut_if.wfi = dut.u_ibex_core.id_stage_i.wfi_insn_dec;
assign dut_if.ebreak = dut.u_ibex_core.id_stage_i.ebrk_insn;
assign dut_if.illegal_instr = dut.u_ibex_core.id_stage_i.illegal_insn_dec;
assign dut_if.dret = dut.u_ibex_core.id_stage_i.dret_insn_dec;
assign dut_if.mret = dut.u_ibex_core.id_stage_i.mret_insn_dec;
assign dut_if.core_sleep = dut.u_ibex_core.core_sleep_o;
initial begin
uvm_config_db#(virtual clk_if)::set(null, "*", "clk_if", ibex_clk_if);
uvm_config_db#(virtual core_ibex_dut_probe_if)::set(null, "*", "dut_if", dut_if);
uvm_config_db#(virtual core_ibex_rvfi_if)::set(null, "*", "rvfi_if", rvfi_if);
uvm_config_db#(virtual ibex_mem_intf)::set(null, "*data_if_slave*", "vif", data_mem_vif);
uvm_config_db#(virtual ibex_mem_intf)::set(null, "*instr_if_slave*", "vif", instr_mem_vif);
uvm_config_db#(virtual irq_if)::set(null, "*", "vif", irq_vif);

View file

@ -172,9 +172,7 @@ class core_ibex_base_test extends uvm_test;
virtual task check_next_core_status(core_status_t core_status, string error_msg = "");
wait_for_mem_txn(cfg.signature_addr, CORE_STATUS);
signature_data = signature_data_q.pop_front();
if (signature_data != core_status) begin
`uvm_error(`gfn, error_msg)
end
`DV_CHECK_EQ_FATAL(signature_data, core_status, error_msg);
endtask
// Waits for a write to the address of the specified CSR and retrieves the csr data

View file

@ -388,52 +388,59 @@ class core_ibex_mem_error_test extends core_ibex_directed_test;
int err_delay;
// check memory error inputs and verify that core jumps to correct exception handler
// TODO(udinator) - add checks for the RVFI interface
virtual task check_stimulus();
forever begin
while (!vseq.data_intf_seq.get_error_synch()) begin
clk_vif.wait_clks(1);
end
vseq.data_intf_seq.inject_error();
`uvm_info(`gfn, "Injected dmem error", UVM_LOW)
// Dmem interface error could be either a load or store operation
fork
begin
fork
check_mem_fault(LOAD_FAULT_EXCEPTION, EXC_CAUSE_LOAD_ACCESS_FAULT);
check_mem_fault(STORE_FAULT_EXCEPTION, EXC_CAUSE_STORE_ACCESS_FAULT);
join_any
disable fork;
end
join
check_mem_fault(1'b1);
// Random delay before injecting instruction fetch fault
`DV_CHECK_STD_RANDOMIZE_WITH_FATAL(err_delay, err_delay inside { [5:100] };)
`DV_CHECK_STD_RANDOMIZE_WITH_FATAL(err_delay, err_delay inside { [25:100] };)
clk_vif.wait_clks(err_delay);
while (!vseq.instr_intf_seq.get_error_synch()) begin
clk_vif.wait_clks(1);
end
`uvm_info(`gfn, $sformatf("vseq.instr_intf_seq.error_synch: 0x%0x", vseq.instr_intf_seq.get_error_synch()), UVM_LOW)
`uvm_info(`gfn, "Injecting imem fault", UVM_LOW)
vseq.instr_intf_seq.inject_error();
`uvm_info(`gfn, $sformatf("vseq.instr_intf_seq.enable_error: 0x%0x", vseq.instr_intf_seq.enable_error), UVM_LOW)
check_mem_fault(INSTR_FAULT_EXCEPTION, EXC_CAUSE_INSTR_ACCESS_FAULT);
check_mem_fault(1'b0);
// Random delay before injecting this series of errors again
`DV_CHECK_STD_RANDOMIZE_WITH_FATAL(err_delay, err_delay inside { [250:750] };)
clk_vif.wait_clks(err_delay);
end
endtask
virtual task check_mem_fault(core_status_t fault_type, ibex_pkg::exc_cause_e exc_type);
virtual task check_mem_fault(bit imem_or_dmem);
bit[ibex_mem_intf_agent_pkg::DATA_WIDTH-1:0] mcause;
forever begin
wait_for_core_status(HANDLING_EXCEPTION);
wait_for_core_status(fault_type);
wait_for_csr_write(CSR_MCAUSE);
mcause = signature_data;
`DV_CHECK_EQ_FATAL(mcause[ibex_mem_intf_agent_pkg::DATA_WIDTH-1], 1'b0,
"mcause interrupt is not set to 1'b0")
`DV_CHECK_EQ_FATAL(mcause[ibex_mem_intf_agent_pkg::DATA_WIDTH-2:0],
exc_type,
"mcause.exception_code is encoding the wrong exception type")
wait(dut_vif.mret === 1'b1);
core_status_t mem_status;
ibex_pkg::exc_cause_e exc_type;
check_next_core_status(HANDLING_EXCEPTION, "Core did not jump to exception handler");
if (imem_or_dmem) begin
// Next write of CORE_STATUS will be the load/store fault type
wait_for_mem_txn(cfg.signature_addr, CORE_STATUS);
mem_status = signature_data_q.pop_front();
if (mem_status == LOAD_FAULT_EXCEPTION) begin
exc_type = EXC_CAUSE_LOAD_ACCESS_FAULT;
end else if (mem_status == STORE_FAULT_EXCEPTION) begin
exc_type = EXC_CAUSE_STORE_ACCESS_FAULT;
end
`uvm_info(`gfn, $sformatf("0x%0x", exc_type), UVM_LOW)
end else begin
check_next_core_status(INSTR_FAULT_EXCEPTION, "Core did not register correct memory fault type");
exc_type = EXC_CAUSE_INSTR_ACCESS_FAULT;
end
wait_for_csr_write(CSR_MCAUSE);
mcause = signature_data;
`DV_CHECK_EQ_FATAL(mcause[ibex_mem_intf_agent_pkg::DATA_WIDTH-1], 1'b0,
"mcause interrupt is not set to 1'b0")
`DV_CHECK_EQ_FATAL(mcause[ibex_mem_intf_agent_pkg::DATA_WIDTH-2:0],
exc_type,
"mcause.exception_code is encoding the wrong exception type")
wait(dut_vif.mret === 1'b1);
`uvm_info(`gfn, "exiting mem fault checker", UVM_LOW)
endtask
endclass