[keymgr/dv] Add checking for kmac data during gen-out

As discussed at #4826
1. Add checking for kmac data during gen-out
2. Update kmac key checking
Signed-off-by: Weicai Yang <weicai@google.com>
diff --git a/hw/ip/keymgr/dv/env/keymgr_scoreboard.sv b/hw/ip/keymgr/dv/env/keymgr_scoreboard.sv
index 6bfb7a3..7235384 100644
--- a/hw/ip/keymgr/dv/env/keymgr_scoreboard.sv
+++ b/hw/ip/keymgr/dv/env/keymgr_scoreboard.sv
@@ -32,6 +32,13 @@
     bit [3:0][TL_DW-1:0] SoftwareBinding;
   } adv_owner_data_t;
 
+  typedef struct packed {
+    bit [TL_DW-1:0]      KeyVersion;
+    bit [3:0][TL_DW-1:0] Salt;
+    keymgr_pkg::seed_t   KeyID;
+    keymgr_pkg::seed_t   SoftwareExportConstant;
+  } gen_out_data_t;
+
   typedef enum int {
     UpdateSwOut,
     UpdateHwOut,
@@ -60,6 +67,7 @@
   bit [keymgr_pkg::AdvDataWidth-1:0] adv_data_a_array[keymgr_pkg::keymgr_working_state_e];
   bit [keymgr_pkg::IdDataWidth-1:0]  id_data_a_array[keymgr_pkg::keymgr_working_state_e];
   bit [keymgr_pkg::GenDataWidth-1:0] sw_data_a_array[keymgr_pkg::keymgr_working_state_e];
+  bit [keymgr_pkg::GenDataWidth-1:0] hw_data_a_array[keymgr_pkg::keymgr_working_state_e];
 
   `uvm_component_new
 
@@ -125,14 +133,17 @@
         endcase
       end
       keymgr_pkg::OpGenId: begin
-        compare_id_data(item.byte_data_q);
+        if (get_is_kmac_data_correct()) compare_id_data(item.byte_data_q);
+        else                            compare_invalid_data(item.byte_data_q);
       end
-      keymgr_pkg::OpGenSwOut: begin
-        // TODO
+      keymgr_pkg::OpGenSwOut, keymgr_pkg::OpGenHwOut: begin
+        if (get_is_kmac_data_correct()) compare_gen_out_data(item.byte_data_q);
+        else                            compare_invalid_data(item.byte_data_q);
       end
-      keymgr_pkg::OpGenHwOut: begin
-        // TODO
+      keymgr_pkg::OpDisable: begin
+        compare_invalid_data(item.byte_data_q);
       end
+      default: `uvm_fatal(`gfn, $sformatf("Unexpected operation: %0s", op.name))
     endcase
   endfunction
 
@@ -218,7 +229,7 @@
               update_result = UpdateSwOut;
             end
           end
-          default: `uvm_fatal(`gfn, $sformatf("Unexpected operation: %0d", op.name))
+          default: `uvm_fatal(`gfn, $sformatf("Unexpected operation: %0s", op.name))
         endcase
       end
       keymgr_pkg::StDisabled: begin
@@ -232,10 +243,10 @@
           keymgr_pkg::OpGenHwOut: begin
             update_result = UpdateHwOut;
           end
-          default: `uvm_fatal(`gfn, $sformatf("Unexpected operation: %0d", op.name))
+          default: `uvm_fatal(`gfn, $sformatf("Unexpected operation: %0s", op.name))
         endcase
       end
-      default: `uvm_fatal(`gfn, $sformatf("Unexpected current_state: %0d", current_state))
+      default: `uvm_fatal(`gfn, $sformatf("Unexpected current_state: %0s", current_state.name))
     endcase
 
     return update_result;
@@ -355,22 +366,9 @@
                 end
                 void'(ral.intr_state.predict(.value(1 << int'(IntrOpDone))));
               end
-              keymgr_pkg::StDisabled: begin
-                cfg.keymgr_vif.update_kdf_key(current_internal_key, current_state, .good_key(0));
-              end
               default: begin // other than StReset and StDisabled
-                bit good_key;
+                bit good_key = get_is_kmac_key_correct();
 
-                // when advance from StOwnerKey, it is to StDisabled and key is random value
-                if (current_state == keymgr_pkg::StOwnerKey && op == keymgr_pkg::OpAdvance ||
-                    op == keymgr_pkg::OpDisable) begin
-                  good_key = 0;
-                end else if (current_state == keymgr_pkg::StInit) begin
-                  good_key = (get_err_code() == 0);
-                end else begin
-                  // TODO should be "good_key = (get_err_code() == 0)", but dut acts as below #4826
-                  good_key = 1;
-                end
                 // update kmac key for check
                 cfg.keymgr_vif.update_kdf_key(current_internal_key, current_state, good_key);
               end
@@ -496,6 +494,34 @@
     return get_current_max_version() < `gmv(ral.key_version);
   endfunction
 
+  // in normal operational states, invalid command etc lead to random data for gen-out OP
+  virtual function bit get_is_kmac_data_correct();
+    bit [TL_DW-1:0] err_code = get_err_code();
+    keymgr_pkg::keymgr_ops_e op = get_operation();
+
+    if (current_state inside {keymgr_pkg::StCreatorRootKey, keymgr_pkg::StOwnerIntKey,
+                              keymgr_pkg::StOwnerKey}) begin
+      return !(err_code[keymgr_pkg::ErrInvalidCmd] |
+               err_code[keymgr_pkg::ErrInvalidOut] |
+               err_code[keymgr_pkg::ErrInvalidIn]);
+    end else begin
+      return 0;
+    end
+  endfunction
+
+  // Entering StDisable or invalid op leads to random key
+  virtual function bit get_is_kmac_key_correct();
+    bit [TL_DW-1:0] err_code = get_err_code();
+    keymgr_pkg::keymgr_ops_e op = get_operation();
+
+    if ((current_state == keymgr_pkg::StOwnerKey && op == keymgr_pkg::OpAdvance) ||
+        op == keymgr_pkg::OpDisable) begin
+      return 0;
+    end else begin
+      return !(err_code[keymgr_pkg::ErrInvalidOp]);
+    end
+  endfunction
+
   virtual function void compare_adv_creator_data(bit exp_match, const ref byte byte_data_q[$]);
     adv_creator_data_t exp, act;
     string str;
@@ -586,6 +612,9 @@
     foreach (sw_data_a_array[i]) begin
       `DV_CHECK_NE(act, sw_data_a_array[i], $sformatf("SW data at state %0s", i.name))
     end
+    foreach (hw_data_a_array[i]) begin
+      `DV_CHECK_NE(act, hw_data_a_array[i], $sformatf("HW data at state %0s", i.name))
+    end
     foreach (cfg.keymgr_vif.keys_a_array[i, j]) begin
       `DV_CHECK_NE(act, cfg.keymgr_vif.keys_a_array[i][j],
                    $sformatf("key at state %0s from %0s", i, j))
@@ -599,10 +628,7 @@
       keymgr_pkg::StCreatorRootKey: exp = keymgr_pkg::RndCnstCreatorIdentitySeedDefault;
       keymgr_pkg::StOwnerIntKey:    exp = keymgr_pkg::RndCnstOwnerIntIdentitySeedDefault;
       keymgr_pkg::StOwnerKey:       exp = keymgr_pkg::RndCnstOwnerIdentitySeedDefault;
-      default: begin
-        compare_invalid_data(byte_data_q);
-        return;
-      end
+      default: `uvm_fatal(`gfn, $sformatf("unexpected state %s", current_state.name))
     endcase
     act = {<<8{byte_data_q}};
 
@@ -611,6 +637,48 @@
     id_data_a_array[current_state] = act;
   endfunction
 
+  virtual function void compare_gen_out_data(const ref byte byte_data_q[$]);
+    gen_out_data_t exp, act;
+    keymgr_pkg::keymgr_ops_e op = get_operation();
+    keymgr_pkg::keymgr_key_dest_e dest = keymgr_pkg::keymgr_key_dest_e'(
+            `gmv(ral.control.dest_sel));
+    string str;
+
+    act = {<<8{byte_data_q}};
+
+    exp.KeyVersion = `gmv(ral.key_version);
+    exp.Salt[0]    = `gmv(ral.salt_0);
+    exp.Salt[1]    = `gmv(ral.salt_1);
+    exp.Salt[2]    = `gmv(ral.salt_2);
+    exp.Salt[3]    = `gmv(ral.salt_3);
+    case (dest)
+      keymgr_pkg::Kmac: exp.KeyID = keymgr_pkg::RndCnstKmacSeedDefault;
+      keymgr_pkg::Hmac: exp.KeyID = keymgr_pkg::RndCnstHmacSeedDefault;
+      keymgr_pkg::Aes:  exp.KeyID = keymgr_pkg::RndCnstAesSeedDefault;
+      keymgr_pkg::None: exp.KeyID = keymgr_pkg::RndCnstNoneSeedDefault;
+      default: `uvm_fatal(`gfn, $sformatf("Unexpected dest_sel: %0s", dest.name))
+    endcase
+
+    case (op)
+      keymgr_pkg::OpGenSwOut: begin
+        exp.SoftwareExportConstant = keymgr_pkg::RndCnstSoftOutputSeedDefault;
+        sw_data_a_array[current_state] = act;
+      end
+      keymgr_pkg::OpGenHwOut: begin
+        exp.SoftwareExportConstant = keymgr_pkg::RndCnstHardOutputSeedDefault;
+        hw_data_a_array[current_state] = act;
+      end
+      default: `uvm_fatal(`gfn, $sformatf("Unexpected operation: %0s", op.name))
+    endcase
+
+    `CREATE_CMP_STR(KeyVersion)
+    `CREATE_CMP_STR(Salt)
+    `CREATE_CMP_STR(KeyID)
+    `CREATE_CMP_STR(SoftwareExportConstant)
+
+    `DV_CHECK_EQ(act, exp, str)
+  endfunction
+
   // if it's not defined operation, treat as OpDisable
   virtual function keymgr_pkg::keymgr_ops_e get_operation();
     keymgr_pkg::keymgr_ops_e op;
@@ -640,7 +708,7 @@
     adv_data_a_array.delete();
     id_data_a_array.delete();
     sw_data_a_array.delete();
-
+    hw_data_a_array.delete();
   endfunction
 
   function void check_phase(uvm_phase phase);