========================================================================
// FFILE NAME : turbo_parallel_fix_log.c
// VERSION : 1.0
// DESCRIPTION : This file is turbo decode BCJR algorithm
// fix slide window log map
// REVERSION :
// -------------------------------------------------------------------
// No. Date Author Description
// -------------------------------------------------------------------
// 1. 2010/9/20 Lu An An initial
// 2. 2011/4/5 ZhuGuanYa parallel//no map1 or map2
// =========================================================================
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <math.h>
#include <semaphore.h>
#define window_size 32 // slide window length
#define inf 127.875
#define llr_es_limit 31.875
#define gamma_limit 31.75
#define gate_counter (Len+4*window_size-1) // the first iteration, SISO1 work , SISO2 wait
#define iteriter 12
//inner interleaver ; interleave msg with interleave_table
void inner_interleave(double *msg, int Len, int *interleave_table)
{
double *tmp;
int i;
tmp = (double*) malloc(Len*sizeof(double));
for(i=0; i<Len; i++)
{
tmp[i] = msg[interleave_table[i]];
}
for(i=0; i<Len; i++)
{
msg[i] = tmp[i];
}
free(tmp);
}
//inner deinterleaver ; deinterleave msg with interleave_table
void inner_deinterleave(double* msg, int Len, int *interleave_table)
{
double *tmp;
int i;
tmp = (double*) malloc(Len*sizeof(double));
for(i=0; i<Len; i++)
{
tmp[interleave_table[i]] = msg[i];
}
for(i=0; i<Len; i++)
{
msg[i] = tmp[i];
}
free(tmp);
}
void get_deinterleave_table(int* deinterleave_table,int Len, int* interleave_table)
{
int*tmp;
int i;
tmp = (int*) malloc(Len*sizeof(int));
for(i=0; i<Len; i++)
{
tmp[interleave_table[i]]=i;
}
for(i=0; i<Len; i++)
{
deinterleave_table[i] = tmp[i];
}
free(tmp);
}
//rate matching; rate match with table inter_index
void rate_matching(int D, int E, double *input, double *output, int *inter_index)
{
int i;
for(i=0; i<E; i++)
{
output[i] = input[inter_index[i]];
}
}
//rate dematching; rate dematch with table inter_index
void rate_dematching(int D, int E, double *input, double *output, int *inter_index)
{
int i;
int j;
for(i=0; i<3*D; i++)
{
output[i] = 0;
}
for(i=0; i<E; i++)
{
output[inter_index[i]] += input[i];
}
}
//max algorithm for Log-MAP algorithm of RSC decoder
//int maxo(int t0, int t1)
double maxo(double t0, double t1)
{
double tmp; //tmp=log(1+exp(-fabs(t0-t1)));
if (fabs(t0-t1)<0.25)
tmp = 0.75;
else if(fabs(t0-t1)<0.75)
tmp = 0.5;
else if(fabs(t0-t1)<2.25)
tmp = 0.25;
else
tmp=0;
if (t0 >= t1)
{
return t0+tmp;//+8*log(1+exp(-abs((t0-t1)/8)));//tmp=4*log(1+exp(-abs((t0-t1)/4)));
}
else
{
return t1+tmp;//+8*log(1+exp(-abs((t0-t1)/8)));//tmp=4*log(1+exp(-abs((t0-t1)/4)));
}
}
//gamma buffer: first in first out
void gamma_buffer(double *gs, double *gp, double gs_tmp, double gp_tmp)
{
int loop;
for (loop=window_size*4; loop>0; loop--)
{
gs[loop]=gs[loop-1];
gp[loop]=gp[loop-1];
}
gs[0]=gs_tmp;
gp[0]=gp_tmp;
}
//Alpha recursive algorithm
void calc_Alpha(double gs, double gp,double *Alpha,double *Alpha_tmp)
{
int state;
int previous_state_1,previous_state_2;
//state 0 and 1 to state 0
state=0;
previous_state_1=0;
previous_state_2=1;
Alpha_tmp[state]=maxo(Alpha[previous_state_1]+gs+gp,Alpha[previous_state_2]);
//Alpha_tmp[state]=maxo(Alpha[previous_state_1]-gs-gp,Alpha[previous_state_2]+gs+gp);
//state 2 and 3 to state 1
state=1;
previous_state_1=2;
previous_state_2=3;
Alpha_tmp[state]=maxo(Alpha[previous_state_1]+gp,Alpha[previous_state_2]+gs);
//Alpha_tmp[state]=maxo(Alpha[previous_state_1]+gs-gp,Alpha[previous_state_2]-gs+gp);
//state 4 and 5 to state 2
state=2;
previous_state_1=4;
previous_state_2=5;
Alpha_tmp[state]=maxo(Alpha[previous_state_1]+gs,Alpha[previous_state_2]+gp);
//Alpha_tmp[state]=maxo(Alpha[previous_state_1]-gs+gp,Alpha[previous_state_2]+gs-gp);
//state 6 and 7 to state 3
state=3;
previous_state_1=6;
previous_state_2=7;
Alpha_tmp[state]=maxo(Alpha[previous_state_1],Alpha[previous_state_2]+gs+gp);
//state 0 and 1 to state 4 //Alpha_tmp[state]=maxo(Alpha[previous_state_1]+gs+gp,Alpha[previous_state_2]-gs-gp);
state=4;
previous_state_1=0;
previous_state_2=1;
Alpha_tmp[state]=maxo(Alpha[previous_state_1],Alpha[previous_state_2]+gs+gp);
//Alpha_tmp[state]=maxo(Alpha[previous_state_1]+gs+gp,Alpha[previous_state_2]-gs-gp);
//state 2 and 3 to state 5
state=5;
previous_state_1=2;
previous_state_2=3;
Alpha_tmp[state]=maxo(Alpha[previous_state_1]+gs,Alpha[previous_state_2]+gp);
//Alpha_tmp[state]=maxo(Alpha[previous_state_1]-gs+gp,Alpha[previous_state_2]+gs-gp);
//state 4 and 5 to state 6
state=6;
previous_state_1=4;
previous_state_2=5;
Alpha_tmp[state]=maxo(Alpha[previous_state_1]+gp,Alpha[previous_state_2]+gs);
//Alpha_tmp[state]=maxo(Alpha[previous_state_1]+gs-gp,Alpha[previous_state_2]-gs+gp);
//state 0 and 1 to state 7
state=7;
previous_state_1=6;
previous_state_2=7;
Alpha_tmp[state]=maxo(Alpha[previous_state_1]+gs+gp,Alpha[previous_state_2]);
//Alpha_tmp[state]=maxo(Alpha[previous_state_1]-gs-gp,Alpha[previous_state_2]+gs+gp);
//Alpha overflow processing
//Alpha overflow processing
}
//Beta recursive algorithm
void calc_Beta(double gs, double gp, double* Beta, double *Beta_tmp)
{
int state;
int next_state_1,next_state_2;
//state 0 to state 0 or 4
state=0;
next_state_1=0;
next_state_2=4;
//Beta_tmp[state]=maxo(Beta[next_state_1]-gs-gp,Beta[next_state_2]+gs+gp);
Beta_tmp[state]=maxo(Beta[next_state_1]+gs+gp,Beta[next_state_2]);
//state 1 to state 0 or 4
state=1;
next_state_1=0;
next_state_2=4;
//Beta_tmp[state]=maxo(Beta[next_state_1]+gs+gp,Beta[next_state_2]-gs-gp);
Beta_tmp[state]=maxo(Beta[next_state_1],Beta[next_state_2]+gs+gp);
//state 2 to state 1 or 5
state=2;
next_state_1=1;
next_state_2=5;
//Beta_tmp[state]=maxo(Beta[next_state_1]+gs-gp,Beta[next_state_2]-gs+gp);
Beta_tmp[state]=maxo(Beta[next_state_1]+gp,Beta[next_state_2]+gs);
//state 3 to state 1 or 5
state=3;
next_state_1=1;
next_state_2=5;
//Beta_tmp[state]=maxo(Beta[next_state_1]-gs+gp,Beta[next_state_2]+gs-gp);
Beta_tmp[state]=maxo(Beta[next_state_1]+gs,Beta[next_state_2]+gp);
//state 4 to state 2 or 6
state=4;
next_state_1=2;
next_state_2=6;
//Beta_tmp[state]=maxo(Beta[next_state_1]-gs+gp,Beta[next_state_2]+gs-gp);
Beta_tmp[state]=maxo(Beta[next_state_1]+gs,Beta[next_state_2]+gp);
//state 5 to state 2 or 6
state=5;
next_state_1=2;
next_state_2=6;
//Beta_tmp[state]=maxo(Beta[next_state_1]+gs-gp,Beta[next_state_2]-gs+gp);
Beta_tmp[state]=maxo(Beta[next_state_1]+gp,Beta[next_state_2]+gs);
//state 6 to state 3 or 7
state=6;
next_state_1=3;
next_state_2=7;
//Beta_tmp[state]=maxo(Beta[next_state_1]+gs+gp,Beta[next_state_2]-gs-gp);
Beta_tmp[state]=maxo(Beta[next_state_1],Beta[next_state_2]+gs+gp);
//state 7 to state 3 or 7
state=7;
next_state_1=3;
next_state_2=7;
//Beta_tmp[state]=maxo(Beta[next_state_1]-gs-gp,Beta[next_state_2]+gs+gp);
Beta_tmp[state]=maxo(Beta[next_state_1]+gs+gp,Beta[next_state_2]);
}
//read Beta from Beta buffer for llr calculation
void read_Beta(int Beta_address_order_flag, int llr_calc_counter, double* Beta_buffer, double* Beta_buffer_tmp)
{
int i;
for(i=0; i<8; i++)
{
if(Beta_address_order_flag==0) // Beta previous buffer address order: window_size ... 5 4 3 2 1 0
{
Beta_buffer_tmp[i]=Beta_buffer[(window_size-1)*8-(llr_calc_counter%window_size)*8+i];
}
else // Beta previous buffer address order 0 1 2 3 ... window_size
{
Beta_buffer_tmp[i]=Beta_buffer[(llr_calc_counter%window_size)*8+i];
}
}
}
//Beta update and save
void Beta_update_and_save(int Beta_initial_end, int Beta_address_order_flag, int Beta_initial_flag, int llr_calc_counter, double gs, double gp, double* Beta, double* Beta_acq, double* Beta_buffer)
{
int i;
double *Beta_tmp;
Beta_tmp = (double*) malloc(8*sizeof(double));
if (Beta_initial_flag==1)
{
for (i=0; i<8; i++)
{
Beta[i]=Beta_acq[i];
}
for (i=0; i<8; i++)
{
if(Beta_address_order_flag==0) // Beta buffer address order 0 1 2 3 ... window_size
{
Beta_buffer[(window_size-1)*8+i]=Beta[i];
}
else // Beta buffer address order window_size ... 5 4 3 2 1 0
{
Beta_buffer[i]=Beta[i];
}
}
}
else
{
calc_Beta(gs,gp,Beta,Beta_tmp);
for (i=0; i<8; i++)
{
if(Beta_address_order_flag==0) // Beta buffer address order 0 1 2 3 ... window_size
{
Beta_buffer[(window_size-1)*8-(llr_calc_counter%window_size)*8+i]=Beta_tmp[i];
}
else // Beta buffer address order window_size ... 5 4 3 2 1 0
{
Beta_buffer[(llr_calc_counter%window_size)*8+i]=Beta_tmp[i];
}
Beta[i]=Beta_tmp[i];
}
}
free(Beta_tmp);
}
//Beta_acq update for slide window MAP algorithm
void Beta_acq_update(int Beta_acq_initial_end, int Beta_acq_initial_flag, double gs, double gp, double* Beta_acq, int map_type)
{
double *Beta_acq_tmp;
int i;
Beta_acq_tmp = (double*) malloc(8*sizeof(double));
if (Beta_acq_initial_end == 1) //in the end of the code word, initial Beta_acq with the following
{
for (i=0; i<8; i++)
{
Beta_acq[i]=0; //turbo code with tail bit, state 0 is the only possible state
}
if (1)
{
Beta_acq[0]=192/8;
}
}
else //not to the end of the code word, initial Beta_acq with the following
{
if (Beta_acq_initial_flag==1) //initial Beta_acq
{
for (i=0; i<8; i++)
{
Beta_acq[i]=0; //eight state has the same probability
}
}
else
{
calc_Beta(gs,gp,Beta_acq,Beta_acq_tmp); //Beta_acq recursive
for (i=0; i<8; i++)
{
Beta_acq[i]=Beta_acq_tmp[i];
}
}
}
free(Beta_acq_tmp);
}
//calculate systematic bit extrinstic information(log likelihood ratio) with gp Alpha Beta -- type = 0;
//calculate partiy bit extrinstic information(log likelihood ratio) with gs Alpha Beta -- type = 1;
double calc_ext_llr(double gs, double gp, double *Alpha,double *Beta, int type)
{
double nom,denom;
double nom1,nom2,nom3,nom4,denom1,denom2,denom3,denom4;
if (type==0)
{
//nom1=maxo(Alpha[0]+gp+Beta[4],Alpha[1]+gp+Beta[0]);
nom1=maxo(Alpha[0]+Beta[4],Alpha[1]+Beta[0]);
//nom2=maxo(Alpha[2]-gp+Beta[1],Alpha[3]-gp+Beta[5]);
nom2=maxo(Alpha[2]+gp+Beta[1],Alpha[3]+gp+Beta[5]);
//nom3=maxo(Alpha[4]-gp+Beta[6],Alpha[5]-gp+Beta[2]);
nom3=maxo(Alpha[4]+gp+Beta[6],Alpha[5]+gp+Beta[2]);
//nom4=maxo(Alpha[6]+gp+Beta[3],Alpha[7]+gp+Beta[7]);
nom4=maxo(Alpha[6]+Beta[3],Alpha[7]+Beta[7]);
nom=maxo(maxo(nom1,nom2),maxo(nom3,nom4));
//denom1=maxo(Alpha[0]-gp+Beta[0],Alpha[1]-gp+Beta[4]);
denom1=maxo(Alpha[0]+gp+Beta[0],Alpha[1]+gp+Beta[4]);
//denom2=maxo(Alpha[2]+gp+Beta[5],Alpha[3]+gp+Beta[1]);
denom2=maxo(Alpha[2]+Beta[5],Alpha[3]+Beta[1]);
//denom3=maxo(Alpha[4]+gp+Beta[2],Alpha[5]+gp+Beta[6]);
denom3=maxo(Alpha[4]+Beta[2],Alpha[5]+Beta[6]);
//denom4=maxo(Alpha[6]-gp+Beta[7],Alpha[7]-gp+Beta[3]);
denom4=maxo(Alpha[6]+gp+Beta[7],Alpha[7]+gp+Beta[3]);
denom=maxo(maxo(denom1,denom2),maxo(denom3,denom4));
return denom-nom;
}
else
{
//nom1=maxo(Alpha[0]+gs+Beta[4],Alpha[1]+gs+Beta[0]);
nom1=maxo(Alpha[0]+Beta[4],Alpha[1]+Beta[0]);
//nom2=maxo(Alpha[2]-gs+Beta[5],Alpha[3]-gs+Beta[1]);
nom2=maxo(Alpha[2]+gs+Beta[5],Alpha[3]+gs+Beta[1]);
//nom3=maxo(Alpha[4]-gs+Beta[2],Alpha[5]-gs+Beta[6]);
nom3=maxo(Alpha[4]+gs+Beta[2],Alpha[5]+gs+Beta[6]);
//nom4=maxo(Alpha[6]+gs+Beta[3],Alpha[7]+gs+Beta[7]);
nom4=maxo(Alpha[6]+Beta[3],Alpha[7]+Beta[7]);
nom=maxo(maxo(nom1,nom2),maxo(nom3,nom4));
//denom1=maxo(Alpha[0]-gs+Beta[0],Alpha[1]-gs+Beta[4]);
denom1=maxo(Alpha[0]+gs+Beta[0],Alpha[1]+gs+Beta[4]);
//denom2=maxo(Alpha[2]+gs+Beta[3],Alpha[3]+gs+Beta[5]);
denom2=maxo(Alpha[2]+Beta[1],Alpha[3]+Beta[5]);
//denom3=maxo(Alpha[4]+gs+Beta[6],Alpha[5]+gs+Beta[2]);
denom3=maxo(Alpha[4]+Beta[6],Alpha[5]+Beta[2]);
//denom4=maxo(Alpha[6]-gs+Beta[7],Alpha[7]-gs+Beta[3]);
denom4=maxo(Alpha[6]+gs+Beta[7],Alpha[7]+gs+Beta[3]);
denom=maxo(maxo(denom1,denom2),maxo(denom3,denom4));
return denom-nom;
}
}
//RSC decoder for turbo decoder
void * turbo_rsc_decoder1(void* args)
//int* Len_p,int* Mem_p,int* llr_es1,int* llr_es2,int* interleave_table,int* deinterleave_table
//int* llr_s1,int* llr_s2,int* llr_p1,int* llr_p2,int* llr_ep1,int* llr_ep2,int* store_llr1,int* store_llr2
//sem1, sem2, itermax, sem3
{
int* Len_p = ((void**)args)[0];
int* Mem_p = ((void**)args)[1];
double* llr_es1 = ((void**)args)[2];
double* llr_es2 = ((void**)args)[3];
int* interleave_table = ((void**)args)[4];
int* deinterleave_table = ((void**)args)[5];
double* llr_s1 = ((void**)args)[6];
double* llr_s2 = ((void**)args)[7];
double* llr_p1 = ((void**)args)[8];
double* llr_p2 = ((void**)args)[9];
double* llr_ep1 = ((void**)args)[10];
double* llr_ep2 = ((void**)args)[11];
double* store_llr1 = ((void**)args)[12];
double* store_llr2 = ((void**)args)[13];
sem_t* sem1_p = ((void**)args)[14];
sem_t* sem2_p = ((void**)args)[15];
int* itermax_p = ((void**)args)[16];
sem_t* sem3_p = ((void**)args)[17];
sem_t* sem4_p = ((void**)args)[18];
double *gs;
double *gp;
double gamma_s;
double gamma_p;
double *Beta,*Beta_acq,*Beta_buffer,*Beta_buffer_tmp;
double *Alpha;
double *Alpha_tmp;
int Beta_initial_flag;
int Beta_acq_initial_flag;
int Beta_address_order_flag;
int i;
int Beta_acq_initial_end;
int Beta_initial_end;
int addr_tmp;
int map_type;
int Len;
int Mem;
int itermax;
int n_iter;
int llr_calc_counter;
int window_number;
int window_counter;
int zero_padding_number;
int tmp;
int index1;
int index2;
gs = (double*) malloc((window_size*4+1)*sizeof(double));
gp = (double*) malloc((window_size*4+1)*sizeof(double));
Alpha = (double*) malloc(8*sizeof(double));
Alpha_tmp = (double*) malloc(8*sizeof(double));
Beta = (double*) malloc(8*sizeof(double));
Beta_acq = (double*) malloc(8*sizeof(double));
Beta_buffer = (double*) malloc(window_size*8*sizeof(double));
Beta_buffer_tmp = (double*) malloc(8*sizeof(double));
//deinterleave_table = (int*) malloc(Len*sizeof(int));
//llr_calc_counter=0;
//llr_calc_state=0;
Beta_acq_initial_end=0;
Beta_initial_end=0;
window_counter=0;
map_type=1;
Len=*Len_p;
Mem=*Mem_p;
itermax=*itermax_p;
//llr_calc_counter = 0;
Len=Len+3; //+3 tail bit;
//printf("428 interleave %d\n",interleave_table[428]);
if((Len%window_size)==0)
{
window_number=Len/window_size;
zero_padding_number=0;
}
else
{
window_number=Len/window_size+1;
zero_padding_number=window_number*window_size-Len;
}
// }
Len=window_size*window_number;
//slide window Log-MAP algorithm
for(n_iter=0;n_iter<itermax;n_iter++)
{
window_counter = 0;
Beta_acq_initial_end=0;
Beta_initial_end=0;
for(i=0;i<window_size*4+1;i++)
{
gs[i]=0;
gp[i]=0;
}
for(i=0;i<8;i++)
{
Alpha[i] = 0;
Alpha_tmp[i] = 0;
Beta[i] = 0;
Beta_acq[i] = 0;
Beta_buffer_tmp[i] = 0;
}
for(i=0;i<window_size*8;i++)
{
Beta_buffer[i]=0;
}
for(llr_calc_counter = 0;llr_calc_counter<Len+4*window_size;llr_calc_counter++)
{
//window_counter = 0;
//printf("post\n");
//if(llr_calc_counter == 0 &&n_iter==1)
/*{
sem_post(&(*sem3_p));
sem_post(&(*sem3_p));
}*/
if((llr_calc_counter%window_size)==0 && llr_calc_counter!=0)
{
window_counter++;
}
if (llr_calc_counter%(2*window_size)<window_size)
{
Beta_address_order_flag=0; //beta address order 0 1 ... 31
}
else
{
Beta_address_order_flag=1; //beta address order 31 30 ... 0
}
//gamma buffer
addr_tmp=llr_calc_counter;
//information bits
if(addr_tmp<Len-3-zero_padding_number)
{
//printf("%d\n",deinterleave_table[addr_tmp]);
tmp=deinterleave_table[addr_tmp];
gamma_s = -llr_s1[addr_tmp]+llr_es2[tmp]+store_llr1[addr_tmp];
gamma_p = -llr_p1[addr_tmp];
//printf("read OK!\n");
}
//tail bit
else if(llr_calc_counter<Len-zero_padding_number)
{
gamma_s = -llr_s1[addr_tmp]+store_llr1[addr_tmp];
gamma_p = -llr_p1[addr_tmp];
//handle overflow problem
}
if(llr_calc_counter<Len-zero_padding_number)
{
gamma_buffer(gs,gp,(gamma_s),gamma_p);
}
else
{
if(llr_calc_counter<Len)
{
gamma_buffer(gs,gp,64,64);
}
else
{
gamma_buffer(gs,gp,0,0);
}
}
//initial Alpha
if(llr_calc_counter==0)
{
for (i=0; i<8; i++)
{
Alpha[i]= 0;
}
if (1)
{
Alpha[0]=192/4;
}
}
//start alpha calculation and llr calculation
//printf("3");
if(window_counter>3)
{
if(window_counter<window_number+4)
{
read_Beta(Beta_address_order_flag, llr_calc_counter, Beta_buffer, Beta_buffer_tmp);
//llr calculation
addr_tmp=4*window_size;
if(llr_calc_counter>=4*window_size && llr_calc_counter<Len-zero_padding_number+4*window_size)
{
llr_es1[llr_calc_counter-4*window_size] = calc_ext_llr(gs[addr_tmp],gp[addr_tmp],Alpha,Beta_buffer_tmp,0);//>>1;
llr_ep1[llr_calc_counter-4*window_size] = calc_ext_llr(gs[addr_tmp],gp[addr_tmp],Alpha,Beta_buffer_tmp,1);
//Alpha calculation
calc_Alpha(gs[addr_tmp],gp[addr_tmp],Alpha,Alpha_tmp);
for(i=0; i<8; i++)
{
Alpha[i]=Alpha_tmp[i]; //error Alpha[i]=Alpha_tmp[i]-64;
}
}
}
}
//start beta calculation
//printf("2");
if(window_counter>2)
{
if(window_counter<window_number+3)
{
if(llr_calc_counter%window_size ==0 )
{
if(window_counter==window_number+2)
{
Beta_initial_end=1;
}
Beta_initial_flag=1;
}
else
{
Beta_initial_flag=0;
}
//Beta update
addr_tmp=2*window_size+(llr_calc_counter%window_size)*2;
Beta_update_and_save(Beta_initial_end,Beta_address_order_flag,Beta_initial_flag, llr_calc_counter, gs[addr_tmp], gp[addr_tmp], Beta, Beta_acq, Beta_buffer);
}
}
//start beta acq calculation
//printf("1");
if(window_counter>1)
{
if(window_counter<(window_number+2));
{
//Beta flag
if ((llr_calc_counter%window_size) ==0 )
{
if(window_counter==window_number+1)
{
Beta_acq_initial_end=1;
}
Beta_acq_initial_flag=1;
}
else
{
Beta_acq_initial_flag=0;
}
addr_tmp=1+(llr_calc_counter%window_size)*2;
Beta_acq_update(Beta_acq_initial_end,Beta_acq_initial_flag, gs[addr_tmp], gp[addr_tmp], Beta_acq,map_type);
}
}
//printf("0\n");
/*
if(n_iter==0&&llr_calc_counter ==0)
{
sem_post(&(*sem3_p));
}
sem_getvalue(&(*sem3_p),&index1);
//sem_getvalue(&(*sem4_p),&index2);*/
if(llr_calc_counter> gate_counter|| n_iter>0)
{
//
sem_post(&(*sem1_p));
//printf("0\n");
sem_wait(&(*sem2_p));
//printf("eeeee\n");
}
}
}
//sem_wait(&(*sem3_p));
//sem_wait(&(*sem4_p));
Len=Len-3-zero_padding_number;
free(Alpha_tmp);
free(gs);
free(gp);
free(Alpha);
free(Beta);
free(Beta_buffer);
free(Beta_buffer_tmp);
free(Beta_acq);
return 0;
}
void * turbo_rsc_decoder2(void* args)
//int* Len_p,int* Mem_p,int* llr_es1,int* llr_es2,int* interleave_table,int* deinterleave_table
//int* llr_s1,int* llr_s2,int* llr_p1,int* llr_p2,int* llr_ep1,int* llr_ep2,int* store_llr1,int* store_llr2
//sem1, sem2, llr_calc_counter, n_iter, itermax. sem3
{
int* Len_p = ((void**)args)[0];
int* Mem_p = ((void**)args)[1];
double* llr_es1 = ((void**)args)[2];
double* llr_es2 = ((void**)args)[3];
int* interleave_table = ((void**)args)[4];
int* deinterleave_table = ((void**)args)[5];
double* llr_s1 = ((void**)args)[6];
double* llr_s2 = ((void**)args)[7];
double* llr_p1 = ((void**)args)[8];
double* llr_p2 = ((void**)args)[9];
double* llr_ep1 = ((void**)args)[10];
double* llr_ep2 = ((void**)args)[11];
double* store_llr1 = ((void**)args)[12];
double* store_llr2 = ((void**)args)[13];
sem_t* sem1_p = ((void**)args)[14];
sem_t* sem2_p = ((void**)args)[15];
int* itermax_p = ((void**)args)[16];
sem_t* sem3_p = ((void**)args)[17];
sem_t* sem4_p = ((void**)args)[18];
//FILE* fd;
double *gs;
double *gp;
double gamma_p;
double gamma_s;
double *Beta,*Beta_acq,*Beta_buffer,*Beta_buffer_tmp;
double *Alpha;
double *Alpha_tmp;
int Beta_initial_flag;
int Beta_acq_initial_flag;
int Beta_address_order_flag;
int i;
int Beta_acq_initial_end;
int Beta_initial_end;
int addr_tmp;
int map_type;
int Len;
int Mem;
int itermax;
int llr_calc_counter;
int n_iter;
int window_number;
int window_counter;
int zero_padding_number;
int tmp;
int index1;
int index2;
//FILE *fd;
gs = (double*) malloc((window_size*4+1)*sizeof(double));
gp = (double*) malloc((window_size*4+1)*sizeof(double));
Alpha = (double*) malloc(8*sizeof(double));
Alpha_tmp = (double*) malloc(8*sizeof(double));
Beta = (double*) malloc(8*sizeof(double));
Beta_acq = (double*) malloc(8*sizeof(double));
Beta_buffer = (double*) malloc(window_size*8*sizeof(double));
Beta_buffer_tmp = (double*) malloc(8*sizeof(double));
//fd = fopen("step_test.txt","w");
//llr_calc_counter=0;
//llr_calc_state=0;
Len=*Len_p;
Mem=*Mem_p;
itermax=*itermax_p;
Beta_acq_initial_end=0;
Beta_initial_end=0;
window_counter=0;
map_type=1;
Len=Len+3; //+3 tail bit;
if((Len%window_size)==0)
{
window_number=Len/window_size;
zero_padding_number=0;
}
else
{
window_number=Len/window_size+1;
zero_padding_number=window_number*window_size-Len;
}
// }
Len=window_size*window_number;
//slide window Log-MAP algorithm
//sem_wait(&(*sem3_p));
//sem_post(&(*sem4_p));
for(n_iter=0;n_iter<itermax;n_iter++)
{
window_counter = 0;
Beta_acq_initial_end=0;
Beta_initial_end=0;
for(i=0;i<window_size*4+1;i++)
{
gs[i]=0;
gp[i]=0;
}
for(i=0;i<8;i++)
{
Alpha[i] = 0;
Alpha_tmp[i] = 0;
Beta[i] = 0;
Beta_acq[i] = 0;
Beta_buffer_tmp[i] = 0;
}
for(i=0;i<window_size*8;i++)
{
Beta_buffer[i]=0;
}
for(llr_calc_counter=0;llr_calc_counter<Len+4*window_size;llr_calc_counter++)
{
//printf("calc_2\n");
//printf("task2\n");
//sem_getvalue(&(*sem3_p),&index1);
//sem_getvalue(&(*sem4_p),&index2);
if(llr_calc_counter < Len +4*window_size - gate_counter - 1 || n_iter<itermax - 1)
{
//sem_post(&(*sem1_p));
sem_wait(&(*sem1_p));
//printf("www\n");
}
//printf("deBUG!\n");
if((llr_calc_counter%window_size)==0 && llr_calc_counter!=0)
{
window_counter++;
//printf("window_counter = %d\n",window_counter);
}
if (llr_calc_counter%(2*window_size)<window_size)
{
Beta_address_order_flag=0; //beta address order 0 1 ... 31
}
else
{
Beta_address_order_flag=1; //beta address order 31 30 ... 0
}
//printf("deBUG!\n");
//gamma buffer
addr_tmp=llr_calc_counter;
//information bits
tmp = interleave_table[addr_tmp];
if(addr_tmp<Len-3-zero_padding_number)
{
//printf("gamma_s = -llr_s2[addr_tmp]+llr_es1[tmp]+store_llr2[addr_tmp];\n");
gamma_s = -llr_s2[addr_tmp]+llr_es1[tmp]+store_llr2[addr_tmp];
//printf("gamma_s = -llr_s2[addr_tmp]+llr_es1[tmp]+store_llr2[addr_tmp];\n");
gamma_p = -llr_p2[addr_tmp];
// printf("deBUG!\n");
//printf("read2222222!!!\n");
//handle overflow problem
}
//tail bit
else if(llr_calc_counter<Len-zero_padding_number)
{
gamma_s = -llr_s2[addr_tmp]+store_llr2[addr_tmp];
gamma_p = -llr_p2[addr_tmp];
}
if(llr_calc_counter<Len-zero_padding_number)
{
gamma_buffer(gs,gp,(gamma_s),gamma_p);
}
else
{
if(llr_calc_counter<Len)
{
gamma_buffer(gs,gp,64,64);
}
else
{
gamma_buffer(gs,gp,0,0);
}
}
//initial Alpha
if(llr_calc_counter==0)
{
for (i=0; i<8; i++)
{
Alpha[i]= 0;
}
if (1)
{
Alpha[0]=192/4;
}
}
//start alpha calculation and llr calculation
if(window_counter>3)
{
if(window_counter<window_number+4)
{
read_Beta(Beta_address_order_flag, llr_calc_counter, Beta_buffer, Beta_buffer_tmp);
//llr calculation
addr_tmp=4*window_size;
if(llr_calc_counter>=4*window_size && llr_calc_counter<Len-zero_padding_number+4*window_size)
{
llr_es2[llr_calc_counter-4*window_size] = calc_ext_llr(gs[addr_tmp],gp[addr_tmp],Alpha,Beta_buffer_tmp,0);//>>1;
llr_ep2[llr_calc_counter-4*window_size] = calc_ext_llr(gs[addr_tmp],gp[addr_tmp],Alpha,Beta_buffer_tmp,1);//>>1;
/*
if(llr_calc_counter==4*window_size+100)
{
printf("gs[100]=%d\n",gs[addr_tmp]);
}
*/
//Alpha calculation
calc_Alpha(gs[addr_tmp],gp[addr_tmp],Alpha,Alpha_tmp);
for(i=0; i<8; i++)
{
Alpha[i]=Alpha_tmp[i]; //error Alpha[i]=Alpha_tmp[i]-64;
}
}
}
}
//printf("4");
//start beta calculation
if(window_counter>2)
{
if(window_counter<window_number+3)
{
if(llr_calc_counter%window_size ==0 )
{
if(window_counter==window_number+2)
{
Beta_initial_end=1;
}
Beta_initial_flag=1;
}
else
{
Beta_initial_flag=0;
}
//Beta update
addr_tmp=2*window_size+(llr_calc_counter%window_size)*2;
Beta_update_and_save(Beta_initial_end,Beta_address_order_flag,Beta_initial_flag, llr_calc_counter, gs[addr_tmp], gp[addr_tmp], Beta, Beta_acq, Beta_buffer);
}
}
//start beta acq calculation
// printf("5");
if(window_counter>1)
{
if(window_counter<(window_number+2));
{
//Beta flag
if ((llr_calc_counter%window_size) ==0 )
{
if(window_counter==window_number+1)
{
Beta_acq_initial_end=1;
}
Beta_acq_initial_flag=1;
}
else
{
Beta_acq_initial_flag=0;
}
addr_tmp=1+(llr_calc_counter%window_size)*2;
Beta_acq_update(Beta_acq_initial_end,Beta_acq_initial_flag, gs[addr_tmp], gp[addr_tmp], Beta_acq,map_type);
}
}
//if(llr_calc_counter==0&&)
//sem_getvalue(&(*sem3_p),&index1);
//sem_getvalue(&(*sem4_p),&index2);
if(llr_calc_counter < Len +4*window_size - gate_counter - 1 || n_iter<itermax - 1)
{
//printf("wwwwww\n");
sem_post(&(*sem2_p));
//sem_wait(&(*sem2_p));
}
}
}
Len=Len-3-zero_padding_number;
free(Alpha_tmp);
free(gs);
free(gp);
free(Alpha);
free(Beta);
free(Beta_buffer);
free(Beta_buffer_tmp);
free(Beta_acq);
//fclose(fd);
return 0;
}
void turbo_decode_rm( short* dec,
double* llr_out,
double* llr_in,
double* store_llr,
int Len,
int E,
int iterCNum,
int g0,
int g1,
int Mem,
int* interleave_table,
int* ratematch_table)
{
double *llr_in_tmp, *llr_out_tmp;
double *llr_s1, *llr_s2, *llr_p1, *llr_p2, *llr_es1, *llr_es2,*llr_ep1, *llr_ep2, *llr_s_tmp, *llr_p1_tmp, *llr_p2_tmp;
double *gs1, *gp1, *gs2, *gp2;
int *deinterleave_table;
double *store_llr1, *store_llr2;
int i = 0;
int itermax = 0;
itermax=iterCNum;
pthread_t thread1,thread2;
sem_t sem1, sem2, sem3, sem4;
//FILE *fd;
llr_in_tmp = (double *) malloc(3*(Len+4)*sizeof(double));
llr_out_tmp = (double*) malloc(3*(Len+4)*sizeof(double));
llr_s1 = (double*) malloc((Len+4)*sizeof(double));
llr_s2 = (double*) malloc((Len+4)*sizeof(double));
llr_p1 = (double*) malloc((Len+4)*sizeof(double));
llr_p2 = (double*) malloc((Len+4)*sizeof(double));
llr_es1 = (double*) malloc((Len+Mem)*sizeof(double));
llr_es2 = (double*) malloc((Len+Mem)*sizeof(double));
llr_ep1 = (double*) malloc((Len+Mem)*sizeof(double));
llr_ep2 = (double*) malloc((Len+Mem)*sizeof(double));
deinterleave_table = (int*) malloc((Len)*sizeof(int));
//store tailbit
llr_s_tmp = (double*) malloc(4*sizeof(double));
llr_p1_tmp = (double*) malloc(4*sizeof(double));
llr_p2_tmp = (double*) malloc(4*sizeof(double));
store_llr1 = (double*) malloc((Len+Mem)*sizeof(double));
store_llr2 = (double*) malloc((Len+Mem)*sizeof(double));
gs1 = (double*) malloc((Len+Mem)*sizeof(double));
gp1 = (double*) malloc((Len+Mem)*sizeof(double));
gs2 = (double*) malloc((Len+Mem)*sizeof(double));
gp2 = (double*) malloc((Len+Mem)*sizeof(double));
sem_init(&sem1, 0, 0);
sem_init(&sem2, 0, 0);
sem_init(&sem3, 0, 0);
sem_init(&sem4, 0, 0);
for(i=0;i<Len+4;i++)
{
llr_s1[i] = 0;
llr_s2[i] = 0;
llr_p1[i] = 0;
llr_p2[i] = 0;
}
for(i=0;i<3*(Len+4);i++)
{
llr_in_tmp[i] = 0;
llr_out_tmp[i]= 0;
}
for(i=0;i<Len+Mem;i++)
{
llr_es1[i]= 0;
llr_es2[i]= 0;
llr_ep1[i]= 0;
llr_ep2[i]= 0;
store_llr1[i]= 0;
store_llr2[i]= 0;
gs1[i]= 0;
gp1[i]= 0;
gs2[i]= 0;
gp2[i]= 0;
}
for(i=0;i<Len;i++)
{
deinterleave_table[i] = 0;
}
for(i=0;i<4;i++)
{
llr_s_tmp[i] = 0;
llr_p1_tmp[i] = 0;
llr_p2_tmp[i] = 0;
}
void* arg[19]={&Len, &Mem, llr_es1, llr_es2, interleave_table, deinterleave_table, llr_s1, llr_s2, llr_p1, llr_p2, llr_ep1, llr_ep2, store_llr1, store_llr2, &sem1, &sem2, &itermax, &sem3, &sem4};
get_deinterleave_table( deinterleave_table, Len, interleave_table);
//rate match....
rate_dematching(Len+4, E, llr_in, llr_in_tmp, ratematch_table);
//printf("rate match");
//*********************************input data**************************************//
for(i=0 ; i<Len+Mem; i++)
{
llr_es1[i] = 0;
llr_es2[i] = 0;
llr_ep1[i] = 0;
llr_ep2[i] = 0;
}
for(i=0; i<Len+4; i++)
{
llr_s1[i] = llr_in_tmp[3*i];
llr_s2[i] = llr_in_tmp[3*i];
llr_p1[i] = llr_in_tmp[3*i+1];
llr_p2[i] = llr_in_tmp[3*i+2];
//check input : |input| > 127 not valid
}
//process tail bit
for(i=0; i<4; i++)
{
llr_s_tmp[i] = llr_s1[Len+i];
llr_p1_tmp[i] = llr_p1[Len+i];
llr_p2_tmp[i] = llr_p2[Len+i];
}
llr_s1[Len] = llr_s_tmp[0];
llr_s1[Len+1] = llr_p2_tmp[0];
llr_s1[Len+2] = llr_p1_tmp[1];
llr_p1[Len] = llr_p1_tmp[0];
llr_p1[Len+1] = llr_s_tmp[1];
llr_p1[Len+2] = llr_p2_tmp[1];
llr_s2[Len] = llr_s_tmp[2];
llr_s2[Len+1] = llr_p2_tmp[2];
llr_s2[Len+2] = llr_p1_tmp[3];
llr_p2[Len] = llr_p1_tmp[2];
llr_p2[Len+1] = llr_s_tmp[3];
llr_p2[Len+2] = llr_p2_tmp[3];
inner_interleave(llr_s2, Len, interleave_table);
for(i=0; i<Len+Mem; i++)
{
if(store_llr[i]<-127/4)
{
store_llr[i]=-127/4;
}
else
{
if(store_llr[i]>127/4)
{
store_llr[i]=127/4;
}
}
}
for(i=0; i<Len+Mem; i++)
{
store_llr1[i] = store_llr[i];
}
inner_interleave(store_llr, Len, interleave_table);
for(i=0; i<Len; i++)
{
//store_llr2[i] = 0;
store_llr2[i] = store_llr[i];
}
for(i=Len; i<Len+Mem; i++)
{
store_llr2[i] = 0;
}
for(i=0; i<Len+Mem; i++)
{
if (llr_s1[i] > 127/4)
{
llr_s1[i] = 127/4;
}
else if (llr_s1[i] < -128/4)
{
llr_s1[i] = -128/4;
}
}
for(i=0; i<Len+Mem; i++)
{
if (llr_s2[i] > 127/4)
{
llr_s2[i] = 127/4;
}
else if (llr_s2[i] < -127/4)
{
llr_s2[i] = -127/4;
}
}
//printf("MAIN llr_es2[100] = %d\n",llr_es2[100]);
//printf("MAIN llr_es1[100] = %d\n",llr_es1[428]);
//printf("TURBO_RSC!!!\n");
pthread_create(&thread1, NULL, turbo_rsc_decoder1, arg);
pthread_create(&thread2, NULL, turbo_rsc_decoder2, arg);
//printf("Creat OK!!\n");
//iterCNum
//calculating..........
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
//printf("deinterleave[100] = %d\n",deinterleave_table[100]);
//printf("MAIN_LATER llr_es1[428] = %d\n",llr_es1[428]);
//printf("MAIN_LATER llr_es2[100] = %d\n",llr_es2[100]);
inner_deinterleave(llr_es2, Len, interleave_table);
for(i=0; i<Len; i++)
{
llr_s1[i] = -llr_s1[i] + llr_es1[i] + llr_es2[i] + store_llr1[i];
llr_p1[i] = -llr_p1[i] + llr_ep1[i];
llr_p2[i] = -llr_p2[i] + llr_ep2[i];
store_llr[i] = (store_llr1[i]+llr_es1[i]+llr_es2[i]);
}
for(i=Len; i<Len+Mem; i++)
{
llr_s1[i] = -llr_s1[i] + llr_es1[i] + store_llr1[i];
llr_s2[i] = -llr_s2[i] + llr_es2[i];
llr_p1[i] = -llr_p1[i] + llr_ep1[i];
llr_p2[i] = -llr_p2[i] + llr_ep2[i];
store_llr[i] = (store_llr1[i]+llr_es1[i]);
}
llr_s_tmp[0] = llr_s1[Len];
llr_p1_tmp[0] = llr_p1[Len];
llr_p2_tmp[0] = llr_s1[Len+1];
llr_s_tmp[1] = llr_p1[Len+1];
llr_p1_tmp[1] = llr_s1[Len+2];
llr_p2_tmp[1] = llr_p1[Len+2];
llr_s_tmp[2] = llr_s2[Len];
llr_p1_tmp[2] = llr_p2[Len];
llr_p2_tmp[2] = llr_s2[Len+1];
llr_s_tmp[3] = llr_p2[Len+1];
llr_p1_tmp[3] = llr_s2[Len+2];
llr_p2_tmp[3] = llr_p2[Len+2];
for(i=0; i<4; i++)
{
llr_s1[Len+i] = llr_s_tmp[i];
llr_p1[Len+i] = llr_p1_tmp[i];
llr_p2[Len+i] = llr_p2_tmp[i];
}
/* decision */
for(i=0; i<Len; i++)
{
dec[i] = (llr_s1[i] < 0)? 1:0;
}
for(i=0; i<Len+4; i++)
{
llr_out_tmp[3*i] = -llr_s1[i];
llr_out_tmp[3*i+1] = -llr_p1[i];
llr_out_tmp[3*i+2] = -llr_p2[i];
}
for(i=0; i<3*(Len+4); i++)
{
llr_out_tmp[i] = (llr_out_tmp[i]>127/4)? 127/4:llr_out_tmp[i];
llr_out_tmp[i] = (llr_out_tmp[i]<-128/4)? -128/4:llr_out_tmp[i];
}
rate_matching(Len+4, E, llr_out_tmp, llr_out, ratematch_table);
sem_destroy(&sem1);
sem_destroy(&sem2);
sem_destroy(&sem3);
sem_destroy(&sem4);
free(gs1);
free(gp1);
free(gs2);
free(gp2);
free(llr_s1);
free(llr_s2);
free(llr_p1);
free(llr_p2);
free(llr_es1);
free(llr_es2);
free(llr_ep1);
free(llr_ep2);
free(store_llr1);
free(store_llr2);
free(llr_s_tmp);
free(llr_p1_tmp);
free(llr_p2_tmp);
free(llr_in_tmp);
free(llr_out_tmp);
free(deinterleave_table);
}
int main()
{
int TTINum;
int TTIloop,rm_loop,block_loop;
int block_length;
int rm_length;
double LLRD[18444];
int store_llr[18444];
int QppIntlTable[6144];
int RmIntlTable[18444];
short Msg[6144];
double llr_out[18444];
short dec[6144];
double LLRD_f[18444];
double store_llr_f[18444];
int err_num;
int code_num;
double ber;
int i;
FILE *fd_TTINum;
FILE *fd_LLRD;
FILE *fd_store_llr;
FILE *fd_QppIntlTable;
FILE *fd_RmIntlTable;
FILE *fd_block_length;
FILE *fd_rm_length;
FILE *fd_Msg;
FILE *fd_result;
//open test source file
fd_result = fopen("result.txt","w");
for(i=iteriter;i<(iteriter+1);i++)
{
printf("\nITERnum = %d\n",i);
//open test source file
fd_TTINum = fopen("../c_test_source/TTINum.txt","r");
fd_QppIntlTable = fopen("../c_test_source/QppIntlTable.txt","r");
fd_block_length = fopen("../c_test_source/block_length.txt","r");
fd_rm_length = fopen("../c_test_source/rm_length.txt","r");
fd_RmIntlTable = fopen("../c_test_source/RmIntlTable.txt","r");
fd_LLRD = fopen("../c_test_source/LLRD.txt","r");
fd_store_llr = fopen("../c_test_source/store_llr.txt","r");
fd_Msg = fopen("../c_test_source/Msg.txt","r");
fscanf(fd_TTINum,"%x",&TTINum);
printf("Test TTINum: %d\n",TTINum);
//fprintf(fd_result,"Test TTINum: %d\n",TTINum);
//initial error number and ber
err_num=0;
code_num=0;
ber=0;
//main loop
for(TTIloop=0; TTIloop<TTINum; TTIloop++)
{
//read block length and rate matching length
fscanf(fd_block_length,"%x",&block_length);
fscanf(fd_rm_length,"%x",&rm_length);
code_num=code_num+block_length;
printf(" TTINum : %d \n <-- block_length : %d -- rm_length: %d -->\n",TTIloop,block_length,rm_length);
//fprintf(fd_result," TTINum : %d \n <-- block_length : %d -- rm_length: %d -->\n",TTIloop,block_length,rm_length);
//read Qpp interleave Table
for (block_loop=0; block_loop<block_length; block_loop++)
{
fscanf(fd_QppIntlTable,"%x",&QppIntlTable[block_loop]);
//printf(" QppIntlTable input : %d -- location %d\n",QppIntlTable[block_loop],block_loop);
}
//read rate matching Table and decoder input
for (rm_loop=0; rm_loop<rm_length; rm_loop++)
{
fscanf(fd_RmIntlTable,"%x",&RmIntlTable[rm_loop]);
fscanf(fd_LLRD,"%lf",&LLRD[rm_loop]);
fscanf(fd_store_llr,"%x",&store_llr[rm_loop]);
LLRD_f[rm_loop] = LLRD[rm_loop];
store_llr_f[rm_loop] = store_llr[rm_loop];
}
//turbo decoder
turbo_decode_rm(dec, llr_out, LLRD_f, store_llr_f, block_length, rm_length, i, 11, 13, 3, QppIntlTable, RmIntlTable);
//read msg to count number of error
for (block_loop=0; block_loop<block_length; block_loop++)
{
fscanf(fd_Msg,"%x",&Msg[block_loop]);
if (dec[block_loop]!=Msg[block_loop])
{
err_num = err_num+1;
}
}
//show result
ber = (err_num*1.0)/code_num;
printf(" BER %f ; error number : %d\n", ber, err_num);
}
//fprintf(fd_result,"code_num = %d, errornumber= %d\n",code_num, err_num);
fprintf(fd_result,"ITERnum = %d BER %f \n", i,ber);
}
//read TTI
//printf(" finish!!!!!!!!!!!!!!!!");
fclose(fd_TTINum);
fclose(fd_block_length);
fclose(fd_rm_length);
fclose(fd_QppIntlTable);
fclose(fd_RmIntlTable);
fclose(fd_store_llr);
fclose(fd_LLRD);
fclose(fd_result);
}
并行译码 多线程
最新推荐文章于 2023-10-08 16:15:51 发布