blob: c56b8694f5aae199b0296e1f4114dfef53483d04 [file] [log] [blame]
// Copyright lowRISC contributors.
// 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;
`uvm_object_utils(aes_seq_item)
aes_item_type_e item_type;
aes_op_e operation;
///////////////////////////////////////
// Control Knobs //
///////////////////////////////////////
// set if this item contains valid information
bit valid = 0;
// 0: auto mode 1: manual start
bit manual_op;
// 0: output data cannot be overwritten
// 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
bit [2:0] key_len;
// 256 bit key (8x32 bit) in two shares, key = share0 ^ share1
bit [7:0][31:0] key [2];
// which fields of the key is valid
bit [7:0] key_vld [2] = '{8'b0, 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;
bit en_b2b_transactions = 1;
///////////////////////////////////////
// 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;
// used by the checker
bit [3:0][31:0] data_out;
// set if data should be fixed and not randomized
bit fixed_data = 0;
// if set unused key bytes will be forced to 0 - controlled from test
bit key_mask = 1;
///////////////////////////////////////
// Randomizable variables //
///////////////////////////////////////
// used by the checker
rand bit [3:0][31:0] data_in;
// back to back
rand bit do_b2b;
function new( string name="aes_sequence_item");
super.new(name);
endfunction
function void post_randomize();
bit [3:0] index;
if(key_mask) begin
case (key_len)
3'b001: begin
key[0][7:4] = 32'h00000000;
key[1][7:4] = 32'h00000000;
end
3'b010: begin
key[0][7:6] = 32'h00000000;
key[1][7:6] = 32'h00000000;
end
default: begin
end
endcase // case (key_len)
if (!en_b2b_transactions) do_b2b = 0;
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_MEDIUM)
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 %b", key_vld[0], key_vld[1]), UVM_MEDIUM)
if(ret_clean) begin
return ( (&key_vld[0] & &key_vld[1]) || ~(|key_vld[0] | |key_vld[1]));
end else begin
return (&key_vld[0] & &key_vld[1]);
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) %b",
key_vld[0], key_vld[1], &key_vld[0] & &key_vld[1]), UVM_MEDIUM)
return (&key_vld[0] & &key_vld[1]);
end
AES_CBC: begin
`uvm_info(`gfn, $sformatf("return key vld(%b, %b) %b AND iv (%b) &b",
key_vld[0], key_vld[1], (&key_vld[0] & &key_vld[1]), iv_vld, &iv_vld), UVM_MEDIUM)
return ((&key_vld[0] & &key_vld[1]) && &iv_vld);
end
AES_CFB: begin
`uvm_info(`gfn, $sformatf("return key vld(%b, %b) %b AND iv (%b) &b",
key_vld[0], key_vld[1], (&key_vld[0] & &key_vld[1]), iv_vld, &iv_vld), UVM_MEDIUM)
return ((&key_vld[0] & &key_vld[1]) && &iv_vld);
end
AES_OFB: begin
`uvm_info(`gfn, $sformatf("return key vld(%b, %b) %b AND iv (%b) &b",
key_vld[0], key_vld[1], (&key_vld[0] & &key_vld[1]), iv_vld, &iv_vld), UVM_MEDIUM)
return ((&key_vld[0] & &key_vld[1]) && &iv_vld);
end
AES_CTR: begin
`uvm_info(`gfn, $sformatf("return key vld(%b, %b) %b AND iv (%b) &b",
key_vld[0], key_vld[1], (&key_vld[0] & &key_vld[1]), iv_vld, &iv_vld), UVM_MEDIUM)
return ((&key_vld[0] & &key_vld[1]) && &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 void clean();
data_in_vld = '0;
iv_vld = '0;
key_vld = '{default: '0};
data_out_vld = '0;
endfunction // clean
virtual function void do_copy(uvm_object rhs);
aes_seq_item rhs_;
`downcast(rhs_,rhs)
super.do_copy(rhs);
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;
manual_op = rhs_.manual_op;
key_mask = rhs_.key_mask;
endfunction // copy
// do compare //
virtual function bit do_compare(uvm_object rhs, uvm_comparer comparer);
aes_seq_item rhs_;
`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 ----| 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 Share 0: \t ") };
for(int i=0; i <8; i++) begin
str = {str, $psprintf("%h ",key[0][i])};
end
str = {str, $psprintf("\n\t ----| Key Share 1: \t ") };
for(int i=0; i <8; i++) begin
str = {str, $psprintf("%h ",key[1][i])};
end
str = {str, $sformatf("\n\t ----| Initializaion vector: \t ") };
for(int i=0; i <4; i++) begin
str = {str, $sformatf("%h ",iv[i])};
end
str = {str, $psprintf("\n\t ----| key_mask: \t %d |----\t \t", key_mask) };
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;
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])};
end
return str;
endfunction
endclass