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
26static 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};
44static 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
51static 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};
85static 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
92static 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};
110static 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
117static unsigned int OneZero_data[] =   { 0x00000000, 0xffffffff};
118static 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
125static unsigned int JustZero_data[] =   { 0x00000000, 0x00000000};
126static 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
133static unsigned int JustOne_data[] =   { 0xffffffff, 0xffffffff};
134static 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
141static unsigned int JustFive_data[] =   { 0x55555555, 0x55555555};
142static 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
149static unsigned int JustA_data[] =   { 0xaaaaaaaa, 0xaaaaaaaa};
150static 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
157static unsigned int FiveA_data[] =   { 0x55555555, 0xaaaaaaaa};
158static 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
165static unsigned int FiveA8_data[] =   {
166  0x5aa5a55a, 0xa55a5aa5, 0xa55a5aa5, 0x5aa5a55a
167};
168static 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
175static unsigned int Long8b10b_data[] =   { 0x16161616, 0x16161616 };
176static 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
183static unsigned int Short8b10b_data[] =   { 0xb5b5b5b5, 0xb5b5b5b5 };
184static 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
191static unsigned int Checker8b10b_data[] =   { 0xb5b5b5b5, 0x4a4a4a4a };
192static 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
199static unsigned int Five7_data[] =   { 0x55555557, 0x55575555 };
200static 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
207static unsigned int Zero2fd_data[] =   { 0x00020002, 0xfffdfffd };
208static 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.
216static 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};
233static const int pattern_array_size =
234    sizeof pattern_array / sizeof pattern_array[0];
235
236Pattern::Pattern() {
237  crc_ = NULL;
238}
239
240Pattern::~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.
248int 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.
285int 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
327PatternList::PatternList() {
328  size_= 0;
329  initialized_ = 0;
330}
331
332PatternList::~PatternList() {
333  if (initialized_) {
334    Destroy();
335  }
336}
337
338// Fill in the class with references to the static data patterns
339int 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.
383int 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"
395Pattern *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.
405Pattern *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