Fix LFSR behavior
[archipelago] / xseg / peers / user / bench-lfsr.c
1 /*
2  * Copyright 2012 GRNET S.A. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or
5  * without modification, are permitted provided that the following
6  * conditions are met:
7  *
8 *   1. Redistributions of source code must retain the above
9 *      copyright notice, this list of conditions and the following
10 *      disclaimer.
11 *   2. Redistributions in binary form must reproduce the above
12 *      copyright notice, this list of conditions and the following
13 *      disclaimer in the documentation and/or other materials
14 *      provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 *
29 * The views and conclusions contained in the software and
30 * documentation are those of the authors and should not be
31 * interpreted as representing official policies, either expressed
32 * or implied, of GRNET S.A.
33 */
34
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <unistd.h>
38 #include <sys/syscall.h>
39 #include <sys/types.h>
40 #include <pthread.h>
41 #include <xseg/xseg.h>
42 #include <peer.h>
43 #include <time.h>
44 #include <sys/util.h>
45 #include <signal.h>
46 #include <bench-xseg.h>
47 #include <limits.h>
48
49 #include <math.h>
50
51 #ifdef __GNUC__
52 #define likely(x)       __builtin_expect(!!(x),1)
53 #define unlikely(x)     __builtin_expect(!!(x),0)
54 #else
55 #define likely(x)       (x)
56 #define unlikely(x)     (x)
57 #endif
58
59 #define MAX_TAPS 6
60
61 #ifdef STAND_ALONE
62 uint64_t global_seed;
63 #endif
64
65 /*
66  * LFSRs are pseudo-random number generators. They are deterministic (meaning
67  * that the same seed will produce the same number sequence) and extremely
68  * fast.
69  *
70  * You can find more about LFSRs from these links:
71  * http://en.wikipedia.org/wiki/Linear_feedback_shift_register
72  * http://www.xilinx.com/support/documentation/application_notes/xapp052.pdf
73  * http://www.ti.com/lit/an/scta036a/scta036a.pdf
74  * http://notabs.org/lfsr/lfsr.html
75  * http://www.electricdruid.net/index.php?page=techniques.practicalLFSRs
76  *
77  * LFSR taps retrieved from:
78  * http://home1.gte.net/res0658s/electronics/LFSRtaps.html
79  *
80  * It's common in the bibliography to start the numbering of LFSR bits from 1
81  * instead of 0. We will use the same numbering in this code and alter it
82  * where necessary.
83  *
84  * Below is a 64x6 uint8_t array that covers all the appropriate taps for
85  * maximal length LFSRs, ranging from 3-bits to 64bit. It's memory overhead
86  * should be relatively small, no more than 384 bytes.
87  */
88 static uint8_t taps[64][MAX_TAPS] =
89 {
90                 {0}, {0}, {0},          //LFSRs with less that 3-bits cannot exist
91                 {3, 2},                         //Tap position for 3-bit LFSR
92                 {4, 3},                         //Tap position for 4-bit LFSR
93                 {5, 3},                         //Tap position for 5-bit LFSR
94                 {6, 5},                         //Tap position for 6-bit LFSR
95                 {7, 6},                         //Tap position for 7-bit LFSR
96                 {8, 6, 5 ,4},           //Tap position for 8-bit LFSR
97                 {9, 5},                         //Tap position for 9-bit LFSR
98                 {10, 7},                        //Tap position for 10-bit LFSR
99                 {11, 9},                        //Tap position for 11-bit LFSR
100                 {12, 6, 4, 1},          //Tap position for 12-bit LFSR
101                 {13, 4, 3, 1},          //Tap position for 13-bit LFSR
102                 {14, 5, 3, 1},          //Tap position for 14-bit LFSR
103                 {15, 14},                       //Tap position for 15-bit LFSR
104                 {16, 15, 13, 4},        //Tap position for 16-bit LFSR
105                 {17, 14},                       //Tap position for 17-bit LFSR
106                 {18, 11},                       //Tap position for 18-bit LFSR
107                 {19, 6, 2, 1},          //Tap position for 19-bit LFSR
108                 {20, 17},                       //Tap position for 20-bit LFSR
109                 {21, 19},                       //Tap position for 21-bit LFSR
110                 {22, 21},                       //Tap position for 22-bit LFSR
111                 {23, 18},                       //Tap position for 23-bit LFSR
112                 {24, 23, 22, 17},       //Tap position for 24-bit LFSR
113                 {25, 22},                       //Tap position for 25-bit LFSR
114                 {26, 6, 2, 1},          //Tap position for 26-bit LFSR
115                 {27, 5, 2, 1},          //Tap position for 27-bit LFSR
116                 {28, 25},                       //Tap position for 28-bit LFSR
117                 {29, 27},                       //Tap position for 29-bit LFSR
118                 {30, 6, 4, 1},          //Tap position for 30-bit LFSR
119                 {31, 28},                       //Tap position for 31-bit LFSR
120                 {32, 31, 29, 1},        //Tap position for 32-bit LFSR
121                 {33, 20},                       //Tap position for 33-bit LFSR
122                 {34, 27, 2, 1},         //Tap position for 34-bit LFSR
123                 {35, 33},                       //Tap position for 35-bit LFSR
124                 {36, 25},                       //Tap position for 36-bit LFSR
125                 {37, 5, 4, 3, 2, 1},//Tap position for 37-bit LFSR
126                 {38, 6, 5, 1},          //Tap position for 38-bit LFSR
127                 {39, 35},                       //Tap position for 39-bit LFSR
128                 {40, 38, 21, 19},       //Tap position for 40-bit LFSR
129                 {41, 38},                       //Tap position for 41-bit LFSR
130                 {42, 41, 20, 19},       //Tap position for 42-bit LFSR
131                 {43, 42, 38, 37},       //Tap position for 43-bit LFSR
132                 {44, 43, 18, 17},       //Tap position for 44-bit LFSR
133                 {45, 44, 42, 41},       //Tap position for 45-bit LFSR
134                 {46, 45, 26, 25},       //Tap position for 46-bit LFSR
135                 {47, 42},                       //Tap position for 47-bit LFSR
136                 {48, 47, 21, 20},       //Tap position for 48-bit LFSR
137                 {49, 40},                       //Tap position for 49-bit LFSR
138                 {50, 49, 24, 23},       //Tap position for 50-bit LFSR
139                 {51, 50, 36, 35},       //Tap position for 51-bit LFSR
140                 {52, 49},                       //Tap position for 52-bit LFSR
141                 {53, 52, 38, 37},       //Tap position for 53-bit LFSR
142                 {54, 53, 18, 17},       //Tap position for 54-bit LFSR
143                 {55, 31},                       //Tap position for 55-bit LFSR
144                 {56, 55, 35, 34},       //Tap position for 56-bit LFSR
145                 {57, 50},                       //Tap position for 57-bit LFSR
146                 {58, 39},                       //Tap position for 58-bit LFSR
147                 {59, 58, 38, 37},       //Tap position for 59-bit LFSR
148                 {60, 59},                       //Tap position for 60-bit LFSR
149                 {61, 60, 46, 45},       //Tap position for 61-bit LFSR
150                 {62, 61, 6, 5},         //Tap position for 62-bit LFSR
151                 {63, 62},                       //Tap position for 63-bit LFSR
152 };
153
154 /*
155  * There are two kinds of LFSRs, each of which can be implemented with XOR or
156  * XNOR logic:
157  * a) Fibonacci LFSRs, that have XOR/XNOR gates serially to produce the input
158  * bit and
159  * b) Galois LFSRs, that have XOR/XNOR gates parallely, separated from one
160  * another and the outputs of which are fed as input bits. Also, the tap bits
161  * are flipped, depending on the output bit.
162  *
163  * A Galois LFSR seems more complicated but is actually the fittest
164  * implementation for an LFSR on CPU, due to the fact that the input bit can
165  * be computed on one turn, instead of 2 - 6 that would be needed for a
166  * Fibonacci LFSR. Another point that must be taken into consideration is
167  * that an LFSR with XOR gates has the 0 state as illegal, which is something
168  * we do not want for benchmarks.
169  *
170  * That's why we use an Galois-XNOR LFSR.
171  *
172  * Below we create what can best be described as an XNOR-mask
173  */
174 static uint64_t lfsr_create_xnormask(uint8_t *taps)
175 {
176         int i;
177         uint64_t xnormask = 0;
178
179         for(i = 0; i < MAX_TAPS && taps[i] != 0; i++)
180                 xnormask |= 1UL << (taps[i] - 1);
181
182         return xnormask;
183 }
184
185 /*
186  * To initialize an LFSR we need the following:
187  * a) the upper limit of random numbers that we want LFSR to generate (size)
188  * b) the initial state of LFSR (seed)
189  *
190  * NOTE1: If the upper limit is bigger than 63 bits or smaller than 3 bits, we
191  * cannot create the LFSR.
192  * NOTE2: If 2^(n+1) < upper_limit <= 2^n , the LFSR that will be created will
193  * have (n+1) bits.
194  * NOTE3: If an LFSR has n bits, the seed must not be all ones (= 2^(n+1) - 1)
195  */
196 /*
197 int lfsr_init(struct lfsr *lfsr, uint64_t size, uint64_t seed)
198 {
199         uint8_t i;
200
201         lfsr->limit = size;
202
203         //i has number of bits of size
204         for (i = 0; size; i++)
205                 size = size >> 1;
206
207         if (i < 3 || i > 63)
208                 return -1;
209
210         lfsr->length = i;
211         lfsr->xnormask = lfsr_create_xnormask(taps[i]);
212
213         if (seed == (1UL << (i + 1)) - 1)
214                 return -1;
215
216         lfsr->state = seed;
217         return 0;
218 }
219 */
220 int lfsr_init(struct lfsr *lfsr, uint64_t size, uint64_t seed)
221 {
222         uint8_t i;
223
224         lfsr->limit = size;
225
226         //i has number of bits of size
227         for (i = 0; size; i++)
228                 size = size >> 1;
229
230         //Too small or too big size to create an LFSR out of it
231         if (i < 3 || i > 63)
232                 return -1;
233
234         //The all ones state is illegal. Due to the fact that our seed is
235         //nanoseconds taken from clock_gettime, we are sure that the 31st bit will
236         //always be 0. The following codes has that in mind and creates a seed
237         //that has at least one 0.
238         if (seed == UINT64_MAX) {
239                 if (i < 32)
240                         lfsr->state = global_seed >> (31 - i);
241                 else
242                         lfsr->state = global_seed << (i - 31);
243         }
244         else {
245                 lfsr->state = seed;
246         }
247
248         lfsr->cached_bit = 1UL << (i-1);
249         lfsr->length = i;
250         lfsr->xnormask = lfsr_create_xnormask(taps[i]);
251
252         return 0;
253 }
254
255 #ifdef STAND_ALONE
256 /*
257  * Sanity-check every LFSR for mistakes.
258  */
259 static int lfsr_check()
260 {
261         struct lfsr lfsr;
262         uint8_t length, i;
263         uint64_t period;
264         uint64_t upper_limit;
265
266         //Create all LFSRs with maximum limit
267         for (length = 3; length < 64; length++) {
268                 if (lfsr_init(&lfsr, pow(2, length) - 1, 1))
269                         return -1;
270         //      printf("XNOR-mask: %lu, state: %lu, limit: %lu\n",
271         //                      lfsr.xnormask, lfsr.state, lfsr.limit);
272                 period = 1; //Already initialized at 1
273                 upper_limit = pow(2, length);
274
275                 while(likely(period++ < upper_limit))
276                         lfsr_next(&lfsr);
277
278                 if (lfsr.state == 1) {
279                         printf("%u-bit LFSR is correct\n", length);
280                 }
281                 else {
282                         printf("%u-bit LFSR did not iterate successfully\n", length);
283                         printf("Current tap positions: ");
284                         for (i = 0; i < MAX_TAPS && taps[length][i] != 0; i++)
285                                 printf("%u ", taps[length][i]);
286                         printf("\n");
287                         return -1;
288                 }
289         //      return 0;
290         }
291
292         return 0;
293 }
294
295 int main()
296 {
297         int r;
298
299         r = lfsr_check();
300
301         return r;
302 }
303 #endif
304