Skip to content

Commit

Permalink
[kmac,dv] Check FIFO empty interrupt
Browse files Browse the repository at this point in the history
  - Linked to this issue lowRISC#22341

Signed-off-by: Martin Velay <[email protected]>
  • Loading branch information
martin-velay committed Jul 9, 2024
1 parent 4a9afc9 commit d777849
Showing 1 changed file with 91 additions and 19 deletions.
110 changes: 91 additions & 19 deletions hw/ip/kmac/dv/env/kmac_scoreboard.sv
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ class kmac_scoreboard extends cip_base_scoreboard #(
bit in_edn_fetch = 0;

// CMD fields
bit [KmacCmdIdx:0] kmac_cmd;
kmac_cmd_e unchecked_kmac_cmd = CmdNone;
kmac_cmd_e checked_kmac_cmd = CmdNone;

Expand All @@ -75,6 +76,14 @@ class kmac_scoreboard extends cip_base_scoreboard #(
bit sha3_absorb;
bit sha3_squeeze;

// FIFO status bits
bit msgfifo_access;
bit fifo_empty_status;
bit fifo_full_status;
bit fifo_full_detected;
bit intr_fifo_empty_allowed;
bit fifo_empty_intr;

bit intr_kmac_done;
bit intr_fifo_empty;
bit intr_kmac_err;
Expand Down Expand Up @@ -168,6 +177,7 @@ class kmac_scoreboard extends cip_base_scoreboard #(
process_kmac_app_req_fifo();
process_kmac_app_rsp_fifo();
process_sideload_key();
predict_fifo_empty_intr();
join_none
end
endtask
Expand Down Expand Up @@ -216,19 +226,19 @@ class kmac_scoreboard extends cip_base_scoreboard #(
forever begin
wait(!cfg.under_reset);
`DV_SPINWAIT_EXIT(
forever begin
@(posedge in_edn_fetch);
// Entropy interface is native 32 bits - prim_edn_req component internally
// does as many EDN fetches as necessary to fill up the required data bus size
// of the "host".
repeat (kmac_reg_pkg::NumSeedsEntropy) begin
`DV_SPINWAIT(edn_fifos[0].get(edn_item);, "Wait EDN request")
end
`uvm_info(`gfn, "got all edn transactions", UVM_HIGH)
set_entropy_fetch(0);
forever begin
@(posedge in_edn_fetch);
// Entropy interface is native 32 bits - prim_edn_req component internally
// does as many EDN fetches as necessary to fill up the required data bus size
// of the "host".
repeat (kmac_reg_pkg::NumSeedsEntropy) begin
edn_fifos[0].get(edn_item);
end
,
wait(cfg.under_reset);
`uvm_info(`gfn, "got all edn transactions", UVM_HIGH)
set_entropy_fetch(0);
end
,
wait(cfg.under_reset);
)
end
endtask
Expand Down Expand Up @@ -599,7 +609,6 @@ class kmac_scoreboard extends cip_base_scoreboard #(

string csr_name = "";

bit msgfifo_access;
bit share0_access;
bit share1_access;

Expand All @@ -613,6 +622,11 @@ class kmac_scoreboard extends cip_base_scoreboard #(
bit data_phase_read = (!write && channel == DataChannel);
bit data_phase_write = (write && channel == DataChannel);

// Indicate that the msgfifo access is now over. Clear it at the begining of the next
// transaction as this flag is used somewhere else and needs to be actually raised for
// a non-null simulation time.
msgfifo_access = 0;

// 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);
Expand Down Expand Up @@ -757,7 +771,7 @@ class kmac_scoreboard extends cip_base_scoreboard #(
//
// ICEBOX - handle error cases
if (addr_phase_write) begin
bit [KmacCmdIdx:0] kmac_cmd = item.a_data[KmacCmdIdx:0];
kmac_cmd = item.a_data[KmacCmdIdx:0];

