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