[otbn,dv] Teach ISS wrapper to handle resets
Without this, you get weird errors where OTBN gets resets half-way
through a stall and a consistency check in the OtbnTraceChecker gets
confused because it sees a stall at one address, followed by an
execution at another.
Signed-off-by: Rupert Swarbrick <rswarbrick@lowrisc.org>
diff --git a/hw/ip/otbn/dv/model/iss_wrapper.cc b/hw/ip/otbn/dv/model/iss_wrapper.cc
index b32504e..14542d0 100644
--- a/hw/ip/otbn/dv/model/iss_wrapper.cc
+++ b/hw/ip/otbn/dv/model/iss_wrapper.cc
@@ -381,6 +381,11 @@
return mismatch ? -1 : (done ? 1 : 0);
}
+void ISSWrapper::reset(bool gen_trace) {
+ if (gen_trace)
+ OtbnTraceChecker::get().Flush();
+}
+
void ISSWrapper::get_regs(std::array<uint32_t, 32> *gprs,
std::array<u256_t, 32> *wdrs) {
assert(gprs && wdrs);
diff --git a/hw/ip/otbn/dv/model/iss_wrapper.h b/hw/ip/otbn/dv/model/iss_wrapper.h
index 8cacc9a..b9b3f82 100644
--- a/hw/ip/otbn/dv/model/iss_wrapper.h
+++ b/hw/ip/otbn/dv/model/iss_wrapper.h
@@ -57,6 +57,12 @@
// it's the value of the ERR_BITS register.
int step(bool gen_trace);
+ // Reset simulation
+ //
+ // This doesn't actually send anything to the ISS, but instead tells
+ // the OtbnTraceChecker to clear out any partial instructions
+ void reset(bool gen_trace);
+
// Get the current value of otbn.INSN_CNT. This should be called just after
// step (but doesn't necessarily need to wait until the run has finished).
uint32_t get_insn_cnt() const { return insn_cnt_; }
diff --git a/hw/ip/otbn/dv/model/otbn_core_model.sv b/hw/ip/otbn/dv/model/otbn_core_model.sv
index 0fbaaf7..e0311b1 100644
--- a/hw/ip/otbn/dv/model/otbn_core_model.sv
+++ b/hw/ip/otbn/dv/model/otbn_core_model.sv
@@ -52,7 +52,7 @@
string design_scope,
int unsigned imem_words,
int unsigned dmem_words);
- import "DPI-C" function void otbn_model_destroy(chandle handle);
+ import "DPI-C" function void otbn_model_destroy(chandle model);
import "DPI-C" context function
int unsigned otbn_model_step(chandle model,
logic start,
@@ -64,6 +64,7 @@
inout bit [31:0] insn_cnt,
inout bit [31:0] err_bits,
inout bit [31:0] stop_pc);
+ import "DPI-C" function void otbn_model_reset(chandle model);
localparam int ImemSizeWords = ImemSizeByte / 4;
@@ -116,7 +117,9 @@
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
- // Clear status (stop running, and forget any errors and final PC)
+ if (status != 0) begin
+ otbn_model_reset(model_handle);
+ end
status <= 0;
raw_err_bits_q <= 0;
stop_pc_q <= 0;
diff --git a/hw/ip/otbn/dv/model/otbn_model.cc b/hw/ip/otbn/dv/model/otbn_model.cc
index e6301a2..11b267a 100644
--- a/hw/ip/otbn/dv/model/otbn_model.cc
+++ b/hw/ip/otbn/dv/model/otbn_model.cc
@@ -660,3 +660,14 @@
return status;
}
+
+// Flush any information in the model
+extern "C" void otbn_model_reset(OtbnModel *model) {
+ assert(model);
+
+ ISSWrapper *iss = model->get_wrapper(false);
+ if (iss) {
+ bool check_rtl = (model->design_scope_.size() > 0);
+ iss->reset(check_rtl);
+ }
+}
diff --git a/hw/ip/otbn/dv/model/otbn_trace_checker.cc b/hw/ip/otbn/dv/model/otbn_trace_checker.cc
index 60b8fa8..7f6d8a1 100644
--- a/hw/ip/otbn/dv/model/otbn_trace_checker.cc
+++ b/hw/ip/otbn/dv/model/otbn_trace_checker.cc
@@ -176,6 +176,12 @@
return MatchPair();
}
+void OtbnTraceChecker::Flush() {
+ rtl_pending_ = false;
+ rtl_stall_ = false;
+ iss_pending_ = false;
+}
+
bool OtbnTraceChecker::Finish() {
assert(!(rtl_pending_ && iss_pending_));
done_ = true;
diff --git a/hw/ip/otbn/dv/model/otbn_trace_checker.h b/hw/ip/otbn/dv/model/otbn_trace_checker.h
index 886c933..eed21f4 100644
--- a/hw/ip/otbn/dv/model/otbn_trace_checker.h
+++ b/hw/ip/otbn/dv/model/otbn_trace_checker.h
@@ -60,6 +60,10 @@
// Prints an error message to stderr and returns false on mismatch.
bool OnIssTrace(const std::vector<std::string> &lines);
+ // Flush any pending entries. We need to do this on reset, to handle
+ // the case where we reset the processor in the middle of a stall.
+ void Flush();
+
// Call this when the ISS simulation completes an operation (on ECALL or
// error).
//