[otbn] Add a "reset" vseq that resets in the middle of operations
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 f5bec69..68b98a0 100644
--- a/hw/ip/otbn/data/otbn_testplan.hjson
+++ b/hw/ip/otbn/data/otbn_testplan.hjson
@@ -54,7 +54,7 @@
'''
milestone: V2
- tests: []
+ tests: ["otbn_reset"]
}
{
name: mem_integrity
diff --git a/hw/ip/otbn/dv/uvm/env/otbn_env.core b/hw/ip/otbn/dv/uvm/env/otbn_env.core
index 9b147c2..af06087 100644
--- a/hw/ip/otbn/dv/uvm/env/otbn_env.core
+++ b/hw/ip/otbn/dv/uvm/env/otbn_env.core
@@ -32,6 +32,7 @@
- seq_lib/otbn_base_vseq.sv: {is_include_file: true}
- seq_lib/otbn_common_vseq.sv: {is_include_file: true}
- seq_lib/otbn_multi_vseq.sv: {is_include_file: true}
+ - seq_lib/otbn_reset_vseq.sv: {is_include_file: true}
- seq_lib/otbn_single_vseq.sv: {is_include_file: true}
- seq_lib/otbn_smoke_vseq.sv: {is_include_file: true}
file_type: systemVerilogSource
diff --git a/hw/ip/otbn/dv/uvm/env/seq_lib/otbn_reset_vseq.sv b/hw/ip/otbn/dv/uvm/env/seq_lib/otbn_reset_vseq.sv
new file mode 100644
index 0000000..ac5bbc9
--- /dev/null
+++ b/hw/ip/otbn/dv/uvm/env/seq_lib/otbn_reset_vseq.sv
@@ -0,0 +1,63 @@
+// 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 multiple times, resetting in the middle of runs
+
+class otbn_reset_vseq extends otbn_base_vseq;
+ `uvm_object_utils(otbn_reset_vseq)
+
+ int unsigned num_iters = 10;
+
+ `uvm_object_new
+
+ task body();
+ int max_cycles;
+ string elf_path;
+
+ elf_path = pick_elf_path();
+ `uvm_info(`gfn, $sformatf("Loading OTBN binary from `%0s'", elf_path), UVM_LOW)
+ load_elf(elf_path, 1'b1);
+
+ max_cycles = 1000;
+ for (int i = 0; i < num_iters; i++) begin
+ int cycle_counter;
+ int reset_wait;
+ bit timed_out = 1'b0;
+
+ // Guess the number of cycles until reset. The first time around, we pick any number between 1
+ // and 1,000. After that, we replace "1,000" with "75% of the longest we've seen the sequence
+ // run before terminating". This should avoid problems where we keep resetting after the
+ // sequence has finished.
+ reset_wait = $urandom_range(max_cycles * 3 / 4) + 1;
+
+ fork
+ run_otbn();
+ begin
+ repeat (reset_wait) begin
+ @(cfg.clk_rst_vif.cb);
+ cycle_counter++;
+ end
+ timed_out = 1'b1;
+ end
+ join_any
+
+ // When we get here, we know that either the OTBN sequence finished (in which case timed_out =
+ // 1'b0) or we timed out. If the OTBN sequence finished, kill the counter process. We don't
+ // kill the run_otbn task: it will spot a reset and terminate on its own.
+ if (!timed_out) begin
+ // If the OTBN sequence finished, update max_cycles. cycle_counter should always be less
+ // than max_cycles (because of how we calculate reset_wait).
+ `DV_CHECK_FATAL(cycle_counter < max_cycles);
+ max_cycles = cycle_counter;
+ disable fork;
+ end
+
+ // If this isn't the last iteration, or if we timed out, reset the DUT
+ if (timed_out || i + 1 < num_iters) begin
+ dut_init("HARD");
+ end
+ end
+ 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 5320855..b063f20 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
@@ -5,5 +5,6 @@
`include "otbn_base_vseq.sv"
`include "otbn_common_vseq.sv"
`include "otbn_multi_vseq.sv"
+`include "otbn_reset_vseq.sv"
`include "otbn_single_vseq.sv"
`include "otbn_smoke_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 669da52..8b6b07a 100644
--- a/hw/ip/otbn/dv/uvm/otbn_sim_cfg.hjson
+++ b/hw/ip/otbn/dv/uvm/otbn_sim_cfg.hjson
@@ -140,7 +140,12 @@
reseed: 5
}
- // TODO: add more tests here
+ {
+ name: "otbn_reset"
+ uvm_test_seq: "otbn_reset_vseq"
+ en_run_modes: ["build_otbn_rig_binary_mode"]
+ reseed: 5
+ }
]
// List of regressions.