Home | History | Annotate | Download | only in fec
      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
     17 struct 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 
     35 double Gain = 32.0;
     36 int Verbose = 0;
     37 
     38 int main(int argc,char *argv[]){
     39   int i,d,tr;
     40   int sr=0,trials = 10000,errcnt,framebits=2048;
     41   long long 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+8)];
     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_viterbi29(framebits)) == NULL){
    100     printf("create_viterbi29 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+8;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 & V29POLYA),gain,Gain,127.5,255);
    121 	symbols[2*i+1] = addnoise(parity(sr & V29POLYB),gain,Gain,127.5,255);
    122       }
    123       /* Decode it and make sure we get the right answer */
    124       /* Initialize Viterbi decoder */
    125       init_viterbi29(vp,0);
    126 
    127       /* Decode block */
    128       update_viterbi29_blk(vp,symbols,framebits+8);
    129 
    130       /* Do Viterbi chainback */
    131       chainback_viterbi29(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   } else {
    162     /* Do time trials */
    163     memset(symbols,127,sizeof(symbols));
    164     printf("Starting time trials\n");
    165     getrusage(RUSAGE_SELF,&start);
    166     for(tr=0;tr < trials;tr++){
    167       /* Initialize Viterbi decoder */
    168       init_viterbi29(vp,0);
    169 
    170       /* Decode block */
    171       update_viterbi29_blk(vp,symbols,framebits);
    172 
    173       /* Do Viterbi chainback */
    174       chainback_viterbi29(vp,data,framebits,0);
    175     }
    176     getrusage(RUSAGE_SELF,&finish);
    177     extime = finish.ru_utime.tv_sec - start.ru_utime.tv_sec + 1e-6*(finish.ru_utime.tv_usec - start.ru_utime.tv_usec);
    178     printf("Execution time for %d %d-bit frames: %.2f sec\n",trials,
    179 	   framebits,extime);
    180     printf("decoder speed: %g bits/s\n",trials*framebits/extime);
    181   }
    182   exit(0);
    183 }
    184 
    185 
    186