AXI agent: Connect the the new AXI agent (#1817)

This commit is contained in:
AEzzejjari 2024-02-18 23:31:44 +01:00 committed by GitHub
parent 45ffb59980
commit 5e80c104c9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 771 additions and 57 deletions

269
verif/env/uvme/cov/uvme_axi_covg.sv vendored Normal file
View file

@ -0,0 +1,269 @@
// Copyright 2023 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: Alae Eddine EZ ZEJJARI (alae-eddine.ez-zejjari@external.thalesgroup.com) sub-contractor MU-Electronics for Thales group
`ifndef __UVME_AXI_COVG_SV__
`define __UVME_AXI_COVG_SV__
/*
* Covergroups
* Decalred at package-level to enable mutliple instances per monitor class (e.g. read/write)
*/
covergroup cg_axi_w_channel(string name)
with function sample(uvma_axi_transaction_c item, bit RVA);
option.per_instance = 1;
option.name = name;
awready_to_valid: coverpoint (item.aw_delay) {
bins dly[] = {[0:16]};
}
wready_to_valid: coverpoint (item.w_data_trs[0].w_delay) {
bins dly[] = {[0:16]};
}
awsize: coverpoint (item.aw_size){
bins size[] = {[0:3]};
ignore_bins IGN_SIZE3 = {3} iff(uvme_cva6_pkg::XLEN == 32);
}
awlock: coverpoint (item.aw_lock){
bins lock[] = {[0:1]};
ignore_bins IGN_EXCLUSIVE = {1} iff(!RVA);
}
wstrb: coverpoint (item.w_data_trs[0].w_strb) {
bins strb1 = {1};
bins strb2 = {2};
bins strb3 = {3};
bins strb4 = {4};
bins strb8 = {8};
bins strb12 = {12};
bins strb15 = {15};
bins strb16 = {16};
bins strb32 = {32};
bins strb48 = {48};
bins strb64 = {64};
bins strb128 = {128};
bins strb192 = {192};
bins strb240 = {240};
bins strb255 = {255};
ignore_bins IGN_STRB255 = {255} iff(uvme_cva6_pkg::XLEN == 32);
}
aw_axi_cross: cross awready_to_valid, wready_to_valid, awsize, awlock{
illegal_bins ILLEGAL_BINS = binsof(awlock) intersect{1} &&
binsof(awsize) intersect{[0:1]};
ignore_bins IGN_CROSS = binsof(awsize) intersect{3} iff(uvme_cva6_pkg::XLEN == 32);
}
endgroup : cg_axi_w_channel
covergroup cg_axi_b_channel(string name)
with function sample(uvma_axi_transaction_c item, bit RVA);
option.per_instance = 1;
option.name = name;
bid: coverpoint (item.b_id){
bins one = {[1:3]};
illegal_bins ILLEGAL_BINS = {2};
ignore_bins IGN_EXID = {3} iff(!RVA);
}
bresp: coverpoint (item.b_resp){
bins zero = {0};
bins one = {1};
bins two = {2};
bins three = {3};
}
b_axi_cross: cross bid, bresp;
endgroup : cg_axi_b_channel
covergroup cg_axi_ar_channel(string name)
with function sample(uvma_axi_transaction_c item, bit RVA);
option.per_instance = 1;
option.name = name;
arid: coverpoint (item.ar_id) {
bins ID[] = {[0:1]};
}
arlen: coverpoint (item.ar_len) {
bins LEN[] = {[0:1]};
}
arsize: coverpoint (item.ar_size) {
bins SIZE[] = {[0:3]} iff(item.ar_len == 0);
}
arready_to_valid: coverpoint (item.ar_delay) {
bins dly[] = {[0:16]};
}
arlock: coverpoint (item.ar_lock){
bins lock[] = {[0:1]};
ignore_bins IGN_EXCLUSIVE = {1} iff(!RVA);
}
ar_axi_cross: cross arready_to_valid, arid, arlen;
ar_size_axi_cross: cross arready_to_valid, arid, arsize {
illegal_bins ILLEGAL_BINS = binsof(arid) intersect{0} &&
binsof(arsize) intersect{[0:2]};
ignore_bins IGN_CROSS = binsof(arid) intersect{1} && binsof(arsize) intersect{3} iff(uvme_cva6_pkg::XLEN == 32);
}
ar_lock_size_axi_cross: cross arready_to_valid, arlock, arsize{
illegal_bins ILLEGAL_BINS = binsof(arlock) intersect{1} &&
binsof(arsize) intersect{[0:1]};
ignore_bins IGN_CROSS = binsof(arlock) intersect{0} && binsof(arsize) intersect{3} iff(uvme_cva6_pkg::XLEN == 32);
}
endgroup : cg_axi_ar_channel
covergroup cg_axi_r_channel(string name)
with function sample(uvma_axi_transaction_c item, int index, bit RVA);
option.per_instance = 1;
option.name = name;
rid: coverpoint (item.r_data_trs[index].r_id) {
bins ID[] = {[0:3]};
illegal_bins ILLEGAL_BINS = {2};
ignore_bins IGN_EXID = {3} iff(!RVA);
}
rlast: coverpoint (item.r_data_trs[index].r_last);
rresp: coverpoint (item.r_data_trs[index].r_resp){
bins zero = {0};
bins one = {1};
bins two = {2};
bins three = {3};
}
r_axi_cross: cross rid, rlast, rresp {
illegal_bins ILLEGAL_BINS = binsof(rid) intersect{3} && binsof(rlast) intersect{0};
}
endgroup : cg_axi_r_channel
/**
* Component encapsulating Open Bus Interface functional coverage model.
*/
class uvme_axi_covg_c extends uvm_component;
// Objects
uvme_cva6_cntxt_c cntxt;
uvme_cva6_cfg_c cfg;
bit RVA;
// TLM
uvm_tlm_analysis_fifo #(uvma_axi_transaction_c) uvme_axi_cov_resp_fifo;
// Covergroup instances
cg_axi_w_channel w_axi_cg;
cg_axi_b_channel b_axi_cg;
cg_axi_ar_channel ar_axi_cg;
cg_axi_r_channel r_axi_cg;
`uvm_component_utils_begin(uvme_axi_covg_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_axi_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 : uvme_axi_covg_c
function uvme_axi_covg_c::new(string name="uvma_axi_cov_model", uvm_component parent=null);
super.new(name, parent);
endfunction : new
// A significant chunk of the build_phase method is common between this
// coverage model and the sequencer (uvma_obi_memory_sqr). This is
// appropriate so the duplicated code has a lint waiver.
//
function void uvme_axi_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 == null) begin
`uvm_fatal("cfg", "Context handle is null")
end
void'(uvm_config_db#(uvme_cva6_cntxt_c)::get(this, "", "cntxt", cntxt));
if (cntxt == null) begin
`uvm_fatal("CNTXT", "Context handle is null")
end
RVA = cfg.ext_a_supported;
uvme_axi_cov_resp_fifo = new("uvme_axi_cov_resp_fifo" , this);
w_axi_cg = new("w_axi_cg");
b_axi_cg = new("b_axi_cg");
ar_axi_cg = new("ar_axi_cg");
r_axi_cg = new("r_axi_cg");
endfunction : build_phase
task uvme_axi_covg_c::run_phase(uvm_phase phase);
super.run_phase(phase);
`uvm_info(get_type_name(), $sformatf("cov_model_enabled = %d", cfg.cov_model_enabled), UVM_HIGH)
`uvm_info(get_type_name(), $sformatf("ATOMIC ENABLE = %d", RVA), UVM_HIGH)
forever begin
uvma_axi_transaction_c resp_item;
uvme_axi_cov_resp_fifo.get(resp_item);
case (resp_item.access_type)
UVMA_AXI_ACCESS_WRITE : begin
w_axi_cg.sample(resp_item, RVA);
b_axi_cg.sample(resp_item, RVA);
end
UVMA_AXI_ACCESS_READ : begin
ar_axi_cg.sample(resp_item, RVA);
for(int i = 0; i <= resp_item.ar_len; i++) begin
r_axi_cg.sample(resp_item, i, RVA);
end
end
endcase
end
endtask : run_phase
`endif // __UVME_AXI_COVG_SV__

306
verif/env/uvme/cov/uvme_axi_ext_covg.sv vendored Normal file
View file

@ -0,0 +1,306 @@
// Copyright 2023 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: Alae Eddine EZ ZEJJARI (alae-eddine.ez-zejjari@external.thalesgroup.com) sub-contractor MU-Electronics for Thales group
`ifndef __UVME_AXI_EXT_COVG_SV__
`define __UVME_AXI_EXT_COVG_SV__
/*
* Covergroups
* Decalred at package-level to enable mutliple instances per monitor class (e.g. read/write)
*/
covergroup cg_axi_aw_order(string name)
with function sample(uvma_axi_transaction_c item[], int t_b1_to_aw, int t_w1_to_aw, bit RVA);
option.per_instance = 1;
option.name = name;
outstanding_resp: coverpoint (t_b1_to_aw < 0){
bins normal = {0};
bins outstanding = {1};
}
awlock1: coverpoint (item[0].aw_lock){
bins lock[] = {[0:1]};
ignore_bins IGN_EXCLUSIVE = {1} iff(!RVA);
}
awlock2: coverpoint (item[1].aw_lock){
bins lock[] = {[0:1]};
ignore_bins IGN_EXCLUSIVE = {1} iff(!RVA);
}
aw_axi_cross: cross outstanding_resp, awlock1, awlock2;
endgroup : cg_axi_aw_order
covergroup cg_axi_ar_order(string name)
with function sample(uvma_axi_transaction_c item[], int t_r1_to_ar, int t_r1l_to_ar, int t_r1_to_r2, int t_r1l_to_r2l, bit RVA);
option.per_instance = 1;
option.name = name;
outstanding_resp: coverpoint (t_r1_to_ar < 0){
bins normal = {0};
bins outstanding = {1};
}
outstanding_last_resp: coverpoint (t_r1l_to_ar < 0 && t_r1_to_ar > 0){
bins normal = {0};
bins outstanding = {1};
}
outoforder_resp_id0: coverpoint (t_r1_to_r2 < 0){
bins normal = {0} iff(item[0].ar_id == 0);
bins outoforder = {1} iff(item[0].ar_id == 0);
}
outoforder_resp_id1: coverpoint (t_r1_to_r2 < 0){
bins normal = {0} iff(item[0].ar_id == 1);
bins outoforder = {1} iff(item[0].ar_id == 1);
}
outoforder_last_resp_id0: coverpoint (t_r1l_to_r2l < 0){
bins normal = {0} iff(item[0].ar_id == 0);
bins outoforder = {1} iff(item[0].ar_id == 0);
}
outoforder_last_resp_id1: coverpoint (t_r1l_to_r2l < 0){
bins normal = {0} iff(item[0].ar_id == 1);
bins outoforder = {1} iff(item[0].ar_id == 1);
}
arid1: coverpoint (item[0].ar_id){
bins id[] = {[0:1]};
}
arlen1: coverpoint (item[0].ar_len){
bins len[] = {[0:1]};
}
arlock1: coverpoint (item[0].ar_lock){
bins lock[] = {[0:1]};
ignore_bins IGN_EXCLUSIVE = {1} iff(!RVA);
}
arid2: coverpoint (item[1].ar_id){
bins id[] = {[0:1]};
}
arlen2: coverpoint (item[1].ar_len){
bins len[] = {[0:1]};
}
arlock2: coverpoint (item[1].ar_lock){
bins lock[] = {[0:1]};
ignore_bins IGN_EXCLUSIVE = {1} iff(!RVA);
}
ar_axi_outstanding_cross: cross outstanding_resp, outstanding_last_resp, arid1, arlen1, arlock1, arid2, arlen2, arlock2{
ignore_bins IGN_CROSS1 = binsof(outstanding_resp) intersect{1} &&
binsof(outstanding_last_resp) intersect{1};
}
aw_axi_outoforder_id0_cross: cross outoforder_resp_id0, outoforder_last_resp_id0, arlen1, arlock1, arlen2, arlock2{
ignore_bins IGN_CROSS1 = binsof(outoforder_resp_id0) intersect{1} &&
binsof(outoforder_last_resp_id0) intersect{0} &&
binsof(arlen2) intersect{0};
ignore_bins IGN_CROSS2 = binsof(outoforder_resp_id0) intersect{0} &&
binsof(outoforder_last_resp_id0) intersect{1} &&
binsof(arlen1) intersect{0};
}
aw_axi_outoforder_id1_cross: cross outoforder_resp_id1, outoforder_last_resp_id1, arlen1, arlock1, arlen2, arlock2{
ignore_bins IGN_CROSS1 = binsof(outoforder_resp_id1) intersect{1} &&
binsof(outoforder_last_resp_id1) intersect{0} &&
binsof(arlen2) intersect{0};
ignore_bins IGN_CROSS2 = binsof(outoforder_resp_id1) intersect{0} &&
binsof(outoforder_last_resp_id1) intersect{1} &&
binsof(arlen1) intersect{0};
}
endgroup : cg_axi_ar_order
/**
* Component encapsulating Open Bus Interface functional coverage model.
*/
class uvme_axi_ext_covg_c extends uvm_component;
// Objects
uvme_cva6_cntxt_c cntxt;
uvme_cva6_cfg_c cfg;
bit RVA;
// Time between write transfer
int t_b1_to_aw; // <0 (outstanding)
int t_w1_to_aw; // <0 (outstanding)
// Time between read transfer
int t_r1_to_ar; // <0 (outstanding)
int t_r1l_to_ar; // <0 (outstanding)
int t_r1_to_r2; // <0 (r2 run before r1)
int t_r1l_to_r2l; // <0 (last r2 run before last r1)
// Covergroup instances
cg_axi_aw_order aw_axi_order_cg;
cg_axi_ar_order ar_axi_order_cg;
//
uvma_axi_transaction_c aw_trs_fifo[];
uvma_axi_transaction_c ar_trs_fifo[];
int order_resp;
// TLM
uvm_tlm_analysis_fifo #(uvma_axi_transaction_c) uvme_axi_cov_fifo;
`uvm_component_utils_begin(uvme_axi_ext_covg_c)
`uvm_component_utils_end
/**
* Default constructor.
*/
extern function new(string name="uvme_axi_ext_covg", 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);
/**
* Forks all sampling loops
*/
extern virtual function int aw_time_operations();
/**
* Forks all sampling loops
*/
extern virtual function int ar_time_operations();
endclass : uvme_axi_ext_covg_c
function uvme_axi_ext_covg_c::new(string name="uvme_axi_ext_covg", uvm_component parent=null);
super.new(name, parent);
endfunction : new
function void uvme_axi_ext_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 == null) begin
`uvm_fatal("cfg", "Context handle is null")
end
void'(uvm_config_db#(uvme_cva6_cntxt_c)::get(this, "", "cntxt", cntxt));
if (cntxt == null) begin
`uvm_fatal("CNTXT", "Context handle is null")
end
RVA = cfg.ext_a_supported;
aw_axi_order_cg = new("aw_axi_order_cg");
ar_axi_order_cg = new("ar_axi_order_cg");
uvme_axi_cov_fifo = new("uvme_axi_cov_fifo" , this);
endfunction : build_phase
task uvme_axi_ext_covg_c::run_phase(uvm_phase phase);
super.run_phase(phase);
forever begin
uvma_axi_transaction_c resp_item;
uvme_axi_cov_fifo.get(resp_item);
case (resp_item.access_type)
UVMA_AXI_ACCESS_WRITE : begin
aw_trs_fifo = new [aw_trs_fifo.size()+1] (aw_trs_fifo);
aw_trs_fifo[aw_trs_fifo.size()-1] = new resp_item;
if(aw_trs_fifo.size() == 2) begin
order_resp = aw_time_operations();
aw_axi_order_cg.sample(aw_trs_fifo, t_b1_to_aw, t_w1_to_aw, RVA);
if(order_resp == 1) aw_trs_fifo[0] = new aw_trs_fifo[1];
aw_trs_fifo = new [aw_trs_fifo.size()-1] (aw_trs_fifo);
end
end
UVMA_AXI_ACCESS_READ : begin
ar_trs_fifo = new [ar_trs_fifo.size()+1] (ar_trs_fifo);
ar_trs_fifo[ar_trs_fifo.size()-1] = new resp_item;
if(ar_trs_fifo.size() == 2) begin
order_resp = ar_time_operations();
ar_axi_order_cg.sample(ar_trs_fifo, t_r1_to_ar, t_r1l_to_ar, t_r1_to_r2, t_r1l_to_r2l, RVA);
if(order_resp == 1) ar_trs_fifo[0] = new ar_trs_fifo[1];
ar_trs_fifo = new [ar_trs_fifo.size()-1] (ar_trs_fifo);
end
end
endcase
end
endtask : run_phase
function int uvme_axi_ext_covg_c::ar_time_operations();
int order_resp = 1;
uvma_axi_transaction_c axi_transaction;
if(ar_trs_fifo[0].ar_start_time > ar_trs_fifo[1].ar_start_time) begin
axi_transaction = new ar_trs_fifo[0];
ar_trs_fifo[0] = new ar_trs_fifo[1];
ar_trs_fifo[1] = new axi_transaction;
order_resp = 0;
end
t_r1_to_ar = ar_trs_fifo[1].ar_start_time - ar_trs_fifo[0].r_data_trs[0].r_start_time;
t_r1l_to_ar = ar_trs_fifo[1].ar_start_time - ar_trs_fifo[0].r_data_trs[ar_trs_fifo[0].r_data_trs.size()-1].r_start_time;
t_r1_to_r2 = ar_trs_fifo[1].r_data_trs[0].r_start_time - ar_trs_fifo[0].r_data_trs[0].r_start_time;
t_r1l_to_r2l = ar_trs_fifo[1].r_data_trs[ar_trs_fifo[1].r_data_trs.size()-1].r_start_time - ar_trs_fifo[0].r_data_trs[ar_trs_fifo[0].r_data_trs.size()-1].r_start_time;
return order_resp;
endfunction : ar_time_operations
function int uvme_axi_ext_covg_c::aw_time_operations();
int order_resp = 1;
uvma_axi_transaction_c axi_transaction;
if(aw_trs_fifo[0].aw_start_time > aw_trs_fifo[1].aw_start_time) begin
axi_transaction = new aw_trs_fifo[0];
aw_trs_fifo[0] = new aw_trs_fifo[1];
aw_trs_fifo[1] = new axi_transaction;
order_resp = 0;
end
t_b1_to_aw = aw_trs_fifo[1].aw_start_time - aw_trs_fifo[0].b_start_time;
t_w1_to_aw = aw_trs_fifo[1].aw_start_time - aw_trs_fifo[0].w_data_trs[0].w_start_time;
return order_resp;
endfunction : aw_time_operations
`endif // __UVME_AXI_EXT_COVG_SV__

View file

@ -35,6 +35,8 @@ class uvme_cva6_cov_model_c extends uvm_component;
uvme_cva6_config_covg_c config_covg;
uvme_illegal_instr_cov_model_c illegal_covg;
uvme_exception_cov_model_c exception_covg;
uvme_axi_covg_c axi_covg;
uvme_axi_ext_covg_c axi_ext_covg;
//
uvm_analysis_export#(uvma_clknrst_mon_trn_c) reset_export;
@ -119,6 +121,15 @@ function void uvme_cva6_cov_model_c::build_phase(uvm_phase phase);
uvm_config_db#(uvme_cva6_cfg_c)::set(this, "config_covg", "cfg", cfg);
uvm_config_db#(uvme_cva6_cntxt_c)::set(this, "config_covg", "cntxt", cntxt);
if(cfg.axi_cfg.cov_model_enabled) begin
axi_covg = uvme_axi_covg_c::type_id::create("axi_covg", this);
axi_ext_covg = uvme_axi_ext_covg_c::type_id::create("axi_ext_covg", this);
uvm_config_db#(uvme_cva6_cfg_c)::set(this, "axi_covg", "cfg", cfg);
uvm_config_db#(uvme_cva6_cntxt_c)::set(this, "axi_covg", "cntxt", cntxt);
uvm_config_db#(uvme_cva6_cfg_c)::set(this, "axi_ext_covg", "cfg", cfg);
uvm_config_db#(uvme_cva6_cntxt_c)::set(this, "axi_ext_covg", "cntxt", cntxt);
end
endfunction : build_phase
function void uvme_cva6_cov_model_c::connect_phase(uvm_phase phase);

View file

@ -194,6 +194,7 @@ 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;

View file

@ -381,6 +381,11 @@ function void uvme_cva6_env_c::connect_coverage_model();
clknrst_agent.mon_ap.connect(cov_model.reset_export);
rvfi_agent.rvfi_core_ap.connect(isacov_agent.monitor.rvfi_instr_imp);
if(cfg.axi_cfg.cov_model_enabled) begin
axi_agent.vsequencer.synchronizer.uvma_sqr_trs_port.connect(cov_model.axi_covg.uvme_axi_cov_resp_fifo.analysis_export);
axi_agent.vsequencer.synchronizer.uvma_sqr_trs_port.connect(cov_model.axi_ext_covg.uvme_axi_cov_fifo.analysis_export);
end
endfunction: connect_coverage_model
`endif // __UVME_CVA6_ENV_SV__

