Skip to content

Commit c67db10

Browse files
committed
[otbn,dv] Adapt OTBN vseqs to match delayed escalation
Sequences must be adapted such that the error escalation behaviour is correctly modelled. Signed-off-by: Pascal Etterli <[email protected]>
1 parent 6a0b046 commit c67db10

8 files changed

+79
-4
lines changed

hw/ip/otbn/dv/uvm/env/seq_lib/otbn_alu_bignum_mod_err_vseq.sv

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,12 @@
88
class otbn_alu_bignum_mod_err_vseq extends otbn_intg_err_vseq;
99
`uvm_object_utils(otbn_alu_bignum_mod_err_vseq)
1010

11-
`uvm_object_new
11+
// TODO: Replaced the macro `uvm_object_new with the effective constructor to be able to
12+
// overwrite expect_delayed_escalation. There is probably a smarter way?
13+
function new (string name="");
14+
super.new(name);
15+
expect_delayed_escalation = 1;
16+
endfunction : new
1217

1318
protected task await_use(output bit [otbn_pkg::BaseWordsPerWLEN-1:0] used_words);
1419
used_words = '0;

hw/ip/otbn/dv/uvm/env/seq_lib/otbn_ctrl_redun_vseq.sv

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,23 @@ class otbn_ctrl_redun_vseq extends otbn_single_vseq;
178178
case(choose_err)
179179
0: begin
180180
insn_dec_shared_i.ld_insn = !insn_dec_shared_i.ld_insn;
181+
// This is a workaround to match the model behaviour to what happens if this
182+
// error is injected. When injecting the ld_insn error from the, the OTBN will start a
183+
// load in parallel to the current instruction. As of this the stall signal is asserted
184+
// and the OTBN enter the stall state (as ld_insn factors into it). We need to model
185+
// this but duplicating the logic in the model is not smart. We therefore signal simply
186+
// to the model to stall once. Due to the error the OTBN will escalate in the next
187+
// cycle anyway.
188+
// TODO: In case the instruction where we inject the error into is a branch instruction
189+
// the assertion NoStallOnBranch in the controller fails. However, this assertion is
190+
// not meaningful in this case and maybe could be disabled.
191+
// TODO: The injection can next to the stall also lead to a non fatal SW error. The RTL
192+
// therefore does not immediately escalate but still retires the current instruction
193+
// and goes into the HALT state. The RTL will then escalate from this state. Due to the
194+
// stall request, the model however won't retire the current instruction. Therefore no
195+
// ISS trace is generated and we get the back-to-back RTL trace entries with no ISS
196+
// entry error. To fix this the errors due to injections must be modelled differently.
197+
cfg.model_agent_cfg.vif.send_stall_request();
181198
end
182199
1: begin
183200
insn_dec_shared_i.st_insn = !insn_dec_shared_i.st_insn;
@@ -309,9 +326,18 @@ class otbn_ctrl_redun_vseq extends otbn_single_vseq;
309326
`uvm_fatal(`gfn, "issue with randomization")
310327
end
311328
endcase
329+
330+
// Due to the delayed escalation, the faulted instruction still commits but with wrong values.
331+
// We must signal to the ISS that the result can be off.
332+
cfg.model_agent_cfg.vif.tolerate_result_mismatch(1);
333+
334+
// Handle any SW error during the delayed escalation
335+
handle_delayed_escalation();
336+
312337
`uvm_info(`gfn, "injecting bad internal state error into ISS", UVM_HIGH)
313338
have_injected_error = 1'b1;
314339
cfg.model_agent_cfg.vif.send_err_escalation(err_val);
340+
315341
`DV_WAIT(cfg.model_agent_cfg.vif.status == otbn_pkg::StatusLocked)
316342
`DV_CHECK_FATAL(uvm_hdl_release(err_path) == 1);
317343
reset_if_locked();

