-
Notifications
You must be signed in to change notification settings - Fork 612
Mem intg testing #1907
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Mem intg testing #1907
Conversation
Signed-off-by: Canberk Topal <ctopal@lowrisc.org>
This will prevent seeing mismatches right at the end of our test. Before this change, mem_error_test could inject error at the store instruction in which we finish up the test, resulting with mismatches with Spike and Ibex on the instructions after finishing. Also do the same prevention for signature_addr as well, since we also don't want to corrupt that memory transaction too. Signed-off-by: Canberk Topal <ctopal@lowrisc.org>
Signed-off-by: Canberk Topal <ctopal@lowrisc.org>
This enables the sequence to corrupt the integrity on write responses should it choose to. Previously the driver would always produce correct integrity.
This enables tests to implement custom test completion handling
rtl/ibex_core.sv
Outdated
captured_debug_req <= 1'b0; | ||
end else begin | ||
// Capture when ID stage has emptied out and something occurs that will cause a trap and we | ||
// haven't yet captured | ||
if (~instr_valid_id & (new_debug_req | new_irq | new_nmi) & ~captured_valid) begin | ||
if (~instr_valid_id & (new_debug_req | new_irq | new_nmi | new_nmi_int) & ~captured_valid) begin |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Line length exceeds max: 100; is: 102 [Style: line-length] [line-length]
rtl/ibex_core.sv
Outdated
rvfi_ext_stage_debug_req[0] <= '0; | ||
end else if (if_stage_i.instr_valid_id_d & if_stage_i.instr_new_id_d) begin | ||
rvfi_ext_stage_mip[0] <= instr_valid_id | ~captured_valid ? cs_registers_i.mip : | ||
captured_mip; | ||
rvfi_ext_stage_nmi[0] <= instr_valid_id | ~captured_valid ? irq_nm_i : | ||
captured_nmi; | ||
rvfi_ext_stage_nmi_int[0] <= instr_valid_id | ~captured_valid ? id_stage_i.controller_i.irq_nm_int : |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Line length exceeds max: 100; is: 108 [Style: line-length] [line-length]
end | ||
// Add integrity bits | ||
{req.intg, req.data} = prim_secded_pkg::prim_secded_inv_39_32_enc(req.data); | ||
|
||
// If data_was_uninitialized is true then we want to force bad integrity bits: invert the | ||
// correct ones, which we know will break things for the codes we use. | ||
if (p_sequencer.cfg.enable_bad_intg_on_uninit_access && | ||
data_was_uninitialized) begin | ||
if ((p_sequencer.cfg.enable_bad_intg_on_uninit_access && data_was_uninitialized) || enable_intg_error) begin |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Line length exceeds max: 100; is: 114 [Style: line-length] [line-length]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Put enable_int_error
on new line.
@@ -221,6 +223,9 @@ module core_ibex_tb_top; | |||
assign dut_if.rf_ren_b = dut.u_ibex_top.u_ibex_core.rf_ren_b; | |||
assign dut_if.rf_rd_a_wb_match = dut.u_ibex_top.u_ibex_core.rf_rd_a_wb_match; | |||
assign dut_if.rf_rd_b_wb_match = dut.u_ibex_top.u_ibex_core.rf_rd_b_wb_match; | |||
assign dut_if.sync_exc_seen = dut.u_ibex_top.u_ibex_core.cs_registers_i.cpuctrlsts_part_q.sync_exc_seen; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Line length exceeds max: 100; is: 109 [Style: line-length] [line-length]
This test picks between inserting an integrity error or a bus error to the response in the case of a memory request from Ibex. Introduces a control knob `enable_mem_intg_err` which can control the rate of having integrity errors per request. This commit also disables checking for double fault alerts in the scoreboard because they're expected to be seen while simulating and they don't cause infinite loop problems because every time a memory response is requested the error causing part is just randomized. That means Ibex trying to execute same instruction again would have a chance to succeed this time. Signed-off-by: Canberk Topal <ctopal@lowrisc.org>
7f9e142
to
a279618
Compare
This commit is mainly an extension to cosim environment to drive the newly introduced state variable `nmi_int` in Spike. This commit - Extends RVFI interface by a single bit (ext_nmi_int) - Configures cosim to set nmi_int inside Spike Signed-off-by: Canberk Topal <ctopal@lowrisc.org>
Signed-off-by: Canberk Topal <ctopal@lowrisc.org>
a279618
to
213dc1b
Compare
When Ibex does a load that receives data with bad integrity it suppresses the write to the destination register. The implements matching functionality for cosim.
213dc1b
to
53ed7bd
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
stop_seq = 1'b0; | ||
seq_finished = 1'b0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Squash this one and the first commit?
end | ||
// Add integrity bits | ||
{req.intg, req.data} = prim_secded_pkg::prim_secded_inv_39_32_enc(req.data); | ||
|
||
// If data_was_uninitialized is true then we want to force bad integrity bits: invert the | ||
// correct ones, which we know will break things for the codes we use. | ||
if (p_sequencer.cfg.enable_bad_intg_on_uninit_access && | ||
data_was_uninitialized) begin | ||
if ((p_sequencer.cfg.enable_bad_intg_on_uninit_access && data_was_uninitialized) || enable_intg_error) begin |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Put enable_int_error
on new line.
+instr_cnt=10000 | ||
+randomize_csr=1 | ||
+enable_unaligned_load_store=1 | ||
+suppress_pmp_setup=1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about the disable_pmp_exception_handler
routine?
@@ -376,6 +377,12 @@ bool SpikeCosim::check_sync_trap(uint32_t write_reg, | |||
return false; | |||
} | |||
|
|||
// If we see an internal NMI, that means we receive an extra memory intf item. | |||
// Deleting that is necessary since next Load/Store would fail otherwise. | |||
if (processor->get_state()->mcause->read() == 0xFFFFFFE0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why don't we check the nmi_int
value instead of mcause
?
if (suppress_reg_write) { | ||
// If we suppressed a register write restore the old register state now | ||
processor->get_state()->XPR.write(suppressed_write_reg, | ||
suppressed_write_reg_data); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't there a way to stop the write in the first place instead of undoing it?
bool SpikeCosim::pc_is_load(uint32_t pc, uint32_t &rd_out) { | ||
uint16_t insn_16; | ||
|
||
if (!backdoor_read_mem(pc, 2, reinterpret_cast<uint8_t *>(&insn_16))) { | ||
return false; | ||
} | ||
|
||
// C.LW | ||
if ((insn_16 & 0xE003) == 0x4000) { | ||
rd_out = ((insn_16 >> 2) & 0x7) + 8; | ||
return true; | ||
} | ||
|
||
// C.LWSP | ||
if ((insn_16 & 0xE003) == 0x4002) { | ||
rd_out = (insn_16 >> 7) & 0x1F; | ||
return rd_out != 0; | ||
} | ||
|
||
uint16_t insn_32; | ||
|
||
if (!backdoor_read_mem(pc, 4, reinterpret_cast<uint8_t *>(&insn_32))) { | ||
return false; | ||
} | ||
|
||
// LB/LH/LW/LBU/LHU | ||
if ((insn_32 & 0x7F) == 0x3) { | ||
uint32_t func = (insn_32 >> 12) & 0x7; | ||
if ((func == 0x3) || (func == 0x6) || (func == 0x7)) { | ||
// Not valid load encodings | ||
return false; | ||
} | ||
|
||
rd_out = (insn_32 >> 7) & 0x1F; | ||
return true; | ||
} | ||
|
||
return false; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't like that this replicates decode logic, although I don't have a concrete alternative in mind.
This is a mix @ctopal's work in #1811 and work I've done. It supersedes #1811