-
Notifications
You must be signed in to change notification settings - Fork 82
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add example_data_procssing_from_flash (#568)
- Loading branch information
1 parent
98dde53
commit a3db63b
Showing
4 changed files
with
400 additions
and
0 deletions.
There are no files selected for viewing
65 changes: 65 additions & 0 deletions
65
sw/applications/example_data_processing_from_flash/gen_stimuly.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
#!/usr/bin/env python | ||
|
||
## Copyright 2024 EPFL | ||
## Solderpad Hardware License, Version 2.1, see LICENSE.md for details. | ||
## SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 | ||
|
||
# type " python gen_stimuly.py " in the terminal to generate the matrices.h file | ||
|
||
import sys | ||
import random | ||
import numpy as np | ||
|
||
def write_arr(f, name, arr, ctype, size): | ||
f.write("const " + ctype + " " + name + "[] = {\n") | ||
|
||
for row in arr: | ||
for elem in row[:-1]: | ||
f.write('%d,' % (elem)) | ||
f.write('%d,\n' % (row[-1])) | ||
|
||
f.write('};\n\n') | ||
return | ||
|
||
def write_arr_flash_only(f, name, arr, ctype, size): | ||
f.write( ctype + " __attribute__((section(\".xheep_data_flash_only\"))) __attribute__ ((aligned (16)))" + name + "[] = {\n") | ||
|
||
for row in arr: | ||
for elem in row[:-1]: | ||
f.write('%d,' % (elem)) | ||
f.write('%d,\n' % (row[-1])) | ||
|
||
f.write('};\n\n') | ||
return | ||
|
||
|
||
################################################################################ | ||
f = open('matrices.h', 'w') | ||
f.write('#ifndef MATRICES_H_\n') | ||
f.write('#define MATRICES_H_\n') | ||
f.write('// This file is automatically generated\n') | ||
|
||
|
||
SIZE = 64 | ||
RANGE = 10 | ||
|
||
m_a = [] | ||
m_b = [] | ||
m_exp = [] | ||
|
||
# Generate random 8 bit integers from -RANGE to RANGE for A and B | ||
A = np.random.randint(0, RANGE, size=(SIZE, SIZE), dtype=np.int32) | ||
B = np.random.randint(0, RANGE, size=(SIZE, SIZE), dtype=np.int32) | ||
C = np.zeros((SIZE, SIZE), dtype=np.int32) | ||
|
||
# Test the function with A and B | ||
C = np.matmul(A,B) | ||
|
||
write_arr_flash_only(f, 'A', A, 'int32_t', SIZE) | ||
write_arr(f, 'B', B, 'int32_t', SIZE) | ||
write_arr(f, 'C', C, 'int32_t', SIZE) | ||
|
||
f.write('#define MATRIX_SIZE %d\n' % SIZE) | ||
|
||
|
||
f.write('#endif') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
// Copyright 2024 EPFL | ||
// Solderpad Hardware License, Version 2.1, see LICENSE.md for details. | ||
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 | ||
// | ||
// File: sw/applications/example_data_processing_from_flash/main.c | ||
// Author: Francesco Poluzzi | ||
// Date: 29/07/2024 | ||
|
||
/** | ||
* @file main.c | ||
* @brief Example of data processing (matrix multiplication) reading data from flash memory | ||
* | ||
* Simple example that read a matrix from flash memory in many step and performs | ||
* matrix multiplication. This is useful for applications where the | ||
* data size does not fit in the available SRAM memory, so some data needs to be | ||
* stored as "flash_only" and read trough the spi interface. This usually requires | ||
* filling a buffer and tiling the data processing. | ||
*/ | ||
|
||
#include <stdio.h> | ||
#include <stdint.h> | ||
#include <stdlib.h> | ||
|
||
#include "x-heep.h" | ||
#include "w25q128jw.h" | ||
#include "main.h" | ||
#include "dma_sdk.h" | ||
|
||
#define TILING_ROWS 2 | ||
|
||
/* By default, printfs are activated for FPGA and disabled for simulation. */ | ||
#define PRINTF_IN_FPGA 1 | ||
#define PRINTF_IN_SIM 0 | ||
#if TARGET_SIM && PRINTF_IN_SIM | ||
#define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) | ||
#elif PRINTF_IN_FPGA && !TARGET_SIM | ||
#define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) | ||
#else | ||
#define PRINTF(...) | ||
#endif | ||
|
||
int32_t buffer_data[MATRIX_SIZE*TILING_ROWS] = {0}; | ||
int32_t output_matrix[MATRIX_SIZE*MATRIX_SIZE] = {0}; | ||
|
||
int main(int argc, char *argv[]) { | ||
|
||
soc_ctrl_t soc_ctrl; | ||
soc_ctrl.base_addr = mmio_region_from_addr((uintptr_t)SOC_CTRL_START_ADDRESS); | ||
|
||
#ifdef TARGET_SIM | ||
PRINTF("This application is meant to run on FPGA only\n"); | ||
return EXIT_SUCCESS; | ||
#endif | ||
|
||
if ( get_spi_flash_mode(&soc_ctrl) == SOC_CTRL_SPI_FLASH_MODE_SPIMEMIO ) { | ||
PRINTF("This application cannot work with the memory mapped SPI FLASH" | ||
"module - do not use the FLASH_EXEC linker script for this application\n"); | ||
return EXIT_SUCCESS; | ||
} | ||
|
||
// Pick the correct spi device based on simulation type | ||
spi_host_t* spi = spi_flash; | ||
|
||
// Init SPI host and SPI<->Flash bridge parameters | ||
if (w25q128jw_init(spi) != FLASH_OK){ | ||
PRINTF("Error initializing SPI flash\n"); | ||
return EXIT_FAILURE; | ||
} | ||
|
||
for (int i = 0; i < MATRIX_SIZE; i+=TILING_ROWS) { | ||
// read first half matrix A from flash and perform matmul | ||
if(fill_buffer(&A[i*MATRIX_SIZE], buffer_data, MATRIX_SIZE*TILING_ROWS)!=FLASH_OK){ | ||
PRINTF("Error reading from flash\n"); | ||
return EXIT_FAILURE; | ||
} | ||
matmul(buffer_data, B, &output_matrix[i*MATRIX_SIZE], TILING_ROWS, MATRIX_SIZE, MATRIX_SIZE); | ||
} | ||
|
||
for(int i = 0; i < MATRIX_SIZE*MATRIX_SIZE; i++){ | ||
if (output_matrix[i] != C[i]){ | ||
PRINTF("Result[%d][%d]:golden model %d : %d\n", (i/MATRIX_SIZE), (i % MATRIX_SIZE), output_matrix[i], C[i]); | ||
return EXIT_FAILURE; | ||
} | ||
} | ||
PRINTF("All tests passed!\n"); | ||
return EXIT_SUCCESS; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
// Copyright 2024 EPFL | ||
// Solderpad Hardware License, Version 2.1, see LICENSE.md for details. | ||
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 | ||
// | ||
// File: sw/applications/example_data_processing_from_flash/main.h | ||
// Author: Francesco Poluzzi | ||
// Date: 29/07/2024 | ||
|
||
#ifndef MAIN_H_ | ||
#define MAIN_H_ | ||
|
||
#include <stdio.h> | ||
#include <stdint.h> | ||
#include <stdlib.h> | ||
|
||
#include "x-heep.h" | ||
#include "w25q128jw.h" | ||
#include "matrices.h" | ||
|
||
w25q_error_codes_t fill_buffer(uint32_t *source, uint32_t *buffer, uint32_t len); | ||
void matmul(int32_t *A, int32_t *B, int32_t *res, int rowsA, int colsA, int colsB); | ||
|
||
w25q_error_codes_t fill_buffer(uint32_t *source, uint32_t *buffer, uint32_t len){ | ||
uint32_t *source_flash = heep_get_flash_address_offset(source); | ||
w25q_error_codes_t status = w25q128jw_read_standard(source_flash, buffer, len*4); | ||
return status; | ||
} | ||
|
||
void matmul(int32_t *A, int32_t *B, int32_t *res, int rowsA, int colsA, int colsB) { | ||
for (int i = 0; i < rowsA; i++) { | ||
for (int j = 0; j < colsB; j++) { | ||
int32_t sum = 0; | ||
for (int k = 0; k < colsA; k++) { | ||
sum += A[i*colsA + k] * B[k*colsB + j]; | ||
} | ||
res[i*colsB + j] = sum; | ||
} | ||
} | ||
} | ||
|
||
|
||
#endif // DATA_H_ |
Oops, something went wrong.