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
main(int argc,char * argv[])38 int 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