Skip to content

Commit

Permalink
[hw,dma,rtl] Use a status interrupt and interrupt prims
Browse files Browse the repository at this point in the history
Signed-off-by: Robert Schilling <[email protected]>
  • Loading branch information
Razer6 committed Oct 31, 2024
1 parent 2fd17be commit 45ecec8
Show file tree
Hide file tree
Showing 9 changed files with 59 additions and 44 deletions.
2 changes: 2 additions & 0 deletions hw/ip/dma/data/dma.hjson
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,11 @@
interrupt_list: [
{ name: "dma_done"
desc: "DMA operation has been completed."
type: "status"
}
{ name: "dma_error"
desc: "DMA error has occurred. DMA_STATUS.error_code register shows the details."
type: "status"
}
]
alert_list: [
Expand Down
6 changes: 3 additions & 3 deletions hw/ip/dma/doc/registers.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,14 +76,14 @@ Interrupt State Register
### Fields

```wavejson
{"reg": [{"name": "dma_done", "bits": 1, "attr": ["rw1c"], "rotate": -90}, {"name": "dma_error", "bits": 1, "attr": ["rw1c"], "rotate": -90}, {"bits": 30}], "config": {"lanes": 1, "fontsize": 10, "vspace": 110}}
{"reg": [{"name": "dma_done", "bits": 1, "attr": ["ro"], "rotate": -90}, {"name": "dma_error", "bits": 1, "attr": ["ro"], "rotate": -90}, {"bits": 30}], "config": {"lanes": 1, "fontsize": 10, "vspace": 110}}
```

| Bits | Type | Reset | Name | Description |
|:------:|:------:|:-------:|:----------|:--------------------------------------------------------------------------|
| 31:2 | | | | Reserved |
| 1 | rw1c | 0x0 | dma_error | DMA error has occurred. DMA_STATUS.error_code register shows the details. |
| 0 | rw1c | 0x0 | dma_done | DMA operation has been completed. |
| 1 | ro | 0x0 | dma_error | DMA error has occurred. DMA_STATUS.error_code register shows the details. |
| 0 | ro | 0x0 | dma_done | DMA operation has been completed. |

## INTR_ENABLE
Interrupt Enable Register
Expand Down
12 changes: 8 additions & 4 deletions hw/ip/dma/dv/env/dma_scoreboard.sv
Original file line number Diff line number Diff line change
Expand Up @@ -809,10 +809,6 @@ class dma_scoreboard extends cip_base_scoreboard #(
// that may be changed according to the new enable bits.
predict_interrupts(CSRtoIntrLatency, `gmv(ral.intr_state), item.a_data);
end
"intr_state": begin
// Writing 1 to an INTR_STATE bit clears the corresponding asserted interrupt.
predict_interrupts(CSRtoIntrLatency, item.a_data & `gmv(ral.intr_enable), 0);
end
"intr_test": begin
`uvm_info(`gfn, $sformatf("intr_test write 0x%x with enables 0x%0x",
item.a_data, intr_enable), UVM_HIGH)
Expand Down Expand Up @@ -953,6 +949,14 @@ class dma_scoreboard extends cip_base_scoreboard #(
index = get_index_from_reg_name(csr.get_name());
dma_config.intr_src_wr_val[index] = item.a_data;
end
"status": begin
bit done, error;
done = get_field_val(ral.status.done, item.a_data);
error = get_field_val(ral.status.error, item.a_data);
// Clearing the status bits also clears the status interrupt
predict_interrupts(CSRtoIntrLatency, done << DMA_DONE & `gmv(ral.intr_enable), 0);
predict_interrupts(CSRtoIntrLatency, error << DMA_ERROR & `gmv(ral.intr_enable), 0);
end
"control": begin
bit go, initial_transfer, start_transfer;
// Update the 'Aborted' prediction in response to setting the CONTROL.abort bit
Expand Down
50 changes: 31 additions & 19 deletions hw/ip/dma/rtl/dma.sv
Original file line number Diff line number Diff line change
Expand Up @@ -1079,17 +1079,39 @@ module dma
assign sha2_data.mask = {<<1{req_dst_be_q}};

// Interrupt logic
logic test_done_interrupt;
logic test_error_interrupt;
prim_intr_hw #(
.IntrT ( "Status" )
) u_intr_dma_done (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.event_intr_i ( reg2hw.status.done.q ),
.reg2hw_intr_enable_q_i ( reg2hw.intr_enable.dma_done.q ),
.reg2hw_intr_test_q_i ( reg2hw.intr_test.dma_done.q ),
.reg2hw_intr_test_qe_i ( reg2hw.intr_test.dma_done.qe ),
.reg2hw_intr_state_q_i ( reg2hw.intr_state.dma_done.q ),
.hw2reg_intr_state_de_o ( hw2reg.intr_state.dma_done.de ),
.hw2reg_intr_state_d_o ( hw2reg.intr_state.dma_done.d ),
.intr_o ( intr_dma_done_o )
);

