From 55d9982ecfcedef76072e28f96e14f3c229a973a Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Sun, 30 Jun 2024 09:21:53 -0700 Subject: [PATCH] [hw,dma,rtl] Set interrupt only when transition to done / error Previously, clearing the DONE or ERROR interrupt before clearing STATUS.done would lead to raise the same interrupt a second time, which could bring FW out of sync. With this change, the DONE and ERROR interrupt are only sent once, when transitioning into the DONE or ERROR state. Signed-off-by: Robert Schilling --- hw/ip/dma/data/dma.hjson | 2 +- hw/ip/dma/rtl/dma.sv | 8 +++--- hw/ip/dma/rtl/dma_reg_pkg.sv | 47 +++++++++++++++++------------------- hw/ip/dma/rtl/dma_reg_top.sv | 2 +- 4 files changed, 29 insertions(+), 30 deletions(-) diff --git a/hw/ip/dma/data/dma.hjson b/hw/ip/dma/data/dma.hjson index 53009e9cdc1d3..0852a0aae419d 100644 --- a/hw/ip/dma/data/dma.hjson +++ b/hw/ip/dma/data/dma.hjson @@ -634,7 +634,7 @@ { bits: "1" name: "done" resval: 0x0 - hwaccess: "hrw" + hwaccess: "hwo" desc: ''' Configured DMA operation is complete. Cleared automatically by the hardware when starting a new transfer. diff --git a/hw/ip/dma/rtl/dma.sv b/hw/ip/dma/rtl/dma.sv index c74aab6292b92..584cb8276d81f 100644 --- a/hw/ip/dma/rtl/dma.sv +++ b/hw/ip/dma/rtl/dma.sv @@ -1320,11 +1320,13 @@ 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 - Set interrupts only in the transition to done / error + hw2reg.intr_state.dma_done.de = (hw2reg.status.done.d & hw2reg.status.done.de) | + 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.de = (hw2reg.status.error.d & hw2reg.status.error.de) | + test_error_interrupt; hw2reg.intr_state.dma_error.d = 1'b1; hw2reg.intr_state.dma_memory_buffer_limit.de = send_memory_buffer_limit_interrupt | diff --git a/hw/ip/dma/rtl/dma_reg_pkg.sv b/hw/ip/dma/rtl/dma_reg_pkg.sv index 93e0b555b17ec..8aaf9c80506fc 100644 --- a/hw/ip/dma/rtl/dma_reg_pkg.sv +++ b/hw/ip/dma/rtl/dma_reg_pkg.sv @@ -164,9 +164,6 @@ package dma_reg_pkg; struct packed { logic q; } busy; - struct packed { - logic q; - } done; struct packed { logic q; logic qe; @@ -316,28 +313,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; // [1168:1166] + dma_reg2hw_intr_enable_reg_t intr_enable; // [1165:1163] + dma_reg2hw_intr_test_reg_t intr_test; // [1162:1157] + dma_reg2hw_alert_test_reg_t alert_test; // [1156:1155] + dma_reg2hw_src_addr_lo_reg_t src_addr_lo; // [1154:1123] + dma_reg2hw_src_addr_hi_reg_t src_addr_hi; // [1122:1091] + dma_reg2hw_dst_addr_lo_reg_t dst_addr_lo; // [1090:1059] + dma_reg2hw_dst_addr_hi_reg_t dst_addr_hi; // [1058:1027] + dma_reg2hw_addr_space_id_reg_t addr_space_id; // [1026:1019] + dma_reg2hw_enabled_memory_range_base_reg_t enabled_memory_range_base; // [1018:986] + dma_reg2hw_enabled_memory_range_limit_reg_t enabled_memory_range_limit; // [985:953] + dma_reg2hw_range_valid_reg_t range_valid; // [952:952] + dma_reg2hw_range_regwen_reg_t range_regwen; // [951:948] + dma_reg2hw_total_data_size_reg_t total_data_size; // [947:916] + dma_reg2hw_chunk_data_size_reg_t chunk_data_size; // [915:884] + dma_reg2hw_transfer_width_reg_t transfer_width; // [883:882] + dma_reg2hw_dst_addr_limit_lo_reg_t dst_addr_limit_lo; // [881:850] + dma_reg2hw_dst_addr_limit_hi_reg_t dst_addr_limit_hi; // [849:818] + dma_reg2hw_dst_addr_almost_limit_lo_reg_t dst_addr_almost_limit_lo; // [817:786] + dma_reg2hw_dst_addr_almost_limit_hi_reg_t dst_addr_almost_limit_hi; // [785:754] + dma_reg2hw_control_reg_t control; // [753:742] + dma_reg2hw_status_reg_t status; // [741: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] diff --git a/hw/ip/dma/rtl/dma_reg_top.sv b/hw/ip/dma/rtl/dma_reg_top.sv index 094acf3250ba8..7bbec99c19ad3 100644 --- a/hw/ip/dma/rtl/dma_reg_top.sv +++ b/hw/ip/dma/rtl/dma_reg_top.sv @@ -1441,7 +1441,7 @@ module dma_reg_top ( // to internal hardware .qe (status_flds_we[1]), - .q (reg2hw.status.done.q), + .q (), .ds (), // to register interface (read)