Skip to content

Commit

Permalink
Add example_data_procssing_from_flash (#568)
Browse files Browse the repository at this point in the history
  • Loading branch information
FrancescoPoluzzi authored Sep 6, 2024
1 parent 98dde53 commit a3db63b
Show file tree
Hide file tree
Showing 4 changed files with 400 additions and 0 deletions.
65 changes: 65 additions & 0 deletions sw/applications/example_data_processing_from_flash/gen_stimuly.py
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')
87 changes: 87 additions & 0 deletions sw/applications/example_data_processing_from_flash/main.c
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;
}
42 changes: 42 additions & 0 deletions sw/applications/example_data_processing_from_flash/main.h
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_
Loading

0 comments on commit a3db63b

Please sign in to comment.