[dv] Construct ISA string from RTL parameters for cosim tests

This commit is contained in:
Rupert Swarbrick 2022-02-17 14:51:51 +00:00 committed by Rupert Swarbrick
parent 9943f9a42c
commit 9f14922382
12 changed files with 127 additions and 23 deletions

View file

@ -14,9 +14,9 @@
#include <iostream>
#include <sstream>
SpikeCosim::SpikeCosim(uint32_t start_pc, uint32_t start_mtvec,
const std::string &trace_log_path, bool secure_ibex,
bool icache_en)
SpikeCosim::SpikeCosim(const std::string &isa_string, uint32_t start_pc,
uint32_t start_mtvec, const std::string &trace_log_path,
bool secure_ibex, bool icache_en)
: nmi_mode(false), pending_iside_error(false) {
FILE *log_file = nullptr;
if (trace_log_path.length() != 0) {
@ -24,9 +24,9 @@ SpikeCosim::SpikeCosim(uint32_t start_pc, uint32_t start_mtvec,
log_file = log->get();
}
processor = std::make_unique<processor_t>("RV32IMC", "MU", DEFAULT_VARCH,
this, 0, false, log_file, nullptr,
secure_ibex, icache_en);
processor = std::make_unique<processor_t>(
isa_string.c_str(), "MU", DEFAULT_VARCH, this, 0, false, log_file,
nullptr, secure_ibex, icache_en);
processor->set_mmu_capability(IMPL_MMU_SBARE);
processor->get_state()->pc = start_pc;

View file

@ -68,9 +68,9 @@ class SpikeCosim : public simif_t, public Cosim {
int insn_cnt;
public:
SpikeCosim(uint32_t start_pc, uint32_t start_mtvec,
const std::string &trace_log_path, bool secure_ibex,
bool icache_en);
SpikeCosim(const std::string &isa_string, uint32_t start_pc,
uint32_t start_mtvec, const std::string &trace_log_path,
bool secure_ibex, bool icache_en);
// simif_t implementation
virtual char *addr_to_mem(reg_t addr) override;

View file

@ -3,12 +3,14 @@
// SPDX-License-Identifier: Apache-2.0
class core_ibex_cosim_cfg extends uvm_object;
string isa_string;
bit [31:0] start_pc;
bit [31:0] start_mtvec;
bit probe_imem_for_errs;
string log_file;
`uvm_object_utils_begin(core_ibex_cosim_cfg)
`uvm_field_string(isa_string, UVM_DEFAULT)
`uvm_field_int(start_pc, UVM_DEFAULT)
`uvm_field_int(start_mtvec, UVM_DEFAULT)
`uvm_field_int(probe_imem_for_errs, UVM_DEFAULT)

View file

@ -53,13 +53,21 @@ class ibex_cosim_scoreboard extends uvm_scoreboard;
`uvm_fatal(`gfn, "Cannot get instr_monitor_if")
end
init_cosim();
endfunction : build_phase
protected function void init_cosim();
if (cosim_handle) begin
spike_cosim_release(cosim_handle);
end
// TODO: Ensure log file on reset gets append rather than overwrite?
cosim_handle = spike_cosim_init(cfg.start_pc, cfg.start_mtvec, cfg.log_file);
cosim_handle = spike_cosim_init(cfg.isa_string, cfg.start_pc, cfg.start_mtvec, cfg.log_file);
if (cosim_handle == null) begin
`uvm_fatal(`gfn, "Could not initialise cosim")
end
endfunction : build_phase
endfunction
virtual task run_phase(uvm_phase phase);
wait (instr_vif.instr_cb.reset === 1'b0);
@ -262,11 +270,7 @@ class ibex_cosim_scoreboard extends uvm_scoreboard;
endfunction : final_phase
task handle_reset();
if (cosim_handle) begin
spike_cosim_release(cosim_handle);
end
cosim_handle = spike_cosim_init(cfg.start_pc, cfg.start_mtvec, cfg.log_file);
init_cosim();
wait (instr_vif.instr_cb.reset === 1'b0);
endtask
endclass : ibex_cosim_scoreboard

View file

@ -3,21 +3,25 @@
// SPDX-License-Identifier: Apache-2.0
#include <svdpi.h>
#include <cassert>
#include "cosim.h"
#include "spike_cosim.h"
extern "C" {
void *spike_cosim_init(svBitVecVal *start_pc, svBitVecVal *start_mtvec,
void *spike_cosim_init(const char *isa_string, svBitVecVal *start_pc,
svBitVecVal *start_mtvec,
const char *log_file_path_cstr) {
assert(isa_string);
std::string log_file_path;
if (log_file_path_cstr) {
log_file_path = log_file_path_cstr;
}
SpikeCosim *cosim =
new SpikeCosim(start_pc[0], start_mtvec[0], log_file_path, false, true);
SpikeCosim *cosim = new SpikeCosim(isa_string, start_pc[0], start_mtvec[0],
log_file_path, false, true);
cosim->add_memory(0x80000000, 0x80000000);
return static_cast<Cosim *>(cosim);
}

View file

@ -2,6 +2,10 @@
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
import "DPI-C" function chandle spike_cosim_init(bit [31:0] start_pc, bit [31:0] start_mtvec,
string log_file_path);
import "DPI-C" function
chandle spike_cosim_init(string isa_string,
bit [31:0] start_pc,
bit [31:0] start_mtvec,
string log_file_path);
import "DPI-C" function void spike_cosim_release(chandle cosim_handle);

View file

@ -256,6 +256,12 @@ module core_ibex_tb_top;
uvm_config_db#(virtual irq_if)::set(null, "*", "vif", irq_vif);
uvm_config_db#(virtual core_ibex_ifetch_if)::set(null, "*", "ifetch_if", ifetch_if);
uvm_config_db#(virtual core_ibex_ifetch_pmp_if)::set(null, "*", "ifetch_pmp_if", ifetch_pmp_if);
// Expose ISA config parameters to UVM DB
uvm_config_db#(bit)::set(null, "*", "RV32E", RV32E);
uvm_config_db#(ibex_pkg::rv32m_e)::set(null, "*", "RV32M", RV32M);
uvm_config_db#(ibex_pkg::rv32b_e)::set(null, "*", "RV32B", RV32B);
run_test();
end

View file

@ -39,6 +39,44 @@ class core_ibex_base_test extends uvm_test;
irq_collected_port = new("irq_collected_port_test", this);
endfunction
function string get_isa_string();
bit RV32E;
rv32m_e RV32M;
rv32b_e RV32B;
string isa;
if (!uvm_config_db#(bit)::get(null, "", "RV32E", RV32E)) begin
`uvm_fatal(`gfn, "Cannot get RV32E parameter")
end
if (!uvm_config_db#(rv32m_e)::get(null, "", "RV32M", RV32M)) begin
`uvm_fatal(`gfn, "Cannot get RV32M parameter")
end
if (!uvm_config_db#(rv32b_e)::get(null, "", "RV32B", RV32B)) begin
`uvm_fatal(`gfn, "Cannot get RV32B parameter")
end
// Construct the right ISA string for the cosimulator by looking at top-level testbench
// parameters.
//
// Note that the bitmanip extensions from the v0.93 spec (Zbe, Zbf, Zbp, Zbr, Zbt) are all
// contained in "Xbitmanip" for Spike at the moment. The specific parts used are listed in
// comments below.
isa = {"rv32", RV32E ? "e" : "i", "c"};
if (RV32M != RV32MNone) isa = {isa, "m"};
case (RV32B)
RV32BNone:
;
RV32BBalanced:
isa = {isa, "_Zba_Zbb_Zbs_Xbitmanip"}; // + Zbf, Zbt
RV32BOTEarlGrey:
isa = {isa, "_Zba_Zbb_Zbc_Zbs_Xbitmanip"}; // + Zbf, Zbp, Zbr, Zbt
RV32BFull:
isa = {isa, "_Zba_Zbb_Zbc_Zbs_Xbitmanip"}; // + Zbe, Zbf, Zbp, Zbr, Zbt
endcase
return isa;
endfunction
virtual function void build_phase(uvm_phase phase);
string cosim_log_file;
@ -63,6 +101,8 @@ class core_ibex_base_test extends uvm_test;
`ifdef INC_IBEX_COSIM
cosim_cfg = core_ibex_cosim_cfg::type_id::create("cosim_cfg", this);
cosim_cfg.isa_string = get_isa_string();
cosim_cfg.start_pc = {{32'h`BOOT_ADDR}[31:8], 8'h80};
cosim_cfg.start_mtvec = {{32'h`BOOT_ADDR}[31:8], 8'h1};
// TODO: Turn on when not using icache

View file

@ -30,8 +30,9 @@ class SimpleSystemCosim : public SimpleSystem {
return ret_code;
}
_cosim = std::make_unique<SpikeCosim>(
0x100080, 0x100001, "simple_system_cosim.log", false, false);
_cosim =
std::make_unique<SpikeCosim>(GetIsaString(), 0x100080, 0x100001,
"simple_system_cosim.log", false, false);
_cosim->add_memory(0x100000, 1024 * 1024);
_cosim->add_memory(0x20000, 4096);

View file

@ -2,9 +2,11 @@
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
#include <cassert>
#include <fstream>
#include <iostream>
#include "Vibex_simple_system__Syms.h"
#include "ibex_pcounts.h"
#include "ibex_simple_system.h"
#include "verilated_toplevel.h"
@ -31,6 +33,35 @@ int SimpleSystem::Main(int argc, char **argv) {
return 0;
}
std::string SimpleSystem::GetIsaString() const {
const Vibex_simple_system &top = _top;
assert(top.ibex_simple_system);
std::string base = top.ibex_simple_system->RV32E ? "rv32e" : "rv32i";
std::string extensions = "c";
if (top.ibex_simple_system->RV32M)
extensions += "m";
// See the equivalent get_isa_string() function in core_ibex_base_test.sv for
// an explanation of the different ISA strings
switch (top.ibex_simple_system->RV32B) {
case 0: // RV32BNone
break;
case 1: // RV32BBalanced
extensions += "_Zba_Zbb_Zbs_Xbitmanip";
break;
case 2: // RV32BOTEarlGrey
case 3: // RV32BFull
extensions += "_Zba_Zbb_Zbc_Zbs_Xbitmanip";
break;
}
return base + extensions;
}
int SimpleSystem::Setup(int argc, char **argv, bool &exit_app) {
VerilatorSimCtrl &simctrl = VerilatorSimCtrl::GetInstance();

View file

@ -11,6 +11,10 @@ class SimpleSystem {
virtual ~SimpleSystem() {}
virtual int Main(int argc, char **argv);
// Return an ISA string, as understood by Spike, for the system being
// simulated.
std::string GetIsaString() const;
protected:
ibex_simple_system _top;
VerilatorMemUtil _memutil;

View file

@ -30,3 +30,11 @@
//
lint_off -rule WIDTH -file "*/rtl/ibex_simple_system.sv"
-match "*expects 1 bits*Initial value's CONST '32'h1'*"
// This isn't a waiver, as such, but rather tells Verilator to expose
// the given parameters' values to C++. This allows cosim to figure
// out what flavour of core it is running, which allows us to call
// Spike with the right ISA.
public -module "ibex_simple_system" -var "RV32E"
public -module "ibex_simple_system" -var "RV32M"
public -module "ibex_simple_system" -var "RV32B"