[dv/top_level] Randomize lc exit_token value

This PR supports randomize lc exit_token in SV and C test.
To support this:
1). Add a random array in SV and pass it to C test.
2). Add cshake128 dpi function to decode the exit_token value.
This PR finishes a TODO in issue #7665

Signed-off-by: Cindy Chen <chencindy@opentitan.org>
diff --git a/hw/top_earlgrey/dv/env/chip_env.core b/hw/top_earlgrey/dv/env/chip_env.core
index bbe5439..2610b89 100644
--- a/hw/top_earlgrey/dv/env/chip_env.core
+++ b/hw/top_earlgrey/dv/env/chip_env.core
@@ -10,15 +10,17 @@
       - lowrisc:opentitan:bus_params_pkg
       - lowrisc:systems:top_earlgrey_pkg
       - lowrisc:ip:spi_device
-      - lowrisc:dv:ralgen
-      - lowrisc:dv:str_utils
+      - lowrisc:ip:kmac_pkg
       - lowrisc:dv:cip_lib
-      - lowrisc:dv:uart_agent
+      - lowrisc:dv:digestpp_dpi
       - lowrisc:dv:jtag_riscv_agent
-      - lowrisc:dv:spi_agent
       - lowrisc:dv:mem_bkdr_util
+      - lowrisc:dv:ralgen
+      - lowrisc:dv:spi_agent
+      - lowrisc:dv:str_utils
       - lowrisc:dv:sw_test_status
       - lowrisc:dv:sw_logger_if
+      - lowrisc:dv:uart_agent
     files:
       - chip_env_pkg.sv
       - chip_env_cfg.sv: {is_include_file: true}
diff --git a/hw/top_earlgrey/dv/env/chip_env_pkg.sv b/hw/top_earlgrey/dv/env/chip_env_pkg.sv
index 5b0b355..b308066 100644
--- a/hw/top_earlgrey/dv/env/chip_env_pkg.sv
+++ b/hw/top_earlgrey/dv/env/chip_env_pkg.sv
@@ -3,27 +3,31 @@
 // SPDX-License-Identifier: Apache-2.0
 
 package chip_env_pkg;
+
   // dep packages
   import uvm_pkg::*;
   import top_pkg::*;
-  import flash_ctrl_pkg::*;
-  import otp_ctrl_pkg::*;
-  import sram_ctrl_pkg::*;
-  import dv_utils_pkg::*;
-  import dv_base_reg_pkg::*;
+
+  import bus_params_pkg::*;
+  import chip_ral_pkg::*;
+  import cip_base_pkg::*;
   import csr_utils_pkg::*;
+  import digestpp_dpi_pkg::*;
+  import dv_base_reg_pkg::*;
+  import dv_lib_pkg::*;
+  import dv_utils_pkg::*;
+  import flash_ctrl_pkg::*;
+  import jtag_riscv_agent_pkg::*;
+  import kmac_pkg::*;
+  import mem_bkdr_util_pkg::*;
+  import otp_ctrl_pkg::*;
+  import spi_agent_pkg::*;
+  import sram_ctrl_pkg::*;
+  import str_utils_pkg::*;
+  import sw_test_status_pkg::*;
   import tl_agent_pkg::*;
   import uart_agent_pkg::*;
-  import jtag_riscv_agent_pkg::*;
-  import spi_agent_pkg::*;
-  import dv_lib_pkg::*;
-  import cip_base_pkg::*;
-  import chip_ral_pkg::*;
-  import sw_test_status_pkg::*;
   import xbar_env_pkg::*;
-  import bus_params_pkg::*;
-  import str_utils_pkg::*;
-  import mem_bkdr_util_pkg::*;
 
   // macro includes
   `include "uvm_macros.svh"
diff --git a/hw/top_earlgrey/dv/env/seq_lib/chip_sw_lc_ctrl_transition_vseq.sv b/hw/top_earlgrey/dv/env/seq_lib/chip_sw_lc_ctrl_transition_vseq.sv
index 519e367..0a79741 100644
--- a/hw/top_earlgrey/dv/env/seq_lib/chip_sw_lc_ctrl_transition_vseq.sv
+++ b/hw/top_earlgrey/dv/env/seq_lib/chip_sw_lc_ctrl_transition_vseq.sv
@@ -7,6 +7,12 @@
 
   `uvm_object_new
 
