[keymgr/dv] Add sideload key check
1. Add sideload key check in interface in order to check the duration as
well
2. create a `get_err_code` function and simpilfy some logic in scb
3. store generated meaningful key in interface to compare with invalid
keys generated by error cases
4. fix some typos in cfgen_vseq and lc_disable_vseq
Signed-off-by: Weicai Yang <weicai@google.com>
diff --git a/hw/ip/keymgr/dv/env/keymgr_env.core b/hw/ip/keymgr/dv/env/keymgr_env.core
index 1dbfc73..00c41f8 100644
--- a/hw/ip/keymgr/dv/env/keymgr_env.core
+++ b/hw/ip/keymgr/dv/env/keymgr_env.core
@@ -11,8 +11,8 @@
- lowrisc:dv:cip_lib
- lowrisc:dv:keymgr_kmac_agent
files:
- - keymgr_if.sv
- keymgr_env_pkg.sv
+ - keymgr_if.sv
- keymgr_env_cfg.sv: {is_include_file: true}
- keymgr_env_cov.sv: {is_include_file: true}
- keymgr_virtual_sequencer.sv: {is_include_file: true}
diff --git a/hw/ip/keymgr/dv/env/keymgr_env_pkg.sv b/hw/ip/keymgr/dv/env/keymgr_env_pkg.sv
index 9f1a494..7e3652a 100644
--- a/hw/ip/keymgr/dv/env/keymgr_env_pkg.sv
+++ b/hw/ip/keymgr/dv/env/keymgr_env_pkg.sv
@@ -24,6 +24,7 @@
parameter uint DIGEST_SHARE_WORD_NUM = keymgr_pkg::KeyWidth / TL_DW;
typedef virtual keymgr_if keymgr_vif;
+ typedef bit [keymgr_pkg::Shares-1:0][keymgr_pkg::KeyWidth-1:0] key_shares_t;
typedef enum {
IntrOpDone,
NumKeyMgrIntr
diff --git a/hw/ip/keymgr/dv/env/keymgr_if.sv b/hw/ip/keymgr/dv/env/keymgr_if.sv
index 35fbc3c..cc511b4 100644
--- a/hw/ip/keymgr/dv/env/keymgr_if.sv
+++ b/hw/ip/keymgr/dv/env/keymgr_if.sv
@@ -17,12 +17,25 @@
keymgr_pkg::hw_key_req_t hmac_key;
keymgr_pkg::hw_key_req_t aes_key;
- keymgr_pkg::hw_key_req_t kmac_key_exp;
- keymgr_pkg::hw_key_req_t hmac_key_exp;
- keymgr_pkg::hw_key_req_t aes_key_exp;
+ keymgr_pkg::hw_key_req_t kmac_key_exp = '0;
+ keymgr_pkg::hw_key_req_t hmac_key_exp = '0;
+ keymgr_pkg::hw_key_req_t aes_key_exp = '0;
- // indicate keymgr entered disabled directly. kmac_key are wiped, don't check output it
- bit direct_to_disabled;
+ // connect KDF interface for assertion check
+ wire keymgr_pkg::kmac_data_req_t kmac_data_req;
+ wire keymgr_pkg::kmac_data_rsp_t kmac_data_rsp;
+
+ // indicate if check the key is same as expected or shouldn't match to any meaningful key
+ bit is_kmac_key_good = 0;
+ bit is_hmac_key_good = 0;
+ bit is_aes_key_good = 0;
+
+ // when kmac sideload key is generated, kmac may be used to do other OP, but once the OP is done,
+ // it should automatically switch back to sideload key
+ bit is_kmac_sideload_avail = 0;
+ keymgr_env_pkg::key_shares_t kmac_sideload_key_shares;
+
+ keymgr_env_pkg::key_shares_t keys_a_array[string][string];
string msg_id = "keymgr_if";
@@ -31,7 +44,7 @@
// the key manager comes out of reset.
// The power/reset manager ensures that
// this sequencing is correct.
- keymgr_en = lc_ctrl_pkg::Off;
+ keymgr_en = lc_ctrl_pkg::lc_tx_t'($urandom);
// async delay as these signals are from different clock domain
#($urandom_range(1000, 0) * 1ns);
@@ -40,7 +53,6 @@
otp_hw_cfg.data.device_id = 'hF0F0;
otp_key = otp_ctrl_pkg::OTP_KEYMGR_KEY_DEFAULT;
flash = flash_ctrl_pkg::KEYMGR_FLASH_DEFAULT;
- direct_to_disabled = 0;
endtask
// randomize otp, lc, flash input data
@@ -74,35 +86,105 @@
flash = local_flash;
endtask
- task automatic update_exp_key(bit [keymgr_pkg::Shares-1:0][keymgr_pkg::KeyWidth-1:0] key_shares,
- keymgr_pkg::keymgr_key_dest_e dest = keymgr_pkg::Kmac);
+ // update kmac key for comparison during KDF
+ function automatic void update_kdf_key(keymgr_env_pkg::key_shares_t key_shares,
+ keymgr_pkg::keymgr_working_state_e state,
+ bit good_key = 1);
+
+ kmac_key_exp <= '{1'b1, key_shares[0], key_shares[1]};
+ is_kmac_key_good = good_key;
+ endfunction
+
+ // store internal key once it's available and use to compare if future OP is invalid
+ function automatic void store_internal_key(keymgr_env_pkg::key_shares_t key_shares,
+ keymgr_pkg::keymgr_working_state_e state);
+
+ keys_a_array[state.name]["Internal"] = key_shares;
+ endfunction
+
+ // update sideload key for comparison
+ // if it's good key, store it to compare for future invalid OP
+ function automatic void update_sideload_key(keymgr_env_pkg::key_shares_t key_shares,
+ keymgr_pkg::keymgr_working_state_e state,
+ keymgr_pkg::keymgr_key_dest_e dest = keymgr_pkg::Kmac,
+ bit good_key = 1);
case (dest)
keymgr_pkg::Kmac: begin
- kmac_key_exp = '{1'b1, key_shares[0], key_shares[1]};
+ kmac_key_exp <= '{1'b1, key_shares[0], key_shares[1]};
+ is_kmac_key_good <= good_key;
+ is_kmac_sideload_avail <= 1;
+ kmac_sideload_key_shares <= key_shares;
end
keymgr_pkg::Hmac: begin
- hmac_key_exp = '{1'b1, key_shares[0], key_shares[1]};
+ hmac_key_exp <= '{1'b1, key_shares[0], key_shares[1]};
+ is_hmac_key_good <= good_key;
end
keymgr_pkg::Aes: begin
- aes_key_exp = '{1'b1, key_shares[0], key_shares[1]};
+ aes_key_exp <= '{1'b1, key_shares[0], key_shares[1]};
+ is_aes_key_good <= good_key;
end
default: `uvm_fatal("keymgr_if", $sformatf("Unexpect dest type %0s", dest.name))
endcase
- endtask
- task automatic enter_disabled_directly();
- direct_to_disabled = 1;
- endtask
- // TODO kmac_key only last until done signal is set. Fix this later
- //`ASSERT(KmacKeyStable, $stable(kmac_key_exp) && $stable(direct_to_disabled) |=> $stable(kmac_key),
- // clk, !rst_n)
- //`ASSERT(KmacKeyUpdate, !$stable(kmac_key_exp) |=> kmac_key == kmac_key_exp,
- // clk, !rst_n && !direct_to_disabled)
+ if (good_key) keys_a_array[state.name][dest.name] = key_shares;
+ endfunction
- `ASSERT(HmacKeyStable, $stable(hmac_key_exp) |=> $stable(hmac_key), clk, !rst_n)
- `ASSERT(HmacKeyUpdate, !$stable(hmac_key_exp) |=> hmac_key == hmac_key_exp, clk, !rst_n)
+ // if kmac sideload key is available, switch to it after an operation is completed
+ // if not available, de-assert valid after done is asserted
+ initial begin
+ forever begin
+ @(posedge clk);
+ if (kmac_data_rsp.done) begin
+ if (is_kmac_sideload_avail) begin
+ kmac_key_exp <= '{1'b1, kmac_sideload_key_shares[0], kmac_sideload_key_shares[1]};
+ is_kmac_key_good <= 1;
+ end else begin
+ kmac_key_exp.valid <= 0;
+ end
+ end // kmac_data_rsp.done
+ end // forever
+ end
- `ASSERT(AesKeyStable, $stable(aes_key_exp) |=> $stable(aes_key), clk, !rst_n)
- `ASSERT(AesKeyUpdate, !$stable(aes_key_exp) |=> aes_key == aes_key_exp, clk, !rst_n)
+ // check if key is invalid, it should not match to any of the meaningful keys
+ initial begin
+ fork
+ forever begin
+ @(posedge clk);
+ if (!is_kmac_key_good) check_invalid_key(kmac_key, "KMAC");
+ end
+ forever begin
+ @(posedge clk);
+ if (!is_hmac_key_good) check_invalid_key(hmac_key, "HMAC");
+ end
+ forever begin
+ @(posedge clk);
+ if (!is_aes_key_good) check_invalid_key(aes_key, "AES");
+ end
+ join
+ end
+ function automatic void check_invalid_key(keymgr_pkg::hw_key_req_t act_key, string key_name);
+ if (rst_n && act_key.valid) begin
+ foreach (keys_a_array[i, j]) begin
+ `DV_CHECK_NE({act_key.key_share1, act_key.key_share0}, keys_a_array[i][j],
+ $sformatf("%s key at state %s from %s", key_name, i, j), , msg_id)
+ end
+ end
+ endfunction
+
+ `define KM_ASSERT(NAME, SEQ) \
+ `ASSERT(NAME, SEQ, clk, !rst_n || keymgr_en != lc_ctrl_pkg::On)
+
+ `KM_ASSERT(CheckKmacKey, is_kmac_key_good && kmac_key_exp.valid -> kmac_key == kmac_key_exp)
+
+ `KM_ASSERT(CheckKmacKeyValid, kmac_key_exp.valid == kmac_key.valid)
+
+ // TODO update hmac and aes checker later
+ //`KM_ASSERT(HmacKeyStable, $stable(hmac_key_exp) |=> $stable(hmac_key))
+ //`KM_ASSERT(HmacKeyUpdate, !$stable(hmac_key_exp) |=> hmac_key == hmac_key_exp)
+
+ //`KM_ASSERT(AesKeyStable, $stable(aes_key_exp) |=> $stable(aes_key))
+ //`KM_ASSERT(AesKeyUpdate, !$stable(aes_key_exp) |=> aes_key == aes_key_exp)
+
+ `undef KM_ASSERT
endinterface
diff --git a/hw/ip/keymgr/dv/env/keymgr_scoreboard.sv b/hw/ip/keymgr/dv/env/keymgr_scoreboard.sv
index abd0fb8..21d3119 100644
--- a/hw/ip/keymgr/dv/env/keymgr_scoreboard.sv
+++ b/hw/ip/keymgr/dv/env/keymgr_scoreboard.sv
@@ -44,7 +44,7 @@
keymgr_pkg::keymgr_op_status_e current_op_status;
// HW internal key, used for OP in current state
- bit [keymgr_pkg::Shares-1:0][keymgr_pkg::KeyWidth-1:0] current_internal_key;
+ key_shares_t current_internal_key;
// preserve value at TL read address phase and compare it at read data phase
keymgr_pkg::keymgr_op_status_e addr_phase_op_status;
@@ -60,9 +60,6 @@
bit [keymgr_pkg::AdvDataWidth-1:0] adv_data_a_array[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];
- bit [keymgr_pkg::Shares-1:0][keymgr_pkg::KeyWidth-1:0]
- internal_key_a_array[keymgr_pkg::keymgr_working_state_e];
`uvm_component_new
@@ -106,6 +103,8 @@
// there must be a OP which causes the KMAC data req
`DV_CHECK_EQ(current_op_status, keymgr_pkg::OpWip)
+ if (cfg.keymgr_vif.keymgr_en != lc_ctrl_pkg::On) return;
+
case (op)
keymgr_pkg::OpAdvance: begin
case (current_state)
@@ -142,10 +141,10 @@
case (update_result)
UpdateInternalKey: begin
- `uvm_info(`gfn, $sformatf("Keymgr State from %0s to %0s", current_state.name,
- get_next_state(current_state)), UVM_LOW)
current_internal_key = {item.rsp_digest_share1, item.rsp_digest_share0};
- internal_key_a_array[current_state] = current_internal_key;
+ cfg.keymgr_vif.store_internal_key(current_internal_key, current_state);
+ `uvm_info(`gfn, $sformatf("Update internal key 0x%0h for state %s", current_internal_key,
+ current_state.name), UVM_MEDIUM)
end
UpdateSwOut: begin
bit [keymgr_pkg::Shares-1:0][DIGEST_SHARE_WORD_NUM-1:0][TL_DW-1:0] sw_share_output;
@@ -159,8 +158,17 @@
`uvm_info(`gfn, $sformatf("Predict %0s = 0x%0h", csr_name, sw_share_output[i][j]),
UVM_MEDIUM)
end
- // TODO
- UpdateHwOut: begin
+ end
+ UpdateHwOut: begin
+ key_shares_t key_shares = {item.rsp_digest_share1, item.rsp_digest_share0};
+ bit good_key = (get_err_code() == 0);
+ keymgr_pkg::keymgr_key_dest_e dest = keymgr_pkg::keymgr_key_dest_e'(
+ `gmv(ral.control.dest_sel));
+
+ if (dest != keymgr_pkg::None) begin
+ cfg.keymgr_vif.update_sideload_key(key_shares, current_state, dest, good_key);
+ `uvm_info(`gfn, $sformatf("Update sideload key 0x%0h for %s", key_shares, dest.name),
+ UVM_MEDIUM)
end
end
default: `uvm_info(`gfn, "KMAC result isn't updated to any output", UVM_MEDIUM)
@@ -170,55 +178,47 @@
void'(ral.intr_state.predict(.value(1 << int'(IntrOpDone))));
endfunction
+ // update current_state, current_op_status, err_code, alert and return update_result for updating
+ // internal key, HW/SW output
virtual function update_result_e process_update_after_op_done();
update_result_e update_result;
- bit advance_state;
keymgr_pkg::keymgr_ops_e op = get_operation();
+ bit is_err = (get_err_code() > 0);
+
+ if (is_err) current_op_status <= keymgr_pkg::OpDoneFail;
+ else current_op_status <= keymgr_pkg::OpDoneSuccess;
+
+ process_error_n_alert();
case (current_state)
- keymgr_pkg::StInit: begin
- current_op_status = keymgr_pkg::OpDoneSuccess;
+ keymgr_pkg::StInit, keymgr_pkg::StCreatorRootKey, keymgr_pkg::StOwnerIntKey,
+ keymgr_pkg::StOwnerKey: begin
case (op)
- keymgr_pkg::OpAdvance, keymgr_pkg::OpDisable: begin
- advance_state = 1;
+ keymgr_pkg::OpAdvance: begin
+ // 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;
+ current_state = get_next_state(current_state);
end
- default: begin // gen-id/sw/hw
- current_op_status = keymgr_pkg::OpDoneFail;
- trigger_error(keymgr_pkg::ErrInvalidOp);
- update_result = NotUpdate;
+ keymgr_pkg::OpDisable: begin
+ update_result = UpdateInternalKey;
+ current_state = keymgr_pkg::StDisabled;
end
- endcase
- end
- keymgr_pkg::StCreatorRootKey, keymgr_pkg::StOwnerIntKey, keymgr_pkg::StOwnerKey: begin
- current_op_status = keymgr_pkg::OpDoneSuccess;
-
- case (op)
- keymgr_pkg::OpAdvance, keymgr_pkg::OpDisable: begin
- advance_state = 1;
- end
- keymgr_pkg::OpGenId: begin
- update_result = UpdateSwOut;
- end
- keymgr_pkg::OpGenSwOut, keymgr_pkg::OpGenHwOut: begin
- // for gen-sw/hw, key_version is used as kmac data. If it's bigger than max
- // version, status will be failed
- if (get_current_max_version() < `gmv(ral.key_version)) begin
- current_op_status = keymgr_pkg::OpDoneFail;
- trigger_error(keymgr_pkg::ErrInvalidIn);
+ keymgr_pkg::OpGenId, keymgr_pkg::OpGenSwOut, keymgr_pkg::OpGenHwOut: begin
+ // If any error, no update for output
+ if (is_err) begin
update_result = NotUpdate;
+ end else if (op == keymgr_pkg::OpGenHwOut) begin
+ update_result = UpdateHwOut;
end else begin
- if (op == keymgr_pkg::OpGenSwOut) update_result = UpdateSwOut;
- else update_result = UpdateHwOut;
+ update_result = UpdateSwOut;
end
end
default: `uvm_fatal(`gfn, $sformatf("Unexpected operation: %0d", op.name))
endcase
end
keymgr_pkg::StDisabled: begin
- cfg.keymgr_vif.update_exp_key(current_internal_key);
- current_op_status = keymgr_pkg::OpDoneFail;
- trigger_error(keymgr_pkg::ErrInvalidOp);
case (op)
keymgr_pkg::OpAdvance, keymgr_pkg::OpDisable: begin
update_result = NotUpdate;
@@ -235,13 +235,6 @@
default: `uvm_fatal(`gfn, $sformatf("Unexpected current_state: %0d", current_state))
endcase
- if (advance_state) begin
- cfg.keymgr_vif.update_exp_key(current_internal_key);
- update_result = UpdateInternalKey;
- if (op == keymgr_pkg::OpAdvance) current_state = get_next_state(current_state);
- else current_state = keymgr_pkg::StDisabled;
- end
-
return update_result;
endfunction
@@ -338,16 +331,45 @@
keymgr_pkg::keymgr_ops_e op = get_operation();
current_op_status = keymgr_pkg::OpWip;
+ `uvm_info(`gfn, $sformatf("At %s, %s is issued", current_state.name, op.name), UVM_LOW)
+
// In StReset, OP doesn't trigger KDF, update result here for InvalidOp and update
// status at `op_status`
// For other states, update result after KDF is done at process_kmac_data_rsp
- if (current_state == keymgr_pkg::StReset && op != keymgr_pkg::OpAdvance) begin
- current_op_status = keymgr_pkg::OpDoneFail;
- // No KDF issued, done interrupt is triggered immediately
- void'(ral.intr_state.predict(.value(1 << int'(IntrOpDone))));
- trigger_error(keymgr_pkg::ErrInvalidOp);
- end
- `uvm_info(`gfn, $sformatf("At %s, %s is issued", current_state.name, op.name), UVM_LOW)
+ case (current_state)
+ keymgr_pkg::StReset: begin
+ if (op == keymgr_pkg::OpAdvance) begin
+ current_internal_key = {cfg.keymgr_vif.otp_key.key_share1,
+ cfg.keymgr_vif.otp_key.key_share0};
+ cfg.keymgr_vif.store_internal_key(current_internal_key, current_state);
+ end else begin // !OpAdvance
+ current_op_status = keymgr_pkg::OpDoneFail;
+ // No KDF issued, done interrupt is triggered immediately
+ void'(ral.intr_state.predict(.value(1 << int'(IntrOpDone))));
+ process_error_n_alert();
+ end
+ void'(ral.intr_state.predict(.value(1 << int'(IntrOpDone))));
+ end
+ keymgr_pkg::StDisabled: begin
+ cfg.keymgr_vif.update_kdf_key(current_internal_key, current_state, .good_key(0));
+ end
+ default: begin // other than StReset and StDisabled
+ bit good_key;
+
+ // when advance from StOwnerKey, it is to StDisabled and key is random value
+ if (current_state == keymgr_pkg::StOwnerKey && op == keymgr_pkg::OpAdvance ||
+ op == keymgr_pkg::OpDisable) begin
+ good_key = 0;
+ end else if (current_state == keymgr_pkg::StInit) begin
+ good_key = (get_err_code() == 0);
+ end else begin
+ // TODO should be "good_key = (get_err_code() == 0)", but dut acts as below #4826
+ good_key = 1;
+ end
+ // update kmac key for check
+ cfg.keymgr_vif.update_kdf_key(current_internal_key, current_state, good_key);
+ end
+ endcase
end // start
end // addr_phase_write
end
@@ -358,10 +380,14 @@
if (addr_phase_read) begin
addr_phase_working_state = current_state;
end else if (data_phase_read) begin
- keymgr_pkg::keymgr_working_state_e act_state;
+ // scb can't predict when advance from stReset is done, as it's updated internally and no
+ // output to indicate that, skip checking it
+ if (current_state != keymgr_pkg::StReset || current_op_status != keymgr_pkg::OpWip) begin
+ keymgr_pkg::keymgr_working_state_e act_state;
- `downcast(act_state, item.d_data)
- `DV_CHECK_EQ(act_state, addr_phase_working_state)
+ `downcast(act_state, item.d_data)
+ `DV_CHECK_EQ(act_state, addr_phase_working_state)
+ end
end
end
"op_status": begin
@@ -391,13 +417,12 @@
default: begin
if (!uvm_re_match("sw_share*", csr.get_name())) begin // sw_share
// if keymgr isn't On, SW output should be entropy and not match to predict value
- //if (data_phase_read && cfg.keymgr_vif.keymgr_en != lc_ctrl_pkg::On) begin
- // if (item.d_data != 0) begin
- // do_read_check = 1'b0;
- // `DV_CHECK_NE(item.d_data, `gmv(csr))
- // end
- //end
- do_read_check = 1'b0;
+ if (data_phase_read && cfg.keymgr_vif.keymgr_en != lc_ctrl_pkg::On) begin
+ if (item.d_data != 0) begin
+ do_read_check = 1'b0;
+ `DV_CHECK_NE(item.d_data, `gmv(csr))
+ end
+ end
end else begin // Not sw_share
// TODO
do_read_check = 1'b0;
@@ -425,8 +450,45 @@
endfunction
// TODO, need to check alert
- virtual function void trigger_error(keymgr_pkg::keymgr_err_pos_e err_code);
- void'(ral.err_code.predict(.value(1 << int'(err_code))));
+ virtual function void process_error_n_alert();
+ keymgr_pkg::keymgr_ops_e op = get_operation();
+ bit [TL_DW-1:0] err = get_err_code();
+
+ void'(ral.err_code.predict(err));
+ `uvm_info(`gfn, $sformatf("%s is issued and error code is 'b%0b", op.name, err), UVM_MEDIUM)
+ endfunction
+
+ virtual function bit [TL_DW-1:0] get_err_code();
+ keymgr_pkg::keymgr_ops_e op = get_operation();
+ bit [TL_DW-1:0] err_code;
+
+ case (current_state)
+ keymgr_pkg::StReset: begin
+ if (op != keymgr_pkg::OpAdvance) begin
+ err_code[keymgr_pkg::ErrInvalidOp] = 1;
+ end
+ end
+ keymgr_pkg::StInit: begin
+ if (!(op inside {keymgr_pkg::OpAdvance, keymgr_pkg::OpDisable})) begin
+ err_code[keymgr_pkg::ErrInvalidOp] = 1;
+ end
+ end
+ keymgr_pkg::StCreatorRootKey, keymgr_pkg::StOwnerIntKey, keymgr_pkg::StOwnerKey: begin
+ if (op inside {keymgr_pkg::OpGenSwOut, keymgr_pkg::OpGenHwOut} &&
+ get_invalid_input_error()) begin
+ err_code[keymgr_pkg::ErrInvalidIn] = 1;
+ end
+ end
+ keymgr_pkg::StDisabled: begin
+ err_code[keymgr_pkg::ErrInvalidOp] = 1;
+ end
+ default: `uvm_fatal(`gfn, $sformatf("unexpected state %s", current_state.name))
+ endcase
+ return err_code;
+ endfunction
+
+ virtual function bit get_invalid_input_error();
+ return get_current_max_version() < `gmv(ral.key_version);
endfunction
virtual function void compare_adv_creator_data(bit exp_match, const ref byte byte_data_q[$]);
@@ -519,8 +581,9 @@
foreach (sw_data_a_array[i]) begin
`DV_CHECK_NE(act, sw_data_a_array[i], $sformatf("SW data at state %0s", i.name))
end
- foreach (hw_data_a_array[i]) begin
- `DV_CHECK_NE(act, hw_data_a_array[i], $sformatf("HW data at state %0s", i.name))
+ foreach (cfg.keymgr_vif.keys_a_array[i, j]) begin
+ `DV_CHECK_NE(act, cfg.keymgr_vif.keys_a_array[i][j],
+ $sformatf("key at state %0s from %0s", i, j))
end
endfunction
@@ -552,8 +615,14 @@
return op;
endfunction
+ virtual function keymgr_pkg::keymgr_working_state_e get_next_state(keymgr_pkg::keymgr_working_state_e cur);
+ if (cfg.keymgr_vif.keymgr_en != lc_ctrl_pkg::On) return keymgr_pkg::StInvalid;
+ else return keymgr_env_pkg::get_next_state(cur);
+ endfunction
+
// TODO, need designer to update for #4680
virtual function void wipe_hw_keys();
+ if (current_state != keymgr_pkg::StReset) current_state = keymgr_pkg::StInvalid;
endfunction
virtual function void reset(string kind = "HARD");
@@ -565,7 +634,7 @@
adv_data_a_array.delete();
id_data_a_array.delete();
sw_data_a_array.delete();
- hw_data_a_array.delete();
+
endfunction
function void check_phase(uvm_phase phase);
diff --git a/hw/ip/keymgr/dv/env/seq_lib/keymgr_cfgen_vseq.sv b/hw/ip/keymgr/dv/env/seq_lib/keymgr_cfgen_vseq.sv
index 0e036c2..81c5736 100644
--- a/hw/ip/keymgr/dv/env/seq_lib/keymgr_cfgen_vseq.sv
+++ b/hw/ip/keymgr/dv/env/seq_lib/keymgr_cfgen_vseq.sv
@@ -26,7 +26,7 @@
// randomly add 0-100 cycle delay, backdoor check op_status again
// When status is still OpWip, call write_cfgen_gated_reg and the write will be ignored
while (!regular_vseq_done) begin
- bit [TL_DW-1] op_status_val, cfgen_val;
+ bit [TL_DW-1:0] op_status_val, cfgen_val;
uint delay;
forever begin
@@ -57,7 +57,7 @@
endtask
virtual task write_cfgen_gated_reg();
- bit [TL_DW-1] val = $urandom;
+ bit [TL_DW-1:0] val = $urandom;
`uvm_info(`gfn, "Write cfgen gated reg, and this write should be ignored", UVM_HIGH)
// since it's timing sensitive, only write one of these reg
diff --git a/hw/ip/keymgr/dv/env/seq_lib/keymgr_lc_disable_vseq.sv b/hw/ip/keymgr/dv/env/seq_lib/keymgr_lc_disable_vseq.sv
index c27a6e0..463937d 100644
--- a/hw/ip/keymgr/dv/env/seq_lib/keymgr_lc_disable_vseq.sv
+++ b/hw/ip/keymgr/dv/env/seq_lib/keymgr_lc_disable_vseq.sv
@@ -54,7 +54,7 @@
cfg.clk_rst_vif.wait_clks(delay_cycles);
forever begin
- bit [TL_DW-1] op_status_val;
+ bit [TL_DW-1:0] op_status_val;
csr_rd(ral.op_status, op_status_val);
if (op_status_val == keymgr_pkg::OpWip) break;
diff --git a/hw/ip/keymgr/dv/tb.sv b/hw/ip/keymgr/dv/tb.sv
index 56c498c..a480a82 100644
--- a/hw/ip/keymgr/dv/tb.sv
+++ b/hw/ip/keymgr/dv/tb.sv
@@ -25,6 +25,10 @@
keymgr_if keymgr_if(.clk(clk), .rst_n(rst_n));
keymgr_kmac_intf keymgr_kmac_intf(.clk(clk), .rst_n(rst_n));
+ // connect KDF interface for assertion check
+ assign keymgr_if.kmac_data_req = keymgr_kmac_intf.kmac_data_req;
+ assign keymgr_if.kmac_data_rsp = keymgr_kmac_intf.kmac_data_rsp;
+
`DV_ALERT_IF_CONNECT
// edn_clk, edn_rst_n and edn_if are defined and driven in below macro