| // 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 |