[aes:dv] Rework of aes DV
Reworked scoreboard to support CTR and CBC modes better
Added new Tests and removed sanity sequence
which is now using stress_vseq
Signed-off-by: Rasmus Madsen <rasmus.madsen@wdc.com>
diff --git a/hw/ip/aes/dv/aes_model_dpi/aes_model_dpi_pkg.sv b/hw/ip/aes/dv/aes_model_dpi/aes_model_dpi_pkg.sv
index 15ca238..653d652 100644
--- a/hw/ip/aes/dv/aes_model_dpi/aes_model_dpi_pkg.sv
+++ b/hw/ip/aes/dv/aes_model_dpi/aes_model_dpi_pkg.sv
@@ -74,6 +74,5 @@
c_dpi_aes_crypt_block(impl_i, op_i, mode_i, iv_in, key_len_i, key_i, data_in, data_out);
data_o = aes_transpose(data_out);
return;
- endfunction
-
+ endfunction // sv_dpi_aes_crypt_block
endpackage
diff --git a/hw/ip/aes/dv/aes_sim_cfg.hjson b/hw/ip/aes/dv/aes_sim_cfg.hjson
index 95d7383..8f006b4 100644
--- a/hw/ip/aes/dv/aes_sim_cfg.hjson
+++ b/hw/ip/aes/dv/aes_sim_cfg.hjson
@@ -57,13 +57,20 @@
tests: [
{
name: aes_wake_up
+ uvm_test: aes_wake_up_test
uvm_test_seq: aes_wake_up_vseq
reseed: 1
}
{
name: aes_sanity
- uvm_test_seq: aes_sanity_vseq
+ uvm_test: aes_sanity_test
+ uvm_test_seq: aes_stress_vseq
+ }
+ {
+ name: aes_stress
+ uvm_test: aes_stress_test
+ uvm_test_seq: aes_stress_vseq
}
]
@@ -73,5 +80,9 @@
name: sanity
tests: ["aes_sanity"]
}
+ {
+ name: stress
+ tests: ["aes_stress"]
+ }
]
}
diff --git a/hw/ip/aes/dv/env/aes_env.core b/hw/ip/aes/dv/env/aes_env.core
index a60f994..636bf8b 100644
--- a/hw/ip/aes/dv/env/aes_env.core
+++ b/hw/ip/aes/dv/env/aes_env.core
@@ -17,6 +17,7 @@
files:
- aes_env_pkg.sv
- aes_seq_item.sv: {is_include_file: true}
+ - aes_message_item.sv: {is_include_file: true}
- aes_env_cfg.sv: {is_include_file: true}
- aes_env_cov.sv: {is_include_file: true}
- aes_virtual_sequencer.sv: {is_include_file: true}
@@ -26,7 +27,7 @@
- seq_lib/aes_base_vseq.sv: {is_include_file: true}
- seq_lib/aes_common_vseq.sv: {is_include_file: true}
- seq_lib/aes_wake_up_vseq.sv: {is_include_file: true}
- - seq_lib/aes_sanity_vseq.sv: {is_include_file: true}
+ - seq_lib/aes_stress_vseq.sv: {is_include_file: true}
file_type: systemVerilogSource
generate:
diff --git a/hw/ip/aes/dv/env/aes_env_cfg.sv b/hw/ip/aes/dv/env/aes_env_cfg.sv
index be8ffbf..888780a 100644
--- a/hw/ip/aes/dv/env/aes_env_cfg.sv
+++ b/hw/ip/aes/dv/env/aes_env_cfg.sv
@@ -10,20 +10,42 @@
`uvm_object_new
// Knobs //
- int data_len_min = 128;
- int data_len_max = 128;
- bit use_key_mask = 0;
- bit use_c_model_pct = 0;
+ int num_messages_min = 1;
+ int num_messages_max = 1;
+ int message_len_min = 128;
+ int message_len_max = 128;
+ bit use_key_mask = 0;
+ bit use_c_model_pct = 0;
+ bit errors_en = 0;
+ // Mode distribution //
+ // chance of selection ecb_mode
+ // ecb_mode /(ecb_mode + cbc_mode + ctr_mode)
+ // with the defaults 10/30 = 1/3 (33%)
+ int ecb_weight = 10;
+ int cbc_weight = 10;
+ int ctr_weight = 10;
+ // KEYLEN weights
+ // change of selecting 128b key
+ // 128b/(128+192+256) = 10/30 = (33%)
+ int key_128b_weight = 10;
+ int key_192b_weight = 10;
+ int key_256b_weight = 10;
+ bit [2:0] error_types = 3'b111; // 001: configuration errors
+ // 010: malicous injection
+ // 100: random resets
+ int config_error_pct; // percentage of configuration errors
// rand variables
rand bit ref_model; // 0: C model 1: OPEN_SSL/BORING_SSL
rand bit key_mask; // randomly select if we force unused key bits to 0
+ rand int num_messages; // number of messages to encrypt/decrypt
- // constraints
- constraint c_ref_model { ref_model dist { 0 :/ use_c_model_pct,
- 1 :/ (100-use_c_model_pct) }; }
+ // constraints
+ constraint c_num_messages { num_messages inside {[num_messages_min : num_messages_max] };}
+ constraint c_ref_model { ref_model dist { 0 :/ use_c_model_pct,
+ 1 :/ (100-use_c_model_pct) }; }
function void post_randomize();
if(use_key_mask) key_mask = 1;
@@ -33,11 +55,17 @@
virtual function string convert2string();
string str = "";
str = super.convert2string();
- str = {str, $psprintf("\n\t ----| AES ENVIRONMENT CONFIG \t ") };
- str = {str, $psprintf("\n\t ----| Max data len %d bits \t ", data_len_max) };
- str = {str, $psprintf("\n\t ----| Min data len %d bits \t ", data_len_min) };
- str = {str, $psprintf("\n\t ----| Reference model:\t %s \t ",
- (ref_model==0) ? "C-MODEL" : "OPEN_SSL" ) };
+ str = {str, $sformatf("\n\t ----| AES ENVIRONMENT CONFIG \t ") };
+ str = {str, $sformatf("\n\t ----| Max Number of message %d \t ", num_messages_max) };
+ str = {str, $sformatf("\n\t ----| Min Number of message %d \t ", num_messages_min) };
+ str = {str, $sformatf("\n\t ----| Max message len %d bytes \t ", message_len_max) };
+ str = {str, $sformatf("\n\t ----| Min message len %d bytes \t ", message_len_min) };
+ str = {str, $sformatf("\n\t ----| Reference model:\t %s \t ",
+ (ref_model==0) ? "C-MODEL" : "OPEN_SSL" ) };
+ str = {str, $sformatf("\n\t ----| num_messages # %d \t ", num_messages) };
+ str = {str, $sformatf("\n\t ----| ECB Weight: %d \t ", ecb_weight) };
+ str = {str, $sformatf("\n\t ----| CBC Weight: %d \t ", cbc_weight) };
+ str = {str, $sformatf("\n\t ----| CTR Weight: %d \t ", ctr_weight) };
str = {str, "\n"};
return str;
endfunction
diff --git a/hw/ip/aes/dv/env/aes_env_pkg.sv b/hw/ip/aes/dv/env/aes_env_pkg.sv
index 5afc8b8..4fef4e9 100644
--- a/hw/ip/aes/dv/env/aes_env_pkg.sv
+++ b/hw/ip/aes/dv/env/aes_env_pkg.sv
@@ -13,6 +13,8 @@
import cip_base_pkg::*;
import aes_reg_pkg::*;
import aes_ral_pkg::*;
+ import aes_pkg::*;
+
// macro includes
`include "uvm_macros.svh"
@@ -20,17 +22,16 @@
// parameters
- parameter uint AES_ADDR_MAP_SIZE = 128;
- // types
- // forward declare classes to allow typedefs below
- typedef class aes_env_cfg;
- typedef class aes_env_cov;
+ parameter uint AES_ADDR_MAP_SIZE = 128;
+
+ typedef enum int { AES_CFG=0, AES_DATA=1, AES_ERR_INJ=2 } aes_item_type_e;
// functions
// package sources
`include "aes_env_cfg.sv"
`include "aes_seq_item.sv"
+ `include "aes_message_item.sv"
`include "aes_env_cov.sv"
`include "aes_virtual_sequencer.sv"
`include "aes_scoreboard.sv"
diff --git a/hw/ip/aes/dv/env/aes_message_item.sv b/hw/ip/aes/dv/env/aes_message_item.sv
new file mode 100644
index 0000000..a0294ff
--- /dev/null
+++ b/hw/ip/aes/dv/env/aes_message_item.sv
@@ -0,0 +1,182 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+class aes_message_item extends uvm_sequence_item;
+
+ `uvm_object_utils(aes_message_item)
+
+ `uvm_object_new
+
+ ///////////////////////////////////////
+ // control Knobs //
+ ///////////////////////////////////////
+
+ // min number of data bytes
+ int message_len_max = 16;
+ // Max number of data bytes
+ int message_len_min = 1;
+ // percentage of configuration errors
+ int config_error_pct = 20;
+ // errors enabled
+ bit errors_en = 1;
+ // configuraiton errors enabled
+ bit config_err = 0;
+
+ // Mode distribution //
+ // chance of selection ecb_mode
+ // ecb_mode /(ecb_mode + cbc_mode + ctr_mode)
+ // with the defaults 10/30 = 1/3 (33%)
+ int ecb_weight = 10;
+ int cbc_weight = 10;
+ int ctr_weight = 10;
+ // KEYLEN weights
+ int key_128b_weight = 10;
+ int key_192b_weight = 10;
+ int key_256b_weight = 10;
+
+ ///////////////////////////////////////
+ // Randomizable variables //
+ ///////////////////////////////////////
+
+ // length of the message //
+ rand int message_length;
+ // mode - which type of ecnryption is used //
+ rand aes_mode_e aes_mode;
+ // operation - encruption or decryption //
+ rand aes_op_e aes_operation;
+ // aes key length //
+ rand bit [2:0] aes_keylen;
+ // 256 bit key (8x32 bit) //
+ rand bit [7:0][31:0] aes_key;
+ // 256 bit initialization vector (8x32 bit) //
+ rand bit [3:0][31:0] aes_iv;
+ // configuration error //
+ rand bit has_config_error;
+
+ ///////////////////////////////////////
+ // FIXED variables //
+ ///////////////////////////////////////
+
+ bit [7:0] input_msg[];
+ bit [7:0] output_msg[];
+ bit [7:0] predicted_msg[];
+
+ ///////////////////////////////////////
+ // Constraints //
+ ///////////////////////////////////////
+
+ constraint c_data { message_length inside { [message_len_min:message_len_max] };}
+
+ constraint c_keylen {
+ solve has_config_error before aes_keylen;
+ if(!has_config_error) {
+ // 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 };
+ } else {
+ !(aes_keylen inside { 3'b001, 3'b010, 3'b100 }); // force the selection to be something invalid
+ }
+ }
+
+ constraint c_mode { aes_mode dist { AES_ECB := ecb_weight, AES_CBC:= cbc_weight, AES_CTR := ctr_weight };}
+
+ constraint c_has_config_error {
+ if(errors_en && config_err)
+ {
+ has_config_error dist { 0 :/ (100-config_error_pct),
+ 1 :/ config_error_pct };
+ }
+ else { has_config_error == 0; }
+ }
+
+
+
+ function void add_data_item(aes_seq_item item);
+ for(int i=0; i < 4 ; i++ ) begin
+ // data_in.push_front (data_in[3:0])
+ input_msg = { input_msg , item.data_in[i][7:0], item.data_in[i][15:8], item.data_in[i][23:16]
+ ,item.data_in[i][31:24]};
+ // data_in.push_front (data_in[3:0])
+ output_msg = { output_msg, item.data_out[i][7:0], item.data_out[i][15:8],
+ item.data_out[i][23:16],item.data_out[i][31:24] };
+ end
+ endfunction // add_data_item
+
+
+ function void add_start_msg_item(aes_seq_item item);
+ this.aes_mode = item.mode;
+ this.aes_operation = item.operation;
+ this.aes_keylen = item.key_len;
+ this.aes_key = item.key;
+
+ add_data_item(item);
+ endfunction // add_start_msg_item
+
+
+ function void alloc_predicted_msg();
+ predicted_msg = new[input_msg.size()];
+ endfunction // alloc_predicted_msg
+
+
+ // convert to string //
+ virtual function string convert2string();
+ string str;
+ str = super.convert2string();
+ str = {str, $sformatf("\n\t ----| AES MESSAGE ITEM |----\t ")
+ };
+ str = {str, $sformatf("\n\t ----| Mode: \t %s |----\t ",
+ aes_mode.name() ) };
+ str = {str, $sformatf("\n\t ----| Operation: \t %s |----\t ",
+ aes_operation.name() ) };
+ str = {str, $sformatf("\n\t ----| has Configuration error: \t %s |----\t ",
+ (has_config_error==1) ? "TRUE" : "FALSE" ) };
+ str = {str, $sformatf("\n\t ----| Message Length: \t %d |----\t ",
+ message_length ) };
+
+ str = {str, $sformatf("\n\t ----| Key Length: \t %03b |----\t ",
+ aes_keylen) };
+ str = {str, $sformatf("\n\t ----| Key: \t ") };
+ for(int i=0; i <8; i++) begin
+ str = {str, $sformatf("%h ",aes_key[i])};
+ end
+ str = {str, $sformatf("\n\t ----| errors_enabled: %b \t ", errors_en) };
+ str = {str, $sformatf("\n\t ----| config_err: %b \t ", config_err) };
+ str = {str, $sformatf("\n\t ----| MODE Distribution: \t " ) };
+ str = {str, $sformatf("\n\t ----| ECB Weight: %d \t ", ecb_weight) };
+ str = {str, $sformatf("\n\t ----| CBC Weight: %d \t ", cbc_weight) };
+ str = {str, $sformatf("\n\t ----| CTR Weight: %d \t ", ctr_weight) };
+ str = {str, $sformatf("\n\t ----| Key Len Distribution :\t " ) };
+ str = {str, $sformatf("\n\t ----| 128 Weight: %d \t ", key_128b_weight) };
+ str = {str, $sformatf("\n\t ----| 192 Weight: %d \t ", key_192b_weight) };
+ str = {str, $sformatf("\n\t ----| 256 Weight: %d \t ", key_256b_weight) };
+ str = {str, $sformatf("\n\t") };
+
+ return str;
+ endfunction // conver2string
+
+
+ virtual function void do_copy(uvm_object rhs);
+ aes_message_item rhs_;
+
+ `downcast(rhs_,rhs)
+ super.do_copy(rhs);
+ aes_operation = rhs_.aes_operation;
+ aes_key = rhs_.aes_key;
+ aes_keylen = rhs_.aes_keylen;
+ aes_mode = rhs_.aes_mode;
+ aes_iv = rhs_.aes_iv;
+ message_length = rhs_.message_length;
+ has_config_error = rhs_.has_config_error;
+ ecb_weight = rhs_.ecb_weight;
+ cbc_weight = rhs_.cbc_weight;
+ ctr_weight = rhs_.ctr_weight;
+ key_128b_weight = rhs_.key_128b_weight;
+ key_192b_weight = rhs_.key_192b_weight;
+ key_256b_weight = rhs_.key_256b_weight;
+ input_msg = rhs_.input_msg;
+ output_msg = rhs_.output_msg;
+ predicted_msg = rhs_.predicted_msg;
+ endfunction // copy
+endclass
diff --git a/hw/ip/aes/dv/env/aes_scoreboard.sv b/hw/ip/aes/dv/env/aes_scoreboard.sv
index 6735f4e..bfae3bb 100644
--- a/hw/ip/aes/dv/env/aes_scoreboard.sv
+++ b/hw/ip/aes/dv/env/aes_scoreboard.sv
@@ -1,32 +1,47 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
+
import aes_model_dpi_pkg::*;
import aes_pkg::*;
class aes_scoreboard extends cip_base_scoreboard #(
- .CFG_T(aes_env_cfg),
- .RAL_T(aes_reg_block),
- .COV_T(aes_env_cov)
+ .CFG_T(aes_env_cfg),
+ .RAL_T(aes_reg_block),
+ .COV_T(aes_env_cov)
);
+
`uvm_component_utils(aes_scoreboard)
`uvm_component_new
// local variables
- aes_seq_item dut_item;
- // TLM agent fifos
+ aes_seq_item input_item; // item containing data and config
+ aes_seq_item output_item; // item containing resulting output
+ aes_seq_item complete_item; // merge of input and output items
- // local queues to hold incoming packets pending comparison
- mailbox #(aes_seq_item) dut_fifo; // all incoming TL transactions will be written to this one
- mailbox #(aes_seq_item) ref_fifo; // this will be a clone of the above before the result has been calculated by the dut!
+ bit aes_from_rst = 1; // 1: nothing has happened since rst was released
+ bit ok_to_fwd = 0; // 0: item is not ready to forward
+ bit finish_message = 0; // set when test is trying to end
+ // - to indicate the last message is finished
+ int message_cnt = 0; // used to check that all messages were received
+
+ // local queues to hold incoming packets pending comparison //
+
+ // Items containing both input and output data, ready to be added to a message
+ mailbox #(aes_seq_item) item_fifo;
+ // completed message item ready for scoring
+ mailbox #(aes_message_item) msg_fifo;
+ // once an operation is started the item is put here to wait for the resuting output
+ aes_seq_item rcv_item_q[$];
function void build_phase(uvm_phase phase);
super.build_phase(phase);
- dut_fifo = new();
- ref_fifo = new();
- dut_item = new("dut_item");
+ msg_fifo = new();
+ item_fifo = new();
+ input_item = new("input_item");
+ output_item = new ();
endfunction
@@ -37,15 +52,21 @@
task run_phase(uvm_phase phase);
super.run_phase(phase);
- fork
- compare();
- join_none
+ `uvm_info(`gfn, $sformatf("%s", cfg.convert2string()), UVM_HIGH)
+ if(cfg.en_scb) begin
+ fork
+ compare();
+ rebuild_message();
+ join_none
+ end
endtask
virtual task process_tl_access(tl_seq_item item, tl_channels_e channel = DataChannel);
uvm_reg csr;
- aes_seq_item ref_item;
+ string csr_name;
+ aes_seq_item input_clone;
+ aes_seq_item complete_clone;
bit do_read_check = 1'b0;
bit write = item.is_write();
uvm_reg_addr_t csr_addr = get_normalized_addr(item.a_addr);
@@ -63,87 +84,159 @@
if (write) begin
void'(csr.predict(.value(item.a_data), .kind(UVM_PREDICT_WRITE), .be(item.a_mask)));
end
- case (csr.get_name())
+ `uvm_info(`gfn, $sformatf("ITEM received reg name : %s",csr.get_name() ), UVM_HIGH)
+ csr_name = csr.get_name();
+ case (1)
// add individual case item for each csr
- "ctrl": begin
- {dut_item.allow_data_ovrwrt, dut_item.man_trigger,dut_item.key_size,dut_item.operation}
- = item.a_data[5:0];
- end
- "key0": begin
- dut_item.key[0] = item.a_data;
- end
- "key1": begin
- dut_item.key[1] = item.a_data;
- end
- "key2": begin
- dut_item.key[2] = item.a_data;
- end
- "key3": begin
- dut_item.key[3] = item.a_data;
- end
- "key4": begin
- dut_item.key[4] = item.a_data;
- end
- "key5": begin
- dut_item.key[5] = item.a_data;
- end
- "key6": begin
- dut_item.key[6] = item.a_data;
- end
- "key7": begin
- dut_item.key[7] = item.a_data;
+ (!uvm_re_match("ctrl", csr_name)): begin
+ input_item.manual_op = item.a_data[7];
+ input_item.key_len = item.a_data[6:4];
+ `downcast(input_item.operation, item.a_data[0]);
+ case (item.a_data[3:1])
+ 3'b001: input_item.mode = AES_ECB;
+ 3'b010: input_item.mode = AES_CBC;
+ 3'b100: input_item.mode = AES_CTR;
+ default: input_item.mode = AES_ECB;
+ endcase // case item.a_data[3
end
- "data_in0" :begin
- dut_item.data_in[0] = item.a_data;
- dut_item.data_in_vld[0] = 1;
- end
-
- "data_in1" :begin
- dut_item.data_in[1] = item.a_data;
- dut_item.data_in_vld[1] = 1;
- end
-
- "data_in2" :begin
- dut_item.data_in[2] = item.a_data;
- dut_item.data_in_vld[2] = 1;
- end
-
- "data_in3": begin
- dut_item.data_in[3] = item.a_data;
- dut_item.data_in_vld[3] = 1;
- end
-
- "trigger": begin
- if (item.a_data[0]) begin
- `downcast(ref_item, dut_item.clone());
- ref_fifo.put(ref_item);
+ (!uvm_re_match("key*", csr_name)): begin
+ for (int i = 0; i < 8; i++) begin
+ string keyname = $sformatf("key%0d", i);
+ if (keyname == csr_name) begin
+ input_item.key[i] = item.a_data;
+ input_item.key_vld[i] = 1'b1;
+ end
end
end
- "status": begin
- //TBD
+ (!uvm_re_match("data_in*", csr_name)): begin
+ for (int i = 0; i < 4; i++) begin
+ string keyname = $sformatf("data_in%0d", i);
+ if (keyname == csr_name) begin
+ input_item.data_in[i] = item.a_data;
+ input_item.data_in_vld[i] = 1'b1;
+ end
+ end
end
+ (!uvm_re_match("iv*", csr_name)): begin
+ for (int i = 0; i < 4; i++) begin
+ string keyname = $sformatf("iv%0d", i);
+ if (keyname == csr_name) begin
+ input_item.iv[i] = item.a_data;
+ input_item.iv_vld[i] = 1'b1;
+ end
+ end
+ end
+
+ // TODO
+ // "trigger": begin
+ // if (item.a_data[0]) begin
+ // // `downcast(ref_item, input_item.clone());
+ // // ref_fifo.put(ref_item);
+ // end
+ // end
+ //
+ // "status": begin
+ // //TBD
+ // end
+
default: begin
- // DO nothing- trying to write to a read only register
+ // DO nothing- trying to write to a read only register
end
endcase
- // forward Item and clear valid bits
- if (!dut_item.man_trigger && (& dut_item.data_in_vld)) begin
- `downcast(ref_item, dut_item.clone());
- ref_fifo.put(ref_item);
- ref_item = new();
- dut_item.data_in_vld = '0;
+
+ ///////////////////////////////////////
+ // Valid checks //
+ ///////////////////////////////////////
+
+ // check that the item is valid - all registers clean base on mode //
+ case (input_item.mode)
+ AES_ECB: begin
+ if(aes_from_rst) begin
+ // verify that all 4 data_in and all 8 key have been updated
+ if(input_item.data_in_valid() && input_item.key_clean(0)) begin
+ //clone and add to ref and rec data fifo
+ ok_to_fwd = 1;
+ aes_from_rst = 0;
+ `uvm_info(`gfn, $sformatf("\n\t ----| First ITEM created OK to clone"), UVM_HIGH)
+ end
+ end else begin
+ // verify that all 4 data_in and all 8 key are clean
+ `uvm_info(`gfn, $sformatf("\n\t ----|data_inv_vld? %b, key clean ? %b",
+ input_item.data_in_valid(), input_item.key_clean(1) ), UVM_HIGH)
+
+ if(input_item.data_in_valid() && input_item.key_clean(1)) begin
+ //clone and add to ref and rec data fifo
+ `uvm_info(`gfn, $sformatf("\n\t ----| OK to clone"), UVM_HIGH)
+ ok_to_fwd = 1;
+ end
+ end
+ end
+
+ AES_CBC: begin
+ if(aes_from_rst) begin
+ // verify that all 4 data_in and all 8 key and all 4 IV have been updated
+ if(input_item.data_in_valid() && input_item.key_clean(0) && input_item.iv_clean(0)) begin
+ //clone and add to ref and rec data fifo
+ ok_to_fwd = 1;
+ aes_from_rst = 0;
+ `uvm_info(`gfn, $sformatf("\n\t ----| First ITEM created OK to clone"), UVM_HIGH)
+ end
+ end else begin
+ // verify that all 4 data_in and all 8 key and all 4 IV are clean
+ `uvm_info(`gfn, $sformatf("\n\t ----|data_inv_vld? %b, key clean ? %b",
+ input_item.data_in_valid(), input_item.key_clean(1) ), UVM_HIGH)
+
+ if(input_item.data_in_valid() && input_item.key_clean(1) && input_item.iv_clean(1)) begin
+ //clone and add to ref and rec data fifo
+ `uvm_info(`gfn, $sformatf("\n\t ----| OK to clone"), UVM_HIGH)
+ ok_to_fwd = 1;
+ end
+ end
+ end
+
+ AES_CTR: begin
+ if(aes_from_rst) begin
+ // verify that all 4 data_in and all 8 key and all 4 IV have been updated
+ if(input_item.data_in_valid() && input_item.key_clean(0) && input_item.iv_clean(0)) begin
+ //clone and add to ref and rec data fifo
+ ok_to_fwd = 1;
+ aes_from_rst = 0;
+ `uvm_info(`gfn, $sformatf("\n\t ----| First ITEM created OK to clone"), UVM_HIGH)
+ end
+ end else begin
+ // verify that all 4 data_in and all 8 and all 4 IV key are clean
+ `uvm_info(`gfn, $sformatf("\n\t ----|data_inv_vld? %b, key clean ? %b",input_item.data_in_valid(), input_item.key_clean(1) ), UVM_HIGH)
+ if(input_item.data_in_valid() && input_item.key_clean(1) && input_item.iv_clean(1)) begin
+ //clone and add to ref and rec data fifo
+ `uvm_info(`gfn, $sformatf("\n\t ----| OK to clone"), UVM_HIGH)
+ ok_to_fwd = 1;
+ end
+ end
+ end
+ default: begin
+ `uvm_fatal(`gfn, $sformatf("\n\t ----| I AM IN DEFAULT CASE I SHOULD NOT BE HERE"))
+ end
+ endcase // case (input_item.mode)
+
+ // forward item to receive side
+ if(ok_to_fwd ) begin
+ ok_to_fwd = 0;
+ `downcast(input_clone, input_item.clone());
+ `uvm_info(`gfn, $sformatf("\n\t AES INPUT ITEM RECEIVED - \n %s", input_clone.convert2string()), UVM_HIGH)
+ rcv_item_q.push_front(input_clone);
+ input_item.clean();
end
end
- // process the csr req
- // for write, update local variable and fifo at address phase
- // for read, update predication at address phase and compare at data phase
- // On reads, if do_read_check, is set, then check mirrored_value against item.d_data
+ //////////////////////////////////////////////////////////////////////////////
+ // get an item from the rcv queue and wait for all output data to be received
+ //////////////////////////////////////////////////////////////////////////////
+
`uvm_info(`gfn, $sformatf("\n\t ---| channel %h", channel), UVM_HIGH)
if (!write && channel == DataChannel) begin
if (do_read_check) begin
@@ -151,84 +244,175 @@
$sformatf("reg name: %0s", csr.get_full_name()))
end
void'(csr.predict(.value(item.d_data), .kind(UVM_PREDICT_READ)));
- `uvm_info(`gfn, $sformatf("\n\t ----| SAW READ - %s data %02h",csr.get_name(), item.d_data)
- , UVM_HIGH)
+ `uvm_info(`gfn, $sformatf("\n\t ----| SAW READ - %s data %02h",csr.get_name(), item.d_data)
+ , UVM_HIGH)
case (csr.get_name())
"data_out0": begin
- dut_item.data_out[0] = item.d_data;
- dut_item.data_out_vld[0] = 1;
+ output_item.data_out[0] = item.d_data;
+ output_item.data_out_vld[0] = 1;
end
"data_out1": begin
- dut_item.data_out[1] = item.d_data;
- dut_item.data_out_vld[1] = 1;
+ output_item.data_out[1] = item.d_data;
+ output_item.data_out_vld[1] = 1;
end
"data_out2": begin
- dut_item.data_out[2] = item.d_data;
- dut_item.data_out_vld[2] = 1;
+ output_item.data_out[2] = item.d_data;
+ output_item.data_out_vld[2] = 1;
end
"data_out3": begin
- dut_item.data_out[3] = item.d_data;
- dut_item.data_out_vld[3] = 1;
+ output_item.data_out[3] = item.d_data;
+ output_item.data_out_vld[3] = 1;
end
- endcase
- if (&dut_item.data_out_vld) begin
- dut_fifo.put(dut_item);
- dut_item = new();
+ endcase // case (csr.get_name())
+
+ if (output_item.data_out_valid()) begin
+ if( rcv_item_q.size() == 0) begin
+ `uvm_fatal(`gfn, $sformatf("\n\t ----| TRIED TO READ EMPTY RECEIVE QUEUE |----"))
+ end
+
+ complete_item = rcv_item_q.pop_back();
+ complete_item.data_out = output_item.data_out;
+
+ `downcast(complete_clone, complete_item.clone());
+ item_fifo.put(complete_clone);
+
+ output_item = new();
+ complete_item = new();
+ `uvm_info(`gfn,
+ $sformatf("\n\t ----|added data to item_fifo (output received) fifo entries %d",
+ item_fifo.num()), UVM_HIGH)
end
end
- endtask
+ endtask // process_tl_access
+
+
+ // takes items from the item queue and builds full aes_messages with both input data and output data.
+ task rebuild_message();
+ typedef enum { MSG_START,MSG_RUN } aes_message_stat_t;
+
+ aes_message_item message, msg_clone;
+ aes_seq_item full_item;
+ aes_message_stat_t msg_state;
+
+ message = new();
+
+ fork
+ begin
+ forever begin
+ case(msg_state)
+ MSG_START: begin
+ full_item = new();
+ item_fifo.get(full_item);
+ `uvm_info(`gfn, $sformatf("\n\t ----| got item from item fifo"), UVM_FULL)
+ if(!full_item.message_start()) begin
+ `uvm_fatal(`gfn,
+ $sformatf("\n\t ----| FIRST ITEM DID NOT HAVE MESSAGE START/CONFIG SETTINGS"))
+ end
+ message.add_start_msg_item(full_item);
+ msg_state = MSG_RUN;
+ end
+
+ MSG_RUN: begin
+ full_item = new();
+ item_fifo.get(full_item);
+ `uvm_info(`gfn, $sformatf("\n\t ----| got item from item fifo"), UVM_FULL)
+ if(full_item.message_start() ) begin
+ `uvm_info(`gfn, $sformatf("\n\t ----| adding message item to mg_fifo"), UVM_FULL)
+ `downcast(msg_clone, message.clone());
+ msg_fifo.put(msg_clone);
+ message = new();
+ message.add_start_msg_item(full_item);
+ end else begin
+ message.add_data_item(full_item);
+ end
+ end
+ endcase // case (msg_state)
+ end
+ end
+
+ begin
+ wait( finish_message )
+ `uvm_info(`gfn, $sformatf("\n\t ----|Finish test received adding message item to mg_fifo")
+ , UVM_HIGH)
+
+ `downcast(msg_clone, message.clone());
+ msg_fifo.put(msg_clone);
+ end
+ join_any
+ endtask // rebuild_message
virtual task compare();
string txt="";
+ bit [3:0][31:0] tmp_input;
+ bit [3:0][31:0] tmp_output;
+
forever begin
- aes_seq_item rtl_item;
- aes_seq_item c_item;
- bit [127:0] calc_data;
+ aes_message_item msg;
`uvm_info(`gfn, $sformatf("\n\t ----| TRYING to get item "), UVM_HIGH)
- dut_fifo.get(rtl_item);
- ref_fifo.get(c_item );
+ msg_fifo.get(msg);
+
`uvm_info(`gfn, $sformatf("\n\t ----| GOT item "), UVM_HIGH)
+ `uvm_info(`gfn, $sformatf("model %b, operation: %b, mode %03b, IV %h, key_len %03b, key %h ",
+ cfg.ref_model, msg.aes_operation, msg.aes_mode, msg.aes_iv, msg.aes_keylen, msg.aes_key)
+ , UVM_HIGH)
- sv_dpi_aes_crypt_block(1'b0, c_item.operation, 3'b001, 128'b0, c_item.key_size, c_item.key,
- c_item.data_in, c_item.data_out);
- `uvm_info(`gfn, $sformatf("\n\t ----| printing C MODEL %s", c_item.convert2string() )
- , UVM_HIGH)
+ msg.alloc_predicted_msg();
+ //ref-model / opration / chipher mode / IV / key_len / key /data i /data o //
+ c_dpi_aes_crypt_message(cfg.ref_model, msg.aes_operation, msg.aes_mode, msg.aes_iv,
+ msg.aes_keylen, msg.aes_key, msg.input_msg, msg.predicted_msg);
- if (!rtl_item.compare(c_item)) begin
- txt = {txt, $sformatf("\n\t ----| RTL_ITEM %s \n\t ", rtl_item.convert2string())};
- txt = {txt, $sformatf("\n\t ----| printing C MODEL %s", c_item.convert2string() )};
- txt = {txt, $sformatf("\n\t ----| \t\t\t DATA OUTPUT \t\t |---- ")};
- txt = {txt, $sformatf("\n\t ----| \t\t\t RTL \t\t REF \t |---- ")};
- foreach (rtl_item.data_out[i]) begin
- txt = {txt, $sformatf("\n\t ----| [%d] \t %02h \t %02h |----", i, rtl_item.data_out[i],
- c_item.data_out[i])};
- end
- `uvm_fatal(`gfn, $sformatf("\t TEST FAILED ITEMS DOES NOT MATCH \n\t %s \n",txt))
- end else begin
- `uvm_info(`gfn, $sformatf("\n\t ----| ITEMS MATCHED |-----"), UVM_LOW)
+ `uvm_info(`gfn, $sformatf("\n\t ----| printing MESSAGE %s", msg.convert2string() )
+ , UVM_HIGH)
+ txt = "";
+ foreach(msg.input_msg[i]) begin
+ txt = { txt, $sformatf("\n\t %h \t %h \t %h",
+ msg.input_msg[i],msg.output_msg[i], msg.predicted_msg[i])};
end
+
+ `uvm_info(`gfn, $sformatf("\n\t input \t output \t predicted %s",txt), UVM_HIGH)
+
+ for( int n =0 ; n < msg.input_msg.size(); n++) begin
+ if( msg.output_msg[n] != msg.predicted_msg[n]) begin
+ txt = "\t TEST FAILED MESSAGES DID NOT MATCH";
+
+ txt = {txt, $sformatf("\n\t ----| ACTUAL OUTPUT DID NOT MATCH PREDICTED OUTPUT |----")};
+ txt = {txt, $sformatf("\n\t ----| FAILED AT BLOCK #%d \t ACTUAL: %h \t PREDICTED: %h, ",
+ n, msg.output_msg[n], msg.predicted_msg[n] )};
+ `uvm_fatal(`gfn, $sformatf(" # %d \n\t %s \n",message_cnt, txt))
+ end
+ end
+ `uvm_info(`gfn, $sformatf("\n\t ----| MESSAGE #%d MATCHED |-----",message_cnt), UVM_HIGH)
+ message_cnt++;
end
endtask
-
+ // TODO get rid of this and do EOP checks in monitor
virtual function void phase_ready_to_end(uvm_phase phase);
if (phase.get_name() != "run") return;
- if ( (dut_fifo.num() != 0 ) || (ref_fifo.num() != 0) ) begin
- phase.raise_objection(this, "fifos still has data");
- fork begin
- wait_fifo_empty();
- phase.drop_objection(this);
- end
- join_none
+
+ // the message currently being reassembled is should be sent for scoring
+ finish_message = 1;
+ `uvm_info(`gfn, $sformatf("Finish message: %b", finish_message), UVM_HIGH)
+
+ // AEs needs this objection - because PHASE READY TO END
+ // is the only way to know that the very last message is now complete
+ phase.raise_objection(this, "need time to finish last item");
+ fork begin
+ wait_fifo_empty();
+ phase.drop_objection(this);
end
+ join_none
endfunction
virtual task wait_fifo_empty();
- wait ((dut_fifo.num() == 0 ) && (ref_fifo.num() == 0));
+ `uvm_info(`gfn, $sformatf("item fifo entries %d", item_fifo.num()), UVM_HIGH)
+ wait (rcv_item_q.size() == 0 );
+ wait (item_fifo.num() == 0 );
+ wait (msg_fifo.num() == 0 );
endtask
@@ -239,15 +423,43 @@
function void check_phase(uvm_phase phase);
- super.check_phase(phase);
- `DV_EOT_PRINT_MAILBOX_CONTENTS(aes_seq_item, dut_fifo)
- `DV_EOT_PRINT_MAILBOX_CONTENTS(aes_seq_item, ref_fifo)
+ string txt = "";
+ if (cfg.en_scb) begin
+ `uvm_info(`gfn, $sformatf(" RASMUS JUST CHECKING"), UVM_LOW)
+ super.check_phase(phase);
+ `DV_EOT_PRINT_MAILBOX_CONTENTS(aes_message_item, msg_fifo)
+ `DV_EOT_PRINT_MAILBOX_CONTENTS(aes_seq_item, item_fifo)
+ `DV_EOT_PRINT_Q_CONTENTS(aes_seq_item, rcv_item_q)
+ if(message_cnt != cfg.num_messages) begin
+ txt = "\n\t ----| NO FAILURES BUT DIDN*T SEE ALL EXPECTED MESSAGES";
+ txt = { txt, $sformatf(" \n\t ----| expected %d, seen: %d", cfg.num_messages, message_cnt ) };
+ `uvm_fatal(`gfn, $sformatf("%s", txt) )
+ end
+ end
+
endfunction
function void report_phase(uvm_phase phase);
- super.report_phase(phase);
- `uvm_info(`gfn, $sformatf("%s", cfg.convert2string()), UVM_LOW)
- endfunction
+ uvm_report_server rpt_srvr;
+ string txt="";
+ super.report_phase(phase);
+ txt = $sformatf("\n\t ----| TEST FINISHED |----");
+ txt = { txt, $sformatf("\n\t SAW %d Good messages ", message_cnt)};
+ txt = { txt, $sformatf("\n\t Expected %d messages ", cfg.num_messages)};
+ rpt_srvr = uvm_report_server::get_server();
+ if(rpt_srvr.get_severity_count(UVM_FATAL)+rpt_srvr.get_severity_count(UVM_ERROR)>0) begin
+ `uvm_info(`gfn, $sformatf("%s", cfg.convert2string()), UVM_LOW)
+ txt = { txt,"\n\t---------------------------------------"};
+ txt = { txt,"\n\t---- TEST FAILED ----"};
+ txt = { txt,"\n\t---------------------------------------"};
+ end else begin
+ txt = {txt, "\n\t---------------------------------------"};
+ txt = { txt,"\n\t---- TEST PASSED ----"};
+ txt = { txt,"\n\t---------------------------------------"};
+ end
+ `uvm_info(`gfn, $sformatf("%s", txt), UVM_HIGH)
+
+ endfunction // report_phase
endclass
diff --git a/hw/ip/aes/dv/env/aes_seq_item.sv b/hw/ip/aes/dv/env/aes_seq_item.sv
index 12b2479..bf73731 100644
--- a/hw/ip/aes/dv/env/aes_seq_item.sv
+++ b/hw/ip/aes/dv/env/aes_seq_item.sv
@@ -2,86 +2,79 @@
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
+
class aes_seq_item extends uvm_sequence_item;
- // Knobs //
- // min number of data bytes
- int data_len_max;
- // Max number of data bytes
- int data_len_min;
+ `uvm_object_utils(aes_seq_item)
+ aes_item_type_e item_type;
- // randomized values //
- rand bit operation; // TODO implement this as enum
- // 0: auto start, 1: wait for start
- rand bit man_trigger;
+ aes_op_e operation;
+
+ ///////////////////////////////////////
+ // control Knobs //
+ ///////////////////////////////////////
+
+ // 0: auto mode 1: manual start
+ bit manual_op;
// 0: output data cannot be overwritten
// 1: new output will overwrite old output even if not read.
- rand bit allow_data_ovrwrt;
- // lenth of plaintext / cypher
- rand bit [31:0] data_len;
+ bit allow_data_ovrwrt;
+ // lenth of plaintext / cypher (max is 128b/16b per block)
+ // used to mask bits that are not part of the data vector
+ bit [3:0] data_len = 0;
// key len 0: 128, 1: 192, 2: 256 3: NOT VALID
- rand bit [2:0] key_size;
+ bit [2:0] key_len;
// 256 bit key (8x32 bit)
- rand bit [7:0][31:0] key;
- // data queue to hold the randomized data
- rand bit [31:0] data_in_queue[$];
+ bit [7:0][31:0] key;
+ // which fields of the key is valid
+ bit [7:0] key_vld = 8'b0;
// randomized data to add to queue
+ bit [3:0][31:0] iv;
+ // indicate if the initialization vector is valid
+ bit [3:0] iv_vld;
+ aes_mode_e mode;
+ ///////////////////////////////////////
+ // FIXED variables //
+ ///////////////////////////////////////
+
+ // indicate which words has data
+ bit [3:0] data_in_vld = 4'b0;
+ // indicate which words has data
+ bit [3:0] data_out_vld = 4'b0;
- // fixed variables //
- // indicated which words has data
- bit [3:0] data_in_vld = 4'b0;
- // indicated which words has data
- bit [3:0] data_out_vld = 4'b0;
// used by the checker
- bit [3:0][31:0] data_in;
- // used by the checker
- bit [3:0][31:0] data_out;
- // used to store output data
- bit [31:0] data_out_queue[$];
+ bit [3:0][31:0] data_out;
+ // used byt the scoreboard to rebuild plaintext messages
+ // bit [31:0] data_in_queue[$];
+ //used by the scoreboard to build the processed message
+ // bit [31:0] data_out_queue[$];
// set if data should be fixed and not randomized
- bit fixed_data = 0;
+ bit fixed_data = 0;
// if set unused key bytes will be forced to 0 - controlled from test
- bit key_mask=0;
+ bit key_mask = 0;
+ ///////////////////////////////////////
+ // Randomizable variables //
+ ///////////////////////////////////////
+
+ // used by the checker
+ rand bit [3:0][31:0] data_in;
+
function new( string name="aes_sequence_item");
super.new(name);
endfunction
- // contraints //
- constraint c_data {
- solve data_len before data_in_queue;
- data_len inside { [data_len_min: data_len_max] };
-
- if(data_len[1:0] == 2'b00) {
- data_in_queue.size() == data_len >> 2;
- } else {
- data_in_queue.size() == data_len >> 2 + 1;
- }
- if(data_len[1:0] == 2'b01) {
- data_in_queue[data_in_queue.size()-1][31:8] == 0;
- } else if (data_len[1:0] == 2'b10) {
- data_in_queue[data_in_queue.size()-1][31:16] == 0;
- } else {
- data_in_queue[data_in_queue.size()-1][31:24] == 0;
- }
- }
-
- constraint c_key_size {key_size inside {3'b001, 3'b010, 3'b100 };
- // key len 0: 128, 1: 192, 2: 256 3: NOT VALID
- }
-
- constraint c_operation_reg {operation == 0; man_trigger == 0; allow_data_ovrwrt == 0; }
-
function void post_randomize();
+ bit [3:0] index;
if(key_mask) begin
- case (key_size)
+ case (key_len)
3'b001: begin
key[7:4] = 32'h00000000;
end
@@ -92,77 +85,153 @@
end
endcase
end
+
+ // mask unused data bits
+ if(data_len != 0) begin
+ for(int i=data_len; i<16; i++) begin
+ data_in[i[3:2]][i[1:0]*8+7 -:8] = 8'd0;
+ end
+ end
+ endfunction // post_randomize
+
+ // function to detect if all datafields
+ // have been updated.
+ function bit data_in_valid();
+ `uvm_info(`gfn, $sformatf("\n\t ----| Checking if ALL data is updated %4b", data_in_vld)
+ , UVM_FULL)
+
+ return &data_in_vld;
+ endfunction // data_in_valid
+
+ // function to detect if all datafields
+ // have been updated.
+ function bit data_out_valid();
+ `uvm_info(`gfn, $sformatf("\n\t ----| Checking if ALL data is valid %4b", data_out_vld)
+ , UVM_FULL)
+
+ return &data_out_vld;
+ endfunction // data_in_valid
+
+ // if ret_clean = 0
+ // return 1 only of all registers have been written
+ // if ret_celan = 1
+ // return 1 if all or none of the registers have been written
+ function bit key_clean(bit ret_clean);
+ `uvm_info(`gfn, $sformatf("\n\t ----| Key status %b", key_vld), UVM_LOW)
+ if(ret_clean) begin
+ return ( (&key_vld) || ~(|key_vld));
+ end else begin
+ return &key_vld;
+ end
+ endfunction // key_clean
+
+ // if ret_clean = 0
+ // return 1 only of all registers have been written
+ // if ret_celan = 1
+ // return 1 if all or none of the registers have been written
+ function bit iv_clean(bit ret_clean);
+ if(ret_clean) begin
+ return ( (&iv_vld) || ~(|iv_vld));
+ end else begin
+ return &iv_vld;
+ end
endfunction
+ // bases on the AES mode
+ // function will return 1 if this is the start of a new message
+ function bit message_start();
+ case(mode)
+ AES_ECB: begin
+ `uvm_info(`gfn, $sformatf("return key vld(%b) %b",key_vld, &key_vld), UVM_LOW)
+ return (&key_vld);
+ end
+ AES_CBC: begin
+ `uvm_info(`gfn, $sformatf("return key vld(%b) %b AND iv (%b) &b",
+ key_vld, &key_vld, iv_vld, &iv_vld), UVM_LOW)
+ return (&key_vld && &iv_vld);
+ end
+ AES_CTR: begin
+ `uvm_info(`gfn, $sformatf("return key vld(%b) %b AND iv (%b) &b",
+ key_vld, &key_vld, iv_vld, &iv_vld), UVM_LOW)
+ return (&key_vld && &iv_vld);
+ end
+ default: begin
+ `uvm_fatal(`gfn, $sformatf("\n\t ----| I AM IN DEFAULT CASE I SHOULD NOT BE HERE"))
+ end
+ endcase // case (mode)
+ endfunction // message_start
- function bit add2output( logic [31:0] data );
- data_out_queue.push_back(data);
- return 1;
- endfunction
+
+ function void clean();
+ data_in_vld = '0;
+ iv_vld = '0;
+ key_vld = '0;
+ data_out_vld= '0;
+ endfunction // clean
virtual function void do_copy(uvm_object rhs);
aes_seq_item rhs_;
- if(!$cast(rhs_,rhs) ) begin
- uvm_report_error("do_copy:", "acst failed");
- return;
- end
+ `downcast(rhs_,rhs)
super.do_copy(rhs);
- operation = rhs_.operation;
- data_in = rhs_.data_in;
- key = rhs_.key;
- key_size = rhs_.key_size;
- data_out = rhs_.data_out;
+ item_type = rhs_.item_type;
+ operation = rhs_.operation;
+ mode = rhs_.mode;
+ data_in = rhs_.data_in;
+ key = rhs_.key;
+ key_len = rhs_.key_len;
+ key_vld = rhs_.key_vld;
+ iv = rhs_.iv;
+ iv_vld = rhs_.iv_vld;
+ data_out = rhs_.data_out;
+ data_len = rhs_.data_len;
endfunction // copy
-// do compare //
-virtual function bit do_compare(uvm_object rhs, uvm_comparer comparer);
+ // do compare //
+ virtual function bit do_compare(uvm_object rhs, uvm_comparer comparer);
- aes_seq_item rhs_;
+ aes_seq_item rhs_;
- if(!$cast(rhs_,rhs))begin
- return 0; // compare failed because object is not of sequence item type
- end
-
-return(super.do_compare(rhs,comparer) &&
- (operation == rhs_.operation) &&
- (data_in == rhs_.data_in) &&
- (key == rhs_.key) &&
- (data_out == rhs_.data_out) );
-endfunction // compare
+ `downcast(rhs_,rhs)
+ return(super.do_compare(rhs,comparer) &&
+ (operation == rhs_.operation) &&
+ (mode == rhs_.mode) &&
+ (data_in == rhs_.data_in) &&
+ (key == rhs_.key) &&
+ (data_out == rhs_.data_out) );
+ endfunction // compare
-// convert to string //
-virtual function string convert2string();
- string str;
- str = super.convert2string();
- str = {str, $psprintf("\n\t ----| AES SEQUENCE ITEM |----\t ")
- };
- str = {str, $psprintf("\n\t ----| Mode: \t %s |----\t ",
- (operation==1'b0) ? "ENCRYPT" : "DECRYPT" ) };
- str = {str, $psprintf("\n\t ----| Key size: \t %s |----\t ",
- (key_size==3'b001) ? "128b" : (key_size == 3'b010) ? "192b" : "256b") };
- str = {str, $psprintf("\n\t ----| Key: \t ") };
- for(int i=0; i <8; i++) begin
- str = {str, $psprintf("%h ",key[i])};
- end
- str = {str, $psprintf("\n\t ----| Input data: \t %h |----\t ", data_in) };
- str = {str, $psprintf("\n\t ----| Output data: \t %h |----\t ", data_out) };
- str = {str, $psprintf("\n\t") };
+ // convert to string //
+ virtual function string convert2string();
+ string str;
+ str = super.convert2string();
+ str = {str, $psprintf("\n\t ----| AES SEQUENCE ITEM |----\t ")
+ };
+ str = {str, $psprintf("\n\t ----| Item Type: \t %s |----\t ",item_type.name()) };
+ str = {str, $psprintf("\n\t ----| AES Mode: \t %s |----\t ",mode.name()) };
+ str = {str, $psprintf("\n\t ----| Operation: \t %s |----\t ", operation.name() ) };
+ str = {str, $psprintf("\n\t ----| Key len: \t %s |----\t ",
+ (key_len==3'b001) ? "128b" : (key_len == 3'b010) ? "192b" : "256b") };
+ str = {str, $psprintf("\n\t ----| Key: \t ") };
+ for(int i=0; i <8; i++) begin
+ str = {str, $psprintf("%h ",key[i])};
+ end
+ str = {str, $psprintf("\n\t ----| Data Length: \t %d |----\t \t", data_len) };
+ str = {str, $psprintf("\n\t ----| Input data: \t %h |----\t ", data_in) };
+ str = {str, $psprintf("\n\t ----| Output data: \t %h |----\t ", data_out) };
+ str = {str, $psprintf("\n\t") };
- return str;
+ return str;
endfunction // conver2string
virtual function string bytes2string();
string str="\n\t ----| data_out: ";
for(int i=0; i<4; i++) begin
- str = {str, $psprintf("%h", data_out[i][31:0])};
+ str = {str, $psprintf("%h", data_out[i][31:0])};
end
return str;
endfunction
-
-`uvm_object_utils(aes_seq_item)
-
endclass
diff --git a/hw/ip/aes/dv/env/seq_lib/aes_base_vseq.sv b/hw/ip/aes/dv/env/seq_lib/aes_base_vseq.sv
index 04a74ce..a96c080 100644
--- a/hw/ip/aes/dv/env/seq_lib/aes_base_vseq.sv
+++ b/hw/ip/aes/dv/env/seq_lib/aes_base_vseq.sv
@@ -2,48 +2,47 @@
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
-
class aes_base_vseq extends cip_base_vseq #(
.CFG_T (aes_env_cfg),
.RAL_T (aes_reg_block),
.COV_T (aes_env_cov),
.VIRTUAL_SEQUENCER_T (aes_virtual_sequencer)
-);
+ );
`uvm_object_utils(aes_base_vseq)
`uvm_object_new
- parameter bit ENCRYPT = 1'b0;
- parameter bit DECRYPT = 1'b1;
-
- aes_reg2hw_t aes_reg;
- aes_seq_item aes_item;
+ aes_reg2hw_t aes_reg;
+ aes_seq_item aes_item;
+ aes_seq_item aes_item_queue[$];
+ aes_message_item aes_message;
+ aes_message_item message_queue[$];
// various knobs to enable certain routines
- bit do_aes_init = 1'b1;
+ bit do_aes_init = 1'b1;
virtual task dut_init(string reset_kind = "HARD");
super.dut_init();
if (do_aes_init) aes_init();
- aes_item_init();
+ aes_item = new();
+ aes_message_init();
endtask
virtual task dut_shutdown();
// check for pending aes operations and wait for them to complete
// TODO
-
endtask
// setup basic aes features
virtual task aes_init();
+
bit [31:0] aes_ctrl = '0;
bit [31:0] aes_trigger = '0;
-
// initialize control register
- aes_ctrl[0] = 0; // set to encryption
- aes_ctrl[3:1] = 3'b001; // set to 128b key
- aes_ctrl[4] = 0; // start encryption automatically, don't overwrite output reg
+ aes_ctrl[0] = 0; // set to encryption
+ aes_ctrl[3:1] = aes_pkg::AES_ECB; //3'b001; // set to ECB MODE
+ aes_ctrl[6:4] = aes_pkg::AES_128; // set to 128b key
csr_wr(.csr(ral.ctrl), .value(aes_ctrl));
csr_wr(.csr(ral.trigger), .value(aes_trigger));
endtask
@@ -52,6 +51,12 @@
virtual task set_operation(bit operation);
ral.ctrl.operation.set(operation);
csr_update(.csr(ral.ctrl));
+ endtask // set_operation
+
+
+ virtual task set_mode(bit [2:0] mode);
+ ral.ctrl.mode.set(mode);
+ csr_update(.csr(ral.ctrl));
endtask
@@ -76,43 +81,185 @@
csr_wr(.csr(ral.key5), .value(key[5]));
csr_wr(.csr(ral.key6), .value(key[6]));
csr_wr(.csr(ral.key7), .value(key[7]));
+ endtask // write_key
+
+
+ virtual task write_iv(bit [3:0][31:0] iv);
+ csr_wr(.csr(ral.iv0), .value(iv[0]));
+ csr_wr(.csr(ral.iv1), .value(iv[1]));
+ csr_wr(.csr(ral.iv2), .value(iv[2]));
+ csr_wr(.csr(ral.iv3), .value(iv[3]));
endtask
- virtual task add_data(ref bit [31:0] data[$]);
- csr_wr(.csr(ral.data_in0), .value(data.pop_back()) );
- csr_wr(.csr(ral.data_in1), .value(data.pop_back()) );
- csr_wr(.csr(ral.data_in2), .value(data.pop_back()) );
- csr_wr(.csr(ral.data_in3), .value(data.pop_back()) );
+ virtual task add_data(ref bit [3:0] [31:0] data);
+ `uvm_info(`gfn, $sformatf("\n\t ----| ADDING DATA TO DUT %h ", data), UVM_HIGH)
+ `uvm_info(`gfn, $sformatf("\n\t ----| DATA_in0: %h ", data[0][31:0]), UVM_HIGH)
+ `uvm_info(`gfn, $sformatf("\n\t ----| DATA_in1: %h ", data[1][31:0]), UVM_HIGH)
+ `uvm_info(`gfn, $sformatf("\n\t ----| DATA_in2: %h ", data[2][31:0]), UVM_HIGH)
+ `uvm_info(`gfn, $sformatf("\n\t ----| DATA_in3: %h ", data[3][31:0]), UVM_HIGH)
+ csr_wr(.csr(ral.data_in0), .value(data[0][31:0]) );
+ csr_wr(.csr(ral.data_in1), .value(data[1][31:0]) );
+ csr_wr(.csr(ral.data_in2), .value(data[2][31:0]) );
+ csr_wr(.csr(ral.data_in3), .value(data[3][31:0]) );
endtask
- virtual task read_data(ref bit [31:0] cypher_txt[$]);
- bit data_rdy = 0;
- bit [31:0] rd_data;
+ ///////////////////////////////////////
+ // ADVANCED TASKS //
+ ///////////////////////////////////////
+
+ virtual task read_data(ref bit [3:0] [31:0] cypher_txt);
+ bit [3:0] [31:0] rd_txt;
+
`uvm_info(`gfn, $sformatf("\n\t ----| POLLING FOR DATA"), UVM_DEBUG)
csr_spinwait(.ptr(ral.status.output_valid) , .exp_data(1'b1)); // poll for data valid
- csr_rd(.ptr(ral.data_out0), .value(rd_data));
- cypher_txt.push_front(rd_data);
+ csr_rd(.ptr(ral.data_out0), .value(cypher_txt[0][31:0]));
+ csr_rd(.ptr(ral.data_out1), .value(cypher_txt[1][31:0]));
+ csr_rd(.ptr(ral.data_out2), .value(cypher_txt[2][31:0]));
+ csr_rd(.ptr(ral.data_out3), .value(cypher_txt[3][31:0]));
- csr_rd(.ptr(ral.data_out1), .value(rd_data));
- cypher_txt.push_front(rd_data);
-
- csr_rd(.ptr(ral.data_out2), .value(rd_data));
- cypher_txt.push_front(rd_data);
-
- csr_rd(.ptr(ral.data_out3), .value(rd_data));
- cypher_txt.push_front(rd_data);
-
- `uvm_info(`gfn, $sformatf("\n\t ----| READ DATA"), UVM_DEBUG)
+ `uvm_info(`gfn, $sformatf("\n\t ----| READ OUPUT DATA"), UVM_MEDIUM)
+ `uvm_info(`gfn, $sformatf("\n\t ----| ADDING DATA TO DUT %h ", cypher_txt), UVM_HIGH)
+ `uvm_info(`gfn, $sformatf("\n\t ----| DATA_out0: %h ", cypher_txt[0][31:0]), UVM_HIGH)
+ `uvm_info(`gfn, $sformatf("\n\t ----| DATA_out1: %h ", cypher_txt[1][31:0]), UVM_HIGH)
+ `uvm_info(`gfn, $sformatf("\n\t ----| DATA_out2: %h ", cypher_txt[2][31:0]), UVM_HIGH)
+ `uvm_info(`gfn, $sformatf("\n\t ----| DATA_out3: %h ", cypher_txt[3][31:0]), UVM_HIGH)
endtask
- function void aes_item_init();
+
+ virtual task setup_dut(aes_seq_item item);
+ set_operation(item.operation);
+ set_mode(item.mode);
+ set_key_len(item.key_len);
+ write_key(item.key);
+ write_iv(item.iv);
+ endtask
+
+
+ // TODO add missing functions
+ virtual task generate_aes_item_queue(ref aes_message_item msg_item);
+ aes_seq_item item_clone;
+
+ // generate DUT cfg
+ aes_ctrl_item_init(msg_item);
+ generate_data_stream(msg_item);
+
+ // aes_generate_err_inj();
+
+ // aes_generate_rnd_rst();
+
+ aes_print_item_queue(aes_item_queue);
+ endtask
+
+
+ virtual task generate_data_stream(ref aes_message_item msg_item);
+ aes_seq_item item_clone;
+
+ // generate an item for each 128b message block
+ for (int n=0; n<msg_item.message_length - 15; n += 16 ) begin
+ `DV_CHECK_RANDOMIZE_FATAL(aes_item)
+ aes_item.item_type = AES_DATA;
+ `uvm_info(`gfn, $sformatf("\n ----| DATA AES ITEM %s", aes_item.convert2string()), UVM_FULL)
+ `downcast(item_clone, aes_item.clone());
+ aes_item_queue.push_front(item_clone);
+ `uvm_info(`gfn, $sformatf("\n ----| generating data item %d", n), UVM_MEDIUM)
+ end
+
+ // check if message length is not divisible by 16bytes
+ if( msg_item.message_length[3:0] != 4'd0) begin
+ `uvm_info(`gfn, $sformatf("\n ----| generating runt "), UVM_MEDIUM)
+ aes_item.data_len = msg_item.message_length[3:0];
+ `DV_CHECK_RANDOMIZE_FATAL(aes_item)
+ aes_item.item_type = AES_DATA;
+ `downcast(item_clone, aes_item.clone());
+ aes_item_queue.push_front(item_clone);
+ end
+ endtask
+
+
+ // TODO
+ // virtual task generate_err_inj(ref aes_message_item msg_item);
+ // endtask
+
+ // TODO
+ // virtual task generate_rnd_rst();
+ // endtask
+
+
+ // this function starst the transmission of items to the dut,
+ // while at the same time offloads the output when ready
+ virtual task transmit_message_with_rd_back();
+ aes_seq_item nxt_item = new();
+ nxt_item = aes_item_queue.pop_back();
+ setup_dut(aes_item);
+
+ while(aes_item_queue.size() > 0) begin
+ nxt_item = aes_item_queue.pop_back();
+ add_data(nxt_item.data_in);
+ read_data(nxt_item.data_out);
+ end
+
+ endtask // transmit_message_with_rd_back
+
+
+ // TODO think about how to randomize error objects vs normal that
+ // are not randomized at this level!
+ function void aes_ctrl_item_init(ref aes_message_item message_item);
+ aes_seq_item item_clone;
aes_item = new();
- aes_item.data_len_max = cfg.data_len_max;
- aes_item.data_len_min = cfg.data_len_min;
- aes_item.key_mask = cfg.key_mask;
+
+ `uvm_info(`gfn, $sformatf("\n Generating configuration item for message of size %d", message_item.message_length), UVM_MEDIUM)
+ `uvm_info(`gfn, $sformatf("\n Message \n %s", message_item.convert2string()), UVM_MEDIUM)
+
+ aes_item.item_type = AES_CFG;
+ aes_item.operation = message_item.aes_operation;
+ aes_item.mode = message_item.aes_mode;
+ aes_item.key_len = message_item.aes_keylen;
+ aes_item.key = message_item.aes_key;
+ `uvm_info(`gfn, $sformatf("----| CONFIG AES ITEM %s", aes_item.convert2string()), UVM_MEDIUM)
+
+ `downcast(item_clone, aes_item.clone());
+ aes_item_queue.push_front(item_clone);
endfunction
+
+ // init the first message - following will rerandomize with the same constraints
+ function void aes_message_init();
+ aes_message = new();
+ aes_message.ecb_weight = cfg.ecb_weight;
+ aes_message.cbc_weight = cfg.cbc_weight;
+ aes_message.ctr_weight = cfg.ctr_weight;
+ aes_message.key_128b_weight = cfg.key_128b_weight;
+ aes_message.key_192b_weight = cfg.key_192b_weight;
+ aes_message.key_256b_weight = cfg.key_256b_weight;
+ aes_message.message_len_max = cfg.message_len_max;
+ aes_message.message_len_min = cfg.message_len_min;
+ aes_message.config_error_pct = cfg.config_error_pct;
+ aes_message.errors_en = cfg.errors_en;
+ endfunction
+
+
+ function void generate_message_queue();
+ aes_message_item cloned_message;
+ for(int i=0; i < cfg.num_messages; i++) begin
+ `DV_CHECK_RANDOMIZE_FATAL(aes_message)
+ `downcast(cloned_message, aes_message.clone());
+ //`assert($cast(cloned_message, aes_message.clone());
+ message_queue.push_front(cloned_message);
+ `uvm_info(`gfn, $sformatf("\n message # %d \n %s",i, cloned_message.convert2string()), UVM_MEDIUM)
+ end
+ endfunction
+
+
+ function void aes_print_item_queue(ref aes_seq_item item_queue[$]);
+ aes_seq_item print_item;
+ `uvm_info(`gfn, $sformatf("----| Item queue size: %d", item_queue.size()), UVM_MEDIUM)
+ for(int n = 0; n<item_queue.size(); n++) begin
+ print_item = item_queue[n];
+ `uvm_info(`gfn, $sformatf("----| ITEM #%d", n ), UVM_MEDIUM)
+ `uvm_info(`gfn, $sformatf("%s", print_item.convert2string()), UVM_MEDIUM)
+ end
+ endfunction
endclass : aes_base_vseq
diff --git a/hw/ip/aes/dv/env/seq_lib/aes_common_vseq.sv b/hw/ip/aes/dv/env/seq_lib/aes_common_vseq.sv
index df33b6e..3e9e1e3 100644
--- a/hw/ip/aes/dv/env/seq_lib/aes_common_vseq.sv
+++ b/hw/ip/aes/dv/env/seq_lib/aes_common_vseq.sv
@@ -10,9 +10,11 @@
}
`uvm_object_new
+
virtual task pre_start();
do_aes_init = 1'b0;
super.pre_start();
+ cfg.en_scb = 0;
endtask
virtual task body();
diff --git a/hw/ip/aes/dv/env/seq_lib/aes_sanity_vseq.sv b/hw/ip/aes/dv/env/seq_lib/aes_sanity_vseq.sv
deleted file mode 100644
index 8664f20..0000000
--- a/hw/ip/aes/dv/env/seq_lib/aes_sanity_vseq.sv
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright lowRISC contributors.
-// Licensed under the Apache License, Version 2.0, see LICENSE for details.
-// SPDX-License-Identifier: Apache-2.0
-
-// basic sanity test vseq
- class aes_sanity_vseq extends aes_base_vseq;
- `uvm_object_utils(aes_sanity_vseq)
-
- `uvm_object_new
-
- task body();
-
- `uvm_info(`gfn, $sformatf("STARTING AES SEQUENCE"), UVM_LOW);
-
- `DV_CHECK_RANDOMIZE_WITH_FATAL(aes_item, key_size == 3'b001;)
- set_operation(aes_item.operation);
- set_key_len(aes_item.key_size);
- // add key
- write_key(aes_item.key);
-
- // add data
- add_data(aes_item.data_in_queue);
-
- // get cypher
- read_data(aes_item.data_out_queue);
-
- endtask : body
-
-endclass : aes_sanity_vseq
diff --git a/hw/ip/aes/dv/env/seq_lib/aes_stress_vseq.sv b/hw/ip/aes/dv/env/seq_lib/aes_stress_vseq.sv
new file mode 100644
index 0000000..c0eea2c
--- /dev/null
+++ b/hw/ip/aes/dv/env/seq_lib/aes_stress_vseq.sv
@@ -0,0 +1,31 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+// basic main test vseq
+class aes_stress_vseq extends aes_base_vseq;
+ `uvm_object_utils(aes_stress_vseq)
+
+ `uvm_object_new
+ aes_message_item my_message;
+
+ task body();
+ `uvm_info(`gfn, $sformatf("\n\t ----| STARTING AES MAIN SEQUENCE |----\n"), UVM_LOW);
+ `uvm_info(`gfn, $sformatf("\n\t cfg item \n %s", cfg.convert2string()), UVM_LOW)
+
+ // generate list of messages //
+ generate_message_queue();
+ // process all messages //
+ while( message_queue.size() > 0) begin
+ // get next message from queue
+ my_message = new();
+ my_message = message_queue.pop_back();
+
+ // for this message generate configuration
+ // and data items (split message into blocks)
+ generate_aes_item_queue(my_message);
+ // setup and transmit
+ transmit_message_with_rd_back();
+ end
+ endtask : body
+endclass
diff --git a/hw/ip/aes/dv/env/seq_lib/aes_vseq_list.sv b/hw/ip/aes/dv/env/seq_lib/aes_vseq_list.sv
index 9b0187a..7d62c58 100644
--- a/hw/ip/aes/dv/env/seq_lib/aes_vseq_list.sv
+++ b/hw/ip/aes/dv/env/seq_lib/aes_vseq_list.sv
@@ -4,5 +4,5 @@
`include "aes_base_vseq.sv"
`include "aes_wake_up_vseq.sv"
-`include "aes_sanity_vseq.sv"
`include "aes_common_vseq.sv"
+`include "aes_stress_vseq.sv"
diff --git a/hw/ip/aes/dv/env/seq_lib/aes_wake_up_vseq.sv b/hw/ip/aes/dv/env/seq_lib/aes_wake_up_vseq.sv
index 3289a4a..00c2989 100644
--- a/hw/ip/aes/dv/env/seq_lib/aes_wake_up_vseq.sv
+++ b/hw/ip/aes/dv/env/seq_lib/aes_wake_up_vseq.sv
@@ -9,35 +9,34 @@
`uvm_object_new
- bit [31:0] plain_text[$] = {32'hDEADBEEF, 32'hEEDDBBAA, 32'hBAADBEEF, 32'hDEAFBEAD};
- logic [255:0] init_key = 256'h0000111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFF;
- bit [31:0] cypher_text[$];
- bit [31:0] decrypted_text[$];
- logic [31:0] read_text[$];
- string str="";
+ parameter bit ENCRYPT = 1'b0;
+ parameter bit DECRYPT = 1'b1;
-
-
-
+ bit [3:0] [31:0] plain_text = 128'hDEADBEEFEEDDBBAABAADBEEFDEAFBEAD;
+ logic [255:0] init_key = 256'h0000111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFF;
+ bit [3:0] [31:0] cypher_text;
+ bit [3:0] [31:0] decrypted_text;
+ logic [3:0] [31:0] read_text;
+ string str="";
+
task body();
`uvm_info(`gfn, $sformatf("STARTING AES SEQUENCE"), UVM_LOW)
+
+
`DV_CHECK_RANDOMIZE_FATAL(this)
- `uvm_info(`gfn, $sformatf("running aes sanity sequence"), UVM_LOW)
- `uvm_info(`gfn, $sformatf(" \n\t ---|setting operation to encrypt"), UVM_LOW)
+ `uvm_info(`gfn, $sformatf(" \n\t ---|setting operation to encrypt"), UVM_HIGH)
// set operation to encrypt
set_operation(ENCRYPT);
-
- `uvm_info(`gfn, $sformatf(" \n\t ---| WRITING INIT KEY %02h", init_key), UVM_LOW)
-
+ `uvm_info(`gfn, $sformatf(" \n\t ---| WRITING INIT KEY %02h", init_key), UVM_HIGH)
write_key(init_key);
cfg.clk_rst_vif.wait_clks(20);
- `uvm_info(`gfn, $sformatf(" \n\t ---| ADDING PLAIN TEXT"), UVM_LOW)
+ `uvm_info(`gfn, $sformatf(" \n\t ---| ADDING PLAIN TEXT"), UVM_HIGH)
add_data(plain_text);
@@ -48,37 +47,38 @@
ral.status.convert2string()), UVM_DEBUG)
read_data(cypher_text);
-
// read output
- `uvm_info(`gfn, $sformatf("\n\t ------|WAIT 0 |-------"), UVM_LOW)
+ `uvm_info(`gfn, $sformatf("\n\t ------|WAIT 0 |-------"), UVM_HIGH)
cfg.clk_rst_vif.wait_clks(20);
// set aes to decrypt
set_operation(DECRYPT);
cfg.clk_rst_vif.wait_clks(20);
- `uvm_info(`gfn, $sformatf("\n\t ---|WRITING INIT KEY FOR DECRYPT: %02h", init_key), UVM_LOW)
+ `uvm_info(`gfn, $sformatf("\n\t ---|WRITING INIT KEY FOR DECRYPT: %02h", init_key), UVM_HIGH)
write_key(init_key);
cfg.clk_rst_vif.wait_clks(20);
- `uvm_info(`gfn, $sformatf("\n\t ---| WRITING CYPHER TEXT"), UVM_LOW)
+ `uvm_info(`gfn, $sformatf("\n\t ---| WRITING CYPHER TEXT"), UVM_HIGH)
add_data(cypher_text);
+
`uvm_info(`gfn, $sformatf("\n\t ---| Polling for data %s", ral.status.convert2string()),
UVM_DEBUG)
cfg.clk_rst_vif.wait_clks(20);
read_data(decrypted_text);
- foreach(decrypted_text[i]) begin
- `uvm_info(`gfn, $sformatf("\n\t ----| decrypted text elememt [%d] : %02h", i, decrypted_text[i]), UVM_LOW)
- end
-
+ //need scoreboard disable
foreach(plain_text[i]) begin
if(plain_text[i] != decrypted_text[i]) begin
str = $sformatf(" \n\t ---| OH NOO TEST FAILED AT POS %d|--- \n \t DECRYPTED: \t %02h \n\t Plaintext: \t %02h ",
i, decrypted_text[i], plain_text[i]);
`uvm_fatal(`gfn, $sformatf("%s",str));
end
-
+
+ end
+ foreach(decrypted_text[i]) begin
+ `uvm_info(`gfn,
+ $sformatf("\n\t ----| decrypted text elememt [%d] : %02h", i, decrypted_text[i]), UVM_HIGH)
end
`uvm_info(`gfn, $sformatf(" \n\t ---| YAY TEST PASSED |--- \n \t "), UVM_NONE)
diff --git a/hw/ip/aes/dv/tests/aes_base_test.sv b/hw/ip/aes/dv/tests/aes_base_test.sv
index 5f5e292..694a73b 100644
--- a/hw/ip/aes/dv/tests/aes_base_test.sv
+++ b/hw/ip/aes/dv/tests/aes_base_test.sv
@@ -9,14 +9,27 @@
`uvm_component_utils(aes_base_test)
`uvm_component_new
- // the base class dv_base_test creates the following instances:
- // aes_env_cfg: cfg
- // aes_env: env
+ virtual function void build_phase(uvm_phase phase);
+ super.build_phase(phase);
+ configure_env();
+ endfunction // build_phase
- // the base class also looks up UVM_TEST_SEQ plusarg to create and run that seq in
- // the run_phase; as such, nothing more needs to be done
-// function configure_knobs()
-// endfunction // configure_knobs
+ virtual function void configure_env();
+ // cfg.ref_model = OpenSSL;
+ // env related knobs
+
+ cfg.errors_en = 0;
+ cfg.num_messages_min = 3;
+ cfg.num_messages_max = 3;
+ // message related knobs
+ cfg.ecb_weight = 100;
+ cfg.cbc_weight = 0;
+ cfg.ctr_weight = 0;
+ cfg.message_len_min = 1; // bytes
+ cfg.message_len_max = 599; // bytes
+ `DV_CHECK_RANDOMIZE_FATAL(cfg)
+ endfunction
+
endclass : aes_base_test
diff --git a/hw/ip/aes/dv/tests/aes_sanity_test.sv b/hw/ip/aes/dv/tests/aes_sanity_test.sv
new file mode 100644
index 0000000..6acdd89
--- /dev/null
+++ b/hw/ip/aes/dv/tests/aes_sanity_test.sv
@@ -0,0 +1,29 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+class aes_sanity_test extends aes_base_test;
+
+ `uvm_component_utils(aes_sanity_test)
+ `uvm_component_new
+
+ virtual function void build_phase(uvm_phase phase);
+ super.build_phase(phase);
+ configure_env();
+ endfunction
+
+ function void configure_env();
+ super.configure_env();
+ cfg.errors_en = 0; // no errors in sanity test
+ cfg.num_messages_min = 2;
+ cfg.num_messages_max = 2;
+ // message related knobs
+ cfg.ecb_weight = 100; // only eCB
+ cfg.cbc_weight = 0;
+ cfg.ctr_weight = 0;
+ cfg.message_len_min = 16; // one block (16bytes=128bits)
+ cfg.message_len_max = 16; //
+
+ `DV_CHECK_RANDOMIZE_FATAL(cfg)
+ endfunction
+endclass : aes_sanity_test
diff --git a/hw/ip/aes/dv/tests/aes_stress_test.sv b/hw/ip/aes/dv/tests/aes_stress_test.sv
new file mode 100644
index 0000000..2b83103
--- /dev/null
+++ b/hw/ip/aes/dv/tests/aes_stress_test.sv
@@ -0,0 +1,29 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+class aes_stress_test extends aes_base_test;
+ `uvm_component_utils(aes_stress_test)
+ `uvm_component_new
+
+ virtual function void build_phase(uvm_phase phase);
+ super.build_phase(phase);
+ configure_env();
+ endfunction
+
+ virtual function void configure_env();
+ // cfg.ref_model = OpenSSL;
+ // env related knobs
+
+ cfg.errors_en = 0;
+ cfg.num_messages_min = 5;
+ cfg.num_messages_max = 5;
+ // message related knobs
+ cfg.ecb_weight = 10;
+ cfg.cbc_weight = 40;
+ cfg.ctr_weight = 40;
+ cfg.message_len_min = 7; // bytes
+ cfg.message_len_max = 251; // bytes
+ `DV_CHECK_RANDOMIZE_FATAL(cfg)
+ endfunction
+endclass : aes_stress_test
diff --git a/hw/ip/aes/dv/tests/aes_test.core b/hw/ip/aes/dv/tests/aes_test.core
index f6d54fa..17d13d8 100644
--- a/hw/ip/aes/dv/tests/aes_test.core
+++ b/hw/ip/aes/dv/tests/aes_test.core
@@ -11,6 +11,9 @@
files:
- aes_test_pkg.sv
- aes_base_test.sv: {is_include_file: true}
+ - aes_wake_up_test.sv: {is_include_file: true}
+ - aes_sanity_test.sv: {is_include_file: true}
+ - aes_stress_test.sv: {is_include_file: true}
file_type: systemVerilogSource
targets:
diff --git a/hw/ip/aes/dv/tests/aes_test_pkg.sv b/hw/ip/aes/dv/tests/aes_test_pkg.sv
index 325cf59..769a9e2 100644
--- a/hw/ip/aes/dv/tests/aes_test_pkg.sv
+++ b/hw/ip/aes/dv/tests/aes_test_pkg.sv
@@ -18,5 +18,8 @@
// package sources
`include "aes_base_test.sv"
+ `include "aes_wake_up_test.sv"
+ `include "aes_sanity_test.sv"
+ `include "aes_stress_test.sv"
endpackage
diff --git a/hw/ip/aes/dv/tests/aes_wake_up_test.sv b/hw/ip/aes/dv/tests/aes_wake_up_test.sv
new file mode 100644
index 0000000..4679306
--- /dev/null
+++ b/hw/ip/aes/dv/tests/aes_wake_up_test.sv
@@ -0,0 +1,25 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+class aes_wake_up_test extends aes_base_test;
+
+ `uvm_component_utils(aes_wake_up_test)
+ `uvm_component_new
+
+ virtual function void build_phase(uvm_phase phase);
+ super.build_phase(phase);
+ configure_env();
+ endfunction
+
+ virtual function void configure_env();
+ // cfg.en_scb = 0;
+ cfg.ecb_weight = 100;
+ cfg.cbc_weight = 0;
+ cfg.ctr_weight = 0;
+ cfg.num_messages_min = 2;
+ cfg.num_messages_max = 2;
+
+ `DV_CHECK_RANDOMIZE_FATAL(cfg)
+ endfunction
+endclass : aes_wake_up_test