Skip to content

Commit

Permalink
Merged PR 119732: ROM regression timeout fix
Browse files Browse the repository at this point in the history
Updated ROM with image that correctly handles the SHA Accel Lock init, resolves timeout in regressions.

Added TRNG support to ROM UVM test, with regression flows for INTERNAL/EXTERNAL TRNG modes.

Related work items: #529197
  • Loading branch information
calebofearth authored and Anjana Parthasarathy committed Aug 24, 2023
1 parent 071060b commit b2c3439
Show file tree
Hide file tree
Showing 12 changed files with 176 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ contents:
path: ""
config:
params:
# 24 hours to help diagnose timeout problem for this test
timeout: 1440
# 12 hours
timeout: 720
weight: 100
generations: 1
formats:
Expand Down
Binary file modified src/integration/test_suites/fw_test_rom/fw_test_rom
Binary file not shown.
Binary file modified src/integration/test_suites/fw_test_rom/fw_test_rom_fw
Binary file not shown.
41 changes: 41 additions & 0 deletions src/integration/uvmf_caliptra_top/config/compile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,44 @@ global:
- '-sv_lib libapb3_IN_SystemVerilog_VCS_full'
# Report "MVC_ERROR" as "UVM_ERROR"
- '+QVIP_UVM_REPORTING'
---
provides: [uvmf_caliptra_top_itrng]
schema_version: 2.4.0
requires:
- uvmf_caliptra_top
targets:
tb:
tops:
- hdl_top
- hvl_top
sim:
pre_exec: |
echo "[PRE-EXEC] Copying SHA512 Vectors to $(pwd)"
cp ${COMPILE_ROOT}/../tb/vectors/SHA*.rsp .
$TOOLS/scripts/run_test_makefile
global:
tool:
vcs:
default:
- '-assert svaext'
- +define+CLP_ASSERT_ON
- '-noinherit_timescale=1ns/1ps'
- '+define+CALIPTRA_INTERNAL_TRNG'
# Suppress a warning due to calling $fgets as task instead of function
# i.e. discarding the return value. This is in auto-generated code.
- '+warn=noRVOSFD'
# Suppress NOTE about repeated package imports within the same
# package (each .svh file included in the auto-generated UVM _pkg.sv
# files imports the same dependencies)
- '-suppress=SV-LCM-PPWI'
elab:
# Suppress warnings about too few port connections - auto-generated interfaces
# declare all signals as inout, but are driven at a lower layer than the
# instantiation, so they will always flag this
- '-suppress=TFIPC'
sim:
- '-sv_root $QUESTA_MVC_HOME/questa_mvc_core/linux_x86_64_gcc-6.2.0_vcs'
- '-sv_lib libahb_IN_SystemVerilog_VCS_full'
- '-sv_lib libapb3_IN_SystemVerilog_VCS_full'
# Report "MVC_ERROR" as "UVM_ERROR"
- '+QVIP_UVM_REPORTING'
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class caliptra_top_rom_sequence extends caliptra_top_bench_sequence_base;
`uvm_object_utils( caliptra_top_rom_sequence );

rand soc_ifc_env_rom_bringup_sequence_t soc_ifc_env_bringup_seq;
rand soc_ifc_env_trng_write_data_sequence_t soc_ifc_env_trng_write_data_seq;
rand soc_ifc_env_mbox_rom_fw_sequence_t soc_ifc_env_mbox_rom_seq;
rand soc_ifc_env_sequence_base_t soc_ifc_env_seq_ii[];
// Local handle to register model for convenience
Expand Down Expand Up @@ -94,6 +95,21 @@ class caliptra_top_rom_sequence extends caliptra_top_bench_sequence_base;

`uvm_info("CALIPTRA_TOP_BRINGUP", "SoC completed poweron and observed reset deassertion to system", UVM_LOW)

