You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
191 lines
5.0 KiB
191 lines
5.0 KiB
/* Test viterbi decoder speeds */ |
|
#include "config.h" |
|
#include <stdio.h> |
|
#include <stdlib.h> |
|
#include <unistd.h> |
|
#include <time.h> |
|
#include <math.h> |
|
#include <memory.h> |
|
#include <sys/time.h> |
|
#include <sys/resource.h> |
|
#ifdef HAVE_GETOPT_H |
|
#include <getopt.h> |
|
#endif |
|
#include "fec.h" |
|
|
|
#if HAVE_GETOPT_LONG |
|
struct option Options[] = { |
|
{"frame-length",1,NULL,'l'}, |
|
{"frame-count",1,NULL,'n'}, |
|
{"ebn0",1,NULL,'e'}, |
|
{"gain",1,NULL,'g'}, |
|
{"verbose",0,NULL,'v'}, |
|
{"force-altivec",0,NULL,'a'}, |
|
{"force-port",0,NULL,'p'}, |
|
{"force-mmx",0,NULL,'m'}, |
|
{"force-sse",0,NULL,'s'}, |
|
{"force-sse2",0,NULL,'t'}, |
|
{NULL}, |
|
}; |
|
#endif |
|
|
|
#define RATE (1./6.) |
|
#define MAXBYTES 10000 |
|
#define OFFSET (127.5) |
|
#define CLIP 255 |
|
|
|
double Gain = 24.0; |
|
int Verbose = 0; |
|
|
|
int main(int argc,char *argv[]){ |
|
int i,d,tr; |
|
int sr=0,trials = 10,errcnt,framebits=2048; |
|
int tot_errs=0; |
|
unsigned char bits[MAXBYTES]; |
|
unsigned char data[MAXBYTES]; |
|
unsigned char xordata[MAXBYTES]; |
|
unsigned char symbols[8*6*(MAXBYTES+14)]; |
|
void *vp; |
|
extern char *optarg; |
|
struct rusage start,finish; |
|
double extime; |
|
double gain,esn0,ebn0; |
|
time_t t; |
|
int badframes=0; |
|
|
|
time(&t); |
|
srandom(t); |
|
ebn0 = -100; |
|
#if HAVE_GETOPT_LONG |
|
while((d = getopt_long(argc,argv,"l:n:te:g:vapmst",Options,NULL)) != EOF){ |
|
#else |
|
while((d = getopt(argc,argv,"l:n:te:g:vapmst")) != EOF){ |
|
#endif |
|
switch(d){ |
|
case 'a': |
|
Cpu_mode = ALTIVEC; |
|
break; |
|
case 'p': |
|
Cpu_mode = PORT; |
|
break; |
|
case 'm': |
|
Cpu_mode = MMX; |
|
break; |
|
case 's': |
|
Cpu_mode = SSE; |
|
break; |
|
case 't': |
|
Cpu_mode = SSE2; |
|
break; |
|
case 'l': |
|
framebits = atoi(optarg); |
|
break; |
|
case 'n': |
|
trials = atoi(optarg); |
|
break; |
|
case 'e': |
|
ebn0 = atof(optarg); |
|
break; |
|
case 'g': |
|
Gain = atof(optarg); |
|
break; |
|
case 'v': |
|
Verbose++; |
|
break; |
|
} |
|
} |
|
if(framebits > 8*MAXBYTES){ |
|
fprintf(stderr,"Frame limited to %d bits\n",MAXBYTES*8); |
|
framebits = MAXBYTES*8; |
|
} |
|
if((vp = create_viterbi615(framebits)) == NULL){ |
|
printf("create_viterbi615 failed\n"); |
|
exit(1); |
|
} |
|
if(ebn0 != -100){ |
|
esn0 = ebn0 + 10*log10((double)RATE); /* Es/No in dB */ |
|
/* Compute noise voltage. The 0.5 factor accounts for BPSK seeing |
|
* only half the noise power, and the sqrt() converts power to |
|
* voltage. |
|
*/ |
|
gain = 1./sqrt(0.5/pow(10.,esn0/10.)); |
|
|
|
printf("nframes = %d framesize = %d ebn0 = %.2f dB gain = %g\n",trials,framebits,ebn0,Gain); |
|
|
|
for(tr=0;tr<trials;tr++){ |
|
/* Encode a frame of random data */ |
|
for(i=0;i<framebits+14;i++){ |
|
int bit = (i < framebits) ? (random() & 1) : 0; |
|
|
|
sr = (sr << 1) | bit; |
|
bits[i/8] = sr & 0xff; |
|
symbols[6*i+0] = addnoise(parity(sr & V615POLYA),gain,Gain,OFFSET,CLIP); |
|
symbols[6*i+1] = addnoise(parity(sr & V615POLYB),gain,Gain,OFFSET,CLIP); |
|
symbols[6*i+2] = addnoise(parity(sr & V615POLYC),gain,Gain,OFFSET,CLIP); |
|
symbols[6*i+3] = addnoise(parity(sr & V615POLYD),gain,Gain,OFFSET,CLIP); |
|
symbols[6*i+4] = addnoise(parity(sr & V615POLYE),gain,Gain,OFFSET,CLIP); |
|
symbols[6*i+5] = addnoise(parity(sr & V615POLYF),gain,Gain,OFFSET,CLIP); |
|
} |
|
/* Decode it and make sure we get the right answer */ |
|
/* Initialize Viterbi decoder */ |
|
init_viterbi615(vp,0); |
|
|
|
/* Decode block */ |
|
update_viterbi615_blk(vp,symbols,framebits+14); |
|
|
|
/* Do Viterbi chainback */ |
|
chainback_viterbi615(vp,data,framebits,0); |
|
errcnt = 0; |
|
for(i=0;i<framebits/8;i++){ |
|
int e = Bitcnt[xordata[i] = data[i] ^ bits[i]]; |
|
errcnt += e; |
|
tot_errs += e; |
|
} |
|
if(errcnt != 0) |
|
badframes++; |
|
if(Verbose > 1 && errcnt != 0){ |
|
printf("frame %d, %d errors: ",tr,errcnt); |
|
for(i=0;i<framebits/8;i++){ |
|
printf("%02x",xordata[i]); |
|
} |
|
printf("\n"); |
|
} |
|
if(Verbose) |
|
printf("BER %d/%d (%10.3g) FER %d/%d (%10.3g)\r", |
|
tot_errs,framebits*(tr+1),tot_errs/((double)framebits*(tr+1)), |
|
badframes,(tr+1),(double)badframes/(tr+1)); |
|
fflush(stdout); |
|
|
|
} |
|
|
|
if(Verbose > 1) |
|
printf("nframes = %d framesize = %d ebn0 = %.2f dB gain = %g\n",trials,framebits,ebn0,Gain); |
|
else if(Verbose == 0) |
|
printf("BER %d/%d (%.3g) FER %d/%d (%.3g)\n", |
|
tot_errs,framebits*(tr+1),tot_errs/((double)framebits*(tr+1)), |
|
badframes,(tr+1),(double)badframes/(tr+1)); |
|
else |
|
printf("\n"); |
|
} else { |
|
/* Do time trials */ |
|
memset(symbols,127,sizeof(symbols)); |
|
printf("Starting time trials\n"); |
|
getrusage(RUSAGE_SELF,&start); |
|
for(tr=0;tr < trials;tr++){ |
|
/* Initialize Viterbi decoder */ |
|
init_viterbi615(vp,0); |
|
|
|
/* Decode block */ |
|
update_viterbi615_blk(vp,symbols,framebits+14); |
|
|
|
/* Do Viterbi chainback */ |
|
chainback_viterbi615(vp,data,framebits,0); |
|
} |
|
getrusage(RUSAGE_SELF,&finish); |
|
extime = finish.ru_utime.tv_sec - start.ru_utime.tv_sec + 1e-6*(finish.ru_utime.tv_usec - start.ru_utime.tv_usec); |
|
printf("Execution time for %d %d-bit frames: %.2f sec\n",trials, |
|
framebits,extime); |
|
printf("decoder speed: %g bits/s\n",trials*framebits/extime); |
|
} |
|
exit(0); |
|
}
|
|
|