blob: e56da96be92306d869077d91c73dca6270d5a7e6 [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.
*/
// Covers various configuration combinations for the masked version of KMAC.
//
// Declare this outside of `kmac_env_cov` so that we can conditionally instantiate this in the
// `build_phase` depending on a value in the env_cfg object.
// macro for the common KMAC configuration fields
`define COMMON_CFG_CGS \
kmac_en: coverpoint kmac; \
xof_en: coverpoint xof; \
strength: coverpoint kstrength; \
mode: coverpoint kmode; \
key_len: coverpoint key; \
msg_endian: coverpoint msg_endianness; \
state_endian: coverpoint state_endianness; \
sideload: coverpoint en_sideload;
// creates the cross bins for all XOF functions
`define XOF_CROSS_CG(strength_cg, valid_mode_expr) \
bins valid = ``valid_mode_expr`` && binsof(``strength_cg``) intersect {sha3_pkg::L128, sha3_pkg::L256}; \
ignore_bins invalid_mode = !``valid_mode_expr``; \
ignore_bins invalid_strength = !binsof(``strength_cg``) intersect {sha3_pkg::L128, sha3_pkg::L256};
// creates the cross bins for SHA3 functions
`define SHA3_CROSS_CG(mode_cg, strength_cg) \
bins valid = binsof(``mode_cg``) intersect {sha3_pkg::Sha3}; \
ignore_bins invalid_mode = !binsof(``mode_cg``) intersect {sha3_pkg::Sha3}; \
ignore_bins invalid_strength = binsof(``strength_cg``) intersect {sha3_pkg::L128};
// creates a coverpoint to cover different TLUL access granularities
`define MASK_CP(name, mask) \
``name``: coverpoint ``mask`` { \
bins byte_access = {'b0001, 'b0010, 'b0100, 'b1000}; \
bins halfword_access = {'b0011, 'b0110, 'b1100}; \
bins triple_byte_access = {'b0111, 'b1110}; \
bins word_access = {'b1111}; \
}
covergroup config_masked_cg with function sample(bit kmac, bit xof,
sha3_pkg::keccak_strength_e kstrength,
sha3_pkg::sha3_mode_e kmode,
kmac_pkg::key_len_e key,
bit msg_endianness,
bit state_endianness,
bit en_sideload,
kmac_pkg::entropy_mode_e entr_mode,
bit fast_entropy);
`COMMON_CFG_CGS
entropy_mode: coverpoint entr_mode;
entropy_fast_process: coverpoint fast_entropy;
// cross the various configuration settings
kmac_cross: cross kmac_en, xof_en, strength, key_len, msg_endian,
state_endian, entropy_mode, entropy_fast_process {
`XOF_CROSS_CG(strength, binsof(kmac_en) intersect {1})
}
cshake_cross: cross mode, strength, msg_endian, state_endian,
entropy_mode, entropy_fast_process {
`XOF_CROSS_CG(strength, binsof(mode) intersect {sha3_pkg::CShake})
}
shake_cross: cross mode, strength, msg_endian, state_endian,
entropy_mode, entropy_fast_process {
`XOF_CROSS_CG(strength, binsof(mode) intersect {sha3_pkg::Shake})
}
sha3_cross: cross mode, strength, msg_endian, state_endian,
entropy_mode, entropy_fast_process {
`SHA3_CROSS_CG(mode, strength)
}
endgroup
// Covers various configuration combinations for the unmasked version of KMAC.
//
// Declare this outside of `kmac_env_cov` so that we can conditionally instantiate this in the
// `build_phase` depending on a value in the env_cfg object.
covergroup config_unmasked_cg with function sample(bit kmac, bit xof,
sha3_pkg::keccak_strength_e kstrength,
sha3_pkg::sha3_mode_e kmode,
kmac_pkg::key_len_e key,
bit msg_endianness,
bit state_endianness,
bit en_sideload);
`COMMON_CFG_CGS
// cross the various configuration settings
kmac_cross: cross kmac_en, xof_en, strength, key_len, msg_endian, state_endian {
`XOF_CROSS_CG(strength, binsof(kmac_en) intersect {1})
}
cshake_cross: cross mode, strength, msg_endian, state_endian {
`XOF_CROSS_CG(strength, binsof(mode) intersect {sha3_pkg::CShake})
}
shake_cross: cross mode, strength, msg_endian, state_endian {
`XOF_CROSS_CG(strength, binsof(mode) intersect {sha3_pkg::Shake})
}
sha3_cross: cross mode, strength, msg_endian, state_endian {
`SHA3_CROSS_CG(mode, strength)
}
endgroup
// Wrapper class for the covergroup for the application interface.
//
// We do this so that we can create an array of these covergroups for each app interface
// present in the testbench environment.
class app_cg_wrap;
// done signal is sent while kecak rounds are running
covergroup app_cg(string name) with function sample(bit single_beat,
bit [keymgr_pkg::KmacDataIfWidth/8-1:0] strb,
bit err,
bit is_done,
bit in_keccak);
option.per_instance = 1;
option.name = name;
single_data_beat: coverpoint single_beat;
data_strb: coverpoint strb {
bins one_byte = {'b0000_0001};
bins two_bytes = {'b0000_0011};
bins three_bytes = {'b0000_0111};
bins four_bytes = {'b0000_1111};
bins five_bytes = {'b0001_1111};
bins six_bytes = {'b0011_1111};
bins seven_bytes = {'b0111_1111};
bins full_data_beat = {'1};
illegal_bins invalid = default;
}
app_err: coverpoint err;
done: coverpoint is_done;
in_keccak_rounds: coverpoint in_keccak;
partial_data_on_last_beat: cross done, data_strb {
bins valid = binsof(done) intersect {1};
ignore_bins invalid = !binsof(done) intersect {1};
}
done_in_keccak_rounds: cross done, in_keccak_rounds {
bins valid = binsof(done) intersect {1};
ignore_bins invalid = !binsof(done) intersect {1};
}
endgroup
function new(string name = "app_cg");
app_cg = new(name);
endfunction
function void sample(bit single_beat,
bit [keymgr_pkg::KmacDataIfWidth/8-1:0] strb,
bit err,
bit is_done,
bit in_keccak);
app_cg.sample(single_beat, strb, err, is_done, in_keccak);
endfunction
endclass
// Covers whether we see an EDN response while keccak rounds are active/inactive.
// Create this covergroup outside of the class as its instantiation relies on a field in the
// env.cfg.
covergroup edn_cg with function sample(bit in_keccak_rounds);
edn_in_keccak: coverpoint in_keccak_rounds;
endgroup
class kmac_env_cov extends cip_base_env_cov #(.CFG_T(kmac_env_cfg));
`uvm_component_utils(kmac_env_cov)
// the base class provides the following handles for use:
// kmac_env_cfg: cfg
// covergroups
config_masked_cg config_masked_cg;
config_unmasked_cg config_unmasked_cg;
edn_cg edn_cg;
app_cg_wrap app_cg_wrappers[kmac_pkg::NumAppIntf];
covergroup msg_len_cg with function sample(int len);
msg_len: coverpoint len {
bins len_0 = {0};
bins len_1 = {1};
bins len_keccak_block_sizes[] = {72, 104, 136, 144, 168};
bins len_0_256 = {[0 : 256]};
bins len_257_512 = {[257 : 512]};
bins len_513_768 = {[513 : 768]};
bins len_769_1024 = {[769 : 1024]};
bins len_1025_2500 = {[1025 : 2500]};
bins len_2501_5000 = {[2501 : 5000]};
bins len_5001_7500 = {[5001 : 7500]};
bins len_7501_10000 = {[7501 : 10_000]};
bins remainder = default;
}
endgroup
covergroup output_digest_len_cg with function sample(int len);
output_digest_len: coverpoint len {
bins len_1 = {1};
bins len_2_63 = {[2 : 63]};
bins len_datapath_width = {64};
bins len_keccak_block_sizes[] = {72, 104, 136, 144, 168};
bins len_min_for_xof_require_squeeze = {137, 169};
bins len_65_200 = {[65 : 200]};
bins len_201_400 = {[201 : 400]};
bins len_401_600 = {[401 : 600]};
bins len_601_800 = {[601 : 800]};
bins len_801_1000 = {[801 : 1_000]};
bins remainder = default;
}
endgroup
covergroup prefix_range_cg with function sample(byte b);
prefix_range: coverpoint b {
bins space = {32};
bins capital_letters = {[65 : 90]};
bins lowercase_letters = {[97 : 122]};
bins rest = default;
}
endgroup
covergroup msgfifo_write_mask_cg with function sample(bit [TL_DBW-1:0] mask);
`MASK_CP(msgfifo_write_mask, mask)
endgroup
covergroup msgfifo_level_cg with function sample(bit fifo_empty, bit fifo_full, bit [4:0] fifo_depth,
sha3_pkg::sha3_mode_e mode, bit kmac_en);
kmac_mode: coverpoint kmac_en;
hash_mode: coverpoint mode {
bins sha3 = {sha3_pkg::Sha3};
bins shake = {sha3_pkg::Shake};
bins cshake = {sha3_pkg::CShake};
}
msgfifo_empty: coverpoint fifo_empty;
msgfifo_full: coverpoint fifo_full;
msgfifo_depth: coverpoint fifo_depth {
bins depth[] = {[0 : KMAC_FIFO_DEPTH]};
bins invalid = default;
}
endgroup
covergroup sha3_status_cg with function sample(bit sha3_idle, bit sha3_absorb, bit sha3_squeeze);
idle: coverpoint sha3_idle;
absorb: coverpoint sha3_absorb;
squeeze: coverpoint sha3_squeeze;
endgroup
covergroup state_read_mask_cg with function sample(bit [TL_DBW-1:0] mask, bit share_num);
share: coverpoint share_num;
`MASK_CP(state_read_mask, mask)
state_mask_share_cross: cross share, state_read_mask;
endgroup
covergroup cmd_process_cg with function sample(bit in_keccak_rounds, bit keccak_complete_cycle);
in_keccak: coverpoint in_keccak_rounds;
in_keccak_complete_cycle: coverpoint keccak_complete_cycle;
endgroup
covergroup sideload_cg with function sample(bit en_sideload, bit in_kmac, bit app_keymgr);
sideload: coverpoint en_sideload;
kmac_mode: coverpoint in_kmac;
in_app_keymgr: coverpoint app_keymgr;
sideload_cross: cross sideload, kmac_mode, in_app_keymgr {
bins sw_kmac_valid_sideload = binsof(sideload) intersect {1} && binsof(kmac_mode);
bins sw_kmac_invalid_sideload = binsof(sideload) intersect {1} && binsof(kmac_mode);
bins app_valid_sideload = binsof(sideload) intersect {1} && binsof(in_app_keymgr);
bins app_invalid_sideload = binsof(sideload) intersect {1} && binsof(in_app_keymgr);
ignore_bins invalid = !binsof(sideload) intersect {1};
}
endgroup
covergroup app_cg with function sample();
endgroup
covergroup error_cg with function sample(kmac_pkg::err_code_e kmac_err,
sha3_pkg::err_code_e sha3_err);
// placeholder comment
kmac_err_code: coverpoint kmac_err {
bins err_none = {kmac_pkg::ErrNone};
bins err_key_not_valid = {kmac_pkg::ErrKeyNotValid};
bins err_sw_pushed_msg_fifo = {kmac_pkg::ErrSwPushedMsgFifo};
bins err_sw_pushed_wrong_cmd = {kmac_pkg::ErrSwPushedWrongCmd};
bins err_wait_timer_expired = {kmac_pkg::ErrWaitTimerExpired};
bins err_incorrect_entropy_mode = {kmac_pkg::ErrIncorrectEntropyMode};
bins invalid = default;
}
sha3_err_code: coverpoint sha3_err {
bins err_none = {sha3_pkg::ErrNone};
bins err_sha3_sw_control = {sha3_pkg::ErrSha3SwControl};
bins invalid = default;
}
endgroup
function sample_cfg(bit kmac,
bit xof,
sha3_pkg::keccak_strength_e kstrength,
sha3_pkg::sha3_mode_e kmode,
kmac_pkg::key_len_e key_len,
bit msg_endianness,
bit state_endianness,
bit en_sideload,
kmac_pkg::entropy_mode_e entropy_mode,
bit fast_entropy);
if (cfg.enable_masking) begin
config_masked_cg.sample(kmac, xof, kstrength, kmode, key_len, msg_endianness,
state_endianness, en_sideload, entropy_mode,
fast_entropy);
end else begin
config_unmasked_cg.sample(kmac, xof, kstrength, kmode, key_len,
msg_endianness, state_endianness,
en_sideload);
end
endfunction
function new(string name, uvm_component parent);
kmac_app_e app_name = app_name.first;
super.new(name, parent);
// [instantiate covergroups here]
msg_len_cg = new();
output_digest_len_cg = new();
prefix_range_cg = new();
msgfifo_write_mask_cg = new();
msgfifo_level_cg = new();
sha3_status_cg = new();
state_read_mask_cg = new();
cmd_process_cg = new();
sideload_cg = new();
error_cg = new(); // TODO sample this in scb
do begin
app_cg_wrappers[app_name] = new({app_name.name(), "_cg"});
app_name = app_name.next;
end while (app_name != app_name.first);
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
if (cfg.enable_masking) begin
config_masked_cg = new();
edn_cg = new();
end else begin
config_unmasked_cg = new();
end
endfunction
endclass
`undef MASK_CP
`undef SHA3_CROSS_CG
`undef XOF_CROSS_CG
`undef COMMON_CFG_CGS