// Handle hash_cnt clear conditions
if (item.a_data[KmacHashCntClrIdx]) `DV_CHECK(ral.entropy_refresh_hash_cnt.predict(0));
Expand Down Expand Up @@ -1093,8 +1107,6 @@ class kmac_scoreboard extends cip_base_scoreboard #(
`uvm_info(`gfn, $sformatf("msg: %0p", msg), UVM_HIGH)
end
end
// indicate that the msgfifo access is now over
msgfifo_access = 0;
end

///////////////////////////////////////////////////
Expand Down Expand Up @@ -1179,6 +1191,64 @@ class kmac_scoreboard extends cip_base_scoreboard #(
end
endtask : process_tl_access

// The FIFO empty interrupt is raised only FIFO is actually empty, but also if all of the
// following conditions are met:
// 1- The KMAC block is not exercised by a hardware application interface.
// 2- The SHA3 block is in the Absorb state.
// 3- Software has not yet written the Process command to finish the absorption process.
// 4- 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.
virtual task predict_fifo_empty_intr();
bit cmd_process_triggered = 0;

forever @(msgfifo_access, in_kmac_app, sha3_absorb, kmac_cmd, sha3_idle) begin
// Get FIFO empty/full status directly from the DUT as the FIFO level is not modeled
csr_rd(.ptr(ral.status.fifo_empty), .value(fifo_empty_status), .backdoor(1));
csr_rd(.ptr(ral.status.fifo_full), .value(fifo_full_status), .backdoor(1));

// Latch Command Process flag
if (!cmd_process_triggered && (kmac_cmd == CmdProcess)) begin
cmd_process_triggered = 1;
end else if (sha3_idle) begin
cmd_process_triggered = 0;
end

// 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 (sha3_idle || fifo_empty_status) begin
// Delay before releasing fifo_full_detected signal to be aligned with the DUT
fork
begin
cfg.clk_rst_vif.wait_clks(3);
fifo_full_detected = 0;
end
join_none
end else if (fifo_full_status) begin
fifo_full_detected = 1;
end

// Check if conditions are met
if (!in_kmac_app && sha3_absorb && !cmd_process_triggered && fifo_full_detected) begin
intr_fifo_empty_allowed = 1;
end else begin
intr_fifo_empty_allowed = 0;
end

// Manage interrupt and check it
if (intr_fifo_empty_allowed && fifo_empty_status) begin
fifo_empty_intr = 1;
wait(!ral.intr_state.is_busy());
void'(ral.intr_state.fifo_empty.predict(.value(fifo_empty_intr),
.kind(UVM_PREDICT_DIRECT)));
`DV_CHECK_EQ(ral.intr_state.fifo_empty.get_mirrored_value(), fifo_empty_intr,
$sformatf("reg name: %0s", ral.intr_state.fifo_empty.get_full_name()))
end else begin
fifo_empty_intr = 0;
end
end
endtask : predict_fifo_empty_intr

virtual function void predict_err(bit is_sha3_err = 0, bit is_kmac_err = 0);
// set interrupt
if (!intr_kmac_err) intr_kmac_err = 1;
Expand Down Expand Up @@ -1217,9 +1287,11 @@ class kmac_scoreboard extends cip_base_scoreboard #(
first_op_after_rst = 1;

// status tracking bits
sha3_idle = ral.status.sha3_idle.get_reset();
sha3_absorb = ral.status.sha3_absorb.get_reset();
sha3_squeeze = ral.status.sha3_squeeze.get_reset();
sha3_idle = ral.status.sha3_idle.get_reset();
sha3_absorb = ral.status.sha3_absorb.get_reset();
sha3_squeeze = ral.status.sha3_squeeze.get_reset();
fifo_empty_status = ral.status.fifo_empty.get_reset();
fifo_full_status = ral.status.fifo_full.get_reset();
endfunction

// This function should be called to reset internal state to prepare for a new hash operation
Expand Down

0 comments on commit d777849

Please sign in to comment.