#include <stdint.h>
#include <stdio.h>
#include <c7x.h>
#include "enable_cache_mmu.h"
#include "invalidate_tlb.h"
#include "DSPLIB_TEST_c7xecr.h"

#if !defined(_HOST_BUILD)
extern const uint64_t pte_lvl0[512];
#endif

/* C7x hardware cycle counter */
#ifndef __cregister
#define __cregister
#endif
extern volatile __cregister unsigned long __TSC;

#define MAT_N 256

/* 256x256 float matrix (~256 KB, fits in L2 SRAM) */
static float mat[MAT_N][MAT_N];

/* Prevent optimizer from removing computation */
static volatile float g_result_sink;

/* Initialize matrix data */
void initMatrix(void)
{
    int i, j;

    for (i = 0; i < MAT_N; i++)
    {
        for (j = 0; j < MAT_N; j++)
        {
            mat[i][j] = (float)(i + j + 1) * 0.01f;
        }
    }
}

/* Standalone benchmark test */
void benchmarkTestStandalone(void)
{
    int i, j;
    float v;

    unsigned long start_time;
    unsigned long stop_time;

    start_time = __TSC;

    for (i = 0; i < MAT_N; i++)
    {
        for (j = 0; j < MAT_N; j++)
        {
            v = mat[i][j];

            /* Same math kernel as app_c7x_opt_benchmark */
            v = v * 1.2345f + 0.9876f;
            v = v * v       - 0.4321f;

            mat[i][j] = v;
        }
    }

    stop_time = __TSC;

    /* Prevent dead-code elimination */
    g_result_sink = mat[0][0];

    printf("\nClock cycles elapsed = %lu",
           stop_time - start_time);
}

int main(void)
{
#if __C7X_VEC_SIZE_BITS__ == 512
   // Known silicon bug, errata: TBD
   __sa_set_cr(0, __sa_get_cr(1));
#endif

#if !defined(_HOST_BUILD)
   enable_cache_mmu((uint64_t) pte_lvl0);
   invalidate_tlb();
#endif

    printf("\n====================================");
    printf("\n C7x Standalone Math Benchmark");
    printf("\n====================================");

    initMatrix();

    benchmarkTestStandalone();

    printf("\n====================================");
    printf("\n Benchmark Complete");
    printf("\n====================================\n");

    return 0;
}
