
#include "shared.h"


unsigned short my_crc(unsigned char* src, unsigned long len)
{
    unsigned short crc16;
    unsigned long i;
    crc16 = crc16_start();
    for(i=0; i<len; i++)
    {
        crc16 = crc16_update(crc16, src[i]);
    }
    return crc16;
}

void my_dump(unsigned char* src, unsigned long interval, unsigned long count, char* filename, int id)
{
    sc_file_t* fh = NULL;
    unsigned long ret;
    int i;
    char buff[100];

    for(i=0; i<2; i++)
    {
        sprintf(buff, filename, id, i);

        scd_logout("Dump to PC (%s) ...", buff);
        fh = sc_fopen(SC_FILE_PC, buff);
        ret = sc_fwrite((void*)src+i*interval, count, fh);
        scd_logout(" Dump %d bytes to PC -> %d bytes [%d]", count, ret, count - ret);
        sc_fclose(fh);
    }
}




void test_shiftbench(void)
{
    unsigned long i;

    /* Benchmark names. */
    char* bench_names[10] = {"Test1", "test2", "pouet"};
    int bench_id;
    unsigned long tm;
    int* dst;
    int* src;

    unsigned long count = 30*1024;
    unsigned long count_u32 = count/4;
    /* Benchmark results. */
    unsigned long bench_ref; // empty loop time (us * count)
    unsigned long bench_bf = 0;  // Normal shift computation (us * count)
    unsigned long bench_af = 0;  // Optimized shift computation (us * count)
    unsigned char* data_in   = test_buffer;
    unsigned long data_count = TEST_BUFFER_SIZE/2; // 256K -> Max 64K integer iterations
    unsigned char* data_out  = data_in + data_count;
    unsigned short crc16_bf = 0, crc16_af = 0;

    while(1)
    {
        row = startrow;
        _printf(2, row+0, COLOR_WHITE, "%s", empty_line);
        _printf(2, row++, COLOR_SILVER, "Type Z to change bench size");

        do
        {
            sc_check();
            pad_read(&pad);
        } while(pad.new == 0);
        for(i=0; i<15; i++)
        {
            _printf(2, row+i, COLOR_WHITE, "%s", empty_line);
        }


        /* Change iteration count ? */
        if(pad.new & PAD_Z)
        {
            char* ret = scd_prompt("Enter benchmark size (KB unit):");
            count =  strtoul(ret, NULL, 0) * 1024;
            if(count <= 100) count = 100;
            if(count >= (TEST_BUFFER_SIZE/2)) count = TEST_BUFFER_SIZE/2;
        }
        _printf(2, row++, COLOR_SILVER, "bench size=%dB (%d KB)", count, count/1024);
        count_u32 = count/4;

        /* Fill input data with random values. */
        _printf(2, row++, COLOR_SILVER, "Fill input data ...");
#if 0
        for(i=0; i<TEST_BUFFER_SIZE; i++)
        {
            data_in[i] = rand() & 0xFF;
        }
#else
        src = (int*)data_in;
        for(i=0; i<count_u32; i++)
        {
            // Fill with unsigned integer values only.
            //*src++ = rand()&0x7FFFFFFF;
            *src++ = rand()&63000;
        }
#endif
//        strcpy(data_in, "This is test data start");

        /* Compute reference time. */
        _printf(2, row++, COLOR_SILVER, "Compute reference ...");
        dst = (int*)data_out; src = (int*)data_in;
        sc_tmr_start();
        for(i=0; i<count_u32; i++)
        {
            *dst++ = (*src++);
        }
        tm = sc_tmr_lap_usec();
        bench_ref = tm;
        _printf(2, row++, COLOR_SILVER, "REF=%d", bench_ref);
        scd_logout("REF=%d", bench_ref); scd_logflush();


        /* Perform each tests. */
        for(bench_id=0; bench_id<1; bench_id++)
        {
            scd_logout("Bench[%2d]:%s", bench_id, bench_names[bench_id]);
            _printf(2, row++, COLOR_SILVER, "Bench[%2d]:%s", bench_id, bench_names[bench_id]);

            if(bench_id == 0)
            {
#define f2i(A) ((A)>>8)
#define RSHIFT_BF(val) (f2i((val) >> 2))
#define RSHIFT_AF(val) (((unsigned long)(val)) >> 10)
                /* Before. */
                dst = (int*)data_out; src = (int*)data_in;
                sc_tmr_start();
                for(i=0; i<count_u32; i++)
                {
                    /* Check ASM here vvv */
                    *dst++ = RSHIFT_BF(*src++);
                    /* Check ASM here ^^^ */
                }
                tm = sc_tmr_lap_usec();
                bench_bf = tm;
                crc16_bf = my_crc(data_out, data_count);
                my_dump(data_in, data_count, count, "B%02d_BF_%d.DAT", bench_id);
                dst = (int*)data_out; src = (int*)data_in; _printf(2, row++, COLOR_SILVER, "  %08X -> %08X", src[0], dst[0]);

                /* After. */
                dst = (int*)data_out; src = (int*)data_in;
                sc_tmr_start();
                for(i=0; i<count_u32; i++)
                {
                    /* Check optimised ASM here vvv */
                    *dst++ = RSHIFT_AF(*src++);
                    /* Check optimised ASM here ^^^ */
                }
                tm = sc_tmr_lap_usec();
                bench_af = tm;
                crc16_af = my_crc(data_out, data_count);
                my_dump(data_in, data_count, count, "B%02d_AF_%d.DAT", bench_id);
                dst = (int*)data_out; src = (int*)data_in; _printf(2, row++, COLOR_SILVER, "  %08X -> %08X", src[0], dst[0]);
            }



            /* Display bench results. */
            _printf(2, row++, COLOR_SILVER, " %d -> %d CRC %04X %04X", bench_bf-bench_ref, bench_af-bench_ref, crc16_bf, crc16_af);
            scd_logout(" %d -> %d [%d -> %d]", bench_bf, bench_af, bench_bf-bench_ref, bench_af-bench_ref); scd_logflush();
        } // Bench loop

    } // While(1)
}


