Statistics
| Branch: | Tag: | Revision:

root / xseg / peers / user / bench-lfsr.c @ 9e593ec0

History | View | Annotate | Download (7.6 kB)

1
#include <stdio.h>
2
#include <math.h>
3

    
4
#include <bench-lfsr.h>
5

    
6
/*
7
 * LFSR taps retrieved from:
8
 * http://home1.gte.net/res0658s/electronics/LFSRtaps.html
9
 *
10
 * The memory overhead of the following tap table should be relatively small,
11
 * no more than 400 bytes.
12
 */
13
static uint8_t taps[64][MAX_TAPS] =
14
{
15
                {0}, {0}, {0},                //LFSRs with less that 3-bits cannot exist
16
                {3, 2},                                //Tap position for 3-bit LFSR
17
                {4, 3},                                //Tap position for 4-bit LFSR
18
                {5, 3},                                //Tap position for 5-bit LFSR
19
                {6, 5},                                //Tap position for 6-bit LFSR
20
                {7, 6},                                //Tap position for 7-bit LFSR
21
                {8, 6, 5 ,4},                //Tap position for 8-bit LFSR
22
                {9, 5},                                //Tap position for 9-bit LFSR
23
                {10, 7},                        //Tap position for 10-bit LFSR
24
                {11, 9},                        //Tap position for 11-bit LFSR
25
                {12, 6, 4, 1},                //Tap position for 12-bit LFSR
26
                {13, 4, 3, 1},                //Tap position for 13-bit LFSR
27
                {14, 5, 3, 1},                //Tap position for 14-bit LFSR
28
                {15, 14},                        //Tap position for 15-bit LFSR
29
                {16, 15, 13, 4},        //Tap position for 16-bit LFSR
30
                {17, 14},                        //Tap position for 17-bit LFSR
31
                {18, 11},                        //Tap position for 18-bit LFSR
32
                {19, 6, 2, 1},                //Tap position for 19-bit LFSR
33
                {20, 17},                        //Tap position for 20-bit LFSR
34
                {21, 19},                        //Tap position for 21-bit LFSR
35
                {22, 21},                        //Tap position for 22-bit LFSR
36
                {23, 18},                        //Tap position for 23-bit LFSR
37
                {24, 23, 22, 17},        //Tap position for 24-bit LFSR
38
                {25, 22},                        //Tap position for 25-bit LFSR
39
                {26, 6, 2, 1},                //Tap position for 26-bit LFSR
40
                {27, 5, 2, 1},                //Tap position for 27-bit LFSR
41
                {28, 25},                        //Tap position for 28-bit LFSR
42
                {29, 27},                        //Tap position for 29-bit LFSR
43
                {30, 6, 4, 1},                //Tap position for 30-bit LFSR
44
                {31, 28},                        //Tap position for 31-bit LFSR
45
                {32, 31, 29, 1},        //Tap position for 32-bit LFSR
46
                {33, 20},                        //Tap position for 33-bit LFSR
47
                {34, 27, 2, 1},                //Tap position for 34-bit LFSR
48
                {35, 33},                        //Tap position for 35-bit LFSR
49
                {36, 25},                        //Tap position for 36-bit LFSR
50
                {37, 5, 4, 3, 2, 1},//Tap position for 37-bit LFSR
51
                {38, 6, 5, 1},                //Tap position for 38-bit LFSR
52
                {39, 35},                        //Tap position for 39-bit LFSR
53
                {40, 38, 21, 19},        //Tap position for 40-bit LFSR
54
                {41, 38},                        //Tap position for 41-bit LFSR
55
                {42, 41, 20, 19},        //Tap position for 42-bit LFSR
56
                {43, 42, 38, 37},        //Tap position for 43-bit LFSR
57
                {44, 43, 18, 17},        //Tap position for 44-bit LFSR
58
                {45, 44, 42, 41},        //Tap position for 45-bit LFSR
59
                {46, 45, 26, 25},        //Tap position for 46-bit LFSR
60
                {47, 42},                        //Tap position for 47-bit LFSR
61
                {48, 47, 21, 20},        //Tap position for 48-bit LFSR
62
                {49, 40},                        //Tap position for 49-bit LFSR
63
                {50, 49, 24, 23},        //Tap position for 50-bit LFSR
64
                {51, 50, 36, 35},        //Tap position for 51-bit LFSR
65
                {52, 49},                        //Tap position for 52-bit LFSR
66
                {53, 52, 38, 37},        //Tap position for 53-bit LFSR
67
                {54, 53, 18, 17},        //Tap position for 54-bit LFSR
68
                {55, 31},                        //Tap position for 55-bit LFSR
69
                {56, 55, 35, 34},        //Tap position for 56-bit LFSR
70
                {57, 50},                        //Tap position for 57-bit LFSR
71
                {58, 39},                        //Tap position for 58-bit LFSR
72
                {59, 58, 38, 37},        //Tap position for 59-bit LFSR
73
                {60, 59},                        //Tap position for 60-bit LFSR
74
                {61, 60, 46, 45},        //Tap position for 61-bit LFSR
75
                {62, 61, 6, 5},                //Tap position for 62-bit LFSR
76
                {63, 62},                        //Tap position for 63-bit LFSR
77
};
78

    
79
#define __LFSR_NEXT(__lfsr, __v)                                                \
80
        __v = ((__v >> 1) | __lfsr->cached_bit) ^                        \
