-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathRunDecoder.cu
205 lines (170 loc) · 7.4 KB
/
RunDecoder.cu
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
#include <random>
#include <math.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <chrono>
#include "GPUincludes.h"
#include "LDPC.h"
#define HISTORY_LENGTH 20
int main (int argc, char **argv) {
using clock = std::chrono::steady_clock;
clock::time_point startTime;
clock::time_point endTime;
clock::duration oneTime;
clock::duration allTime;
// for recording time spent encoding.
clock::duration allTimeE;
int status;
unsigned int numChecks, numBits;
unsigned int nBundles;
unsigned int numRowsW, numColsW, numParityBits, shiftRegLength;
unsigned int *W_ROW_ROM;
H_matrix *hmat = (H_matrix*) malloc(sizeof(H_matrix));
int maxIterations;
char H_Alist_File[256];
char wROM_File[256];
FILE *src;
int errnum;
unsigned int infoLeng, rnum, rdenom;
float ebno;
unsigned int how_many;
float rNominal;
float No, sigma2, lc;
unsigned int seed = 163331;
/* or use this to get a fresh sequence each time the program is run.
std::random_device rd; //Will be used to obtain a seed for the random number engine
std::mt19937 generator(rd()); //Standard mersenne_twister_engine seeded with rd()
*/
std::mt19937 generator(seed); //Standard mersenne_twister_engine
std::uniform_real_distribution<> rDist(0, 1);
// normal distribution for noise.
// NOTE, we are using the same random number generator ("generator") here.
std::normal_distribution<float> normDist(0.0, 1.0);
if (argc < 8) {
printf("usage: RunDecoder <infoLength> <r-numerator> <r-denominator> <ebno> <numpackets> <maxIterations> <numBundles>\n" );
exit(-1);
}
infoLeng = atoi(argv[1]);
rnum = atoi(argv[2]);
rdenom = atoi(argv[3]);
rNominal = float(rnum)/float(rdenom);
ebno = atof(argv[4]);
how_many = atoi(argv[5]);
maxIterations = atoi(argv[6]);
nBundles = atoi(argv[7]);
sprintf(H_Alist_File, "./G_and_H_Matrices/H_%d%d_%d.alist", rnum, rdenom, infoLeng);
sprintf(wROM_File, "./G_and_H_Matrices/W_ROW_ROM_%d%d_%d.binary", rnum, rdenom, infoLeng);
// Noise variance and log-likelihood ratio (LLR) scale factor. Because
// Ec = R*Eb is unity (i.e. we transmit +1's and -1's), then No = 1/(R*EbNo).
No = 1/(rNominal * pow(10,(ebno/10)));
sigma2 = No/2;
// When r is scaled by Lc it results in precisely scaled LLRs
lc = 4/No;
status = ReadAlistFile(hmat, H_Alist_File);
if ( status != 0) {
printf ("Unable to read alist file: %s\n", H_Alist_File);
exit(-1);
}
numBits = hmat->numBits;
numChecks = hmat->numChecks;
src = fopen(wROM_File, "r");
if (src == NULL) {
errnum = errno;
printf("Value of errno: %d\n", errnum);
perror("Error printed by perror");
printf("Error opening file %s\n", wROM_File);
return(EXIT_FAILURE);
}
fread(& numRowsW, sizeof(unsigned int), 1, src);
fread(& numColsW, sizeof(unsigned int), 1, src);
fread(& shiftRegLength, sizeof(unsigned int), 1, src);
W_ROW_ROM = (unsigned int*) malloc(numRowsW * numColsW * sizeof( unsigned int));
fread(W_ROW_ROM, sizeof(unsigned int), numRowsW * numColsW, src);
numParityBits = numColsW;
fclose(src);
printf("parameters have been read.\n");
printf("SLOTS_PER_ELT = %d # bundles = %d\n", SLOTS_PER_ELT, nBundles);
printf("numBits = %i, numChecks = %i\n", numBits, numChecks);
printf("infoLeng = %i, numParityBits = %i (%i), numBits = %i\n",
infoLeng, numParityBits, infoLeng + numParityBits, numBits);
printf("maxChecksPerBit = %i maxBitsPerCheck = %i\n", hmat->maxChecksPerBit, hmat->maxBitsPerCheck);
printf("ebn0 = %f, sigma = %f\n", ebno, sigma2);
// ///////////////////////////////////////////
unsigned int decision[numBits];
bundleElt estimates[numBits];
unsigned int successes = 0;
unsigned int iterationSum = 0;
int packetsPerCycle, cycle, totalPackets;
int itersHistory[HISTORY_LENGTH+1];
int iters;
unsigned int* infoWord;
unsigned int* codeWord;
float s, noise;
float* receivedSig;
bundleElt* receivedBundle;
infoWord = (unsigned int *)malloc(infoLeng * sizeof(unsigned int));
codeWord = (unsigned int *)malloc((infoLeng+numParityBits) * sizeof(unsigned int));
receivedSig = (float *)malloc(numBits * sizeof(float));
receivedBundle = (bundleElt *)malloc(numBits * nBundles * sizeof(bundleElt));
// An ugly way to intialize variable allTime (accumulated interesting time) to zero.
startTime = clock::now();
allTime = startTime - startTime;
// timer for encoding.
allTimeE = allTime;
initLdpcDecoder (hmat, nBundles);
packetsPerCycle = SLOTS_PER_ELT * nBundles;
totalPackets = 0;
cycle = 0;
while (totalPackets < how_many) {
cycle++;
startTime = clock::now();
for (unsigned int bundleIndex=0; bundleIndex < nBundles; bundleIndex++) {
int bundleBase = bundleIndex * numBits;
for (unsigned int slot=0; slot < SLOTS_PER_ELT; slot++) {
for (unsigned int j=0; j < infoLeng; j++) infoWord[j] = (0.5 >= rDist(generator))? 1:0;
ldpcEncoder(infoWord, W_ROW_ROM, infoLeng, numRowsW, numColsW, shiftRegLength, codeWord);
// Modulate the codeWord, and add noise
for (unsigned int j=0; j < (infoLeng+numParityBits) ; j++) {
s = 2*float(codeWord[j]) - 1;
// AWGN channel
noise = sqrt(sigma2) * normDist(generator);
// When r is scaled by Lc it results in precisely scaled LLRs
receivedSig[j] = lc*(s + noise);
}
// The LDPC codes are punctured, so the r we feed to the decoder is
// longer than the r we got from the channel. The punctured positions are filled in as zeros
for (unsigned int j=(infoLeng+numParityBits); j<numBits; j++) receivedSig[j] = 0.0;
for (unsigned int j=0; j < numBits; j++ ) receivedBundle[bundleBase + j].s[slot] = receivedSig[j];
}
}
endTime = clock::now();
oneTime = endTime - startTime;
allTimeE = allTimeE + oneTime;
// Finally, ready to decode signal
startTime = clock::now();
iters = ldpcDecoderWithInit (hmat, receivedBundle, maxIterations, decision, estimates, nBundles);
endTime = clock::now();
oneTime = endTime - startTime;
allTime = allTime + oneTime;
totalPackets += packetsPerCycle;
successes += iters >> 8;
iters = iters & 0xff ;
iterationSum = iterationSum + iters;
if ( cycle <= HISTORY_LENGTH) { itersHistory[cycle] = iters;}
if (totalPackets % 1000 == 0)
printf(" %i Successes out of %i packets (%i msec).\n",
successes, totalPackets, std::chrono::duration_cast<std::chrono::milliseconds>(allTime).count());
}
printf("%i msec to decode %i packets.\n",std::chrono::duration_cast<std::chrono::milliseconds>(allTime).count(),totalPackets);
printf("%i msec to encode %i packets.\n",std::chrono::duration_cast<std::chrono::milliseconds>(allTimeE).count(),totalPackets);
printf(" %i Successes out of %i packets. (%.2f%%)\n", successes, totalPackets, 100.0 * successes/ totalPackets);
printf("Information rate: %.2f Mbps\n", successes * infoLeng / (1000.0 * std::chrono::duration_cast<std::chrono::milliseconds>(allTime).count()));
// Note, each iteration carries SLOTS_PER_ELT * nBundles packets, so make adjustments here.
int allIters = iterationSum * packetsPerCycle;
printf(" %i cumulative iterations, or about %.1f per packet.\n", allIters, allIters/(float)how_many);
printf("Number of iterations for the first few packets: ");
for (unsigned int i=1; i<= MIN(cycle, HISTORY_LENGTH); i++) {printf(" %i", itersHistory[i]);}
printf ("\n");
cudaDeviceReset();
}