| // 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; | 
 |   cfg_error_type_t  config_error_type_en  = 3'b000; | 
 |   // errors enabled mask | 
 |   error_types_t     error_types           = 3'b000; | 
 |  | 
 |   // manual mode percentage | 
 |   int               manual_operation_pct  = 10; | 
 |   // maskout unused key bits | 
 |   bit               keymask               = 0; | 
 |   // use fixed key | 
 |   bit               fixed_key_en          = 0; | 
 |   // used fixed key length | 
 |   bit               fixed_keylen_en       = 0; | 
 |   // use fixed data (same data for each block in a message | 
 |   bit               fixed_data_en         = 0; | 
 |   // fixed operation | 
 |   bit               fixed_operation_en    = 0; | 
 |   // fixed IV | 
 |   bit               fixed_iv_en           = 0; | 
 |   // sideload | 
 |   int               sideload_pct          = 0; | 
 |   rand bit          sideload_en           = 0; | 
 |  | 
 |   // clear register percentage | 
 |   // percentage of items that will try to clear | 
 |   // one or more registers | 
 |   int               clear_reg_pct         = 0; | 
 |  | 
 |  | 
 |   // predefined values for fixed mode | 
 |   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 [3:0] [31:0]    fixed_iv         = 128'h00000000000000000000000000000000; | 
 |  | 
 |   // Mode distribution // | 
 |   // chance of selection ecb_mode | 
 |   // ecb_mode /(ecb_mode + cbc_mode + cfb_mode + ofb_mode + ctr_mode) | 
 |   // with the defaults 10/50 = 1/5 (20%) | 
 |   int    ecb_weight           = 10; | 
 |   int    cbc_weight           = 10; | 
 |   int    cfb_weight           = 10; | 
 |   int    ofb_weight           = 10; | 
 |   int    ctr_weight           = 10; | 
 |  | 
 |   // KEYLEN weights | 
 |   int    key_128b_weight      = 10; | 
 |   int    key_192b_weight      = 10; | 
 |   int    key_256b_weight      = 10; | 
 |  | 
 |   // reseed weight | 
 |   int    per8_weight          = 60; | 
 |   int    per64_weight         = 30; | 
 |   int    per8k_weight         = 10; | 
 |  | 
 |   // set if this message should not be | 
 |   // validated | 
 |   // due to a premature trigger | 
 |   // i.e unkown key and IV settings used | 
 |   bit    skip_msg             = 0; | 
 |  | 
 |   /////////////////////////////////////// | 
 |   // Randomizable variables            // | 
 |   /////////////////////////////////////// | 
 |  | 
 |   // length of the message                                     // | 
 |   rand int               message_length; | 
 |   // 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; | 
 |   // aes key length                                            // | 
 |   rand bit [2:0]         aes_keylen; | 
 |   // 256 bit key (8x32 bit)                                    // | 
 |   rand bit [7:0][31:0]   aes_key [2]; | 
 |   // 256 bit initialization vector (8x32 bit)                  // | 
 |   rand bit [3:0][31:0]   aes_iv; | 
 |   // configuration error                                       // | 
 |   rand bit               has_config_error; | 
 |   // [0] mode error [1] key_len error | 
 |   rand cfg_error_type_t  cfg_error_type; | 
 |   // run AES in manual mode | 
 |   rand bit               manual_operation; | 
 |   // reseed rate | 
 |   rand bit [2:0]         reseed_rate; | 
 |  | 
 |  | 
 |   /////////////////////////////////////// | 
 |   // FIXED variables                   // | 
 |   /////////////////////////////////////// | 
 |  | 
 |   bit [7:0]            input_msg[]; | 
 |   bit [7:0]            output_msg[]; | 
 |   bit [7:0]            predicted_msg[]; | 
 |   bit                  output_cleared[]; | 
 |  | 
 |   /////////////////////////////////////// | 
 |   // Constraints                       // | 
 |   /////////////////////////////////////// | 
 |  | 
 |   constraint data_c { message_length inside { [message_len_min:message_len_max] };} | 
 |  | 
 |   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 }; | 
 |     } else { | 
 |       // force the selection to be something invalid | 
 |       !(aes_keylen inside { 3'b001, 3'b010, 3'b100 }); | 
 |     } | 
 |     if (fixed_keylen_en) { | 
 |       aes_keylen == fixed_keylen | 
 |     }; | 
 |   } | 
 |  | 
 |   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 :/ per8_weight, | 
 |                            3'b010 :/ per64_weight, | 
 |                            3'b100 :/ per8k_weight }; | 
 |     } else { | 
 |       !( reseed_rate  inside { 3'b001, 3'b010, 3'b100 }); | 
 |     } | 
 |   } | 
 |  | 
 |  | 
 |   constraint key_c { | 
 |     if (fixed_key_en) { | 
 |       aes_key[0] == fixed_key[0], | 
 |       aes_key[1] == fixed_key[1] | 
 |     }; | 
 |   } | 
 |  | 
 |   constraint iv_c { | 
 |     if (fixed_iv_en) { | 
 |       aes_iv == fixed_iv | 
 |     }; | 
 |   } | 
 |  | 
 |   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 & !sideload_en) { | 
 |       cfg_error_type inside {[1:7]}; | 
 |       config_error_type_en[0] -> cfg_error_type[0] == 0; | 
 |       config_error_type_en[1] -> cfg_error_type[1] == 0; | 
 |       config_error_type_en[2] -> cfg_error_type[2] == 0; | 
 |     } else { | 
 |       cfg_error_type == 3'b000; | 
 |     } | 
 |   } | 
 |  | 
 |   constraint sideload_c { | 
 |     sideload_en dist{ 0:/(100-sideload_pct), | 
 |                       1:/sideload_pct}; | 
 |   } | 
 |  | 
 |   constraint manual_operation_c { | 
 |     solve sideload_en before manual_operation; | 
 |     if (!sideload_en) { | 
 |       manual_operation dist { 0:/ (100 - manual_operation_pct), | 
 |                               1:/ manual_operation_pct}; | 
 |     } 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] | 
 |                     ,item.data_in[i][31:24]}; | 
 |       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] }; | 
 |       `uvm_info(`gfn, $sformatf("\n\t ---| adding to 0x%0h to data, length is now: %0d", | 
 |                {item.data_in[i][7:0], item.data_in[i][15:8],item.data_in[i][23:16], item.data_in[i][31:24]}, | 
 |                input_msg.size()), UVM_FULL) | 
 |       output_cleared = { output_cleared, item.data_was_cleared, item.data_was_cleared, | 
 |                         item.data_was_cleared, item.data_was_cleared}; | 
 |     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_key       = item.key; | 
 |     this.aes_iv        = item.iv; | 
 |  | 
 |     // check for valid keylen | 
 |     if (item.key_len inside { 3'b001, 3'b010, 3'b100 }) begin | 
 |       this.aes_keylen  = item.key_len; | 
 |     end else begin | 
 |       this.aes_keylen = 3'b100; // force to 256b | 
 |       `uvm_info(`gfn, $sformatf("\n\t ---| Illegal key len detected reverting to default 256"), | 
 |                 UVM_MEDIUM) | 
 |     end | 
 |     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 ----| \t\t AES MESSAGE ITEM   \t      |----\t ") | 
 |            }; | 
 |     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 ----| 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 ", | 
 |                            cfg_error_type.mode, cfg_error_type.key_len)}; | 
 |     str = {str,  $sformatf("\n\t ----| Message Length:  \t  \t %d             \t ", | 
 |                            message_length)}; | 
 |  | 
 |     str = {str,  $sformatf("\n\t ----| Key Length:   \t \t %03b                             \t ", | 
 |                            aes_keylen)}; | 
 |     str = {str,  $sformatf("\n\t ----| Key Share 0: \t \t ")}; | 
 |     for (int i=0; i <8; i++) begin | 
 |       str = {str, $sformatf("%h ",aes_key[0][i])}; | 
 |     end | 
 |     str = {str,  $sformatf("\n\t ----| Key Share 1: \t \t ")}; | 
 |     for (int i=0; i <8; i++) begin | 
 |       str = {str, $sformatf("%h ",aes_key[1][i])}; | 
 |     end | 
 |     str = {str,  $sformatf("\n\t ----| Key Mask:  \t  \t %0b                             |----\t ", | 
 |                            keymask)}; | 
 |      str = {str,  $sformatf("\n\t ----| Initializaion vector:     \t    \t ")}; | 
 |     for (int i=0; i <4; i++) begin | 
 |       str = {str, $sformatf("%h ",aes_iv[i])}; | 
 |     end | 
 |     str = {str,  $sformatf("\n\t ----| Manual Mode : %b      \t   \t ", manual_operation)}; | 
 |     str = {str,  $sformatf("\n\t ----| SideLoad En : %b      \t   \t ", sideload_en)}; | 
 |     str = {str,  $sformatf("\n\t ----| errors types enabled: %b      \t   \t ", error_types)}; | 
 |     str = {str,  $sformatf("\n\t ----| CFB Weight: %d       \t \t ", cfb_weight)}; | 
 |     str = {str,  $sformatf("\n\t ----| OFB Weight: %d       \t \t ", ofb_weight)}; | 
 |     str = {str,  $sformatf("\n\t ----| ECB Weight: %d       \t \t ", ecb_weight)}; | 
 |     str = {str,  $sformatf("\n\t ----| CBC Weight: %d       \t \t ", cbc_weight)}; | 
 |     str = {str,  $sformatf("\n\t ----| CTR Weight: %d       \t \t ", ctr_weight)}; | 
 |     str = {str,  $sformatf("\n\t ----| Key Len Distribution: \t \t " ) }; | 
 |     str = {str,  $sformatf("\n\t ----| 128 Weight: %d       \t \t ", key_128b_weight)}; | 
 |     str = {str,  $sformatf("\n\t ----| 192 Weight: %d       \t \t ", key_192b_weight)}; | 
 |     str = {str,  $sformatf("\n\t ----| 256 Weight: %d       \t \t ", key_256b_weight)}; | 
 |     str = {str,  $sformatf("\n\t")}; | 
 |  | 
 |     return str; | 
 |   endfunction // conver2string | 
 |  | 
 |    virtual function string print_data(); | 
 |      string txt=""; | 
 |  | 
 |      txt = $sformatf("\n\t ---| Printing message data \n\t ---| data length: %d", input_msg.size()); | 
 |      foreach (input_msg[i]) begin | 
 |        txt = {txt, $sformatf("\n\t ----| [%0d] 0x%0h \t 0x%0h",i, input_msg[i], output_msg[i])}; | 
 |      end | 
 |      return txt; | 
 |    endfunction // get_data_length | 
 |  | 
 |  | 
 |   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; | 
 |     cfg_error_type   = rhs_.cfg_error_type; | 
 |     error_types      = rhs_.error_types; | 
 |     ecb_weight       = rhs_.ecb_weight; | 
 |     cbc_weight       = rhs_.cbc_weight; | 
 |     cfb_weight       = rhs_.cfb_weight; | 
 |     ofb_weight       = rhs_.ofb_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; | 
 |     output_cleared   = rhs_.output_cleared; | 
 |     predicted_msg    = rhs_.predicted_msg; | 
 |     manual_operation = rhs_.manual_operation; | 
 |     keymask          = rhs_.keymask; | 
 |     fixed_data_en    = rhs_.fixed_data_en; | 
 |     fixed_data       = rhs_.fixed_data; | 
 |     fixed_iv_en      = rhs_.fixed_iv_en; | 
 |     skip_msg         = rhs_.skip_msg; | 
 |     sideload_en      = rhs_.sideload_en; | 
 |     reseed_rate      = rhs_.reseed_rate; | 
 |   endfunction // copy | 
 | endclass |