Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[hmac,dv] Fix fifo_empty interrupt #25683

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
141 changes: 83 additions & 58 deletions hw/ip/hmac/dv/env/hmac_scoreboard.sv
Original file line number Diff line number Diff line change
Expand Up @@ -369,9 +369,9 @@ task hmac_scoreboard::process_tl_access(tl_seq_item item, tl_channels_e channel,
// Update expected status register
if (csr_name == "status") begin
hmac_status_data = (hmac_idle << HmacStaIdle) |
(hmac_fifo_empty << HmacStaMsgFifoEmpty) |
(hmac_fifo_full << HmacStaMsgFifoFull) |
(hmac_fifo_depth << HmacStaMsgFifoDepthLsb);
(hmac_fifo_empty << HmacStaMsgFifoEmpty) |
(hmac_fifo_full << HmacStaMsgFifoFull) |
(hmac_fifo_depth << HmacStaMsgFifoDepthLsb);
void'(ral.status.predict(.value(hmac_status_data), .kind(UVM_PREDICT_READ)));
// Update expected FIFO Empty interrupt register
end else if (csr_name == "intr_state") begin
Expand Down Expand Up @@ -478,8 +478,19 @@ task hmac_scoreboard::process_tl_access(tl_seq_item item, tl_channels_e channel,
return;
end
"status": begin
if (!do_cycle_accurate_check || cfg.sar_skip_ctxt) begin
do_read_check = 0;
bit [5:0] rd_fifo_depth = item.d_data[HmacStaMsgFifoDepthMsb:HmacStaMsgFifoDepthLsb];
do_read_check = 0;
if (!cfg.sar_skip_ctxt) begin
// We don't really need to be cycle accurate for this status register, instead we
// tolerate +1
if ((`gmv(ral.status.fifo_depth) != rd_fifo_depth) &&
(`gmv(ral.status.fifo_depth)+1 != rd_fifo_depth)) begin
`uvm_error(`gfn, $sformatf({"Check failed, read status.fifo_depth is not matching ",
"expected value, not even with tolerance of +1: got 0x%0d but exp 0x%0h"},
rd_fifo_depth, `gmv(ral.status.fifo_depth)))
end else begin
do_read_check = 1; // Still perform check as this register holds other fields
end
end
if (cfg.en_cov) cov.status_cg.sample(item.d_data, `gmv(ral.cfg));
end
Expand Down Expand Up @@ -594,7 +605,7 @@ task hmac_scoreboard::hmac_process_fifo_wr();
if ((hmac_wr_cnt - hmac_rd_cnt) == HMAC_MSG_FIFO_DEPTH_WR) begin
wait((hmac_wr_cnt - hmac_rd_cnt) < HMAC_MSG_FIFO_DEPTH_WR);
end
@(negedge cfg.clk_rst_vif.clk);
cfg.clk_rst_vif.wait_n_clks(1);
if (!hmac_stopped) begin
hmac_wr_cnt++;
`uvm_info(`gfn, $sformatf("increase wr cnt %0d", hmac_wr_cnt), UVM_HIGH)
Expand All @@ -607,60 +618,74 @@ endtask : hmac_process_fifo_wr
task hmac_scoreboard::hmac_process_fifo_status();
bit pre_fifo_empty_intr;
forever @(hmac_wr_cnt, hmac_rd_cnt, hmac_process, hmac_start, hmac_stopped, hmac_continue) begin
// Store hmac_process and hmac_start to be able to detect when it goes up, as it could remain
// up for a while
bit hmac_process_posedge = hmac_process & ~hmac_process_last;
bit hmac_start_posedge = hmac_start & ~hmac_start_last;
bit hmac_stopped_posedge = hmac_stopped & ~hmac_stopped_last;
bit hmac_continue_posedge = hmac_continue & ~hmac_continue_last;

// Store last value to be able to detect signal change
hmac_process_last = hmac_process;
hmac_stopped_last = hmac_stopped;
hmac_start_last = hmac_start;
hmac_continue_last = hmac_continue;

// when hmac_wr_cnt and hmac_rd_cnt update at the same time, wait the clock rising edge
// to guarantee get both update and at the same time as the DUT
cfg.clk_rst_vif.wait_clks(1);

// Compute FIFO level flags
hmac_fifo_depth = hmac_wr_cnt - hmac_rd_cnt;
hmac_fifo_full = hmac_fifo_depth == HMAC_MSG_FIFO_DEPTH_WR;
hmac_fifo_empty = hmac_fifo_depth == 0;

// The FIFO empty interrupt is raised only if the message FIFO is actually writable by
// software, i.e., if all of the following conditions are met:
// 1- The HMAC block is not running in HMAC mode and performing the second round of
// computing the final hash of the outer key as well as the result of the first round
// using the inner key.
// 2- Software has not yet written the Process or Stop command to finish the hashing
// operation.
// 3- The message FIFO must also have been full previously. Otherwise, the hardware empties
// the FIFO faster than software can fill it and there is no point in interrupting the
// software to inform it about the message FIFO being empty.
if (fifo_full_detected && hmac_fifo_empty) begin
pre_fifo_empty_intr = 1;
end else begin
pre_fifo_empty_intr = 0;
end
// Spawn a thread as an event from the list above might occurs during the time we wait
// for the clock cycle (later in this thread).
fork begin
// Store hmac_process and hmac_start to be able to detect when it goes up, as it could remain
// up for a while
bit hmac_process_posedge = hmac_process & ~hmac_process_last;
bit hmac_start_posedge = hmac_start & ~hmac_start_last;
bit hmac_stopped_posedge = hmac_stopped & ~hmac_stopped_last;
bit hmac_continue_posedge = hmac_continue & ~hmac_continue_last;

// Store last value to be able to detect signal change
hmac_process_last = hmac_process;
hmac_stopped_last = hmac_stopped;
hmac_start_last = hmac_start;
hmac_continue_last = hmac_continue;

// when hmac_wr_cnt and hmac_rd_cnt update at the same time, wait the clock rising edge
// to guarantee get both update and at the same time as the DUT
cfg.clk_rst_vif.wait_clks(1);

// Compute FIFO level flags
hmac_fifo_depth = hmac_wr_cnt - hmac_rd_cnt;
hmac_fifo_full = hmac_fifo_depth == HMAC_MSG_FIFO_DEPTH_WR;
hmac_fifo_empty = hmac_fifo_depth == 0;

// Check whether FIFO full should be cleared (for another reason than the emptiness)
if (hmac_start_posedge || hmac_process_posedge || hmac_stopped_posedge ||
hmac_continue_posedge) begin
fifo_full_detected = 0;
end

// Delay FIFO empty signal to be aligned with the DUT behavior
fork
begin
cfg.clk_rst_vif.wait_clks(1);
fifo_empty_intr = pre_fifo_empty_intr;
// The FIFO empty interrupt is raised only if the message FIFO is actually writable by
// software, i.e., if all of the following conditions are met:
// 1- The HMAC block is not running in HMAC mode and performing the second round of
// computing the final hash of the outer key as well as the result of the first round
// using the inner key.
// 2- Software has not yet written the Process or Stop command to finish the hashing
// operation.
// 3- The message FIFO must also have been full previously. Otherwise, the hardware empties
// the FIFO faster than software can fill it and there is no point in interrupting the
// software to inform it about the message FIFO being empty.
if (fifo_full_detected && hmac_fifo_empty) begin
pre_fifo_empty_intr = 1;
end else begin
pre_fifo_empty_intr = 0;
end
join_none

// Check whether FIFO full has been detected for the ongoing message but the retrictions cases
// have the priority in case full is set at the same moment
if (hmac_fifo_empty || hmac_start_posedge || hmac_process_posedge ||
hmac_stopped_posedge || hmac_continue_posedge) begin
fifo_full_detected = 0;
end else if (hmac_fifo_full) begin
fifo_full_detected = 1;
end

// Delay FIFO empty signal to be aligned with the DUT behavior
fork
begin
cfg.clk_rst_vif.wait_clks(1);
fifo_empty_intr = pre_fifo_empty_intr;
end
join_none

// Ensures that FIFO levels have been updated as a read and write may have race conditions
// and 2 processes are spawned in parallel. And wait on the second negative edge to be sure
// that empty/full flags will be up to date.
cfg.clk_rst_vif.wait_n_clks(2);
// Reset full flag when emptiness has been reached
if (hmac_fifo_empty) begin
fifo_full_detected = 0;
// Check whether FIFO full has been detected for the ongoing message but the retrictions cases
// have the priority in case full is set at the same moment
end else if (hmac_fifo_full) begin
fifo_full_detected = 1;
end
end join_none
end
endtask : hmac_process_fifo_status

Expand Down
Loading