// 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;
}