1 // Copyright 2006 Google Inc. All Rights Reserved.
2
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6
7 // http://www.apache.org/licenses/LICENSE-2.0
8
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 // pattern.cc : library of stressful data patterns
16
17 #include <sys/types.h>
18
19 // This file must work with autoconf on its public version,
20 // so these includes are correct.
21 #include "pattern.h"
22 #include "sattypes.h"
23
24 // Static data patterns.
25
26 static unsigned int walkingOnes_data[] = {
27 0x00000001, 0x00000002, 0x00000004, 0x00000008,
28 0x00000010, 0x00000020, 0x00000040, 0x00000080,
29 0x00000100, 0x00000200, 0x00000400, 0x00000800,
30 0x00001000, 0x00002000, 0x00004000, 0x00008000,
31 0x00010000, 0x00020000, 0x00040000, 0x00080000,
32 0x00100000, 0x00200000, 0x00400000, 0x00800000,
33 0x01000000, 0x02000000, 0x04000000, 0x08000000,
34 0x10000000, 0x20000000, 0x40000000, 0x80000000,
35 0x40000000, 0x20000000, 0x10000000, 0x08000000,
36 0x04000000, 0x02000000, 0x01000000, 0x00800000,
37 0x00400000, 0x00200000, 0x00100000, 0x00080000,
38 0x00040000, 0x00020000, 0x00010000, 0x00008000,
39 0x00004000, 0x00002000, 0x00001000, 0x00000800,
40 0x00000400, 0x00000200, 0x00000100, 0x00000080,
41 0x00000040, 0x00000020, 0x00000010, 0x00000008,
42 0x00000004, 0x00000002, 0x00000001, 0x00000000
43 };
44 static const struct PatternData walkingOnes = {
45 "walkingOnes",
46 walkingOnes_data,
47 (sizeof walkingOnes_data / sizeof walkingOnes_data[0]) - 1,
48 {1, 1, 2, 1} // Weight for choosing 32/64/128/256 bit wide of this pattern
49 };
50
51 static unsigned int walkingInvOnes_data[] = {
52 0x00000001, 0xfffffffe, 0x00000002, 0xfffffffd,
53 0x00000004, 0xfffffffb, 0x00000008, 0xfffffff7,
54 0x00000010, 0xffffffef, 0x00000020, 0xffffffdf,
55 0x00000040, 0xffffffbf, 0x00000080, 0xffffff7f,
56 0x00000100, 0xfffffeff, 0x00000200, 0xfffffdff,
57 0x00000400, 0xfffffbff, 0x00000800, 0xfffff7ff,
58 0x00001000, 0xffffefff, 0x00002000, 0xffffdfff,
59 0x00004000, 0xffffbfff, 0x00008000, 0xffff7fff,
60 0x00010000, 0xfffeffff, 0x00020000, 0xfffdffff,
61 0x00040000, 0xfffbffff, 0x00080000, 0xfff7ffff,
62 0x00100000, 0xffefffff, 0x00200000, 0xffdfffff,
63 0x00400000, 0xffbfffff, 0x00800000, 0xff7fffff,
64 0x01000000, 0xfeffffff, 0x02000000, 0xfdffffff,
65 0x04000000, 0xfbffffff, 0x08000000, 0xf7ffffff,
66 0x10000000, 0xefffffff, 0x20000000, 0xdfffffff,
67 0x40000000, 0xbfffffff, 0x80000000, 0x7fffffff,
68 0x40000000, 0xbfffffff, 0x20000000, 0xdfffffff,
69 0x10000000, 0xefffffff, 0x08000000, 0xf7ffffff,
70 0x04000000, 0xfbffffff, 0x02000000, 0xfdffffff,
71 0x01000000, 0xfeffffff, 0x00800000, 0xff7fffff,
72 0x00400000, 0xffbfffff, 0x00200000, 0xffdfffff,
73 0x00100000, 0xffefffff, 0x00080000, 0xfff7ffff,
74 0x00040000, 0xfffbffff, 0x00020000, 0xfffdffff,
75 0x00010000, 0xfffeffff, 0x00008000, 0xffff7fff,
76 0x00004000, 0xffffbfff, 0x00002000, 0xffffdfff,
77 0x00001000, 0xffffefff, 0x00000800, 0xfffff7ff,
78 0x00000400, 0xfffffbff, 0x00000200, 0xfffffdff,
79 0x00000100, 0xfffffeff, 0x00000080, 0xffffff7f,
80 0x00000040, 0xffffffbf, 0x00000020, 0xffffffdf,
81 0x00000010, 0xffffffef, 0x00000008, 0xfffffff7,
82 0x00000004, 0xfffffffb, 0x00000002, 0xfffffffd,
83 0x00000001, 0xfffffffe, 0x00000000, 0xffffffff
84 };
85 static const struct PatternData walkingInvOnes = {
86 "walkingInvOnes",
87 walkingInvOnes_data,
88 (sizeof walkingInvOnes_data / sizeof walkingInvOnes_data[0]) - 1,
89 {2, 2, 5, 5}
90 };
91
92 static unsigned int walkingZeros_data[] = {
93 0xfffffffe, 0xfffffffd, 0xfffffffb, 0xfffffff7,
94 0xffffffef, 0xffffffdf, 0xffffffbf, 0xffffff7f,
95 0xfffffeff, 0xfffffdff, 0xfffffbff, 0xfffff7ff,
96 0xffffefff, 0xffffdfff, 0xffffbfff, 0xffff7fff,
97 0xfffeffff, 0xfffdffff, 0xfffbffff, 0xfff7ffff,
98 0xffefffff, 0xffdfffff, 0xffbfffff, 0xff7fffff,
99 0xfeffffff, 0xfdffffff, 0xfbffffff, 0xf7ffffff,
100 0xefffffff, 0xdfffffff, 0xbfffffff, 0x7fffffff,
101 0xbfffffff, 0xdfffffff, 0xefffffff, 0xf7ffffff,
102 0xfbffffff, 0xfdffffff, 0xfeffffff, 0xff7fffff,
103 0xffbfffff, 0xffdfffff, 0xffefffff, 0xfff7ffff,
104 0xfffbffff, 0xfffdffff, 0xfffeffff, 0xffff7fff,
105 0xffffbfff, 0xffffdfff, 0xffffefff, 0xfffff7ff,
106 0xfffffbff, 0xfffffdff, 0xfffffeff, 0xffffff7f,
107 0xffffffbf, 0xffffffdf, 0xffffffef, 0xfffffff7,
108 0xfffffffb, 0xfffffffd, 0xfffffffe, 0xffffffff
109 };
110 static const struct PatternData walkingZeros = {
111 "walkingZeros",
112 walkingZeros_data,
113 (sizeof walkingZeros_data / sizeof walkingZeros_data[0]) - 1,
114 {1, 1, 2, 1}
115 };
116
117 static unsigned int OneZero_data[] = { 0x00000000, 0xffffffff};
118 static const struct PatternData OneZero = {
119 "OneZero",
120 OneZero_data,
121 (sizeof OneZero_data / sizeof OneZero_data[0]) - 1,
122 {5, 5, 15, 5}
123 };
124
125 static unsigned int JustZero_data[] = { 0x00000000, 0x00000000};
126 static const struct PatternData JustZero = {
127 "JustZero",
128 JustZero_data,
129 (sizeof JustZero_data / sizeof JustZero_data[0]) - 1,
130 {2, 0, 0, 0}
131 };
132
133 static unsigned int JustOne_data[] = { 0xffffffff, 0xffffffff};
134 static const struct PatternData JustOne = {
135 "JustOne",
136 JustOne_data,
137 (sizeof JustOne_data / sizeof JustOne_data[0]) - 1,
138 {2, 0, 0, 0}
139 };
140
141 static unsigned int JustFive_data[] = { 0x55555555, 0x55555555};
142 static const struct PatternData JustFive = {
143 "JustFive",
144 JustFive_data,
145 (sizeof JustFive_data / sizeof JustFive_data[0]) - 1,
146 {2, 0, 0, 0}
147 };
148
149 static unsigned int JustA_data[] = { 0xaaaaaaaa, 0xaaaaaaaa};
150 static const struct PatternData JustA = {
151 "JustA",
152 JustA_data,
153 (sizeof JustA_data / sizeof JustA_data[0]) - 1,
154 {2, 0, 0, 0}
155 };
156
157 static unsigned int FiveA_data[] = { 0x55555555, 0xaaaaaaaa};
158 static const struct PatternData FiveA = {
159 "FiveA",
160 FiveA_data,
161 (sizeof FiveA_data / sizeof FiveA_data[0]) - 1,
162 {1, 1, 1, 1}
163 };
164
165 static unsigned int FiveA8_data[] = {
166 0x5aa5a55a, 0xa55a5aa5, 0xa55a5aa5, 0x5aa5a55a
167 };
168 static const struct PatternData FiveA8 = {
169 "FiveA8",
170 FiveA8_data,
171 (sizeof FiveA8_data / sizeof FiveA8_data[0]) - 1,
172 {1, 1, 1, 1}
173 };
174
175 static unsigned int Long8b10b_data[] = { 0x16161616, 0x16161616 };
176 static const struct PatternData Long8b10b = {
177 "Long8b10b",
178 Long8b10b_data,
179 (sizeof Long8b10b_data / sizeof Long8b10b_data[0]) - 1,
180 {2, 0, 0, 0}
181 };
182
183 static unsigned int Short8b10b_data[] = { 0xb5b5b5b5, 0xb5b5b5b5 };
184 static const struct PatternData Short8b10b = {
185 "Short8b10b",
186 Short8b10b_data,
187 (sizeof Short8b10b_data / sizeof Short8b10b_data[0]) - 1,
188 {2, 0, 0, 0}
189 };
190
191 static unsigned int Checker8b10b_data[] = { 0xb5b5b5b5, 0x4a4a4a4a };
192 static const struct PatternData Checker8b10b = {
193 "Checker8b10b",
194 Checker8b10b_data,
195 (sizeof Checker8b10b_data / sizeof Checker8b10b_data[0]) - 1,
196 {1, 0, 0, 1}
197 };
198
199 static unsigned int Five7_data[] = { 0x55555557, 0x55575555 };
200 static const struct PatternData Five7 = {
201 "Five7",
202 Five7_data,
203 (sizeof Five7_data / sizeof Five7_data[0]) - 1,
204 {0, 2, 0, 0}
205 };
206
207 static unsigned int Zero2fd_data[] = { 0x00020002, 0xfffdfffd };
208 static const struct PatternData Zero2fd = {
209 "Zero2fd",
210 Zero2fd_data,
211 (sizeof Zero2fd_data / sizeof Zero2fd_data[0]) - 1,
212 {0, 2, 0, 0}
213 };
214
215 // Extern array of useable patterns.
216 static const struct PatternData pattern_array[] = {
217 walkingOnes,
218 walkingInvOnes,
219 walkingZeros,
220 OneZero,
221 JustZero,
222 JustOne,
223 JustFive,
224 JustA,
225 FiveA,
226 FiveA8,
227 Long8b10b,
228 Short8b10b,
229 Checker8b10b,
230 Five7,
231 Zero2fd,
232 };
233 static const int pattern_array_size =
234 sizeof pattern_array / sizeof pattern_array[0];
235
Pattern()236 Pattern::Pattern() {
237 crc_ = NULL;
238 }
239
~Pattern()240 Pattern::~Pattern() {
241 if (crc_ != NULL) {
242 delete crc_;
243 }
244 }
245
246 // Calculate CRC for this pattern. This must match
247 // the CRC calculation in worker.cc.
CalculateCrc()248 int Pattern::CalculateCrc() {
249 // TODO(johnhuang):
250 // Consider refactoring to the form:
251 // while (i < count) AdlerInc(uint64, uint64, AdlerChecksum*)
252 uint64 a1 = 1;
253 uint64 a2 = 1;
254 uint64 b1 = 0;
255 uint64 b2 = 0;
256
257 // checksum is calculated using only the first 4096 bytes of data.
258 int i = 0;
259 int blocksize = 4096;
260 int count = blocksize / sizeof i;
261 while (i < count) {
262 a1 += pattern(i);
263 b1 += a1;
264 i++;
265 a1 += pattern(i);
266 b1 += a1;
267 i++;
268
269 a2 += pattern(i);
270 b2 += a2;
271 i++;
272 a2 += pattern(i);
273 b2 += a2;
274 i++;
275 }
276 if (crc_ != NULL) {
277 delete crc_;
278 }
279 crc_ = new AdlerChecksum();
280 crc_->Set(a1, a2, b1, b2);
281 return 0;
282 }
283
284 // Initialize pattern's CRC.
Initialize(const struct PatternData & pattern_init,int buswidth,bool invert,int weight)285 int Pattern::Initialize(const struct PatternData &pattern_init,
286 int buswidth,
287 bool invert,
288 int weight) {
289 int result = 1;
290
291 pattern_ = &pattern_init;
292 busshift_ = 2;
293 inverse_ = invert;
294 weight_ = weight;
295
296 name_.clear();
297 name_.append(pattern_->name);
298
299 if (invert)
300 name_.append("~");
301
302 if (buswidth == 32) {
303 name_.append("32");
304 busshift_ = 0;
305 } else if (buswidth == 64) {
306 name_.append("64");
307 busshift_ = 1;
308 } else if (buswidth == 128) {
309 name_.append("128");
310 busshift_ = 2;
311 } else if (buswidth == 256) {
312 name_.append("256");
313 busshift_ = 3;
314 } else {
315 logprintf(0, "Process Error: Confused by bus width %d\n",
316 buswidth);
317 name_.append("Broken");
318 result = 0;
319 }
320
321 CalculateCrc();
322
323 return result;
324 }
325
326
PatternList()327 PatternList::PatternList() {
328 size_= 0;
329 initialized_ = 0;
330 }
331
~PatternList()332 PatternList::~PatternList() {
333 if (initialized_) {
334 Destroy();
335 }
336 }
337
338 // Fill in the class with references to the static data patterns
Initialize()339 int PatternList::Initialize() {
340 int patterncount = 0;
341 int weightcount = 0;
342
343 patterns_.resize(pattern_array_size * 8);
344 for (int i = 0; i < pattern_array_size; i++) {
345 // Non inverted.
346 weightcount += pattern_array[i].weight[0];
347 patterns_[patterncount++].Initialize(pattern_array[i], 32, false,
348 pattern_array[i].weight[0]);
349 weightcount += pattern_array[i].weight[1];
350 patterns_[patterncount++].Initialize(pattern_array[i], 64, false,
351 pattern_array[i].weight[1]);
352 weightcount += pattern_array[i].weight[2];
353 patterns_[patterncount++].Initialize(pattern_array[i], 128, false,
354 pattern_array[i].weight[2]);
355 weightcount += pattern_array[i].weight[3];
356 patterns_[patterncount++].Initialize(pattern_array[i], 256, false,
357 pattern_array[i].weight[3]);
358
359 // Inverted.
360 weightcount += pattern_array[i].weight[0];
361 patterns_[patterncount++].Initialize(pattern_array[i], 32, true,
362 pattern_array[i].weight[0]);
363 weightcount += pattern_array[i].weight[1];
364 patterns_[patterncount++].Initialize(pattern_array[i], 64, true,
365 pattern_array[i].weight[1]);
366 weightcount += pattern_array[i].weight[2];
367 patterns_[patterncount++].Initialize(pattern_array[i], 128, true,
368 pattern_array[i].weight[2]);
369 weightcount += pattern_array[i].weight[3];
370 patterns_[patterncount++].Initialize(pattern_array[i], 256, true,
371 pattern_array[i].weight[3]);
372 }
373 size_ = patterncount;
374 weightcount_ = weightcount;
375 initialized_ = 1;
376
377 logprintf(12, "Log: initialized %d data patterns\n", size_);
378
379 return 1;
380 }
381
382 // Free the stuff.
Destroy()383 int PatternList::Destroy() {
384 if (!initialized_)
385 return 0;
386
387 patterns_.clear();
388 size_ = 0;
389 initialized_ = 0;
390
391 return 1;
392 }
393
394 // Return pattern numbered "i"
GetPattern(int i)395 Pattern *PatternList::GetPattern(int i) {
396 if (static_cast<unsigned int>(i) < size_) {
397 return &patterns_[i];
398 }
399
400 logprintf(0, "Process Error: Out of bounds pattern access\n");
401 return 0;
402 }
403
404 // Return a randomly selected pattern.
GetRandomPattern()405 Pattern *PatternList::GetRandomPattern() {
406 unsigned int target = random();
407 target = target % weightcount_;
408
409 unsigned int i = 0;
410 unsigned int sum = 0;
411 while (target > sum) {
412 sum += patterns_[i].weight();
413 i++;
414 }
415 if (i < size_) {
416 return &patterns_[i];
417 }
418
419 logprintf(0, "Process Error: Out of bounds pattern access\n");
420 return 0;
421 }
422