diff --git a/dv/cosim/cosim.h b/dv/cosim/cosim.h index e6bd445e..f359a0dc 100644 --- a/dv/cosim/cosim.h +++ b/dv/cosim/cosim.h @@ -132,6 +132,10 @@ class Cosim { // Clear internal vector of error descriptions virtual void clear_errors() = 0; + + // Returns a count of instructions executed by co-simulator and DUT without + // failures. + virtual int get_insn_cnt() = 0; }; #endif // COSIM_H_ diff --git a/dv/cosim/cosim_dpi.cc b/dv/cosim/cosim_dpi.cc index 676fc85e..d931ecbe 100644 --- a/dv/cosim/cosim_dpi.cc +++ b/dv/cosim/cosim_dpi.cc @@ -92,3 +92,9 @@ void riscv_cosim_write_mem_byte(Cosim *cosim, const svBitVecVal *addr, uint8_t byte = d[0] & 0xff; cosim->backdoor_write_mem(addr[0], 1, &byte); } + +int riscv_cosim_get_insn_cnt(Cosim *cosim) { + assert(cosim); + + return cosim->get_insn_cnt(); +} diff --git a/dv/cosim/cosim_dpi.h b/dv/cosim/cosim_dpi.h index 7eb76259..1ded1b87 100644 --- a/dv/cosim/cosim_dpi.h +++ b/dv/cosim/cosim_dpi.h @@ -30,6 +30,7 @@ const char *riscv_cosim_get_error(Cosim *cosim, int index); void riscv_cosim_clear_errors(Cosim *cosim); void riscv_cosim_write_mem_byte(Cosim *cosim, const svBitVecVal *addr, const svBitVecVal *d); +int riscv_cosim_get_insn_cnt(Cosim *cosim); } #endif // COSIM_DPI_H_ diff --git a/dv/cosim/cosim_dpi.svh b/dv/cosim/cosim_dpi.svh index c9bdf6a7..82124448 100644 --- a/dv/cosim/cosim_dpi.svh +++ b/dv/cosim/cosim_dpi.svh @@ -22,3 +22,4 @@ import "DPI-C" function string riscv_cosim_get_error(chandle cosim_handle, int i import "DPI-C" function void riscv_cosim_clear_errors(chandle cosim_handle); import "DPI-C" function void riscv_cosim_write_mem_byte(chandle cosim_handle, bit [31:0] addr, bit [7:0] d); +import "DPI-C" function int riscv_cosim_get_insn_cnt(chandle cosim_handle); diff --git a/dv/cosim/spike_cosim.cc b/dv/cosim/spike_cosim.cc index 1da6dfd6..7d59dc3f 100644 --- a/dv/cosim/spike_cosim.cc +++ b/dv/cosim/spike_cosim.cc @@ -222,8 +222,14 @@ bool SpikeCosim::step(uint32_t write_reg, uint32_t write_reg_data, uint32_t pc, pending_iside_error = false; // Errors may have been generated outside of step() (e.g. in - // check_mem_access()), return false if there are any. - return errors.size() == 0; + // check_mem_access()). Only increment insn_cnt and return true if there are + // no errors + if (errors.size() == 0) { + insn_cnt++; + return true; + } + + return false; } bool SpikeCosim::check_gpr_write(const commit_log_reg_t::value_type ®_change, @@ -538,3 +544,5 @@ bool SpikeCosim::pc_is_mret(uint32_t pc) { return insn == 0x30200073; } + +int SpikeCosim::get_insn_cnt() { return insn_cnt; } diff --git a/dv/cosim/spike_cosim.h b/dv/cosim/spike_cosim.h index 46187dd4..ee811085 100644 --- a/dv/cosim/spike_cosim.h +++ b/dv/cosim/spike_cosim.h @@ -54,6 +54,8 @@ class SpikeCosim : public simif_t, public Cosim { void on_csr_write(const commit_log_reg_t::value_type ®_change); + int insn_cnt; + public: SpikeCosim(uint32_t start_pc, uint32_t start_mtvec, const std::string &trace_log_path, bool secure_ibex, @@ -87,6 +89,7 @@ class SpikeCosim : public simif_t, public Cosim { void set_iside_error(uint32_t addr) override; const std::vector &get_errors() override; void clear_errors() override; + int get_insn_cnt() override; }; #endif // SPIKE_COSIM_H_ diff --git a/dv/uvm/core_ibex/common/ibex_cosim_agent/ibex_cosim_scoreboard.sv b/dv/uvm/core_ibex/common/ibex_cosim_agent/ibex_cosim_scoreboard.sv index f4c105b5..c25a7937 100644 --- a/dv/uvm/core_ibex/common/ibex_cosim_agent/ibex_cosim_scoreboard.sv +++ b/dv/uvm/core_ibex/common/ibex_cosim_agent/ibex_cosim_scoreboard.sv @@ -224,6 +224,9 @@ class ibex_cosim_scoreboard extends uvm_scoreboard; function void final_phase(uvm_phase phase); super.final_phase(phase); + `uvm_info(`gfn, $sformatf("Co-simulation matched %d instructions", + riscv_cosim_get_insn_cnt(cosim_handle)), UVM_LOW) + if (cosim_handle) begin spike_cosim_release(cosim_handle); end