blob: 2d9941a237abca2bf0ed6b9e0def4c0d7d64699d [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
/**
* Covergoups that are dependent on run-time parameters that may be available
* only in build_phase can be defined here
* Covergroups may also be wrapped inside helper classes if needed.
*/
class pwm_env_cov extends cip_base_env_cov #(.CFG_T(pwm_env_cfg));
`uvm_component_utils(pwm_env_cov)
// the base class provides the following handles for use:
// pwm_env_cfg: cfg
// covergroups
covergroup cfg_cg with function sample(bit [26:0] clkdiv,
bit [3:0] dcresn,
bit cntren);
clkdiv_cp: coverpoint clkdiv {
bins minimum_value = {0};
bins valid_range[4] = {[0:$]};
bins maximum_value = {MAX_CLK_DIV};
}
dcresn_cp: coverpoint dcresn {
bins minimum_value = {0};
bins valid_range[4] = {[0:$]};
bins maximum_value = {'hF};
}
cntren_cp: coverpoint cntren;
cfg_cg_cross_cp: cross clkdiv_cp, dcresn_cp;
endgroup : cfg_cg
covergroup pwm_chan_en_inv_cg with function sample(bit [PWM_NUM_CHANNELS-1:0] en_chan,
bit [PWM_NUM_CHANNELS-1:0] inv_chan);
// channels and inverts
en_chan_cp: coverpoint en_chan {
bins en_single_chan[6] = {'h1, 'h2, 'h4, 'h8, 'h10, 'h20};
bins en_all_chan = {'h3F};
}
inv_chan_cp: coverpoint inv_chan {
bins en_single_chan[6] = {'h1, 'h2, 'h4, 'h8, 'h10, 'h20};
bins en_all_chan = {'h3F};
}
en_inv_cross_cp: cross en_chan_cp, inv_chan_cp {
bins inverted_enabled = en_inv_cross_cp with (en_chan_cp == inv_chan_cp);
ignore_bins not_eq = en_inv_cross_cp with (en_chan_cp != inv_chan_cp);
}
endgroup : pwm_chan_en_inv_cg
covergroup pwm_per_channel_cg with function sample(
bit [PWM_NUM_CHANNELS-1:0] en_chan,
bit [PWM_NUM_CHANNELS-1:0] inv_chan,
bit [15:0] phase_delay,
bit blink_en,
bit htbt_en,
bit [15:0] duty_cycle_a,
bit [15:0] duty_cycle_b,
bit [15:0] blink_x,
bit [15:0] blink_y
);
// sampled channel
channels_cp: coverpoint en_chan {
wildcard bins channel_0 = {6'b?????1};
wildcard bins channel_1 = {6'b????1?};
wildcard bins channel_2 = {6'b???1??};
wildcard bins channel_3 = {6'b??1???};
wildcard bins channel_4 = {6'b?1????};
wildcard bins channel_5 = {6'b1?????};
}
// pwm_params
// phase_delay will not go as large as MAX_16/3,
// since it is computed and derived from MAX_16 value
// phase delay of the PWM rising edge, in units of 2^(-16) PWM cycles
phase_delay_cp: coverpoint phase_delay {
bins minimum_value = {0};
bins high_range = {[0:(MAX_16/3)]};
}
phase_delay_per_channel_cross_cp: cross phase_delay_cp, channels_cp;
htbt_en_cp: coverpoint htbt_en {
bins enabled = {1};
bins disabled = {0};
}
htbt_en_per_channel_cross_cp: cross htbt_en_cp, channels_cp;
blink_en_cp: coverpoint blink_en {
bins enabled = {1};
bins disabled = {0};
}
blink_en_per_channel_cross_cp: cross blink_en_cp, channels_cp;
// htbt can only be enabled when blink is also enabled
htbt_blink_en_cp: cross blink_en_cp, htbt_en_cp {
ignore_bins undefined_state = (binsof(blink_en_cp) && binsof(htbt_en_cp))
with ((blink_en_cp == 0) && (htbt_en_cp == 1));
}
// duty cycles
duty_cycle_a_cp: coverpoint duty_cycle_a {
bins minimum_value = {0};
bins low_range = {[0:(MAX_16/3)]};
bins mid_range = {[(MAX_16/3):((2*MAX_16)/3)]};
bins high_range = {[((2*MAX_16)/3):$]};
bins maximum_value = {MAX_16};
}
duty_a_per_channel_cross_cp: cross duty_cycle_a_cp, channels_cp;
duty_cycle_b_cp: coverpoint duty_cycle_b {
bins minimum_value = {0};
bins low_range = {[0:(MAX_16/3)]};
bins mid_range = {[(MAX_16/3):((2*MAX_16)/3)]};
bins high_range = {[((2*MAX_16)/3):$]};
bins maximum_value = {MAX_16};
}
duty_b_per_channel_cross_cp: cross duty_cycle_b_cp, channels_cp;
dc_a_b_cross_cp: cross duty_cycle_a_cp, duty_cycle_b_cp {
bins a_lt_b = (binsof(duty_cycle_a_cp) && binsof(duty_cycle_b_cp))
with (duty_cycle_a_cp < duty_cycle_b_cp);
bins a_gt_b = (binsof(duty_cycle_a_cp) && binsof(duty_cycle_b_cp))
with (duty_cycle_a_cp > duty_cycle_b_cp);
bins a_eq_b = (binsof(duty_cycle_a_cp) && binsof(duty_cycle_b_cp))
with (duty_cycle_a_cp == duty_cycle_b_cp);
}
dc_a_b_cross_per_channel_cross_cp: cross dc_a_b_cross_cp, channels_cp;
// blink parameter
blink_x_cp: coverpoint blink_x {
bins minimum_value = {0};
bins low_range = {[0:(MAX_16/3)]};
bins mid_range = {[(MAX_16/3):((2*MAX_16)/3)]};
bins high_range = {[((2*MAX_16)/3):$]};
bins maximum_value = {MAX_16};
}
blink_x_per_channel_cross_cp: cross blink_x_cp, channels_cp;
blink_y_cp: coverpoint blink_y {
bins minimum_value = {0};
bins low_range = {[0:(MAX_16/3)]};
bins mid_range = {[(MAX_16/3):((2*MAX_16)/3)]};
bins high_range = {[((2*MAX_16)/3):$]};
bins maximum_value = {MAX_16};
}
blink_y_per_channel_cross_cp: cross blink_y_cp, channels_cp;
blink_x_y_cross_cp: cross blink_x_cp, blink_y_cp {
bins x_lt_y = (binsof(blink_x_cp) && binsof(blink_y_cp))
with (blink_x_cp < blink_y_cp);
bins x_gt_y = (binsof(blink_x_cp) && binsof(blink_y_cp))
with (blink_x_cp > blink_y_cp);
bins x_eq_y = (binsof(blink_x_cp) && binsof(blink_y_cp))
with (blink_x_cp == blink_y_cp);
}
blink_x_y_cross_per_channel_cross_cp: cross blink_x_y_cross_cp, channels_cp;
endgroup : pwm_per_channel_cg
covergroup lowpower_cg with function sample(bit tl_clk_gate,
bit pwm_if_pulse);
pwm_pulse_cp: coverpoint pwm_if_pulse {
bins pulses = (0, 1 => 1, 0);
}
tl_clk_gated_cp: coverpoint tl_clk_gate {
bins gated = {1};
ignore_bins not_gated = {0};
}
pulse_while_gated_cross_cp: cross pwm_pulse_cp, tl_clk_gated_cp {
option.at_least = 1;
}
endgroup : lowpower_cg
covergroup clock_cg with function sample(int core_clk_freq, int tl_clk_freq);
core_clk_cp: coverpoint core_clk_freq {
bins valid_range[10] = {[0:50]};
}
tl_clk_cp: coverpoint tl_clk_freq {
bins valid_range[1] = {[0:50]};
}
tl_core_eq_cross_cp: cross core_clk_cp, tl_clk_cp;
endgroup : clock_cg
// Since DUT doesnt have a status register or a output signal to monitor underflow / overflow.
// passing the coverage from TB calculated values
covergroup dc_uf_ovf_tb_cg with function sample(bit [PWM_NUM_CHANNELS-1:0] channel, bit uf_ovf);
// sampled channel
channels_cp: coverpoint channel {
wildcard bins channel_0 = {6'b?????1};
wildcard bins channel_1 = {6'b????1?};
wildcard bins channel_2 = {6'b???1??};
wildcard bins channel_3 = {6'b??1???};
wildcard bins channel_4 = {6'b?1????};
wildcard bins channel_5 = {6'b1?????};
}
dc_uf_ovf_cp: coverpoint uf_ovf {
bins dc_overflow = {1};
bins dc_underflow = {0};
}
pwm_uf_ovf_cross_cp: cross channels_cp, dc_uf_ovf_cp;
endgroup : dc_uf_ovf_tb_cg
function new(string name, uvm_component parent);
super.new(name, parent);
//regwen_cg = new(); // TODO stage V2S
cfg_cg = new();
pwm_chan_en_inv_cg = new();
pwm_per_channel_cg = new();
lowpower_cg = new();
clock_cg = new();
dc_uf_ovf_tb_cg = new();
endfunction : new
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
// [or instantiate covergroups here]
// Please instantiate sticky_intr_cov array of objects for all interrupts that are sticky
// See cip_base_env_cov for details
endfunction
endclass