blob: ca967018861783fb62e14ebcdbde2509d872efcb [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//
// Implements functional coverage for AES
interface aes_cov_if
(
input bit clk_i,
input bit idle_i
);
import uvm_pkg::*;
import aes_pkg::*;
import dv_utils_pkg::*;
`include "dv_fcov_macros.svh"
bit en_full_cov = 1'b1;
bit en_intg_cov = 1'b1;
///////////////////////////////////
// Control register cover points //
///////////////////////////////////
covergroup aes_aux_regwen_cg with function sample(bit regwen);
option.per_instance = 1;
option.name = "aes_aux_ctrl_cg";
cp_regwen: coverpoint regwen;
endgroup // aes_aux_regen_cg
covergroup aes_ctrl_cg with function sample(
bit aes_op,
bit [aes_pkg::AES_MODE_WIDTH-1:0] aes_mode,
bit [aes_pkg::AES_KEYLEN_WIDTH-1:0] aes_keylen,
bit aes_man_op,
bit aes_sideload,
bit [aes_pkg::AES_PRNGRESEEDRATE_WIDTH-1:0] aes_prng_reseed_rate
);
option.per_instance = 1;
option.name = "aes_ctrl_cg";
cp_operation: coverpoint aes_op
{
bins enc = {AES_ENC};
bins dec = {AES_DEC};
bins illegal = { [0:$] } with ($countones(item) != 1);
}
cp_mode: coverpoint aes_mode
{
bins ecb = { AES_ECB};
bins cbc = { AES_CBC };
bins cfb = { AES_CFB };
bins ofb = { AES_OFB };
bins ctr = { AES_CTR };
bins none = { AES_NONE };
bins illegal = { [0:$] } with ($countones(item) != 1);
}
cp_key_len: coverpoint aes_keylen
{
bins aes_128 = {AES_128};
bins aes_192 = {AES_192};
bins aes_256 = {AES_256};
bins illegal = { [0:$] } with ($countones(item) != 1);
}
cp_manual_operation: coverpoint aes_man_op
{
bins auto_mode = { 1'b0 };
bins manual_mode = { 1'b1 };
}
cp_sideload: coverpoint aes_sideload;
cp_prng_reseed: coverpoint aes_prng_reseed_rate
{
bins per_1 = {PER_1};
bins per_64 = {PER_64};
bins per_8k = {PER_8K};
bins illegal = {[0:$]} with ($countones(item) != 1);
}
// Cross coverage points
// All key_lens are tested in all modes with sideload
cr_mode_key_len: cross cp_mode, cp_key_len, cp_sideload;
// all modes are tested in both auto an manual operation
cr_mode_man_op: cross cp_mode, cp_manual_operation;
// All modes used in both incryption and decryption
cr_mode_op: cross cp_mode, cp_operation;
endgroup // aes_ctrl_cg
///////////////////////////////////
// Status register cover points //
///////////////////////////////////
covergroup aes_status_cg with function sample(status_t aes_status);
option.per_instance = 1;
option.name = "aes_status_cg";
cp_idle: coverpoint aes_status.idle;
cp_stall: coverpoint aes_status.stall;
cp_out_lost: coverpoint aes_status.output_lost;
cp_out_valid: coverpoint aes_status.output_valid;
cp_in_Ready: coverpoint aes_status.input_ready;
cp_alert_recov: coverpoint aes_status.alert_recov_ctrl_update_err;
cp_alert_fatal: coverpoint aes_status.alert_fatal_fault;
endgroup // aes_status_cg
///////////////////////////////////
// Trigger register cover points //
///////////////////////////////////
covergroup aes_trigger_cg with function sample(bit aes_start,
bit aes_key_iv_datain_clear,
bit aes_dataout_clear,
bit aes_prng_reseed
);
option.per_instance = 1;
option.name = "aes_trigger_cg";
cp_start: coverpoint aes_start;
cp_key_iv_datain_clear: coverpoint aes_key_iv_datain_clear;
cp_dataout_clear: coverpoint aes_dataout_clear;
cp_prng_reseed: coverpoint aes_prng_reseed;
cr_clear: cross cp_key_iv_datain_clear, cp_dataout_clear;
endgroup // aes_trigger_cg
///////////////////////////////////
// Alert register cover points //
///////////////////////////////////
covergroup aes_alert_cg with function sample(alert_test_t alert_test);
option.per_instance = 1;
option.name = "aes_test_alert_cg";
cp_fatal_fault: coverpoint alert_test.fatal_fault;
cp_recov_fault: coverpoint alert_test.recov_ctrl_update_err;
endgroup // aes_alert_cg
///////////////////////////////////
// Reseed //
///////////////////////////////////
//TODO V2s
// things to cover (req->ack on edn bus)
// - write to Trigger.reseed does infact cause a reseed
// - if Key_touch_Reseed (enabled) writing a complete key triggers reseeding
// - @Sideload_en triggers a reseed
// this will be covered by assertion
///////////////////////////////////
// transition cover groups //
///////////////////////////////////
// interleaving writes to each registers is allowed
// This covergroup has a bin for each i => j combination. For example, 0 => 0 means "write to
// data_in_0 twice in a row". 3 => 0 means "write to data_in_3 and then data_in_0"
// it also checks that we attemp to access the register while DUT is !idle
// the test well verify correct behavior (read and write data is accepted under certain
// conditions
covergroup aes_wr_data_interleave_cg with function sample(int data_in, bit idle);
option.per_instance = 1;
option.name = "aes_wr_data_interleave_cg";
cp_wr_data: coverpoint data_in
{
bins reg_interleave[] = (0,1,2,3 => 0,1,2,3);
}
// Data can still be accepted when !Idle
// check that we verify this
cp_wr_not_idle: coverpoint data_in iff(!idle)
{
bins data_not_idle = {[0:3]};
}
endgroup
// interleaving writes to each registers is allowed
// This covergroup has a bin for each i => j combination. For example, 0 => 0 means "reading
// data_out_0 twice in a row". 3 => 0 means "reading data_out_3 and then data_out_0"
// it also checks that we attemp to access the register while DUT is !idle
// the test well verify correct behavior (read and write data is accepted under certain
// conditions
covergroup aes_rd_data_interleave_cg with function sample(int data_out, bit idle);
option.per_instance = 1;
option.name = "aes_rd_data_interleave_cg";
cp_rd_data: coverpoint data_out
{
bins reg_interleave[] = (0,1,2,3 => 0,1,2,3);
}
// check that we see reads when not idle
cp_wr_not_idle: coverpoint data_out iff(!idle)
{
bins data_not_idle = {[0:3]};
}
endgroup
// interleaving writes to each registers is allowed
// This covergroup has a bin for each i => j combination. For example, 0 => 0 means "write to
// iv_0 twice in a row". 3 => 0 means "write to iv_3 and then iv_0"
// it also checks that we attemp to access the register while DUT is !idle
// the test well verify correct behavior (read and write data is accepted under certain
// conditions
covergroup aes_iv_interleave_cg with function sample(int iv, bit idle);
option.per_instance = 1;
option.name = "aes_iv_interleave_cg";
cp_iv: coverpoint iv
{
bins reg_interleave[] = (0,1,2,3 => 0,1,2,3);
}
// Writes to IV should be ignored when !IDLE
// check that we actually try to do this
cp_wr_not_idle: coverpoint iv iff(!idle)
{
bins iv_not_idle = {[0:3]};
}
endgroup
// interleaving writes to each registers is allowed
// This covergroup has a bin for each i => j combination. For example, 0 => 0 means "write to
// key_0 twice in a row". 3 => 0 means "write to key_3 and then key_0"
// it also checks that we attemp to access the register while DUT is !idle
// the test well verify correct behavior (read and write data is accepted under certain
// conditions
covergroup aes_key_interleave_cg with function sample(int key, bit idle);
option.per_instance = 1;
option.name = "aes_key_interleave_cg";
cp_key: coverpoint key
{
// we don't care if all transitions have been coverd
// just that we interleave
bins from_0toX = ( 0 => [1:15]);
bins from_1toX = ( 1 => 0) ,(1 => [2:15] );
bins from_2toX = ( 2 => [0:1]) ,(2 => [3:15] );
bins from_3toX = ( 3 => [0:2]) ,(3 => [4:15] );
bins from_4toX = ( 4 => [0:3]) ,(4 => [5:15] );
bins from_5toX = ( 5 => [0:4]) ,(5 => [6:15] );
bins from_6toX = ( 6 => [0:5]) ,(6 => [7:15] );
bins from_7toX = ( 7 => [0:6]) ,(7 => [8:15] );
bins from_8toX = ( 8 => [0:7]) ,(8 => [9:15] );
bins from_9toX = ( 9 => [0:8]) ,(9 => [10:15]);
bins from_10toX = (10 => [0:9]) ,(10 => [11:15]);
bins from_11toX = (11 => [0:10]),(11 => [12:15]);
bins from_12toX = (12 => [0:11]),(12 => [13:15]);
bins from_13toX = (13 => [0:12]),(14 => [14:15]);
bins from_14toX = (14 => [0:13]),(14 => 15);
bins from_15toX = (15 => [0:14]);
}
// Writes to IV should be ignored when !IDLE
// check that we actually try to do this
cp_wr_not_idle: coverpoint key iff(!idle)
{
bins key_not_idle = {[0:3]};
}
endgroup // aes_key_interleave_cg
// interleaving writes to each registers is allowed
// This covergroup has a bin for each i => j combination. For example, 0 => 0 means "write to
// data_in twice in a row". 2 => 0 means "write to iv and then data_in"
covergroup aes_reg_interleave_cg with function sample(bit [1:0] value);
option.per_instance = 1;
option.name = "aes_reg_interleave_cg";
// data in = 0
// key = 1
// iv = 2
cp_reg: coverpoint value
{
bins DataToX = (0 => 1,2);
bins KeyToX = (1 => 0,2);
bins IvToX = (2 => 0,1);
}
endgroup // aes_reg_interleave_cg
///////////////////////////////////
// Instantiation Macros //
///////////////////////////////////
`DV_FCOV_INSTANTIATE_CG(aes_aux_regwen_cg, en_full_cov)
`DV_FCOV_INSTANTIATE_CG(aes_ctrl_cg, en_full_cov)
`DV_FCOV_INSTANTIATE_CG(aes_status_cg, en_full_cov)
`DV_FCOV_INSTANTIATE_CG(aes_trigger_cg, en_full_cov)
`DV_FCOV_INSTANTIATE_CG(aes_alert_cg, en_full_cov)
`DV_FCOV_INSTANTIATE_CG(aes_wr_data_interleave_cg, en_full_cov)
`DV_FCOV_INSTANTIATE_CG(aes_rd_data_interleave_cg, en_full_cov)
`DV_FCOV_INSTANTIATE_CG(aes_iv_interleave_cg, en_full_cov)
`DV_FCOV_INSTANTIATE_CG(aes_key_interleave_cg, en_full_cov)
`DV_FCOV_INSTANTIATE_CG(aes_reg_interleave_cg, en_full_cov)
///////////////////////////////////
// Sample functions //
// needed for xcelium //
///////////////////////////////////
function automatic void cg_aux_regwen_sample(bit val);
aes_aux_regwen_cg_inst.sample(val);
endfunction
function automatic void cg_ctrl_sample(
bit aes_op,
bit [aes_pkg::AES_MODE_WIDTH-1:0] aes_mode,
bit [aes_pkg::AES_KEYLEN_WIDTH-1:0] aes_keylen,
bit aes_man_op,
bit aes_sideload,
bit [aes_pkg::AES_PRNGRESEEDRATE_WIDTH-1:0] aes_prng_reseed_rate
);
aes_ctrl_cg_inst.sample(aes_op, aes_mode, aes_keylen, aes_man_op,
aes_sideload, aes_prng_reseed_rate );
endfunction
function automatic void cg_status_sample(bit [31:0] val);
aes_status_cg_inst.sample(val);
endfunction
function automatic void cg_trigger_sample(bit aes_start,
bit aes_key_iv_datain_clear,
bit aes_dataout_clear,
bit aes_prng_reseed
);
aes_trigger_cg_inst.sample(aes_start,
aes_key_iv_datain_clear,
aes_dataout_clear,
aes_prng_reseed);
endfunction
function automatic void cg_alert_test_sample(bit [31:0] val);
aes_alert_cg_inst.sample(val);
endfunction
function automatic void cg_wr_data_sample(int data_in);
aes_wr_data_interleave_cg_inst.sample(data_in, idle_i);
aes_reg_interleave_cg_inst.sample(0);
endfunction
function automatic void cg_rd_data_sample(int data_out);
aes_rd_data_interleave_cg_inst.sample(data_out, idle_i);
endfunction
function automatic void cg_iv_sample(int iv);
aes_iv_interleave_cg_inst.sample(iv, idle_i);
aes_reg_interleave_cg_inst.sample(2);
endfunction
function automatic void cg_key_sample(int key);
aes_key_interleave_cg_inst.sample(key, idle_i);
aes_reg_interleave_cg_inst.sample(1);
endfunction
endinterface