`ifndef CALIPTRA_INTERNAL_TRNG
`uvm_info("CALIPTRA_TOP_ROM_TEST", "Initiating TRNG responder sequence in an infinite loop to handle ROM TRNG requests", UVM_LOW)
fork
forever begin
soc_ifc_env_trng_write_data_seq = soc_ifc_env_trng_write_data_sequence_t::type_id::create("soc_ifc_env_trng_write_data_seq");
soc_ifc_env_trng_write_data_seq.soc_ifc_status_agent_rsp_seq = soc_ifc_subenv_soc_ifc_status_agent_responder_seq;
if (!soc_ifc_env_trng_write_data_seq.randomize())
`uvm_fatal("CALIPTRA_TOP_ROM_TEST", $sformatf("caliptra_top_rom_sequence::body() - %s randomization failed", soc_ifc_env_trng_write_data_seq.get_type_name()));
soc_ifc_env_trng_write_data_seq.start(top_configuration.soc_ifc_subenv_config.vsqr);
end
join_none
`else
`uvm_info("CALIPTRA_TOP_ROM_TEST", "Not initiating TRNG responder sequence to handle ROM TRNG requests because INTERNAL TRNG is enabled", UVM_LOW)
`endif

run_firmware_init(soc_ifc_env_mbox_rom_seq);

// After firmware init, wait for generic_output_wires write to 0xFF
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,10 @@ import uvmf_base_pkg_hdl::*;
logic [`CALIPTRA_IMEM_ADDR_WIDTH-1:0] imem_addr;
logic [`CALIPTRA_IMEM_DATA_WIDTH-1:0] imem_rdata;

logic etrng_req;
logic [3:0] itrng_data;
logic itrng_valid;

//device lifecycle
security_state_t security_state_stub_inactive;

