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