ossc/ip/nios2_hw_crc/HAL/doc/crc_main.c

225 lines
11 KiB
C

/******************************************************************************
* *
* License Agreement *
* *
* Copyright (c) 2008 Altera Corporation, San Jose, California, USA. *
* All rights reserved. *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* Software is furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *
* DEALINGS IN THE SOFTWARE. *
* *
* This agreement shall be governed in all respects by the laws of the State *
* of California and by the laws of the United States of America. *
* Altera does not recommend, suggest or require that this reference design *
* file be used in conjunction or combination with any other product. *
******************************************************************************/
/******************************************************************************
* Author - JCJB *
* *
* This design uses the following CRC-32 implementations: *
* *
* --> Software - Uses modulo 2 division to perform the remainder calculation. *
* --> Optimized Software - Uses a lookup table of all possible division *
* values. The calculation operates on 8 bit data. *
* --> Custom Instruction - Uses a parallel hardware CRC circuit to calculate *
* the remainder. The calculation operates on 8, *
* 16, 24, or 32 bit data. *
* *
* The software implementations can be changed to CRC-16 or CRC-CCITT however *
* the custom instruction must be modified as well to support the same *
* standard. Simply use the values defined in crc.h to change the standard *
* used (using the same values in the hardware parameterization) or define *
* your own standard. *
*******************************************************************************/
#include "system.h"
#include "stdio.h"
#include "crc.h"
#include "ci_crc.h"
#include "sys/alt_timestamp.h"
#include "stdlib.h"
/* Modify these values to adjust the test being performed */
#define NUMBER_OF_BUFFERS 32
#define BUFFER_SIZE 256 /* in bytes */
/* Change the name of memory device according to what you are using
* e.g.: DDR_SDRAM_0 ##_SPAN
* SSRAM_0 ##_SPAN
*/
#define MEMORY_DEVICE_SIZE 32768
/* Make sure there is room left for Nios II text, rodata, rwdata, stack,
* and heap. This software and the buffer space must fit within the
* size of memory device. A total of 1.5 MBytes is reserved. If BUFFER_SIZE
* is a multiple of four then exactly 256kB will be left, otherwise is
* amount will be less since the column dimension needs some padding to
* stay 32 bit aligned
*/
#if ((BUFFER_SIZE * NUMBER_OF_BUFFERS) >= MEMORY_DEVICE_SIZE - 10000)
#error Your buffer space has exceeded the maximum allowable space. Please\
reduce the buffer space so that there is enough room to hold Nios II\
code.
#endif
/* This will line up the data onto a 32 bit (or greater) boundary. A 2d array
* is being used here for simplicity. The first dimension represents a byte
* of data and the second dimension represents an individual buffer
*/
#if ((BUFFER_SIZE & 0x3) == 0)
unsigned char data_buffer_region[NUMBER_OF_BUFFERS][BUFFER_SIZE] __attribute__ ((aligned(4)));
#else /* need to allocate extra bytes so that all buffers start on a 32 bit
boundaries by rounding up the column dimension to the next power of 4
*/
unsigned char data_buffer_region[NUMBER_OF_BUFFERS][BUFFER_SIZE + 4 - (BUFFER_SIZE&0x3)] __attribute__ ((aligned(4)));
#endif
int main()
{
unsigned long buffer_counter, data_counter;
unsigned long sw_slow_results[NUMBER_OF_BUFFERS];
unsigned long sw_fast_results[NUMBER_OF_BUFFERS];
unsigned long ci_results[NUMBER_OF_BUFFERS];
unsigned char random_data = 0x5A;
//unsigned long sw_slow_timeA, sw_slow_timeB;
// unsigned long sw_fast_timeA, sw_fast_timeB;
// unsigned long ci_timeA, ci_timeB;
alt_u32 sw_slow_timeA, sw_slow_timeB;
alt_u32 sw_fast_timeA, sw_fast_timeB;
alt_u32 ci_timeA, ci_timeB;
printf("+-----------------------------------------------------------+\n");
printf("| Comparison between software and custom instruction CRC32 |\n");
printf("+-----------------------------------------------------------+\n\n\n");
printf("System specification\n");
printf("--------------------\n");
printf("System clock speed = %lu MHz\n", (unsigned long)ALT_CPU_FREQ /(unsigned long)1000000);
printf("Number of buffer locations = %d\n", NUMBER_OF_BUFFERS);
printf("Size of each buffer = %d bytes\n\n\n", BUFFER_SIZE);
/* Initializing the data buffers */
printf("Initializing all of the buffers with pseudo-random data\n");
printf("-------------------------------------------------------\n");
for(buffer_counter = 0; buffer_counter < NUMBER_OF_BUFFERS; buffer_counter++)
{
for(data_counter = 0; data_counter < BUFFER_SIZE; data_counter++)
{
data_buffer_region[buffer_counter][data_counter] = random_data;
random_data = (random_data >> 4) + (random_data << 4) + (data_counter & 0xFF);
}
}
printf("Initialization completed\n\n\n");
if(alt_timestamp_start() < 0) // starts the timestamp timer
{
printf("Please add the high resolution timer to the timestamp timer setting in the syslib properties page.\n");
exit(1);
}
/* Slow software CRC based on a modulo 2 division implementation */
printf("Running the software CRC\n");
printf("------------------------\n");
sw_slow_timeA = alt_timestamp();
for(buffer_counter = 0; buffer_counter < NUMBER_OF_BUFFERS; buffer_counter++)
{
sw_slow_results[buffer_counter] = crcSlow(data_buffer_region[buffer_counter], BUFFER_SIZE);
}
sw_slow_timeB = alt_timestamp();
printf("Completed\n\n\n");
/* Fast software CRC based on a lookup table implementation */
crcInit();
printf("Running the optimized software CRC\n");
printf("----------------------------------\n");
sw_fast_timeA = alt_timestamp();
for(buffer_counter = 0; buffer_counter < NUMBER_OF_BUFFERS; buffer_counter++)
{
sw_fast_results[buffer_counter] = crcFast(data_buffer_region[buffer_counter], BUFFER_SIZE);
}
sw_fast_timeB = alt_timestamp();
printf("Completed\n\n\n");
/* Custom instruction CRC */
printf("Running the custom instruction CRC\n");
printf("----------------------------------\n");
ci_timeA = alt_timestamp();
for(buffer_counter = 0; buffer_counter < NUMBER_OF_BUFFERS; buffer_counter++)
{
ci_results[buffer_counter] = crcCI(data_buffer_region[buffer_counter], BUFFER_SIZE);
}
ci_timeB = alt_timestamp();
printf("Completed\n\n\n");
/* Validation of results */
printf("Validating the CRC results from all implementations\n");
printf("----------------------------------------------------\n");
for(buffer_counter = 0; buffer_counter < NUMBER_OF_BUFFERS; buffer_counter++)
{
/* Test every combination of results to make sure they are consistant */
if((sw_slow_results[buffer_counter] != ci_results[buffer_counter]) |
(sw_fast_results[buffer_counter] != ci_results[buffer_counter]))
{
printf("FAILURE! Software CRC = 0x%lx, Optimized Software CRC = 0x%lx, Custom Instruction CRC = 0x%lx,\n",
sw_slow_results[buffer_counter], sw_fast_results[buffer_counter], ci_results[buffer_counter]);
exit(1);
}
}
printf("All CRC implementations produced the same results\n\n\n");
// Report processing times
printf("Processing time for each implementation\n");
printf("---------------------------------------\n");
printf("Software CRC = %.2lu ms\n", 1000*((unsigned long)(sw_slow_timeB-sw_slow_timeA))/((unsigned long)alt_timestamp_freq()));
printf("Optimized software CRC = %.2lu ms\n", 1000*((unsigned long)(sw_fast_timeB-sw_fast_timeA))/((unsigned long)alt_timestamp_freq()));
printf("Custom instruction CRC = %.2lu ms\n\n\n", 1000*((unsigned long)(ci_timeB-ci_timeA))/((unsigned long)alt_timestamp_freq()));
printf("Processing throughput for each implementation\n"); // throughput = total bits / (time(s) * 1000000)
printf("---------------------------------------------\n");
printf("Software CRC = %.2lu Mbps\n", (8 * NUMBER_OF_BUFFERS * BUFFER_SIZE)/(1000000*(unsigned long)(sw_slow_timeB-sw_slow_timeA)/((unsigned long)alt_timestamp_freq())));
printf("Optimized software CRC = %.2lu Mbps\n", (8 * NUMBER_OF_BUFFERS * BUFFER_SIZE)/(1000000*(unsigned long)(sw_fast_timeB-sw_fast_timeA)/((unsigned long)alt_timestamp_freq())));
printf("Custom instruction CRC = %.2lu Mbps\n\n\n", (8 * NUMBER_OF_BUFFERS * BUFFER_SIZE)/(1000000*(unsigned long)(ci_timeB-ci_timeA)/((unsigned long)alt_timestamp_freq())));
printf("Speedup ratio\n");
printf("-------------\n");
printf("Custom instruction CRC vs software CRC = %lu\n", ((unsigned long)(sw_slow_timeB-sw_slow_timeA))/((unsigned long)(ci_timeB-ci_timeA)));
printf("Custom instruction CRC vs optimized software CRC = %lu\n", ((unsigned long)(sw_fast_timeB-sw_fast_timeA))/((unsigned long)(ci_timeB-ci_timeA)));
printf("Optimized software CRC vs software CRC= %lu\n", ((unsigned long)(sw_slow_timeB-sw_slow_timeA))/((unsigned long)(sw_fast_timeB-sw_fast_timeA)));
return 0;
}