[dv/hmac] HMAC FIFOEmpty DV
This assumes tx_empty will trigger only during reg_hash_start and
reg_hash_process
Co-authored-by: Cindy Chen <chencindy@google.com>
Signed-off-by: Eunchan Kim <eunchan@opentitan.org>
Signed-off-by: Cindy Chen <chencindy@google.com>
diff --git a/hw/ip/hmac/dv/env/hmac_env_pkg.sv b/hw/ip/hmac/dv/env/hmac_env_pkg.sv
index 0896b86..55c34f2 100644
--- a/hw/ip/hmac/dv/env/hmac_env_pkg.sv
+++ b/hw/ip/hmac/dv/env/hmac_env_pkg.sv
@@ -38,7 +38,7 @@
typedef enum {
HmacDone,
- HmacMsgFifoFull,
+ HmacMsgFifoEmpty,
HmacErr
} hmac_intr_e;
diff --git a/hw/ip/hmac/dv/env/hmac_scoreboard.sv b/hw/ip/hmac/dv/env/hmac_scoreboard.sv
index e626083..54dc5f6 100644
--- a/hw/ip/hmac/dv/env/hmac_scoreboard.sv
+++ b/hw/ip/hmac/dv/env/hmac_scoreboard.sv
@@ -8,7 +8,7 @@
`uvm_component_utils(hmac_scoreboard)
`uvm_component_new
- bit sha_en, fifo_full;
+ bit sha_en, fifo_full, fifo_empty;
bit [7:0] msg_q[$];
bit hmac_start, hmac_process;
int hmac_wr_cnt, hmac_rd_cnt;
@@ -22,7 +22,7 @@
task run_phase(uvm_phase phase);
super.run_phase(phase);
fork
- hmac_process_fifo_full();
+ hmac_process_fifo_status();
hmac_process_fifo_wr();
hmac_process_fifo_rd();
join_none
@@ -95,6 +95,9 @@
void'(ral.intr_state.predict(.value(intr_state_exp), .kind(UVM_PREDICT_DIRECT)));
intr_test = item.a_data;
end
+ "intr_state": begin
+ if (item.a_data[HmacMsgFifoEmpty]) fifo_empty = 0;
+ end
"cfg": begin
if (hmac_start) return; // won't update configs if hash start
if (cfg.en_cov) cov.cfg_cg.sample(item.a_data);
@@ -141,6 +144,11 @@
(hmac_fifo_full << HmacStaMsgFifoFull) |
(hmac_fifo_depth << HmacStaMsgFifoDepth);
void'(ral.status.predict(.value(hmac_status_data), .kind(UVM_PREDICT_READ)));
+ end else if (csr_name == "intr_state") begin
+ if (fifo_empty && ral.intr_state.fifo_empty.get_mirrored_value() != 1) begin
+ void'(ral.intr_state.fifo_empty.predict(.value(1), .kind(UVM_PREDICT_READ)));
+ `uvm_info(`gfn, "predict again", UVM_HIGH)
+ end
end
return;
end
@@ -223,6 +231,7 @@
hmac_rd_cnt = 0;
intr_test = 0;
key = '{default:0};
+ fifo_empty = 0;
endfunction
// clear variables after expected digest is calculated
@@ -265,15 +274,19 @@
join
endtask
- virtual task hmac_process_fifo_full();
+ virtual task hmac_process_fifo_status();
forever @(hmac_wr_cnt, hmac_rd_cnt) begin
// when hmac_wr_cnt and hmac_rd_cnt update at the same time, wait 1ps to guarantee
// get both update
#1ps;
- if ((hmac_wr_cnt - hmac_rd_cnt) == HMAC_MSG_FIFO_DEPTH) begin
- void'(ral.intr_state.fifo_full.predict(.value(1)));
- `uvm_info(`gfn, "predict interrupt fifo full is set", UVM_HIGH)
- fifo_full = 1;
+ if ((hmac_wr_cnt == hmac_rd_cnt) && (hmac_wr_cnt != 0)) begin
+ // after the rd wr pointers are equal, wait one clk cycle for the fifo_empty register
+ // update, wait another clk cycle for the register value to reflect
+ if (!fifo_empty) begin
+ cfg.clk_rst_vif.wait_clks(2);
+ `uvm_info(`gfn, "predict interrupt fifo empty is set", UVM_HIGH)
+ fifo_empty = 1;
+ end
end
end
endtask
@@ -347,7 +360,7 @@
function void check_phase(uvm_phase phase);
super.check_phase(phase);
- `DV_CHECK_EQ(cfg.intr_vif.pins[HmacMsgFifoFull], 1'b0)
+ `DV_CHECK_EQ(cfg.intr_vif.pins[HmacMsgFifoEmpty], 1'b0)
`DV_CHECK_EQ(cfg.intr_vif.pins[HmacDone], 1'b0)
`DV_CHECK_EQ(cfg.intr_vif.pins[HmacErr], 1'b0)
endfunction
diff --git a/hw/ip/hmac/dv/env/seq_lib/hmac_base_vseq.sv b/hw/ip/hmac/dv/env/seq_lib/hmac_base_vseq.sv
index 2567e3c..51a743a 100644
--- a/hw/ip/hmac/dv/env/seq_lib/hmac_base_vseq.sv
+++ b/hw/ip/hmac/dv/env/seq_lib/hmac_base_vseq.sv
@@ -52,7 +52,7 @@
bit hmac_en = 1'b1,
bit endian_swap = 1'b1,
bit digest_swap = 1'b1,
- bit intr_fifo_full_en = 1'b1,
+ bit intr_fifo_empty_en = 1'b1,
bit intr_hmac_done_en = 1'b1,
bit intr_hmac_err_en = 1'b1);
bit [TL_DW-1:0] interrupts;
@@ -65,7 +65,7 @@
// enable interrupts
interrupts = (intr_hmac_err_en << HmacErr) | (intr_hmac_done_en << HmacDone) |
- (intr_fifo_full_en << HmacMsgFifoFull);
+ (intr_fifo_empty_en << HmacMsgFifoEmpty);
cfg_interrupts(.interrupts(interrupts), .enable(1'b1));
endtask
@@ -192,8 +192,8 @@
.blocking($urandom_range(0, 1)));
if (ral.cfg.sha_en.get_mirrored_value()) begin
- if (!do_back_pressure) check_status_intr_fifo_full();
- else clear_intr_fifo_full();
+ //if (!do_back_pressure) check_status_intr_fifo_full();
+ //else clear_intr_fifo_full();
// randomly change key, config regs during msg wr, should trigger error or be discarded
write_discard_config_and_key($urandom_range(0, 20) == 0, $urandom_range(0, 20) == 0);
end else begin
@@ -226,7 +226,7 @@
.blocking($urandom_range(0, 1)));
end
if (ral.cfg.sha_en.get_mirrored_value()) begin
- clear_intr_fifo_full();
+ //clear_intr_fifo_full();
end else begin
check_error_code();
end
@@ -248,33 +248,33 @@
// read status FIFO FULL and check intr FIFO FULL
// if intr_fifo_full_enable is disable, check intr_fifo_full_state and clear it
- virtual task check_status_intr_fifo_full();
- bit msg_fifo_full;
- csr_utils_pkg::wait_no_outstanding_access();
- csr_rd(ral.status.fifo_full, msg_fifo_full);
- if (ral.intr_enable.fifo_full.get_mirrored_value()) begin
- check_interrupts(.interrupts((1 << HmacMsgFifoFull)), .check_set(msg_fifo_full));
- end else begin
- csr_rd_check(.ptr(ral.intr_state), .compare_value(msg_fifo_full),
- .compare_mask(1 << HmacMsgFifoFull));
- csr_wr(.csr(ral.intr_state), .value(1 << HmacMsgFifoFull));
- end
- endtask
+ //virtual task check_status_intr_fifo_full();
+ // bit msg_fifo_full;
+ // csr_utils_pkg::wait_no_outstanding_access();
+ // csr_rd(ral.status.fifo_full, msg_fifo_full);
+ // if (ral.intr_enable.fifo_full.get_mirrored_value()) begin
+ // check_interrupts(.interrupts((1 << HmacMsgFifoFull)), .check_set(msg_fifo_full));
+ // end else begin
+ // csr_rd_check(.ptr(ral.intr_state), .compare_value(msg_fifo_full),
+ // .compare_mask(1 << HmacMsgFifoFull));
+ // csr_wr(.csr(ral.intr_state), .value(1 << HmacMsgFifoFull));
+ // end
+ //endtask
// when msg fifo full interrupt is set, this task clears the interrupt
// checking the correctness of the fifo full interrupt is done in scb
- virtual task clear_intr_fifo_full();
- csr_utils_pkg::wait_no_outstanding_access();
- if (ral.intr_enable.fifo_full.get_mirrored_value()) begin
- if (cfg.intr_vif.pins[HmacMsgFifoFull] === 1'b1) begin
- check_interrupts(.interrupts((1 << HmacMsgFifoFull)), .check_set(1'b1));
- end
- end else begin
- bit msg_fifo_full;
- csr_rd(ral.intr_state.fifo_full, msg_fifo_full);
- if (msg_fifo_full) csr_wr(.csr(ral.intr_state), .value(msg_fifo_full << HmacMsgFifoFull));
- end
- endtask
+ //virtual task clear_intr_fifo_full();
+ // csr_utils_pkg::wait_no_outstanding_access();
+ // if (ral.intr_enable.fifo_full.get_mirrored_value()) begin
+ // if (cfg.intr_vif.pins[HmacMsgFifoFull] === 1'b1) begin
+ // check_interrupts(.interrupts((1 << HmacMsgFifoFull)), .check_set(1'b1));
+ // end
+ // end else begin
+ // bit msg_fifo_full;
+ // csr_rd(ral.intr_state.fifo_full, msg_fifo_full);
+ // if (msg_fifo_full) csr_wr(.csr(ral.intr_state), .value(msg_fifo_full << HmacMsgFifoFull));
+ // end
+ //endtask
// this task is called when sha_en=0 and sequence set hash_start, or streamed in msg
// it will check intr_pin, intr_state, and error_code register
diff --git a/hw/ip/hmac/dv/env/seq_lib/hmac_sanity_vseq.sv b/hw/ip/hmac/dv/env/seq_lib/hmac_sanity_vseq.sv
index 7441614..0f28d33 100644
--- a/hw/ip/hmac/dv/env/seq_lib/hmac_sanity_vseq.sv
+++ b/hw/ip/hmac/dv/env/seq_lib/hmac_sanity_vseq.sv
@@ -14,7 +14,7 @@
rand bit sha_en;
rand bit endian_swap;
rand bit digest_swap;
- rand bit intr_fifo_full_en;
+ rand bit intr_fifo_empty_en;
rand bit intr_hmac_done_en;
rand bit intr_hmac_err_en;
rand bit [31:0] key[8];
@@ -42,7 +42,7 @@
}
constraint intr_enable_c {
- intr_fifo_full_en dist {1'b1 := 8, 1'b0 := 2};
+ intr_fifo_empty_en dist {1'b1 := 8, 1'b0 := 2};
intr_hmac_done_en dist {1'b1 := 8, 1'b0 := 2};
intr_hmac_err_en dist {1'b1 := 8, 1'b0 := 2};
}
@@ -59,12 +59,12 @@
`DV_CHECK_RANDOMIZE_FATAL(this)
`uvm_info(`gfn, $sformatf("starting seq %0d/%0d, message size %0d, hmac=%0d, sha=%0d",
i, num_trans, msg.size(), hmac_en, sha_en), UVM_LOW)
- `uvm_info(`gfn, $sformatf("intr_fifo_full/hmac_done/hmac_err_en=%b, endian/digest_swap=%b",
- {intr_fifo_full_en, intr_hmac_done_en, intr_hmac_err_en},
+ `uvm_info(`gfn, $sformatf("intr_fifo_empty/hmac_done/hmac_err_en=%b, endian/digest_swap=%b",
+ {intr_fifo_empty_en, intr_hmac_done_en, intr_hmac_err_en},
{endian_swap, digest_swap}), UVM_HIGH)
// initialize hmac configs
hmac_init(.sha_en(sha_en), .hmac_en(hmac_en), .endian_swap(endian_swap),
- .digest_swap(digest_swap), .intr_fifo_full_en(intr_fifo_full_en),
+ .digest_swap(digest_swap), .intr_fifo_empty_en(intr_fifo_empty_en),
.intr_hmac_done_en(intr_hmac_done_en), .intr_hmac_err_en(intr_hmac_err_en));
// can randomly read previous digest
@@ -77,6 +77,7 @@
if (i != 1 && $urandom_range(0, 1)) rd_digest();
if (sha_en || $urandom_range(0, 1)) begin
+ bit [TL_DW-1:0] intr_state_val;
// start stream in msg
if (do_hash_start) trigger_hash();
@@ -101,22 +102,21 @@
// msg stream in finished, start hash
if (do_hash_start) trigger_process();
- // fifo_full intr can be triggered at the latest two cycle after process
- // example: current fifo_depth=(14 words + 2 bytes), then wr last 4 bytes, design will
- // process the 15th word then trigger intr_fifo_full
- cfg.clk_rst_vif.wait_clks(2);
- clear_intr_fifo_full();
+ // TODO: temp solution as after hmac_process, scb hmac_empty has one cycle mismatch with
+ // RTL
+ if (hmac_en) cfg.clk_rst_vif.wait_clks(HMAC_KEY_PROCESS_CYCLES);
+ else cfg.clk_rst_vif.wait_clks(HMAC_MSG_PROCESS_CYCLES);
if (do_hash_start) begin
// wait for interrupt to assert, check status and clear it
if (intr_hmac_done_en) begin
wait(cfg.intr_vif.pins[HmacDone] === 1'b1);
- check_interrupts(.interrupts((1 << HmacDone)), .check_set(1'b1));
end else begin
csr_spinwait(.ptr(ral.intr_state.hmac_done), .exp_data(1'b1));
- csr_wr(.csr(ral.intr_state), .value(1 << HmacDone));
end
end
+ csr_rd(.ptr(ral.intr_state), .value(intr_state_val));
+ csr_wr(.csr(ral.intr_state), .value(intr_state_val));
end
// if disable sha, digest should be cleared
diff --git a/hw/ip/hmac/dv/env/seq_lib/hmac_test_vectors_sha_vseq.sv b/hw/ip/hmac/dv/env/seq_lib/hmac_test_vectors_sha_vseq.sv
index fee3868..5d28b2f 100644
--- a/hw/ip/hmac/dv/env/seq_lib/hmac_test_vectors_sha_vseq.sv
+++ b/hw/ip/hmac/dv/env/seq_lib/hmac_test_vectors_sha_vseq.sv
@@ -49,7 +49,7 @@
// example: current fifo_depth=(14 words + 2 bytes), then wr last 4 bytes, design will
// process the 15th word then trigger intr_fifo_full
cfg.clk_rst_vif.wait_clks(2);
- clear_intr_fifo_full();
+ //clear_intr_fifo_full();
wait(cfg.intr_vif.pins[HmacDone] === 1'b1);
check_interrupts(.interrupts((1 << HmacDone)), .check_set(1'b1));
diff --git a/hw/ip/hmac/dv/tb/tb.sv b/hw/ip/hmac/dv/tb/tb.sv
index 9ecf845..e6948d2 100644
--- a/hw/ip/hmac/dv/tb/tb.sv
+++ b/hw/ip/hmac/dv/tb/tb.sv
@@ -20,7 +20,7 @@
wire [NUM_MAX_INTERRUPTS-1:0] interrupts;
wire intr_hmac_done;
- wire intr_fifo_full;
+ wire intr_fifo_empty;
wire intr_hmac_err;
// parameters
@@ -42,16 +42,16 @@
.tl_o ( tl_if.d2h ),
.intr_hmac_done_o ( intr_hmac_done ),
- .intr_fifo_full_o ( intr_fifo_full ),
+ .intr_fifo_empty_o ( intr_fifo_empty ),
.intr_hmac_err_o ( intr_hmac_err ),
.alert_rx_i ( alert_if_msg_push_sha_disabled.alert_rx ),
.alert_tx_o ( alert_if_msg_push_sha_disabled.alert_tx )
);
- assign interrupts[HmacDone] = intr_hmac_done;
- assign interrupts[HmacMsgFifoFull] = intr_fifo_full;
- assign interrupts[HmacErr] = intr_hmac_err;
+ assign interrupts[HmacDone] = intr_hmac_done;
+ assign interrupts[HmacMsgFifoEmpty] = intr_fifo_empty;
+ assign interrupts[HmacErr] = intr_hmac_err;
initial begin
// drive clk and rst_n from clk_if