hw/ip/otbn/dv/uvm/env/seq_lib/otbn_dmem_err_vseq.sv

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ class otbn_dmem_err_vseq extends otbn_base_vseq;
3333

3434
// Inject error at negedge of clock to avoid racing with second cycle of store instruction.
3535
@(cfg.clk_rst_vif.cbn);
36+
`uvm_info(`gfn, $sformatf("Modifying DMEM"), UVM_LOW)
3637

3738
for (int i = 0; i < DmemSizeByte / 32; i++) begin
3839
bit [ExtWLEN-1:0] old_data = cfg.read_dmem_word(i, key, nonce);
@@ -41,7 +42,11 @@ class otbn_dmem_err_vseq extends otbn_base_vseq;
4142
cfg.write_dmem_word(i, bad_data, key, nonce);
4243
end
4344

45+
// Invalidate the memory. Any next read will result in an escalation.
4446
cfg.model_agent_cfg.vif.invalidate_dmem();
47+
// As the next read will result in a mismatch between RTL and ISS, we must signal to the ISS
48+
// that this is expected.
49+
cfg.model_agent_cfg.vif.tolerate_result_mismatch(0);
4550

4651
wait (!(cfg.model_agent_cfg.vif.status inside {otbn_pkg::StatusBusyExecute,
4752
otbn_pkg::StatusBusySecWipeInt}));

hw/ip/otbn/dv/uvm/env/seq_lib/otbn_intg_err_vseq.sv

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ class otbn_intg_err_vseq extends otbn_base_vseq;
1111

1212
`uvm_object_new
1313

14+
// A flag whether the injected fault leads to a delayed escalation. Some escalation sources are
15+
// flopped in the RTL to improve timing. Overwrite this in the deriving class.
16+
protected bit expect_delayed_escalation = 0;
17+
1418
// Wait until the integrity-checked signal is used (otherwise an injected error would not have any
1519
// consequences) or an internal timeout expires. The `used_words` output indicates which words
1620
// were used during the call of this task.
@@ -81,7 +85,16 @@ class otbn_intg_err_vseq extends otbn_base_vseq;
8185

8286
inject_errors(used_words, corrupted_words);
8387

88+
if (expect_delayed_escalation) begin
89+
// Due to the delayed escalation, the faulted instruction still commits but with wrong values.
90+
// We must signal to the ISS that the result can be off.
91+
cfg.model_agent_cfg.vif.tolerate_result_mismatch(1);
92+
93+
handle_delayed_escalation(); // This resumes on the next clk posedge
94+
end
95+
8496
// Notify the model about the integrity violation error.
97+
// The HW escalation must happen on the rising edge. Otherwise the model is informed too late.
8598
if (|(corrupted_words & used_words)) begin
8699
otbn_pkg::err_bits_t err_bits;
87100
err_bits = '{reg_intg_violation: 1'b1, default: 1'b0};

hw/ip/otbn/dv/uvm/env/seq_lib/otbn_mac_bignum_acc_err_vseq.sv

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,12 @@
88
class otbn_mac_bignum_acc_err_vseq extends otbn_intg_err_vseq;
99
`uvm_object_utils(otbn_mac_bignum_acc_err_vseq)
1010

11-
`uvm_object_new
11+
// TODO: Replaced the macro `uvm_object_new with the effective constructor to be able to
12+
// overwrite expect_delayed_escalation. There is probably a smarter way?
13+
function new (string name="");
14+
super.new(name);
15+
expect_delayed_escalation = 1;
16+
endfunction : new
1217

1318
protected task await_use(output bit [otbn_pkg::BaseWordsPerWLEN-1:0] used_words);
1419
used_words = '0;