81
                        (((__v & 1UL) - 1UL) & __lfsr->xormask);
82

    
83
static inline void __lfsr_next(struct bench_lfsr *lfsr, unsigned int spin)
84
{
85
        /*
86
         * This should be O(1) since most compilers will create a jump table for
87
         * this switch.
88
         */
89
        switch (spin) {
90
                case 16: __LFSR_NEXT(lfsr, lfsr->last_val);
91
                case 15: __LFSR_NEXT(lfsr, lfsr->last_val);
92
                case 14: __LFSR_NEXT(lfsr, lfsr->last_val);
93
                case 13: __LFSR_NEXT(lfsr, lfsr->last_val);
94
                case 12: __LFSR_NEXT(lfsr, lfsr->last_val);
95
                case 11: __LFSR_NEXT(lfsr, lfsr->last_val);
96
                case 10: __LFSR_NEXT(lfsr, lfsr->last_val);
97
                case  9: __LFSR_NEXT(lfsr, lfsr->last_val);
98
                case  8: __LFSR_NEXT(lfsr, lfsr->last_val);
99
                case  7: __LFSR_NEXT(lfsr, lfsr->last_val);
100
                case  6: __LFSR_NEXT(lfsr, lfsr->last_val);
101
                case  5: __LFSR_NEXT(lfsr, lfsr->last_val);
102
                case  4: __LFSR_NEXT(lfsr, lfsr->last_val);
103
                case  3: __LFSR_NEXT(lfsr, lfsr->last_val);
104
                case  2: __LFSR_NEXT(lfsr, lfsr->last_val);
105
                case  1: __LFSR_NEXT(lfsr, lfsr->last_val);
106
                case  0: __LFSR_NEXT(lfsr, lfsr->last_val);
107
                default: break;
108
        }
109
}
110

    
111
/*
112
 * lfsr_next does the following:
113
 *
114
 * a. Return if the number of max values has been exceeded.
115
 * b. Check if we have a spin value that produces a repeating subsequence.
116
 *    This is previously calculated in `prepare_spin` and cycle_length should
117
 *    be > 0. If we do have such a spin:
118
 *
119
 *    i. Decrement the calculated cycle.
120
 *    ii. If it reaches zero, add "+1" to the spin and reset the cycle_length
121
 *        (we have it cached in the struct fio_lfsr)
122
 *
123
 *    In either case, continue with the calculation of the next value.
124
 * c. Check if the calculated value exceeds the desirable range. In this case,
125
 *    go back to b, else return.
126
 */
