OpenCores
URL https://opencores.org/ocsvn/tanhapprox/tanhapprox/trunk

Subversion Repositories tanhapprox

[/] [tanhapprox/] [trunk/] [ann.c] - Rev 3

Compare with Previous | Blame | View Log

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "ann.h"
#include "Data.h"
// include definitions for performance counter and custom instruction
#include "altera_avalon_performance_counter.h"
#include "system.h"
 
// debug options
#define PRINT_RESULTS    1
#define ACCELERATED_TANH 0
#define ACCELERATED_FLOATING_POINT 1
 
#if ACCELERATED_FLOATING_POINT == 0
#pragma no_custom_fadds
#pragma no_custom_fsubs
#pragma no_custom_fmuls
#pragma no_custom_fdivs
#endif // ACCELERATED_FLOATING_POINT == 0
 
#if ACCELERATED_TANH != 0
#define ALT_F_LOGSIG_APPROX_INST(A) __builtin_custom_fnf(ALT_CI_LOGSIG_APPROX_INST_N,(A))
#endif // ACCELERATED_TANH != 0
 
float aOutput[DATA_LENGTH][DATA_WIDTH];
 
void PrintArray(float *aIn, int nLength)
{
	int nIndex;  
 
    printf("\n");
	for (nIndex = 0; nIndex < nLength; nIndex++)
	{
		printf("%f ", aIn[nIndex]);
	}
	printf("\n");
}
 
int main()
{
	int nIndexCol, nIndexRow;
    float nMeanSquaredError = 0;
    float nCurrentError = 0;
 
	float aInputWeightsMultipliedByInput[DATA_WIDTH];
	float aIntermediate1[DATA_WIDTH];
 
	float aHiddenWeightsMultipliedByInt1[DATA_WIDTH];
	float aIntermediate2[DATA_WIDTH];
 
	float aOutputWeightsMultipliedByInt2[DATA_WIDTH];
 
    printf("Start: Tansig acceleration [%d], floating point unit [%d]\n", ACCELERATED_TANH, ACCELERATED_FLOATING_POINT );
 
    Normalize(aInput, DATA_LENGTH);
    ArrayFill(aOutput, DATA_LENGTH, 0);
 
    // start measuring time
    PERF_RESET (PERFORMANCE_COUNTER_0_BASE);            //Reset Performance Counters to 0
    PERF_START_MEASURING (PERFORMANCE_COUNTER_0_BASE);  //Start the Counter
    PERF_BEGIN (PERFORMANCE_COUNTER_0_BASE,2);          //Start the overhead counter
    PERF_BEGIN (PERFORMANCE_COUNTER_0_BASE,1);          //Start the Matrix Multiplication Counter
    PERF_END (PERFORMANCE_COUNTER_0_BASE,2);            //Stop the overhead counter
 
	for (nIndexCol = 0; nIndexCol < DATA_LENGTH; nIndexCol++)
	{
		MatrixMultiplication(aInputWeights, aInput[nIndexCol], aInputWeightsMultipliedByInput, false);
		MatrixAddition(aInputWeightsMultipliedByInput, aInputBias, aIntermediate1);
		ArrayTanh(aIntermediate1);
 
		MatrixMultiplication(aHiddenWeights, aIntermediate1, aHiddenWeightsMultipliedByInt1, false);
		MatrixAddition(aHiddenWeightsMultipliedByInt1, aHiddenBias, aIntermediate2);
		ArrayTanh(aIntermediate2);
 
		MatrixMultiplication(aOutputWeights, aIntermediate2, aOutputWeightsMultipliedByInt2, false);
		MatrixAddition(aOutputWeightsMultipliedByInt2, aOutputBias, aOutput[nIndexCol]);
	}
 
    PERF_END (PERFORMANCE_COUNTER_0_BASE,1);            //Stop the Matrix Multiplication Counter
    PERF_STOP_MEASURING (PERFORMANCE_COUNTER_0_BASE);   //Stop all counters  
    perf_print_formatted_report((void *)PERFORMANCE_COUNTER_0_BASE, ALT_CPU_FREQ, 2,
    "ANN Calcs","PC overhead");  
 
 
	Unnormalize(aOutput, DATA_LENGTH);
 
#if PRINT_RESULTS != 0
	// Print results
	printf("Results\n");
	for (nIndexCol = 0; nIndexCol < DATA_LENGTH; nIndexCol++)
	{
		// print only the first 3 columns of result matrix (as result is a Nx3 matrix)
        printf("%f %f %f\n", aOutput[nIndexCol][0], aOutput[nIndexCol][1], aOutput[nIndexCol][2] );
	}
#endif // PRINT_RESULTS != 0
 
	for (nIndexCol = 0; nIndexCol < DATA_LENGTH; nIndexCol++)
	{
		for (nIndexRow = 0; nIndexRow < (DATA_WIDTH - 1); nIndexRow++)
		{
			nCurrentError		= aOutput[nIndexCol][nIndexRow] - aExpectedResults[nIndexCol][nIndexRow];
			nMeanSquaredError	+= nCurrentError * nCurrentError;
		}
	}
 
	nMeanSquaredError = nMeanSquaredError / (DATA_LENGTH * (DATA_WIDTH - 1));
 
	printf("Mean Squared Error: %f", nMeanSquaredError);
 
	system("PAUSE");
}
 
 
void ArrayFill(float aInput[DATA_LENGTH][DATA_WIDTH], int nCountCol, float nValueToFill)
{
	int nIndexCol, nIndexRow;
    for (nIndexCol = 0; nIndexCol < nCountCol; nIndexCol++)
	{
		for (nIndexRow = 0; nIndexRow < DATA_WIDTH; nIndexRow++)
		{
			aInput[nIndexCol][nIndexRow] = nValueToFill;
		}
	}
}
 
 
void ArrayTanh(float aInput[DATA_WIDTH])
{
	int nIndexRow;
    for (nIndexRow = 0; nIndexRow < DATA_WIDTH; nIndexRow++)
	{
        // choose between accelerated and non-accelerated tangent sigmoid
#if ACCELERATED_TANH == 0
        // non-accelerated (calculate with math.h)
		aInput[nIndexRow] = tanhf(aInput[nIndexRow]);
#else
        // accelerated (estimate with dedicated look-up table)
        aInput[nIndexRow] = ALT_F_LOGSIG_APPROX_INST(aInput[nIndexRow]);
#endif
	}
}
 
 
// Multiplies a 4x4 matrix by a 4x1
void MatrixMultiplication(float aMatrix1[DATA_WIDTH][DATA_WIDTH], float aMatrix2[DATA_WIDTH], float aOutput[DATA_WIDTH], char bPrintResults)
{
	int nIndexRow, nIndexCol;
    if (bPrintResults == true) printf("beginning matrix multiplication\n");
	// Init Output to 0's
	for (nIndexRow = 0; nIndexRow < DATA_WIDTH; nIndexRow++)
	{
		aOutput[nIndexRow] = 0;
	}
 
	for (nIndexRow = 0; nIndexRow < DATA_WIDTH; nIndexRow++)
	{
		for (nIndexCol = 0; nIndexCol < DATA_WIDTH; nIndexCol++)
		{
			if (bPrintResults == true) printf("%f * %f\n",aMatrix1[nIndexRow][nIndexCol],aMatrix2[nIndexCol]);
			aOutput[nIndexRow] += aMatrix1[nIndexRow][nIndexCol] * aMatrix2[nIndexCol];
		}
	}
}
 
