/****************************************************************************** * Copyright (c) 2017, Texas Instruments Incorporated - http://www.ti.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of Texas Instruments Incorporated nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ /*============================================================================== This file shows an example of using LibArch function to do memory copy. ===============================================================================*/ #include #include #include #include #include #include #include #include #include #define TEST_BUFF_SIZE (1024*1024) #define TEST_DATA_SIZE (1024*1024) #define MAX_EDMA_1D1D_COPY_SIZE (65535) #define EDMA_2D2D_COPY_LINE_SIZE (1024) #pragma DATA_SECTION(data_buf1, ".DDR_DATA") #pragma DATA_ALIGN(data_buf1,128) char data_buf1[TEST_BUFF_SIZE]; #pragma DATA_SECTION(data_buf2, ".DDR_DATA") #pragma DATA_ALIGN(data_buf2,128) char data_buf2[TEST_BUFF_SIZE]; extern signed char* getGlobalAddr(signed char* addr); void fill_buffers(int *buf1, int *buf2, int num_elements); int verify_copy(char *in_ptr, char *out_ptr, int num_bytes); /*============================================================================== * This function benchmarks data transfer in external memory. It measures clock * cycles taken by memcpy versus LibArch functions for transfer sizes from * 8 bytes to 1M bytes. *============================================================================*/ void lib_benchmark_data_transfer() { EDMA3_DRV_Result result; Uint32 num_bytes, num_bytes_per_line, num_lines, pitch, test_data_size; lib_emt_Handle handle_emt; uint64_t clock_cntr_start, clock_cntr_end, cycles_edma, cycles_memcpy; int *in_ptr, *out_ptr; /* allocate a LibArch channel for data transfer */ handle_emt = lib_emt_alloc(1); // 1 as a dummy number as linked transfer is not used printf("Benchmarking results:\n"); printf("Transfer size (bytes)\t LibArch API\t memcpy\n"); in_ptr = (int *)getGlobalAddr((signed char *)&data_buf1[0]); // necessary when data_buf in L2 SRAM out_ptr = (int *)getGlobalAddr((signed char *)&data_buf2[0]); lib_clock_enable(); for(test_data_size=8; test_data_size<=TEST_BUFF_SIZE; test_data_size*=2) { /* Fill buffers with data for testing. */ fill_buffers((int *)&data_buf1[0], (int *)&data_buf2[0], test_data_size/sizeof(int)); num_bytes = test_data_size; /* Necessary to flush/invalidate cache when buffers are in cacheable area */ Cache_wb(in_ptr, num_bytes, Cache_Type_ALL, (Bool)TRUE); Cache_inv(out_ptr, num_bytes, Cache_Type_ALL, (Bool)TRUE); /*----- measure clock cycles used by LibArch functions -----*/ if(num_bytes <= MAX_EDMA_1D1D_COPY_SIZE) { /* 1D1D copy for sizes smaller than 65535 */ clock_cntr_start = lib_clock_read(); lib_emt_copy1D1D(handle_emt, in_ptr, out_ptr, num_bytes); lib_emt_wait(handle_emt); clock_cntr_end = lib_clock_read(); cycles_edma = clock_cntr_end - clock_cntr_start; if(verify_copy((char *)in_ptr, (char *)out_ptr, num_bytes)) { //printf("Clock cycles used by EDMA 1D1D copy is %lld.\n", cycles_edma); } else { printf("1D1D copy error!\n"); } } /* 1D1D copy */ else { /* 2D2D copy for sizes larger than 65535 */ clock_cntr_start = lib_clock_read(); num_bytes_per_line = EDMA_2D2D_COPY_LINE_SIZE; num_lines = num_bytes / EDMA_2D2D_COPY_LINE_SIZE; pitch = EDMA_2D2D_COPY_LINE_SIZE; lib_emt_copy2D2D(handle_emt, in_ptr, out_ptr, num_bytes_per_line, num_lines, pitch, pitch); lib_emt_wait(handle_emt); clock_cntr_end = lib_clock_read(); cycles_edma = clock_cntr_end - clock_cntr_start; if(verify_copy((char *)in_ptr, (char *)out_ptr, num_bytes)) { //printf("Clock cycles used by EDMA 2D2D copy is %lld.\n", cycles_edma); } else { printf("2D2D copy error!\n"); } } /* 2D2D copy */ /* Refill buffers with data for testing. */ fill_buffers((int *)&data_buf1[0], (int *)&data_buf2[0], test_data_size/sizeof(int)); /*----- measure clock cycles used by memcpy -----*/ clock_cntr_start = lib_clock_read(); memcpy(&data_buf2[0], &data_buf1[0], num_bytes); clock_cntr_end = lib_clock_read(); cycles_memcpy = clock_cntr_end - clock_cntr_start; if(verify_copy((char *)&data_buf1[0], (char *)&data_buf2[0], num_bytes)) { //printf("Clock cycles used by memcpy is %lld.\n", cycles_memcpy); } else { printf("memcpy error!\n"); } printf("%d\t\t\t%lld\t\t%lld\n", num_bytes, cycles_memcpy, cycles_edma); } /* free the LibArch channel allocated earlier */ lib_emt_free(handle_emt); } /* lib_benchmark_data_transfer */ /*============================================================================== * This function fills buffers with data. *============================================================================*/ void fill_buffers(int *buf1, int *buf2, int num_elements) { int i; for(i=0; i 0) { return 0; } else { return 1; } } /* nothing past this line */