View file

@ -51,6 +51,9 @@ package uvme_cva6_pkg;
import uvmc_rvfi_scoreboard_pkg::*;
import uvmc_rvfi_reference_model_pkg::*;
import uvma_isacov_pkg::*;
import "DPI-C" function 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[]);
// Default legal opcode and funct7 for RV32I instructions
bit [6:0] legal_i_opcode[$] = '{7'b0000011,
@ -96,12 +99,15 @@ package uvme_cva6_pkg;
`include "uvme_illegal_instr_covg.sv"
`include "uvme_exception_covg.sv"
`include "uvme_cva6_config_covg.sv"
`include "uvme_axi_covg.sv"
`include "uvme_axi_ext_covg.sv"
`include "uvme_cva6_cov_model.sv"
`include "uvme_cva6_env.sv"
// Virtual sequences
`include "uvme_cva6_base_vseq.sv"
`include "uvme_cva6_reset_vseq.sv"
`include "uvme_axi_fw_preload_seq.sv"
// `include "uvme_cva6_interrupt_noise_vseq.sv"
`include "uvme_cva6_vseq_lib.sv"

View file

@ -0,0 +1,84 @@
// 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: Alae Eddine EZ ZEJJARI (alae-eddine.ez-zejjari@external.thalesgroup.com)  sub-contractor MU-Electronics for Thales group
`ifndef __UVME_AXI_FW_PRELOAD_SEQ_SV__
`define __UVME_AXI_FW_PRELOAD_SEQ_SV__
/**
* Virtual sequence preloads the CVA6 memory.
*/
class uvme_axi_fw_preload_seq_c extends uvma_axi_fw_preload_seq_c;
uvml_mem_c mem;
static uvm_cmdline_processor uvcl = uvm_cmdline_processor::get_inst();
bit[63:0] value;
logic [7:0][7:0] mem_row;
string binary = "";
longint address;
longint len;
byte buffer[];
`uvm_object_utils(uvme_axi_fw_preload_seq_c)
/**
* Default constructor.
*/
extern function new(string name="uvma_axi_fw_preload_seq");
extern virtual task body();
endclass : uvme_axi_fw_preload_seq_c
function uvme_axi_fw_preload_seq_c::new(string name="uvma_axi_fw_preload_seq");
super.new(name);
mem = uvml_mem_c::type_id::create("mem");
mem.mem_default = MEM_DEFAULT_0;
endfunction : new
task uvme_axi_fw_preload_seq_c::body();
void'(uvcl.get_arg_value("+elf_file=", binary));
if (binary != "") begin
void'(read_elf(binary));
wait(p_sequencer.cntxt.axi_vi.clk);
// while there are more sections to process
while (get_section(address, len)) begin
automatic int num_words0 = (len+7)/8;
`uvm_info( "Core Test", $sformatf("Loading Address: %x, Length: %x", address, len), UVM_HIGH)
buffer = new [num_words0*8];
void'(read_section_sv(address, buffer));
// preload memories
// 64-bit
for (int i = 0; i < num_words0; i++) begin
mem_row = '0;
for (int j = 0; j < 8; j++) begin
mem_row[j] = buffer[i*8 + j];
end
mem.write(address + i*8 + 0, mem_row[0]);
mem.write(address + i*8 + 1, mem_row[1]);
mem.write(address + i*8 + 2, mem_row[2]);
mem.write(address + i*8 + 3, mem_row[3]);
mem.write(address + i*8 + 4, mem_row[4]);
mem.write(address + i*8 + 5, mem_row[5]);
mem.write(address + i*8 + 6, mem_row[6]);
mem.write(address + i*8 + 7, mem_row[7]);
end
p_sequencer.cntxt.mem = mem;
end
end
endtask : body
`endif // __UVME_AXI_FW_PRELOAD_SEQ_SV__

