1/* Test viterbi decoder speeds */ 2#include "config.h" 3#include <stdio.h> 4#include <stdlib.h> 5#include <unistd.h> 6#include <time.h> 7#include <math.h> 8#include <memory.h> 9#include <sys/time.h> 10#include <sys/resource.h> 11#ifdef HAVE_GETOPT_H 12#include <getopt.h> 13#endif 14#include "fec.h" 15 16#if HAVE_GETOPT_LONG 17struct option Options[] = { 18 {"frame-length",1,NULL,'l'}, 19 {"frame-count",1,NULL,'n'}, 20 {"ebn0",1,NULL,'e'}, 21 {"gain",1,NULL,'g'}, 22 {"verbose",0,NULL,'v'}, 23 {"force-altivec",0,NULL,'a'}, 24 {"force-port",0,NULL,'p'}, 25 {"force-mmx",0,NULL,'m'}, 26 {"force-sse",0,NULL,'s'}, 27 {"force-sse2",0,NULL,'t'}, 28 {NULL}, 29}; 30#endif 31 32#define RATE (1./2.) 33#define MAXBYTES 10000 34 35double Gain = 32.0; 36int Verbose = 0; 37 38int main(int argc,char *argv[]){ 39 int i,d,tr; 40 int sr=0,trials = 10000,errcnt,framebits=2048; 41 long long int tot_errs=0; 42 unsigned char bits[MAXBYTES]; 43 unsigned char data[MAXBYTES]; 44 unsigned char xordata[MAXBYTES]; 45 unsigned char symbols[8*2*(MAXBYTES+6)]; 46 void *vp; 47 extern char *optarg; 48 struct rusage start,finish; 49 double extime; 50 double gain,esn0,ebn0; 51 time_t t; 52 int badframes=0; 53 54 time(&t); 55 srandom(t); 56 ebn0 = -100; 57#if HAVE_GETOPT_LONG 58 while((d = getopt_long(argc,argv,"l:n:te:g:vapmst",Options,NULL)) != EOF){ 59#else 60 while((d = getopt(argc,argv,"l:n:te:g:vapmst")) != EOF){ 61#endif 62 switch(d){ 63 case 'a': 64 Cpu_mode = ALTIVEC; 65 break; 66 case 'p': 67 Cpu_mode = PORT; 68 break; 69 case 'm': 70 Cpu_mode = MMX; 71 break; 72 case 's': 73 Cpu_mode = SSE; 74 break; 75 case 't': 76 Cpu_mode = SSE2; 77 break; 78 case 'l': 79 framebits = atoi(optarg); 80 break; 81 case 'n': 82 trials = atoi(optarg); 83 break; 84 case 'e': 85 ebn0 = atof(optarg); 86 break; 87 case 'g': 88 Gain = atof(optarg); 89 break; 90 case 'v': 91 Verbose++; 92 break; 93 } 94 } 95 if(framebits > 8*MAXBYTES){ 96 fprintf(stderr,"Frame limited to %d bits\n",MAXBYTES*8); 97 framebits = MAXBYTES*8; 98 } 99 if((vp = create_viterbi27(framebits)) == NULL){ 100 printf("create_viterbi27 failed\n"); 101 exit(1); 102 } 103 if(ebn0 != -100){ 104 esn0 = ebn0 + 10*log10((double)RATE); /* Es/No in dB */ 105 /* Compute noise voltage. The 0.5 factor accounts for BPSK seeing 106 * only half the noise power, and the sqrt() converts power to 107 * voltage. 108 */ 109 gain = 1./sqrt(0.5/pow(10.,esn0/10.)); 110 111 printf("nframes = %d framesize = %d ebn0 = %.2f dB gain = %g\n",trials,framebits,ebn0,Gain); 112 113 for(tr=0;tr<trials;tr++){ 114 /* Encode a frame of random data */ 115 for(i=0;i<framebits+6;i++){ 116 int bit = (i < framebits) ? (random() & 1) : 0; 117 118 sr = (sr << 1) | bit; 119 bits[i/8] = sr & 0xff; 120 symbols[2*i+0] = addnoise(parity(sr & V27POLYA),gain,Gain,127.5,255); 121 symbols[2*i+1] = addnoise(parity(sr & V27POLYB),gain,Gain,127.5,255); 122 } 123 /* Decode it and make sure we get the right answer */ 124 /* Initialize Viterbi decoder */ 125 init_viterbi27(vp,0); 126 127 /* Decode block */ 128 update_viterbi27_blk(vp,symbols,framebits+6); 129 130 /* Do Viterbi chainback */ 131 chainback_viterbi27(vp,data,framebits,0); 132 errcnt = 0; 133 for(i=0;i<framebits/8;i++){ 134 int e = Bitcnt[xordata[i] = data[i] ^ bits[i]]; 135 errcnt += e; 136 tot_errs += e; 137 } 138 if(errcnt != 0) 139 badframes++; 140 if(Verbose > 1 && errcnt != 0){ 141 printf("frame %d, %d errors: ",tr,errcnt); 142 for(i=0;i<framebits/8;i++){ 143 printf("%02x",xordata[i]); 144 } 145 printf("\n"); 146 } 147 if(Verbose) 148 printf("BER %lld/%lld (%10.3g) FER %d/%d (%10.3g)\r", 149 tot_errs,(long long)framebits*(tr+1),tot_errs/((double)framebits*(tr+1)), 150 badframes,tr+1,(double)badframes/(tr+1)); 151 fflush(stdout); 152 } 153 if(Verbose > 1) 154 printf("nframes = %d framesize = %d ebn0 = %.2f dB gain = %g\n",trials,framebits,ebn0,Gain); 155 else if(Verbose == 0) 156 printf("BER %lld/%lld (%.3g) FER %d/%d (%.3g)\n", 157 tot_errs,(long long)framebits*trials,tot_errs/((double)framebits*trials), 158 badframes,tr+1,(double)badframes/(tr+1)); 159 else 160 printf("\n"); 161 162 } else { 163 /* Do time trials */ 164 memset(symbols,127,sizeof(symbols)); 165 printf("Starting time trials\n"); 166 getrusage(RUSAGE_SELF,&start); 167 for(tr=0;tr < trials;tr++){ 168 /* Initialize Viterbi decoder */ 169 init_viterbi27(vp,0); 170 171 /* Decode block */ 172 update_viterbi27_blk(vp,symbols,framebits); 173 174 /* Do Viterbi chainback */ 175 chainback_viterbi27(vp,data,framebits,0); 176 } 177 getrusage(RUSAGE_SELF,&finish); 178 extime = finish.ru_utime.tv_sec - start.ru_utime.tv_sec + 1e-6*(finish.ru_utime.tv_usec - start.ru_utime.tv_usec); 179 printf("Execution time for %d %d-bit frames: %.2f sec\n",trials, 180 framebits,extime); 181 printf("decoder speed: %g bits/s\n",trials*framebits/extime); 182 } 183 exit(0); 184} 185