hw/ip/otbn/dv/uvm/env/seq_lib/otbn_pc_ctrl_flow_redun_vseq.sv

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,25 @@ class otbn_pc_ctrl_flow_redun_vseq extends otbn_single_vseq;
4141
prefetch_ignore_err))
4242
`uvm_fatal(`gfn, "failed to read prefetch_ignore_errs_i");
4343
end while(!(imem_rvalid & insn_fetch_req_valid & !prefetch_ignore_err));
44+
4445
`DV_CHECK_FATAL(uvm_hdl_read(addr_path, good_addr));
4546
// Mask to corrupt 1 to 2 bits of the prefetch addr
4647
`DV_CHECK_STD_RANDOMIZE_WITH_FATAL(mask, $countones(mask) inside {[1:2]};)
4748
bad_addr = good_addr ^ mask;
4849
`DV_CHECK_FATAL(uvm_hdl_force(addr_path, bad_addr) == 1);
50+
51+
// The core will never execute an instruction but the model will and then wait for a RTL trace.
52+
// However, due to the error the RTL will never produce traces and therefore the checker fails
53+
// because the model has two consecutive traces without a RTL trace.
54+
// We can tell the model that it should wait by requesting a stall for one cycle.
55+
cfg.model_agent_cfg.vif.send_stall_request();
56+
57+
// Send the HW escalation signal in the next cycle
58+
@(cfg.clk_rst_vif.cb);
4959
`uvm_info(`gfn, "injecting bad internal state error into ISS", UVM_HIGH)
5060
cfg.model_agent_cfg.vif.send_err_escalation(err_val);
61+
62+
// OTBN should perform a secure wipe and lock up
5163
wait(cfg.model_agent_cfg.vif.status == otbn_pkg::StatusLocked);
5264
`DV_CHECK_FATAL(uvm_hdl_release(addr_path) == 1);
5365
reset_if_locked();

hw/ip/otbn/dv/uvm/env/seq_lib/otbn_rf_base_intg_err_vseq.sv

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,15 @@ class otbn_rf_base_intg_err_vseq extends otbn_base_vseq;
115115

116116
inject_errors();
117117

118+
// Due to the delayed escalation, the faulted instruction still commits but with wrong values.
119+
// We must signal to the ISS that the result can be off.
120+
cfg.model_agent_cfg.vif.tolerate_result_mismatch(1);
121+
122+
handle_delayed_escalation(); // This resumes on the next clk posedge
123+
118124
// Notify the model about the integrity violation error.
125+
// The HW escalation must happen on the rising edge. Otherwise the model is informed too late.
126+
`uvm_info(`gfn, $sformatf("Send HW escalation to model"), UVM_LOW)
119127
err_bits = '{reg_intg_violation: 1'b1, default: 1'b0};
120128
cfg.model_agent_cfg.vif.send_err_escalation(err_bits);
121129

hw/ip/otbn/dv/uvm/env/seq_lib/otbn_zero_state_err_urnd_vseq.sv

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,13 @@ class otbn_zero_state_err_urnd_vseq extends otbn_single_vseq;
2626

2727
cfg.clk_rst_vif.wait_clks($urandom_range(10, 1000));
2828
`DV_CHECK_FATAL(uvm_hdl_force(prng_path, 'b0) == 1);
29+
cfg.clk_rst_vif.wait_clks(1); // the escalation is delayed by one cycle
30+
`DV_CHECK_FATAL(uvm_hdl_release(prng_path) == 1);
31+
`uvm_info(`gfn,"string released", UVM_HIGH)
2932
`uvm_info(`gfn,"injecting zero state error into ISS", UVM_HIGH)
3033
cfg.model_agent_cfg.vif.send_err_escalation(err_val);
3134
cfg.clk_rst_vif.wait_clks(1);
3235
cfg.model_agent_cfg.vif.otbn_set_no_sec_wipe_chk();
33-
`DV_CHECK_FATAL(uvm_hdl_release(prng_path) == 1);
34-
`uvm_info(`gfn,"string released", UVM_HIGH)
3536
wait (cfg.model_agent_cfg.vif.status == otbn_pkg::StatusLocked);
3637
reset_if_locked();
3738
end

0 commit comments

Comments
 (0)