View file

@ -179,7 +179,7 @@ export DV_UVMA_RVFI_PATH = $(CORE_V_VERIF)/lib/uvm_agents/uvma_rvfi
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_axi
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_DEBUG_PATH = $(CORE_V_VERIF)/lib/uvm_agents/uvma_debug
export DV_UVMA_OBI_PATH = $(CORE_V_VERIF)/lib/uvm_agents/uvma_obi

View file

@ -201,6 +201,7 @@ module cva6_tb_wrapper import uvmt_cva6_pkg::*; #(
assign axi_slave.aw_prot = axi_ariane_req.aw.prot;
assign axi_slave.aw_qos = axi_ariane_req.aw.qos;
assign axi_slave.aw_region = axi_ariane_req.aw.region;
assign axi_slave.aw_atop = axi_ariane_req.aw.atop;
assign axi_slave.aw_user = 0;
// W Channel
assign axi_slave.w_data = axi_ariane_req.w.data;

View file

@ -5,48 +5,27 @@
// 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: Alae Eddine EZ ZEJJARI (alae-eddine.ez-zejjari@external.thalesgroup.com)
// Original Author: Alae Eddine EZ ZEJJARI (alae-eddine.ez-zejjari@external.thalesgroup.com)  sub-contractor MU-Electronics for Thales group
module uvmt_axi_assert (uvma_axi_intf.passive axi_assert, input bit clk, input rst_n);
module uvmt_axi_assert (uvma_axi_intf axi_assert_if);
import uvm_pkg::*;
uvma_axi_assert axi_mix_assert(.axi_assert(axi_assert_if));
bind uvmt_axi_assert
uvma_axi_aw_assert axi_aw_assert(.axi_assert(axi_assert),
.clk(clk),
.rst_n(rst_n)
);
uvma_axi_aw_assert axi_aw_assert(.axi_assert(axi_assert_if));
bind uvmt_axi_assert
uvma_axi_ar_assert axi_ar_assert(.axi_assert(axi_assert),
.clk(clk),
.rst_n(rst_n)
);
uvma_axi_ar_assert axi_ar_assert(.axi_assert(axi_assert_if));
bind uvmt_axi_assert
uvma_axi_w_assert axi_w_assert(.axi_assert(axi_assert),
.clk(clk),
.rst_n(rst_n)
);
uvma_axi_w_assert axi_w_assert(.axi_assert(axi_assert_if));
bind uvmt_axi_assert
uvma_axi_r_assert axi_r_assert(.axi_assert(axi_assert),
.clk(clk),
.rst_n(rst_n)
);
uvma_axi_r_assert axi_r_assert(.axi_assert(axi_assert_if));
bind uvmt_axi_assert
uvma_axi_b_assert axi_b_assert(.axi_assert(axi_assert),
.clk(clk),
.rst_n(rst_n)
);
uvma_axi_b_assert axi_b_assert(.axi_assert(axi_assert_if));
bind uvmt_axi_assert
uvmt_cva6_axi_assert cva6_axi_assert(.axi_assert(axi_assert),
.clk(clk),
.rst_n(rst_n)
);
uvma_axi_amo_assert axi_amo_assert(.axi_assert(axi_assert_if));
uvmt_cva6_axi_assert cva6_axi_assert(.axi_assert_if(axi_assert_if));
endmodule : uvmt_axi_assert

