| // 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(#16840): 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 |