/****************************************************************************** * * * 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; }