[entropy_src, dv] Add scoreboard support for accesses to ENTROPY_DATA - Make use of the entropy_data_q to receive raw entropy for predicting accesses to ENTROPY_DATA - Activate the scoreboard in the smoke test - Miscellaneous debug comments, which can be activated with --run-mode set_verbosity_comp_a_uvm_debug Signed-off-by: Martin Lueker-Boden <martin.lueker-boden@wdc.com>
diff --git a/hw/ip/entropy_src/dv/entropy_src_sim_cfg.hjson b/hw/ip/entropy_src/dv/entropy_src_sim_cfg.hjson index 409da16..b396348 100644 --- a/hw/ip/entropy_src/dv/entropy_src_sim_cfg.hjson +++ b/hw/ip/entropy_src/dv/entropy_src_sim_cfg.hjson
@@ -68,5 +68,17 @@ tests: ["entropy_src_smoke"] } ] + + component_a: "uvm_test_top.env.scoreboard" + id_a : _ALL_ + verbosity_a: UVM_MEDIUM + phase_a: run + + run_modes: [ + { + name: set_verbosity_comp_a_uvm_debug + run_opts: ["+uvm_set_verbosity={component_a},{id_a},{verbosity_a},{phase_a}"] + } + ] }
diff --git a/hw/ip/entropy_src/dv/env/entropy_src_scoreboard.sv b/hw/ip/entropy_src/dv/env/entropy_src_scoreboard.sv index 44c1206..c60e896 100644 --- a/hw/ip/entropy_src/dv/env/entropy_src_scoreboard.sv +++ b/hw/ip/entropy_src/dv/env/entropy_src_scoreboard.sv
@@ -2,22 +2,27 @@ // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 -class entropy_src_scoreboard extends cip_base_scoreboard #( +class entropy_src_scoreboard extends cip_base_scoreboard + #( .CFG_T(entropy_src_env_cfg), .RAL_T(entropy_src_reg_block), .COV_T(entropy_src_env_cov) ); + import entropy_src_pkg::*; + `uvm_component_utils(entropy_src_scoreboard) + int entropy_data_reads = 0; + // local variables - push_pull_item#(.HostDataWidth(entropy_src_pkg::RNG_BUS_WIDTH)) rng_item; - bit [31:0] entropy_data_q[$]; - bit [entropy_src_pkg::FIPS_CSRNG_BUS_WIDTH-1:0] fips_csrng_q[$]; + push_pull_item#(.HostDataWidth(RNG_BUS_WIDTH)) rng_item; + bit [31:0] entropy_data_q[$]; + bit [FIPS_CSRNG_BUS_WIDTH - 1:0] fips_csrng_q[$]; // TLM agent fifos - uvm_tlm_analysis_fifo#(push_pull_item#(.HostDataWidth(entropy_src_pkg::FIPS_CSRNG_BUS_WIDTH))) + uvm_tlm_analysis_fifo#(push_pull_item#(.HostDataWidth(FIPS_CSRNG_BUS_WIDTH))) csrng_fifo; - uvm_tlm_analysis_fifo#(push_pull_item#(.HostDataWidth(entropy_src_pkg::RNG_BUS_WIDTH))) + uvm_tlm_analysis_fifo#(push_pull_item#(.HostDataWidth(RNG_BUS_WIDTH))) rng_fifo; `uvm_component_new @@ -35,26 +40,26 @@ task run_phase(uvm_phase phase); super.run_phase(phase); - - fork - collect_entropy(); - process_csrng(); - join_none + if (cfg.en_scb) begin + fork + collect_entropy(); + process_csrng(); + join_none + end endtask virtual task process_tl_access(tl_seq_item item, tl_channels_e channel, string ral_name); uvm_reg csr; // TODO: Add conditioning prediction, still TBD in design - bit do_read_check = 1'b1; - bit write = item.is_write(); + bit do_read_check = 1'b1; + bit write = item.is_write(); uvm_reg_addr_t csr_addr = cfg.ral_models[ral_name].get_word_aligned_addr(item.a_addr); // if access was to a valid csr, get the csr handle if (csr_addr inside {cfg.ral_models[ral_name].csr_addrs}) begin csr = cfg.ral_models[ral_name].default_map.get_reg_by_offset(csr_addr); `DV_CHECK_NE_FATAL(csr, null) - end - else begin + end else begin `uvm_fatal(`gfn, $sformatf("Access unexpected addr 0x%0h", csr_addr)) end @@ -71,6 +76,7 @@ case (csr.get_name()) // add individual case item for each csr "intr_state": begin + // TODO do_read_check = 1'b0; end "intr_enable": begin @@ -139,7 +145,11 @@ if (do_read_check) begin case (csr.get_name()) "entropy_data": begin - void'(csr.predict(.value(entropy_data_q.pop_front()), .kind(UVM_PREDICT_READ))); + bit [31:0] ed_pred_data = entropy_data_q.pop_front(); + `uvm_info(`gfn, $sformatf("entropy_data_prediction: %08h\n", ed_pred_data), UVM_MEDIUM) + `DV_CHECK_FATAL(csr.predict(.value(ed_pred_data), .kind(UVM_PREDICT_READ))) + entropy_data_reads++; + `uvm_info(`gfn, $sformatf("entropy_data_reads: %3d\n", entropy_data_reads), UVM_MEDIUM); end endcase @@ -149,37 +159,60 @@ end endtask - function bit [entropy_src_pkg::FIPS_CSRNG_BUS_WIDTH-1:0] predict_fips_csrng ( - bit [entropy_src_pkg::RNG_BUS_WIDTH-1:0] data_q[$]); - bit [entropy_src_pkg::FIPS_CSRNG_BUS_WIDTH - 1:0] fips_csrng_data; - bit [entropy_src_pkg::CSRNG_BUS_WIDTH - 1:0] csrng_data; - bit [entropy_src_pkg::FIPS_BUS_WIDTH - 1:0] fips_data; + function bit [FIPS_BUS_WIDTH - 1:0] get_fips_compliance( + bit [FIPS_CSRNG_BUS_WIDTH - 1:0] fips_csrng); + return fips_csrng[CSRNG_BUS_WIDTH +: FIPS_BUS_WIDTH]; + endfunction - // TODO: Add shah3 prediction + function bit [CSRNG_BUS_WIDTH - 1:0] get_csrng_seed(bit [FIPS_CSRNG_BUS_WIDTH - 1:0] fips_csrng); + return fips_csrng[0 +: CSRNG_BUS_WIDTH]; + endfunction + + function bit [FIPS_CSRNG_BUS_WIDTH - 1:0] predict_fips_csrng( + bit [RNG_BUS_WIDTH - 1:0] data_q[$]); + bit [FIPS_CSRNG_BUS_WIDTH - 1:0] fips_csrng_data; + bit [CSRNG_BUS_WIDTH - 1:0] csrng_data; + bit [FIPS_BUS_WIDTH - 1:0] fips_data; + + // TODO: Add SHA3 prediction if (cfg.type_bypass) begin fips_data = '0; + end else begin + // TODO: support Boot mode entropy + // Will require some changes from #9451 + fips_data = '1; end + for (int i = data_q.size() - 1; i >= 0 ; i--) begin + // Since the queue is read from back to front + // earlier rng bits occupy the less significant bits of csrng_data csrng_data = (csrng_data << 4) + data_q[i]; end fips_csrng_data = {fips_data, csrng_data}; - return csrng_data; + return fips_csrng_data; endfunction task collect_entropy(); - bit [15:0] window_size; - bit [entropy_src_pkg::RNG_BUS_WIDTH-1:0] rng_data, rng_data_q[$]; + bit [15:0] window_size; + bit [RNG_BUS_WIDTH - 1:0] rng_data, rng_data_q[$]; + bit first_call; + int rng_frames_per_window; + + first_call = 1'b1; // TODO: Read window size from register - if (cfg.type_bypass) - window_size = entropy_src_pkg::CSRNG_BUS_WIDTH; + if (cfg.type_bypass || first_call) + window_size = CSRNG_BUS_WIDTH; else window_size = 2048; + // TODO: RNG bit-select + rng_frames_per_window = window_size/RNG_BUS_WIDTH; + forever begin if (cfg.rng_bit_enable == prim_mubi_pkg::MuBi4True) begin - for (int i = 0; i < entropy_src_pkg::RNG_BUS_WIDTH; i++) begin + for (int i = 0; i < RNG_BUS_WIDTH; i++) begin rng_fifo.get(rng_item); rng_data[i] = rng_item.h_data[cfg.rng_bit_sel]; end @@ -189,22 +222,39 @@ rng_data = rng_item.h_data; end rng_data_q.push_back(rng_data); - if (rng_data_q.size() == entropy_src_pkg::CSRNG_BUS_WIDTH/entropy_src_pkg::RNG_BUS_WIDTH) begin - fips_csrng_q.push_back(predict_fips_csrng(rng_data_q[0:entropy_src_pkg::CSRNG_BUS_WIDTH-1])); - for (int i = 0; i < entropy_src_pkg::CSRNG_BUS_WIDTH/entropy_src_pkg::RNG_BUS_WIDTH; i++) begin - rng_data_q.delete(0); + + if (rng_data_q.size() == rng_frames_per_window) begin + bit [FIPS_CSRNG_BUS_WIDTH - 1:0] fips_csrng; + fips_csrng = predict_fips_csrng(rng_data_q); + if (cfg.route_software == prim_mubi_pkg::MuBi4True) begin + bit [CSRNG_BUS_WIDTH - 1:0] csrng_seed = get_csrng_seed(fips_csrng); + for (int i = 0; i < CSRNG_BUS_WIDTH/TL_DW; i++) begin + bit [TL_DW - 1:0] entropy_slice = csrng_seed[i*TL_DW +: TL_DW]; + entropy_data_q.push_back(entropy_slice); + end + end else if (cfg.route_software == prim_mubi_pkg::MuBi4False) begin + fips_csrng_q.push_back(fips_csrng); + end else begin + // TODO: invalid MuBi value for route_software: What where does data go? + end + for (int i = 0; i < rng_frames_per_window; i++) begin + rng_data_q.delete(); end end + first_call = 1'b0; end endtask virtual task process_csrng(); - push_pull_item#(.HostDataWidth(entropy_src_pkg::FIPS_CSRNG_BUS_WIDTH)) item; - bit [entropy_src_pkg::FIPS_CSRNG_BUS_WIDTH - 1:0] fips_csrng_data; + push_pull_item#(.HostDataWidth(FIPS_CSRNG_BUS_WIDTH)) item; + bit [FIPS_CSRNG_BUS_WIDTH - 1:0] fips_csrng_data; + + `uvm_info(`gfn, "task \"process_csrng\" starting\n", UVM_FULL) forever begin csrng_fifo.get(item); fips_csrng_data = item.d_data; + `uvm_info(`gfn, "process_csrng: new item: %096h\n", UVM_MEDIUM) `DV_CHECK_EQ_FATAL(fips_csrng_data, fips_csrng_q[0]) fips_csrng_q.pop_front(); end
diff --git a/hw/ip/entropy_src/dv/env/seq_lib/entropy_src_smoke_vseq.sv b/hw/ip/entropy_src/dv/env/seq_lib/entropy_src_smoke_vseq.sv index 5c24eee..1f37e9d 100644 --- a/hw/ip/entropy_src/dv/env/seq_lib/entropy_src_smoke_vseq.sv +++ b/hw/ip/entropy_src/dv/env/seq_lib/entropy_src_smoke_vseq.sv
@@ -28,9 +28,9 @@ csr_spinwait(.ptr(ral.intr_state.es_entropy_valid), .exp_data(1'b1)); // Read and check entropy - for (int i = 0; i < entropy_src_pkg::CSRNG_BUS_WIDTH/TL_DW/2; i++) begin - csr_rd_check(.ptr(ral.entropy_data), .compare_value(INCR_ENTROPY_LO)); - csr_rd_check(.ptr(ral.entropy_data), .compare_value(INCR_ENTROPY_HI)); + for (int i = 0; i < entropy_src_pkg::CSRNG_BUS_WIDTH/TL_DW; i++) begin + bit [TL_DW-1:0] entropy_tlul; + csr_rd(.ptr(ral.entropy_data), .value(entropy_tlul)); end // Ensure entropy_valid interrupt bit set
diff --git a/hw/ip/entropy_src/dv/tests/entropy_src_smoke_test.sv b/hw/ip/entropy_src/dv/tests/entropy_src_smoke_test.sv index 341beda..9fe8c16 100644 --- a/hw/ip/entropy_src/dv/tests/entropy_src_smoke_test.sv +++ b/hw/ip/entropy_src/dv/tests/entropy_src_smoke_test.sv
@@ -10,8 +10,7 @@ function void configure_env(); super.configure_env(); - // TODO: Enable scoreboard - cfg.en_scb = 0; + cfg.en_scb = 1; cfg.fips_window_size = 2048; cfg.bypass_window_size = 384; cfg.boot_mode_retry_limit = 10;