[keymgr/dv] Update scb/seq for DICE support

For design update at #7207
1. randomize CDI_SEL and both sw_binding in seq
2. remove hack code. store and check both CDI internal data

Signed-off-by: Weicai Yang <weicai@google.com>
diff --git a/hw/ip/keymgr/dv/env/keymgr_env_pkg.sv b/hw/ip/keymgr/dv/env/keymgr_env_pkg.sv
index d3a2cde..f5756bb 100644
--- a/hw/ip/keymgr/dv/env/keymgr_env_pkg.sv
+++ b/hw/ip/keymgr/dv/env/keymgr_env_pkg.sv
@@ -31,6 +31,11 @@
     NumKeyMgrIntr
   } keymgr_intr_e;
 
+  typedef enum {
+    Sealing,
+    Attestation
+  } keymgr_cdi_type_e;
+
   string msg_id = "keymgr_env_pkg";
   // functions
   // state is incremental, if it's not in defined enum, consider as StDisabled
diff --git a/hw/ip/keymgr/dv/env/keymgr_scoreboard.sv b/hw/ip/keymgr/dv/env/keymgr_scoreboard.sv
index a76b9ae..68a2ef2 100644
--- a/hw/ip/keymgr/dv/env/keymgr_scoreboard.sv
+++ b/hw/ip/keymgr/dv/env/keymgr_scoreboard.sv
@@ -71,7 +71,8 @@
 
   // local queues to hold incoming packets pending comparison
   // store meaningful data, in non-working state, should not match to these data
-  bit [keymgr_pkg::AdvDataWidth-1:0] adv_data_a_array[keymgr_pkg::keymgr_working_state_e];
+  bit [keymgr_pkg::AdvDataWidth-1:0] adv_data_a_array[keymgr_cdi_type_e][
+                                     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];
@@ -128,23 +129,27 @@
 
     case (op)
       keymgr_pkg::OpAdvance: begin
