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