blob: 8352a600555d00291db8e0c914000a4b08685d10 [file] [log] [blame]
// 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_MODEL_H_
#define OPENTITAN_HW_IP_OTBN_DV_MODEL_OTBN_MODEL_H_
#include <cstdint>
#include <stdexcept>
#include <string>
#include <svdpi.h>
#include <vector>
#include "otbn_memutil.h"
struct ISSWrapper;
class OtbnModel {
public:
enum command_t { Execute, DmemWipe, ImemWipe };
OtbnModel(const std::string &mem_scope, const std::string &design_scope);
~OtbnModel();
// Replace any current loop warps with those from memutil. Returns 0
// on success or -1 on failure. In the latter case, a message will
// already have been written to stderr.
int take_loop_warps(const OtbnMemUtil &memutil);
// True if this model is running in a simulation that has an RTL
// implementation too (which needs checking).
bool has_rtl() const { return !design_scope_.empty(); }
// Start an execution or an IMEM or DMEM secure wipe operation. Returns 0 on
// success; -1 on failure.
int start_operation(command_t command);
// Flush EDN data from model because of edn_rst_n. Returns 0 on success or -1
// on error.
int edn_flush();
// Send ISS some RND data from EDN. Returns 0 on success or -1 on error.
int edn_rnd_step(svLogicVecVal *edn_rnd_data /* logic [31:0] */,
unsigned char fips_err);
// Send ISS some URND data from EDN. Returns 0 on success or -1 on error.
int edn_urnd_step(svLogicVecVal *edn_urnd_data /* logic [31:0] */);
// Signal that RTL is finished processing RND data from EDN. Returns 0 on
// success or -1 on error.
int edn_rnd_cdc_done();
// Signal that RTL is finished processing data from EDN for URND. Returns 0
// on success or -1 on error.
int edn_urnd_cdc_done();
// Signal that RTL is finished processing OTP key. Returns 0 on success or -1
// on error.
int otp_key_cdc_done();
// Set or unset the two keys from keymgr. Returns 0 on success or -1
// on error.
int set_keymgr_value(svLogicVecVal *key0 /* logic [383:0] */,
svLogicVecVal *key1 /* logic [383:0] */,
unsigned char valid);
// Step once in the model. Returns 1 if the model has finished, 0 if not and
// -1 on failure. If gen_trace is true, pass trace entries to the trace
// checker. If the model has finished, writes otbn.ERR_BITS to *err_bits.
int step(svBitVecVal *status /* bit [7:0] */,
svBitVecVal *insn_cnt /* bit [31:0] */,
svBitVecVal *rnd_req /* bit [0:0] */,
svBitVecVal *err_bits /* bit [31:0] */,
svBitVecVal *stop_pc /* bit [31:0] */);
// Check model against RTL (if there is any) when a run has finished. Prints
// messages to stderr on failure or mismatch. Returns 1 for a match, 0 for a
// mismatch, -1 for some other failure.
int check() const;
// Grab contents of dmem from the model and load it back into the RTL
// simulation. This is used when there's no RTL model of the design. Returns
// 0 on success; -1 on failure.
int load_dmem();
// Mark all of IMEM as invalid so that any fetch causes an integrity
// error. Returns 0 on success; -1 on failure.
int invalidate_imem();
// Mark all of DMEM as invalid so that any load causes an integrity
// error. Returns 0 on success; -1 on failure.
int invalidate_dmem();
// Set software_errs_fatal bit in ISS model.
int set_software_errs_fatal(unsigned char new_val);
// Tell the model to not execute checks to see if secure wiping has written
// random data to all registers before wiping them with zeroes.
int set_no_sec_wipe_chk();
// Step CRC by consuming 48 bits of data.
//
// This doesn't actually update any internal state: we're just using the
// otbn_model framework as a convenient connection between SystemVerilog and
// Python. Returns 0 on success; -1 on failure.
int step_crc(const svBitVecVal *item /* bit [47:0] */,
svBitVecVal *state /* bit [31:0] */);
// Flush any information in the model. Returns 0 on success or -1 on error.
int reset(svBitVecVal *status /* bit [7:0] */,
svBitVecVal *insn_cnt /* bit [31:0] */,
svBitVecVal *rnd_req /* bit [0:0] */,
svBitVecVal *err_bits /* bit [31:0] */,
svBitVecVal *stop_pc /* bit [31:0] */);
// Escalate errors. Returns 0 on success; -1 on failure.
int send_err_escalation(svBitVecVal *err_val /* bit [31:0] */,
svBit lock_immediately);
// Returns true if we have an ISS wrapper and it has the START_WIPE flag
// asserted
bool is_at_start_of_wipe() const;
// Trigger initial secure wipe.
int initial_secure_wipe();
// Send RMA request to model.
int send_rma_req();
// Disable stack integrity checks
int disable_stack_check();
private:
// Constructs an ISS wrapper if necessary. If something goes wrong, this
// function prints a message and then returns null. If ensure is true, it
// will never return null without printing a message, so error handling at
// the callsite can silently return a failure code.
ISSWrapper *ensure_wrapper();
// Read the contents of the ISS's memory
Ecc32MemArea::EccWords get_sim_memory(bool is_imem) const;
// Set the contents of the ISS's memory
void set_sim_memory(bool is_imem, const Ecc32MemArea::EccWords &words);
// Grab contents of dmem from the model and compare them with the RTL. Prints
// messages to stderr on failure or mismatch. Returns true on success; false
// on mismatch. Throws a std::runtime_error on failure.
bool check_dmem(ISSWrapper &iss) const;
// Compare contents of ISS registers with those from the design. Prints
// messages to stderr on failure or mismatch. Returns true on success; false
// on mismatch. Throws a std::runtime_error on failure.
bool check_regs(ISSWrapper &iss) const;
// Compare contents of ISS call stack with those from the design. Prints
// messages to stderr on failure or mismatch. Returns true on success; false
// on mismatch. Throws a std::runtime_error on failure.
bool check_call_stack(ISSWrapper &iss) const;
// We want to create the model in an initial block in the SystemVerilog
// simulation, but might not actually want to spawn the ISS. To handle that
// in a non-racy way, the most convenient thing is to spawn the ISS the first
// time it's actually needed. Use ensure_wrapper() to create as needed.
std::unique_ptr<ISSWrapper> iss_;
OtbnMemUtil mem_util_;
std::string design_scope_;
bool stack_check_enabled_ = true;
};
#endif // OPENTITAN_HW_IP_OTBN_DV_MODEL_OTBN_MODEL_H_