// Adds two 4x1 matrices
void MatrixAddition(float aMatrix1[DATA_WIDTH], float aMatrix2[DATA_WIDTH], float aOutput[DATA_WIDTH])
{
	int nIndexRow;
    for (nIndexRow = 0; nIndexRow < DATA_WIDTH; nIndexRow++)
	{
		aOutput[nIndexRow] = aMatrix1[nIndexRow] + aMatrix2[nIndexRow];
	}
}
 
 
// Normalizes matrix entries from -1 to 1
void Normalize(float aInput[DATA_LENGTH][DATA_WIDTH], int nCountCol)
{
	float aMin[DATA_WIDTH];
	float aMax[DATA_WIDTH];
	float nCurrentCell;
    int nIndexRow, nIndexCol;
 
	// First find min and max
	for ( nIndexRow = 0; nIndexRow < DATA_WIDTH; nIndexRow++ )
	{
		aMin[nIndexRow] = 9999999; // HACK!!
		aMax[nIndexRow] = 0;
		for ( nIndexCol = 0; nIndexCol < nCountCol; nIndexCol++ )
		{
			nCurrentCell = aInput[nIndexCol][nIndexRow];
			if (nCurrentCell < aMin[nIndexRow]) aMin[nIndexRow] = nCurrentCell;
			if (nCurrentCell > aMax[nIndexRow]) aMax[nIndexRow] = nCurrentCell;
		}
	}
 
 
	// Normalize
	for ( nIndexCol = 0; nIndexCol < nCountCol; nIndexCol++)
	{
		for ( nIndexRow = 0; nIndexRow < DATA_WIDTH; nIndexRow++)
		{
			nCurrentCell					= aInput[nIndexCol][nIndexRow];
			aInput[nIndexCol][nIndexRow]	= (((nCurrentCell - aMin[nIndexRow]) / (aMax[nIndexRow] - aMin[nIndexRow])) * 2) - 1;
		}
	}
}
 
// "Un-normalizes matrix"
void Unnormalize(float aInput[][DATA_WIDTH], int nCountCol)
{
	int nIndexCol, nIndexRow;
    for ( nIndexCol = 0; nIndexCol < nCountCol; nIndexCol++)
	{
		for ( nIndexRow = 0; nIndexRow < DATA_WIDTH; nIndexRow++)
		{
			aInput[nIndexCol][nIndexRow] = (aInput[nIndexCol][nIndexRow] + 1) / 2;
		}
	}
}
 
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.