[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;