Force error checking on storage params by imposing it on construction. Change-Id: I66a902cd5a7c809d3ac5be65b406de29fc0acf1c Signed-off-by: Daniel R. Carvalho <odanrc@yahoo.com.br> Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/25426 Tested-by: kokoro <noreply+kokoro@google.com> Reviewed-by: Bobby R. Bruce <bbruce@ucdavis.edu> Maintainer: Bobby R. Bruce <bbruce@ucdavis.edu>
226 lines
6.5 KiB
C++
226 lines
6.5 KiB
C++
/*
|
|
* Copyright (c) 2021 Daniel R. Carvalho
|
|
* Copyright (c) 2019 Arm Limited
|
|
* All rights reserved.
|
|
*
|
|
* The license below extends only to copyright in the software and shall
|
|
* not be construed as granting a license to any other intellectual
|
|
* property including but not limited to intellectual property relating
|
|
* to a hardware implementation of the functionality of the software
|
|
* licensed hereunder. You may use the software subject to the license
|
|
* terms below provided that you ensure that this notice is replicated
|
|
* unmodified and in its entirety in all distributions of the software,
|
|
* modified or unmodified, in source code or in binary form.
|
|
*
|
|
* Copyright (c) 2003-2005 The Regents of The University of Michigan
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are
|
|
* met: redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer;
|
|
* redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution;
|
|
* neither the name of the copyright holders nor the names of its
|
|
* contributors may be used to endorse or promote products derived from
|
|
* this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#include "base/stats/storage.hh"
|
|
|
|
#include <cmath>
|
|
|
|
namespace Stats {
|
|
|
|
void
|
|
DistStor::sample(Counter val, int number)
|
|
{
|
|
assert(bucket_size > 0);
|
|
if (val < min_track)
|
|
underflow += number;
|
|
else if (val > max_track)
|
|
overflow += number;
|
|
else {
|
|
cvec[std::floor((val - min_track) / bucket_size)] += number;
|
|
}
|
|
|
|
if (val < min_val)
|
|
min_val = val;
|
|
|
|
if (val > max_val)
|
|
max_val = val;
|
|
|
|
sum += val * number;
|
|
squares += val * val * number;
|
|
samples += number;
|
|
}
|
|
|
|
void
|
|
HistStor::growOut()
|
|
{
|
|
int size = cvec.size();
|
|
int zero = size / 2; // round down!
|
|
int top_half = zero + (size - zero + 1) / 2; // round up!
|
|
int bottom_half = (size - zero) / 2; // round down!
|
|
|
|
// grow down
|
|
int low_pair = zero - 1;
|
|
for (int i = zero - 1; i >= bottom_half; i--) {
|
|
cvec[i] = cvec[low_pair];
|
|
if (low_pair - 1 >= 0)
|
|
cvec[i] += cvec[low_pair - 1];
|
|
low_pair -= 2;
|
|
}
|
|
assert(low_pair == 0 || low_pair == -1 || low_pair == -2);
|
|
|
|
for (int i = bottom_half - 1; i >= 0; i--)
|
|
cvec[i] = Counter();
|
|
|
|
// grow up
|
|
int high_pair = zero;
|
|
for (int i = zero; i < top_half; i++) {
|
|
cvec[i] = cvec[high_pair];
|
|
if (high_pair + 1 < size)
|
|
cvec[i] += cvec[high_pair + 1];
|
|
high_pair += 2;
|
|
}
|
|
assert(high_pair == size || high_pair == size + 1);
|
|
|
|
for (int i = top_half; i < size; i++)
|
|
cvec[i] = Counter();
|
|
|
|
max_bucket *= 2;
|
|
min_bucket *= 2;
|
|
bucket_size *= 2;
|
|
}
|
|
|
|
void
|
|
HistStor::growDown()
|
|
{
|
|
const int size = cvec.size();
|
|
const int zero = size / 2; // round down!
|
|
const bool even = ((size - 1) % 2) == 0;
|
|
|
|
// Make sure that zero becomes the lower bound of the middle bucket. On
|
|
// an even number of buckets the last bucket does not change its lower
|
|
// bound, therefore it does not need to absorb any other bucket
|
|
int pair = size - 1;
|
|
if (even) {
|
|
pair--;
|
|
}
|
|
for (int i = pair; i >= zero; --i) {
|
|
cvec[i] = cvec[pair];
|
|
if (pair - 1 >= 0)
|
|
cvec[i] += cvec[pair - 1];
|
|
pair -= 2;
|
|
}
|
|
|
|
for (int i = zero - 1; i >= 0; i--)
|
|
cvec[i] = Counter();
|
|
|
|
// Double the range by using the negative of the lower bound of the last
|
|
// bucket as the new lower bound of the first bucket
|
|
min_bucket = -max_bucket;
|
|
|
|
// A special case must be handled when there is an odd number of
|
|
// buckets so that zero is kept as the lower bound of the middle bucket
|
|
if (!even) {
|
|
min_bucket -= bucket_size;
|
|
max_bucket -= bucket_size;
|
|
}
|
|
|
|
// Only update the bucket size once the range has been updated
|
|
bucket_size *= 2;
|
|
}
|
|
|
|
void
|
|
HistStor::growUp()
|
|
{
|
|
int size = cvec.size();
|
|
int half = (size + 1) / 2; // round up!
|
|
|
|
int pair = 0;
|
|
for (int i = 0; i < half; i++) {
|
|
cvec[i] = cvec[pair];
|
|
if (pair + 1 < size)
|
|
cvec[i] += cvec[pair + 1];
|
|
pair += 2;
|
|
}
|
|
assert(pair == size || pair == size + 1);
|
|
|
|
for (int i = half; i < size; i++)
|
|
cvec[i] = Counter();
|
|
|
|
max_bucket *= 2;
|
|
bucket_size *= 2;
|
|
}
|
|
|
|
void
|
|
HistStor::sample(Counter val, int number)
|
|
{
|
|
assert(min_bucket < max_bucket);
|
|
if (val < min_bucket) {
|
|
if (min_bucket == 0)
|
|
growDown();
|
|
|
|
while (val < min_bucket)
|
|
growOut();
|
|
} else if (val >= max_bucket + bucket_size) {
|
|
if (min_bucket == 0) {
|
|
while (val >= max_bucket + bucket_size)
|
|
growUp();
|
|
} else {
|
|
while (val >= max_bucket + bucket_size)
|
|
growOut();
|
|
}
|
|
}
|
|
|
|
assert(bucket_size > 0);
|
|
size_type index =
|
|
(int64_t)std::floor((val - min_bucket) / bucket_size);
|
|
|
|
assert(index < size());
|
|
cvec[index] += number;
|
|
|
|
sum += val * number;
|
|
squares += val * val * number;
|
|
logs += std::log(val) * number;
|
|
samples += number;
|
|
}
|
|
|
|
void
|
|
HistStor::add(HistStor *hs)
|
|
{
|
|
int b_size = hs->size();
|
|
assert(size() == b_size);
|
|
assert(min_bucket == hs->min_bucket);
|
|
|
|
sum += hs->sum;
|
|
logs += hs->logs;
|
|
squares += hs->squares;
|
|
samples += hs->samples;
|
|
|
|
while (bucket_size > hs->bucket_size)
|
|
hs->growUp();
|
|
while (bucket_size < hs->bucket_size)
|
|
growUp();
|
|
|
|
for (uint32_t i = 0; i < b_size; i++)
|
|
cvec[i] += hs->cvec[i];
|
|
}
|
|
|
|
} // namespace Stats
|