// Copyright 2006 Google Inc. All Rights Reserved. // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // pattern.cc : library of stressful data patterns #include <sys/types.h> // This file must work with autoconf on its public version, // so these includes are correct. #include "pattern.h" #include "sattypes.h" // Static data patterns. static unsigned int walkingOnes_data[] = { 0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010, 0x00000020, 0x00000040, 0x00000080, 0x00000100, 0x00000200, 0x00000400, 0x00000800, 0x00001000, 0x00002000, 0x00004000, 0x00008000, 0x00010000, 0x00020000, 0x00040000, 0x00080000, 0x00100000, 0x00200000, 0x00400000, 0x00800000, 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000, 0x40000000, 0x20000000, 0x10000000, 0x08000000, 0x04000000, 0x02000000, 0x01000000, 0x00800000, 0x00400000, 0x00200000, 0x00100000, 0x00080000, 0x00040000, 0x00020000, 0x00010000, 0x00008000, 0x00004000, 0x00002000, 0x00001000, 0x00000800, 0x00000400, 0x00000200, 0x00000100, 0x00000080, 0x00000040, 0x00000020, 0x00000010, 0x00000008, 0x00000004, 0x00000002, 0x00000001, 0x00000000 }; static const struct PatternData walkingOnes = { "walkingOnes", walkingOnes_data, (sizeof walkingOnes_data / sizeof walkingOnes_data[0]) - 1, {1, 1, 2, 1} // Weight for choosing 32/64/128/256 bit wide of this pattern }; static unsigned int walkingInvOnes_data[] = { 0x00000001, 0xfffffffe, 0x00000002, 0xfffffffd, 0x00000004, 0xfffffffb, 0x00000008, 0xfffffff7, 0x00000010, 0xffffffef, 0x00000020, 0xffffffdf, 0x00000040, 0xffffffbf, 0x00000080, 0xffffff7f, 0x00000100, 0xfffffeff, 0x00000200, 0xfffffdff, 0x00000400, 0xfffffbff, 0x00000800, 0xfffff7ff, 0x00001000, 0xffffefff, 0x00002000, 0xffffdfff, 0x00004000, 0xffffbfff, 0x00008000, 0xffff7fff, 0x00010000, 0xfffeffff, 0x00020000, 0xfffdffff, 0x00040000, 0xfffbffff, 0x00080000, 0xfff7ffff, 0x00100000, 0xffefffff, 0x00200000, 0xffdfffff, 0x00400000, 0xffbfffff, 0x00800000, 0xff7fffff, 0x01000000, 0xfeffffff, 0x02000000, 0xfdffffff, 0x04000000, 0xfbffffff, 0x08000000, 0xf7ffffff, 0x10000000, 0xefffffff, 0x20000000, 0xdfffffff, 0x40000000, 0xbfffffff, 0x80000000, 0x7fffffff, 0x40000000, 0xbfffffff, 0x20000000, 0xdfffffff, 0x10000000, 0xefffffff, 0x08000000, 0xf7ffffff, 0x04000000, 0xfbffffff, 0x02000000, 0xfdffffff, 0x01000000, 0xfeffffff, 0x00800000, 0xff7fffff, 0x00400000, 0xffbfffff, 0x00200000, 0xffdfffff, 0x00100000, 0xffefffff, 0x00080000, 0xfff7ffff, 0x00040000, 0xfffbffff, 0x00020000, 0xfffdffff, 0x00010000, 0xfffeffff, 0x00008000, 0xffff7fff, 0x00004000, 0xffffbfff, 0x00002000, 0xffffdfff, 0x00001000, 0xffffefff, 0x00000800, 0xfffff7ff, 0x00000400, 0xfffffbff, 0x00000200, 0xfffffdff, 0x00000100, 0xfffffeff, 0x00000080, 0xffffff7f, 0x00000040, 0xffffffbf, 0x00000020, 0xffffffdf, 0x00000010, 0xffffffef, 0x00000008, 0xfffffff7, 0x00000004, 0xfffffffb, 0x00000002, 0xfffffffd, 0x00000001, 0xfffffffe, 0x00000000, 0xffffffff }; static const struct PatternData walkingInvOnes = { "walkingInvOnes", walkingInvOnes_data, (sizeof walkingInvOnes_data / sizeof walkingInvOnes_data[0]) - 1, {2, 2, 5, 5} }; static unsigned int walkingZeros_data[] = { 0xfffffffe, 0xfffffffd, 0xfffffffb, 0xfffffff7, 0xffffffef, 0xffffffdf, 0xffffffbf, 0xffffff7f, 0xfffffeff, 0xfffffdff, 0xfffffbff, 0xfffff7ff, 0xffffefff, 0xffffdfff, 0xffffbfff, 0xffff7fff, 0xfffeffff, 0xfffdffff, 0xfffbffff, 0xfff7ffff, 0xffefffff, 0xffdfffff, 0xffbfffff, 0xff7fffff, 0xfeffffff, 0xfdffffff, 0xfbffffff, 0xf7ffffff, 0xefffffff, 0xdfffffff, 0xbfffffff, 0x7fffffff, 0xbfffffff, 0xdfffffff, 0xefffffff, 0xf7ffffff, 0xfbffffff, 0xfdffffff, 0xfeffffff, 0xff7fffff, 0xffbfffff, 0xffdfffff, 0xffefffff, 0xfff7ffff, 0xfffbffff, 0xfffdffff, 0xfffeffff, 0xffff7fff, 0xffffbfff, 0xffffdfff, 0xffffefff, 0xfffff7ff, 0xfffffbff, 0xfffffdff, 0xfffffeff, 0xffffff7f, 0xffffffbf, 0xffffffdf, 0xffffffef, 0xfffffff7, 0xfffffffb, 0xfffffffd, 0xfffffffe, 0xffffffff }; static const struct PatternData walkingZeros = { "walkingZeros", walkingZeros_data, (sizeof walkingZeros_data / sizeof walkingZeros_data[0]) - 1, {1, 1, 2, 1} }; static unsigned int OneZero_data[] = { 0x00000000, 0xffffffff}; static const struct PatternData OneZero = { "OneZero", OneZero_data, (sizeof OneZero_data / sizeof OneZero_data[0]) - 1, {5, 5, 15, 5} }; static unsigned int JustZero_data[] = { 0x00000000, 0x00000000}; static const struct PatternData JustZero = { "JustZero", JustZero_data, (sizeof JustZero_data / sizeof JustZero_data[0]) - 1, {2, 0, 0, 0} }; static unsigned int JustOne_data[] = { 0xffffffff, 0xffffffff}; static const struct PatternData JustOne = { "JustOne", JustOne_data, (sizeof JustOne_data / sizeof JustOne_data[0]) - 1, {2, 0, 0, 0} }; static unsigned int JustFive_data[] = { 0x55555555, 0x55555555}; static const struct PatternData JustFive = { "JustFive", JustFive_data, (sizeof JustFive_data / sizeof JustFive_data[0]) - 1, {2, 0, 0, 0} }; static unsigned int JustA_data[] = { 0xaaaaaaaa, 0xaaaaaaaa}; static const struct PatternData JustA = { "JustA", JustA_data, (sizeof JustA_data / sizeof JustA_data[0]) - 1, {2, 0, 0, 0} }; static unsigned int FiveA_data[] = { 0x55555555, 0xaaaaaaaa}; static const struct PatternData FiveA = { "FiveA", FiveA_data, (sizeof FiveA_data / sizeof FiveA_data[0]) - 1, {1, 1, 1, 1} }; static unsigned int FiveA8_data[] = { 0x5aa5a55a, 0xa55a5aa5, 0xa55a5aa5, 0x5aa5a55a }; static const struct PatternData FiveA8 = { "FiveA8", FiveA8_data, (sizeof FiveA8_data / sizeof FiveA8_data[0]) - 1, {1, 1, 1, 1} }; static unsigned int Long8b10b_data[] = { 0x16161616, 0x16161616 }; static const struct PatternData Long8b10b = { "Long8b10b", Long8b10b_data, (sizeof Long8b10b_data / sizeof Long8b10b_data[0]) - 1, {2, 0, 0, 0} }; static unsigned int Short8b10b_data[] = { 0xb5b5b5b5, 0xb5b5b5b5 }; static const struct PatternData Short8b10b = { "Short8b10b", Short8b10b_data, (sizeof Short8b10b_data / sizeof Short8b10b_data[0]) - 1, {2, 0, 0, 0} }; static unsigned int Checker8b10b_data[] = { 0xb5b5b5b5, 0x4a4a4a4a }; static const struct PatternData Checker8b10b = { "Checker8b10b", Checker8b10b_data, (sizeof Checker8b10b_data / sizeof Checker8b10b_data[0]) - 1, {1, 0, 0, 1} }; static unsigned int Five7_data[] = { 0x55555557, 0x55575555 }; static const struct PatternData Five7 = { "Five7", Five7_data, (sizeof Five7_data / sizeof Five7_data[0]) - 1, {0, 2, 0, 0} }; static unsigned int Zero2fd_data[] = { 0x00020002, 0xfffdfffd }; static const struct PatternData Zero2fd = { "Zero2fd", Zero2fd_data, (sizeof Zero2fd_data / sizeof Zero2fd_data[0]) - 1, {0, 2, 0, 0} }; // Extern array of useable patterns. static const struct PatternData pattern_array[] = { walkingOnes, walkingInvOnes, walkingZeros, OneZero, JustZero, JustOne, JustFive, JustA, FiveA, FiveA8, Long8b10b, Short8b10b, Checker8b10b, Five7, Zero2fd, }; static const int pattern_array_size = sizeof pattern_array / sizeof pattern_array[0]; Pattern::Pattern() { crc_ = NULL; } Pattern::~Pattern() { if (crc_ != NULL) { delete crc_; } } // Calculate CRC for this pattern. This must match // the CRC calculation in worker.cc. int Pattern::CalculateCrc() { // TODO(johnhuang): // Consider refactoring to the form: // while (i < count) AdlerInc(uint64, uint64, AdlerChecksum*) uint64 a1 = 1; uint64 a2 = 1; uint64 b1 = 0; uint64 b2 = 0; // checksum is calculated using only the first 4096 bytes of data. int i = 0; int blocksize = 4096; int count = blocksize / sizeof i; while (i < count) { a1 += pattern(i); b1 += a1; i++; a1 += pattern(i); b1 += a1; i++; a2 += pattern(i); b2 += a2; i++; a2 += pattern(i); b2 += a2; i++; } if (crc_ != NULL) { delete crc_; } crc_ = new AdlerChecksum(); crc_->Set(a1, a2, b1, b2); return 0; } // Initialize pattern's CRC. int Pattern::Initialize(const struct PatternData &pattern_init, int buswidth, bool invert, int weight) { int result = 1; pattern_ = &pattern_init; busshift_ = 2; inverse_ = invert; weight_ = weight; name_.clear(); name_.append(pattern_->name); if (invert) name_.append("~"); if (buswidth == 32) { name_.append("32"); busshift_ = 0; } else if (buswidth == 64) { name_.append("64"); busshift_ = 1; } else if (buswidth == 128) { name_.append("128"); busshift_ = 2; } else if (buswidth == 256) { name_.append("256"); busshift_ = 3; } else { logprintf(0, "Process Error: Confused by bus width %d\n", buswidth); name_.append("Broken"); result = 0; } CalculateCrc(); return result; } PatternList::PatternList() { size_= 0; initialized_ = 0; } PatternList::~PatternList() { if (initialized_) { Destroy(); } } // Fill in the class with references to the static data patterns int PatternList::Initialize() { int patterncount = 0; int weightcount = 0; patterns_.resize(pattern_array_size * 8); for (int i = 0; i < pattern_array_size; i++) { // Non inverted. weightcount += pattern_array[i].weight[0]; patterns_[patterncount++].Initialize(pattern_array[i], 32, false, pattern_array[i].weight[0]); weightcount += pattern_array[i].weight[1]; patterns_[patterncount++].Initialize(pattern_array[i], 64, false, pattern_array[i].weight[1]); weightcount += pattern_array[i].weight[2]; patterns_[patterncount++].Initialize(pattern_array[i], 128, false, pattern_array[i].weight[2]); weightcount += pattern_array[i].weight[3]; patterns_[patterncount++].Initialize(pattern_array[i], 256, false, pattern_array[i].weight[3]); // Inverted. weightcount += pattern_array[i].weight[0]; patterns_[patterncount++].Initialize(pattern_array[i], 32, true, pattern_array[i].weight[0]); weightcount += pattern_array[i].weight[1]; patterns_[patterncount++].Initialize(pattern_array[i], 64, true, pattern_array[i].weight[1]); weightcount += pattern_array[i].weight[2]; patterns_[patterncount++].Initialize(pattern_array[i], 128, true, pattern_array[i].weight[2]); weightcount += pattern_array[i].weight[3]; patterns_[patterncount++].Initialize(pattern_array[i], 256, true, pattern_array[i].weight[3]); } size_ = patterncount; weightcount_ = weightcount; initialized_ = 1; logprintf(12, "Log: initialized %d data patterns\n", size_); return 1; } // Free the stuff. int PatternList::Destroy() { if (!initialized_) return 0; patterns_.clear(); size_ = 0; initialized_ = 0; return 1; } // Return pattern numbered "i" Pattern *PatternList::GetPattern(int i) { if (static_cast<unsigned int>(i) < size_) { return &patterns_[i]; } logprintf(0, "Process Error: Out of bounds pattern access\n"); return 0; } // Return a randomly selected pattern. Pattern *PatternList::GetRandomPattern() { unsigned int target = random(); target = target % weightcount_; unsigned int i = 0; unsigned int sum = 0; while (target > sum) { sum += patterns_[i].weight(); i++; } if (i < size_) { return &patterns_[i]; } logprintf(0, "Process Error: Out of bounds pattern access\n"); return 0; }