[kmac] added life cycle escalation

 - Added life cycle escalation input port
 - Added dedicated error state for all FSMs

Signed-off-by: Michael Tempelmeier <michael.tempelmeier@gi-de.com>
diff --git a/hw/ip/kmac/data/kmac.hjson b/hw/ip/kmac/data/kmac.hjson
index 0cf6fcf..559b10e 100644
--- a/hw/ip/kmac/data/kmac.hjson
+++ b/hw/ip/kmac/data/kmac.hjson
@@ -148,6 +148,13 @@
       name:    "en_masking"
       act:     "req"
     }
+    { struct:  "lc_tx"
+      type:    "uni"
+      name:    "lc_escalate_en"
+      act:     "rcv"
+      default: "lc_ctrl_pkg::Off"
+      package: "lc_ctrl_pkg"
+    }
   ]
   countermeasures: [
     { name: "BUS.INTEGRITY",
diff --git a/hw/ip/kmac/dv/tb.sv b/hw/ip/kmac/dv/tb.sv
index 75c509b..f065b4c 100644
--- a/hw/ip/kmac/dv/tb.sv
+++ b/hw/ip/kmac/dv/tb.sv
@@ -63,6 +63,9 @@
     .alert_rx_i         (alert_rx ),
     .alert_tx_o         (alert_tx ),
 
+    // life cycle escalation input
+    .lc_escalate_en_i   (lc_ctrl_pkg::Off ),
+
     // KeyMgr sideload key interface
     .keymgr_key_i       (kmac_sideload_key),
 
diff --git a/hw/ip/kmac/kmac.core b/hw/ip/kmac/kmac.core
index 7b24c97..f057001 100644
--- a/hw/ip/kmac/kmac.core
+++ b/hw/ip/kmac/kmac.core
@@ -20,6 +20,8 @@
       - lowrisc:ip:edn_pkg
       - lowrisc:prim:edn_req
       - lowrisc:ip:kmac_pkg
+      - lowrisc:ip:lc_ctrl_pkg
+      - lowrisc:prim:lc_sync
     files:
       - rtl/kmac_reg_pkg.sv
       - rtl/kmac_reg_top.sv
diff --git a/hw/ip/kmac/rtl/kmac.sv b/hw/ip/kmac/rtl/kmac.sv
index 50db71c..b35ab13 100644
--- a/hw/ip/kmac/rtl/kmac.sv
+++ b/hw/ip/kmac/rtl/kmac.sv
@@ -59,6 +59,9 @@
   output edn_pkg::edn_req_t entropy_o,
   input  edn_pkg::edn_rsp_t entropy_i,
 
+  // Life cycle
+  input  lc_ctrl_pkg::lc_tx_t lc_escalate_en_i,
+
   // interrupts
   output logic intr_kmac_done_o,
   output logic intr_fifo_empty_o,
@@ -82,40 +85,43 @@
   // This state machine is to track the current process based on SW input and
   // KMAC operation.
   // Encoding generated with:
-  // $ ./util/design/sparse-fsm-encode.py -d 3 -m 5 -n 6 \
-  //      -s 4015776642 --language=sv
+  // $ ./util/design/sparse-fsm-encode.py -d 3 -m 6 -n 6 \
+  //      -s 1966361510 --language=sv
   //
   // Hamming distance histogram:
   //
   //  0: --
   //  1: --
   //  2: --
-  //  3: |||||||||||||||||||| (50.00%)
-  //  4: |||||||||||||||| (40.00%)
-  //  5: |||| (10.00%)
+  //  3: |||||||||||||||||||| (53.33%)
+  //  4: ||||||||||||||| (40.00%)
+  //  5: || (6.67%)
   //  6: --
   //
   // Minimum Hamming distance: 3
   // Maximum Hamming distance: 5
-  // Minimum Hamming weight: 1
+  // Minimum Hamming weight: 2
   // Maximum Hamming weight: 5
   //
   localparam int StateWidth = 6;
   typedef enum logic [StateWidth-1:0] {
     // Idle state
-    KmacIdle = 6'b001000,
+    KmacIdle = 6'b001011,
 
     // When software writes CmdStart @ KmacIdle and kmac_en, FSM moves to this
-    KmacPrefix = 6'b100110,
+    KmacPrefix = 6'b000110,
 
     // When SHA3 engine processes Key block, FSM moves to here.
-    KmacKeyBlock = 6'b111101,
+    KmacKeyBlock = 6'b111110,
 
     // Message Feed
-    KmacMsgFeed = 6'b010010,
+    KmacMsgFeed = 6'b010101,
 
     // Complete and squeeze
-    KmacDigest = 6'b100001
+    KmacDigest = 6'b101101,
+
+    // Error
+    KmacTerminalError = 6'b110000
 
   } kmac_st_e;
 
@@ -294,6 +300,9 @@
   logic alert_fatal, alert_recov_operation;
   logic alert_intg_err;
 
+  // Life cycle
+  lc_ctrl_pkg::lc_tx_t       lc_escalate_en;
+
   //////////////////////////////////////
   // Connecting Register IF to logics //
   //////////////////////////////////////
@@ -720,12 +729,23 @@
         end
       end
 
-      default: begin
+      KmacTerminalError: begin
         //this state is terminal
-        kmac_st_d = kmac_st;
+        kmac_st_d = KmacTerminalError;
+        kmac_state_error = 1'b 1;
+      end
+
+      default: begin
+        kmac_st_d = KmacTerminalError;
         kmac_state_error = 1'b 1;
       end
     endcase
+
+    // Unconditionally jump into the terminal error state
+    // if the life cycle controller triggers an escalation.
+    if (lc_escalate_en != lc_ctrl_pkg::Off) begin
+      kmac_st_d = KmacTerminalError;
+    end
   end
   `ASSERT_KNOWN(KmacStKnown_A, kmac_st)
 
@@ -767,6 +787,9 @@
     .done_i    (sha3_done           ),
     .process_o (kmac2sha3_process   ),
 
+    // LC escalation
+    .lc_escalate_en_i (lc_escalate_en),
+
     // Error detection
     .sparse_fsm_error_o (kmac_core_state_error),
     .key_index_error_o  (key_index_error)
@@ -804,6 +827,9 @@
     .run_i      (sha3_run         ),
     .done_i     (sha3_done        ),
 
+    // LC escalation
+    //.lc_escalate_en_i (lc_escalate_en),
+
     .absorbed_o  (sha3_absorbed),
     .squeezing_o (unused_sha3_squeeze),
 
@@ -946,6 +972,9 @@
     .sw_cmd_i (checked_sw_cmd),
     .cmd_o    (kmac_cmd),
 
+    // LC escalation
+    .lc_escalate_en_i (lc_escalate_en),
+
     // Error report
     .error_o            (app_err),
     .sparse_fsm_error_o (kmac_app_state_error)
@@ -1019,7 +1048,10 @@
     .sha3_absorbed_i(sha3_absorbed       ),
     .keccak_done_i  (sha3_block_processed),
 
-    .error_o           (errchecker_err),
+    // LC escalation
+    .lc_escalate_en_i (lc_escalate_en),
+
+    .error_o            (errchecker_err),
     .sparse_fsm_error_o (kmac_errchk_state_error)
   );
 
@@ -1089,6 +1121,9 @@
       .hash_cnt_clr_i   (entropy_hash_clr),
       .hash_threshold_i (entropy_hash_threshold),
 
+      // LC escalation
+      .lc_escalate_en_i (lc_escalate_en),
+
       // Error
       .err_o              (entropy_err),
       .sparse_fsm_error_o (kmac_entropy_state_error),
@@ -1238,6 +1273,16 @@
     );
   end
 
+  // Synchronize life cycle input
+  prim_lc_sync #(
+    .NumCopies (1)
+  ) u_prim_lc_sync (
+    .clk_i,
+    .rst_ni,
+    .lc_en_i ( lc_escalate_en_i ),
+    .lc_en_o ( lc_escalate_en   )
+  );
+
   assign en_masking_o = EnMasking;
 
   ////////////////
diff --git a/hw/ip/kmac/rtl/kmac_app.sv b/hw/ip/kmac/rtl/kmac_app.sv
index 0c1609a..59ef2c8 100644
--- a/hw/ip/kmac/rtl/kmac_app.sv
+++ b/hw/ip/kmac/rtl/kmac_app.sv
@@ -106,6 +106,9 @@
   // error_o value is pushed to Error FIFO at KMAC/SHA3 top and reported to SW
   output kmac_pkg::err_t error_o,
 
+  // Life cycle
+  input  lc_ctrl_pkg::lc_tx_t lc_escalate_en_i,
+
   output logic sparse_fsm_error_o
 );
 
@@ -155,7 +158,7 @@
   };
 
   // Encoding generated with:
-  // $ ./util/design/sparse-fsm-encode.py -d 3 -m 9 -n 10 \
+  // $ ./util/design/sparse-fsm-encode.py -d 3 -m 10 -n 10 \
   //      -s 155490773 --language=sv
   //
   // Hamming distance histogram:
@@ -163,17 +166,17 @@
   //  0: --
   //  1: --
   //  2: --
-  //  3: |||||||||| (16.67%)
-  //  4: |||||||||||||||||||| (30.56%)
-  //  5: |||||||||||||||| (25.00%)
-  //  6: ||||||||| (13.89%)
-  //  7: ||||||||| (13.89%)
-  //  8: --
+  //  3: |||||||||| (13.33%)
+  //  4: |||||||||||||||||||| (24.44%)
+  //  5: |||||||||||||||||||| (24.44%)
+  //  6: |||||||||||||| (17.78%)
+  //  7: |||||||||||||| (17.78%)
+  //  8: | (2.22%)
   //  9: --
   // 10: --
   //
   // Minimum Hamming distance: 3
-  // Maximum Hamming distance: 7
+  // Maximum Hamming distance: 8
   // Minimum Hamming weight: 2
   // Maximum Hamming weight: 9
   //
@@ -181,7 +184,7 @@
 
   // States
   typedef enum logic [StateWidth-1:0] {
-    StIdle = 10'b1011011010,
+    StIdle = 10'b0101110011,
 
     // Application operation.
     //
@@ -217,7 +220,10 @@
     // When KeyMgr operates, the secret key is not ready yet.
     StKeyMgrErrKeyNotValid = 10'b1001110100,
 
-    StError = 10'b1101011101
+    StError = 10'b1101011101,
+
+    // This state is used for terminal errors
+    StTerminalError = 10'b0010001001
   } st_e;
 
   /////////////
@@ -500,12 +506,23 @@
 
       end
 
-      default: begin
+      StTerminalError: begin
         // this state is terminal
         st_d = st;
         sparse_fsm_error_o = 1'b 1;
       end
+
+      default: begin
+        st_d = StTerminalError;
+        sparse_fsm_error_o = 1'b 1;
+      end
     endcase
+
+    // Unconditionally jump into the terminal error state
+    // if the life cycle controller triggers an escalation.
+    if (lc_escalate_en_i != lc_ctrl_pkg::Off) begin
+      st_d = StTerminalError;
+    end
   end
 
   if (SecIdleAcceptSwMsg != 1'b0) begin : gen_lint_err
diff --git a/hw/ip/kmac/rtl/kmac_core.sv b/hw/ip/kmac/rtl/kmac_core.sv
index dffd561..2e1c3de 100644
--- a/hw/ip/kmac/rtl/kmac_core.sv
+++ b/hw/ip/kmac/rtl/kmac_core.sv
@@ -49,6 +49,9 @@
   // Control to SHA3 core
   output logic process_o,
 
+  // Life cycle
+  input  lc_ctrl_pkg::lc_tx_t lc_escalate_en_i,
+
   output logic sparse_fsm_error_o,
   output logic key_index_error_o
 );
@@ -67,7 +70,7 @@
   /////////////////
 
   // Encoding generated with:
-  // $ ./util/design/sparse-fsm-encode.py -d 3 -m 4 -n 5 \
+  // $ ./util/design/sparse-fsm-encode.py -d 3 -m 5 -n 6 \
   //      -s 401658243 --language=sv
   //
   // Hamming distance histogram:
@@ -75,32 +78,36 @@
   //  0: --
   //  1: --
   //  2: --
-  //  3: |||||||||||||||||||| (66.67%)
-  //  4: |||||||||| (33.33%)
-  //  5: --
+  //  3: |||||||||||||||||||| (50.00%)
+  //  4: |||||||||||||||| (40.00%)
+  //  5: |||| (10.00%)
+  //  6: --
   //
   // Minimum Hamming distance: 3
-  // Maximum Hamming distance: 4
+  // Maximum Hamming distance: 5
   // Minimum Hamming weight: 1
   // Maximum Hamming weight: 4
   //
-  localparam int StateWidth = 5;
+  localparam int StateWidth = 6;
   typedef enum logic [StateWidth-1:0] {
-    StKmacIdle = 5'b01100,
+    StKmacIdle = 6'b011000,
 
     // Secret Key pushing stage
     // The key is sliced by prim_slicer. This state pushes the sliced data into
     // SHA3 hashing engine. When it hits the block size limit,
     // (same as in sha3pad) the state machine moves to Message.
-    StKey = 5'b01011,
+    StKey = 6'b010111,
 
     // Incoming Message
     // The core does nothing but forwarding the incoming message to SHA3 hashing
     // engine by turning off `en_kmac_datapath`.
-    StKmacMsg = 5'b10111,
+    StKmacMsg = 6'b001110,
 
     // Wait till done signal
-    StKmacFlush = 5'b10000
+    StKmacFlush = 6'b101011,
+
+    // Terminal Error
+    StTerminalError = 6'b100000
   } kmac_st_e ;
 
   /////////////
@@ -224,12 +231,24 @@
         end
       end
 
-      default: begin
+      StTerminalError: begin
         // this state is terminal
         st_d = st;
         sparse_fsm_error_o = 1'b 1;
       end
+
+      default: begin
+        // this state is terminal
+        st_d = StTerminalError;
+        sparse_fsm_error_o = 1'b 1;
+      end
     endcase
+
+    // Unconditionally jump into the terminal error state
+    // if the life cycle controller triggers an escalation.
+    if (lc_escalate_en_i != lc_ctrl_pkg::Off) begin
+      st_d = StTerminalError;
+    end
   end
 
   //////////////
diff --git a/hw/ip/kmac/rtl/kmac_entropy.sv b/hw/ip/kmac/rtl/kmac_entropy.sv
index 8c2f2e8..470a401 100644
--- a/hw/ip/kmac/rtl/kmac_entropy.sv
+++ b/hw/ip/kmac/rtl/kmac_entropy.sv
@@ -56,6 +56,9 @@
   input                                     hash_cnt_clr_i,
   input        [kmac_reg_pkg::HashCntW-1:0] hash_threshold_i,
 
+  // Life cycle
+  input  lc_ctrl_pkg::lc_tx_t lc_escalate_en_i,
+
   // Error output
   output err_t err_o,
   output logic sparse_fsm_error_o,
@@ -80,7 +83,7 @@
 
 
   // Encoding generated with:
-  // $ ./util/design/sparse-fsm-encode.py -d 3 -m 8 -n 10 \
+  // $ ./util/design/sparse-fsm-encode.py -d 3 -m 9 -n 10 \
   //      -s 507672272 --language=sv
   //
   // Hamming distance histogram:
@@ -88,13 +91,13 @@
   //  0: --
   //  1: --
   //  2: --
-  //  3: |||||||||| (14.29%)
-  //  4: |||||||||| (14.29%)
-  //  5: |||||||||||||||||||| (28.57%)
-  //  6: |||||||||||| (17.86%)
-  //  7: ||||||| (10.71%)
-  //  8: ||||||| (10.71%)
-  //  9: || (3.57%)
+  //  3: ||||||||||| (13.89%)
+  //  4: ||||||||||||||| (19.44%)
+  //  5: |||||||||||||||||||| (25.00%)
+  //  6: ||||||||||||||| (19.44%)
+  //  7: ||||||||||| (13.89%)
+  //  8: |||| (5.56%)
+  //  9: || (2.78%)
   // 10: --
   //
   // Minimum Hamming distance: 3
@@ -108,12 +111,12 @@
   typedef enum logic [StateWidth-1:0] {
     // Reset: Reset state. The entropy is not ready. The state machine should
     // get new entropy from EDN or the seed should be feeded by the software.
-    StRandReset = 10'b 1101110011,
+    StRandReset = 10'b1001111000,
 
     // The seed is fed into LFSR and the entropy is ready. It means the
     // rand_valid is asserted with valid data. It takes a few steps to reach
     // this state from StRandIdle.
-    StRandReady = 10'b 1001111000,
+    StRandReady = 10'b0110000100,
 
     // EDN interface: Send request and receive
     // RandEdnReq state can be transit from StRandReset or from StRandReady
@@ -131,28 +134,28 @@
     //        EdnReq to refresh seed
     //     3. If a KMAC operation is completed, the FSM also refreshes the LFSR
     //        seed to prepare next KMAC op or wipe out operation.
-    StRandEdn = 10'b 0110000100,
+    StRandEdn = 10'b1100100111,
 
     // Sw Seed: If mode is set to manual mode, This entropy module needs initial
     // seed from the software. It waits the seed update signal to expand initial
     // entropy
-    StSwSeedWait = 10'b 1100100111,
+    StSwSeedWait = 10'b1011110110,
 
     // Expand: The SW or EDN provides 64-bit entropy (seed). In this state, this
     // entropy generator expands the 64-bit entropy into 320-bit entropy using
     // LFSR. Then it expands 320-bit pseudo random entropy into 1600-bit by
     // replicating the PR entropy five times w/ compile-time shuffling scheme.
-    StRandExpand = 10'b 1011110110,
+    StRandExpand = 10'b0000001100,
 
     // ErrWaitExpired: If Edn timer expires, FSM moves to this state and wait
     // the software response. Software should switch to manual mode then disable
     // the timer (to 0) and update the seed via register interface.
-    StRandErrWaitExpired = 10'b 0000001100,
+    StRandErrWaitExpired = 10'b0001100011,
 
     // ErrNoValidMode: If SW sets entropy ready but the mode is not either
     // Manual Mode nor EdnMode, this logic reports to SW with
     // NoValidEntropyMode.
-    StRandErrIncorrectMode = 10'b 0001100011,
+    StRandErrIncorrectMode = 10'b1110010000,
 
     // Err: After the error is reported, FSM sits in Err state ignoring all the
     // requests. It does not generate new entropy and drops the entropy valid
@@ -162,7 +165,9 @@
     // clear the entropy ready signal before clear the error interrupt so that
     // the FSM sits in StRandReset state not moving forward with incorrect
     // configurations.
-    StRandErr = 10'b 1110010000
+    StRandErr = 10'b1000011110,
+
+    StTerminalError = 10'b0010011000
   } rand_st_e;
 
   /////////////
@@ -597,12 +602,23 @@
 
       end
 
-      default: begin
+      StTerminalError: begin
         // this state is terminal
         st_d = st;
         sparse_fsm_error_o = 1'b 1;
       end
+
+      default: begin
+        st_d = StTerminalError;
+        sparse_fsm_error_o = 1'b 1;
+      end
     endcase
+
+    // Unconditionally jump into the terminal error state
+    // if the life cycle controller triggers an escalation.
+    if (lc_escalate_en_i != lc_ctrl_pkg::Off) begin
+      st_d = StTerminalError;
+    end
   end
   `ASSERT_KNOWN(RandStKnown_A, st)
 
diff --git a/hw/ip/kmac/rtl/kmac_errchk.sv b/hw/ip/kmac/rtl/kmac_errchk.sv
index 071345e..0e92851 100644
--- a/hw/ip/kmac/rtl/kmac_errchk.sv
+++ b/hw/ip/kmac/rtl/kmac_errchk.sv
@@ -67,6 +67,9 @@
   input sha3_absorbed_i,
   input keccak_done_i,
 
+  // Life cycle
+  input  lc_ctrl_pkg::lc_tx_t lc_escalate_en_i,
+
   output err_t error_o,
   output logic sparse_fsm_error_o
 );
@@ -111,7 +114,8 @@
     StMsgFeed = 6'b110001,
     StProcessing = 6'b010110,
     StAbsorbed = 6'b100010,
-    StSqueezing = 6'b111100
+    StSqueezing = 6'b111100,
+    StTerminalError = 6'b011011
   } st_e;
   st_e st, st_d;
 
@@ -187,6 +191,11 @@
         end
       end
 
+      StTerminalError: begin
+        err_swsequence = 1'b 0;
+        sparse_fsm_error_o = 1'b 1;
+      end
+
       default: begin
         err_swsequence = 1'b 0;
         sparse_fsm_error_o = 1'b 1;
@@ -350,11 +359,22 @@
         end
       end
 
-      default: begin
+      StTerminalError: begin
         // this state is terminal
         st_d = st;
       end
+
+      default: begin
+        // this state is terminal
+        st_d = StTerminalError;
+      end
     endcase
+
+    // Unconditionally jump into the terminal error state
+    // if the life cycle controller triggers an escalation.
+    if (lc_escalate_en_i != lc_ctrl_pkg::Off) begin
+      st_d = StTerminalError;
+    end
   end : next_state
   `ASSERT_KNOWN(StKnown_A, st)
 
diff --git a/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson b/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson
index e3e6e2e..b10b85e 100644
--- a/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson
+++ b/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson
@@ -5148,6 +5148,18 @@
           index: -1
         }
         {
+          name: lc_escalate_en
+          struct: lc_tx
+          package: lc_ctrl_pkg
+          type: uni
+          act: rcv
+          width: 1
+          default: lc_ctrl_pkg::Off
+          inst_name: kmac
+          top_signame: lc_ctrl_lc_escalate_en
+          index: -1
+        }
+        {
           name: tl
           struct: tl
           package: tlul_pkg
@@ -7334,6 +7346,7 @@
       lc_ctrl.lc_escalate_en:
       [
         aes.lc_escalate_en
+        kmac.lc_escalate_en
         otbn.lc_escalate_en
         otp_ctrl.lc_escalate_en
         sram_ctrl_main.lc_escalate_en
@@ -16796,6 +16809,18 @@
         index: -1
       }
       {
+        name: lc_escalate_en
+        struct: lc_tx
+        package: lc_ctrl_pkg
+        type: uni
+        act: rcv
+        width: 1
+        default: lc_ctrl_pkg::Off
+        inst_name: kmac
+        top_signame: lc_ctrl_lc_escalate_en
+        index: -1
+      }
+      {
         name: tl
         struct: tl
         package: tlul_pkg
diff --git a/hw/top_earlgrey/data/top_earlgrey.hjson b/hw/top_earlgrey/data/top_earlgrey.hjson
index 22b9025..5db16df 100644
--- a/hw/top_earlgrey/data/top_earlgrey.hjson
+++ b/hw/top_earlgrey/data/top_earlgrey.hjson
@@ -881,6 +881,7 @@
       'lc_ctrl.lc_cpu_en'          : ['rv_core_ibex.lc_cpu_en'],
       'lc_ctrl.lc_keymgr_en'       : ['keymgr.lc_keymgr_en'],
       'lc_ctrl.lc_escalate_en'     : ['aes.lc_escalate_en',
+                                      'kmac.lc_escalate_en',
                                       'otbn.lc_escalate_en',
                                       'otp_ctrl.lc_escalate_en',
                                       'sram_ctrl_main.lc_escalate_en',
diff --git a/hw/top_earlgrey/rtl/autogen/top_earlgrey.sv b/hw/top_earlgrey/rtl/autogen/top_earlgrey.sv
index 8fdee10..461efb4 100644
--- a/hw/top_earlgrey/rtl/autogen/top_earlgrey.sv
+++ b/hw/top_earlgrey/rtl/autogen/top_earlgrey.sv
@@ -2204,6 +2204,7 @@
       .entropy_i(edn0_edn_rsp[3]),
       .idle_o(clkmgr_aon_idle[2]),
       .en_masking_o(kmac_en_masking),
+      .lc_escalate_en_i(lc_ctrl_lc_escalate_en),
       .tl_i(kmac_tl_req),
       .tl_o(kmac_tl_rsp),