View file

@ -5,93 +5,98 @@
// 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: Alae Eddine EZ ZEJJARI (alae-eddine.ez-zejjari@external.thalesgroup.com)
// Original Author: Alae Eddine EZ ZEJJARI (alae-eddine.ez-zejjari@external.thalesgroup.com)  sub-contractor MU-Electronics for Thales group
// *************************** AXI features supported by CVA6 ************************** //
module uvmt_cva6_axi_assert (uvma_axi_intf axi_assert, input bit clk, input rst_n);
module uvmt_cva6_axi_assert (uvma_axi_intf axi_assert_if);
import uvm_pkg::*;
//check if the CVA6 identify read transaction with an ID equal to 0 or 1
property AXI4_CVA6_ARID;
@(posedge clk) disable iff (!rst_n) axi_assert.ar_valid |-> axi_assert.ar_id == 0 || axi_assert.ar_id == 1;
@(posedge axi_assert_if.clk) disable iff (!axi_assert_if.rst_n) axi_assert_if.ar_valid |-> axi_assert_if.ar_id == 0 || axi_assert_if.ar_id == 1 || (axi_assert_if.ar_id == 3 && axi_assert_if.ar_lock == 1);
endproperty
//check if the CVA6 identify write transaction with an ID equal to 0 or 1
property AXI4_CVA6_AWID;
@(posedge clk) disable iff (!rst_n) axi_assert.aw_valid |-> axi_assert.aw_id == 1;
@(posedge axi_assert_if.clk) disable iff (!axi_assert_if.rst_n) axi_assert_if.aw_valid |-> axi_assert_if.aw_id == 1 || (axi_assert_if.aw_id == 3 && axi_assert_if.aw_atop != 0) || (axi_assert_if.aw_id == 3 && axi_assert_if.aw_lock == 1);
endproperty
//Check if user-defined extension for read address channel is equal to 0b00
property AXI4_CVA6_ARUSER;
@(posedge clk) disable iff (!rst_n) axi_assert.ar_valid |-> axi_assert.ar_user == 0;
@(posedge axi_assert_if.clk) disable iff (!axi_assert_if.rst_n) axi_assert_if.ar_valid |-> axi_assert_if.ar_user == 0;
endproperty
//Check if user-defined extension for write address channel is equal to 0b00
property AXI4_CVA6_AWUSER;
@(posedge clk) disable iff (!rst_n) axi_assert.aw_valid |-> axi_assert.aw_user == 0;
@(posedge axi_assert_if.clk) disable iff (!axi_assert_if.rst_n) axi_assert_if.aw_valid |-> axi_assert_if.aw_user == 0;
endproperty
//Check if Quality of Service identifier for write transaction is equal to 0b0000
property AXI4_CVA6_AWQOS;
@(posedge clk) disable iff (!rst_n) axi_assert.aw_valid |-> axi_assert.aw_qos == 0;
@(posedge axi_assert_if.clk) disable iff (!axi_assert_if.rst_n) axi_assert_if.aw_valid |-> axi_assert_if.aw_qos == 0;
endproperty
//Check if Quality of Service identifier for read transaction is equal to 0b0000
property AXI4_CVA6_ARQOS;
@(posedge clk) disable iff (!rst_n) axi_assert.ar_valid |-> axi_assert.ar_qos == 0;
@(posedge axi_assert_if.clk) disable iff (!axi_assert_if.rst_n) axi_assert_if.ar_valid |-> axi_assert_if.ar_qos == 0;
endproperty
//Check if Region indicator for write transaction is equal to 0b0000
property AXI4_CVA6_AWREGION;
@(posedge clk) disable iff (!rst_n) axi_assert.aw_valid |-> axi_assert.aw_region == 0;
@(posedge axi_assert_if.clk) disable iff (!axi_assert_if.rst_n) axi_assert_if.aw_valid |-> axi_assert_if.aw_region == 0;
endproperty
//Check if Region indicator for read transaction is equal to 0b0000
property AXI4_CVA6_ARREGION;
@(posedge clk) disable iff (!rst_n) axi_assert.ar_valid |-> axi_assert.ar_region == 0;
@(posedge axi_assert_if.clk) disable iff (!axi_assert_if.rst_n) axi_assert_if.ar_valid |-> axi_assert_if.ar_region == 0;
endproperty
//Check if AWCACHE is always equal to 0b0000
property AXI4_CVA6_AWCACHE;
@(posedge clk) disable iff (!rst_n) axi_assert.aw_valid |-> axi_assert.aw_cache == 2;
@(posedge axi_assert_if.clk) disable iff (!axi_assert_if.rst_n) axi_assert_if.aw_valid |-> axi_assert_if.aw_cache == 2;
endproperty
//Check if ARCACHE is always equal to 0b0000
property AXI4_CVA6_ARCACHE;
@(posedge clk) disable iff (!rst_n) axi_assert.ar_valid |-> axi_assert.ar_cache == 2;
@(posedge axi_assert_if.clk) disable iff (!axi_assert_if.rst_n) axi_assert_if.ar_valid |-> axi_assert_if.ar_cache == 2;
endproperty
//Check if Protection attributes for write transaction always take the 0b000
property AXI4_CVA6_AWPROT;
@(posedge clk) disable iff (!rst_n) axi_assert.aw_valid |-> axi_assert.aw_prot == 0;
@(posedge axi_assert_if.clk) disable iff (!axi_assert_if.rst_n) axi_assert_if.aw_valid |-> axi_assert_if.aw_prot == 0;
endproperty
//Check if Protection attributes for read transaction always take the 0b000
property AXI4_CVA6_ARPROT;
@(posedge clk) disable iff (!rst_n) axi_assert.ar_valid |-> axi_assert.ar_prot == 0;
@(posedge axi_assert_if.clk) disable iff (!axi_assert_if.rst_n) axi_assert_if.ar_valid |-> axi_assert_if.ar_prot == 0;
endproperty
//Check if all write transaction performed by CVA6 are of type INCR
property AXI4_CVA6_AWBURST;
@(posedge clk) disable iff (!rst_n) axi_assert.aw_valid |-> axi_assert.aw_burst == 1;
@(posedge axi_assert_if.clk) disable iff (!axi_assert_if.rst_n) axi_assert_if.aw_valid |-> axi_assert_if.aw_burst == 1;
endproperty
//Check if all read transaction performed by CVA6 are of type INCR
property AXI4_CVA6_ARBURST;
@(posedge clk) disable iff (!rst_n) axi_assert.ar_valid |-> axi_assert.ar_burst == 1;
@(posedge axi_assert_if.clk) disable iff (!axi_assert_if.rst_n) axi_assert_if.ar_valid |-> axi_assert_if.ar_burst == 1;
endproperty
//Check if all write transaction performed by CVA6 are equal to 0
property AXI4_CVA6_AWLEN;
@(posedge clk) disable iff (!rst_n) axi_assert.aw_valid |-> axi_assert.aw_len == 0;
@(posedge axi_assert_if.clk) disable iff (!axi_assert_if.rst_n) axi_assert_if.aw_valid |-> axi_assert_if.aw_len == 0;
endproperty
//Check if all Read transaction performed by CVA6 are equal to 0 or 1
property AXI4_CVA6_ARLEN;
@(posedge clk) disable iff (!rst_n) axi_assert.ar_valid |-> axi_assert.ar_len == 0 || axi_assert.ar_len == 1;
@(posedge axi_assert_if.clk) disable iff (!axi_assert_if.rst_n) axi_assert_if.ar_valid |-> axi_assert_if.ar_len == 0 || axi_assert_if.ar_len == 1;
endproperty
//Check if all Write transaction performed by CVA6 are of type Non atomic, AtomicLoad or AtomicSwap
property AXI4_CVA6_AWATOP;
@(posedge axi_assert_if.clk) disable iff (!axi_assert_if.rst_n) axi_assert_if.aw_valid |-> (axi_assert_if.aw_atop[5:4] == 0 || axi_assert_if.aw_atop[5:4] == 2 || axi_assert_if.aw_atop[5:4] == 3) && axi_assert_if.aw_atop[3] == 0;
endproperty
/********************************************** Assert Property ******************************************************/
@ -144,6 +149,9 @@ module uvmt_cva6_axi_assert (uvma_axi_intf axi_assert, input bit clk, input rst
cva6_awlen : assert property (AXI4_CVA6_AWLEN)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_CVA6_AWLEN");
cva6_awatop : assert property (AXI4_CVA6_AWATOP)
else `uvm_error (" AXI4 protocol checks assertion ", "Violation of AXI4_CVA6_AWATOP");
/********************************************** Cover Property ******************************************************/
@ -179,7 +187,7 @@ module uvmt_cva6_axi_assert (uvma_axi_intf axi_assert, input bit clk, input rst
cov_cva6_awlen : cover property(AXI4_CVA6_AWLEN);
cov_cva6_awatop : cover property(AXI4_CVA6_AWATOP);
endmodule : uvmt_cva6_axi_assert

View file

@ -88,7 +88,7 @@ module uvmt_cva6_tb;
uvma_rvfi_csr_if#(uvme_cva6_pkg::XLEN) rvfi_csr_if [RVFI_NRET-1:0]();
uvmt_default_inputs_intf default_inputs_vif();
uvmt_default_inputs_intf default_inputs_vif();
//bind assertion module for cvxif interface
bind uvmt_cva6_dut_wrap
@ -98,10 +98,8 @@ module uvmt_cva6_tb;
);
//bind assertion module for axi interface
bind uvmt_cva6_dut_wrap
uvmt_axi_assert axi_assert(.axi_assert(axi_if.passive),
.clk(clknrst_if.clk),
.rst_n(clknrst_if.reset_n)
);
uvmt_axi_assert axi_assert(.axi_assert_if(axi_if));
// DUT Wrapper Interfaces
uvmt_rvfi_if #(
// RVFI
@ -238,6 +236,14 @@ module uvmt_cva6_tb;
// Specify time format for simulation (units_number, precision_number, suffix_string, minimum_field_width)
$timeformat(-9, 3, " ns", 8);
axi_if.aw_assertion_enabled = 1;
axi_if.w_assertion_enabled = 1;
axi_if.b_assertion_enabled = 1;
axi_if.ar_assertion_enabled = 1;
axi_if.r_assertion_enabled = 1;
axi_if.axi_assertion_enabled = 1;
axi_if.axi_amo_assertion_enabled = 1;
// Add interfaces handles to uvm_config_db
uvm_config_db#(virtual uvma_clknrst_if )::set(.cntxt(null), .inst_name("*.env.clknrst_agent"), .field_name("vif"), .value(clknrst_if));
uvm_config_db#(virtual uvma_cvxif_intf )::set(.cntxt(null), .inst_name("*.env.cvxif_agent"), .field_name("vif"), .value(cvxif_if) );

View file

@ -40,6 +40,12 @@ class uvmt_cva6_base_test_c extends uvm_test;
uvme_cva6_env_c env ;
uvme_cva6_vsqr_c vsequencer;
typedef enum {
UVMA_AXI_VERSION_1P1,
UVMA_AXI_VERSION_1P2,
UVMA_AXI_VERSION_1P3
} uvma_axi_version_enum;
// Handles testbench interfaces
virtual uvmt_rvfi_if rvfi_vif; // virtual peripheral status
// virtual uvmt_cva6_core_cntrl_if core_cntrl_vif; // control inputs to the core
@ -50,6 +56,8 @@ class uvmt_cva6_base_test_c extends uvm_test;
// Variable can be modified from command line, to change the AXI agent mode
int force_axi_mode = -1;
uvm_factory factory;
`uvm_component_utils_begin(uvmt_cva6_base_test_c)
`uvm_field_object(test_cfg , UVM_DEFAULT)
@ -74,6 +82,16 @@ class uvmt_cva6_base_test_c extends uvm_test;
soft test_cfg.tpt == NO_TEST_PROGRAM;
}
constraint memory_region_cfg {
env_cfg.axi_cfg.axi_region_enabled == 0;
env_cfg.axi_cfg.axi_prot_enabled == 0;
env_cfg.axi_cfg.m_addr_start == 64'h0;
env_cfg.axi_cfg.m_addr_end == 64'h7fffffffffffffff;
env_cfg.axi_cfg.m_num_part == 1;
env_cfg.axi_cfg.m_part_st[0].axi_prot_type_access == 0;
env_cfg.axi_cfg.m_part_st[0].m_type_access == 3;
}
/**
* 1. Replaces default report server with rs.
@ -223,6 +241,26 @@ function void uvmt_cva6_base_test_c::build_phase(uvm_phase phase);
create_env ();
create_components();
`uvm_info("BASE TEST", $sformatf("AXI config version = %s", env_cfg.axi_cfg.version), UVM_LOW)
factory = uvm_factory::get();
case (env_cfg.axi_cfg.version)
UVMA_AXI_VERSION_1P2 : begin
factory.set_type_override_by_name("uvma_axi_synchronizer_c", "uvma_axi_ext_synchronizer_c");
`uvm_info("BASE TEST", $sformatf("AXI EXT SYNCHRONIZER"), UVM_LOW)
end
UVMA_AXI_VERSION_1P3 : begin
factory.set_type_override_by_name("uvma_axi_synchronizer_c", "uvma_axi_amo_synchronizer_c");
`uvm_info("BASE TEST", $sformatf("AXI AMO SYNCHRONIZER"), UVM_LOW)
end
endcase
if(!env_cfg.axi_cfg.preload_mem) begin
factory.set_type_override_by_name("uvma_axi_fw_preload_seq_c", "uvme_axi_fw_preload_seq_c");
end
endfunction : build_phase