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./3.)
     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*3*(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_viterbi39(framebits)) == NULL){
    100     printf("create_viterbi39 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[3*i+0] = addnoise(parity(sr & V39POLYA),gain,Gain,127.5,255);
    121 	symbols[3*i+1] = addnoise(parity(sr & V39POLYB),gain,Gain,127.5,255);
    122 	symbols[3*i+2] = addnoise(parity(sr & V39POLYC),gain,Gain,127.5,255);
    123       }
    124       /* Decode it and make sure we get the right answer */
    125       /* Initialize Viterbi decoder */
    126       init_viterbi39(vp,0);
    127 
    128       /* Decode block */
    129       update_viterbi39_blk(vp,symbols,framebits+8);
    130 
    131       /* Do Viterbi chainback */
    132       chainback_viterbi39(vp,data,framebits,0);
    133       errcnt = 0;
    134       for(i=0;i<framebits/8;i++){
    135 	int e = Bitcnt[xordata[i] = data[i] ^ bits[i]];
    136 	errcnt += e;
    137 	tot_errs += e;
    138       }
    139       if(errcnt != 0)
    140 	badframes++;
    141       if(Verbose > 1 && errcnt != 0){
    142 	printf("frame %d, %d errors: ",tr,errcnt);
    143 	for(i=0;i<framebits/8;i++){
    144 	  printf("%02x",xordata[i]);
    145 	}
    146 	printf("\n");
    147       }
    148       if(Verbose)
    149 	printf("BER %lld/%lld (%10.3g) FER %d/%d (%10.3g)\r",
    150 	       tot_errs,(long long)framebits*(tr+1),tot_errs/((double)framebits*(tr+1)),
    151 	       badframes,tr+1,(double)badframes/(tr+1));
    152       fflush(stdout);
    153     }
    154     if(Verbose > 1)
    155       printf("nframes = %d framesize = %d ebn0 = %.2f dB gain = %g\n",trials,framebits,ebn0,Gain);
    156     else if(Verbose == 0)
    157       printf("BER %lld/%lld (%.3g) FER %d/%d (%.3g)\n",
    158 	     tot_errs,(long long)framebits*trials,tot_errs/((double)framebits*trials),
    159 	     badframes,tr+1,(double)badframes/(tr+1));
    160     else
    161       printf("\n");
    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_viterbi39(vp,0);
    170 
    171       /* Decode block */
    172       update_viterbi39_blk(vp,symbols,framebits);
    173 
    174       /* Do Viterbi chainback */
    175       chainback_viterbi39(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 
    186 
    187