mirror of
https://github.com/lowRISC/ibex.git
synced 2025-04-20 03:47:15 -04:00
[dv] Construct ISA string from RTL parameters for cosim tests
This commit is contained in:
parent
9943f9a42c
commit
9f14922382
12 changed files with 127 additions and 23 deletions
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue