Skip to content

Commit

Permalink
[aes/dv] Randomly drive invalid AES operation values
Browse files Browse the repository at this point in the history
This commit properly randomizes the operation values to fix a coverage
hole. Previously, the operation field of the main control register
was only written with valid one-hot encoded values but not with invalid
values leading to a small DV coverage hole.

This resolves lowRISC#20941.

Signed-off-by: Pirmin Vogel <[email protected]>
  • Loading branch information
vogelpi committed Sep 25, 2024
1 parent f15c944 commit 6ba8da3
Show file tree
Hide file tree
Showing 16 changed files with 123 additions and 88 deletions.
14 changes: 9 additions & 5 deletions hw/ip/aes/dv/env/aes_env_cfg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ class aes_env_cfg extends cip_base_env_cfg #(.RAL_T(aes_reg_block));
bit fixed_data_en = 0;
// fixed operation
bit fixed_operation_en = 0;
bit fixed_operation = 1'b0;
bit [1:0] fixed_operation = AES_ENC;
// fixed iv (will set all to bits 0)
bit fixed_iv_en = 0;

Expand All @@ -90,10 +90,14 @@ class aes_env_cfg extends cip_base_env_cfg #(.RAL_T(aes_reg_block));
// [3]: inject Lc_escalate
error_types_t error_types = 4'b1111;

// [2]: reseed error
// [1]: mode error
// [0]: key_len
cfg_error_type_t config_error_type = 3'b111;
// [0]: op_error
// [1]: reseed error
// [2]: mode error
// [3]: key_len
cfg_error_type_t config_error_type_en = '{key_len: 1'b1,
mode: 1'b1,
rsd_rate: 1'b1,
op: 1'b1};
int config_error_pct = 30;

// min and max wait (clk) before an error injection
Expand Down
1 change: 1 addition & 0 deletions hw/ip/aes/dv/env/aes_env_pkg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ package aes_env_pkg;
bit key_len;
bit mode;
bit rsd_rate;
bit op;
} cfg_error_type_t;

// used in FI verification seq and if
Expand Down
150 changes: 84 additions & 66 deletions hw/ip/aes/dv/env/aes_message_item.sv
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class aes_message_item extends uvm_sequence_item;
int message_len_min = 1;
// percentage of configuration errors
int config_error_pct = 20;
cfg_error_type_t config_error_type_en = 3'b000;
cfg_error_type_t config_error_type_en = '0;
// errors enabled mask
error_types_t error_types = 3'b000;

Expand Down Expand Up @@ -49,7 +49,7 @@ class aes_message_item extends uvm_sequence_item;
bit [3:0] [31:0] fixed_data = 128'hDEADBEEFEEDDBBAABAADBEEFDEAFBEAD;
bit [7:0] [31:0] fixed_key [2] = '{256'h0000111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFF, 256'h0};
bit [2:0] fixed_keylen = 3'b001;
bit fixed_operation = 1'b0;
bit [1:0] fixed_operation = AES_ENC;
bit [3:0] [31:0] fixed_iv = 128'h00000000000000000000000000000000;

// Mode distribution //
Expand Down Expand Up @@ -87,7 +87,7 @@ class aes_message_item extends uvm_sequence_item;
// mode - which type of ecnryption is used //
rand aes_mode_e aes_mode = AES_NONE;
// operation - encruption or decryption //
rand aes_op_e aes_operation;
rand bit [1:0] aes_operation;
// aes key length //
rand bit [2:0] aes_keylen;
// 256 bit key (8x32 bit) //
Expand All @@ -96,7 +96,10 @@ class aes_message_item extends uvm_sequence_item;
rand bit [3:0][31:0] aes_iv;
// configuration error //
rand bit has_config_error;
// [0] mode error [1] key_len error
// [0]: op_error
// [1]: reseed error
// [2]: mode error
// [3]: key_len
rand cfg_error_type_t cfg_error_type;
// run AES in manual mode
rand bit manual_operation;
Expand All @@ -119,38 +122,91 @@ class aes_message_item extends uvm_sequence_item;

constraint data_c { message_length inside { [message_len_min:message_len_max] };}

constraint has_config_error_c {
if (error_types.cfg) {
has_config_error dist { 0 :/ (100 - config_error_pct),
1 :/ config_error_pct};
} else {
has_config_error == 0;
}
}

constraint config_error_type_c {
solve has_config_error before cfg_error_type;
if (has_config_error) {
cfg_error_type inside {[1:15]};
config_error_type_en.op == 0 -> cfg_error_type.op == 0;
config_error_type_en.rsd_rate == 0 -> cfg_error_type.rsd_rate == 0;
config_error_type_en.mode == 0 -> cfg_error_type.mode == 0;
config_error_type_en.key_len == 0 -> cfg_error_type.key_len == 0;
} else {
cfg_error_type == '0;
}
}

constraint keylen_c {
solve has_config_error before aes_keylen;
solve cfg_error_type before aes_keylen;
if (!(has_config_error && cfg_error_type.key_len) ) {
// key len 001: 128, 010: 192, 100: 256
aes_keylen inside { 3'b001, 3'b010, 3'b100 };
// mode distribution
aes_keylen dist { 3'b001 := key_128b_weight,
3'b010 := key_192b_weight,
3'b100 := key_256b_weight };
aes_keylen inside { AES_128, AES_192, AES_256 };
aes_keylen dist { AES_128 := key_128b_weight,
AES_192 := key_192b_weight,
AES_256 := key_256b_weight };
} else {
// force the selection to be something invalid
!(aes_keylen inside { 3'b001, 3'b010, 3'b100 });
!(aes_keylen inside { AES_128, AES_192, AES_256 });
}
// A fixed key length is given the highest priority. This setting is mostly useful for
// debugging the DUT.
if (fixed_keylen_en) {
aes_keylen == fixed_keylen
};
}

constraint mode_c {
solve has_config_error before aes_mode;
solve cfg_error_type before aes_mode;
if (!(has_config_error && cfg_error_type.mode)) {
aes_mode dist { AES_ECB := ecb_weight,
AES_CBC := cbc_weight,
AES_CFB := cfb_weight,
AES_OFB := ofb_weight,
AES_CTR := ctr_weight};
} else {
// the mode will be randomized to a random
// non legal value later.
aes_mode == AES_NONE;
}
}

constraint rsd_rate_c {
solve has_config_error before reseed_rate;
solve cfg_error_type before reseed_rate;
if (!(has_config_error && cfg_error_type.rsd_rate) ) {
reseed_rate inside { 3'b001, 3'b010, 3'b100 };
reseed_rate dist { 3'b001 :/ per1_weight,
3'b010 :/ per64_weight,
3'b100 :/ per8k_weight };
reseed_rate inside { PER_1, PER_64, PER_8K };
reseed_rate dist { PER_1 :/ per1_weight,
PER_64 :/ per64_weight,
PER_8K :/ per8k_weight };
} else {
!( reseed_rate inside { 3'b001, 3'b010, 3'b100 });
!( reseed_rate inside { PER_1, PER_64, PER_8K });
}
}

constraint operation_c {
solve has_config_error before aes_operation;
solve cfg_error_type before aes_operation;
if (!(has_config_error && cfg_error_type.op) ) {
aes_operation inside { AES_ENC, AES_DEC };
aes_operation dist { AES_ENC :/ 1,
AES_DEC :/ 1 };
} else {
!( aes_operation inside { AES_ENC, AES_DEC });
}
// A fixed operation is given the highest priority. This setting is mostly useful for
// debugging the DUT.
if (fixed_operation_en) {
aes_operation == fixed_operation
};
}

constraint key_c {
if (fixed_key_en) {
Expand All @@ -165,51 +221,6 @@ class aes_message_item extends uvm_sequence_item;
};
}

constraint operation_c {
if (fixed_operation_en) {
aes_operation == fixed_operation
};
}

constraint mode_c {
solve has_config_error before aes_mode;
solve cfg_error_type before aes_mode;
if (!(has_config_error && cfg_error_type.mode)) {
aes_mode dist { AES_ECB := ecb_weight,
AES_CBC := cbc_weight,
AES_CFB := cfb_weight,
AES_OFB := ofb_weight,
AES_CTR := ctr_weight};
} else {
// the mode will be randomized to a random
// non legal value later.
aes_mode == AES_NONE;
}
}

constraint has_config_error_c {
if (error_types.cfg)
{
has_config_error dist { 0 :/ (100 - config_error_pct),
1 :/ config_error_pct};
}
else { has_config_error == 0;}
}


constraint config_error_type_c {
solve has_config_error before cfg_error_type;
solve sideload_en before cfg_error_type;
if (has_config_error) {
cfg_error_type inside {[1:7]};
config_error_type_en[0] == 0 -> cfg_error_type[0] == 0;
config_error_type_en[1] == 0 -> cfg_error_type[1] == 0;
config_error_type_en[2] == 0 -> cfg_error_type[2] == 0;
} else {
cfg_error_type == 3'b000;
}
}

constraint sideload_c {
sideload_en dist{ 0:/(100-sideload_pct),
1:/sideload_pct};
Expand All @@ -223,10 +234,8 @@ class aes_message_item extends uvm_sequence_item;
} else {
manual_operation == 0 ;
}

}


function void add_data_item(aes_seq_item item);
for (int i=0; i < 4 ; i++) begin
input_msg = { input_msg , item.data_in[i][7:0], item.data_in[i][15:8], item.data_in[i][23:16]
Expand All @@ -252,6 +261,14 @@ class aes_message_item extends uvm_sequence_item;
// Check for invalid configuration values and resolve them if necessary. Illegal mode values
// don't need to be handled here as they don't result in the DUT actually producing output
// data.
if (item.operation inside {AES_ENC, AES_DEC}) begin
this.aes_operation = item.operation;
end else begin
this.aes_operation = AES_ENC;
`uvm_info(`gfn,
$sformatf("\n\t ---| Illegal operation value detected. Resolving to default AES_ENC"),
UVM_MEDIUM)
end
if (item.key_len inside {AES_128, AES_192, AES_256}) begin
this.aes_keylen = item.key_len;
end else begin
Expand Down Expand Up @@ -286,8 +303,9 @@ class aes_message_item extends uvm_sequence_item;
str = {str, "\n\t ----| "};
str = {str, $sformatf("\n\t ----| Mode: \t \t \t %s \t ",
aes_mode.name())};
str = {str, $sformatf("\n\t ----| Operation: \t \t %s \t ",
aes_operation.name())};
str = {str, $sformatf("\n\t ----| Operation: %s",
aes_operation == AES_ENC ? "AES_ENC" :
aes_operation == AES_DEC ? "AES_DEC" : "INVALID")};
str = {str, $sformatf("\n\t ----| has Configuration error: %s \t \t \t ",
(has_config_error==1) ? "TRUE" : "FALSE")};
str = {str, $sformatf("\n\t ----| Mode error en: \t %d \n\t ----| Key_len error en: \t %d \t \t ",
Expand Down
5 changes: 3 additions & 2 deletions hw/ip/aes/dv/env/aes_seq_item.sv
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class aes_seq_item extends uvm_sequence_item;
`uvm_object_utils(aes_seq_item)

aes_item_type_e item_type;
aes_op_e operation;
bit [1:0] operation;

///////////////////////////////////////
// Control Knobs //
Expand Down Expand Up @@ -335,7 +335,8 @@ class aes_seq_item extends uvm_sequence_item;
str = {str, $psprintf("\n\t ----| AES Mode: \t %s |----\t ",
mode.name()) };
str = {str, $psprintf("\n\t ----| Operation: \t %s |----\t ",
operation.name() ) };
operation == AES_ENC ? "AES_ENC" :
operation == AES_DEC ? "AES_DEC" : "INVALID")};
str = {str, $psprintf("\n\t ----| Key len: \t %s \t(%3b) |----\t ",
(key_len==3'b001) ? "128b" : (key_len == 3'b010) ? "192b" : "256b", key_len)};
str = {str, $psprintf("\n\t ----| Key Share 0: \t ")};
Expand Down
10 changes: 8 additions & 2 deletions hw/ip/aes/dv/env/seq_lib/aes_base_vseq.sv
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,10 @@ class aes_base_vseq extends cip_base_vseq #(


virtual task set_operation(bit [1:0] operation);
if (ral.ctrl_shadowed.operation.get_mirrored_value() != operation) begin
ral.ctrl_shadowed.operation.set(operation);
csr_update(.csr(ral.ctrl_shadowed), .en_shadow_wr(1'b1), .blocking(1));
end
endtask // set_operation


Expand Down Expand Up @@ -1011,7 +1013,7 @@ class aes_base_vseq extends cip_base_vseq #(
aes_message.message_len_min = cfg.message_len_min;
aes_message.config_error_pct = cfg.config_error_pct;
aes_message.error_types = cfg.error_types;
aes_message.config_error_type_en = cfg.config_error_type;
aes_message.config_error_type_en = cfg.config_error_type_en;
aes_message.manual_operation_pct = cfg.manual_operation_pct;
aes_message.keymask = cfg.key_mask;
aes_message.fixed_key_en = cfg.fixed_key_en;
Expand All @@ -1032,7 +1034,11 @@ class aes_base_vseq extends cip_base_vseq #(
aes_message_item cloned_message;
for (int i=0; i < cfg.num_messages; i++) begin
`DV_CHECK_RANDOMIZE_FATAL(aes_message)
if (aes_message.cfg_error_type[1] == 1'b1) cfg.num_corrupt_messages += 1;
// For errors in the mode field, the DUT will not produce any output. Such messages are
// counted as corrupt messages.
if (aes_message.cfg_error_type.mode == 1'b1) begin
cfg.num_corrupt_messages += 1;
end
`downcast(cloned_message, aes_message.clone());
message_queue.push_front(cloned_message);
`uvm_info(`gfn, $sformatf("\n\t ----| MESSAGE # %d \n %s",i, cloned_message.convert2string())
Expand Down
2 changes: 1 addition & 1 deletion hw/ip/aes/dv/tests/aes_alert_reset_test.sv
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class aes_alert_reset_test extends aes_base_test;
cfg.fixed_key_en = 0;

cfg.fixed_operation_en = 0;
cfg.fixed_operation = 0;
cfg.fixed_operation = aes_pkg::AES_ENC;

cfg.fixed_keylen_en = 0;
cfg.fixed_keylen = 3'b001;
Expand Down
2 changes: 1 addition & 1 deletion hw/ip/aes/dv/tests/aes_b2b_test.sv
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class aes_b2b_test extends aes_base_test;
cfg.fixed_key_en = 0;

cfg.fixed_operation_en = 0;
cfg.fixed_operation = 0;
cfg.fixed_operation = aes_pkg::AES_ENC;

cfg.fixed_keylen_en = 0;
cfg.fixed_keylen = 3'b010;
Expand Down
2 changes: 1 addition & 1 deletion hw/ip/aes/dv/tests/aes_base_test.sv
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ class aes_base_test extends cip_base_test #(
cfg.fixed_data_en = 0;
// fixed operation (enc or dec)
cfg.fixed_operation_en = 0;
cfg.fixed_operation = 1'b0;
cfg.fixed_operation = aes_pkg::AES_ENC;
// fixed iv (will set all to 0)
cfg.fixed_iv_en = 0;
cfg.fixed_keylen_en = 0;
Expand Down
2 changes: 1 addition & 1 deletion hw/ip/aes/dv/tests/aes_clear_test.sv
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class aes_clear_test extends aes_base_test;
cfg.fixed_key_en = 0;

cfg.fixed_operation_en = 0;
cfg.fixed_operation = 0;
cfg.fixed_operation = aes_pkg::AES_ENC;

cfg.fixed_keylen_en = 0;
cfg.fixed_keylen = 3'b001;
Expand Down
7 changes: 5 additions & 2 deletions hw/ip/aes/dv/tests/aes_config_error_test.sv
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ class aes_config_error_test extends aes_base_test;

cfg.error_types = 4'b0001;
cfg.config_error_pct = 75;
cfg.config_error_type = 3'b111;
cfg.config_error_type_en = '{key_len: 1'b1,
mode: 1'b1,
rsd_rate: 1'b1,
op: 1'b1};
cfg.num_messages_min = 3;
cfg.num_messages_max = 10;
// message related knobs
Expand All @@ -37,7 +40,7 @@ class aes_config_error_test extends aes_base_test;
cfg.fixed_key_en = 0;

cfg.fixed_operation_en = 0;
cfg.fixed_operation = 0;
cfg.fixed_operation = aes_pkg::AES_ENC;

cfg.fixed_keylen_en = 0;
cfg.fixed_keylen = 3'b001;
Expand Down
2 changes: 1 addition & 1 deletion hw/ip/aes/dv/tests/aes_fi_test.sv
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class aes_fi_test extends aes_base_test;
cfg.fixed_key_en = 0;

cfg.fixed_operation_en = 0;
cfg.fixed_operation = 0;
cfg.fixed_operation = aes_pkg::AES_ENC;

cfg.fixed_keylen_en = 0;
cfg.fixed_keylen = 3'b001;
Expand Down
Loading

0 comments on commit 6ba8da3

Please sign in to comment.