[otbn,dv] Add a sequence that drives the lc_escalate_en_i input Signed-off-by: Rupert Swarbrick <rswarbrick@lowrisc.org>
diff --git a/hw/ip/otbn/data/otbn_testplan.hjson b/hw/ip/otbn/data/otbn_testplan.hjson index 2e672ee..1884e8c 100644 --- a/hw/ip/otbn/data/otbn_testplan.hjson +++ b/hw/ip/otbn/data/otbn_testplan.hjson
@@ -119,7 +119,7 @@ Trigger the life cycle escalation input. ''' milestone: V2 - tests: [] + tests: ["otbn_escalate"] } ] }
diff --git a/hw/ip/otbn/dv/uvm/env/otbn_env.core b/hw/ip/otbn/dv/uvm/env/otbn_env.core index 039ad68..53e1a9f 100644 --- a/hw/ip/otbn/dv/uvm/env/otbn_env.core +++ b/hw/ip/otbn/dv/uvm/env/otbn_env.core
@@ -44,6 +44,7 @@ - seq_lib/otbn_single_vseq.sv: {is_include_file: true} - seq_lib/otbn_smoke_vseq.sv: {is_include_file: true} - seq_lib/otbn_stress_all_vseq.sv: {is_include_file: true} + - seq_lib/otbn_escalate_vseq.sv: {is_include_file: true} file_type: systemVerilogSource generate:
diff --git a/hw/ip/otbn/dv/uvm/env/otbn_escalate_if.sv b/hw/ip/otbn/dv/uvm/env/otbn_escalate_if.sv index fc26dba..dc7fc06 100644 --- a/hw/ip/otbn/dv/uvm/env/otbn_escalate_if.sv +++ b/hw/ip/otbn/dv/uvm/env/otbn_escalate_if.sv
@@ -11,4 +11,19 @@ lc_ctrl_pkg::lc_tx_t enable; + function automatic void reset_signals(); + enable = lc_ctrl_pkg::Off; + endfunction + + task automatic set_after_n_clocks(int unsigned n); + `DV_SPINWAIT_EXIT( + begin + repeat (n) @(posedge clk_i); + enable = lc_ctrl_pkg::On; + end, + @(negedge rst_ni);, + "Not setting enable signal because we've gone into reset", + "otbn_escalate_if") + endtask + endinterface
diff --git a/hw/ip/otbn/dv/uvm/env/seq_lib/otbn_base_vseq.sv b/hw/ip/otbn/dv/uvm/env/seq_lib/otbn_base_vseq.sv index 71af972..99513b8 100644 --- a/hw/ip/otbn/dv/uvm/env/seq_lib/otbn_base_vseq.sv +++ b/hw/ip/otbn/dv/uvm/env/seq_lib/otbn_base_vseq.sv
@@ -38,7 +38,7 @@ // Overridden from dv_base_vseq task dut_init(string reset_kind = "HARD"); // Always drive the lifecycle escalation signal to off at the start of the sequence. - cfg.escalate_vif.enable = lc_ctrl_pkg::Off; + cfg.escalate_vif.reset_signals(); super.dut_init(reset_kind); endtask
diff --git a/hw/ip/otbn/dv/uvm/env/seq_lib/otbn_escalate_vseq.sv b/hw/ip/otbn/dv/uvm/env/seq_lib/otbn_escalate_vseq.sv new file mode 100644 index 0000000..d2388a5 --- /dev/null +++ b/hw/ip/otbn/dv/uvm/env/seq_lib/otbn_escalate_vseq.sv
@@ -0,0 +1,76 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +// A sequence that runs a program, asserting the lc_escalate_en_i at some point during the run. +// Occasionally, it will assert just before or just after. + +class otbn_escalate_vseq extends otbn_base_vseq; + `uvm_object_utils(otbn_escalate_vseq) + + `uvm_object_new + + task body(); + string elf_path; + int unsigned bda_idx; + bit go_before, go_during, go_after; + + elf_path = pick_elf_path(); + `uvm_info(`gfn, $sformatf("Loading OTBN binary from `%0s'", elf_path), UVM_LOW) + + // Pick whether we're going before (5%), during (90%), or after (5%). + bda_idx = $urandom_range(100); + go_before = bda_idx < 5; + go_during = 5 <= bda_idx && bda_idx < 95; + go_after = 95 <= bda_idx; + + fork + load_elf(elf_path, .backdoor(1'b0)); + if (go_before) send_escalation_signal(100); + join + + if (go_before) begin + // At this point, we've sent our escalation signal already. Wait for the fatal alert to + // trigger and then return. + wait_alert_and_reset(); + return; + end + + if (go_after) begin + // We want to send the escalation signal after OTBN is finished. Run an operation, send the + // signal, then wait for the fatal alert. + run_otbn(); + send_escalation_signal(10); + wait_alert_and_reset(); + return; + end + + // This is the interesting case. Start OTBN running. When this task returns, we'll be in the + // middle of a run. + start_running_otbn(.check_end_addr(1'b0)); + + // Send an escalation signal immediately (the randomisation about where we should strike has + // already been done inside start_running_otbn()) + send_escalation_signal(1); + + // Wait for an alert to come out before returning + wait_alert_and_reset(); + endtask + + // Wait between zero and max_cycles clock cycles and then set the escalation signal to enabled. + // Return immediately if we go into reset. + task send_escalation_signal(int unsigned max_cycles); + cfg.escalate_vif.set_after_n_clocks($urandom_range(max_cycles)); + endtask + + // Wait for a fatal alert to come out and retrigger at least once. Then reset the DUT. This is + // needed at the end of the sequence because otherwise the monitor that sees the re-triggering + // fatal alert will stop the test from ever finishing. + task wait_alert_and_reset(); + repeat (2) wait_alert_trigger("fatal", .wait_complete(1)); + + do_apply_reset = 1'b1; + dut_init("HARD"); + endtask + +endclass
diff --git a/hw/ip/otbn/dv/uvm/env/seq_lib/otbn_vseq_list.sv b/hw/ip/otbn/dv/uvm/env/seq_lib/otbn_vseq_list.sv index cc1ed50..ccefedc 100644 --- a/hw/ip/otbn/dv/uvm/env/seq_lib/otbn_vseq_list.sv +++ b/hw/ip/otbn/dv/uvm/env/seq_lib/otbn_vseq_list.sv
@@ -12,3 +12,4 @@ `include "otbn_imem_err_vseq.sv" `include "otbn_dmem_err_vseq.sv" `include "otbn_stress_all_vseq.sv" +`include "otbn_escalate_vseq.sv"
diff --git a/hw/ip/otbn/dv/uvm/otbn_sim_cfg.hjson b/hw/ip/otbn/dv/uvm/otbn_sim_cfg.hjson index 02380ce..c4ee920 100644 --- a/hw/ip/otbn/dv/uvm/otbn_sim_cfg.hjson +++ b/hw/ip/otbn/dv/uvm/otbn_sim_cfg.hjson
@@ -197,6 +197,13 @@ } { + name: "otbn_escalate" + uvm_test_seq: "otbn_escalate_vseq" + en_run_modes: ["build_otbn_rig_binary_mode"] + reseed: 5 + } + + { name: "otbn_stress_all" uvm_test_seq: "otbn_stress_all_vseq" en_run_modes: ["build_otbn_rig_binaries_mode"]