+  // LC sends two 64-bit msg as input token.
+  localparam uint ExitTokenWidthBit  = kmac_pkg::MsgWidth * 2;
+  localparam uint ExitTokenWidthByte = ExitTokenWidthBit / 8;
+
+  rand bit [7:0] lc_exit_token[ExitTokenWidthByte];
+
   virtual task dut_init(string reset_kind = "HARD");
     bit [otp_ctrl_reg_pkg::TestUnlockTokenSize-1:0] rand_unlock_token;
     `DV_CHECK_STD_RANDOMIZE_FATAL(rand_unlock_token)
@@ -17,18 +23,40 @@
     cfg.mem_bkdr_util_h[Otp].otp_write_lc_partition(lc_ctrl_state_pkg::LcStTestUnlocked2);
 
     // Override the test exit token to match SW test's input token.
-    // TODO: randomize the exit_token.
     cfg.mem_bkdr_util_h[Otp].otp_write_secret0_partition(
         .unlock_token(rand_unlock_token),
-        .exit_token('h547070d7503264af5b9a971b894ef3be));
+        .exit_token(get_otp_exit_token(lc_exit_token)));
   endtask
 
+  // This function takes the token value from LC_CTRL token CSRs, then runs through cshake128 to
+  // get a 768-bit XORed token output.
+  // The first 128 bits of the decoded token should match the OTP's secret9 paritition's
+  // descrambled exit token value.
+  virtual function bit[ExitTokenWidthBit-1:0] get_otp_exit_token(
+      bit[7:0] token_in[ExitTokenWidthByte]);
+
+    bit [7:0]                      dpi_digest[kmac_pkg::AppDigestW/8];
+    bit [kmac_pkg::AppDigestW-1:0] digest_bits;
+
+    digestpp_dpi_pkg::c_dpi_cshake128(token_in, "", "LC_CTRL", ExitTokenWidthByte,
+                                      kmac_pkg::AppDigestW/8, dpi_digest);
+
+    digest_bits = {<< byte {dpi_digest}};
+    return (digest_bits[ExitTokenWidthBit-1:0]);
+  endfunction
+
   virtual task body();
+    byte lc_exit_token_byte [ExitTokenWidthByte];
     super.body();
 
-     // Select LC jtag.
+    // Select LC jtag.
     cfg.tap_straps_vif.drive(SelectLCJtagTap);
 
+    // Override the C test kLcExitToken with random data.
+    // TODO: try to remove this conversion variable, and use `bit[7:0]` array type as input.
+    foreach (lc_exit_token[i]) lc_exit_token_byte[i] = lc_exit_token[i];
+    sw_symbol_backdoor_overwrite("kLcExitToken", lc_exit_token_byte);
+
     // Wait for SW to finish set up LC_CTRL.
     cfg.clk_rst_vif.wait_clks(21000);
 
diff --git a/sw/device/tests/sim_dv/lc_ctrl_transition_test.c b/sw/device/tests/sim_dv/lc_ctrl_transition_test.c
index 6ec9087..4cf8c1e 100644
--- a/sw/device/tests/sim_dv/lc_ctrl_transition_test.c
+++ b/sw/device/tests/sim_dv/lc_ctrl_transition_test.c
@@ -21,9 +21,8 @@
 
 const test_config_t kTestConfig;
 
-// TODO: Issue more resets and andomize this array in each reset.
 // LC exit token value for LC state transition.
-static const uint8_t lc_exit_token[LC_TOKEN_SIZE] = {
+static volatile const uint8_t kLcExitToken[LC_TOKEN_SIZE] = {
     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
 };
@@ -75,7 +74,9 @@
     dif_lc_ctrl_token_t token;
     dif_lc_ctrl_settings_t settings;
     settings.clock_select = kDifLcCtrlInternalClockEn;
-    memcpy(token.data, lc_exit_token, sizeof(lc_exit_token));
+    for (int i = 0; i < LC_TOKEN_SIZE; i++) {
+      token.data[i] = kLcExitToken[i];
+    }
     CHECK(dif_lc_ctrl_mutex_try_acquire(&lc) == kDifLcCtrlMutexOk);
     CHECK(dif_lc_ctrl_transition(&lc, kDifLcCtrlStateDev, &token, &settings) ==
               kDifLcCtrlMutexOk,