add UVM interrupt agent (#2309)

This commit is contained in:
Jalali 2024-07-05 09:54:34 +00:00 committed by GitHub
parent 9900d5fd19
commit 2616d5e649
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
34 changed files with 1583 additions and 34 deletions

View file

@ -37,6 +37,7 @@ class uvme_cva6_cov_model_c extends uvm_component;
uvme_exception_cov_model_c exception_covg;
uvme_axi_covg_c axi_covg;
uvme_axi_ext_covg_c axi_ext_covg;
uvme_interrupt_covg_c interrupt_covg;
//
uvm_analysis_export#(uvma_clknrst_mon_trn_c) reset_export;
@ -101,12 +102,13 @@ function void uvme_cva6_cov_model_c::build_phase(uvm_phase phase);
`uvm_fatal("CNTXT", "Context handle is null")
end
if (cfg.cov_cvxif_model_enabled) begin
if (cfg.cvxif_cfg.cov_model_enabled) begin
cvxif_covg = uvme_cvxif_covg_c::type_id::create("cvxif_covg", this);
uvm_config_db#(uvme_cva6_cfg_c)::set(this, "cvxif_covg", "cfg", cfg);
uvm_config_db#(uvme_cva6_cntxt_c)::set(this, "cvxif_covg", "cntxt", cntxt);
end
if (cfg.cov_isa_model_enabled) begin
if (cfg.isacov_cfg.cov_model_enabled) begin
isa_covg = uvme_isa_cov_model_c::type_id::create("isa_covg", this);
illegal_covg = uvme_illegal_instr_cov_model_c::type_id::create("illegal_covg", this);
exception_covg = uvme_exception_cov_model_c::type_id::create("exception_covg", this);
@ -114,8 +116,6 @@ function void uvme_cva6_cov_model_c::build_phase(uvm_phase phase);
uvm_config_db#(uvme_cva6_cfg_c)::set(this, "illegal_covg", "cfg", cfg);
uvm_config_db#(uvme_cva6_cfg_c)::set(this, "exception_covg", "cfg", cfg);
end
uvm_config_db#(uvme_cva6_cntxt_c)::set(this, "cvxif_covg", "cntxt", cntxt);
config_covg = uvme_cva6_config_covg_c::type_id::create("config_covg", this);
uvm_config_db#(uvme_cva6_cfg_c)::set(this, "config_covg", "cfg", cfg);
@ -130,6 +130,12 @@ function void uvme_cva6_cov_model_c::build_phase(uvm_phase phase);
uvm_config_db#(uvme_cva6_cntxt_c)::set(this, "axi_ext_covg", "cntxt", cntxt);
end
if(cfg.interrupt_cfg.cov_model_enabled) begin
interrupt_covg = uvme_interrupt_covg_c::type_id::create("interrupt_covg", this);
uvm_config_db#(uvme_cva6_cfg_c)::set(this, "interrupt_covg", "cfg", cfg);
uvm_config_db#(uvme_cva6_cntxt_c)::set(this, "interrupt_covg", "cntxt", cntxt);
end
endfunction : build_phase
function void uvme_cva6_cov_model_c::connect_phase(uvm_phase phase);

View file

@ -0,0 +1,126 @@
//
// Copyright 2024 OpenHW Group
// Copyright 2024 Thales
//
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://solderpad.org/licenses/
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
// Original Author: Ayoub JALALI (ayoub.jalali@external.thalesgroup.com)
covergroup cg_interrupt(
string name
) with function sample (
uvma_isacov_instr_c instr
);
option.per_instance = 1;
option.name = name;
cp_interrupt: coverpoint instr.rvfi.name_csrs["mcause"].wdata {
bins NO_INTERRUPT = {0} iff (!instr.trap);
bins MACHINE_MODE_EXTERNAL_INTERRUPT = {32'h8000000b} iff (instr.trap);
bins MACHINE_MODE_SOFTWARE_INTERRUPT = {32'h80000003} iff (instr.trap);
bins MACHINE_MODE_TIMER_INTERRUPT = {32'h80000007} iff (instr.trap);
}
cp_mstatus_mie: coverpoint instr.rvfi.name_csrs["mstatus"].wdata[3] {
bins GLOBAL_INTERRUPT_ENABLE = {1'h1};
}
cp_msie: coverpoint instr.rvfi.name_csrs["mie"].wdata[3] {
bins MSIE = {1'h1};
}
cp_mtie: coverpoint instr.rvfi.name_csrs["mie"].wdata[7] {
bins MTIE = {1'h1};
}
cp_meie: coverpoint instr.rvfi.name_csrs["mie"].wdata[11] {
bins MEIE = {1'h1};
}
cp_msip: coverpoint instr.rvfi.name_csrs["mip"].wdata[3] {
bins MSIP = {1'h1};
}
cp_mtip: coverpoint instr.rvfi.name_csrs["mip"].wdata[7] {
bins MTIP = {1'h1};
}
cp_meip: coverpoint instr.rvfi.name_csrs["mip"].wdata[11] {
bins MEIP = {1'h1};
}
endgroup : cg_interrupt
class uvme_interrupt_covg_c extends uvm_component;
/*
* Class members
*/
// Objects
uvme_cva6_cfg_c cfg ;
uvme_cva6_cntxt_c cntxt ;
// TLM
uvm_tlm_analysis_fifo#(uvma_isacov_mon_trn_c) mon_trn_fifo;
uvma_isacov_mon_trn_c mon_trn;
`uvm_component_utils(uvme_interrupt_covg_c)
//Interrupt Covergroup
cg_interrupt interrupt_cg;
extern function new(string name = "interrupt_covg", uvm_component parent = null);
extern function void build_phase(uvm_phase phase);
extern task run_phase(uvm_phase phase);
endclass : uvme_interrupt_covg_c
function uvme_interrupt_covg_c::new(string name = "interrupt_covg", uvm_component parent = null);
super.new(name, parent);
endfunction : new
function void uvme_interrupt_covg_c::build_phase(uvm_phase phase);
super.build_phase(phase);
void'(uvm_config_db#(uvme_cva6_cfg_c)::get(this, "", "cfg", cfg));
if (!cfg) begin
`uvm_fatal("CFG", "Configuration handle is null")
end
interrupt_cg = new("interrupt_cg");
mon_trn_fifo = new("mon_trn_fifo" , this);
endfunction : build_phase
task uvme_interrupt_covg_c::run_phase(uvm_phase phase);
super.run_phase(phase);
`uvm_info(get_type_name(), "The Interrupt env coverage model is running", UVM_LOW);
forever begin
mon_trn_fifo.get(mon_trn);
interrupt_cg.sample(mon_trn.instr);
end
endtask : run_phase

16
verif/env/uvme/uvma_interrupt/README.md vendored Normal file
View file

@ -0,0 +1,16 @@
Description of the interrupt agent.
- The interrupt agent supports mainly 3 modes:
1 - The agent sends one interrupt request, then we deassert it.
2 - The agent sends several interrupt requests at the same time, with the same size, then we deassert the interrupt requests.
3 - The agent sends randomized interrupt requests.
- The interrupt agent has 2 type of delays in `uvma_interrupt_seq_item.sv`:
1 - `irq_delay` is related to the delay between two interrupt request.
2 - `irq_time` is related to the time the interrupt request could take.
- The interrupt agent sends requests asynchronously.
- To enable interrupt requests you should add the option `"+enable_interrupt"`.
- There is no mechanism to clear the interrupt requests (on going).

View file

@ -0,0 +1,111 @@
// Copyright 2024 Thales DIS SAS
//
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
// You may obtain a copy of the License at https://solderpad.org/licenses/
//
// Original Author: Ayoub JALALI (ayoub.jalali@external.thalesgroup.com)
`ifndef __UVMA_INTERRUPT_COV_MODEL_SV__
`define __UVMA_INTERRUPT_COV_MODEL_SV__
covergroup cg_interrupt(
string name
) with function
sample(uvma_interrupt_seq_item_c req_item);
option.per_instance = 1;
option.name = name;
cp_interrupt_req : coverpoint req_item.interrupt_valid;
endgroup: cg_interrupt
/**
* Component encapsulating Interrupt functional coverage model.
*/
class uvma_interrupt_cov_model_c extends uvm_component;
// Objects
uvma_interrupt_cfg_c cfg;
uvma_interrupt_cntxt_c cntxt;
uvma_interrupt_seq_item_c req_item;
// TLM
uvm_tlm_analysis_fifo#(uvma_interrupt_seq_item_c) seq_item_fifo;
`uvm_component_utils_begin(uvma_interrupt_cov_model_c)
`uvm_field_object(cfg , UVM_DEFAULT)
`uvm_field_object(cntxt, UVM_DEFAULT)
`uvm_component_utils_end
cg_interrupt interrupt_cg;
/**
* Default constructor.
*/
extern function new(string name="uvma_interrupt_cov_model", uvm_component parent=null);
/**
* 1. Ensures cfg & cntxt handles are not null.
* 2. Builds fifos.
*/
extern virtual function void build_phase(uvm_phase phase);
/**
* Forks all sampling loops
*/
extern virtual task run_phase(uvm_phase phase);
endclass : uvma_interrupt_cov_model_c
function uvma_interrupt_cov_model_c::new(string name="uvma_interrupt_cov_model", uvm_component parent=null);
super.new(name, parent);
endfunction : new
function void uvma_interrupt_cov_model_c::build_phase(uvm_phase phase);
super.build_phase(phase);
void'(uvm_config_db#(uvma_interrupt_cfg_c)::get(this, "", "cfg", cfg));
if (cfg == null) begin
`uvm_fatal("CFG", "Configuration handle is null")
end
void'(uvm_config_db#(uvma_interrupt_cntxt_c)::get(this, "", "cntxt", cntxt));
if (cntxt == null) begin
`uvm_fatal("CNTXT", "Context handle is null")
end
interrupt_cg = new("interrupt_cg");
seq_item_fifo = new("seq_item_fifo", this);
endfunction : build_phase
task uvma_interrupt_cov_model_c::run_phase(uvm_phase phase);
super.run_phase(phase);
if (cfg.enabled && cfg.cov_model_enabled) begin
// Sequence items
forever begin
seq_item_fifo.get(req_item);
interrupt_cg.sample(req_item);
end
end
endtask : run_phase
`endif // __UVMA_INTERRUPT_COV_MODEL_SV__

View file

@ -0,0 +1,55 @@
// Copyright 2024 Thales DIS SAS
//
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
// You may obtain a copy of the License at https://solderpad.org/licenses/
//
// Original Author: Ayoub JALALI (ayoub.jalali@external.thalesgroup.com)
`ifndef __UVMA_INTERRUPT_BASE_SEQ_SV__
`define __UVMA_INTERRUPT_BASE_SEQ_SV__
/**
* Abstract object from which all other Interrupt agent sequences must extend.
* Subclasses must be run on Interrupt sequencer (uvma_interrupt_sqr_c) instance.
*/
class uvma_interrupt_base_seq_c extends uvm_sequence#(uvma_interrupt_seq_item_c);
`uvm_object_utils(uvma_interrupt_base_seq_c)
`uvm_declare_p_sequencer(uvma_interrupt_sqr_c)
// Objects
uvma_interrupt_cfg_c cfg;
uvma_interrupt_cntxt_c cntxt;
uvma_interrupt_seq_item_c req_item;
/**
* Default constructor.
*/
extern function new(string name="uvma_interrupt_base_seq");
/**
* Assigns cfg and cntxt handles from p_sequencer.
*/
extern virtual task pre_start();
endclass : uvma_interrupt_base_seq_c
function uvma_interrupt_base_seq_c::new(string name="uvma_interrupt_base_seq");
super.new(name);
endfunction : new
task uvma_interrupt_base_seq_c::pre_start();
cfg = p_sequencer.cfg;
cntxt = p_sequencer.cntxt;
endtask : pre_start
`endif // __UVMA_INTERRUPT_BASE_SEQ_SV__

View file

@ -0,0 +1,60 @@
// Copyright 2024 Thales DIS SAS
//
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
// You may obtain a copy of the License at https://solderpad.org/licenses/
//
// Original Author: Ayoub JALALI (ayoub.jalali@external.thalesgroup.com)
`ifndef __UVMA_INTERRUPT_SEQ_SV__
`define __UVMA_INTERRUPT_SEQ_SV__
/**
* Abstract object from which all other Interrupt agent sequences must extend.
* Subclasses must be run on Interrupt sequencer (uvma_interrupt_sqr_c) instance.
*/
class uvma_interrupt_seq_c extends uvma_interrupt_base_seq_c;
`uvm_object_utils(uvma_interrupt_seq_c)
`uvm_declare_p_sequencer(uvma_interrupt_sqr_c)
/**
* Default constructor.
*/
extern function new(string name="uvma_interrupt_seq");
extern virtual task body();
endclass : uvma_interrupt_seq_c
function uvma_interrupt_seq_c::new(string name="uvma_interrupt_seq");
super.new(name);
endfunction : new
task uvma_interrupt_seq_c::body();
forever begin
req_item = uvma_interrupt_seq_item_c::type_id::create("req_item");
start_item(req_item);
assert(req_item.randomize() with {
if(!cfg.enable_interrupt){
req_item.interrupt_valid == 'h0;
}
else {
req_item.irq_cntrl != UVMA_INTERRUPT_RANDOMIZE;
}
})
cfg.calc_random_req_latency();
finish_item(req_item);
end
endtask : body
`endif // __UVMA_INTERRUPT_SEQ_SV__

View file

@ -0,0 +1,66 @@
// Copyright 2024 Thales DIS SAS
//
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
// You may obtain a copy of the License at https://solderpad.org/licenses/
//
// Original Author: Ayoub JALALI (ayoub.jalali@external.thalesgroup.com)
`ifndef __UVMA_INTERRUPT_SEQ_ITEM_SV__
`define __UVMA_INTERRUPT_SEQ_ITEM_SV__
/**
* Object created by Interrupt agent sequences extending uvma_interrupt_seq_base_c.
*/
class uvma_interrupt_seq_item_c extends uvml_trn_seq_item_c;
rand uvma_interrupt_cntrl_enum irq_cntrl;
rand int unsigned irq_delay; // Delay before applying individual interrupt
rand int unsigned irq_time; // How many cycles take an interrupt
rand bit[NUM_IRQ-1:0] interrupt_valid; //the valid interrupts for the core under test
`uvm_object_utils_begin(uvma_interrupt_seq_item_c)
`uvm_field_enum(uvma_interrupt_cntrl_enum, irq_cntrl, UVM_DEFAULT)
`uvm_field_int(irq_delay, UVM_DEFAULT)
`uvm_field_int(irq_time, UVM_DEFAULT)
`uvm_field_int(interrupt_valid, UVM_DEFAULT)
`uvm_object_utils_end
constraint default_irq_delay_c {
irq_delay inside {[150:250]};
}
constraint default_irq_time_c {
irq_time inside {[5:10]};
}
constraint irq_mode_c {
if (irq_cntrl == UVMA_INTERRUPT_ONE_BY_ONE) {
$countones(interrupt_valid) == 1;
}
if (irq_cntrl == UVMA_INTERRUPT_MORE_THAN_ONE) {
$countones(interrupt_valid) > 1;
}
}
/**
* Default constructor.
*/
extern function new(string name="uvma_interrupt_seq_item");
endclass : uvma_interrupt_seq_item_c
function uvma_interrupt_seq_item_c::new(string name="uvma_interrupt_seq_item");
super.new(name);
endfunction : new
`endif // __UVMA_INTERRUPT_SEQ_ITEM_SV__

View file

@ -0,0 +1,182 @@
// Copyright 2024 Thales DIS SAS
//
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
// You may obtain a copy of the License at https://solderpad.org/licenses/
//
// Original Author: Ayoub JALALI (ayoub.jalali@external.thalesgroup.com)
`ifndef __UVMA_INTERRUPT_AGENT_SV__
`define __UVMA_INTERRUPT_AGENT_SV__
class uvma_interrupt_agent_c extends uvm_agent;
// Objects
uvma_interrupt_cfg_c cfg;
uvma_interrupt_cntxt_c cntxt;
// Components
uvma_interrupt_mon_c monitor;
uvma_interrupt_drv_c driver;
uvma_interrupt_sqr_c sequencer;
uvma_interrupt_cov_model_c cov_model;
`uvm_component_utils_begin(uvma_interrupt_agent_c)
`uvm_field_object(cfg , UVM_DEFAULT)
`uvm_field_object(cntxt, UVM_DEFAULT)
`uvm_component_utils_end
/**
* Default constructor.
*/
extern function new(string name="uvma_interrupt_agent", uvm_component parent=null);
/**
* 1. Ensures cfg & cntxt handles are not null
* 2. Builds all components
*/
extern virtual function void build_phase(uvm_phase phase);
/**
* 1. Links agent's analysis ports to sub-components'
* 2. Connects coverage models and loggers
*/
extern virtual function void connect_phase(uvm_phase phase);
/**
* Uses uvm_config_db to retrieve cfg and hand out to sub-components.
*/
extern function void get_and_set_cfg();
/**
* Uses uvm_config_db to retrieve cntxt and hand out to sub-components.
*/
extern function void get_and_set_cntxt();
/**
* Uses uvm_config_db to retrieve the Virtual Interface (vif) associated with this
* agent.
*/
extern function void retrieve_vif();
/**
* Creates sub-components.
*/
extern function void create_components();
/**
* Connects sequencer and driver's TLM port(s).
*/
extern function void connect_sequencer_and_driver();
/**
* Connects coverage model to monitor and driver's analysis ports.
*/
extern function void connect_cov_model();
endclass : uvma_interrupt_agent_c
function uvma_interrupt_agent_c::new(string name="uvma_interrupt_agent", uvm_component parent=null);
super.new(name, parent);
endfunction : new
function void uvma_interrupt_agent_c::build_phase(uvm_phase phase);
super.build_phase(phase);
get_and_set_cfg ();
get_and_set_cntxt();
retrieve_vif ();
create_components();
endfunction : build_phase
function void uvma_interrupt_agent_c::connect_phase(uvm_phase phase);
super.connect_phase(phase);
connect_sequencer_and_driver();
connect_cov_model();
endfunction: connect_phase
function void uvma_interrupt_agent_c::get_and_set_cfg();
void'(uvm_config_db#(uvma_interrupt_cfg_c)::get(this, "", "cfg", cfg));
if (cfg == null) begin
`uvm_fatal("CFG", "Configuration handle is null")
end
else begin
`uvm_info("CFG", $sformatf("Found configuration handle:\n%s", cfg.sprint()), UVM_DEBUG)
uvm_config_db#(uvma_interrupt_cfg_c)::set(this, "*", "cfg", cfg);
end
endfunction : get_and_set_cfg
function void uvma_interrupt_agent_c::get_and_set_cntxt();
void'(uvm_config_db#(uvma_interrupt_cntxt_c)::get(this, "", "cntxt", cntxt));
if (cntxt == null) begin
`uvm_info("CNTXT", "Context handle is null; creating.", UVM_DEBUG)
cntxt = uvma_interrupt_cntxt_c::type_id::create("cntxt");
end
uvm_config_db#(uvma_interrupt_cntxt_c)::set(this, "*", "cntxt", cntxt);
endfunction : get_and_set_cntxt
function void uvma_interrupt_agent_c::retrieve_vif();
if (!uvm_config_db#(virtual uvma_interrupt_if)::get(this, "", "interrupt_vif", cntxt.interrupt_vif)) begin
`uvm_fatal("VIF", $sformatf("Could not find vif handle of type %s in uvm_config_db", $typename(cntxt.interrupt_vif)))
end
else begin
`uvm_info("VIF", $sformatf("Found vif handle of type %s in uvm_config_db", $typename(cntxt.interrupt_vif)), UVM_DEBUG)
end
endfunction : retrieve_vif
function void uvma_interrupt_agent_c::create_components();
monitor = uvma_interrupt_mon_c ::type_id::create("monitor" , this);
if (cfg.is_active == UVM_ACTIVE) begin
sequencer = uvma_interrupt_sqr_c ::type_id::create("sequencer" , this);
driver = uvma_interrupt_drv_c ::type_id::create("driver" , this);
end
if (cfg.cov_model_enabled) begin
cov_model = uvma_interrupt_cov_model_c ::type_id::create("cov_model" , this);
end
endfunction : create_components
function void uvma_interrupt_agent_c::connect_sequencer_and_driver();
if (cfg.is_active == UVM_ACTIVE) begin
driver.seq_item_port.connect(sequencer.seq_item_export);
end
endfunction : connect_sequencer_and_driver
function void uvma_interrupt_agent_c::connect_cov_model();
if (cfg.cov_model_enabled) begin
monitor.ap.connect(cov_model.seq_item_fifo.analysis_export);
end
endfunction : connect_cov_model
`endif // __UVMA_INTERRUPT_AGENT_SV__

View file

@ -0,0 +1,115 @@
// Copyright 2024 Thales DIS SAS
//
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
// You may obtain a copy of the License at https://solderpad.org/licenses/
//
// Original Author: Ayoub JALALI (ayoub.jalali@external.thalesgroup.com)
`ifndef __UVMA_INTERRUPT_CFG_SV__
`define __UVMA_INTERRUPT_CFG_SV__
class uvma_interrupt_cfg_c extends uvm_object;
// Common options
rand bit enabled;
rand uvm_active_passive_enum is_active;
rand bit cov_model_enabled;
rand bit trn_log_enabled;
rand bit enable_interrupt;
bit interrupt_plusarg_valid;
// Interrupt request latency modes
rand uvma_interrupt_drv_req_enum drv_req_mode;
rand int unsigned drv_req_fixed_latency;
rand int unsigned drv_req_random_latency_min;
rand int unsigned drv_req_random_latency_max;
`uvm_object_utils_begin(uvma_interrupt_cfg_c)
`uvm_field_int ( enabled , UVM_DEFAULT)
`uvm_field_enum(uvm_active_passive_enum, is_active , UVM_DEFAULT)
`uvm_field_int ( cov_model_enabled , UVM_DEFAULT)
`uvm_field_int ( trn_log_enabled , UVM_DEFAULT)
`uvm_field_int ( enable_interrupt , UVM_DEFAULT)
`uvm_field_int ( interrupt_plusarg_valid , UVM_DEFAULT)
`uvm_field_enum(uvma_interrupt_drv_req_enum, drv_req_mode , UVM_DEFAULT)
`uvm_field_int ( drv_req_fixed_latency , UVM_DEFAULT)
`uvm_field_int ( drv_req_random_latency_min , UVM_DEFAULT)
`uvm_field_int ( drv_req_random_latency_max , UVM_DEFAULT)
`uvm_object_utils_end
constraint defaults_cons {
soft enabled == 1;
soft is_active == UVM_PASSIVE;
soft cov_model_enabled == 1;
soft trn_log_enabled == 1;
}
constraint default_enable_irq_cons {
soft enable_interrupt == 0;
}
constraint default_drive_req_mode_cons {
soft drv_req_mode == UVMA_INTERRUPT_DRV_REQ_MODE_FIXED_LATENCY;
}
constraint default_fixed_req_latency_cons {
soft drv_req_fixed_latency inside {[250:300]};
}
constraint valid_random_req_latency_cons {
drv_req_random_latency_min < drv_req_random_latency_max;
}
constraint default_random_latency_cons {
soft drv_req_random_latency_min inside {[50:100]};
soft drv_req_random_latency_max inside {[150:200]};
}
/**
* Default constructor.
*/
extern function new(string name="uvma_interrupt_cfg");
/**
* Calculate a new random gnt latency
*/
extern function int unsigned calc_random_req_latency();
endclass : uvma_interrupt_cfg_c
function uvma_interrupt_cfg_c::new(string name="uvma_interrupt_cfg");
super.new(name);
// Read plusargs for defaults
if ($test$plusargs("enable_interrupt")) begin
interrupt_plusarg_valid = 1;
end
endfunction : new
function int unsigned uvma_interrupt_cfg_c::calc_random_req_latency();
int unsigned req_latency;
case (drv_req_mode)
UVMA_INTERRUPT_DRV_REQ_MODE_CONSTANT : req_latency = 0;
UVMA_INTERRUPT_DRV_REQ_MODE_FIXED_LATENCY : req_latency = drv_req_fixed_latency;
UVMA_INTERRUPT_DRV_REQ_MODE_RANDOM_LATENCY: begin
req_latency = $urandom_range(drv_req_random_latency_min, drv_req_random_latency_max);
end
endcase
return req_latency;
endfunction : calc_random_req_latency
`endif // __UVMA_INTERRUPT_CFG_SV__

View file

@ -0,0 +1,68 @@
// Copyright 2024 Thales DIS SAS
//
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
// You may obtain a copy of the License at https://solderpad.org/licenses/
//
// Original Author: Ayoub JALALI (ayoub.jalali@external.thalesgroup.com)
`ifndef __UVMA_INTERRUPT_CNTXT_SV__
`define __UVMA_INTERRUPT_CNTXT_SV__
/**
* Object encapsulating all state variables for all Interrupt agent
* (uvma_interrupt_agent_c) components.
*/
class uvma_interrupt_cntxt_c extends uvm_object;
// Handle to agent interface
virtual uvma_interrupt_if interrupt_vif;
// Events
uvm_event sample_cfg_e;
uvm_event sample_cntxt_e;
`uvm_object_utils_begin(uvma_interrupt_cntxt_c)
`uvm_field_event(sample_cfg_e , UVM_DEFAULT)
`uvm_field_event(sample_cntxt_e, UVM_DEFAULT)
`uvm_object_utils_end
/**
* Builds events.
*/
extern function new(string name="uvma_interrupt_cntxt");
/**
* TODO Describe uvma_interrupt_cntxt_c::reset()
*/
extern function void reset();
endclass : uvma_interrupt_cntxt_c
`pragma protect begin
function uvma_interrupt_cntxt_c::new(string name="uvma_interrupt_cntxt");
super.new(name);
sample_cfg_e = new("sample_cfg_e" );
sample_cntxt_e = new("sample_cntxt_e");
endfunction : new
function void uvma_interrupt_cntxt_c::reset();
// TODO Implement uvma_interrupt_cntxt_c::reset()
endfunction : reset
`pragma protect end
`endif // __UVMA_INTERRUPT_CNTXT_SV__

View file

@ -0,0 +1,14 @@
// Copyright 2024 Thales DIS SAS
//
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
// You may obtain a copy of the License at https://solderpad.org/licenses/
//
// Original Author: Ayoub JALALI (ayoub.jalali@external.thalesgroup.com)
`ifndef __UVMA_INTERRUPT_CONSTANTS_SV__
`define __UVMA_INTERRUPT_CONSTANTS_SV__
`endif // __UVMA_INTERRUPT_CONSTANTS_SV__

View file

@ -0,0 +1,165 @@
// Copyright 2024 Thales DIS SAS
//
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
// You may obtain a copy of the License at https://solderpad.org/licenses/
//
// Original Author: Ayoub JALALI (ayoub.jalali@external.thalesgroup.com)
`ifndef __UVMA_INTERRUPT_DRV_SV__
`define __UVMA_INTERRUPT_DRV_SV__
/**
* Component driving interrupt virtual interface (uvma_interrupt_if).
*/
class uvma_interrupt_drv_c extends uvm_driver#(uvma_interrupt_seq_item_c);
// Objects
uvma_interrupt_cfg_c cfg;
uvma_interrupt_cntxt_c cntxt;
uvma_interrupt_seq_item_c req_item;
`uvm_component_utils_begin(uvma_interrupt_drv_c)
`uvm_field_object(cfg , UVM_DEFAULT)
`uvm_field_object(cntxt, UVM_DEFAULT)
`uvm_component_utils_end
/**
* Default constructor.
*/
extern function new(string name="uvma_interrupt_drv", uvm_component parent=null);
/**
* 1. Ensures cfg & cntxt handles are not null.
* 2. Builds ap.
*/
extern virtual function void build_phase(uvm_phase phase);
/**
* Obtains the reqs from the sequence item port and calls drv_irq()
*/
extern virtual task run_phase(uvm_phase phase);
/**
* Drives the virtual interface's (cntxt.interrupt_vif) signals using req's contents.
*/
extern task drv_irq(uvma_interrupt_seq_item_c req);
/**
* Assert only one interrupt each time
*/
extern task assert_irq_one_by_one(uvma_interrupt_seq_item_c req);
/**
* Assert one or more interrupt each time
*/
extern task assert_irq_more(uvma_interrupt_seq_item_c req);
/**
* Randomize interrupt signal
*/
extern task assert_irq_randomize(uvma_interrupt_seq_item_c req);
endclass : uvma_interrupt_drv_c
function uvma_interrupt_drv_c::new(string name="uvma_interrupt_drv", uvm_component parent=null);
super.new(name, parent);
endfunction : new
function void uvma_interrupt_drv_c::build_phase(uvm_phase phase);
super.build_phase(phase);
void'(uvm_config_db#(uvma_interrupt_cfg_c)::get(this, "", "cfg", cfg));
if (cfg == null) begin
`uvm_fatal("CFG", "Configuration handle is null")
end
uvm_config_db#(uvma_interrupt_cfg_c)::set(this, "*", "cfg", cfg);
void'(uvm_config_db#(uvma_interrupt_cntxt_c)::get(this, "", "cntxt", cntxt));
if (cntxt == null) begin
`uvm_fatal("CNTXT", "Context handle is null")
end
uvm_config_db#(uvma_interrupt_cntxt_c)::set(this, "*", "cntxt", cntxt);
req_item = uvma_interrupt_seq_item_c::type_id::create("req_item");
endfunction : build_phase
task uvma_interrupt_drv_c::run_phase(uvm_phase phase);
super.run_phase(phase);
//Initial the interface before the CPU start
cntxt.interrupt_vif.irq <= 'h0;
if(!cfg.enable_interrupt) begin
`uvm_warning(get_type_name(), "Driving Interrupt reqeust is disabled");
return;
end
forever begin
seq_item_port.get_next_item(req_item);
drv_irq(req_item);
seq_item_port.item_done();
end
endtask : run_phase
task uvma_interrupt_drv_c::drv_irq(uvma_interrupt_seq_item_c req);
`uvm_info(get_type_name(), $sformatf("Driving:\n%s", req.sprint()), UVM_HIGH);
case (req.irq_cntrl)
UVMA_INTERRUPT_ONE_BY_ONE: begin
assert_irq_one_by_one(req);
end
UVMA_INTERRUPT_MORE_THAN_ONE: begin
assert_irq_more(req);
end
UVMA_INTERRUPT_RANDOMIZE: begin
assert_irq_randomize(req);
end
endcase
endtask : drv_irq
task uvma_interrupt_drv_c::assert_irq_one_by_one(uvma_interrupt_seq_item_c req);
#req.irq_delay;
cntxt.interrupt_vif.irq <= req.interrupt_valid;
`uvm_info(get_type_name(), $sformatf("Assert interrupt channel(s) %0b", req.interrupt_valid), UVM_HIGH)
#req.irq_time;
cntxt.interrupt_vif.irq <= 'h0;
endtask : assert_irq_one_by_one
task uvma_interrupt_drv_c::assert_irq_more(uvma_interrupt_seq_item_c req);
#req.irq_delay;
cntxt.interrupt_vif.irq <= req.interrupt_valid;
#req.irq_time;
cntxt.interrupt_vif.irq <= 'h0;
endtask : assert_irq_more
task uvma_interrupt_drv_c::assert_irq_randomize(uvma_interrupt_seq_item_c req);
repeat(5) begin
#req.irq_delay;
cntxt.interrupt_vif.irq <= req.interrupt_valid;
#req.irq_time;
end
cntxt.interrupt_vif.irq <= 'h0;
cfg.calc_random_req_latency();
endtask : assert_irq_randomize
`endif // __UVMA_INTERRUPT_DRV_SV__

View file

@ -0,0 +1,28 @@
// Copyright 2024 Thales DIS SAS
//
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
// You may obtain a copy of the License at https://solderpad.org/licenses/
//
// Original Author: Ayoub JALALI (ayoub.jalali@external.thalesgroup.com)
`ifndef __UVMA_INTERRUPT_IF_SV__
`define __UVMA_INTERRUPT_IF_SV__
/**
* Encapsulates all signals and clocking of Interrupt interface. Used by
* monitor and driver.
*/
interface uvma_interrupt_if
(
);
logic [uvma_interrupt_pkg::NUM_IRQ-1:0] irq;
endinterface : uvma_interrupt_if
`endif // __UVMA_INTERRUPT_IF_SV__

View file

@ -0,0 +1,25 @@
// Copyright 2020 OpenHW Group
// Copyright 2020 Datum Technology Corporation
// Copyright 2020 Silicon Labs, Inc.
//
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://solderpad.org/licenses/
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
`ifndef __UVMA_INTERRUPT_MACROS_SV__
`define __UVMA_INTERRUPT_MACROS_SV__
`endif // __UVMA_INTERRUPT_MACROS_SV__

View file

@ -0,0 +1,114 @@
// Copyright 2024 Thales DIS SAS
//
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
// You may obtain a copy of the License at https://solderpad.org/licenses/
//
// Original Author: Ayoub JALALI (ayoub.jalali@external.thalesgroup.com)
`ifndef __UVMA_INTERRUPT_MON_SV__
`define __UVMA_INTERRUPT_MON_SV__
class uvma_interrupt_mon_c extends uvm_monitor;
// Objects
uvma_interrupt_cfg_c cfg;
uvma_interrupt_cntxt_c cntxt;
`uvm_component_utils_begin(uvma_interrupt_mon_c)
`uvm_field_object(cfg , UVM_DEFAULT)
`uvm_field_object(cntxt, UVM_DEFAULT)
`uvm_component_utils_end
// TLM
uvm_analysis_port #(uvma_interrupt_seq_item_c) ap;
/**
* Default constructor.
*/
extern function new(string name="uvma_interrupt_mon", uvm_component parent=null);
/**
* 1. Ensures cfg & cntxt handles are not null.
* 2. Builds ap.
*/
extern virtual function void build_phase(uvm_phase phase);
/**
* Oversees monitoring via monitor_clk() and monitor_reset() tasks in parallel
* forks.
*/
extern virtual task run_phase(uvm_phase phase);
/**
* Monitor interrupt
*/
extern virtual task mon_irq();
endclass : uvma_interrupt_mon_c
/**
* Default constructor.
*/
function uvma_interrupt_mon_c::new(string name = "uvma_interrupt_mon", uvm_component parent);
super.new(name, parent);
endfunction
/**
* 1. Ensures cfg & cntxt handles are not null.
* 2. Builds ap.
*/
function void uvma_interrupt_mon_c::build_phase(uvm_phase phase);
super.build_phase(phase);
void'(uvm_config_db#(uvma_interrupt_cntxt_c)::get(this, "", "cntxt", cntxt));
if (cntxt == null) begin
`uvm_fatal("build_phase", "monitor cntxt class failed")
end
void'(uvm_config_db#(uvma_interrupt_cfg_c)::get(this, "", "cfg", cfg));
if (cfg == null) begin
`uvm_fatal("CFG", "Configuration handle is null")
end
ap = new("ap", this);
endfunction
/**
* TODO Describe uvma_interrupt_mon_c::run_phase()
*/
task uvma_interrupt_mon_c::run_phase(uvm_phase phase);
super.run_phase(phase);
fork
begin
mon_irq();
end
join_none
endtask: run_phase
/**
* TODO Describe uvma_interrupt_mon_c::mon_post_reset()
*/
task uvma_interrupt_mon_c::mon_irq();
uvma_interrupt_seq_item_c irq_item;
while(1) begin
@(cntxt.interrupt_vif.irq);
irq_item = uvma_interrupt_seq_item_c::type_id::create("irq_item");
irq_item.interrupt_valid = cntxt.interrupt_vif.irq;
`uvm_info(get_type_name(), $sformatf("monitor interrupt : %0d", irq_item.interrupt_valid), UVM_LOW)
ap.write(irq_item);
end
endtask: mon_irq
`endif

View file

@ -0,0 +1,17 @@
// Copyright 2024 Thales DIS SAS
//
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
// You may obtain a copy of the License at https://solderpad.org/licenses/
//
// Original Author: Ayoub JALALI (ayoub.jalali@external.thalesgroup.com)
// Directories
+incdir+${DV_UVMA_INTERRUPT_PATH}
+incdir+${DV_UVMA_INTERRUPT_PATH}/cov
+incdir+${DV_UVMA_INTERRUPT_PATH}/seq
// Files
${DV_UVMA_INTERRUPT_PATH}/uvma_interrupt_pkg.sv

View file

@ -0,0 +1,61 @@
// Copyright 2024 Thales DIS SAS
//
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
// You may obtain a copy of the License at https://solderpad.org/licenses/
//
// Original Author: Ayoub JALALI (ayoub.jalali@external.thalesgroup.com)
`ifndef __UVMA_INTERRUPT_PKG_SV__
`define __UVMA_INTERRUPT_PKG_SV__
// Pre-processor macros
`include "uvm_macros.svh"
`include "uvml_hrtbt_macros.sv"
`include "uvma_interrupt_macros.sv"
/**
* Encapsulates all the types needed for an UVM agent capable of driving and/or
* monitoring Clock & Reset.
*/
package uvma_interrupt_pkg;
import uvm_pkg ::*;
import uvml_hrtbt_pkg::*;
import uvml_trn_pkg ::*;
import uvml_logs_pkg ::*;
parameter NUM_IRQ = 3;
// Constants / Structs / Enums
`include "uvma_interrupt_constants.sv"
`include "uvma_interrupt_tdefs.sv"
// Objects
`include "uvma_interrupt_cfg.sv"
`include "uvma_interrupt_cntxt.sv"
// High-level transactions
`include "uvma_interrupt_seq_item.sv"
// Agent components
`include "uvma_interrupt_cov_model.sv"
`include "uvma_interrupt_mon.sv"
`include "uvma_interrupt_drv.sv"
`include "uvma_interrupt_sqr.sv"
`include "uvma_interrupt_agent.sv"
// Sequences
`include "uvma_interrupt_base_seq.sv"
`include "uvma_interrupt_seq.sv"
endpackage : uvma_interrupt_pkg
// Interface(s) / Module(s) / Checker(s)
`include "uvma_interrupt_if.sv"
`endif // __UVMA_INTERRUPT_PKG_SV__

View file

@ -0,0 +1,77 @@
//
// Copyright 2020 OpenHW Group
// Copyright 2020 Datum Technology Corporation
// Copyright 2020 Silicon Labs, Inc.
// Copyright 2024 Thales DIS SAS
//
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
// You may obtain a copy of the License at https://solderpad.org/licenses/
//
// Original Author: Ayoub JALALI (ayoub.jalali@external.thalesgroup.com)
`ifndef __UVMA_INTERRUPT_SQR_SV__
`define __UVMA_INTERRUPT_SQR_SV__
/**
* Component running interrupt sequences extending uvma_interrupt_seq_base_c.
* Provides sequence items for uvma_interrupt_drv_c.
*/
class uvma_interrupt_sqr_c extends uvm_sequencer#(uvma_interrupt_seq_item_c);
// Objects
uvma_interrupt_cfg_c cfg;
uvma_interrupt_cntxt_c cntxt;
// Analysis port to receive
uvm_tlm_analysis_fifo #(uvma_interrupt_seq_item_c) mm_req_fifo;
`uvm_component_utils_begin(uvma_interrupt_sqr_c)
`uvm_field_object(cfg , UVM_DEFAULT)
`uvm_field_object(cntxt, UVM_DEFAULT)
`uvm_component_utils_end
/**
* Default constructor.
*/
extern function new(string name="uvma_interrupt_sqr", uvm_component parent=null);
/**
* Ensures cfg & cntxt handles are not null
*/
extern virtual function void build_phase(uvm_phase phase);
endclass : uvma_interrupt_sqr_c
function uvma_interrupt_sqr_c::new(string name="uvma_interrupt_sqr", uvm_component parent=null);
super.new(name, parent);
endfunction : new
function void uvma_interrupt_sqr_c::build_phase(uvm_phase phase);
super.build_phase(phase);
void'(uvm_config_db#(uvma_interrupt_cfg_c)::get(this, "", "cfg", cfg));
if (cfg == null) begin
`uvm_fatal("CFG", "Configuration handle is null")
end
void'(uvm_config_db#(uvma_interrupt_cntxt_c)::get(this, "", "cntxt", cntxt));
if (cntxt == null) begin
`uvm_fatal("CNTXT", "Context handle is null")
end
mm_req_fifo = new("mm_req_fifo", this);
endfunction : build_phase
`endif // __UVMA_INTERRUPT_SQR_SV__

View file

@ -0,0 +1,25 @@
// Copyright 2024 Thales DIS SAS
//
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
// You may obtain a copy of the License at https://solderpad.org/licenses/
//
// Original Author: Ayoub JALALI (ayoub.jalali@external.thalesgroup.com)
`ifndef __UVMA_INTERRUPT_TDEFS_SV__
`define __UVMA_INTERRUPT_TDEFS_SV__
typedef enum {
UVMA_INTERRUPT_ONE_BY_ONE,
UVMA_INTERRUPT_MORE_THAN_ONE,
UVMA_INTERRUPT_RANDOMIZE
} uvma_interrupt_cntrl_enum;
typedef enum {
UVMA_INTERRUPT_DRV_REQ_MODE_CONSTANT,
UVMA_INTERRUPT_DRV_REQ_MODE_FIXED_LATENCY,
UVMA_INTERRUPT_DRV_REQ_MODE_RANDOM_LATENCY
} uvma_interrupt_drv_req_enum;
`endif // __UVMA_INTERRUPT_TDEFS_SV__

View file

@ -34,8 +34,6 @@ class uvme_cva6_cfg_c extends uvma_core_cntrl_cfg_c;
rand bit scoreboard_enabled;
rand bit tandem_enabled;
rand bit cov_model_enabled;
rand bit cov_cvxif_model_enabled;
rand bit cov_isa_model_enabled;
rand bit trn_log_enabled;
rand int unsigned sys_clk_period;
@ -45,6 +43,7 @@ class uvme_cva6_cfg_c extends uvma_core_cntrl_cfg_c;
rand uvma_axi_cfg_c axi_cfg;
rand uvma_rvfi_cfg_c#(ILEN,XLEN) rvfi_cfg;
rand uvma_isacov_cfg_c isacov_cfg;
rand uvma_interrupt_cfg_c interrupt_cfg;
// Zicond extension
rand bit ext_zicond_supported;
@ -84,6 +83,8 @@ class uvme_cva6_cfg_c extends uvma_core_cntrl_cfg_c;
`uvm_field_object(isacov_cfg, UVM_DEFAULT)
`uvm_field_object(interrupt_cfg, UVM_DEFAULT)
`uvm_object_utils_end
@ -185,11 +186,20 @@ class uvme_cva6_cfg_c extends uvma_core_cntrl_cfg_c;
(!dm_exception_addr_plusarg_valid) -> (dm_exception_addr == 'h0000_0000);
}
constraint default_interrupt_cons {
if (interrupt_cfg.interrupt_plusarg_valid) {
interrupt_cfg.enable_interrupt == 'h1;
}
else
interrupt_cfg.enable_interrupt == 'h0;
}
constraint agent_cfg_cons {
if (enabled) {
clknrst_cfg.enabled == 1;
isacov_cfg.enabled == 1;
rvfi_cfg.enabled == 1;
clknrst_cfg.enabled == 1;
isacov_cfg.enabled == 1;
rvfi_cfg.enabled == 1;
interrupt_cfg.enabled == 1;
}
isacov_cfg.seq_instr_group_x2_enabled == 1;
@ -203,9 +213,10 @@ class uvme_cva6_cfg_c extends uvma_core_cntrl_cfg_c;
axi_cfg.rand_channel_delay_enabled == 0;
if (is_active == UVM_ACTIVE) {
clknrst_cfg.is_active == UVM_ACTIVE;
isacov_cfg.is_active == UVM_PASSIVE;
rvfi_cfg.is_active == UVM_PASSIVE;
clknrst_cfg.is_active == UVM_ACTIVE;
isacov_cfg.is_active == UVM_PASSIVE;
rvfi_cfg.is_active == UVM_PASSIVE;
interrupt_cfg.is_active == UVM_ACTIVE;
}
if (trn_log_enabled) {
@ -216,12 +227,10 @@ class uvme_cva6_cfg_c extends uvma_core_cntrl_cfg_c;
}
if (cov_model_enabled) {
cvxif_cfg.cov_model_enabled == 1;
isacov_cfg.cov_model_enabled == 1;
axi_cfg.cov_model_enabled == 1;
//env coverage models
cov_cvxif_model_enabled == 1;
cov_isa_model_enabled == 1;
cvxif_cfg.cov_model_enabled == 1;
isacov_cfg.cov_model_enabled == 1;
axi_cfg.cov_model_enabled == 1;
interrupt_cfg.cov_model_enabled == 1;
}
}
@ -253,6 +262,7 @@ function uvme_cva6_cfg_c::new(string name="uvme_cva6_cfg");
axi_cfg = uvma_axi_cfg_c::type_id::create("axi_cfg");
rvfi_cfg = uvma_rvfi_cfg_c#(ILEN,XLEN)::type_id::create("rvfi_cfg");
isacov_cfg = uvma_isacov_cfg_c::type_id::create("isacov_cfg");
interrupt_cfg = uvma_interrupt_cfg_c::type_id::create("interrupt_cfg");
isacov_cfg.core_cfg = this;
rvfi_cfg.core_cfg = this;

View file

@ -35,6 +35,7 @@ class uvme_cva6_cntxt_c extends uvm_object;
uvma_axi_cntxt_c axi_cntxt;
uvma_cva6_core_cntrl_cntxt_c core_cntrl_cntxt;
uvma_rvfi_cntxt_c rvfi_cntxt;
uvma_interrupt_cntxt_c interrupt_cntxt;
// Memory modelling
rand uvml_mem_cva6 mem;
@ -49,6 +50,7 @@ class uvme_cva6_cntxt_c extends uvm_object;
`uvm_field_object(axi_cntxt, UVM_DEFAULT)
`uvm_field_object(core_cntrl_cntxt, UVM_DEFAULT)
`uvm_field_object(rvfi_cntxt, UVM_DEFAULT)
`uvm_field_object(interrupt_cntxt, UVM_DEFAULT)
`uvm_field_event(sample_cfg_e , UVM_DEFAULT)
`uvm_field_event(sample_cntxt_e, UVM_DEFAULT)
`uvm_field_object(mem, UVM_DEFAULT)
@ -75,6 +77,7 @@ function uvme_cva6_cntxt_c::new(string name="uvme_cva6_cntxt");
axi_cntxt = uvma_axi_cntxt_c::type_id::create("axi_cntxt");
mem = uvml_mem_cva6::type_id::create("mem");
rvfi_cntxt = uvma_rvfi_cntxt_c#()::type_id::create("rvfi_cntxt");
interrupt_cntxt = uvma_interrupt_cntxt_c::type_id::create("interrupt_cntxt");
sample_cfg_e = new("sample_cfg_e" );
sample_cntxt_e = new("sample_cntxt_e");

View file

@ -47,6 +47,7 @@ class uvme_cva6_env_c extends uvm_env;
uvma_cva6_core_cntrl_agent_c core_cntrl_agent;
uvma_rvfi_agent_c#(ILEN,XLEN) rvfi_agent;
uvma_isacov_agent_c#(ILEN,XLEN) isacov_agent;
uvma_interrupt_agent_c interrupt_agent;
// Handle to agent switch interface
virtual uvmt_axi_switch_intf axi_switch_vif;
@ -258,6 +259,8 @@ function void uvme_cva6_env_c::assign_cfg();
uvm_config_db#(uvma_core_cntrl_cfg_c)::set(this, "*rvfi_scoreboard", "cfg", cfg);
uvm_config_db#(uvma_core_cntrl_cfg_c)::set(this, "reference_model", "cfg", cfg);
uvm_config_db#(uvma_interrupt_cfg_c)::set(this, "*interrupt_agent", "cfg", cfg.interrupt_cfg);
endfunction: assign_cfg
@ -267,6 +270,7 @@ function void uvme_cva6_env_c::assign_cntxt();
uvm_config_db#(uvma_clknrst_cntxt_c)::set(this, "clknrst_agent", "cntxt", cntxt.clknrst_cntxt);
uvm_config_db#(uvma_axi_cntxt_c)::set(this, "axi_agent", "cntxt", cntxt.axi_cntxt);
uvm_config_db#(uvma_rvfi_cntxt_c)::set(this, "rvfi_agent", "cntxt", cntxt.rvfi_cntxt);
uvm_config_db#(uvma_interrupt_cntxt_c)::set(this, "interrupt_agent", "cntxt", cntxt.interrupt_cntxt);
endfunction: assign_cntxt
@ -279,6 +283,7 @@ function void uvme_cva6_env_c::create_agents();
core_cntrl_agent = uvma_cva6_core_cntrl_agent_c::type_id::create("core_cntrl_agent", this);
rvfi_agent = uvma_rvfi_agent_c#(ILEN,XLEN)::type_id::create("rvfi_agent", this);
isacov_agent = uvma_isacov_agent_c#(ILEN,XLEN)::type_id::create("isacov_agent", this);
interrupt_agent = uvma_interrupt_agent_c::type_id::create("interrupt_agent", this);
endfunction: create_agents
@ -358,6 +363,7 @@ function void uvme_cva6_env_c::assemble_vsequencer();
vsequencer.clknrst_sequencer = clknrst_agent.sequencer;
vsequencer.cvxif_vsequencer = cvxif_agent.vsequencer;
vsequencer.axi_vsequencer = axi_agent.vsequencer;
vsequencer.interrupt_sequencer = interrupt_agent.sequencer;
endfunction: assemble_vsequencer
@ -379,15 +385,23 @@ task uvme_cva6_env_c::run_phase(uvm_phase phase);
axi_vseq.start(axi_agent.vsequencer);
end
end
begin
if(cfg.interrupt_cfg.is_active == UVM_ACTIVE) begin
uvma_interrupt_seq_c interrupt_seq;
interrupt_seq = uvma_interrupt_seq_c::type_id::create("interrupt_seq");
interrupt_seq.start(interrupt_agent.sequencer);
end
end
join_none
endtask
function void uvme_cva6_env_c::connect_coverage_model();
if (cfg.cov_cvxif_model_enabled) begin
if (cfg.cvxif_cfg.cov_model_enabled) begin
cvxif_agent.monitor.req_ap.connect(cov_model.cvxif_covg.req_item_fifo.analysis_export);
end
if (cfg.cov_isa_model_enabled) begin
if (cfg.isacov_cfg.cov_model_enabled) begin
isacov_agent.monitor.ap.connect(cov_model.isa_covg.mon_trn_fifo.analysis_export);
isacov_agent.monitor.ap.connect(cov_model.illegal_covg.mon_trn_fifo.analysis_export);
isacov_agent.monitor.ap.connect(cov_model.exception_covg.mon_trn_fifo.analysis_export);
@ -408,6 +422,10 @@ function void uvme_cva6_env_c::connect_coverage_model();
axi_agent.monitor.m_axi_superset_write_req_packets_collected.connect(cov_model.axi_ext_covg.uvme_axi_cov_aw_req_fifo.analysis_export);
end
if(cfg.interrupt_cfg.cov_model_enabled) begin
isacov_agent.monitor.ap.connect(cov_model.interrupt_covg.mon_trn_fifo.analysis_export);
end
endfunction: connect_coverage_model
`endif // __UVME_CVA6_ENV_SV__

View file

@ -22,6 +22,7 @@
+incdir+${CVA6_UVME_PATH}/cov
+incdir+${CVA6_UVME_PATH}/vseq
+incdir+${CVA6_UVME_PATH}/cvxif_vseq
+incdir+${CVA6_UVME_PATH}/uvma_interrupt
// Files
${CVA6_UVME_PATH}/uvme_cva6_pkg.sv

View file

@ -54,7 +54,9 @@ package uvme_cva6_pkg;
import uvmc_rvfi_scoreboard_pkg::*;
import uvmc_rvfi_reference_model_pkg::*;
import uvma_isacov_pkg::*;
import uvma_interrupt_pkg::*;
import config_pkg::*;
import "DPI-C" function void read_elf(input string filename);
import "DPI-C" function byte get_section(output longint address, output longint len);
import "DPI-C" context function void read_section_sv(input longint address, inout byte buffer[]);
@ -102,6 +104,7 @@ package uvme_cva6_pkg;
`include "uvme_isa_covg.sv"
`include "uvme_illegal_instr_covg.sv"
`include "uvme_exception_covg.sv"
`include "uvme_interrupt_covg.sv"
`include "uvme_cva6_config_covg.sv"
`include "uvme_axi_covg.sv"
`include "uvme_axi_ext_covg.sv"

View file

@ -35,9 +35,10 @@ class uvme_cva6_vsqr_c extends uvm_sequencer#(
uvme_cva6_cntxt_c cntxt;
// Sequencer handles
uvma_clknrst_sqr_c clknrst_sequencer;
uvma_cvxif_vsqr_c cvxif_vsequencer;
uvma_axi_vsqr_c axi_vsequencer;
uvma_clknrst_sqr_c clknrst_sequencer;
uvma_cvxif_vsqr_c cvxif_vsequencer;
uvma_axi_vsqr_c axi_vsequencer;
uvma_interrupt_sqr_c interrupt_sequencer;
`uvm_component_utils_begin(uvme_cva6_vsqr_c)

View file

@ -0,0 +1,42 @@
# Copyright 2023 Thales DIS
#
# Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
# You may obtain a copy of the License at https://solderpad.org/licenses/
#
# Original Author: Ayoub JALALI - Thales
if [ -n "$RISCV_ZCB" ]; then
echo "Using RISCV_ZCB to support Zcb extension"
RISCV=$RISCV_ZCB
fi
if ! [ -n "$RISCV" ]; then
echo "Error: RISCV variable undefined"
return
fi
# install the required tools
source ./verif/regress/install-verilator.sh
source ./verif/regress/install-spike.sh
source ./verif/sim/setup-env.sh
export cov=1 #enable the Code Coverage
if ! [ -n "$DV_TARGET" ]; then
DV_TARGET=cv32a65x
fi
if ! [ -n "$DV_SIMULATORS" ]; then
DV_SIMULATORS=vcs-uvm,spike
fi
cd verif/sim/
cp ../env/corev-dv/custom/riscv_custom_instr_enum.sv ./dv/src/isa/custom/
python3 cva6.py --testlist=cva6_base_testlist.yaml --test riscv_interrupt_test --iss_yaml cva6.yaml --target $DV_TARGET -cs ../env/corev-dv/target/rv32imcb/ --mabi ilp32 --isa rv32imc --isa_extension="zba,zbb,zbc,zbs,zcb" --simulator_yaml ../env/corev-dv/simulator.yaml --iss=$DV_SIMULATORS --priv=m --issrun_opts="+enable_interrupt" -i 5 -bz 1 --iss_timeout 300
python3 cva6.py --testlist=../tests/testlist_interrupt.yaml --test jump_to_zero --iss_yaml cva6.yaml --target $DV_TARGET -cs ../env/corev-dv/target/rv32imcb/ --mabi ilp32 --isa rv32imc --isa_extension="zba,zbb,zbc,zbs,zcb" --simulator_yaml ../env/corev-dv/simulator.yaml --iss=$DV_SIMULATORS --priv=m --issrun_opts="+enable_interrupt"
cd -

View file

@ -164,7 +164,7 @@ export DV_UVMA_ISACOV_PATH = $(CORE_V_VERIF)/lib/uvm_agents/uvma_isacov
export DV_UVMA_CLKNRST_PATH = $(CORE_V_VERIF)/lib/uvm_agents/uvma_clknrst
export DV_UVMA_CVXIF_PATH = $(CORE_V_VERIF)/lib/uvm_agents/uvma_cvxif
export DV_UVMA_AXI_PATH = $(CORE_V_VERIF)/lib/uvm_agents/uvma_axi5
export DV_UVMA_INTERRUPT_PATH = $(CORE_V_VERIF)/lib/uvm_agents/uvma_interrupt
export DV_UVMA_INTERRUPT_PATH = $(DV_UVME_PATH)/uvma_interrupt
export DV_UVMA_DEBUG_PATH = $(CORE_V_VERIF)/lib/uvm_agents/uvma_debug
export DV_UVMA_OBI_PATH = $(CORE_V_VERIF)/lib/uvm_agents/uvma_obi
export DV_UVMC_RVFI_SCOREBOARD_PATH = $(CORE_V_VERIF)/lib/uvm_components/uvmc_rvfi_scoreboard/

View file

@ -730,3 +730,34 @@
iterations: 2
gen_test: cva6_instr_hazard_test_c
rtl_test: core_base_test
- test: riscv_interrupt_test
description: >
Arithmetic instruction test, no load/store/branch instructions no compressed
gcc_opts: >
-static
-mcmodel=medany
-fvisibility=hidden
-nostdlib
-nostartfiles
gen_opts: >
+instr_cnt=500
+num_of_sub_program=0
+no_fence=1
+no_data_page=1
+enable_interrupt=1
+enable_timer_irq=1
+no_branch_jump=1
+no_wfi=0
+boot_mode=m
+no_csr_instr=1
+tvec_alignment=8
+disable_compressed_instr=1
+enable_zba_extension=1
+enable_zbb_extension=1
+enable_zbc_extension=1
+enable_zbs_extension=1
+enable_zcb_extension=1
iterations: 2
gen_test: cva6_instr_base_test_c
rtl_test: core_base_test

View file

@ -58,6 +58,7 @@ module cva6_tb_wrapper import uvmt_cva6_pkg::*; #(
output rvfi_csr_t rvfi_csr_o,
input cvxif_pkg::cvxif_resp_t cvxif_resp,
output cvxif_pkg::cvxif_req_t cvxif_req,
input logic [2:0] irq_i,
uvma_axi_intf axi_slave,
uvmt_axi_switch_intf axi_switch_vif,
uvmt_default_inputs_intf default_inputs_vif
@ -81,19 +82,19 @@ module cva6_tb_wrapper import uvmt_cva6_pkg::*; #(
.rvfi_probes_csr_t ( rvfi_probes_csr_t ),
.rvfi_probes_t ( rvfi_probes_t )
) i_cva6 (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.boot_addr_i ( boot_addr_i ),//Driving the boot_addr value from the core control agent
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.boot_addr_i ( boot_addr_i ),//Driving the boot_addr value from the core control agent
.hart_id_i ( default_inputs_vif.hart_id ),
.irq_i ( default_inputs_vif.irq ),
.ipi_i ( default_inputs_vif.ipi ),
.time_irq_i ( default_inputs_vif.time_irq ),
.irq_i ( {1'b0, irq_i[0]} ),
.ipi_i ( irq_i[1] ),
.time_irq_i ( irq_i[2] ),
.debug_req_i ( default_inputs_vif.debug_req ),
.rvfi_probes_o ( rvfi_probes ),
.cvxif_req_o ( cvxif_req ),
.cvxif_resp_i ( cvxif_resp ),
.noc_req_o ( axi_ariane_req ),
.noc_resp_i ( axi_ariane_resp )
.cvxif_req_o ( cvxif_req ),
.cvxif_resp_i ( cvxif_resp ),
.noc_req_o ( axi_ariane_req ),
.noc_resp_i ( axi_ariane_resp )
);
//----------------------------------------------------------------------------

View file

@ -30,6 +30,7 @@
-f ${DV_UVMA_ISACOV_PATH}/uvma_isacov_pkg.flist
-f ${DV_UVMC_RVFI_REFERENCE_MODEL_PATH}/uvmc_rvfi_reference_model_pkg.flist
-f ${DV_UVMC_RVFI_SCOREBOARD_PATH}/uvmc_rvfi_scoreboard_pkg.flist
-f ${CVA6_UVME_PATH}/uvma_interrupt/uvma_interrupt_pkg.flist
// Environments
-f ${CVA6_UVME_PATH}/uvme_cva6_pkg.flist

View file

@ -34,6 +34,7 @@ module uvmt_cva6_dut_wrap # (
uvmt_axi_switch_intf axi_switch_vif,
uvmt_default_inputs_intf default_inputs_vif,
uvme_cva6_core_cntrl_if core_cntrl_if,
uvma_interrupt_if interrupt_vif,
output logic[31:0] tb_exit_o,
output rvfi_instr_t [CVA6Cfg.NrCommitPorts-1:0] rvfi_o,
output rvfi_csr_t rvfi_csr_o
@ -60,6 +61,7 @@ module uvmt_cva6_dut_wrap # (
.boot_addr_i ( boot_addr ),
.cvxif_resp ( cvxif_if.cvxif_resp_o ),
.cvxif_req ( cvxif_if.cvxif_req_i ),
.irq_i ( interrupt_vif.irq ),
.axi_slave ( axi_if ),
.axi_switch_vif ( axi_switch_vif ),
.default_inputs_vif ( default_inputs_vif ),

View file

@ -67,6 +67,11 @@ module uvmt_cva6_tb;
.clk(clknrst_if.clk),
.rst_n(clknrst_if.reset_n)
);
uvma_interrupt_if
interrupt_vif(
);
uvmt_axi_switch_intf axi_switch_vif();
uvme_cva6_core_cntrl_if core_cntrl_if();
uvma_rvfi_instr_if #(
@ -122,6 +127,7 @@ module uvmt_cva6_tb;
.axi_switch_vif (axi_switch_vif),
.default_inputs_vif (default_inputs_vif),
.core_cntrl_if(core_cntrl_if),
.interrupt_vif(interrupt_vif),
.tb_exit_o(tb_exit_if.tb_exit_o),
.rvfi_o(rvfi_if.rvfi_o),
.rvfi_csr_o(rvfi_if.rvfi_csr_o)
@ -370,6 +376,8 @@ module uvmt_cva6_tb;
uvm_config_db#(virtual uvmt_axi_switch_intf )::set(.cntxt(null), .inst_name("*.env"), .field_name("axi_switch_vif"), .value(axi_switch_vif));
uvm_config_db#(virtual uvmt_rvfi_if#( .CVA6Cfg(CVA6Cfg), .rvfi_instr_t(rvfi_instr_t), .rvfi_csr_t (rvfi_csr_t)))::set(.cntxt(null), .inst_name("*"), .field_name("rvfi_vif"), .value(rvfi_if));
uvm_config_db#(virtual uvme_cva6_core_cntrl_if)::set(.cntxt(null), .inst_name("*"), .field_name("core_cntrl_vif"), .value(core_cntrl_if));
uvm_config_db#(virtual uvma_interrupt_if)::set(.cntxt(null), .inst_name("*"), .field_name("interrupt_vif"), .value(interrupt_vif));
uvm_config_db#(virtual uvmt_tb_exit_if)::set(.cntxt(null), .inst_name("*"), .field_name("tb_exit_vif"), .value(tb_exit_if));
// DUT and ENV parameters

View file

@ -0,0 +1,65 @@
# Copyright 2024 Thales DIS SAS
#
# Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
# You may obtain a copy of the License at https://solderpad.org/licenses/
#
# Original Author: Ayoub JALALI (ayoub.jalali@external.thalesgroup.com)
#*****************************************************************************
# jump_to_zero.S
#-----------------------------------------------------------------------------
#
.globl main
main:
# core of the test
la t1, exception_handler
csrw mtvec, t1 ## Load the address of the exception handler into MTVEC
csrw 0x341, zero ## Writing Zero to MEPC CSR
csrw 0x342, zero ## Writing Zero to MCAUSE CSR
#End Handle exceptions
# enable interrupt in mie and mstatus
li a1, 0x888
csrw mie, a1
csrr a2, mie
li a1, 0x8
csrw mstatus, a1
csrr a2, mstatus
jump00:
jal a1, jump00
jump01:
c.j jump01
jump02:
c.jal jump02
#End of test
j test_done
test_done:
li ra, 0
slli ra, ra, 1
addi ra, ra, 1
sw ra, tohost, t5
self_loop: j self_loop
.align 8
exception_handler:
# increment return address to skip instruction generating the exception
# valid only if faulting instruction is not compressed (4-byte long)
csrr s11, mepc
lbu s5, 0(s11)
li s9, 0x3
and s5, s5, s9
bne s5, s9, exception_handler_incr_mepc2
addi s11, s11, 2
exception_handler_incr_mepc2:
addi s11, s11, 2
csrw mepc, s11
csrr t6, mepc
mret

View file

@ -0,0 +1,32 @@
# Copyright 2024 Thales DIS design services SAS
#
# Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
# You may obtain a copy of the License at https:#solderpad.org/licenses/
#
# Original Author: Ayoub JALALI (ayoub.jalali@external.thalesgroup.com)
# ================================================================================
# Regression test list format
# --------------------------------------------------------------------------------
# test : Assembly test name
# description : Description of this test
# gen_opts : Instruction generator options
# iterations : Number of iterations of this test
# no_iss : Enable/disable ISS simulator (Optional)
# gen_test : Test name used by the instruction generator
# asm_tests : Path to directed, hand-coded assembly test file or directory
# rtl_test : RTL simulation test name
# cmp_opts : Compile options passed to the instruction generator
# sim_opts : Simulation options passed to the instruction generator
# no_post_compare : Enable/disable comparison of trace log and ISS log (Optional)
# compare_opts : Options for the RTL & ISS trace comparison
# gcc_opts : gcc compile options
# --------------------------------------------------------------------------------
- test: jump_to_zero
iterations: 1
path_var: TESTS_PATH
gcc_opts: "-static -mcmodel=medany -fvisibility=hidden -nostdlib -nostartfiles ../tests/custom/common/syscalls.c ../tests/custom/common/crt.S -I../tests/custom/env -I../tests/custom/common -T ../tests/custom/common/test.ld -lgcc"
asm_tests: <path_var>/custom/interrupt/jump_to_zero.S