blob: cce96396dd143dda4c60ae04c6d8b834e0d120fa [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
// Covergroup: pending_req_on_rst_cg
// define bins for having pending request while on reset
covergroup pending_req_on_rst_cg(string name, string path) with function
sample(bit req_pending);
option.per_instance = 1;
option.name = {path, "::", name};
cp_req_pending: coverpoint req_pending {
bins values[] = {0, 1};
}
endgroup
// coverage for sampling all the values of outstanding req, up to its max
covergroup max_outstanding_cg(string name, int max_outstanding, string path) with function
sample(int num_outstanding);
option.per_instance = 1;
option.name = {path, "::", name};
cp_num_of_outstanding: coverpoint num_outstanding {
bins values[] = {[1:max_outstanding]};
}
endgroup : max_outstanding_cg
covergroup tl_a_chan_cov_cg(string name, int valid_source_width, string path) with function
sample(tl_seq_item item);
option.per_instance = 1;
option.name = {path, "::", name};
cp_opcode: coverpoint item.a_opcode {
bins values[] = {Get, PutFullData, PutPartialData};
}
cp_mask: coverpoint item.a_mask {
bins all_enables = {'1};
bins others = default;
}
cp_size: coverpoint item.a_size {
bins biggest_size = {$clog2(DataWidth >> 3)};
bins others = default;
}
cp_source: coverpoint item.a_source {
bins valid_sources[] = {[0 : 2 << (valid_source_width - 1) - 1]};
}
cross cp_opcode, cp_mask, cp_size;
endgroup : tl_a_chan_cov_cg
covergroup tl_d_chan_cov_cg(string name, string path) with function sample(tl_seq_item item);
option.per_instance = 1;
option.name = {path, "::", name};
cp_opcode: coverpoint item.d_opcode {
bins values[] = {AccessAckData, AccessAckData};
}
cp_size: coverpoint item.a_size {
bins biggest_size = {$clog2(DataWidth >> 3)};
bins others = default;
}
cp_error: coverpoint item.d_error;
cross cp_opcode, cp_size;
endgroup : tl_d_chan_cov_cg
class tl_agent_cov extends dv_base_agent_cov #(tl_agent_cfg);
// sample these at proper location, for example, m_pending_req_on_rst_cg called after reset
pending_req_on_rst_cg m_pending_req_on_rst_cg;
max_outstanding_cg m_max_outstanding_cg;
bit_toggle_cg_wrap m_outstanding_item_w_same_addr_cov_obj;
// knob to create m_outstanding_item_w_same_addr_cov_obj, even design supports more than
// 1 outstanding items, but may not support they use the same address
// TODO: may need to disable it for spi_device and hmac even they support 2 oustanding items
bit en_cov_outstanding_item_w_same_addr = 1;
// item coverage, call sample(item) at the end of transaction to sample them
tl_a_chan_cov_cg m_tl_a_chan_cov_cg; // host mode
tl_d_chan_cov_cg m_tl_d_chan_cov_cg; // device mode
bit_toggle_cg_wrap m_tl_error_cov_objs[string]; // host mode
`uvm_component_utils(tl_agent_cov)
`uvm_component_new
function void build_phase(uvm_phase phase);
string tl_error_names[] = {"invalid_a_opcode",
"PutFullData_mask_not_match_size",
"addr_not_align_mask",
"addr_not_align_size",
"mask_not_in_enabled_lanes",
"size_over_max"};
super.build_phase(phase);
m_pending_req_on_rst_cg = new("m_pending_req_on_rst_cg", `gfn);
m_max_outstanding_cg = new("m_max_outstanding_cg", cfg.max_outstanding_req, `gfn);
if (cfg.max_outstanding_req > 1 && en_cov_outstanding_item_w_same_addr) begin
m_outstanding_item_w_same_addr_cov_obj = new(.name("m_outstanding_item_w_same_addr_cov_obj"),
.path(`gfn));
end
if (cfg.if_mode == dv_utils_pkg::Host) begin
m_tl_a_chan_cov_cg = new("m_tl_a_chan_cov_cg", cfg.valid_a_source_width, `gfn);
foreach (tl_error_names[i]) begin
m_tl_error_cov_objs[tl_error_names[i]] = new(.name(tl_error_names[i]), .path(`gfn));
end
end else begin // device mode
m_tl_d_chan_cov_cg = new("m_tl_d_chan_cov_cg", `gfn);
end
endfunction : build_phase
// sample info that is within the seq_item, this will be called at the end of transaction
virtual function void sample(tl_seq_item item);
if (cfg.if_mode == dv_utils_pkg::Host) begin
if (!item.get_exp_d_error()) begin // no error
m_tl_a_chan_cov_cg.sample(item);
end else begin // error cases
m_tl_error_cov_objs["invalid_a_opcode"].sample(item.get_error_a_opcode_invalid());
m_tl_error_cov_objs["PutFullData_mask_not_match_size"].sample(
item.get_error_PutFullData_mask_size_mismatched());
m_tl_error_cov_objs["addr_not_align_mask"].sample(item.get_error_addr_size_misaligned());
m_tl_error_cov_objs["addr_not_align_size"].sample(item.get_error_addr_size_misaligned());
m_tl_error_cov_objs["mask_not_in_enabled_lanes"].sample(
item.get_error_mask_not_in_enabled_lanes());
m_tl_error_cov_objs["size_over_max"].sample(item.get_error_size_over_max());
end
end else begin // device mode
m_tl_d_chan_cov_cg.sample(item);
end
endfunction : sample
endclass