diff --git a/docs/source/Verification/VerifHEEP.md b/docs/source/Verification/VerifHEEP.md
index e69de29bb..707f543af 100644
--- a/docs/source/Verification/VerifHEEP.md
+++ b/docs/source/Verification/VerifHEEP.md
@@ -0,0 +1,184 @@
+# VerifHeep
+
+## Introduction
+
+**VerifHeep** is a Python library designed to provide various methods for implementing a verification and testing environment tailored specifically for X-Heep.
+
+In particular, VerifHeep enables **on FPGA** verification, testing and performance estimation, offering a tenfold speed improvement compared to traditional simulation tools like Verilator or QuestaSim.
+This library employs a _software-based_ verification approach, meaning it conducts its tests by compiling a specific software application, running it on the target unit, and analyzing the results. The user is required to develop an application that can test and verify the target unit and display the data in accordance with specific formats.
+
+This library has been developed with a focus on verifying and characterizing external accelerators, such as the _im2col Smart Peripheral Controller_ (SPC).
+In fact, the `scripts/examples` folder contains the verification environment for this very accelerator, `im2col_verificaiton.py`, along with `im2col_spc_plotter.py` to plot the acquired data.
+Users are encouraged to refer to this file as a real-world example of how to use the library and can use it as starting point to develop their own verification environment.
+
+This guide aims to address any questions that might arise from studying the *im2col_spc* example. It provides a detailed explanation of each method in VerifHeep, along with the parameters required for its proper functioning.
+
+> :bulb: The FPGA synthesis must be performed with the **Xilinx scan chains** enabled, as these will be used to load the program.
+Additionally, the EPFL programmer will be used for serial communication with the board. Without these two lines of communication, it would be impossible to load the program and read the serial stream.
+
+## Methods description
+
+#### __init__
+
+_Purpose_:
+The initialization function is used to create the VerifHeep object. During this process, it's required to indicate the target of the verification and its directory. Furthermore, an optimization flag can be set when synthesis or simulation module building will be performed.
+
+_Parameters_:
+- **target**: Indicated the target of the verification environment, must be one of the following:
+ - `pynq-z2`
+ - `questasim`
+ - `verilator`
+- **xheep_dir**: Sets the directory of the X-Heep project, necessary to run scripts.
+- **opt_en**: By default set to _false_, this flag indicates whether optimization should be performed when building the simulation model. Available **only** with QuestaSim!
+
+#### compileModel
+
+_Purpose_:
+This method is used to compile a simulation model for both Verilator and QuestaSim, i.e. run _make mcu-gen_, provided they are properly installed on the host system.
+
+_Parameters_:
+- **mem_banks**: By default set to 6, this flag indicates how many memory banks will be included in the X-Heep model. No interleaved banks are supported.
+- **cpu**: By default set to `cv32e40px`, this flags indicates which CPU will be included in the model.
+- **bus**: By default set to `1toN`, this flag indicates the bus type.
+
+#### buildModel
+
+_Purpose_:
+This method is used to either build a simulation model for Verilator or QuestaSim or to synthesize the project with Xilinx Vivado, provided they are properly installed on the host system.
+
+_Parameters_:
+- **mem_banks**: By default set to *6*, this flag indicates how many memory banks will be included. No interleaved banks are supported.
+- **cpu**: By default set to `cv32e40px`, this flags indicates which CPU will be included.
+- **bus**: By default set to `1toN`, this flag indicates the bus type.
+
+#### serialBegin
+
+_Purpose_:
+This method is used to set up the serial communication with the _pynq-z2_ FPGA board.
+
+> :bulb: **Tip:** Checkout which USB port is connected to the _pynq-z2_ by running a simple hello world (no flash load since the scan chains are used).
+Set the USB port parameter of the verification environment as a global variable to quickly modify it. Its value might change!
+
+_Parameters_:
+- **port**: Indicates the USB port connected to the EPFL programmer for the pynq-z2.
+- **baudrate**: Indicates the connection speed, usually set to 9600.
+
+_Return value_:
+- **Outcome of the connection**, which is _False_ for unsuccessful.
+
+#### setupDeb
+
+_Purpose_:
+This method is used to set up the GDB debugger. It creates a process on which the debug communication will be run, thus making this function conveniently non-blocking.
+
+> :warning: This method should obviously be called at the beginning of the verification process, but not only then! Empirical evidence suggests **resetting the debug connection** approximately **every 100 iterations** to ensure reliable operation.
+
+_Parameters_:
+None
+
+#### stopDeb
+
+_Purpose_:
+This method is used to close the debugger. Useful both at the end of a script or during the cyclical reset of the debug connection, as explained before.
+
+_Parameters_:
+None
+
+#### genInputDataset
+
+_Purpose_:
+This method is used to generate random data that the application can use to perform verification. It's possible to set the range of the data, the dimension of the array, the datatype and its variable identifier. In addition, it's possible to obtain a single _.h_ file or both a _.c_ and a _.h_ file.
+
+_Parameters_:
+- **dataset_size**: Indicates the size of the input array to be generated.
+- **parameters**: This optional argument is a *dictionary* of parameters that might be useful for the application. It has *no impact on the value generation* but it will be written in the *.h* file.
+- **row_size**: By default set to *0*, this parameter is used to organize the array in the case of matrix generation. In other words, every *row_size* words, the matrix will have a new line.
+- **range_min** / **range_max**: These are used to set the range of the random data. They can be both negative and float, if the datatype supports it.
+- **dataset_dir**: Indicates the directory in which the generated file will be saved, including the name of the file itself.
+- **dataset_dir_c**: By default *empty*, when set to a directory it forces the method to generate both a _.c_ and a _.h_, the first with the data definition and the second with its declaration.
+- **dataset_name**: Indicates the name of the dataset.
+- **datatype**: By default set to *uint32_t*, indicates the datatype of the array to be generated.
+
+#### genGoldenResult
+
+_Purpose_:
+This method is used to generate golden data from an input dataset, enabling applications to verify the functionality of a unit or accelerator. This feature is performed by a user-defined function, passed as a parameter, which processes the input data.
+
+Similar to input generation, users can specify the data range, array dimensions, data type, and variable identifier. Additionally, the output can be configured to produce either a single _.h_ file or both a _.c_ and a _.h_ file.
+
+_Parameters_:
+- **function**: This function is the one used by the method to generate the golden results.
+- **golden_size**: Indicates the size of the output array to be computed.
+- **parameters**:This optional argument is a *dictionary* of parameters that might be useful for the application. It has no impact on the golden result computation but it will be written in the *.h* file.
+- **row_size**: By default set to *0*, this parameter is used to organize the array in the case of matrix generation. In other words, every *row_size* words, the matrix will have a new line.
+- **range_min** / **range_max**: These are used to set the range of the random data. They can be both negative and float, if the datatype supports it.
+- **golden_dir**: Indicates the directory in which the generated file will be saved, including the name of the file itself.
+- **golden_dir_c**: By default *empty*, when set to a directory it forces the method to generate both a _.c_ and a _.h_, the first with the data definition and the second with its declaration.
+- **input_dir**: Indicates the input data used to generate the golden result.
+- **golden_name**: Indicates the name of the golden result array.
+- **output_datatype**: By default set to *uint32_t*, indicates the datatype of the array to be computed.
+
+#### modifyFile
+
+_Purpose_:
+This method is simple yet very useful in particular situations. It allows the user to modify a row with a replacement of its choice. It can be used to modify _#define_ that could change the behaviour of the application.
+
+For example, the im2col SPC verification example makes use of this feature twice. The first time it modifies the format of the output of the application to be adherent to the verification procedure (which by default it is not).
+The second time it reduces the verification times, by avoiding to repeat unnecessary tests.
+
+_Parameters_:
+- **file_dir**: Indicates the directory of the file that the user wants to modify.
+- **pattern**: Indicates the pattern to look for in the file, using the library **re**.
+- **replacement**: Indicates the row that will be put in place instead of the pattern found.
+
+#### chronoStart/chronoStop
+
+_Purpose_:This method is used to track the execution time of an iteration and, by extension, to estimate the total execution time of the verification process.
+
+_Parameters_:
+None
+
+#### chronoExecutionEst
+
+_Purpose_:This method estimates the total execution time of the verification process, assuming the verification consists of a loop with N iterations. It requires that the `_chronoStart_` method is called at the beginning and the `_chronoStop_` method is called at the end of each iteration.
+
+_Parameters_:
+- **loop_size**: Size of the loop, i.e. number of iterations of the entire verification process. If it's composed of nested loops, the total number of iterations is obtained by multiplying the size of each loop.
+
+_Return value_:
+- **Remaining time**, a _dictionary_:
+ - _"hours"_
+ - _"minutes"_
+ - _"seconds"_
+
+#### launchTest
+
+_Purpose_:
+This method is crucial in the verification process, as it's in charge of compiling the application, loading it on the FPGA using the scan chains and GDB, waiting for the results and storing then in *self.results*.
+
+Its important to note that this method expects a **specific output format** from the application, which needs to be strictly respected otherwise the whole verification would be disrupted.
+By default, this is the format expected:
+
+
+
test_id:cycles:outcome
+ ...
+ &
+
+
+An application can send N lines composed of:
+- **test_id**: the ID of the test being performed. A single application can test multiple aspects or features, so different tests can be performed in a single run. In the **im2col_spc** application, this is exactly what happens: three different tests are perfomed each run.
+- **cycles**: the number of cycles needed by the system to perform that specific test. In order to keep track of the execution cycles, a `timer_sdk` has been developed. Please refer to `example_timer_sdk` for a practical implementation.
+- **outcome**: the outcome of the verification performed by the application itself. For example, the application might set up the DMA to perform a transaction and then check that the result corresponds to the golden result.
+
+Each of these fields can be **left blank** or with whatever ASCII character, but the format has to be followed nonetheless. For example, one could be interested only in verify its design, avoiding the performance estimation. In such case, _cycles_ could be always set to _0_.
+
+At the end of the run, the application **must send the end character** `&`.
+
+If needed, the format of the data sent by the application can be modified by changing the _pattern_ parameter.
+
+_Parameters_:
+- **example_name**: Name of the example folder in X-Heep sw/application. e.g. For the DMA verification, this field would have been *example_dma*.
+- **input_size**: This field will be appended to the data obtained by the simulation, not mandatory but might be useful for data processing.
+- **pattern**: By default set to *test_id:cycles:outcome*. It can be changed by the user, with **caution**.
+- **en_timeout_term**: By default set to _False_, if enabled it terminates the application in case that the board doesn't reply in time.
+
diff --git a/hw/core-v-mini-mcu/ao_peripheral_subsystem.sv b/hw/core-v-mini-mcu/ao_peripheral_subsystem.sv
index 7b91998c7..bec386b79 100644
--- a/hw/core-v-mini-mcu/ao_peripheral_subsystem.sv
+++ b/hw/core-v-mini-mcu/ao_peripheral_subsystem.sv
@@ -152,6 +152,8 @@ module ao_peripheral_subsystem
logic [23:0] cio_gpio_en_unused;
/* DMA signals */
+ logic dma_clk_gate_en_ni[core_v_mini_mcu_pkg::DMA_CH_NUM-1:0];
+ power_manager_out_t dma_subsystem_pwr_ctrl_o[core_v_mini_mcu_pkg::DMA_CH_NUM-1:0];
logic [DMA_GLOBAL_TRIGGER_SLOT_NUM-1:0] dma_global_trigger_slots;
logic [DMA_EXT_TRIGGER_SLOT_NUM-1:0] dma_ext_trigger_slots;
obi_pkg::obi_req_t busfifo2regconv_req;
@@ -182,6 +184,13 @@ module ao_peripheral_subsystem
end
endgenerate
+ /* DMA clock gating */
+ generate
+ for (genvar i = 0; i < core_v_mini_mcu_pkg::DMA_CH_NUM; i++) begin : dma_clk_gate_gen
+ assign dma_clk_gate_en_ni[i] = dma_subsystem_pwr_ctrl_o[i].clkgate_en_n;
+ end
+ endgenerate
+
/*_________________________________________________________________________________________________________________________________ */
/* Module instantiation */
@@ -350,7 +359,8 @@ module ao_peripheral_subsystem
.cpu_subsystem_pwr_ctrl_i,
.peripheral_subsystem_pwr_ctrl_i,
.memory_subsystem_pwr_ctrl_i,
- .external_subsystem_pwr_ctrl_i
+ .external_subsystem_pwr_ctrl_i,
+ .dma_subsystem_pwr_ctrl_o
);
/* ??? */
@@ -390,6 +400,7 @@ module ao_peripheral_subsystem
) dma_subsystem_i (
.clk_i,
.rst_ni,
+ .clk_gate_en_ni(dma_clk_gate_en_ni),
.reg_req_i(ao_peripheral_slv_req[core_v_mini_mcu_pkg::DMA_IDX]),
.reg_rsp_o(ao_peripheral_slv_rsp[core_v_mini_mcu_pkg::DMA_IDX]),
.dma_read_req_o,
diff --git a/hw/ip/dma/rtl/dma.sv b/hw/ip/dma/rtl/dma.sv
index ef4042655..b3275e2c9 100644
--- a/hw/ip/dma/rtl/dma.sv
+++ b/hw/ip/dma/rtl/dma.sv
@@ -21,6 +21,7 @@ module dma #(
) (
input logic clk_i,
input logic rst_ni,
+ input logic clk_gate_en_ni,
input logic ext_dma_stop_i,
@@ -58,6 +59,9 @@ module dma #(
/* Signals declaration */
+ /* Gated clock */
+ logic clk_cg;
+
/* Registers */
dma_reg2hw_t reg2hw;
dma_hw2reg_t hw2reg;
@@ -164,12 +168,33 @@ module dma #(
/* Module instantiation */
+ /* Clock gating cell */
+
+`ifndef FPGA_SYNTHESIS
+`ifndef VERILATOR
+ tc_clk_gating clk_gating_cell (
+ .clk_i,
+ .en_i(clk_gate_en_ni),
+ .test_en_i(1'b0),
+ .clk_o(clk_cg)
+ );
+
+`else
+ assign clk_cg = clk_i & clk_gate_en_ni;
+`endif
+
+`else
+ assign clk_cg = clk_i & clk_gate_en_ni;
+`endif
+
+
+
/* Read FIFO */
fifo_v3 #(
.DEPTH(FIFO_DEPTH),
.FALL_THROUGH(1'b1)
) dma_read_fifo_i (
- .clk_i,
+ .clk_i(clk_cg),
.rst_ni,
.flush_i(fifo_flush),
.testmode_i(1'b0),
@@ -190,7 +215,7 @@ module dma #(
.DEPTH(FIFO_DEPTH),
.FALL_THROUGH(1'b1)
) dma_read_addr_fifo_i (
- .clk_i,
+ .clk_i(clk_cg),
.rst_ni,
.flush_i(fifo_flush),
.testmode_i(1'b0),
@@ -211,7 +236,7 @@ module dma #(
.DEPTH(FIFO_DEPTH),
.FALL_THROUGH(1'b1)
) dma_write_fifo_i (
- .clk_i,
+ .clk_i(clk_cg),
.rst_ni,
.flush_i(fifo_flush),
.testmode_i(1'b0),
@@ -231,7 +256,7 @@ module dma #(
.reg_req_t(reg_req_t),
.reg_rsp_t(reg_rsp_t)
) dma_reg_top_i (
- .clk_i,
+ .clk_i(clk_cg),
.rst_ni,
.reg_req_i,
.reg_rsp_o,
@@ -242,7 +267,7 @@ module dma #(
/* Read FSM */
dma_obiread_fsm dma_obiread_fsm_i (
- .clk_i,
+ .clk_i(clk_cg),
.rst_ni,
.reg2hw_i(reg2hw),
.dma_start_i(dma_start),
@@ -265,7 +290,7 @@ module dma #(
/* Read address FSM */
dma_obiread_addr_fsm dma_obiread_addr_fsm_i (
- .clk_i,
+ .clk_i(clk_cg),
.rst_ni,
.reg2hw_i(reg2hw),
.dma_start_i(dma_start),
@@ -282,7 +307,7 @@ module dma #(
/* DMA padding FSM */
dma_padding_fsm dma_padding_fsm_i (
- .clk_i,
+ .clk_i(clk_cg),
.rst_ni,
.reg2hw_i(reg2hw),
.dma_padding_fsm_on_i(dma_padding_fsm_on),
@@ -300,7 +325,7 @@ module dma #(
/* Write FSM */
dma_obiwrite_fsm dma_obiwrite_fsm_i (
- .clk_i,
+ .clk_i(clk_cg),
.rst_ni,
.reg2hw_i(reg2hw),
.dma_start_i(dma_start),
@@ -354,7 +379,7 @@ module dma #(
end
/* Update DMA state */
- always_ff @(posedge clk_i, negedge rst_ni) begin
+ always_ff @(posedge clk_cg, negedge rst_ni) begin
if (~rst_ni) begin
dma_state_q <= DMA_READY;
end else begin
@@ -363,7 +388,7 @@ module dma #(
end
/* DMA pulse start when dma_start register is written */
- always_ff @(posedge clk_i or negedge rst_ni) begin : proc_dma_start
+ always_ff @(posedge clk_cg or negedge rst_ni) begin : proc_dma_start
if (~rst_ni) begin
dma_start_pending <= 1'b0;
end else begin
@@ -376,7 +401,7 @@ module dma #(
end
/* Transaction IFR update */
- always_ff @(posedge clk_i, negedge rst_ni) begin : proc_ff_transaction_ifr
+ always_ff @(posedge clk_cg, negedge rst_ni) begin : proc_ff_transaction_ifr
if (~rst_ni) begin
transaction_ifr <= '0;
end else if (reg2hw.interrupt_en.transaction_done.q == 1'b1) begin
@@ -391,7 +416,7 @@ module dma #(
end
/* Delayed transaction interrupt signals */
- always_ff @(posedge clk_i, negedge rst_ni) begin : proc_ff_intr
+ always_ff @(posedge clk_cg, negedge rst_ni) begin : proc_ff_intr
if (~rst_ni) begin
dma_done_intr_n <= '0;
end else begin
@@ -400,7 +425,7 @@ module dma #(
end
/* Window IFR update */
- always_ff @(posedge clk_i, negedge rst_ni) begin : proc_ff_window_ifr
+ always_ff @(posedge clk_cg, negedge rst_ni) begin : proc_ff_window_ifr
if (~rst_ni) begin
window_ifr <= '0;
end else if (reg2hw.interrupt_en.window_done.q == 1'b1) begin
@@ -415,7 +440,7 @@ module dma #(
end
/* Delayed window interrupt signals */
- always_ff @(posedge clk_i, negedge rst_ni) begin : proc_ff_window_intr
+ always_ff @(posedge clk_cg, negedge rst_ni) begin : proc_ff_window_intr
if (~rst_ni) begin
dma_window_intr_n <= '0;
end else begin
@@ -424,7 +449,7 @@ module dma #(
end
- always_ff @(posedge clk_i, negedge rst_ni) begin : proc_dma_window_cnt
+ always_ff @(posedge clk_cg, negedge rst_ni) begin : proc_dma_window_cnt
if (~rst_ni) begin
window_counter <= 'h0;
end else begin
@@ -457,7 +482,7 @@ module dma #(
// update window_done flag
// set on dma_window_event
// reset on read
- always_ff @(posedge clk_i, negedge rst_ni) begin : proc_dma_window_done
+ always_ff @(posedge clk_cg, negedge rst_ni) begin : proc_dma_window_done
if (~rst_ni) begin
window_done_q <= 1'b0;
end else begin
@@ -466,7 +491,7 @@ module dma #(
end
end
- always_ff @(posedge clk_i, negedge rst_ni) begin
+ always_ff @(posedge clk_cg, negedge rst_ni) begin
if (~rst_ni) begin
dma_padding_fsm_on <= 1'b0;
end else begin
diff --git a/hw/ip/dma/rtl/dma_2.sv b/hw/ip/dma/rtl/dma_2.sv
deleted file mode 100644
index dc591a5da..000000000
--- a/hw/ip/dma/rtl/dma_2.sv
+++ /dev/null
@@ -1,565 +0,0 @@
-/* verilator lint_off WIDTH */
-
-/*
- * Copyright 2024 EPFL
- * Solderpad Hardware License, Version 2.1, see LICENSE.md for details.
- * SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
- *
- * Author: Tommaso Terzano
- *
- *
- * Info: Direct Memory Access (DMA) channel module.
- */
-
-module dma #(
- parameter int unsigned FIFO_DEPTH = 4,
- parameter type reg_req_t = logic,
- parameter type reg_rsp_t = logic,
- parameter type obi_req_t = logic,
- parameter type obi_resp_t = logic,
- parameter int unsigned SLOT_NUM = 0
-) (
- input logic clk_i,
- input logic rst_ni,
-
- input logic ext_dma_stop_i,
-
- input reg_req_t reg_req_i,
- output reg_rsp_t reg_rsp_o,
-
- output obi_req_t dma_read_req_o,
- input obi_resp_t dma_read_resp_i,
-
- output obi_req_t dma_write_req_o,
- input obi_resp_t dma_write_resp_i,
-
- output obi_req_t dma_addr_req_o,
- input obi_resp_t dma_addr_resp_i,
-
- input logic [SLOT_NUM-1:0] trigger_slot_i,
-
- output dma_done_intr_o,
- output dma_window_intr_o,
-
- output dma_done_o
-);
-
- import dma_reg_pkg::*;
-
-
- /*_________________________________________________________________________________________________________________________________ */
-
- /* Parameter definition */
-
- localparam int unsigned LastFifoUsage = FIFO_DEPTH - 1;
- localparam int unsigned Addr_Fifo_Depth = (FIFO_DEPTH > 1) ? $clog2(FIFO_DEPTH) : 1;
-
- /*_________________________________________________________________________________________________________________________________ */
-
- /* Signals declaration */
-
- dma_reg2hw_t reg2hw;
- dma_hw2reg_t hw2reg;
-
- logic [31:0] read_ptr_valid_reg;
- logic [2:0] dma_cnt_du;
- logic dma_start;
- logic dma_done;
- logic dma_window_event;
-
- logic window_done_q;
-
- logic data_in_req;
- logic data_in_we;
- logic [3:0] data_in_be;
- logic [31:0] data_in_addr;
- logic data_in_gnt;
- logic data_in_rvalid;
- logic [31:0] data_in_rdata;
-
- logic data_addr_in_req;
- logic data_addr_in_we;
- logic [ 3:0] data_addr_in_be;
- logic [31:0] data_addr_in_addr;
- logic data_addr_in_gnt;
- logic data_addr_in_rvalid;
- logic [31:0] data_addr_in_rdata;
-
- logic data_out_req;
- logic data_out_we;
- logic [3:0] data_out_be;
- logic [31:0] data_out_addr;
- logic [31:0] data_out_wdata;
- logic data_out_gnt;
- logic data_out_rvalid;
- logic [31:0] data_out_rdata;
-
- /* Interrupt Flag Register signals */
- logic transaction_ifr;
- logic dma_done_intr_n;
- logic dma_done_intr;
- logic window_ifr;
- logic dma_window_intr;
- logic dma_window_intr_n;
-
- /* FIFO signals */
- logic [Addr_Fifo_Depth-1:0] read_fifo_usage;
- logic [Addr_Fifo_Depth-1:0] read_addr_fifo_usage;
- logic [Addr_Fifo_Depth-1:0] write_fifo_usage;
-
- logic fifo_flush;
- logic read_fifo_full;
- logic read_fifo_empty;
- logic read_fifo_alm_full;
- logic [31:0] read_fifo_input;
- logic [31:0] read_fifo_output;
-
- logic read_addr_fifo_full;
- logic read_addr_fifo_empty;
- logic read_addr_fifo_alm_full;
- logic [31:0] read_addr_fifo_input;
- logic [31:0] read_addr_fifo_output;
-
- logic write_fifo_full;
- logic write_fifo_empty;
- logic write_fifo_alm_full;
- logic [31:0] write_fifo_input;
- logic [31:0] write_fifo_output;
-
- /* Trigger signals */
- logic wait_for_rx;
- logic wait_for_tx;
-
- /* Destination datatypes */
- dma_data_type_t dst_data_type;
- dma_data_type_t src_data_type;
-
- /* FSM states */
- typedef enum logic [1:0] {
- DMA_DATA_TYPE_WORD,
- DMA_DATA_TYPE_HALF_WORD,
- DMA_DATA_TYPE_BYTE,
- DMA_DATA_TYPE_BYTE_
- } dma_data_type_t;
-
- enum {
- DMA_READY,
- DMA_STARTING,
- DMA_RUNNING
- }
- dma_state_q, dma_state_d;
-
- enum logic {
- DMA_READ_FSM_IDLE,
- DMA_READ_FSM_ON
- }
- dma_read_fsm_state, dma_read_fsm_n_state, dma_read_addr_fsm_state, dma_read_addr_fsm_n_state;
-
- enum logic {
- DMA_WRITE_FSM_IDLE,
- DMA_WRITE_FSM_ON
- }
- dma_write_fsm_state, dma_write_fsm_n_state;
-
- logic [ 3:0] byte_enable_out;
-
- logic circular_mode;
- logic address_mode;
-
- logic dma_start_pending;
-
- logic [31:0] window_counter;
-
- /*_________________________________________________________________________________________________________________________________ */
-
- /* Module instantiation */
-
- /* Read FIFO */
- fifo_v3 #(
- .DEPTH(FIFO_DEPTH)
- ) dma_read_fifo_i (
- .clk_i,
- .rst_ni,
- .flush_i(fifo_flush),
- .testmode_i(1'b0),
- // status flags
- .full_o(read_fifo_full),
- .empty_o(read_fifo_empty),
- .usage_o(read_fifo_usage),
- // as long as the queue is not full we can push new data
- .data_i(read_fifo_input),
- .push_i(read_fifo_push),
- // as long as the queue is not empty we can pop new elements
- .data_o(read_fifo_output),
- .pop_i(read_fifo_pop)
- );
-
- /* Read address mode FIFO */
- fifo_v3 #(
- .DEPTH(FIFO_DEPTH)
- ) dma_read_addr_fifo_i (
- .clk_i,
- .rst_ni,
- .flush_i(fifo_flush),
- .testmode_i(1'b0),
- // status flags
- .full_o(read_addr_fifo_full),
- .empty_o(read_addr_fifo_empty),
- .usage_o(read_addr_fifo_usage),
- // as long as the queue is not full we can push new data
- .data_i(read_addr_fifo_input),
- .push_i(read_addr_fifo_push),
- // as long as the queue is not empty we can pop new elements
- .data_o(read_addr_fifo_output),
- .pop_i(read_addr_fifo_pop)
- );
-
- /* Write FIFO */
- fifo_v3 #(
- .DEPTH(FIFO_DEPTH)
- ) dma_write_fifo_i (
- .clk_i,
- .rst_ni,
- .flush_i(fifo_flush),
- .testmode_i(1'b0),
- // status flags
- .full_o(write_fifo_full),
- .empty_o(write_fifo_empty),
- .usage_o(write_fifo_usage),
- // as long as the queue is not full we can push new data
- .data_i(write_fifo_input),
- .push_i(write_fifo_push),
- // as long as the queue is not empty we can pop new elements
- .data_o(write_fifo_output),
- .pop_i(write_fifo_pop)
- );
-
- dma_reg_top #(
- .reg_req_t(reg_req_t),
- .reg_rsp_t(reg_rsp_t)
- ) dma_reg_top_i (
- .clk_i,
- .rst_ni,
- .reg_req_i,
- .reg_rsp_o,
- .reg2hw,
- .hw2reg,
- .devmode_i(1'b1)
- );
-
- /* Read FSM */
- dma_obiread_fsm dma_obiread_fsm_i(
- ) (
- .clk_i,
- .rst_ni,
- .dma_start_i(dma_start),
- .ext_dma_stop_i,
- .read_fifo_full_i(read_fifo_full),
- .read_fifo_alm_full_i(read_fifo_alm_full),
- .dma_cnt_du_i(dma_cnt_du),
- .wait_for_rx_i(wait_for_rx),
- .data_in_rvalid_i(data_in_rvalid),
- .data_in_req_o(data_in_req),
- .data_in_we_o(data_in_we),
- .data_in_be_o(data_in_be),
- .data_in_addr_o(data_in_addr),
- .read_fifo_flush_o(fifo_flush),
- .read_ptr_valid_reg_o(read_ptr_valid_reg)
- );
-
- /* Read address FSM */
- dma_obiread_fsm_addr dma_obiread_fsm_addr_i(
- ) (
- .clk_i,
- .rst_ni,
- .dma_start_i(dma_start),
- .read_fifo_addr_full_i(read_fifo_full),
- .read_fifo_addr_alm_full_i(read_fifo_alm_full),
- .address_mode_i(address_mode),
- .data_addr_in_req_o(data_addr_in_req),
- .data_addr_in_we_o(data_addr_in_we),
- .data_addr_in_be_o(data_addr_in_be),
- .data_addr_in_addr_o(data_addr_in_addr)
- );
-
- /* DMA padding FSM */
- dma_padding_fsm dma_padding_fsm_i(
- .clk_i,
- .rst_ni,
- .dma_padding_fsm_on_i,
- .dma_start_i(dma_start),
- .read_fifo_empty_i(read_fifo_empty),
- .write_fifo_full_i(write_fifo_full),
- .write_fifo_alm_full_i(write_fifo_alm_full),
- .data_read_i(read_fifo_output),
- .dma_cnt_du_i(dma_cnt_du),
- .read_ptr_valid_reg_i(read_ptr_valid_reg),
- .padding_fsm_done_o(padding_fsm_done),
- .write_fifo_push_o(write_fifo_push),
- .read_fifo_pop_o(read_fifo_pop),
- .data_write_o(write_fifo_input)
- );
-
- /* Write FSM */
- dma_obiwrite_fsm dma_obiwrite_fsm_i(
- ) (
- .clk_i,
- .rst_ni,
- .dma_start_i(dma_start),
- .ext_dma_stop_i(ext_dma_stop_i),
- .write_fifo_empty_i(write_fifo_empty),
- .dma_cnt_du_i(dma_cnt_du),
- .fifo_output_i(write_fifo_output),
- .wait_for_tx_i(wait_for_tx),
- .data_out_req_o(data_out_req),
- .data_out_we_o(data_out_we),
- .data_out_be_o(data_out_be),
- .data_out_addr_o(data_out_addr),
- .data_out_wdata_o(data_out_wdata),
- .dma_done_o(dma_done)
- );
-
- /*_________________________________________________________________________________________________________________________________ */
-
- /* FSMs instantiation */
-
- //
- // Main DMA state machine
- //
- // READY : idle, waiting for a write pulse to size registered in `dma_start_pending`
- // STARTING: load transaction data
- // RUNNING : waiting for transaction finish
- // when `dma_done` rises either enter ready or restart in circular mode
- //
-
- always_comb begin
- dma_state_d = dma_state_q;
- case (dma_state_q)
- DMA_READY: begin
- if (dma_start_pending) begin
- dma_state_d = DMA_STARTING;
- end
- end
- DMA_STARTING: begin
- dma_state_d = DMA_RUNNING;
- end
- DMA_RUNNING: begin
- if (dma_done) begin
- if (circular_mode) dma_state_d = DMA_STARTING;
- else dma_state_d = DMA_READY;
- end
- end
- endcase
- end
-
- /* Update DMA state */
- always_ff @(posedge clk_i, negedge rst_ni) begin
- if (~rst_ni) begin
- dma_state_q <= DMA_READY;
- end else begin
- dma_state_q <= dma_state_d;
- end
- end
-
- /* DMA pulse start when dma_start register is written */
- always_ff @(posedge clk_i or negedge rst_ni) begin : proc_dma_start
- if (~rst_ni) begin
- dma_start_pending <= 1'b0;
- end else begin
- if (dma_start == 1'b1) begin
- dma_start_pending <= 1'b0;
- end else if ((reg2hw.size_d1.qe & |reg2hw.size_d1.q)) begin
- dma_start_pending <= 1'b1;
- end
- end
- end
-
- /* Transaction IFR update */
- always_ff @(posedge clk_i, negedge rst_ni) begin : proc_ff_transaction_ifr
- if (~rst_ni) begin
- transaction_ifr <= '0;
- end else if (reg2hw.interrupt_en.transaction_done.q == 1'b1) begin
- // Enter here only if the transaction_done interrupt is enabled
- if (dma_done == 1'b1) begin
- transaction_ifr <= 1'b1;
- end else if (reg2hw.transaction_ifr.re == 1'b1) begin
- // If the IFR bit is read, we must clear the transaction_ifr
- transaction_ifr <= 1'b0;
- end
- end
- end
-
- /* Delayed transaction interrupt signals */
- always_ff @(posedge clk_i, negedge rst_ni) begin : proc_ff_intr
- if (~rst_ni) begin
- dma_done_intr_n <= '0;
- end else begin
- dma_done_intr_n <= dma_done_intr;
- end
- end
-
- /* Window IFR update */
- always_ff @(posedge clk_i, negedge rst_ni) begin : proc_ff_window_ifr
- if (~rst_ni) begin
- window_ifr <= '0;
- end else if (reg2hw.interrupt_en.window_done.q == 1'b1) begin
- // Enter here only if the window_done interrupt is enabled
- if (dma_window_event == 1'b1) begin
- window_ifr <= 1'b1;
- end else if (reg2hw.window_ifr.re == 1'b1) begin
- // If the IFR bit is read, we must clear the window_ifr
- window_ifr <= 1'b0;
- end
- end
- end
-
- /* Delayed window interrupt signals */
- always_ff @(posedge clk_i, negedge rst_ni) begin : proc_ff_window_intr
- if (~rst_ni) begin
- dma_window_intr_n <= '0;
- end else begin
- dma_window_intr_n <= dma_window_intr;
- end
- end
-
-
- always_ff @(posedge clk_i, negedge rst_ni) begin : proc_dma_window_cnt
- if (~rst_ni) begin
- window_counter <= 'h0;
- end else begin
- if (|reg2hw.window_size.q) begin
- if (dma_start | dma_done) begin
- window_counter <= 'h0;
- end else if (data_out_gnt) begin
- if (window_counter + 'h1 >= {19'h0, reg2hw.window_size.q}) begin
- window_counter <= 'h0;
- end else begin
- window_counter <= window_counter + 'h1;
- end
- end
- end
- end
- end
-
- // Update WINDOW_COUNT register
- always_comb begin : proc_dma_window_cnt_reg
- hw2reg.window_count.d = reg2hw.window_count.q + 'h1;
- hw2reg.window_count.de = 1'b0;
- if (dma_start) begin
- hw2reg.window_count.d = 'h0;
- hw2reg.window_count.de = 1'b1;
- end else if (dma_window_event) begin
- hw2reg.window_count.de = 1'b1;
- end
- end
-
- // update window_done flag
- // set on dma_window_event
- // reset on read
- always_ff @(posedge clk_i, negedge rst_ni) begin : proc_dma_window_done
- if (~rst_ni) begin
- window_done_q <= 1'b0;
- end else begin
- if (dma_window_event) window_done_q <= 1'b1;
- else if (reg2hw.status.window_done.re) window_done_q <= 1'b0;
- end
- end
-
- /* Compute the data unit */
- always_comb begin
- case (dst_data_type)
- DMA_DATA_TYPE_WORD: dma_cnt_du = 3'h4;
- DMA_DATA_TYPE_HALF_WORD: dma_cnt_du = 3'h2;
- DMA_DATA_TYPE_BYTE, DMA_DATA_TYPE_BYTE_: dma_cnt_du = 3'h1;
- endcase
- end
-
- /*_________________________________________________________________________________________________________________________________ */
-
- /* Signal assignments */
-
- assign dma_done_o = dma_done;
-
- /* OBI signals */
- assign dma_read_req_o.req = data_in_req;
- assign dma_read_req_o.we = data_in_we;
- assign dma_read_req_o.be = data_in_be;
- assign dma_read_req_o.addr = data_in_addr;
- assign dma_read_req_o.wdata = 32'h0;
-
- assign data_in_gnt = dma_read_resp_i.gnt;
- assign data_in_rvalid = dma_read_resp_i.rvalid;
- assign data_in_rdata = dma_read_resp_i.rdata;
-
- assign dma_addr_req_o.req = data_addr_in_req;
- assign dma_addr_req_o.we = data_addr_in_we;
- assign dma_addr_req_o.be = data_addr_in_be;
- assign dma_addr_req_o.addr = data_addr_in_addr;
- assign dma_addr_req_o.wdata = 32'h0;
-
- assign data_addr_in_gnt = dma_addr_resp_i.gnt;
- assign data_addr_in_rvalid = dma_addr_resp_i.rvalid;
- assign data_addr_in_rdata = dma_addr_resp_i.rdata;
-
- assign dma_write_req_o.req = data_out_req;
- assign dma_write_req_o.we = data_out_we;
- assign dma_write_req_o.be = data_out_be;
- assign dma_write_req_o.addr = data_out_addr;
- assign dma_write_req_o.wdata = data_out_wdata;
-
- assign data_out_gnt = dma_write_resp_i.gnt;
- assign data_out_rvalid = dma_write_resp_i.rvalid;
- assign data_out_rdata = dma_write_resp_i.rdata;
-
- assign dma_done_intr = transaction_ifr;
- assign dma_window_intr = window_ifr;
-
- assign dma_done_intr_o = dma_done_intr_n;
- assign hw2reg.transaction_ifr.d = transaction_ifr;
- assign dma_window_intr_o = dma_window_intr_n;
- assign hw2reg.window_ifr.d = window_ifr;
-
- assign dst_data_type = dma_data_type_t'(reg2hw.dst_data_type.q);
- assign src_data_type = dma_data_type_t'(reg2hw.src_data_type.q);
-
- assign hw2reg.status.ready.d = (dma_state_q == DMA_READY);
-
- assign hw2reg.status.window_done.d = window_done_q;
-
- assign circular_mode = reg2hw.mode.q == 1;
- assign address_mode = reg2hw.mode.q == 2;
-
- /* DMA Dimensionality configuration flags */
- assign dma_conf_1d = reg2hw.dim_config.q == 0;
- assign dma_conf_2d = reg2hw.dim_config.q == 1;
-
- /* DMA read pointer source selection */
- assign read_ptr_update_sel = reg2hw.dim_inv.q;
-
- /* DMA 2D increment */
- assign dma_src_d2_inc = reg2hw.src_ptr_inc_d2.q;
- assign dma_src_d1_inc = reg2hw.src_ptr_inc_d1.q;
- assign dma_dst_d2_inc = reg2hw.dst_ptr_inc_d2.q;
- assign dma_dst_d1_inc = reg2hw.dst_ptr_inc_d1.q;
-
- /* Sign extend flag */
- assign write_address = address_mode ? fifo_addr_output : write_ptr_reg;
-
- assign wait_for_rx = |(reg2hw.slot.rx_trigger_slot.q[SLOT_NUM-1:0] & (~trigger_slot_i));
- assign wait_for_tx = |(reg2hw.slot.tx_trigger_slot.q[SLOT_NUM-1:0] & (~trigger_slot_i));
-
- assign fifo_addr_empty_check = fifo_addr_empty && address_mode;
-
- assign read_fifo_alm_full = (read_fifo_usage == LastFifoUsage[Addr_Fifo_Depth-1:0]);
- assign read_fifo_addr_alm_full = (read_addr_fifo_usage == LastFifoUsage[Addr_Fifo_Depth-1:0]);
- assign write_fifo_alm_full = (write_fifo_usage == LastFifoUsage[Addr_Fifo_Depth-1:0]);
-
- assign dma_start = (dma_state_q == DMA_STARTING);
-
- assign read_addr_fifo_input = data_addr_in_rdata; //never misaligned, always 32b
-
- // WINDOW EVENT
- // Count gnt write transaction and generate event pulse if WINDOW_SIZE is reached
- assign dma_window_event = |reg2hw.window_size.q & data_out_gnt & (window_counter + 'h1 >= {19'h0, reg2hw.window_size.q});
-
-endmodule : dma
diff --git a/hw/ip/dma_subsystem/rtl/dma_subsystem.sv b/hw/ip/dma_subsystem/rtl/dma_subsystem.sv
index 3eeb2c957..ee0189e6d 100644
--- a/hw/ip/dma_subsystem/rtl/dma_subsystem.sv
+++ b/hw/ip/dma_subsystem/rtl/dma_subsystem.sv
@@ -20,6 +20,7 @@ module dma_subsystem #(
) (
input logic clk_i,
input logic rst_ni,
+ input logic clk_gate_en_ni [core_v_mini_mcu_pkg::DMA_CH_NUM-1:0],
input reg_req_t reg_req_i,
output reg_rsp_t reg_rsp_o,
@@ -123,6 +124,7 @@ module dma_subsystem #(
) dma_i (
.clk_i,
.rst_ni,
+ .clk_gate_en_ni(clk_gate_en_ni[i]),
.ext_dma_stop_i(ext_dma_stop_i[i]),
.reg_req_i(submodules_req[i]),
.reg_rsp_o(submodules_rsp[i]),
diff --git a/hw/ip/power_manager/data/power_manager.hjson.tpl b/hw/ip/power_manager/data/power_manager.hjson.tpl
index 0d3362558..6c564b96e 100644
--- a/hw/ip/power_manager/data/power_manager.hjson.tpl
+++ b/hw/ip/power_manager/data/power_manager.hjson.tpl
@@ -223,6 +223,17 @@
]
}
+% for channel in range(int(dma_ch_count)):
+ { name: "DMA_CH${channel}_CLK_GATE",
+ desc: "Clock-gates the DMA CH${channel}",
+ resval: "0x00000000"
+ swaccess: "rw",
+ hwaccess: "hro",
+ fields: [
+ { bits: "0", name: "DMA_CH${channel}_CLK_GATE", desc: "Clock-gates the DMA CH${channel}" }
+ ]
+ }
+% endfor
% for bank in xheep.iter_ram_banks():
{ name: "RAM_${bank.name()}_CLK_GATE",
diff --git a/hw/ip/power_manager/data/power_manager.sv.tpl b/hw/ip/power_manager/data/power_manager.sv.tpl
index 0e1266702..a6abf35df 100644
--- a/hw/ip/power_manager/data/power_manager.sv.tpl
+++ b/hw/ip/power_manager/data/power_manager.sv.tpl
@@ -49,6 +49,7 @@ module power_manager import power_manager_pkg::*; #(
output power_manager_out_t peripheral_subsystem_pwr_ctrl_o,
output power_manager_out_t memory_subsystem_pwr_ctrl_o[core_v_mini_mcu_pkg::NUM_BANKS-1:0],
output power_manager_out_t external_subsystem_pwr_ctrl_o[EXT_DOMAINS_RND-1:0],
+ output power_manager_out_t dma_subsystem_pwr_ctrl_o[core_v_mini_mcu_pkg::DMA_CH_NUM-1:0],
// Power Manager input signals
input power_manager_in_t cpu_subsystem_pwr_ctrl_i,
@@ -131,6 +132,10 @@ module power_manager import power_manager_pkg::*; #(
assign memory_subsystem_pwr_ctrl_o[${bank.name()}].clkgate_en_n = ~reg2hw.ram_${bank.name()}_clk_gate.q;
% endfor
+% for channel in range(int(dma_ch_count)):
+ assign dma_subsystem_pwr_ctrl_o[${channel}].clkgate_en_n = ~reg2hw.dma_ch${channel}_clk_gate.q;
+% endfor
+
% if external_domains != 0:
% for ext in range(external_domains):
assign external_subsystem_pwr_ctrl_o[${ext}].pwrgate_en_n = external_subsystem_powergate_switch_n[${ext}];
diff --git a/hw/ip/power_manager/power_manager_gen.sh b/hw/ip/power_manager/power_manager_gen.sh
old mode 100644
new mode 100755
diff --git a/mcu_cfg_minimal.hjson b/mcu_cfg_minimal.hjson
index 0be257d7b..a6d928447 100644
--- a/mcu_cfg_minimal.hjson
+++ b/mcu_cfg_minimal.hjson
@@ -20,6 +20,7 @@
ao_peripherals: {
address: 0x20000000,
length: 0x00100000,
+ num_spc: 0x1,
soc_ctrl: {
offset: 0x00000000,
length: 0x00010000,
@@ -42,6 +43,8 @@
length: 0x00010000,
ch_length: 0x100,
num_channels: 0x1,
+ num_master_ports: 0x1,
+ num_channels_per_master_port: 0x1,
path: "./hw/ip/dma/data/dma.hjson"
},
power_manager: {
diff --git a/scripts/verification/examples/im2col_spc_verification.py b/scripts/verification/examples/im2col_spc_verification.py
index eaf7eca45..58282a674 100644
--- a/scripts/verification/examples/im2col_spc_verification.py
+++ b/scripts/verification/examples/im2col_spc_verification.py
@@ -10,6 +10,10 @@
# and the golden result, then it runs the test on the PYNQ-Z2 board and stores the results
# in a file. The data can be then read and plotted using the plotter.py script.
#
+# It requires the user to perform the synthesis and to program the FPGA with the bitstream,
+# as it is a delicate and device-dependent operation.
+# Another very important step required is the connection to GDB using X-Heep script "make openOCD_bscan"
+#
import re
import time
@@ -285,9 +289,9 @@ def main(stdscr):
if int(test["ID"]) == 0:
im2col_cpu.append(string)
- elif int(test["ID"]) == 2:
+ elif int(test["ID"]) == 1:
im2col_dma_2d_C.append(string)
- elif int(test["ID"]) == 3:
+ elif int(test["ID"]) == 2:
im2col_spc.append(string)
# Stop the chrono and calculate the remaining time of the verification
diff --git a/scripts/verification/verifheep.py b/scripts/verification/verifheep.py
index 7891d1c13..ef82ee138 100644
--- a/scripts/verification/verifheep.py
+++ b/scripts/verification/verifheep.py
@@ -33,7 +33,6 @@
# of the iterations that have already been executed.
# This is useful to estimate the remaining time of the execution of a multi-iteration test.
#
-#
import subprocess
import re
@@ -43,9 +42,6 @@
import threading
import queue
import random
-import matplotlib.pyplot as plt
-import pandas as pd
-import numpy as np
import os
# Set this to True to enable debugging prints
@@ -58,8 +54,10 @@ def PRINT_DEB(*args, **kwargs):
class VerifHeep:
def __init__(self, target, xheep_dir, opt_en=False):
self.target = target
+ if target not in ['verilator', 'questasim', 'pynq-z2']:
+ raise Exception(f'Target {target} not supported. Choose one among:\n- verilator\n- questasim (with optional optimization)\n- pynq-z2\n')
if (target != 'pynq-z2' and opt_en) or (target != 'verilator' and opt_en):
- raise Exception(f'Target {target} not supported with {opt_en}. Choose one among:\n- Verilator\n- QuestaSim (with optional optimization)\n- Pynq-z2\n')
+ raise Exception(f'Target {target} not supported with {opt_en}. Choose one among:\n- verilator\n- questasim (with optional optimization)\n- pynq-z2\n')
self.opt_en = opt_en
self.xheep_dir = xheep_dir
@@ -144,8 +142,12 @@ def setUpDeb(self):
if self.gdb.signalstatus is not None:
print(f"GDB terminated by signal: {self.gdb.signalstatus}")
exit(1)
+
+ def stopDeb(self):
+ self.gdb.sendcontrol('c')
+ self.gdb.terminate()
- def launchTest(self, example_name, input_size=0, pattern=r'(\d+):(\d+):(\d+)', en_timeout_term=0):
+ def launchTest(self, example_name, input_size=0, pattern=r'(\d+):(\d+):(\d+)', en_timeout_term=False):
PRINT_DEB(f"Running test {example_name} with input size {input_size}...")
# Check that the serial connection is still open
@@ -219,10 +221,6 @@ def dumpResults(self, filename="results.txt"):
with open(filename, 'w') as f:
for result in self.results:
f.write(result + '\n')
-
- def stopDeb(self):
- self.gdb.sendcontrol('c')
- self.gdb.terminate()
# Performance estimation methods
@@ -245,7 +243,7 @@ def chronoExecutionEst(self, loop_size):
# Data generation methods
- def genInputDataset(self, dataset_size, parameters, row_size=0, range_min=0, range_max=1, dataset_dir="input_dataset.h", dataset_dir_c="", dataset_name="input_dataset", datatype="uint32_t"):
+ def genInputDataset(self, dataset_size, parameters="", row_size=0, range_min=0, range_max=1, dataset_dir="input_dataset.h", dataset_dir_c="", dataset_name="input_dataset", datatype="uint32_t"):
if dataset_dir_c == "":
with open(dataset_dir, 'w') as f:
@@ -256,6 +254,11 @@ def genInputDataset(self, dataset_size, parameters, row_size=0, range_min=0, ran
f.write(license)
f.write(f"#include \n\n")
+ # Write the parameters, if there are any
+ if parameters:
+ for key, value in parameters.items():
+ f.write(f"#define {key} {value}\n")
+
# Vector declaration
f.write(f"const {datatype} {dataset_name}[{dataset_size}] = " + "{\n")
@@ -457,15 +460,15 @@ def genGoldenResult(self, function, golden_size, parameters, row_size=0, output_
# Close the file
f.write(f"#endif // {golden_name.upper()}_H\n")
- def modifyFile(self, filename, pattern, replacement):
+ def modifyFile(self, file_dir, pattern, replacement):
- with open(filename, 'r') as f:
+ with open(file_dir, 'r') as f:
content = f.read()
# Replace the pattern with the replacement
new_content = re.sub(pattern, replacement, content)
- with open(filename, 'w') as f:
+ with open(file_dir, 'w') as f:
f.write(new_content)
# Serial communication thread
diff --git a/sw/applications/example_dma/main.c b/sw/applications/example_dma/main.c
index 34d075721..e2387a8ca 100644
--- a/sw/applications/example_dma/main.c
+++ b/sw/applications/example_dma/main.c
@@ -118,13 +118,13 @@ dma_data_type_t C_type_2_dma_type(int C_type)
#define INIT_TEST(signed, data_size, dma_src_type, dma_dst_type) \
tgt_src.ptr = (uint8_t *)src; \
- tgt_src.inc_du = 1; \
+ tgt_src.inc_d1_du = 1; \
tgt_src.inc_d2_du = 0; \
tgt_src.trig = DMA_TRIG_MEMORY; \
tgt_src.type = dma_src_type; \
tgt_src.env = NULL; \
tgt_dst.ptr = (uint8_t *)dst; \
- tgt_dst.inc_du = 1; \
+ tgt_dst.inc_d1_du = 1; \
tgt_dst.inc_d2_du = 0; \
tgt_dst.trig = DMA_TRIG_MEMORY; \
tgt_dst.type = dma_dst_type; \
@@ -247,7 +247,7 @@ int main(int argc, char *argv[])
dma_target_t tgt_dst;
dma_target_t tgt_addr = {
.ptr = (uint8_t *)test_addr_4B_PTR,
- .inc_du = 1,
+ .inc_d1_du = 1,
.trig = DMA_TRIG_MEMORY,
};
@@ -263,12 +263,12 @@ int main(int argc, char *argv[])
// Initialize the DMA for the next tests
tgt_src.ptr = (uint8_t *)test_data_4B;
- tgt_src.inc_du = 1;
+ tgt_src.inc_d1_du = 1;
tgt_src.trig = DMA_TRIG_MEMORY;
tgt_src.type = DMA_DATA_TYPE_WORD;
tgt_dst.ptr = (uint8_t *)copied_data_4B;
- tgt_dst.inc_du = 1;
+ tgt_dst.inc_d1_du = 1;
tgt_dst.trig = DMA_TRIG_MEMORY;
tgt_dst.type = DMA_DATA_TYPE_WORD;
diff --git a/sw/applications/example_dma_2d/main.c b/sw/applications/example_dma_2d/main.c
index 8e6ab9a4e..d9f4d6f61 100644
--- a/sw/applications/example_dma_2d/main.c
+++ b/sw/applications/example_dma_2d/main.c
@@ -83,7 +83,7 @@
/* By default, printfs are activated for FPGA and disabled for simulation. */
#define PRINTF_IN_FPGA 1
-#define PRINTF_IN_SIM 1
+#define PRINTF_IN_SIM 0
#if TARGET_SIM && PRINTF_IN_SIM
#define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__)
diff --git a/tb/testharness.sv b/tb/testharness.sv
index 910e5dd53..2fa26eba4 100644
--- a/tb/testharness.sv
+++ b/tb/testharness.sv
@@ -482,6 +482,7 @@ module testharness #(
) dma_i (
.clk_i,
.rst_ni,
+ .clk_gate_en_ni('1),
.ext_dma_stop_i('0),
.reg_req_i(ext_periph_slv_req[testharness_pkg::MEMCOPY_CTRL_IDX]),
.reg_rsp_o(ext_periph_slv_rsp[testharness_pkg::MEMCOPY_CTRL_IDX]),