prim_intr_hw #(
.IntrT ( "Status" )
) u_intr_error (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.event_intr_i ( reg2hw.status.error.q ),
.reg2hw_intr_enable_q_i ( reg2hw.intr_enable.dma_error.q ),
.reg2hw_intr_test_q_i ( reg2hw.intr_test.dma_error.q ),
.reg2hw_intr_test_qe_i ( reg2hw.intr_test.dma_error.qe ),
.reg2hw_intr_state_q_i ( reg2hw.intr_state.dma_error.q ),
.hw2reg_intr_state_de_o ( hw2reg.intr_state.dma_error.de ),
.hw2reg_intr_state_d_o ( hw2reg.intr_state.dma_error.d ),
.intr_o ( intr_dma_error_o )
);

logic data_move_state;
logic update_dst_addr_reg, update_src_addr_reg;

assign test_done_interrupt = reg2hw.intr_test.dma_done.q && reg2hw.intr_test.dma_done.qe;
assign test_error_interrupt = reg2hw.intr_test.dma_error.q && reg2hw.intr_test.dma_error.qe;

// Signal interrupt controller whenever an enabled interrupt info bit is set
assign intr_dma_done_o = reg2hw.intr_state.dma_done.q && reg2hw.intr_enable.dma_done.q;
assign intr_dma_error_o = reg2hw.intr_state.dma_error.q && reg2hw.intr_enable.dma_error.q;

assign data_move_state = (ctrl_state_q == DmaSendWrite) ||
(ctrl_state_q == DmaWaitWriteResponse) ||
Expand All @@ -1114,8 +1136,6 @@ module dma
transfer_remaining_bytes : chunk_remaining_bytes;

always_comb begin
hw2reg = '0;

// Clear the go bit if we are in a single transfer and finished the DMA operation,
// hardware handshake mode when we finished all transfers, or when aborting the transfer.
hw2reg.control.go.de = clear_go || cfg_abort_en;
Expand Down Expand Up @@ -1199,6 +1219,7 @@ module dma
// SHA2-512: digest[0-7][63:0] store the 512-bit digest.
for (int i = 0; i < NR_SHA_DIGEST_ELEMENTS; i++) begin
hw2reg.sha2_digest[i].de = sha2_digest_set | clear_sha_status;
hw2reg.sha2_digest[i].d = '0;
end

// Only mux the digest data when sha2_digest_set is set. Setting the digest happens during the
Expand Down Expand Up @@ -1251,15 +1272,6 @@ module dma
hw2reg.control.abort.de = hw2reg.status.aborted.de;
hw2reg.control.abort.d = 1'b0;

// 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;
hw2reg.intr_state.dma_error.d = 1'b1;

