Skip to content

Commit

Permalink
add UVM interrupt agent (#2309)
Browse files Browse the repository at this point in the history
  • Loading branch information
AyoubJalali authored Jul 5, 2024
1 parent 9900d5f commit 2616d5e
Show file tree
Hide file tree
Showing 34 changed files with 1,583 additions and 34 deletions.
14 changes: 10 additions & 4 deletions verif/env/uvme/cov/uvme_cva6_cov_model.sv
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -101,21 +102,20 @@ 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);
uvm_config_db#(uvme_cva6_cfg_c)::set(this, "isa_covg", "cfg", cfg);
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);
Expand All @@ -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);
Expand Down
126 changes: 126 additions & 0 deletions verif/env/uvme/cov/uvme_interrupt_covg.sv
Original file line number Diff line number Diff line change
@@ -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 ([email protected])

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 changes: 16 additions & 0 deletions verif/env/uvme/uvma_interrupt/README.md
Original file line number Diff line number Diff line change
@@ -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).
111 changes: 111 additions & 0 deletions verif/env/uvme/uvma_interrupt/cov/uvma_interrupt_cov_model.sv
Original file line number Diff line number Diff line change
@@ -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 ([email protected])


`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__
55 changes: 55 additions & 0 deletions verif/env/uvme/uvma_interrupt/seq/uvma_interrupt_base_seq.sv
Original file line number Diff line number Diff line change
@@ -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 ([email protected])


`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__
Loading

0 comments on commit 2616d5e

Please sign in to comment.