+        keymgr_cdi_type_e cdi_type;
+        `downcast(cdi_type, adv_cnt)
+
         case (current_state)
           keymgr_pkg::StInit: begin
             bit is_err = get_hw_invalid_input();
-
-            compare_adv_creator_data(.exp_match(!is_err),
+            compare_adv_creator_data(.cdi_type(cdi_type),
+                                     .exp_match(!is_err),
                                      .byte_data_q(item.byte_data_q));
             if (is_err) compare_invalid_data(item.byte_data_q);
           end
           keymgr_pkg::StCreatorRootKey: begin
             bit is_err = get_hw_invalid_input();
 
-            compare_adv_owner_int_data(.exp_match(!is_err),
+            compare_adv_owner_int_data(.cdi_type(cdi_type),
+                                       .exp_match(!is_err),
                                        .byte_data_q(item.byte_data_q));
             if (is_err) compare_invalid_data(item.byte_data_q);
           end
           keymgr_pkg::StOwnerIntKey: begin
-            compare_adv_owner_data(item.byte_data_q);
+            compare_adv_owner_data(cdi_type, item.byte_data_q);
           end
           keymgr_pkg::StOwnerKey, keymgr_pkg::StDisabled, keymgr_pkg::StInvalid: begin
             compare_invalid_data(item.byte_data_q);
@@ -170,40 +175,10 @@
   virtual function void process_kmac_data_rsp(kmac_app_item item);
     update_result_e update_result;
     bit process_update;
-    bit adv_from_non_reset;
-    int cdis;
 
     is_kmac_rsp_err = item.rsp_error;
     is_kmac_invalid_data = item.get_is_kmac_rsp_data_invalid();
-
-    // TODO: hack alert.  Since advance operations take 2 passes now, add the following
-    // to inform the function when to actaully process the update.
-    // This is not entirely correct, because an error that shows up during the first pass
-    // is still considered an error.  The process function must be updated to account for that.
-    adv_from_non_reset = 1'b0;
-    if (get_operation() == keymgr_pkg::OpAdvance && current_state != keymgr_pkg::StReset) begin
-      adv_from_non_reset = 1'b1;
-    end
-
-    cdis = keymgr_pkg::CDIs - 1;
-    if (adv_from_non_reset && (adv_cnt == cdis)) begin
-      `uvm_info(`gfn, $sformatf("complete advance"), UVM_MEDIUM)
-      adv_cnt = 0;
-      process_update = 1'b1;
-    end else if (adv_from_non_reset && (adv_cnt < cdis)) begin
-      `uvm_info(`gfn, $sformatf("partial advance"), UVM_MEDIUM)
-      adv_cnt = adv_cnt + 1;
-      process_update = 1'b0;
-      update_result = UpdateInternalKey;
-    end else if (get_operation() != keymgr_pkg::OpAdvance) begin
-      `uvm_info(`gfn, $sformatf("not advance"), UVM_MEDIUM)
-      adv_cnt = 0;
-      process_update = 1'b1;
-    end
-
-    if (process_update) begin
-      update_result = process_update_after_op_done();
-    end
+    update_result = process_update_after_op_done();
 
     case (update_result)
       UpdateInternalKey: begin
@@ -249,18 +224,28 @@
   virtual function update_result_e process_update_after_op_done();
     update_result_e update_result;
     keymgr_pkg::keymgr_ops_e op = get_operation();
+    bit is_final_kdf;
 
+    // for advance after StReset, it needs 2 KDF. Only update opt_status after the last one
+    if (!(op inside {keymgr_pkg::OpAdvance, keymgr_pkg::OpDisable}) ||
+        current_state == keymgr_pkg::StReset) begin
+      is_final_kdf = 1;
+    end else begin
+      is_final_kdf = (adv_cnt == keymgr_pkg::CDIs - 1);
+    end
     // op_status is updated one cycle after done. If SW reads at this edge, still return old value
     // delay half cycle to push the update available in next cycle
     fork
       begin
         cfg.clk_rst_vif.wait_n_clks(1);
-        if (get_err_code()) current_op_status = keymgr_pkg::OpDoneFail;
-        else                current_op_status = keymgr_pkg::OpDoneSuccess;
+        if (is_final_kdf) begin
+          if (get_err_code()) current_op_status = keymgr_pkg::OpDoneFail;
+          else                current_op_status = keymgr_pkg::OpDoneSuccess;
+        end
       end
     join_none
 
-    process_error_n_alert();
+    if (is_final_kdf) process_error_n_alert();
     // IntrOpDone occurs after every KDF
     void'(ral.intr_state.predict(.value(1 << int'(IntrOpDone))));
 
@@ -279,15 +264,26 @@
               // if it's StOwnerKey, it advacens to OpDisable. Key is just random value
               if (current_state == keymgr_pkg::StOwnerKey) update_result = NotUpdate;
               else                                         update_result = UpdateInternalKey;
-              update_state(get_next_state(current_state));
-              // set sw_binding_regwen after advance OP
-              void'(ral.sw_binding_regwen.predict(.value(1)));
-              ral.sw_binding_regwen.en.set_lockable_flds_access(.lock(0));
+
+              if (adv_cnt != keymgr_pkg::CDIs - 1) begin
+                adv_cnt++;
+              end else begin
+                adv_cnt = 0;
+                update_state(get_next_state(current_state));
+                // set sw_binding_regwen after advance OP
+                void'(ral.sw_binding_regwen.predict(.value(1)));
+                ral.sw_binding_regwen.en.set_lockable_flds_access(.lock(0));
+              end
             end
           end
           keymgr_pkg::OpDisable: begin
             update_result = UpdateInternalKey;
-            update_state(keymgr_pkg::StDisabled);
+            if (adv_cnt != keymgr_pkg::CDIs - 1) begin
+              adv_cnt++;
+            end else begin
+              adv_cnt = 0;
+              update_state(keymgr_pkg::StDisabled);
+            end
           end
           keymgr_pkg::OpGenId, keymgr_pkg::OpGenSwOut, keymgr_pkg::OpGenHwOut: begin
             // If only op error but no fault error, no update for output
@@ -307,6 +303,11 @@
         case (op)
           keymgr_pkg::OpAdvance, keymgr_pkg::OpDisable: begin
             update_result = NotUpdate;
+            if (adv_cnt != keymgr_pkg::CDIs - 1) begin
+              adv_cnt++;
+            end else begin
+              adv_cnt = 0;
+            end
           end
           keymgr_pkg::OpGenSwOut, keymgr_pkg::OpGenId: begin
             update_result = UpdateSwOut;
@@ -716,9 +717,11 @@
     end
   endfunction
 
-  virtual function void compare_adv_creator_data(bit exp_match, const ref byte byte_data_q[$]);
+  virtual function void compare_adv_creator_data(keymgr_cdi_type_e cdi_type,
+                                                 bit exp_match,
+                                                 const ref byte byte_data_q[$]);
     adv_creator_data_t exp, act;
-    string str;
+    string str = $sformatf("cdi_type: %s\n", cdi_type.name);
 
     if (exp_match) `DV_CHECK_EQ(byte_data_q.size, keymgr_pkg::AdvDataWidth / 8)
     act = {<<8{byte_data_q}};
@@ -729,10 +732,7 @@
     exp.DeviceIdentifier   = cfg.keymgr_vif.otp_device_id;
     exp.HardwareRevisionSecret = keymgr_pkg::RndCnstRevisionSeedDefault;
 
-    for (int i = 0; i < keymgr_reg_pkg::NumSwBindingReg; i++) begin
-      uvm_reg rg = ral.get_reg_by_name($sformatf("sealing_sw_binding_%0d", i));
-      exp.SoftwareBinding[i] = `gmv(rg);
-    end
+    get_sw_binding_mirrored_value(cdi_type, exp.SoftwareBinding);
 
     // The order of the string creation must match the design
     `CREATE_CMP_STR(DiversificationKey)
@@ -748,20 +748,19 @@
       `DV_CHECK_NE(act, exp, str)
     end
 
-    if (exp_match) adv_data_a_array[keymgr_pkg::StCreatorRootKey] = act;
+    if (exp_match) adv_data_a_array[Sealing][keymgr_pkg::StCreatorRootKey] = act;
   endfunction
 
-  virtual function void compare_adv_owner_int_data(bit exp_match, const ref byte byte_data_q[$]);
+  virtual function void compare_adv_owner_int_data(keymgr_cdi_type_e cdi_type,
+                                                   bit exp_match,
+                                                   const ref byte byte_data_q[$]);
     adv_owner_int_data_t exp, act;
-    string str;
+    string str = $sformatf("cdi_type: %s\n", cdi_type.name);
 
     act = {<<8{byte_data_q}};
 
     exp.OwnerRootSecret = cfg.keymgr_vif.flash.seeds[flash_ctrl_pkg::OwnerSeedIdx];
-    for (int i = 0; i < keymgr_reg_pkg::NumSwBindingReg; i++) begin
-      uvm_reg rg = ral.get_reg_by_name($sformatf("sealing_sw_binding_%0d", i));
-      exp.SoftwareBinding[i] = `gmv(rg);
-    end
+    get_sw_binding_mirrored_value(cdi_type, exp.SoftwareBinding);
 
     `CREATE_CMP_STR(unused)
     `CREATE_CMP_STR(OwnerRootSecret)
@@ -775,19 +774,17 @@
       `DV_CHECK_NE(act, exp, str)
     end
 
-    if (exp_match) adv_data_a_array[keymgr_pkg::StOwnerIntKey] = act;
+    if (exp_match) adv_data_a_array[Sealing][keymgr_pkg::StOwnerIntKey] = act;
   endfunction
 
-  virtual function void compare_adv_owner_data(const ref byte byte_data_q[$]);
+  virtual function void compare_adv_owner_data(keymgr_cdi_type_e cdi_type,
+                                               const ref byte byte_data_q[$]);
     adv_owner_data_t exp, act;
-    string str;
+    string str = $sformatf("cdi_type: %s\n", cdi_type.name);
 
     act = {<<8{byte_data_q}};
 
-    for (int i = 0; i < keymgr_reg_pkg::NumSwBindingReg; i++) begin
-      uvm_reg rg = ral.get_reg_by_name($sformatf("sealing_sw_binding_%0d", i));
-      exp.SoftwareBinding[i] = `gmv(rg);
-    end
+    get_sw_binding_mirrored_value(cdi_type, exp.SoftwareBinding);
 
     `CREATE_CMP_STR(unused)
     for (int i=0; i < keymgr_reg_pkg::NumSwBindingReg; i++) begin
@@ -796,7 +793,7 @@
 
     `DV_CHECK_EQ(act, exp, str)
 
-    adv_data_a_array[keymgr_pkg::StOwnerKey] = act;
+    adv_data_a_array[Sealing][keymgr_pkg::StOwnerKey] = act;
   endfunction
 
   // for invalid OP, should not output any meaningful data to KMAC. Check the outputs aren't
@@ -805,8 +802,9 @@
     adv_owner_data_t act;
 
     act = {<<8{byte_data_q}};
-    foreach (adv_data_a_array[i]) begin
-      `DV_CHECK_NE(act, adv_data_a_array[i], $sformatf("Adv data to state %0s", i.name))
+    foreach (adv_data_a_array[i, j]) begin
+      `DV_CHECK_NE(act, adv_data_a_array[i][j], $sformatf("Adv data to state %0s for %0s", j.name,
+                                                          i.name))
     end
     foreach (id_data_a_array[i]) begin
       `DV_CHECK_NE(act, id_data_a_array[i], $sformatf("ID data at state %0s", i.name))
@@ -882,6 +880,19 @@
     `DV_CHECK_EQ(act, exp, str)
   endfunction
 
+  virtual function void get_sw_binding_mirrored_value(
+        input keymgr_cdi_type_e cdi_type,
+        output bit [keymgr_reg_pkg::NumSwBindingReg-1:0][TL_DW-1:0] sw_binding);
+
+    for (int i = 0; i < keymgr_reg_pkg::NumSwBindingReg; i++) begin
+      case (cdi_type)
+        Sealing: sw_binding[i] = `gmv(ral.sealing_sw_binding[i]);
+        Attestation: sw_binding[i] = `gmv(ral.attest_sw_binding[i]);
+        default: `uvm_fatal(`gfn, $sformatf("Unsupported CDI type %s", cdi_type.name))
+      endcase
+    end
+  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;
diff --git a/hw/ip/keymgr/dv/env/seq_lib/keymgr_base_vseq.sv b/hw/ip/keymgr/dv/env/seq_lib/keymgr_base_vseq.sv
index 7eed019..e4ec524 100644
--- a/hw/ip/keymgr/dv/env/seq_lib/keymgr_base_vseq.sv
+++ b/hw/ip/keymgr/dv/env/seq_lib/keymgr_base_vseq.sv
@@ -208,6 +208,7 @@
 
     ral.control.start.set(1'b1);
     ral.control.operation.set(int'(operation));
+    `DV_CHECK_RANDOMIZE_FATAL(ral.control.cdi_sel)
     // TODO, test KMAC interface only since the other interface may be removed later
     `DV_CHECK_RANDOMIZE_WITH_FATAL(ral.control.dest_sel,
                                    value inside {keymgr_pkg::None, keymgr_pkg::Kmac};);
diff --git a/hw/ip/keymgr/dv/env/seq_lib/keymgr_random_vseq.sv b/hw/ip/keymgr/dv/env/seq_lib/keymgr_random_vseq.sv
index 343c8d4..aa5fb19 100644
--- a/hw/ip/keymgr/dv/env/seq_lib/keymgr_random_vseq.sv
+++ b/hw/ip/keymgr/dv/env/seq_lib/keymgr_random_vseq.sv
@@ -19,8 +19,8 @@
 
     csr_random_n_add_to_q(ral.sw_binding_regwen, csr_update_q);
     for (int i = 0; i < keymgr_reg_pkg::NumSwBindingReg; i++) begin
-      uvm_reg rg = ral.get_reg_by_name($sformatf("sealing_sw_binding_%0d", i));
-      csr_random_n_add_to_q(rg, csr_update_q);
+      csr_random_n_add_to_q(ral.sealing_sw_binding[i], csr_update_q);
+      csr_random_n_add_to_q(ral.attest_sw_binding[i], csr_update_q);
     end
     for (int i = 0; i < keymgr_reg_pkg::NumSaltReg; i++) begin
       uvm_reg rg = ral.get_reg_by_name($sformatf("salt_%0d", i));