// Clear the SHA2 digests if the SHA2 valid flag is cleared (RW1C)
if (reg2hw.status.sha2_digest_valid.qe & reg2hw.status.sha2_digest_valid.q) begin
for (int i = 0; i < NR_SHA_DIGEST_ELEMENTS; i++) begin
Expand Down
22 changes: 7 additions & 15 deletions hw/ip/dma/rtl/dma_reg_top.sv
Original file line number Diff line number Diff line change
Expand Up @@ -121,11 +121,8 @@ module dma_reg_top (
// Define SW related signals
// Format: <reg>_<field>_{wd|we|qs}
// or <reg>_{wd|we|qs} if field == 1 or 0
logic intr_state_we;
logic intr_state_dma_done_qs;
logic intr_state_dma_done_wd;
logic intr_state_dma_error_qs;
logic intr_state_dma_error_wd;
logic intr_enable_we;
logic intr_enable_dma_done_qs;
logic intr_enable_dma_done_wd;
Expand Down Expand Up @@ -308,16 +305,16 @@ module dma_reg_top (
// F[dma_done]: 0:0
prim_subreg #(
.DW (1),
.SwAccess(prim_subreg_pkg::SwAccessW1C),
.SwAccess(prim_subreg_pkg::SwAccessRO),
.RESVAL (1'h0),
.Mubi (1'b0)
) u_intr_state_dma_done (
.clk_i (clk_i),
.rst_ni (rst_ni),

// from register interface
.we (intr_state_we),
.wd (intr_state_dma_done_wd),
.we (1'b0),
.wd ('0),

// from internal hardware
.de (hw2reg.intr_state.dma_done.de),
Expand All @@ -335,16 +332,16 @@ module dma_reg_top (
// F[dma_error]: 1:1
prim_subreg #(
.DW (1),
.SwAccess(prim_subreg_pkg::SwAccessW1C),
.SwAccess(prim_subreg_pkg::SwAccessRO),
.RESVAL (1'h0),
.Mubi (1'b0)
) u_intr_state_dma_error (
.clk_i (clk_i),
.rst_ni (rst_ni),

// from register interface
.we (intr_state_we),
.wd (intr_state_dma_error_wd),
.we (1'b0),
.wd ('0),

// from internal hardware
.de (hw2reg.intr_state.dma_error.de),
Expand Down Expand Up @@ -3004,11 +3001,6 @@ module dma_reg_top (
end

// Generate write-enables
assign intr_state_we = addr_hit[0] & reg_we & !reg_error;

assign intr_state_dma_done_wd = reg_wdata[0];

assign intr_state_dma_error_wd = reg_wdata[1];
assign intr_enable_we = addr_hit[1] & reg_we & !reg_error;

assign intr_enable_dma_done_wd = reg_wdata[0];
Expand Down Expand Up @@ -3166,7 +3158,7 @@ module dma_reg_top (
// Assign write-enables to checker logic vector.
always_comb begin
reg_we_check = '0;
reg_we_check[0] = intr_state_we;
reg_we_check[0] = 1'b0;
reg_we_check[1] = intr_enable_we;
reg_we_check[2] = intr_test_we;
reg_we_check[3] = alert_test_we;
Expand Down
4 changes: 2 additions & 2 deletions sw/device/lib/dif/autogen/dif_dma_autogen.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ static bool dma_get_irq_bit_index(dif_dma_irq_t irq,
}

static dif_irq_type_t irq_types[] = {
kDifIrqTypeEvent,
kDifIrqTypeEvent,
kDifIrqTypeStatus,
kDifIrqTypeStatus,
};

OT_WARN_UNUSED_RESULT
Expand Down
2 changes: 1 addition & 1 deletion sw/device/lib/dif/autogen/dif_dma_autogen_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ TEST_F(IrqGetTypeTest, Success) {
dif_irq_type_t type;

EXPECT_DIF_OK(dif_dma_irq_get_type(&dma_, kDifDmaIrqDmaDone, &type));
EXPECT_EQ(type, kDifIrqTypeEvent);
EXPECT_EQ(type, kDifIrqTypeStatus);
}

class IrqGetStateTest : public DmaTest {};
Expand Down
3 changes: 3 additions & 0 deletions sw/device/lib/testing/autogen/isr_testutils.c
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ void isr_testutils_csrng_isr(
}

void isr_testutils_dma_isr(plic_isr_ctx_t plic_ctx, dma_isr_ctx_t dma_ctx,
bool mute_status_irq,
top_earlgrey_plic_peripheral_t *peripheral_serviced,
dif_dma_irq_t *irq_serviced) {
// Claim the IRQ at the PLIC.
Expand Down Expand Up @@ -243,6 +244,8 @@ void isr_testutils_dma_isr(plic_isr_ctx_t plic_ctx, dma_isr_ctx_t dma_ctx,
CHECK_DIF_OK(dif_dma_irq_get_type(dma_ctx.dma, irq, &type));
if (type == kDifIrqTypeEvent) {
CHECK_DIF_OK(dif_dma_irq_acknowledge(dma_ctx.dma, irq));
} else if (mute_status_irq) {
CHECK_DIF_OK(dif_dma_irq_set_enabled(dma_ctx.dma, irq, kDifToggleDisabled));
}

// Complete the IRQ at the PLIC.
Expand Down
2 changes: 2 additions & 0 deletions sw/device/lib/testing/autogen/isr_testutils.h
Original file line number Diff line number Diff line change
Expand Up @@ -691,11 +691,13 @@ void isr_testutils_csrng_isr(
*
* @param plic_ctx A PLIC ISR context handle.
* @param dma_ctx A(n) dma ISR context handle.
* @param mute_status_irq set to true to disable the serviced status type IRQ.
* @param[out] peripheral_serviced Out param for the peripheral that was
* serviced.
* @param[out] irq_serviced Out param for the IRQ that was serviced.
*/
void isr_testutils_dma_isr(plic_isr_ctx_t plic_ctx, dma_isr_ctx_t dma_ctx,
bool mute_status_irq,
top_earlgrey_plic_peripheral_t *peripheral_serviced,
dif_dma_irq_t *irq_serviced);

Expand Down

0 comments on commit 45ecec8

Please sign in to comment.