| // Copyright lowRISC contributors. |
| // Licensed under the Apache License, Version 2.0, see LICENSE for details. |
| // SPDX-License-Identifier: Apache-2.0 |
| #ifndef OPENTITAN_HW_IP_OTBN_DV_MODEL_OTBN_TRACE_CHECKER_H_ |
| #define OPENTITAN_HW_IP_OTBN_DV_MODEL_OTBN_TRACE_CHECKER_H_ |
| |
| // A singleton class that listens to trace entries from the simulated core (as |
| // an OtbnTraceListener) and compares them with the trace coming out of the |
| // stepped ISS process. |
| // |
| // Trace entries from the simulated core appear as a result of DPI callbacks, |
| // so there's no way to propagate errors when they appear. ISS trace entries |
| // arrive through a synchronous interface, so the checker reports any mismatch |
| // at that point. |
| // |
| // For example, if "RTL A" means "trace event A from RTL" and "ISS B" means |
| // "trace event B from ISS" then the following is a correct series of trace |
| // events: |
| // |
| // RTL A; ISS A; ISS B; RTL B ... |
| // |
| // None of these are valid: |
| // |
| // RTL A; RTL B; ... (*) |
| // ISS A; ISS B; ... |
| // RTL A; ISS B; ... |
| // |
| // The only way that an invalid trace is not reported is if no ISS trace events |
| // appear after the error. Trace (*), above, is an example of this. Another |
| // example would be if the last trace events were one of: |
| // |
| // ...; ISS A; RTL B |
| // ...; ISS A (and nothing else) |
| // |
| // To catch these cases, the ISS simulation must call the Finish() method when |
| // it is done (which checks there are no outstanding events missing). |
| |
| #include <iosfwd> |
| #include <string> |
| #include <vector> |
| |
| #include "otbn_trace_entry.h" |
| #include "otbn_trace_listener.h" |
| |
| class OtbnTraceChecker : public OtbnTraceListener { |
| public: |
| OtbnTraceChecker(); |
| ~OtbnTraceChecker(); |
| |
| // Get the singleton object |
| static OtbnTraceChecker &get(); |
| |
| // Take a trace entry from the wrapped RTL. Any mismatch error is stored |
| // until the next call to an API function that can respond with the error. |
| void AcceptTraceString(const std::string &trace, |
| unsigned int cycle_count) override; |
| |
| // Take a trace entry from the wrapped ISS. |
| // |
| // 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). |
| // |
| // Prints an error message to stderr and returns false if it detects a |
| // mismatch. |
| bool Finish(); |
| |
| // Return and clear the ISS data for the last pair of trace entries that went |
| // through MatchPair if there is any. |
| const OtbnIssTraceEntry::IssData *PopIssData(); |
| |
| // Tell the model not to execute checks to see if secure wiping has written |
| // random data to all registers before wiping them with zeroes on the next |
| // secure wipe entry. |
| void set_no_sec_wipe_chk(); |
| |
| private: |
| // If rtl_pending_ and iss_pending_ are not both true, return true |
| // immediately with no other change. Otherwise, compare the two pending trace |
| // entries. If they match, clear them both and return true. If not, print a |
| // message to stderr and return false. |
| bool MatchPair(); |
| |
| bool rtl_started_; |
| bool rtl_pending_; |
| OtbnTraceEntry rtl_entry_; |
| |
| bool iss_started_; |
| bool iss_pending_; |
| OtbnIssTraceEntry iss_entry_; |
| |
| bool done_; |
| bool seen_err_; |
| |
| // The ISS entry for the last pair of trace entries that went through |
| // MatchPair. |
| bool last_data_vld_; |
| OtbnIssTraceEntry::IssData last_data_; |
| bool no_sec_wipe_data_chk_; |
| }; |
| |
| #endif // OPENTITAN_HW_IP_OTBN_DV_MODEL_OTBN_TRACE_CHECKER_H_ |