Expand Down Expand Up @@ -234,10 +238,17 @@ import uvmf_base_pkg_hdl::*;
.cptra_error_fatal (soc_ifc_subenv_soc_ifc_status_agent_bus.cptra_error_fatal),
.cptra_error_non_fatal(soc_ifc_subenv_soc_ifc_status_agent_bus.cptra_error_non_fatal),
// External TRNG
`ifdef CALIPTRA_INTERNAL_TRNG
.etrng_req (etrng_req),
// Internal TRNG
.itrng_data (itrng_data ),
.itrng_valid (itrng_valid),
`else
.etrng_req (soc_ifc_subenv_soc_ifc_status_agent_bus.trng_req),
// Internal TRNG
.itrng_data (4'h0), // TODO
.itrng_valid (1'b0), // TODO
.itrng_data (4'h0),
.itrng_valid (1'b0),
`endif

.generic_input_wires (soc_ifc_subenv_soc_ifc_ctrl_agent_bus.generic_input_wires),
.generic_output_wires(soc_ifc_subenv_soc_ifc_status_agent_bus.generic_output_wires),
Expand Down Expand Up @@ -310,6 +321,20 @@ import uvmf_base_pkg_hdl::*;
assign soc_ifc_subenv_mbox_sram_agent_bus.mbox_sram_req = mbox_sram_req;
assign mbox_sram_resp = soc_ifc_subenv_mbox_sram_agent_bus.mbox_sram_resp;

`ifdef CALIPTRA_INTERNAL_TRNG
//=========================================================================-
// Physical RNG used for Internal TRNG
//=========================================================================-
physical_rng physical_rng_i (
.clk (clk),
.enable (etrng_req),
.data (itrng_data),
.valid (itrng_valid)
);

assign soc_ifc_subenv_soc_ifc_status_agent_bus.trng_req = 1'b0;
`endif

//=========================================================================-
// Services for SRAM exports, STDOUT, etc
//=========================================================================-
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,18 @@ class soc_ifc_env_reset_sequence_base extends soc_ifc_env_sequence_base #(.CONFI

rand uvm_reg_data_t uds_seed_rand [12];
rand uvm_reg_data_t field_entropy_rand [32];
rand uvm_reg_data_t owner_pk_hash_rand [12];
rand uvm_reg_data_t key_manifest_pk_hash_rand [12];
rand uvm_reg_data_t idevid_cert_attr_rand [24];
rand uvm_reg_data_t soc_stepping_id_rand;
rand struct packed {
bit uds;
bit field_entropy;
bit [0:11] key_manifest_pk_hash;
bit [0:11] owner_pk_hash;
bit soc_stepping_id;
bit [0:23] idevid_cert_attr;
bit lms_verify;
} fuses_to_set;


Expand Down Expand Up @@ -107,7 +112,7 @@ class soc_ifc_env_reset_sequence_base extends soc_ifc_env_sequence_base #(.CONFI
if (!fuse_ready)
`uvm_info("SOC_IFC_RST", "Received status transition while waiting for Mailbox ready_for_fuses, ready_for_fuses still not set", UVM_MEDIUM)
else
`uvm_info("SOC_IFC_RST", "Fuse ready, initiating fuse download", UVM_LOW)
`uvm_info("SOC_IFC_RST", $sformatf("Fuse ready, initiating fuse download with fuses_to_set: [%p]", this.fuses_to_set), UVM_LOW)
end

// Write UDS
Expand All @@ -128,6 +133,24 @@ class soc_ifc_env_reset_sequence_base extends soc_ifc_env_sequence_base #(.CONFI
end
end

// Key Manifest PK Hash (Vendor)
foreach (this.fuses_to_set.key_manifest_pk_hash[ii]) begin
if (this.fuses_to_set.key_manifest_pk_hash[ii]) begin
`uvm_info("SOC_IFC_RST", $sformatf("Writing Key Manifest PK Hash [%d] to fuse bank with value 0x%0x", ii, key_manifest_pk_hash_rand[ii]), UVM_LOW)
reg_model.soc_ifc_reg_rm.fuse_key_manifest_pk_hash[ii].write(sts, key_manifest_pk_hash_rand[ii], UVM_FRONTDOOR, reg_model.soc_ifc_APB_map, this, .extension(apb_user_obj));
if (sts != UVM_IS_OK) `uvm_error("SOC_IFC_RST", $sformatf("Failed when writing to Key Manifest PK Hash [%d]", ii))
end
end

// Owner PK Hash
foreach (this.fuses_to_set.owner_pk_hash[ii]) begin
if (this.fuses_to_set.owner_pk_hash[ii]) begin
`uvm_info("SOC_IFC_RST", $sformatf("Writing Owner PK Hash [%d] to fuse bank with value 0x%0x", ii, owner_pk_hash_rand[ii]), UVM_LOW)
reg_model.soc_ifc_reg_rm.fuse_owner_pk_hash[ii].write(sts, owner_pk_hash_rand[ii], UVM_FRONTDOOR, reg_model.soc_ifc_APB_map, this, .extension(apb_user_obj));
if (sts != UVM_IS_OK) `uvm_error("SOC_IFC_RST", $sformatf("Failed when writing to Owner PK Hash [%d]", ii))
end
end

// Write SoC Stepping ID
if (this.fuses_to_set.soc_stepping_id) begin
`uvm_info("SOC_IFC_RST", "Writing SOC Stepping ID to fuse bank", UVM_LOW)
Expand All @@ -144,6 +167,14 @@ class soc_ifc_env_reset_sequence_base extends soc_ifc_env_sequence_base #(.CONFI
end
end

// Write LMS Verify Bit
if (this.fuses_to_set.lms_verify) begin
uvm_reg_data_t lms_verify_data = 1 << reg_model.soc_ifc_reg_rm.fuse_lms_verify.lms_verify.get_lsb_pos();
`uvm_info("SOC_IFC_RST", "Writing LMS Verify=1 to fuse bank", UVM_LOW)
reg_model.soc_ifc_reg_rm.fuse_lms_verify.write(sts, lms_verify_data, UVM_FRONTDOOR, reg_model.soc_ifc_APB_map, this, .extension(apb_user_obj));
if (sts != UVM_IS_OK) `uvm_error("SOC_IFC_RST", "Failed when writing to lms_verify")
end

// Set Fuse Done
reg_model.soc_ifc_reg_rm.CPTRA_FUSE_WR_DONE.write(sts, `UVM_REG_DATA_WIDTH'(1), UVM_FRONTDOOR, reg_model.soc_ifc_APB_map, this, .extension(apb_user_obj));
`uvm_info("SOC_IFC_RST", $sformatf("Fuse download completed, status: %p", sts), UVM_MEDIUM)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,43 @@ class soc_ifc_env_rom_bringup_sequence extends soc_ifc_env_reset_sequence_base;

typedef soc_ifc_ctrl_rom_poweron_sequence soc_ifc_ctrl_agent_poweron_sequence_t;

// Decide which fuses to initialize
constraint always_set_uds_c { this.fuses_to_set.uds == 1'b1; }
constraint always_set_fe_c { this.fuses_to_set.field_entropy == 1'b1; }
// Roughly once per week, assuming the nightly Directed regression isn't running every day (since it is triggered by a PR)
constraint infrequently_set_lms_verify_c { this.fuses_to_set.lms_verify dist {0 :/ 4, 1 :/ 1}; }
constraint always_set_key_manifest_pk_hash_c { this.fuses_to_set.key_manifest_pk_hash == {12{1'b1}}; }
constraint always_set_owner_pk_hash_c { this.fuses_to_set.owner_pk_hash == {12{1'b1}}; }
constraint always_set_idevid_c { this.fuses_to_set.idevid_cert_attr[0] == 1'b1;
this.fuses_to_set.idevid_cert_attr[6] == 1'b1;
this.fuses_to_set.idevid_cert_attr[7] == 1'b1; }
// Configure the values to set to initialized fuses
constraint key_manifest_pk_hash_values_c { key_manifest_pk_hash_rand[0] == 32'h6DC8DE16;
key_manifest_pk_hash_rand[1] == 32'hD559D129;
key_manifest_pk_hash_rand[2] == 32'h7BAB1E43;
key_manifest_pk_hash_rand[3] == 32'hEBD7C533;
key_manifest_pk_hash_rand[4] == 32'hDFE57001;
key_manifest_pk_hash_rand[5] == 32'h1AA56220;
key_manifest_pk_hash_rand[6] == 32'h0F66AD6D;
key_manifest_pk_hash_rand[7] == 32'h87051086;
key_manifest_pk_hash_rand[8] == 32'hC785E930;
key_manifest_pk_hash_rand[9] == 32'hD3D947B4;
key_manifest_pk_hash_rand[10] == 32'h7495822E;
key_manifest_pk_hash_rand[11] == 32'hCB643FF1;
solve this.fuses_to_set before this.key_manifest_pk_hash_rand; }
constraint owner_pk_hash_values_c { owner_pk_hash_rand[0] == 32'hF58D4920;
owner_pk_hash_rand[1] == 32'hBA65DA44;
owner_pk_hash_rand[2] == 32'hB0F728BC;
owner_pk_hash_rand[3] == 32'hFB893202;
owner_pk_hash_rand[4] == 32'hCFAAA942;
owner_pk_hash_rand[5] == 32'hBC66A0C0;
owner_pk_hash_rand[6] == 32'h007A2CE2;
owner_pk_hash_rand[7] == 32'h29A8E08F;
owner_pk_hash_rand[8] == 32'h9E8EEBAE;
owner_pk_hash_rand[9] == 32'hB36E9CC0;
owner_pk_hash_rand[10] == 32'h962E4B7A;
owner_pk_hash_rand[11] == 32'h50214999;
solve this.fuses_to_set before this.owner_pk_hash_rand; }
constraint idevid_values_c { idevid_cert_attr_rand[0] == '0; /* SHA1 */
idevid_cert_attr_rand[6] == 32'hFFFF_FFFF; /* UEID LSWord */
idevid_cert_attr_rand[7] == 32'hFFFF_FFFF; /* MSWord */}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class soc_ifc_env_mbox_rom_fw_sequence extends soc_ifc_env_mbox_sequence_base;

// This shouldn't be randomized, specify it
constraint mbox_cmd_c { mbox_op_rand.cmd == mbox_cmd_e'(MBOX_CMD_ROM_FW_UPD); }
constraint mbox_dlen_c { mbox_op_rand.dlen == 10644; }
constraint mbox_dlen_c { mbox_op_rand.dlen == 13708; }
// Response data is only non-zero if a response is requested, and also must
// be small enough to fit in the mailbox
// Firmware team encodes commands differently from this environment; response
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class soc_ifc_env_trng_write_data_sequence extends soc_ifc_env_sequence_base #(.
rand bit trng_write_done;
rand bit [3:0] trng_num_dwords;

int sts_rsp_count;
bit trng_data_req;

bit [apb5_master_0_params::PAUSER_WIDTH-1:0] trng_valid_user;
Expand Down Expand Up @@ -69,15 +70,24 @@ class soc_ifc_env_trng_write_data_sequence extends soc_ifc_env_sequence_base #(.

virtual task body();

sts_rsp_count = 0;

fork
forever begin
@(soc_ifc_status_agent_rsp_seq.new_rsp) sts_rsp_count++;
end
join_none

soc_ifc_env_trng_setup();
`uvm_info("TRNG_REQ_SEQ", $sformatf("Responding to TRNG_DATA_REQ with %0d dwords", trng_num_dwords), UVM_DEBUG)
if (this.trng_data_req == 1'b0)
soc_ifc_env_trng_poll_data_req();
if (this.trng_data_req) begin
`uvm_info("TRNG_REQ_SEQ", $sformatf("Responding to TRNG_DATA_REQ with %0d dwords", trng_num_dwords), UVM_FULL)
soc_ifc_env_trng_write_data();
soc_ifc_env_trng_write_done();
soc_ifc_env_trng_wait_idle();
end
`uvm_info("TRNG_REQ_SEQ", "TRNG write data sequence completed", UVM_HIGH)

endtask

Expand Down Expand Up @@ -108,6 +118,7 @@ task soc_ifc_env_trng_write_data_sequence::soc_ifc_env_trng_setup();

// Assign user and use throughout sequence
apb_user_obj.set_addr_user(trng_valid_user);
`uvm_info("TRNG_REQ_SEQ", $sformatf("trng_valid_user initialized to value 0x%x", trng_valid_user), UVM_HIGH)

endtask

Expand All @@ -120,10 +131,15 @@ task soc_ifc_env_trng_write_data_sequence::soc_ifc_env_trng_poll_data_req();

soc_ifc_env_trng_check_data_req(data_req);
while (data_req == 1'b0) begin
configuration.soc_ifc_ctrl_agent_config.wait_for_num_clocks(200);
soc_ifc_env_trng_check_data_req(data_req);
wait (sts_rsp_count != 0);
data_req = soc_ifc_status_agent_rsp_seq.rsp.trng_req_pending;
sts_rsp_count = 0;
end
soc_ifc_env_trng_check_data_req(data_req);
if (!data_req)
`uvm_error("TRNG_REQ_SEQ", "Got status transaction with trng_req_pending, but read from CPTRA_TRNG_STATUS.DATA_REQ returned 0!")
this.trng_data_req = data_req;
`uvm_info("TRNG_REQ_SEQ", $sformatf("Got status transaction with trng_req_pending, read from CPTRA_TRNG_STATUS.DATA_REQ returned %d", data_req), UVM_MEDIUM)
endtask

//==========================================
Expand Down Expand Up @@ -152,7 +168,7 @@ task soc_ifc_env_trng_write_data_sequence::soc_ifc_env_trng_write_data();
uvm_reg_data_t data;
for (ii = 0; ii < this.trng_num_dwords; ii++) begin
if (!std::randomize(data)) `uvm_error("TRNG_REQ_SEQ", "Failed to randomize data")
`uvm_info("TRNG_REQ_SEQ", $sformatf("Sending TRNG_DATA[%0d]: 0x%0x", ii, data), UVM_DEBUG)
`uvm_info("TRNG_REQ_SEQ", $sformatf("Sending TRNG_DATA[%0d]: 0x%0x", ii, data), UVM_HIGH)
reg_model.soc_ifc_reg_rm.CPTRA_TRNG_DATA[ii].write(reg_sts, uvm_reg_data_t'(data), UVM_FRONTDOOR, reg_model.soc_ifc_APB_map, this, .extension(apb_user_obj));
if (reg_sts != UVM_IS_OK)
`uvm_error("TRNG_REQ_SEQ", "Register access failed (TRNG_DATA)")
Expand All @@ -165,7 +181,7 @@ endtask
//==========================================
task soc_ifc_env_trng_write_data_sequence::soc_ifc_env_trng_write_done();
uvm_status_e reg_sts;
`uvm_info("TRNG_REQ_SEQ", "Sending TRNG_DONE", UVM_DEBUG)
`uvm_info("TRNG_REQ_SEQ", "Sending TRNG_DONE", UVM_MEDIUM)
reg_model.soc_ifc_reg_rm.CPTRA_TRNG_STATUS.write(reg_sts, uvm_reg_data_t'(trng_write_done) << reg_model.soc_ifc_reg_rm.CPTRA_TRNG_STATUS.DATA_WR_DONE.get_lsb_pos(), UVM_FRONTDOOR, reg_model.soc_ifc_APB_map, this, .extension(apb_user_obj));
if (reg_sts != UVM_IS_OK)
`uvm_error("TRNG_REQ_SEQ", "Register access failed (TRNG_DONE)")
Expand All @@ -191,4 +207,5 @@ task soc_ifc_env_trng_write_data_sequence::soc_ifc_env_trng_wait_idle();
if (reg_sts != UVM_IS_OK)
`uvm_error("TRNG_REQ_SEQ", "Register access failed (CPTRA_TRNG_STATUS)")
end
`uvm_info("TRNG_REQ_SEQ", "Observed TRNG_DONE cleared to 0", UVM_HIGH)
endtask
Original file line number Diff line number Diff line change
Expand Up @@ -1263,7 +1263,7 @@ class soc_ifc_predictor #(
"CPTRA_WDT_TIMER1_TIMEOUT_PERIOD[0]",
"CPTRA_WDT_TIMER1_TIMEOUT_PERIOD[1]": begin
if (ahb_txn.RnW == AHB_WRITE) begin
`uvm_info("PRED_AHB", {"Detected write to ", axs_reg.get_name()," register on AHB interface"}, UVM_MEDIUM);
`uvm_info("PRED_AHB", {"Write to ",axs_reg.get_name()," register on AHB interface has no side-effect"}, UVM_HIGH) // TODO
end
end
"CPTRA_WDT_TIMER2_EN": begin
Expand All @@ -1282,7 +1282,7 @@ class soc_ifc_predictor #(
"CPTRA_WDT_TIMER2_TIMEOUT_PERIOD[0]",
"CPTRA_WDT_TIMER2_TIMEOUT_PERIOD[1]": begin
if (ahb_txn.RnW == AHB_WRITE) begin
`uvm_info("PRED_AHB", {"Detected write to ",axs_reg.get_name()," register on AHB interface"}, UVM_LOW) // TODO
`uvm_info("PRED_AHB", {"Write to ",axs_reg.get_name()," register on AHB interface has no side-effect"}, UVM_HIGH) // TODO
end
end
"CPTRA_WDT_STATUS": begin
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class soc_ifc_ctrl_rom_poweron_sequence
req=soc_ifc_ctrl_transaction::type_id::create("pwr_req");
start_item(req);
// Randomize the transaction (must be DEVICE_UNPROVISIONED for ROM bringup)
if(!req.randomize() with {security_state.device_lifecycle == DEVICE_UNPROVISIONED;})
if(!req.randomize() with {security_state.device_lifecycle != DEVICE_UNPROVISIONED;})
`uvm_fatal("SOC_IFC_CTRL_RST", "soc_ifc_ctrl_reset_sequence_base::body()-soc_ifc_ctrl_transaction randomization failed")
req.set_pwrgood = 1'b0;
req.assert_rst = 1'b1; // active-low assertion
Expand Down

0 comments on commit b2c3439

Please sign in to comment.