[dv/chip] Make lc_transition task more generic

This PR enhance the jtag_lc_state_transition task to includes
transitions from:
1). Raw -> any valid states
2). Testlock -> any valid states

Signed-off-by: Cindy Chen <chencindy@opentitan.org>
diff --git a/hw/top_earlgrey/dv/env/chip_env_pkg.sv b/hw/top_earlgrey/dv/env/chip_env_pkg.sv
index 66c198a..b5d5eba 100644
--- a/hw/top_earlgrey/dv/env/chip_env_pkg.sv
+++ b/hw/top_earlgrey/dv/env/chip_env_pkg.sv
@@ -58,6 +58,11 @@
   parameter bit [TL_AW-1:0] SW_DV_TEST_STATUS_ADDR  = SW_DV_START_ADDR + 0;
   parameter bit [TL_AW-1:0] SW_DV_LOG_ADDR          = SW_DV_START_ADDR + 4;
 
+  // LC token paramters
+  // LC sends two 64-bit msg as input token.
+  localparam uint TokenWidthBit  = kmac_pkg::MsgWidth * 2;
+  localparam uint TokenWidthByte = TokenWidthBit / 8;
+
   typedef virtual pins_if #(NUM_GPIOS)  gpio_vif;
   typedef virtual sw_logger_if          sw_logger_vif;
   typedef virtual sw_test_status_if     sw_test_status_vif;
diff --git a/hw/top_earlgrey/dv/env/seq_lib/chip_sw_base_vseq.sv b/hw/top_earlgrey/dv/env/seq_lib/chip_sw_base_vseq.sv
index b43bd09..871194d 100644
--- a/hw/top_earlgrey/dv/env/seq_lib/chip_sw_base_vseq.sv
+++ b/hw/top_earlgrey/dv/env/seq_lib/chip_sw_base_vseq.sv
@@ -351,25 +351,93 @@
     cfg.m_jtag_riscv_agent_cfg.allow_errors = 0;
   endtask
 
