From 77db431b9f226f5df3e257913959a6b3f707f373 Mon Sep 17 00:00:00 2001 From: Navaneeth-Kunhi Purayil Date: Tue, 11 Aug 2026 16:53:55 +0200 Subject: [PATCH 1/6] [hardware] fix handshake to align stage --- hardware/src/vlsu/align_stage.sv | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/hardware/src/vlsu/align_stage.sv b/hardware/src/vlsu/align_stage.sv index bad8998..8b29d00 100644 --- a/hardware/src/vlsu/align_stage.sv +++ b/hardware/src/vlsu/align_stage.sv @@ -160,7 +160,6 @@ assign axi_req_o.ar_valid = axi_req_i.ar_valid && axi_resp_o.ar_ready; assign axi_req_o.b_ready = axi_req_i.b_ready; assign axi_req_o.r_ready = axi_req_cut_ready[0]; -assign axi_req_cut_ready[NumStages] = axi_req_i.r_ready; // Resp channel assignments assign axi_resp_o.ar_ready = axi_resp_i.ar_ready && !tracker_full; @@ -256,9 +255,11 @@ always_comb begin axi_resp_o.r_valid = 1'b0; axi_resp_o.r = axi_resp_i_cut[NumStages].r; axi_resp_o.r.last = 1'b0; + + axi_req_cut_ready[NumStages] = axi_req_i.r_ready; // For a valid handshake assign to buffer to be used later - if (axi_resp_i_cut[NumStages].r_valid && axi_req_cut_ready[NumStages]) begin + if (axi_resp_i_cut[NumStages].r_valid && axi_req_i.r_ready) begin // Buffer data in this cycle data_d = axi_resp_i_cut[NumStages].r.data; data_valid_d = 1'b1; @@ -269,7 +270,7 @@ always_comb begin if (!(tracker_q[rd_resp_pnt_q[NumStages-1]].op inside {VLXE, VLSE})) begin // Combine the previous data and the current data packets using byte enable - if (data_valid_q && axi_req_cut_ready[NumStages]) begin + if (data_valid_q && axi_req_i.r_ready) begin // Number of elements in a single AXI transaction automatic vlen_t axi_valid_el = AxiDataBytes >> tracker_q[rd_resp_pnt_q_del[NumStages-1]].vew; @@ -300,6 +301,13 @@ always_comb begin // If the current data is not misaligned and we have a valid data // Set valid data for the next subsequent load to avoid bubble data_valid_d = be_final_d[AxiDataBytes-1] & axi_resp_i_cut[NumStages].r_valid; + + // If misaligned but we already have a response for the next request, + // stall it for 1 cycle + if (!be_final_d[AxiDataBytes-1] & !axi_resp_i_cut[NumStages].r.last) begin + axi_req_cut_ready[NumStages] = 1'b0; + end + last_d = 1'b0; end end From bed8e0726640f5f06c734148edd44ab31faa9aeb Mon Sep 17 00:00:00 2001 From: Navaneeth-Kunhi Purayil Date: Thu, 13 Aug 2026 20:08:34 +0200 Subject: [PATCH 2/6] [hardware] fix synchronization in shuffle --- hardware/src/vlsu/shuffle_stage.sv | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/hardware/src/vlsu/shuffle_stage.sv b/hardware/src/vlsu/shuffle_stage.sv index 7fab30a..9dc6f68 100644 --- a/hardware/src/vlsu/shuffle_stage.sv +++ b/hardware/src/vlsu/shuffle_stage.sv @@ -261,6 +261,7 @@ logic [NumBuffers-1:0] wr_buffer_completed_d, wr_buffer_completed_q; vlen_cluster_t vl_idx_cluster_d, vl_idx_cluster_q; logic pending_resp; +logic buffer_ld_resp_accepted; always_ff @(posedge clk_i or negedge rst_ni) begin if(~rst_ni) begin @@ -548,6 +549,7 @@ always_comb begin rdbuf_pnt_d = rdbuf_pnt_q; shift_d = shift_q; r_ready_buf = r_ready_buf_q; + buffer_ld_resp_accepted = 1'b0; rd_cluster_completed_d = rd_cluster_completed_q; rd_buffer_completed_d = rd_buffer_completed_q; @@ -564,12 +566,13 @@ always_comb begin // If have a valid handshake on response add to the buffer // If have a valid response from L2 after aligning buffer it first pointed by rdbuf_pnt_q // Set we have a valid data - if (axi_resp_i[0].r_valid && r_ready_buf_q) begin + if (axi_resp_i[0].r_valid & r_ready_buf_q & (&r_ready_i)) begin for (int c=0; c Date: Fri, 14 Aug 2026 16:52:34 +0200 Subject: [PATCH 3/6] [hardware] add stall to delayed pointer --- hardware/src/vlsu/align_stage.sv | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hardware/src/vlsu/align_stage.sv b/hardware/src/vlsu/align_stage.sv index 8b29d00..cf18898 100644 --- a/hardware/src/vlsu/align_stage.sv +++ b/hardware/src/vlsu/align_stage.sv @@ -311,6 +311,9 @@ always_comb begin last_d = 1'b0; end end + end else if (data_valid_q & !axi_req_i.r_ready) begin + // Maintain the delayed pointer in the case data cannot be sent out + rd_resp_pnt_d_del[NumStages-1] = rd_resp_pnt_q_del[NumStages-1]; end end else begin // Indexed operation From 0c4661bf3f0c57e9564a1ec008048c769129d5f9 Mon Sep 17 00:00:00 2001 From: Navaneeth-Kunhi Purayil Date: Tue, 18 Aug 2026 10:24:00 +0200 Subject: [PATCH 4/6] [hardware] cleanup shuffle stage --- hardware/src/vlsu/shuffle_stage.sv | 332 +++++++++++++++++++---------- 1 file changed, 218 insertions(+), 114 deletions(-) diff --git a/hardware/src/vlsu/shuffle_stage.sv b/hardware/src/vlsu/shuffle_stage.sv index 9dc6f68..b5c1027 100644 --- a/hardware/src/vlsu/shuffle_stage.sv +++ b/hardware/src/vlsu/shuffle_stage.sv @@ -44,12 +44,30 @@ module shuffle_stage import ara_pkg::*; import rvv_pkg::*; #( output axi_resp_t [NrClusters-1:0] axi_resp_o ); +`include "common_cells/registers.svh" + // There are 2 dapaths in this unit // 1) Shuffle - to shuffle the data coming from memory to the required cluster based on element width // 2) Buffer - to buffer the data coming from memory if the element width is 64b and ClusterAxiDataWidth is 32N, since in this case, the data coming from memory needs to be stored and sent in 2 cycles to the clusters. // This is only needed for loads, for stores we can just buffer the write data until we have enough data to send to the clusters. +localparam int unsigned NUM_DATAPATHS = 2; +localparam int unsigned NumTrackers=16; typedef enum logic { SHUFFLE, BUFFER } datapath_t; +typedef logic [$clog2(NumTrackers)-1:0] pnt_t; +typedef logic [$clog2(NumTrackers):0] cnt_t; +typedef axi_w_t [NrClusters-1:0] stage_w_t; + +logic [NrClusters-1:0] buf_sel_d, buf_sel_q; +logic cluster_sel_d, cluster_sel_q; +logic cluster_buf_ready, cluster_buf_valid; + +pnt_t [NumStages-1:0] wr_issue_pnt_d, wr_issue_pnt_q; + +logic [NrClusters-1:0] wr_cluster_completed_d, wr_cluster_status_completed; + +`FF(buf_sel_q, buf_sel_d, '0, clk_i, rst_ni) +`FF(cluster_sel_q, cluster_sel_d, '0, clk_i, rst_ni) // This is the main tracking structure for the requests coming into the shuffle stage. // It keeps track of the status of each request and is used to configure the shuffle and buffer datapath. @@ -73,11 +91,6 @@ typedef struct packed { ara_op_e op; } req_track_t; -localparam int unsigned NumTrackers=16; - -typedef logic [$clog2(NumTrackers)-1:0] pnt_t; -typedef logic [$clog2(NumTrackers):0] cnt_t; - req_track_t [NumTrackers-1:0] rd_tracker_d, rd_tracker_q; pnt_t rd_accept_pnt_d, rd_accept_pnt_q; pnt_t [NumStages-1:0] rd_issue_pnt_d, rd_issue_pnt_q; @@ -85,20 +98,17 @@ cnt_t rd_cnt_d, rd_cnt_q; req_track_t [NumTrackers-1:0] wr_tracker_d, wr_tracker_q; pnt_t wr_accept_pnt_d, wr_accept_pnt_q; -pnt_t [NumStages-1:0] wr_issue_pnt_d, wr_issue_pnt_q; cnt_t wr_cnt_d, wr_cnt_q; typedef axi_r_t [NrClusters-1:0] stage_r_t; stage_r_t [NumStages-1:0] r_data_in, r_data_out; -typedef axi_w_t [NrClusters-1:0] stage_w_t; stage_w_t [NumStages-1:0] w_data_in, w_data_out; logic [NumStages-1:0] r_valid, r_ready, w_valid, w_ready; logic [NumStages-1:0] r_shuffle_en, w_shuffle_en; logic [NrClusters-1:0] r_ready_i, r_valid_o; -logic [NrClusters-1:0] w_valid_i, w_ready_o; logic rd_full, wr_full; assign rd_full = (rd_cnt_q == NumTrackers); @@ -126,17 +136,36 @@ stream_fork #( .ready_o(r_ready[NumStages-1] ) ); +logic [NrClusters-1:0] axi_wr_buffer_valid, axi_wr_buffer_ready; +logic [NrClusters-1:0] axi_wr_shuffle_valid, axi_wr_shuffle_ready; +logic [NrClusters-1:0] axi_wr_shuffle_ready_inp, axi_wr_shuffle_valid_inp; + // To handle cases where write data does not come simultaneously // from all the clusters stream_join #( .N_INP(NrClusters) ) i_cluster_stream_join ( - .inp_ready_o(w_ready_o), - .inp_valid_i(w_valid_i), + .inp_ready_o(axi_wr_shuffle_ready_inp), + .inp_valid_i(axi_wr_shuffle_valid_inp), .oup_ready_i(w_ready[0]), .oup_valid_o(w_valid[0]) ); +always_comb begin + axi_wr_shuffle_ready = axi_wr_shuffle_ready_inp; + axi_wr_shuffle_valid_inp = axi_wr_shuffle_valid; + + for (int c=0; c 0) && (wr_tracker_q[wr_issue_pnt_q[0]].vl[c] == '0); + if (wr_cluster_status_completed[c] & axi_req_i[0].w_valid) begin + // Fake handshake for all completed clusters for 1 more cycle + // say not ready to upstream, send a dummy packet for the completed cluster downstream + axi_wr_shuffle_ready[c] = 1'b0; + axi_wr_shuffle_valid_inp[c] = 1'b1; + end + end +end + for (genvar s=0; s NrLanes) begin + wr_tracker_d[wr_issue_pnt_q[0]].vl[cluster_in] -= NrLanes; + end else begin + wr_tracker_d[wr_issue_pnt_q[0]].vl[cluster_in] = '0; + wr_cluster_completed_d[cluster_in] = 1'b1; - // Since cluster 0 always has the most elements, just set once for cluster0 - if (c==0) - wr_buffer_completed_d[wrbuf_pnt_q >> $clog2(NrClusters/2)] = 1'b1; - - end else begin - wr_tracker_d[wr_issue_pnt_q[0]].vl[wrbuf_pnt_q + c] -= nelem; - end - end + if (wr_cluster_completed_d == '1) begin + wr_cluster_completed_d = '0; + wr_buf_data_o[0].last = 1'b1; + + // start again from cluster-0 + cluster_sel_d = '0; - // If the instruction has been completed - // Or if there are less elements that the second buffer is not used - if ((&wr_buffer_completed_d) || - (wr_buffer_completed_d == 2'b01 && wr_tracker_d[wr_issue_pnt_q[0]].second_buffer_unused)) begin - wr_buffer_completed_d = '0; - wrbuf_pnt_d = '0; - axi_req_buf_out[0].w.last = 1'b1; + for (int s=0; s < NumStages ; s++) begin + wr_issue_pnt_d[s] = (wr_issue_pnt_q[s] == NumTrackers-1) ? '0 : wr_issue_pnt_q[s] + 1; + wr_tracker_d[wr_issue_pnt_q[s]].shuffle_en = '0; + wr_tracker_d[wr_issue_pnt_q[s]].datapath = SHUFFLE; + end + wr_cnt_d -= 1'b1; + end end - end - - // If the last cluster sends the data, remove request from tracker - if (axi_req_buf_out[0].w_valid & axi_req_buf_out[0].w.last) begin - for (int s=0; s < NumStages ; s++) begin - wr_issue_pnt_d[s] = (wr_issue_pnt_q[s] == NumTrackers-1) ? '0 : wr_issue_pnt_q[s] + 1; - wr_tracker_d[wr_issue_pnt_q[s]].shuffle_en = '0; - wr_tracker_d[wr_issue_pnt_q[s]].datapath = SHUFFLE; end - wr_cnt_d -= 1'b1; end end else begin @@ -815,7 +937,6 @@ always_comb begin for (int c=0; c > wr_tracker_q[wr_issue_pnt_q[0]].vew; - // wr_tracker_d[wr_issue_pnt_q[0]].vl[c] -= (wr_tracker_q[wr_issue_pnt_q[0]].vl[c] >= nelem) ? nelem : '0; wr_tracker_d[wr_issue_pnt_q[0]].len[c] -= 1; if (wr_tracker_q[wr_issue_pnt_q[0]].vl[c] <= nelem) begin wr_tracker_d[wr_issue_pnt_q[0]].vl[c] = 0; @@ -882,9 +1003,6 @@ for (genvar c=0; c < NrClusters; c++) begin // Usually responses from both shuffle and buffer paths do not exist simutaneously assign axi_resp_o[c].r = r_valid_o[c] ? r_data_out[NumStages-1][c] : axi_resp_buf_out[c].r; // Copy output resp from last stage assign axi_resp_o[c].r_valid = r_valid_o[c] ? ((rd_tracker_q[rd_issue_pnt_q[NumStages-1]].vl[c] == 0) ? 1'b0 : 1'b1) : axi_resp_buf_out[c].r_valid; - - // Writes - assign axi_resp_o[c].w_ready = (wr_op inside {VSXE, VSSE}) ? ((c == cluster_w_q) ? axi_resp_i[c].w_ready : 1'b0) : (wr_datapath ? ~wrbuf_full_q[c] : w_ready_o[c]); // Copy ready from stream join output to response end @@ -904,24 +1022,10 @@ for (genvar c=0; c < NrClusters; c++) begin assign r_ready_i[c] = axi_req_i[c].r_ready; // From input request, get ready inputs to stream fork // Writes - assign w_data_in[0][c] = (wr_datapath == BUFFER) ? '0 : - axi_req_i[c].w_valid ? axi_req_i[c].w : '0; // Copy input write data to first shuffle stage - - // If other cluster have completed writes, and cluster 0 has a write packet remaining, assume a fake write valid to the stream fork module - assign wr_cluster_completed[c] = (wr_cnt_q > 0) && (wr_tracker_q[wr_issue_pnt_q[0]].vl[c] == '0); - - // wvalids for the shuffle datapath - // For VSXE/VSSE, not using the shuffle datapath - assign w_valid_i[c] = (wr_op inside {VSXE, VSSE}) ? 1'b0 : - ((wr_cluster_completed[c] & axi_req_i[0].w_valid) ? 1'b1 : (wr_datapath == BUFFER)? 1'b0 : axi_req_i[c].w_valid); // Copy valid signals to stream join - - assign axi_req_o[c].w = (wr_op inside {VSXE, VSSE}) ? axi_req_i[c].w : - (w_valid[NumStages-1] ? w_data_out[NumStages-1][c] : axi_req_buf_out[c].w); // Copy last stage data to req output - assign axi_req_o[c].w_valid = (wr_op inside {VSXE, VSSE}) ? ((c == cluster_w_q) ? axi_req_i[c].w_valid : 1'b0) : - (w_valid[NumStages-1] ? 1'b1 : axi_req_buf_out[c].w_valid); // valid signal is the output valid of stream join + assign w_data_in[0][c] = axi_req_i[c].w_valid ? axi_req_i[c].w : '0; end -assign w_ready[NumStages-1] = axi_resp_i[0].w_ready; // The Global Ld-St is ready to receive write packets together. Hence using only cluster-0 's w_ready. +assign w_ready[NumStages-1] = &w_ready_shuffle; // The Global Ld-St is ready to receive write packets together. Hence using only cluster-0 's w_ready. endmodule From 63bd1ef139f5b58284fbb27cccdd73fe1b76d75c Mon Sep 17 00:00:00 2001 From: Navaneeth-Kunhi Purayil Date: Tue, 18 Aug 2026 11:52:32 +0200 Subject: [PATCH 5/6] [hardware] fix vl cap --- hardware/src/ara_dispatcher.sv | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/hardware/src/ara_dispatcher.sv b/hardware/src/ara_dispatcher.sv index 0b45839..0f4cd16 100644 --- a/hardware/src/ara_dispatcher.sv +++ b/hardware/src/ara_dispatcher.sv @@ -526,8 +526,13 @@ module ara_dispatcher import ara_pkg::*; import rvv_pkg::*; #( automatic int unsigned vl_rem = vl_tot & ((1 << num_clusters_i << $clog2(NrLanes)) - 1); automatic int unsigned vl_base = (vl_tot & ('1 << (num_clusters_i + $clog2(NrLanes)))) >> num_clusters_i; automatic int unsigned vl_rem_diff = vl_rem - (cluster_id_i * NrLanes); - vl_d = ((vl_tot >> num_clusters_i) >= vlmax) ? vlmax : vl_base; - vl_d += (vl_rem >= (cluster_id_i+1) * NrLanes) ? NrLanes : (vl_rem >= (cluster_id_i * NrLanes)) ? vl_rem_diff : '0; + if ((vl_tot >> num_clusters_i) >= vlmax) begin + vl_d = vlmax; + end else begin + vl_d = vl_base; + vl_d += (vl_rem >= (cluster_id_i+1) * NrLanes) ? NrLanes : + (vl_rem >= (cluster_id_i * NrLanes)) ? vl_rem_diff : '0; + end vl_cluster_d = (vl_tot >= vlmax_cluster) ? vlmax_cluster : vl_tot; end else begin // vsetvl || vsetvli if (insn.vsetvl_type.rs1 == '0 && insn.vsetvl_type.rd == '0) begin @@ -544,9 +549,16 @@ module ara_dispatcher import ara_pkg::*; import rvv_pkg::*; #( automatic int unsigned vl_rem = vl_tot & ((1 << num_clusters_i << $clog2(NrLanes)) - 1); automatic int unsigned vl_base = (vl_tot & ('1 << (num_clusters_i + $clog2(NrLanes)))) >> num_clusters_i; automatic int unsigned vl_rem_diff = vl_rem - (cluster_id_i * NrLanes); - vl_d = ((|acc_req_i.rs1[$bits(acc_req_i.rs1)-1:$bits(vl_cluster_d)]) || (vl_tot >= vlmax_cluster)) ? vlmax : vl_base; - vl_d += (vl_rem >= (cluster_id_i+1) * NrLanes) ? NrLanes : (vl_rem >= (cluster_id_i * NrLanes)) ? vl_rem_diff : '0; - vl_cluster_d = ((|acc_req_i.rs1[$bits(acc_req_i.rs1)-1:$bits(vl_cluster_d)]) || (vl_tot >= vlmax_cluster)) ? vlmax_cluster : vlen_cluster_t'(acc_req_i.rs1); + if ((|acc_req_i.rs1[$bits(acc_req_i.rs1)-1:$bits(vl_cluster_d)]) || + (vl_tot >= vlmax_cluster)) begin + vl_d = vlmax; + end else begin + vl_d = vl_base; + vl_d += (vl_rem >= (cluster_id_i+1) * NrLanes) ? NrLanes : + (vl_rem >= (cluster_id_i * NrLanes)) ? vl_rem_diff : '0; + end + vl_cluster_d = ((|acc_req_i.rs1[$bits(acc_req_i.rs1)-1:$bits(vl_cluster_d)]) || + (vl_tot >= vlmax_cluster)) ? vlmax_cluster : vlen_cluster_t'(acc_req_i.rs1); end end end From 9bd19b8d9abc8612f5bf5aa250c1f52c8daca066 Mon Sep 17 00:00:00 2001 From: Navaneeth-Kunhi Purayil Date: Tue, 18 Aug 2026 13:59:01 +0200 Subject: [PATCH 6/6] [mk, apps] clean makefile --- Makefile | 2 +- apps/Makefile | 13 +++++++------ apps/README.md | 13 +++++++++++-- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/Makefile b/Makefile index 1c83c7d..ebbfbf6 100644 --- a/Makefile +++ b/Makefile @@ -189,7 +189,7 @@ riscv_unit_tests: autoconf && \ ./configure target_alias=${GCC_INSTALL_DIR}/bin/riscv64-unknown-elf --prefix=${RISCV_TESTS_INSTALL_DIR}/target && \ cd env/p && git apply ../../../patches/eoc.patch &&\ - cd ../../../ && make riscv_tests_compile)) + cd ../../../ && make riscv_tests_standard)) # Helper targets .PHONY: clean diff --git a/apps/Makefile b/apps/Makefile index f95b5f5..67afc97 100644 --- a/apps/Makefile +++ b/apps/Makefile @@ -30,6 +30,7 @@ include $(COMMON_DIR)/default_args.mk nr_clusters ?= 2 include $(COMMON_DIR)/runtime.mk +include rivec.mk APPS := $(patsubst $(APPS_DIR)/%/main.c,%,$(wildcard $(APPS_DIR)/*/main.c)) @@ -51,7 +52,7 @@ bin/fft: ENV_DEFINES += -DFFT_SAMPLES=$(subst ",,$(firstword $(def_args_fft))) bin/fft%: ENV_DEFINES += -DFFT_SAMPLES=$(subst ",,$(firstword $(def_args_fft))) endif -all: $(BINARIES) +all: apps_binaries riscv_tests rivec_binaries # Pre-process the linker-script to correclty align the sections .PHONY: linker_script @@ -62,7 +63,9 @@ linker_script: $(COMMON_DIR)/script/align_sections.sh $(ROOT_DIR)/../../config/$ # Make all applications $(APPS): % : bin/% $(APPS_DIR)/Makefile $(shell find common -type f) -.PHONY: $(BINARIES) +.PHONY: apps_binaries + +apps_binaries: $(BINARIES) # Patch spike crt0 to enable vector extension before execution .PHONY: patch-spike-crt0 @@ -114,8 +117,6 @@ bin/$1: $1/data.S.o $(addsuffix .o, $(shell find $(1) -name "*.c" -o -name "*.S" endef $(foreach app,$(APPS),$(eval $(call app_compile_template,$(app)))) -include rivec.mk - # Make the RISC-V tests riscv_tests: $(CVA6_BINARIES) $(ARA_BINARIES) @@ -174,8 +175,8 @@ riscv_tests_spike_clean: make -C riscv-tests/isa clean # Compile Standardized RISC-V tests -.PHONY: riscv_tests_compile -riscv_tests_compile: +.PHONY: riscv_tests_standard +riscv_tests_standard: cd riscv-tests && \ make benchmarks && make isa -i diff --git a/apps/README.md b/apps/README.md index 7f87aa9..8651107 100644 --- a/apps/README.md +++ b/apps/README.md @@ -3,6 +3,15 @@ This folder contains the benchmarks, programs, and tests ready to be run on AraXL. All software sources are licensed under [Apache 2.0](../LICENSE.sw). +1) Synthetic benchmarks such as `fmatmul`, `fconv2d` in this `apps/` folder +2) Custom RISC-V tests in `rvv-tests/` +3) RiVEC benchmarks as a git submodule `riscv-vectorized-benchmark-suite/` modified to run on the araxl baremetal environment + +To compile all tests and benchmarks +```bash +make all nr_clusters=2 +``` + SW utilities and benchmarks for AraXL using external contributions, * `RiVEC` - Use of the RISC-V VECTOR intrinsics mapping `common/rivec/vector_defines.h` and benchmarks `apps/cos`, `apps/log`, `apps/exp` by Cristóbal Ramírez Lazo, "Barcelona 2019" under [license](common/rivec/LICENSE) * `print` - `common/printf.c`, `common/printf.h` Print primitives for embedded systems under the MIT License (MIT) @@ -44,7 +53,7 @@ Example: ```bash cd apps -make bin/fconv2d OUT_MTX_SIZE=112 F_SIZE=7 +make bin/fconv2d def_args_fconv2d="64 64 7" ``` ### Standard RISC-V tests @@ -52,7 +61,7 @@ make bin/fconv2d OUT_MTX_SIZE=112 F_SIZE=7 To compile the standardized riscv tests from https://github.com/riscv/riscv-tests ```bash cd apps -make riscv_tests_compile +make riscv_tests_standard ``` ### RISC-V vector tests