Skip to content

Commit

Permalink
[hw,dma,rtl] Add STATUS.chunk_done bit
Browse files Browse the repository at this point in the history
Signed-off-by: Robert Schilling <[email protected]>
  • Loading branch information
Razer6 committed Jul 24, 2024
1 parent 0eec3b9 commit 66e8043
Show file tree
Hide file tree
Showing 9 changed files with 126 additions and 61 deletions.
15 changes: 12 additions & 3 deletions hw/ip/dma/data/dma.hjson
Original file line number Diff line number Diff line change
Expand Up @@ -624,7 +624,6 @@
resval: 0x0
hwaccess: "hrw"
swaccess: "ro"
hwaccess: "hrw"
desc: '''
DMA operation is active if this bit is set.
DMA engine clears this bit when operation is complete.
Expand All @@ -641,11 +640,21 @@
'''
}
{ bits: "2"
name: "chunk_done"
resval: 0x0
hwaccess: "hrw"
desc: '''
Transfer of a single chunk is complete.
Only raised for multi-chunk memory-to-memory transfers.
Cleared automatically by the hardware when starting the transfer of a new chunk.
'''
}
{ bits: "3"
name: "aborted"
resval: 0x0
desc: "Set once aborted operation drains."
}
{ bits: "3"
{ bits: "4"
name: "error"
resval: 0x0
hwaccess: "hrw"
Expand All @@ -655,7 +664,7 @@
ERROR_CODE register denotes the source of the error.
'''
}
{ bits: "4"
{ bits: "5"
name: "sha2_digest_valid"
swaccess: "ro"
resval: 0x0
Expand Down
2 changes: 2 additions & 0 deletions hw/ip/dma/dv/env/dma_env_cov.sv
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ endgroup
covergroup dma_status_cg with function sample(
bit busy,
bit done,
bit chunk_done,
bit aborted,
bit error,
bit sha2_digest_valid
Expand All @@ -222,6 +223,7 @@ covergroup dma_status_cg with function sample(
option.name = "dma_status_cg";
cp_status_busy: coverpoint busy;
cp_status_done: coverpoint done;
cp_status_chunk_done: coverpoint chunk_done;
cp_status_aborted: coverpoint aborted;
cp_status_error: coverpoint error;
cp_sha2_digest_valid: coverpoint sha2_digest_valid;
Expand Down
15 changes: 9 additions & 6 deletions hw/ip/dma/dv/env/dma_scoreboard.sv
Original file line number Diff line number Diff line change
Expand Up @@ -1095,21 +1095,23 @@ class dma_scoreboard extends cip_base_scoreboard #(
do_read_check = 1;
end
"status": begin
bit busy, done, aborted, error, sha2_digest_valid;
bit busy, done, chunk_done, aborted, error, sha2_digest_valid;
bit exp_aborted = abort_via_reg_write;

do_read_check = 1'b0;
busy = get_field_val(ral.status.busy, item.d_data);
done = get_field_val(ral.status.done, item.d_data);
chunk_done = get_field_val(ral.status.chunk_done, item.d_data);
aborted = get_field_val(ral.status.aborted, item.d_data);
error = get_field_val(ral.status.error, item.d_data);
sha2_digest_valid = get_field_val(ral.status.sha2_digest_valid, item.d_data);

if (done || aborted || error) begin
if (done || chunk_done || aborted || error) begin
string reasons;
if (done) reasons = "Done ";
if (aborted) reasons = {reasons, "Aborted "};
if (error) reasons = {reasons, "Error" };
if (done) reasons = "Done ";
if (chunk_done) reasons = {reasons, "ChunkDone "};
if (aborted) reasons = {reasons, "Aborted "};
if (error) reasons = {reasons, "Error" };
operation_in_progress = 1'b0;
`uvm_info(`gfn, $sformatf("Detected end of DMA operation (%s)", reasons), UVM_MEDIUM)
// Clear variables
Expand Down Expand Up @@ -1138,13 +1140,14 @@ class dma_scoreboard extends cip_base_scoreboard #(
// Sample dma status and error code
cov.status_cg.sample(.busy (busy),
.done (done),
.chunk_done (chunk_done),
.aborted (aborted),
.error (error),
.sha2_digest_valid (sha2_digest_valid));
end
// Check results after each chunk of the transfer (memory-to-memory) or after the complete
// transfer (handshaking mode).
if (dma_config.is_valid_config && done) begin
if (dma_config.is_valid_config && (done || chunk_done)) begin
if (num_bytes_transferred >= dma_config.total_data_size) begin
// SHA digest (expecting zeros if unused)
// When using inline hashing, sha2_digest_valid must be raised at the end
Expand Down
4 changes: 2 additions & 2 deletions hw/ip/dma/dv/env/seq_lib/dma_base_vseq.sv
Original file line number Diff line number Diff line change
Expand Up @@ -752,12 +752,12 @@ class dma_base_vseq extends cip_base_vseq #(
csr_rd(ral.status, v);
// Collect some STATUS bit that do not generate interrupts, and inform parallel threads
// if (v[0]) ->e_busy;
if (v[2]) status[StatusAborted] = 1'b1;
if (v[3]) status[StatusAborted] = 1'b1;
// Respond to the STATUS.done and STATUS.error bits only if we're not insisting upon
// interrupt-driven completion.
if (!intr_driven) begin
if (v[1]) status[StatusDone] = 1'b1;
if (v[3]) status[StatusError] = 1'b1;
if (v[4]) status[StatusError] = 1'b1;
end
// Note: sha2_digest_valid is not a completion event
// v[12]
Expand Down
22 changes: 15 additions & 7 deletions hw/ip/dma/rtl/dma.sv
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ module dma

logic dma_state_error;
dma_ctrl_state_e ctrl_state_q, ctrl_state_d;
logic clear_go, clear_status, clear_sha_status;
logic clear_go, chunk_done, clear_status, clear_sha_status;

logic [INTR_CLEAR_SOURCES_WIDTH-1:0] clear_index_d, clear_index_q;
logic clear_index_en, intr_clear_tlul_rsp_valid;
Expand Down Expand Up @@ -607,6 +607,7 @@ module dma
clear_index_en = '0;

clear_go = 1'b0;
chunk_done = 1'b0;

// Mux the TLUL grant and response signals depending on the selected bus interface
intr_clear_tlul_gnt = reg2hw.clear_intr_bus.q[clear_index_q]? dma_host_tlul_gnt :
Expand Down Expand Up @@ -966,8 +967,9 @@ module dma
end else if (chunk_byte_d >= reg2hw.chunk_data_size.q) begin
// Conditionally clear the go bit when not being in hardware handshake mode.
// In non-hardware handshake mode, finishing one chunk should raise the done IRQ
// and done bit, and release the go bit for the next FW-controlled chunk.
// and chunk done bit, and release the go bit for the next FW-controlled chunk.
clear_go = !control_q.cfg_handshake_en;
chunk_done = !control_q.cfg_handshake_en;
ctrl_state_d = DmaIdle;
end else begin
ctrl_state_d = DmaAddrSetup;
Expand Down Expand Up @@ -1249,11 +1251,15 @@ module dma
clear_sha_status = (ctrl_state_q == DmaIdle) && (ctrl_state_d != DmaIdle) &&
reg2hw.control.initial_transfer.q;

// Set done bit and raise interrupt when we either finished a single transfer or all transfers
// in hardware handshake mode. Automatically clear the done bit when starting a new transfer
hw2reg.status.done.de = ((!cfg_abort_en) && data_move_state && clear_go) | clear_status;
// Set the done bit only when finishing all chunks. Automatically clear the done bit when
// starting a new transfer
hw2reg.status.done.de = ((!cfg_abort_en) && data_move_state && clear_go && ~chunk_done) |
clear_status;
hw2reg.status.done.d = clear_status? 1'b0 : 1'b1;

hw2reg.status.chunk_done.de = ((!cfg_abort_en) && chunk_done) | clear_status;
hw2reg.status.chunk_done.d = clear_status? 1'b0 : 1'b1;

hw2reg.status.error.de = (ctrl_state_d == DmaError) | clear_status;
hw2reg.status.error.d = clear_status? 1'b0 : 1'b1;

Expand Down Expand Up @@ -1320,8 +1326,10 @@ module dma
hw2reg.control.abort.de = hw2reg.status.aborted.de;
hw2reg.control.abort.d = 1'b0;

// interrupt management
hw2reg.intr_state.dma_done.de = reg2hw.status.done.q | test_done_interrupt;
// Interrupt management
// Raise the done interrupt either when finishing finishing a single chunk or the whole
// transfer.
hw2reg.intr_state.dma_done.de = reg2hw.status.done.q | chunk_done | test_done_interrupt;
hw2reg.intr_state.dma_done.d = 1'b1;

hw2reg.intr_state.dma_error.de = reg2hw.status.error.q | test_error_interrupt;
Expand Down
67 changes: 37 additions & 30 deletions hw/ip/dma/rtl/dma_reg_pkg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,9 @@ package dma_reg_pkg;
struct packed {
logic q;
} done;
struct packed {
logic q;
} chunk_done;
struct packed {
logic q;
logic qe;
Expand Down Expand Up @@ -260,6 +263,10 @@ package dma_reg_pkg;
logic d;
logic de;
} done;
struct packed {
logic d;
logic de;
} chunk_done;
struct packed {
logic d;
logic de;
Expand Down Expand Up @@ -316,28 +323,28 @@ package dma_reg_pkg;

// Register -> HW type
typedef struct packed {
dma_reg2hw_intr_state_reg_t intr_state; // [1169:1167]
dma_reg2hw_intr_enable_reg_t intr_enable; // [1166:1164]
dma_reg2hw_intr_test_reg_t intr_test; // [1163:1158]
dma_reg2hw_alert_test_reg_t alert_test; // [1157:1156]
dma_reg2hw_src_addr_lo_reg_t src_addr_lo; // [1155:1124]
dma_reg2hw_src_addr_hi_reg_t src_addr_hi; // [1123:1092]
dma_reg2hw_dst_addr_lo_reg_t dst_addr_lo; // [1091:1060]
dma_reg2hw_dst_addr_hi_reg_t dst_addr_hi; // [1059:1028]
dma_reg2hw_addr_space_id_reg_t addr_space_id; // [1027:1020]
dma_reg2hw_enabled_memory_range_base_reg_t enabled_memory_range_base; // [1019:987]
dma_reg2hw_enabled_memory_range_limit_reg_t enabled_memory_range_limit; // [986:954]
dma_reg2hw_range_valid_reg_t range_valid; // [953:953]
dma_reg2hw_range_regwen_reg_t range_regwen; // [952:949]
dma_reg2hw_total_data_size_reg_t total_data_size; // [948:917]
dma_reg2hw_chunk_data_size_reg_t chunk_data_size; // [916:885]
dma_reg2hw_transfer_width_reg_t transfer_width; // [884:883]
dma_reg2hw_dst_addr_limit_lo_reg_t dst_addr_limit_lo; // [882:851]
dma_reg2hw_dst_addr_limit_hi_reg_t dst_addr_limit_hi; // [850:819]
dma_reg2hw_dst_addr_almost_limit_lo_reg_t dst_addr_almost_limit_lo; // [818:787]
dma_reg2hw_dst_addr_almost_limit_hi_reg_t dst_addr_almost_limit_hi; // [786:755]
dma_reg2hw_control_reg_t control; // [754:743]
dma_reg2hw_status_reg_t status; // [742:737]
dma_reg2hw_intr_state_reg_t intr_state; // [1170:1168]
dma_reg2hw_intr_enable_reg_t intr_enable; // [1167:1165]
dma_reg2hw_intr_test_reg_t intr_test; // [1164:1159]
dma_reg2hw_alert_test_reg_t alert_test; // [1158:1157]
dma_reg2hw_src_addr_lo_reg_t src_addr_lo; // [1156:1125]
dma_reg2hw_src_addr_hi_reg_t src_addr_hi; // [1124:1093]
dma_reg2hw_dst_addr_lo_reg_t dst_addr_lo; // [1092:1061]
dma_reg2hw_dst_addr_hi_reg_t dst_addr_hi; // [1060:1029]
dma_reg2hw_addr_space_id_reg_t addr_space_id; // [1028:1021]
dma_reg2hw_enabled_memory_range_base_reg_t enabled_memory_range_base; // [1020:988]
dma_reg2hw_enabled_memory_range_limit_reg_t enabled_memory_range_limit; // [987:955]
dma_reg2hw_range_valid_reg_t range_valid; // [954:954]
dma_reg2hw_range_regwen_reg_t range_regwen; // [953:950]
dma_reg2hw_total_data_size_reg_t total_data_size; // [949:918]
dma_reg2hw_chunk_data_size_reg_t chunk_data_size; // [917:886]
dma_reg2hw_transfer_width_reg_t transfer_width; // [885:884]
dma_reg2hw_dst_addr_limit_lo_reg_t dst_addr_limit_lo; // [883:852]
dma_reg2hw_dst_addr_limit_hi_reg_t dst_addr_limit_hi; // [851:820]
dma_reg2hw_dst_addr_almost_limit_lo_reg_t dst_addr_almost_limit_lo; // [819:788]
dma_reg2hw_dst_addr_almost_limit_hi_reg_t dst_addr_almost_limit_hi; // [787:756]
dma_reg2hw_control_reg_t control; // [755:744]
dma_reg2hw_status_reg_t status; // [743:737]
dma_reg2hw_handshake_intr_enable_reg_t handshake_intr_enable; // [736:726]
dma_reg2hw_clear_intr_src_reg_t clear_intr_src; // [725:715]
dma_reg2hw_clear_intr_bus_reg_t clear_intr_bus; // [714:704]
Expand All @@ -347,14 +354,14 @@ package dma_reg_pkg;

// HW -> register type
typedef struct packed {
dma_hw2reg_intr_state_reg_t intr_state; // [701:696]
dma_hw2reg_src_addr_lo_reg_t src_addr_lo; // [695:663]
dma_hw2reg_src_addr_hi_reg_t src_addr_hi; // [662:630]
dma_hw2reg_dst_addr_lo_reg_t dst_addr_lo; // [629:597]
dma_hw2reg_dst_addr_hi_reg_t dst_addr_hi; // [596:564]
dma_hw2reg_cfg_regwen_reg_t cfg_regwen; // [563:560]
dma_hw2reg_control_reg_t control; // [559:554]
dma_hw2reg_status_reg_t status; // [553:544]
dma_hw2reg_intr_state_reg_t intr_state; // [703:698]
dma_hw2reg_src_addr_lo_reg_t src_addr_lo; // [697:665]
dma_hw2reg_src_addr_hi_reg_t src_addr_hi; // [664:632]
dma_hw2reg_dst_addr_lo_reg_t dst_addr_lo; // [631:599]
dma_hw2reg_dst_addr_hi_reg_t dst_addr_hi; // [598:566]
dma_hw2reg_cfg_regwen_reg_t cfg_regwen; // [565:562]
dma_hw2reg_control_reg_t control; // [561:556]
dma_hw2reg_status_reg_t status; // [555:544]
dma_hw2reg_error_code_reg_t error_code; // [543:528]
dma_hw2reg_sha2_digest_mreg_t [15:0] sha2_digest; // [527:0]
} dma_hw2reg_t;
Expand Down
Loading

0 comments on commit 66e8043

Please sign in to comment.