127
uint64_t lfsr_next(struct bench_lfsr *lfsr)
128
{
129
        lfsr->num_vals++;
130

    
131
        do {
132
                if (lfsr->cycle_length) {
133
                        lfsr->cycle_length--;
134
                        if (!lfsr->cycle_length) {
135
                                __lfsr_next(lfsr, lfsr->spin + 1);
136
                                lfsr->cycle_length = lfsr->cached_cycle_length;
137
                                goto check;
138
                        }
139
                }
140
                __lfsr_next(lfsr, lfsr->spin);
141
check: ;
142
        } while (lfsr->last_val > lfsr->max_val);
143

    
144
        return lfsr->last_val;
145
}
146

    
147
static uint64_t lfsr_create_xormask(uint8_t *taps)
148
{
149
        int i;
150
        uint64_t xormask = 0;
151

    
152
        for(i = 0; i < MAX_TAPS && taps[i] != 0; i++)
153
                xormask |= 1UL << (taps[i] - 1);
154

    
155
        return xormask;
156
}
157

    
158
static uint8_t *find_lfsr(uint64_t size)
159
{
160
        int i;
161

    
162
        for (i = 3; i < 64; i++)
163
                if ((1UL << i) > size) /* TODO: Explain why. */
164
                        return taps[i];
165

    
166
        return NULL;
167
}
168

    
169
/*
170
 * It is well-known that all maximal n-bit LFSRs will start repeating
171
 * themselves after their 2^n iteration. The introduction of spins however, is
172
 * possible to create a repetition of a sub-sequence before we hit that mark.
173
 * This happens if:
174
 *
175
 * [1]: ((2^n - 1) * i) % (spin + 1) == 0,
176
 * where "n" is LFSR's bits and "i" any number within the range [1,spin]
177
 *
178
 * It is important to know beforehand if a spin can cause a repetition of a
179
 * sub-sequence (cycle) and its length. However, calculating (2^n - 1) * i may
180
 * produce a buffer overflow for "n" close to 64, so we expand the above to:
181
 *
182
 * [2]: (2^n - 1) -> (x * (spin + 1) + y), where x >= 0 and 0 <= y <= spin
183
 *
184
 * Thus, [1] is equivalent to (y * i) % (spin + 1) == 0;
185
 * Also, the cycle's length will be (x * i) + (y * i) / (spin + 1)
186
 */
187
int prepare_spin(struct bench_lfsr *lfsr, unsigned int spin)
188
{
189
        uint64_t max = (lfsr->cached_bit << 1) - 1;
190
        uint64_t x, y;
191
        int i;
192

    
193
        if (spin > 15)
194
                return 1;
195

    
196
        x = max / (spin + 1);
197
        y = max % (spin + 1);
198
        lfsr->cycle_length = max;        /* This is the expected cycle */
199
        lfsr->spin = spin;
200

    
201
        for (i = 1; i <= spin; i++) {
202
                if ((y * i) % (spin + 1) == 0) {
203
                        lfsr->cycle_length = (x * i) + (y * i) / (spin + 1);
204
                        break;
205
                }
206
        }
207
        lfsr->cached_cycle_length = lfsr->cycle_length;
208

    
209
        return 0;
210
}
211

    
212
int lfsr_reset(struct bench_lfsr *lfsr, unsigned long seed)
213
{
214
        uint64_t bitmask = (lfsr->cached_bit << 1) - 1;
215

    
216
        lfsr->num_vals = 0;
217
        lfsr->last_val = seed & bitmask;
218

    
219
        /* All-ones state is illegal for XNOR LFSRs */
220
        if (lfsr->last_val == bitmask)
221
                return 1;
222

    
223
        return 0;
224
}
225

    
226
int lfsr_init(struct bench_lfsr *lfsr, uint64_t nums, unsigned long seed,
227
                unsigned int spin)
228
{
229
        uint8_t *lfsr_taps;
230

    
231
        lfsr_taps = find_lfsr(nums);
232
        if (!lfsr_taps)
233
                return 1;
234

    
235
        lfsr->max_val = nums - 1;
236
        lfsr->xormask = lfsr_create_xormask(lfsr_taps);
237
        lfsr->cached_bit = 1UL << (lfsr_taps[0] - 1);
238

    
239
        if (prepare_spin(lfsr, spin))
240
                return 1;
241

    
242
        if (lfsr_reset(lfsr, seed))
243
                return 1;
244

    
245
        return 0;
246
}
247