[dv/lc_ctrl] randomize otp_ctrl if's token input

This PR support randomize otp_ctrl interface's token input by:
1. Remove the hardcoded 0 that tied to token decode, and use push-pull
agent.
2. Constraint the decoded token by checking the state transition.

Signed-off-by: Cindy Chen <chencindy@google.com>
diff --git a/hw/ip/lc_ctrl/dv/env/lc_ctrl_env_cfg.sv b/hw/ip/lc_ctrl/dv/env/lc_ctrl_env_cfg.sv
index 240cf42..4aed5df 100644
--- a/hw/ip/lc_ctrl/dv/env/lc_ctrl_env_cfg.sv
+++ b/hw/ip/lc_ctrl/dv/env/lc_ctrl_env_cfg.sv
@@ -36,8 +36,10 @@
                                  .HostDataWidth(lc_ctrl_state_pkg::LcTokenWidth))
         ::type_id::create("m_otp_token_pull_agent_cfg");
     `DV_CHECK_RANDOMIZE_FATAL(m_otp_token_pull_agent_cfg)
-    m_otp_token_pull_agent_cfg.agent_type = PullAgent;
-    m_otp_token_pull_agent_cfg.if_mode    = Device;
+    m_otp_token_pull_agent_cfg.agent_type                 = PullAgent;
+    m_otp_token_pull_agent_cfg.if_mode                    = Device;
+    m_otp_token_pull_agent_cfg.in_bidirectional_mode      = 1;
+    m_otp_token_pull_agent_cfg.hold_d_data_until_next_req = 1;
 
     m_esc_wipe_secrets_agent_cfg = alert_esc_agent_cfg::type_id::create(
         "m_esc_wipe_secrets_agent_cfg");
diff --git a/hw/ip/lc_ctrl/dv/env/lc_ctrl_if.sv b/hw/ip/lc_ctrl/dv/env/lc_ctrl_if.sv
index 3c777ba..0c7a684 100644
--- a/hw/ip/lc_ctrl/dv/env/lc_ctrl_if.sv
+++ b/hw/ip/lc_ctrl/dv/env/lc_ctrl_if.sv
@@ -44,9 +44,9 @@
     otp_i.error = 0;
     otp_i.state = lc_state;
     otp_i.count = lc_cnt;
-    otp_i.test_unlock_token = 0;
-    otp_i.test_exit_token = 0;
-    otp_i.rma_token = 0;
+    otp_i.test_unlock_token = $urandom();
+    otp_i.test_exit_token = $urandom();
+    otp_i.rma_token = $urandom();
     otp_i.id_state = LcIdBlank;
 
     otp_hw_cfg_i.valid = Off;
@@ -54,7 +54,6 @@
 
     clk_byp_ack_i = clk_byp_ack;
     flash_rma_ack_i = flash_rma_ack;
-    hashed_token = '0;
   endtask
 
   task automatic set_clk_byp_ack(lc_tx_t val);
@@ -65,7 +64,4 @@
     flash_rma_ack_i = val;
   endtask
 
-  task automatic set_hashed_token(lc_token_t val);
-    hashed_token = val;
-  endtask
 endinterface
diff --git a/hw/ip/lc_ctrl/dv/env/seq_lib/lc_ctrl_smoke_vseq.sv b/hw/ip/lc_ctrl/dv/env/seq_lib/lc_ctrl_smoke_vseq.sv
index 27e4771..2e9d693 100644
--- a/hw/ip/lc_ctrl/dv/env/seq_lib/lc_ctrl_smoke_vseq.sv
+++ b/hw/ip/lc_ctrl/dv/env/seq_lib/lc_ctrl_smoke_vseq.sv
@@ -47,10 +47,8 @@
         randomize_next_lc_state(dec_lc_state(lc_state));
         `uvm_info(`gfn, $sformatf("next_LC_state is %0s, input token is %0h", next_lc_state.name,
                                   token_val), UVM_DEBUG)
-        if (lc_state == LcStRaw && next_lc_state inside {DecLcStTestUnlocked0,
-            DecLcStTestUnlocked1, DecLcStTestUnlocked2, DecLcStTestUnlocked3}) begin
-          cfg.lc_ctrl_vif.set_hashed_token(lc_ctrl_state_pkg::RndCnstRawUnlockTokenHashed);
-        end
+
+        set_hashed_token();
         sw_transition_req(next_lc_state, token_val);
       end else begin
         // wait at least two clks for scb to finish checking lc outputs
@@ -76,4 +74,30 @@
     end
   endfunction
 
+  virtual function void set_hashed_token();
+    // Raw Token
+    if (lc_state == LcStRaw && next_lc_state inside {DecLcStTestUnlocked0,
+        DecLcStTestUnlocked1, DecLcStTestUnlocked2, DecLcStTestUnlocked3}) begin
+      cfg.m_otp_token_pull_agent_cfg.add_d_user_data(
+          lc_ctrl_state_pkg::RndCnstRawUnlockTokenHashed);
+    // RMA Token
+    end else if (lc_state inside {LcStProd, LcStDev} && next_lc_state == DecLcStRma) begin
+      cfg.m_otp_token_pull_agent_cfg.add_d_user_data(cfg.lc_ctrl_vif.otp_i.rma_token);
+    // Test Exit Token
+    end else if (lc_state inside {LcStTestUnlocked3, LcStTestLocked2, LcStTestUnlocked2,
+                 LcStTestLocked1, LcStTestUnlocked1, LcStTestLocked0, LcStTestUnlocked0} &&
+                 next_lc_state inside {DecLcStDev, DecLcStProd, DecLcStProdEnd}) begin
+      cfg.m_otp_token_pull_agent_cfg.add_d_user_data(cfg.lc_ctrl_vif.otp_i.test_exit_token);
+    // Test Unlock Token
+    end else if ((lc_state == LcStTestLocked2 && next_lc_state == DecLcStTestUnlocked3) ||
+                 (lc_state == LcStTestLocked1 && next_lc_state inside
+                  {DecLcStTestUnlocked3, DecLcStTestUnlocked2}) ||
+                 (lc_state == LcStTestLocked0 && next_lc_state inside
+                  {DecLcStTestUnlocked3, DecLcStTestUnlocked2, DecLcStTestUnlocked1})) begin
+      cfg.m_otp_token_pull_agent_cfg.add_d_user_data(cfg.lc_ctrl_vif.otp_i.test_unlock_token);
+    // Test Zero Token
+    end else begin
+      cfg.m_otp_token_pull_agent_cfg.add_d_user_data(0);
+    end
+  endfunction
 endclass : lc_ctrl_smoke_vseq
diff --git a/hw/ip/lc_ctrl/dv/tb.sv b/hw/ip/lc_ctrl/dv/tb.sv
index 99c577f..d68ef21 100644
--- a/hw/ip/lc_ctrl/dv/tb.sv
+++ b/hw/ip/lc_ctrl/dv/tb.sv
@@ -18,8 +18,6 @@
   wire clk, rst_n;
   wire devmode;
   wire [LcPwrIfWidth-1:0] pwr_lc;
-  // TODO: can delete once push-pull agent support constraint data
-  wire otp_ctrl_pkg::lc_otp_token_rsp_t   otp_token_rsp;
 
   // interfaces
   clk_rst_if   clk_rst_if(.clk(clk), .rst_n(rst_n));
@@ -37,10 +35,6 @@
 
   `DV_ALERT_IF_CONNECT
 
-  assign otp_token_rsp.ack = otp_token_if.ack;
-  // TODO: temp constraint to 0 because it has to equal to otp_lc_data_i tokens
-  assign otp_token_rsp.hashed_token = lc_ctrl_if.hashed_token;
-
   // dut
   lc_ctrl dut (
     .clk_i                      (clk      ),
@@ -67,7 +61,7 @@
     .lc_otp_program_i           ({otp_prog_if.d_data, otp_prog_if.ack}),
 
     .lc_otp_token_o             ({otp_token_if.req, otp_token_if.h_data}),
-    .lc_otp_token_i             (otp_token_rsp),
+    .lc_otp_token_i             ({ otp_token_if.ack, otp_token_if.d_data}),
 
     .otp_lc_data_i              (lc_ctrl_if.otp_i),