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 72974fd
Show file tree
Hide file tree
Showing 10 changed files with 133 additions and 67 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
13 changes: 7 additions & 6 deletions hw/ip/dma/doc/registers.md
Original file line number Diff line number Diff line change
Expand Up @@ -639,20 +639,21 @@ Other values are reserved.
Status indication for DMA data movement.
- Offset: `0x58`
- Reset default: `0x0`
- Reset mask: `0x1f`
- Reset mask: `0x3f`

### Fields

```wavejson
{"reg": [{"name": "busy", "bits": 1, "attr": ["ro"], "rotate": -90}, {"name": "done", "bits": 1, "attr": ["rw1c"], "rotate": -90}, {"name": "aborted", "bits": 1, "attr": ["rw1c"], "rotate": -90}, {"name": "error", "bits": 1, "attr": ["rw1c"], "rotate": -90}, {"name": "sha2_digest_valid", "bits": 1, "attr": ["ro"], "rotate": -90}, {"bits": 27}], "config": {"lanes": 1, "fontsize": 10, "vspace": 190}}
{"reg": [{"name": "busy", "bits": 1, "attr": ["ro"], "rotate": -90}, {"name": "done", "bits": 1, "attr": ["rw1c"], "rotate": -90}, {"name": "chunk_done", "bits": 1, "attr": ["rw1c"], "rotate": -90}, {"name": "aborted", "bits": 1, "attr": ["rw1c"], "rotate": -90}, {"name": "error", "bits": 1, "attr": ["rw1c"], "rotate": -90}, {"name": "sha2_digest_valid", "bits": 1, "attr": ["ro"], "rotate": -90}, {"bits": 26}], "config": {"lanes": 1, "fontsize": 10, "vspace": 190}}
```

| Bits | Type | Reset | Name | Description |
|:------:|:------:|:-------:|:------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 31:5 | | | | Reserved |
| 4 | ro | 0x0 | sha2_digest_valid | Indicates whether the SHA2_DIGEST register contains a valid digest. This value is cleared on the initial transfer and set when the digest is written. |
| 3 | rw1c | 0x0 | error | Error occurred during the operation. ERROR_CODE register denotes the source of the error. |
| 2 | rw1c | 0x0 | aborted | Set once aborted operation drains. |
| 31:6 | | | | Reserved |
| 5 | ro | 0x0 | sha2_digest_valid | Indicates whether the SHA2_DIGEST register contains a valid digest. This value is cleared on the initial transfer and set when the digest is written. |
| 4 | rw1c | 0x0 | error | Error occurred during the operation. ERROR_CODE register denotes the source of the error. |
| 3 | rw1c | 0x0 | aborted | Set once aborted operation drains. |
| 2 | rw1c | 0x0 | chunk_done | 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. |
| 1 | rw1c | 0x0 | done | Configured DMA operation is complete. Cleared automatically by the hardware when starting a new transfer. |
| 0 | ro | 0x0 | busy | DMA operation is active if this bit is set. DMA engine clears this bit when operation is complete. This bit may be set as long as hardware handshake mode is active and triggered. |

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 72974fd

Please sign in to comment.