-  // Use JTAG interface to transit LC_CTRL from RAW state to the valid next state.
-  virtual task lc_raw_state_transition(dec_lc_state_e dest_state);
-    if (!(dest_state inside {DecLcStTestUnlocked0, DecLcStTestUnlocked1, DecLcStTestUnlocked2,
-                             DecLcStTestUnlocked3, DecLcStTestUnlocked4, DecLcStTestUnlocked5,
-                             DecLcStTestUnlocked6, DecLcStScrap})) begin
-      `uvm_fatal(`gfn, $sformatf("invalid state transition request from RAW state to %0s",
-                                 dest_state.name))
+  // Use JTAG interface to transit LC_CTRL from one state to the valid next state.
+  // Currently support the following transitions:
+  // 1). RAW state -> test unlock state N
+  //     This transition will use default raw unlock token.
+  // 2). Test lock state N -> test unlock state N+1
+  //     This transition requires user to input the correct test unlock token.
+  virtual task jtag_lc_state_transition(dec_lc_state_e src_state,
+                                        dec_lc_state_e dest_state,
+                                        bit [TokenWidthBit-1:0] test_unlock_token = 0);
+    bit [TL_DW-1:0] actual_src_state;
+    bit valid_transition;
+    jtag_riscv_agent_pkg::jtag_read_csr(ral.lc_ctrl.lc_state.get_offset(),
+                                        p_sequencer.jtag_sequencer_h,
+                                        actual_src_state);
+    `DV_CHECK_EQ({DecLcStateNumRep{src_state}}, actual_src_state)
+
+    // Check if the requested transition is valid.
+    case (src_state)
+      DecLcStRaw: begin
+        if (dest_state inside {DecLcStTestUnlocked0, DecLcStTestUnlocked1, DecLcStTestUnlocked2,
+                               DecLcStTestUnlocked3, DecLcStTestUnlocked4, DecLcStTestUnlocked5,
+                               DecLcStTestUnlocked6, DecLcStTestUnlocked7, DecLcStScrap}) begin
+          valid_transition = 1;
+          test_unlock_token = RndCnstRawUnlockToken;
+        end
+      end
+      DecLcStTestLocked0: begin
+        if (dest_state inside {DecLcStTestUnlocked1, DecLcStTestUnlocked2, DecLcStTestUnlocked3,
+                               DecLcStTestUnlocked4, DecLcStTestUnlocked5, DecLcStTestUnlocked6,
+                               DecLcStTestUnlocked7, DecLcStScrap}) begin
+          valid_transition = 1;
+        end
+      end
+      DecLcStTestLocked1: begin
+        if (dest_state inside {DecLcStTestUnlocked2, DecLcStTestUnlocked3, DecLcStTestUnlocked4,
+                               DecLcStTestUnlocked5, DecLcStTestUnlocked6,DecLcStTestUnlocked7,
+                               DecLcStScrap}) begin
+          valid_transition = 1;
+        end
+      end
+      DecLcStTestLocked2: begin
+        if (dest_state inside {DecLcStTestUnlocked3, DecLcStTestUnlocked4, DecLcStTestUnlocked5,
+                               DecLcStTestUnlocked6, DecLcStTestUnlocked7, DecLcStScrap}) begin
+          valid_transition = 1;
+        end
+      end
+      DecLcStTestLocked3: begin
+        if (dest_state inside {DecLcStTestUnlocked4, DecLcStTestUnlocked5, DecLcStTestUnlocked6,
+                               DecLcStTestUnlocked7, DecLcStScrap}) begin
+          valid_transition = 1;
+        end
+      end
+      DecLcStTestLocked4: begin
+        if (dest_state inside {DecLcStTestUnlocked5, DecLcStTestUnlocked6, DecLcStTestUnlocked7,
+                               DecLcStScrap}) begin
+          valid_transition = 1;
+        end
+      end
+      DecLcStTestLocked5: begin
+        if (dest_state inside {DecLcStTestUnlocked6, DecLcStTestUnlocked7, DecLcStScrap}) begin
+          valid_transition = 1;
+        end
+      end
+       DecLcStTestLocked6: begin
+        if (dest_state inside {DecLcStTestUnlocked7, DecLcStScrap}) valid_transition = 1;
+      end
+     default: `uvm_fatal(`gfn, $sformatf("%0s src state not supported", src_state.name))
+    endcase
+
+    if (!valid_transition) begin
+      `uvm_fatal(`gfn, $sformatf("invalid state transition request from %0s state to %0s",
+                                 src_state.name, dest_state.name))
     end
 
-    `uvm_info(`gfn, "Start LC transition request to TestUnlock state", UVM_LOW)
+    `uvm_info(`gfn, $sformatf("Start LC transition request from %0s staet to %0s state",
+                              src_state.name, dest_state.name), UVM_LOW)
     jtag_riscv_agent_pkg::jtag_write_csr(ral.lc_ctrl.claim_transition_if.get_offset(),
                                          p_sequencer.jtag_sequencer_h,
                                          prim_mubi_pkg::MuBi8True);
+
+    // Write LC state transition token.
     begin
-      bit [TL_DW-1:0] raw_unlock_token_csr_vals[4] = {<< 32 {{>> 8 {RndCnstRawUnlockToken}}}};
-      foreach (raw_unlock_token_csr_vals[index]) begin
+      bit [TL_DW-1:0] token_csr_vals[4] = {<< 32 {{>> 8 {test_unlock_token}}}};
+      foreach (token_csr_vals[index]) begin
         jtag_riscv_agent_pkg::jtag_write_csr(ral.lc_ctrl.transition_token[index].get_offset(),
                                              p_sequencer.jtag_sequencer_h,
-                                             raw_unlock_token_csr_vals[index]);
+                                             token_csr_vals[index]);
       end
     end
 
@@ -382,5 +450,7 @@
     `uvm_info(`gfn, "Sent LC transition request", UVM_LOW)
 
     wait_lc_status(LcTransitionSuccessful);
+    `uvm_info(`gfn, "LC transition request succeed!", UVM_LOW)
   endtask
+
 endclass : chip_sw_base_vseq
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 4b92c27..35daf9c 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,10 +7,6 @@
 
   `uvm_object_new
 
-  // LC sends two 64-bit msg as input token.
-  localparam uint TokenWidthBit  = kmac_pkg::MsgWidth * 2;
-  localparam uint TokenWidthByte = TokenWidthBit / 8;
-
   rand bit [7:0] lc_exit_token[TokenWidthByte];
   rand bit [7:0] lc_unlock_token[TokenWidthByte];
 
@@ -80,28 +76,7 @@
       // error. This error is permitted and can be ignored.
       wait_lc_ready(.allow_err(1));
 
-      // Use JTAG interface to transit LC_CTRL from TestLock to TestUnlock state.
-      `uvm_info(`gfn, "Start LC transition request to TestUnlock state", UVM_LOW)
-      jtag_riscv_agent_pkg::jtag_write_csr(ral.lc_ctrl.claim_transition_if.get_offset(),
-                                           p_sequencer.jtag_sequencer_h,
-                                           prim_mubi_pkg::MuBi8True);
-      begin
-        bit [TL_DW-1:0] unlock_token_csr_vals[4] = {<< 32 {{<< 8 {lc_unlock_token}}}};
-        foreach (unlock_token_csr_vals[index]) begin
-          jtag_riscv_agent_pkg::jtag_write_csr(ral.lc_ctrl.transition_token[index].get_offset(),
-                                               p_sequencer.jtag_sequencer_h,
-                                               unlock_token_csr_vals[index]);
-        end
-      end
-      jtag_riscv_agent_pkg::jtag_write_csr(ral.lc_ctrl.transition_target.get_offset(),
-                                           p_sequencer.jtag_sequencer_h,
-                                           {DecLcStateNumRep{DecLcStTestUnlocked2}});
-      jtag_riscv_agent_pkg::jtag_write_csr(ral.lc_ctrl.transition_cmd.get_offset(),
-                                           p_sequencer.jtag_sequencer_h,
-                                           1);
-      `uvm_info(`gfn, "Sent LC transition request", UVM_LOW)
-
-      wait_lc_status(LcTransitionSuccessful);
+      jtag_lc_state_transition(DecLcStTestLocked1, DecLcStTestUnlocked2, {<<8{lc_unlock_token}});
 
       // LC state transition requires a chip reset.
       apply_reset();