Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision

Target

Select target project
  • avn/swd/rockets/r2a-obsw
  • avn/swd/rockets/lynx-obsw
  • avn/swd/rockets/tortellino-obsw
  • emilio.corigliano/obsw
4 results
Select Git revision
Show changes
Showing
with 16350 additions and 1 deletion
Subproject commit 5eb5356ba0cf9aedd3b444ff6f48761b1a576cd9
Subproject commit 667bdf009d5f87ac76a380fe17fecc21eea9fe48
# ABSURD: Another Benchmark Suite for Real-Time Embedded Systems
An open-source collection of benchmarks for real-time systems.
## Why another benchmark suite?
Many benchmark suites are available, however, they have numerous limitations
and missing features with respect to modern embedded applications.
### Main features
The benchmarks contained in this suite are developed with the following
features and goals:
* Written in C or C++
* Do not need any external library
* The use of the C or C++ standard library is limited to the necessary cases
* Input sizes and values are never hard-coded and can be provided by the user or
randomly generated
* Cover a wide range of systems, from a small microcontroller to a modern
multi-core processor
* When possible, provide an automatic check for the generated output to verify the
correct execution of the benchmark
### List of benchmarks
Check the list of benchmarks with their features
[here](docs/list-of-benchmarks.pdf).
## How to run this benchmark suite
The variety of embedded systems (platform architectures, compilers, tools,
operating systems, etc.) make the distribution of already compiled binaries for
the benchmark suite difficult and probably useless. You have to compile the C
programs, and the compilation process (e.g., make/cmake files) is up to you.
These benchmarks are developed to simplify the integration process. For
instance, they rely only on a small subset of standard C libraries\*, which are
usually available even in small microcontrollers.
Check the README in the `code` directory for further instruction on how to
compile the benchmark suite.
_\* With the exception of C++ multithread programs_
## Dataset & Reproducibility
We acquired time measurements on real platforms and published the data in the
[ABSURD data repository](https://github.com/HEAPLab/ABSURD-data). In addition,
to ensure reproducibility, a snapshot of the code and the dataset is periodically
performed (via Github tags) and published on different platforms (such as zenodo.org).
_Links to zenodo.org will appear here_
## Source code annotations
For most of the benchmarks, we provide an annotated version to run static analyses.
We moved the annotated code into the `annotated` branch of this repository. Please
be sure to change the relevant macros in the `user.h` file.
### Generator
No need the actual data but just want some synthetic data for your simulation?
You can use the ABSURD generator, which generates random execution times
based on the real dataset. Check the `generator` directory for further
information.
## License
All the software and datasets (with the exception described in the next paragraph)
are released under the Apache License. Please check the [LICENSE](LICENSE) file.
The source code of the benchmark `md5` has been taken from the RFC 1321. You may
want to check the original license before use and redistribute the software.
## Contributors
The software is mainly developed by [HEAP Lab - Politecnico di Milano](https://heaplab.deib.polimi.it).
Current maintainer: federico.reghenzani ~at~ polimi.it
Please check the Github authors' list for the individual contributors.
## Directory Content
- `include`: Support header files and custom input data examples
- `basic`: Very simple programs, such as simple loops or finding the maximum of an array
- `kernels`: Common algorithms of various complexity (sorting, fft, etc.)
- `apps`: Complex and complete applications
- `synthetic`: Not really computing anything, e.g., distribution-based loops, etc.
- `test`: Contains code and CMake files used to test and generate the datasets.
- `util`: Utility functions (currently the implementation of the PRNG function)
## Benchmarks configuration
ABSURD benchmark suite is easily re-configurable in order to leave the possibility to the users to tailor the benchmarks to their needs.
To configure the suite the users just have to edit the [user.h](include/user.h) and [dev_classes.h](include/dev_classes.h) as explained in the following sections.
### Pseudo-Random Generator Seed
Users can set the seed used by the PRNG function editing the `SEED` macro inside [user.h](include/user.h) file. The sequence generated depends only on the seed used by the generator, thus allowing to have input reproducibility
### Benchmarks input
To make ABSURD usable in as many scenarios as possible, we implemented the concept of device classes (5 classes, letter A to E) defing various parameters, such as array lengths or the input size, with the idea of ​​having the size of the inputs linked to the device type, targetting from microcontrollers (with A class) to high-end devices (with E class).
The users can find inside the file [dev_classes.h](include/dev_classes.h) the classes definitions and can modify them if not compatible with their scenarios.
Moreover, for benchmarks that work on images we offer the possibility to define custom input uncommenting the following macros inside [user.h](include/user.h):
```
/**Uncomment the following constants to enable the use of user-defined images in the respective benchmarks **/
/*#define USER_AVG_FILTER_RGB*/
/*#define USER_GAUSS_FILTER_RGB*/
/*#define USER_AVG_FILTER*/
/*#define USER_GAUSS_FILTER*/
/*#define USER_DILATE*/
/*#define USER_ERODE*/
/*#define USER_IMAGE_CANNY*/
/*#define USER_IMAGE_SCALING*/
/*#define USER_JPEG_COMPRESS*/
```
The user-defined images must be defined as you can see in the example files in [data](include/data) folder.
### Time measurement
Time measurement macro functions are defined inside [user.h](include/user.h) file and in the subfiles under `include/platforms` directory.
By implementing the macros `MEASURE_GLOBAL_VARIABLES()`,`MEASURE_START()` and `MEASURE_STOP()` users are able to respectively: perform the setup needed for the measurement, start and stop the measure.
For example:
```
/** Variables declared in the global scope to support measurements **/
#define MEASURE_GLOBAL_VARIABLES() static struct timespec start,stop; \
double result;
/** The code to be executed when the time measurement starts **/
#define MEASURE_START() do{ \
result=0; \
clock_gettime(CLOCK_MONOTONIC, &start); \
} while(0);
/** The code to be executed when the time measurement stops **/
#define MEASURE_STOP() do{ \
clock_gettime(CLOCK_MONOTONIC, &stop); \
result=(stop.tv_sec - start.tv_sec)*BILLION + (stop.tv_nsec - start.tv_nsec); \
} while(0);
```
### Output test
Some benchmarks offer the possibility to verify the obtained result at the end of computation through `CHECK_RESULT(x)` macro defined inside [user.h](include/user.h) file. Users can implement their version editing this file.
For example:
```
#define CHECK_RESULT(x) assert(x);
```
## How to compile
We include inside the repository the `CMake` files and code used to test and generate the datasets with Odroid-H2 and ST NUCLEO-F746ZG boards
To build the suite on your own, you have to clone the repository and create a folder where to save generated Makefiles, object files and output binaries:
```
git clone git@github.com:HEAPLab/ABSURD.git
cd ABSURD/code/test
mkdir build
cd build
```
Once done that, you have to configure the build through `cmake` command. For example:
```
cmake -DCLASS_A=ON -DNUCLEO_F746ZG=ON -DMULTI_THREAD=ON ..
```
Here is a full list of the available options and their descriptions:
- `CLASS_A`: compile using class A input parameters, default OFF;
- `CLASS_B`: compile using class B input parameters, default OFF;
- `CLASS_C`: compile using class C input parameters, default OFF;
- `CLASS_D`: compile using class D input parameters, default OFF;
- `CLASS_E`: compile using class E input parameters, default OFF;
- `MULTI_THREAD`: compile multi-threaded benchmarks. Default ON;
- `WITH_ANSI`: use ANSI C standard. Default OFF;
- `NUCLEO_F746ZG`: compile benchmarks for ST NUCLEO-F746ZG board. Default OFF. Due to memory size, benchmarks can be compiled only if class A or B are selected;
Finally, to compile:
```
make -j[number of jobs]
```
## Annotations
If you switch to `annotated` branch, you can find the same benchmarks but with annotated source code.
In order to properly run your WCET tool, you need to set the following macros:
- `#define ANN_LOOP_BOUND(iters)` - Maximum number of iterations of the following loop is `iters`
- `#define ANN_VAR(min,max)` - The next variable declaration has boundaries [`min`;`max`]
- `#define ANN_VAR_NOBOUNDS()` - The next variable declaration has no boundaries (bounded by variable itself)
- `#define ANN_RECURSION(rec_nr)` - The next function is recursive and can be called at most `rec_nr` times
The entry point of each benchmark is not annotated but can be easily identified as the first non-static function.
# Apps benchmarks
This folder contains complex programs. In particular:
- `ann`: it trains a random ANN with multiple hidden layer on random data;
- `canny`: implemention of Canny edge detector, it performs edge detection on a random/user defined grayscale image;
- `img_scaling`: it performs image scaling, through bicubic interpolation, on a random/user defined grayscale image;
- `jpeg_compress`: it performs JPEG compression on a random/user defined RGB image;
- `latnav`: it consists of a sequence of PID controllers emulating an aircraft autopilot for lateral navigation;
- `acas`: it emulates the 'Airborne Collision Avoidance System' (ACAS) with a variable number of aircrafts.
This diff is collapsed.
/******************************************************************************
* Copyright 2021 Politecnico di Milano
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
#include "user.h"
#include "simple_random.h"
#include <math.h>
#define IN_NODES 2
#define HIDDEN_NODES 2
#define HIDDEN_LAYERS 1
#define OUT_NODES 1
#define LR 0.1
#define NN_EPOCH 1
unsigned int ann_result;
MEASURE_GLOBAL_VARIABLES()
static double train_in[ARRAY_LENGTH][IN_NODES];
static double train_out[ARRAY_LENGTH][OUT_NODES];
static double net_out[OUT_NODES];
static double in_weight[IN_NODES][HIDDEN_NODES];
static double hl_weight[HIDDEN_LAYERS][HIDDEN_NODES][HIDDEN_NODES];
static double hl_bias[HIDDEN_LAYERS][HIDDEN_NODES];
static double out_weight[HIDDEN_NODES][OUT_NODES];
static double out_bias[OUT_NODES];
static double temp_out[HIDDEN_LAYERS][HIDDEN_NODES];
static double delta_out[OUT_NODES];
static double delta_hidden[HIDDEN_LAYERS][HIDDEN_NODES];
static double sigmoid(double x){
return 1/(1+exp(-x));
}
static double d_sigmoid(double x){
return x*(1-x);
}
static void init_train_data(){
int i;
for (i = 0; i < ARRAY_LENGTH; i++){
random_get_array(train_in[i],IN_NODES);
}
for (i = 0; i < ARRAY_LENGTH; i++){
random_get_array(train_out[i],OUT_NODES);
}
}
static void init_weights(){
int i,h,l;
for(i=0;i<IN_NODES;i++){
for ( h = 0; h < HIDDEN_NODES; h++){
in_weight[i][h]=random_get();
}
}
for(l=0;l<HIDDEN_LAYERS;l++){
for ( h = 0; h < HIDDEN_NODES; h++){
hl_bias[l][h]=random_get();
for(i=0;i<HIDDEN_NODES;i++){
hl_weight[l][h][i]=random_get();
}
}
}
for(i=0;i<OUT_NODES;i++){
out_bias[i]=random_get();
for ( h = 0; h < HIDDEN_NODES; h++){
out_weight[h][i]=random_get();
}
}
}
static void forward_pass(int train_idx){
int h,l,y;
for(h=0;h<HIDDEN_NODES;h++){
int x;
double activation;
activation=hl_bias[0][h];
for(x=0;x<IN_NODES;x++){
activation+=(in_weight[x][h]*train_in[train_idx][x]);
}
temp_out[0][h]=sigmoid(activation);
}
for(l=1;l<HIDDEN_LAYERS;l++){
for(h=0;h<HIDDEN_NODES;h++){
double activation;
int x;
activation=hl_bias[l][h];
for(x=0;x<HIDDEN_NODES;x++){
activation+=(hl_weight[l][h][x]*temp_out[l-1][h]);
}
temp_out[l][h]=sigmoid(activation);
}
}
for(y=0;y<OUT_NODES;y++){
double activation;
activation=out_bias[y];
for(h=0;h<HIDDEN_NODES;h++){
activation+=(out_weight[h][y]*temp_out[HIDDEN_LAYERS-1][h]);
}
net_out[y]=sigmoid(activation);
}
}
static void back_propagation(int train_idx){
int y,h,l,x;
/*Compute deltas for OUTPUT LAYER*/
for(y=0;y<OUT_NODES;y++){
delta_out[y] = (train_out[train_idx][y]-net_out[y])*d_sigmoid(net_out[y]);
}
/* Compute deltas for HIDDEN LAYER */
for(h=0;h<HIDDEN_NODES;h++){
double d_error;
d_error=0;
for(y=0;y<OUT_NODES;y++){
d_error+=delta_out[y]*out_weight[h][y];
}
delta_hidden[HIDDEN_LAYERS-1][h]=d_error*sigmoid(temp_out[HIDDEN_LAYERS-1][h]);
}
for(l=HIDDEN_NODES-2;l>=0;l--){
for(h=0;h<HIDDEN_NODES;h++){
double d_error;
d_error=0;
for(y=0;y<HIDDEN_NODES;y++){
d_error+=delta_hidden[l+1][y]*hl_weight[l][h][y];
}
delta_hidden[l][h]=d_error*sigmoid(temp_out[l][h]);
}
}
/*Update weights*/
for(y=0;y<OUT_NODES;y++){
out_bias[y]+=delta_out[y]*LR;
for(h=0;h<HIDDEN_NODES;h++){
out_weight[h][y]+=temp_out[HIDDEN_LAYERS-1][h]*delta_out[y]*LR;
}
}
for(l=HIDDEN_NODES-2;l>0;l--){
for(h=0;h<HIDDEN_NODES;h++){
hl_bias[l][h]+=delta_hidden[l][h]*LR;
for(x=0;x<IN_NODES;x++){
hl_weight[l][h][x]+=temp_out[l-1][x]*delta_hidden[l][h]*LR;
}
}
}
for(h=0;h<HIDDEN_NODES;h++){
hl_bias[0][h]+=delta_hidden[0][h]*LR;
for(x=0;x<IN_NODES;x++){
in_weight[x][h]+=train_in[train_idx][x]*delta_hidden[0][h]*LR;
}
}
}
/**
* @brief Actual neural network training implementation
*
*/
static void ann_routine(){
int i,j;
init_weights();
for(i=0; i<NN_EPOCH;i++){
for(j=0; j<ARRAY_LENGTH; j++){
forward_pass(j);
back_propagation(j);
}
}
}
/**
* @brief It trains a neural network on a random dataset. The execution time is measured through user defined MEASURE_START()/MEASURE_STOP() macros.
*/
void ann(){
init_train_data();
MEASURE_START(ann_result)
ann_routine();
MEASURE_STOP(ann_result)
}
\ No newline at end of file
/******************************************************************************
* Copyright 2021 Politecnico di Milano
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
#include "user.h"
#include "simple_random.h"
#include <math.h>
#ifdef USER_IMAGE_CANNY
#include "data/canny_image.h"
#endif
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
#define SIGMA 1.0
#define KERNEL_SIZE 5
#define CLAMP(v, min, max) if (v < min) { v = min; } else if (v > max) { v = max; }
unsigned int canny_result;
MEASURE_GLOBAL_VARIABLES()
#ifndef USER_IMAGE_CANNY
static unsigned char mat_in[IMG_HEIGHT][IMG_WIDTH];
static unsigned char mat_out[IMG_HEIGHT][IMG_WIDTH];
#endif
static unsigned char mat_blured[IMG_HEIGHT][IMG_WIDTH];
static double grad_orientation[IMG_HEIGHT][IMG_WIDTH];
static unsigned char mat_edges[IMG_HEIGHT][IMG_WIDTH];
static unsigned char top_bottom[IMG_HEIGHT][IMG_WIDTH];
static unsigned char bottom_top[IMG_HEIGHT][IMG_WIDTH];
static unsigned char left_right[IMG_HEIGHT][IMG_WIDTH];
static unsigned char right_left[IMG_HEIGHT][IMG_WIDTH];
/* KERNEL_SIZExKERNEL_SIZE gaussian filter with origin in (1,1) */
static double kernel_gauss[KERNEL_SIZE][KERNEL_SIZE];
/* Sobel operators */
static double sobel_x[3][3]={{-1,0,1},
{-2,0,2},
{-1,0,1}};
static double sobel_y[3][3]={{-1,-2,-1},
{0,0,0},
{1,2,1}};
/**
* @brief It generates a KERNEL_SIZE x KERNEL_SIZE gaussian kernel
*
*/
static void gaussian_kernel_init(){
int i;
double sum;
sum=0;
for (i = 0; i < KERNEL_SIZE; i++) {
int j;
for (j = 0; j < KERNEL_SIZE; j++) {
double x,y;
x = i - (KERNEL_SIZE - 1) / 2.0;
y = j - (KERNEL_SIZE - 1) / 2.0;
kernel_gauss[i][j] = exp(((pow(x, 2) + pow(y, 2)) / ((2 * pow(SIGMA, 2)))) * (-1));
sum += kernel_gauss[i][j];
}
}
for (i = 0; i < KERNEL_SIZE; i++) {
int j;
for (j = 0; j < KERNEL_SIZE; j++) {
kernel_gauss[i][j] /= sum;
}
}
}
/**
* @brief Performs 2D convolution of 3x3 kernel on src image
* @param src source image
* @param p_x center point x coordinate
* @param p_y center point y coordinate
* @param k 3x3 kernel
* @return int
*/
static int convolution2D_3x3(unsigned char src[IMG_HEIGHT][IMG_WIDTH], int p_x, int p_y,double k[3][3]){
int k_r,offset_x,offset_y,i;
double temp;
k_r=1;
/*kernel can be superimposed? if not we are on borders, then we keep the values unchanged*/
if(p_x-k_r<0 || p_y-k_r<0 || p_x+k_r>=IMG_HEIGHT || p_y+k_r>=IMG_WIDTH){
return src[p_x][p_y];
}
/*offset between kernel's indexes and array's ones */
offset_x=p_x-k_r;
offset_y=p_y-k_r;
temp=0;
for(i=p_x-k_r;i<=p_x+k_r;i++){
int j;
for(j=p_y-k_r;j<=p_y+k_r;j++){
temp+=k[i-offset_x][j-offset_y] * src[i][j];
}
}
return temp;
}
/**
* @brief Performs 2D convolution of 3x3 kernel on src image
* @param src source image
* @param p_x center point x coordinate
* @param p_y center point y coordinate
* @param k 5x5 kernel
* @return int
*/
static int convolution2D_5x5(unsigned char src[IMG_HEIGHT][IMG_WIDTH], int p_x, int p_y,double k[5][5]){
int k_r,offset_x,offset_y,i;
double temp;
k_r=2;
/*kernel can be superimposed? if not we are on borders, then we keep the values unchanged*/
if(p_x-k_r<0 || p_y-k_r<0 || p_x+k_r>=IMG_HEIGHT || p_y+k_r>=IMG_WIDTH){
return src[p_x][p_y];
}
/*offset between kernel's indexes and array's ones */
offset_x=p_x-k_r;
offset_y=p_y-k_r;
temp=0;
for(i=p_x-k_r;i<=p_x+k_r;i++){
int j;
for(j=p_y-k_r;j<=p_y+k_r;j++){
temp+=k[i-offset_x][j-offset_y] * src[i][j];
}
}
return temp;
}
/**
* @brief It applies sobel operator on input image
*
*/
static void sobel(){
int i;
for(i=0;i<IMG_HEIGHT;i++){
int j;
for(j=0;j<IMG_WIDTH;j++){
int mag_x,mag_y,mag;
mag_x=convolution2D_3x3(mat_blured,i,j,sobel_x);
mag_y=convolution2D_3x3(mat_blured,i,j,sobel_y);
mag=sqrt(mag_x*mag_x+mag_y*mag_y);
CLAMP(mag,0,255)
mat_edges[i][j]=mag;
grad_orientation[i][j]=atan2(mag_y,mag_x);
}
}
}
/**
* @brief It performs gauss filtering on input image
*
*/
static void gauss_filter(){
int i,j;
for(i=0;i<IMG_HEIGHT;i++){
for(j=0;j<IMG_WIDTH;j++){
mat_blured[i][j]=convolution2D_5x5(mat_in,i,j,kernel_gauss);
}
}
}
/**
* @brief It performs non-maximum suppression
*
*/
static void nms(){
int i,j;
for(i=1;i<IMG_HEIGHT;i++){
for(j=1;j<IMG_WIDTH;j++){
double direction,curr_p,next_p,prev_p;
direction=grad_orientation[i][j];
curr_p=mat_edges[i][j];
if((0 <= direction && direction < M_PI/8) || ((15*M_PI)/8 <= direction && direction < 2*M_PI)){
next_p=mat_edges[i][j+1];
prev_p=mat_edges[i][j-1];
}
else if ((M_PI/8 <= direction && direction < (3*M_PI)/8) || ((9*M_PI)/8 <= direction && direction < (11*M_PI)/8)){
next_p=mat_edges[i-1][j+1];
prev_p=mat_edges[i+1][j-1];
}
else if (((3*M_PI)/8 <= direction && direction < (5*M_PI)/8) || ((11*M_PI)/8 <= direction && direction < (13*M_PI)/8)){
next_p=mat_edges[i+1][j];
prev_p=mat_edges[i-1][j];
}
else{
next_p=mat_edges[i+1][j+1];
prev_p=mat_edges[i-1][j-1];
}
if(curr_p>= prev_p && curr_p>=next_p){
mat_out[i][j]=curr_p;
}
}
}
}
/**
* @brief It scans point's neighbours to check if the point at (x,y) is part of an edge
*
* @param x x coordinate
* @param y y coordinate
* @return unsigned char
*/
static unsigned char check_neighbours(int x, int y){
int i,j;
for(i=x;x-1>0 && i<IMG_HEIGHT;i++){
for(j=y;y-1>0 &&j<IMG_WIDTH;j++){
if(mat_out[i][j]==255) return 255;
}
}
return 0;
}
/**
* @brief It performs hysteresis thresholding
*
* @param low_thresh low threshold
* @param high_thresh high threshold
*/
static void hyst_tresh(int low_thresh, int high_thresh){
int i,j;
for(i=0;i<IMG_HEIGHT;i++){
for(j=0;j<IMG_WIDTH;j++){
int elem;
elem= mat_out[i][j];
if(elem>=high_thresh) top_bottom[i][j]=255;
else if (elem<=low_thresh) top_bottom[i][j]=0;
else top_bottom[i][j]=check_neighbours(i,j);
}
}
for(i=IMG_HEIGHT-1;i>=0;i--){
for(j=IMG_WIDTH-1;j>=0;j--){
int elem;
elem= mat_out[i][j];
if(elem>=high_thresh) bottom_top[i][j]=255;
else if (elem<=low_thresh) bottom_top[i][j]=0;
else bottom_top[i][j]=check_neighbours(i,j);
}
}
for(i=0;i<IMG_HEIGHT;i++){
for(j=IMG_WIDTH-1;j>=0;j--){
int elem;
elem= mat_out[i][j];
if(elem>=high_thresh) right_left[i][j]=255;
else if (elem<=low_thresh) right_left[i][j]=0;
else right_left[i][j]=check_neighbours(i,j);
}
}
for(i=IMG_HEIGHT-1;i>=0;i--){
for(j=0;j<IMG_WIDTH;j++){
int elem;
elem= mat_out[i][j];
if(elem>=high_thresh) left_right[i][j]=255;
else if (elem<=low_thresh) left_right[i][j]=0;
else left_right[i][j]=check_neighbours(i,j);
}
}
for(i=0;i<IMG_HEIGHT;i++){
for(j=0;j<IMG_WIDTH;j++){
int sum;
sum=top_bottom[i][j]+bottom_top[i][j]+left_right[i][j]+right_left[i][j];
CLAMP(sum,0,255)
mat_out[i][j]=sum;
}}
}
/**
* @brief Actual Canny algorithm implementation
*
*/
static void canny_routine(){
/*kernel initialization*/
gaussian_kernel_init();
gauss_filter();
sobel();
nms();
hyst_tresh(100,200);
}
/**
* @brief It performs canny algorithm on a random grayscale image . The execution time is measured through user defined MEASURE_START()/MEASURE_STOP() macros.
*/
void canny(){
int i;
#ifndef USER_IMAGE_CANNY
int j;
for (i = 0; i < IMG_HEIGHT; i++){
for (j = 0; j < IMG_WIDTH; j++){
mat_in[i][j]=random_get()*256;
}
}
#endif
MEASURE_START(canny_result);
canny_routine();
MEASURE_STOP(canny_result);
}
\ No newline at end of file
/******************************************************************************
* Copyright 2021 Politecnico di Milano
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
#include "user.h"
#include "simple_random.h"
#define SCALING_FACTOR 2
#ifdef USER_IMAGE_SCALING
#include "data/scaling_image.h"
#endif
#define CLAMP(v, min, max) if (v < min) { v = min; } else if (v > max) { v = max; }
unsigned int img_scaling_result;
MEASURE_GLOBAL_VARIABLES()
#ifndef USER_IMAGE_SCALING
static unsigned char mat_in[IMG_HEIGHT][IMG_WIDTH];
static unsigned char mat_out[SCALING_FACTOR*IMG_HEIGHT][SCALING_FACTOR*IMG_WIDTH];
#endif
static double hermit_poly(double p_0, double p_1, double p_2, double p_3, double x){
double a,b,c,d;
a = -p_0/2 + (3 *p_1)/2 - (3 *p_2)/2 + p_3/2;
b = p_0 - (5 *p_1)/2 + 2*p_2 - p_3/2;
c = - p_0/2 +p_2/2;
d = p_1;
return a*x*x*x + b*x*x +c*x+d;
}
static unsigned int get_pixel(int x, int y){
CLAMP(x,0,IMG_WIDTH);
CLAMP(y,0,IMG_HEIGHT);
return mat_in[x][y];
}
static double bicubic_interpolation(int x,int y, double dx, double dy){
double col0,col1,col2,col3,res;
col0=hermit_poly(get_pixel(x-1,y-1),get_pixel(x,y-1),get_pixel(x+1,y-1),get_pixel(x+2,y-1),dx);
col1=hermit_poly(get_pixel(x-1,y),get_pixel(x,y),get_pixel(x+1,y),get_pixel(x+2,y),dx);
col2=hermit_poly(get_pixel(x-1,y+1),get_pixel(x,y+1),get_pixel(x+1,y+1),get_pixel(x+2,y+1),dx);
col3=hermit_poly(get_pixel(x-1,y+2),get_pixel(x,y+2),get_pixel(x+1,y+2),get_pixel(x+2,y+2),dx);
res=hermit_poly(col0,col1,col2,col3,dy);
CLAMP(res,0,255);
return res;
}
/**
* @brief Actual image scaling implementation
*
*/
static void img_scaling_routine(){
int i,j;
for(i=0;i<SCALING_FACTOR*IMG_HEIGHT;i++){
for(j=0;j<SCALING_FACTOR*IMG_WIDTH;j++){
int x,y;
double dx,dy;
x = i/SCALING_FACTOR;
y = j/SCALING_FACTOR;
dx=i/SCALING_FACTOR-x;
dy=j/SCALING_FACTOR-y;
mat_out[i][j]=bicubic_interpolation(x,y,dx,dy);
}
}
}
/**
* @brief It performs image scaling on a random RGB image using bicubic interpolation. The execution time is measured through user defined MEASURE_START()/MEASURE_STOP() macros.
*/
void img_scaling(){
int i;
#ifndef USER_IMAGE_SCALING
int j;
for (i = 0; i < IMG_HEIGHT; i++){
for (j = 0; j < IMG_WIDTH; j++){
mat_in[i][j]=random_get()*256;
}
}
#endif
MEASURE_START(img_scaling_result);
img_scaling_routine();
MEASURE_STOP(img_scaling_result);
}
\ No newline at end of file
This diff is collapsed.
/******************************************************************************
* Copyright 2021 Politecnico di Milano
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
#include "user.h"
#include "simple_random.h"
#include <math.h>
#define TIME_STEP 0.001
#define CLAMP(x, minim, maxim) (x < minim ? minim : (x > maxim ? maxim : x))
unsigned int latnav_result;
MEASURE_GLOBAL_VARIABLES()
typedef struct pid_controller_s {
double p;
double i;
double d;
double b;
double prev_error;
double integral_sum;
double backpropagation;
} pid_controller_t;
double run_pid(pid_controller_t* pid, double error) {
double output;
output = error * pid->p;
pid->integral_sum += ((error * pid->i) + (pid->b * pid->backpropagation)) * TIME_STEP;
output += pid->integral_sum;
output += pid->d * (error - pid->prev_error) / TIME_STEP;
pid->prev_error = error;
return output;
}
double roll_limiter(double desired_roll, double speed) {
double limit_perc,limit;
if (speed <= 140) {
return CLAMP(desired_roll, -30, 30);
}
if (speed >= 300) {
return CLAMP(desired_roll, -40, 40);
}
limit_perc = (speed < 220) ? (speed-140) / 80 : ((speed-220) / 80);
limit = (speed < 220) ? (30 + limit_perc * 37) : (40 + (1-limit_perc) * 27);
return CLAMP (desired_roll, -limit, limit);
}
double roll_rate_limiter(double desired_roll_rate, double roll) {
if (roll < 20 && roll > -20) {
return CLAMP (desired_roll_rate, -5, 5);
} else if (roll < 30 && roll > -30) {
return CLAMP (desired_roll_rate, -3, 3);
} else {
return CLAMP (desired_roll_rate, -1, 1);
}
}
double ailerons_limiter(double aileron) {
return CLAMP(aileron, -30, 30);
}
void latnav() {
pid_controller_t pid_roll_rate,pid_roll,pid_heading;
double curr_heading,curr_roll,curr_roll_rate;
int i;
pid_roll_rate.p = random_get();
pid_roll_rate.i = random_get();
pid_roll_rate.d = random_get();
pid_roll_rate.b = random_get();
pid_roll.p = random_get();
pid_roll.i = random_get();
pid_roll.d = random_get();
pid_roll.b = random_get();
pid_heading.p = random_get();
pid_heading.i = random_get();
pid_heading.d = random_get();
pid_heading.b = random_get();
pid_roll_rate.integral_sum= pid_roll_rate.prev_error= pid_roll_rate.backpropagation= 0;
pid_roll.integral_sum = pid_roll.prev_error = pid_roll.backpropagation = 0;
pid_heading.integral_sum = pid_heading.prev_error = pid_heading.backpropagation = 0;
curr_heading = random_get();
curr_roll = random_get();
curr_roll_rate = random_get();
MEASURE_START(latnav_result);
for(i=0; i<ITERATIONS; i++) {
double desired_roll,actual_roll,desired_roll_rate,actual_roll_rate,desired_ailerons,actual_ailerons;
desired_roll = run_pid(&pid_heading, curr_heading-random_get());
actual_roll = roll_limiter(desired_roll, 400);
pid_heading.backpropagation = actual_roll - desired_roll;
desired_roll_rate = run_pid(&pid_roll, curr_roll - actual_roll);
actual_roll_rate = roll_rate_limiter(desired_roll_rate, curr_roll);
pid_roll.backpropagation = actual_roll_rate - desired_roll_rate;
desired_ailerons = run_pid(&pid_roll, curr_roll_rate - actual_roll_rate);
actual_ailerons = ailerons_limiter(desired_roll_rate);
pid_roll.backpropagation = actual_ailerons - desired_ailerons;
/* Just a random plane model*/
curr_heading += curr_roll/10 * TIME_STEP;
curr_roll += curr_roll_rate * TIME_STEP;
curr_roll_rate += desired_ailerons / 5;
}
MEASURE_STOP(latnav_result);
}
This diff is collapsed.
This diff is collapsed.
#ifndef IRIS_DATASET_H_
#define IRIS_DATASET_H_
#define IRIS_DATASET_LEN 150
double iris_dataset[IRIS_DATASET_LEN][5]={
//Iris-setosa
{5.1,3.5,1.4,0.2,0.0},
{4.9,3.0,1.4,0.2,0.0},
{4.7,3.2,1.3,0.2,0.0},
{4.6,3.1,1.5,0.2,0.0},
{5.0,3.6,1.4,0.2,0.0},
{5.4,3.9,1.7,0.4,0.0},
{4.6,3.4,1.4,0.3,0.0},
{5.0,3.4,1.5,0.2,0.0},
{4.4,2.9,1.4,0.2,0.0},
{4.9,3.1,1.5,0.1,0.0},
{5.4,3.7,1.5,0.2,0.0},
{4.8,3.4,1.6,0.2,0.0},
{4.8,3.0,1.4,0.1,0.0},
{4.3,3.0,1.1,0.1,0.0},
{5.8,4.0,1.2,0.2,0.0},
{5.7,4.4,1.5,0.4,0.0},
{5.4,3.9,1.3,0.4,0.0},
{5.1,3.5,1.4,0.3,0.0},
{5.7,3.8,1.7,0.3,0.0},
{5.1,3.8,1.5,0.3,0.0},
{5.4,3.4,1.7,0.2,0.0},
{5.1,3.7,1.5,0.4,0.0},
{4.6,3.6,1.0,0.2,0.0},
{5.1,3.3,1.7,0.5,0.0},
{4.8,3.4,1.9,0.2,0.0},
{5.0,3.0,1.6,0.2,0.0},
{5.0,3.4,1.6,0.4,0.0},
{5.2,3.5,1.5,0.2,0.0},
{5.2,3.4,1.4,0.2,0.0},
{4.7,3.2,1.6,0.2,0.0},
{4.8,3.1,1.6,0.2,0.0},
{5.4,3.4,1.5,0.4,0.0},
{5.2,4.1,1.5,0.1,0.0},
{5.5,4.2,1.4,0.2,0.0},
{4.9,3.1,1.5,0.1,0.0},
{5.0,3.2,1.2,0.2,0.0},
{5.5,3.5,1.3,0.2,0.0},
{4.9,3.1,1.5,0.1,0.0},
{4.4,3.0,1.3,0.2,0.0},
{5.1,3.4,1.5,0.2,0.0},
{5.0,3.5,1.3,0.3,0.0},
{4.5,2.3,1.3,0.3,0.0},
{4.4,3.2,1.3,0.2,0.0},
{5.0,3.5,1.6,0.6,0.0},
{5.1,3.8,1.9,0.4,0.0},
{4.8,3.0,1.4,0.3,0.0},
{5.1,3.8,1.6,0.2,0.0},
{4.6,3.2,1.4,0.2,0.0},
{5.3,3.7,1.5,0.2,0.0},
{5.0,3.3,1.4,0.2,0.0},
//Iris-versicolor
{7.0,3.2,4.7,1.4,1.0},
{6.4,3.2,4.5,1.5,1.0},
{6.9,3.1,4.9,1.5,1.0},
{5.5,2.3,4.0,1.3,1.0},
{6.5,2.8,4.6,1.5,1.0},
{5.7,2.8,4.5,1.3,1.0},
{6.3,3.3,4.7,1.6,1.0},
{4.9,2.4,3.3,1.0,1.0},
{6.6,2.9,4.6,1.3,1.0},
{5.2,2.7,3.9,1.4,1.0},
{5.0,2.0,3.5,1.0,1.0},
{5.9,3.0,4.2,1.5,1.0},
{6.0,2.2,4.0,1.0,1.0},
{6.1,2.9,4.7,1.4,1.0},
{5.6,2.9,3.6,1.3,1.0},
{6.7,3.1,4.4,1.4,1.0},
{5.6,3.0,4.5,1.5,1.0},
{5.8,2.7,4.1,1.0,1.0},
{6.2,2.2,4.5,1.5,1.0},
{5.6,2.5,3.9,1.1,1.0},
{5.9,3.2,4.8,1.8,1.0},
{6.1,2.8,4.0,1.3,1.0},
{6.3,2.5,4.9,1.5,1.0},
{6.1,2.8,4.7,1.2,1.0},
{6.4,2.9,4.3,1.3,1.0},
{6.6,3.0,4.4,1.4,1.0},
{6.8,2.8,4.8,1.4,1.0},
{6.7,3.0,5.0,1.7,1.0},
{6.0,2.9,4.5,1.5,1.0},
{5.7,2.6,3.5,1.0,1.0},
{5.5,2.4,3.8,1.1,1.0},
{5.5,2.4,3.7,1.0,1.0},
{5.8,2.7,3.9,1.2,1.0},
{6.0,2.7,5.1,1.6,1.0},
{5.4,3.0,4.5,1.5,1.0},
{6.0,3.4,4.5,1.6,1.0},
{6.7,3.1,4.7,1.5,1.0},
{6.3,2.3,4.4,1.3,1.0},
{5.6,3.0,4.1,1.3,1.0},
{5.5,2.5,4.0,1.3,1.0},
{5.5,2.6,4.4,1.2,1.0},
{6.1,3.0,4.6,1.4,1.0},
{5.8,2.6,4.0,1.2,1.0},
{5.0,2.3,3.3,1.0,1.0},
{5.6,2.7,4.2,1.3,1.0},
{5.7,3.0,4.2,1.2,1.0},
{5.7,2.9,4.2,1.3,1.0},
{6.2,2.9,4.3,1.3,1.0},
{5.1,2.5,3.0,1.1,1.0},
{5.7,2.8,4.1,1.3,1.0},
//Iris-virginica
{6.3,3.3,6.0,2.5,2.0},
{5.8,2.7,5.1,1.9,2.0},
{7.1,3.0,5.9,2.1,2.0},
{6.3,2.9,5.6,1.8,2.0},
{6.5,3.0,5.8,2.2,2.0},
{7.6,3.0,6.6,2.1,2.0},
{4.9,2.5,4.5,1.7,2.0},
{7.3,2.9,6.3,1.8,2.0},
{6.7,2.5,5.8,1.8,2.0},
{7.2,3.6,6.1,2.5,2.0},
{6.5,3.2,5.1,2.0,2.0},
{6.4,2.7,5.3,1.9,2.0},
{6.8,3.0,5.5,2.1,2.0},
{5.7,2.5,5.0,2.0,2.0},
{5.8,2.8,5.1,2.4,2.0},
{6.4,3.2,5.3,2.3,2.0},
{6.5,3.0,5.5,1.8,2.0},
{7.7,3.8,6.7,2.2,2.0},
{7.7,2.6,6.9,2.3,2.0},
{6.0,2.2,5.0,1.5,2.0},
{6.9,3.2,5.7,2.3,2.0},
{5.6,2.8,4.9,2.0,2.0},
{7.7,2.8,6.7,2.0,2.0},
{6.3,2.7,4.9,1.8,2.0},
{6.7,3.3,5.7,2.1,2.0},
{7.2,3.2,6.0,1.8,2.0},
{6.2,2.8,4.8,1.8,2.0},
{6.1,3.0,4.9,1.8,2.0},
{6.4,2.8,5.6,2.1,2.0},
{7.2,3.0,5.8,1.6,2.0},
{7.4,2.8,6.1,1.9,2.0},
{7.9,3.8,6.4,2.0,2.0},
{6.4,2.8,5.6,2.2,2.0},
{6.3,2.8,5.1,1.5,2.0},
{6.1,2.6,5.6,1.4,2.0},
{7.7,3.0,6.1,2.3,2.0},
{6.3,3.4,5.6,2.4,2.0},
{6.4,3.1,5.5,1.8,2.0},
{6.0,3.0,4.8,1.8,2.0},
{6.9,3.1,5.4,2.1,2.0},
{6.7,3.1,5.6,2.4,2.0},
{6.9,3.1,5.1,2.3,2.0},
{5.8,2.7,5.1,1.9,2.0},
{6.8,3.2,5.9,2.3,2.0},
{6.7,3.3,5.7,2.5,2.0},
{6.7,3.0,5.2,2.3,2.0},
{6.3,2.5,5.0,1.9,2.0},
{6.5,3.0,5.2,2.0,2.0},
{6.2,3.4,5.4,2.3,2.0},
{5.9,3.0,5.1,1.8,2.0}
};
#endif //IRIS_DATASET_H
\ No newline at end of file
This diff is collapsed.