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./6.)
     33 #define MAXBYTES 10000
     34 #define OFFSET (127.5)
     35 #define CLIP 255
     36 
     37 double Gain = 24.0;
     38 int Verbose = 0;
     39 
     40 int 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