stdlib,tests: Add StatTester SimObject and Scalar tests (#973)

This SimObject can be used to quickly test the statistics are
functioning correctly. The SimObject schedules a single event which sets
the statistics to values dependent on the SimObject params.

With this commit the "Scalar" stats have a StatTester subclass that can
be used for testing. More can be added as required.

Tests are included to check our Scalar SimStat functionality.
This commit is contained in:
Bobby R. Bruce
2024-04-04 19:12:44 -07:00
committed by GitHub
11 changed files with 530 additions and 2 deletions

View File

@@ -7,3 +7,4 @@ USE_POWER_ISA=y
USE_RISCV_ISA=y
USE_SPARC_ISA=y
USE_X86_ISA=y
USE_TEST_OBJECTS=y

View File

@@ -51,3 +51,4 @@ rsource "arch/Kconfig"
rsource "cpu/Kconfig"
rsource "systemc/Kconfig"
rsource "gpu-compute/Kconfig"
rsource "test_objects/Kconfig"

29
src/test_objects/Kconfig Normal file
View File

@@ -0,0 +1,29 @@
# Copyright (c) 2024 The Regents of the University of California
# 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.
config USE_TEST_OBJECTS
bool "SimObjects used for testing the gem5 simulator"
default n

View File

@@ -0,0 +1,31 @@
# Copyright (c) 2024 The Regents of the University of California
# 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.
Import ("*")
if env['CONF']['USE_TEST_OBJECTS']:
SimObject('StatTester.py', sim_objects=['StatTester', 'ScalarStatTester'])
Source('stat_tester.cc')

View File

@@ -0,0 +1,46 @@
# Copyright (c) 2024 The Regents of the University of California
# 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.
from m5.params import *
from m5.SimObject import SimObject
class StatTester(SimObject):
type = "StatTester"
abstract = True
cxx_header = "test_objects/stat_tester.hh"
cxx_class = "gem5::StatTester"
name = Param.String("stat", "Name of the stat.")
description = Param.String("", "The descriptionof the stat.")
class ScalarStatTester(StatTester):
type = "ScalarStatTester"
cxx_header = "test_objects/stat_tester.hh"
cxx_class = "gem5::ScalarStatTester"
value = Param.Float("The scalar stat's value.")

View File

@@ -0,0 +1,54 @@
/*
* Copyright (c) 2024 The Regents of the University of California
* 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 "test_objects/stat_tester.hh"
#include "base/stats/group.hh"
namespace gem5
{
void
ScalarStatTester::setStats()
{
stats.scalar = params.value;
}
ScalarStatTester::ScalarStatTesterStats::ScalarStatTesterStats(
statistics::Group *parent,
const ScalarStatTesterParams &params
) : statistics::Group(parent),
scalar(this,
params.name.c_str(),
statistics::units::Count::get(),
params.description.c_str()
)
{
}
} // namespace gem5

View File

@@ -0,0 +1,119 @@
/*
* Copyright (c) 2024 The Regents of the University of California
* 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.
*/
#ifndef __STAT_TESTER_HH__
#define __STAT_TESTER_HH__
#include "base/statistics.hh"
#include "params/ScalarStatTester.hh"
#include "params/StatTester.hh"
#include "sim/sim_object.hh"
namespace gem5
{
/**
* This classes are used to test the stats system from setting through to
* output. The value of the stats are set via the parameters and when
* included in a simulation will create these stats and update them at Tick
* zero.
*
* Example usage
* -------------
*
* import m5
* from m5.objects import (
* Root,
* ScalarStatTester,
* )
*
* stat_tester = ScalarStatTester()
*
* stat_tester.value = 42
* stat_tester.name = "example"
* root = Root(full_system=False)
* root.stat_tester = stat_tester
*
* m5.instantiate()
* m5.simulate()
*
* When the above is run, the m5out/stats.txt file will contain the
* following:
*
* ---------- Begin Simulation Statistics ----------
* simSeconds 18446744.073710
* simTicks 18446744073709551616
* finalTick 18446744073709551616
* simFreq 1000000000000
* hostSeconds 0.00
* hostTickRate 101355736668733798612992
* hostMemory 403847696
* stat_tester.example 42
* ---------- End Simulation Statistics ----------
*/
class StatTester : public SimObject
{
private:
EventFunctionWrapper event;
public:
StatTester(const StatTesterParams &p) :
SimObject(p),
event([this]{ setStats(); }, name() + ".event")
{}
void startup() override { schedule(event, curTick()); }
protected:
virtual void setStats(){}
};
class ScalarStatTester : public StatTester
{
private:
ScalarStatTesterParams params;
public:
ScalarStatTester(const ScalarStatTesterParams &p) :
StatTester(p), params(p), stats(this, p) {}
protected:
void setStats() override;
struct ScalarStatTesterStats : public statistics::Group
{
ScalarStatTesterStats(
statistics::Group *parent,
const ScalarStatTesterParams &params
);
statistics::Scalar scalar;
} stats;
};
} // namespace gem5
#endif // __STAT_TESTER_HH__

View File

@@ -199,6 +199,24 @@ class SConsFixture(UniqueFixture):
log.test_log, setconfig_command, time=None, stderr=sys.stderr
)
setconfig_add_test_obj_command = [
"scons",
"-C",
self.directory,
"--ignore-style",
"--no-compress-debug",
"setconfig",
self.target_dir,
"USE_TEST_OBJECTS=y",
]
log_call(
log.test_log,
setconfig_add_test_obj_command,
time=None,
stderr=sys.stderr,
)
command = [
"scons",
"-C",

View File

@@ -1,7 +1,11 @@
# Stats
This test runs an SE simulation with the hdf5 stats and checks that the simulation succeeds and the stats file exists.
To run these tests by themselves, you can run the following command in the tests directory:
These test ensure the stats are output correctly.
1. "test_hdf5" - Test hdf5 output. Runs a simulation and ensures the hdf5
output exists.
2. "test_simstats_output" - Tests the SimStat python module is parsing and
outputting the stats correctly.
```bash
./main.py run gem5/stats --length=[length]

View File

@@ -0,0 +1,110 @@
# Copyright (c) 2024 The Regents of the University of California
# 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.
import argparse
import sys
from typing import Union
import m5
from m5.objects import (
Root,
ScalarStatTester,
)
from m5.stats.gem5stats import get_simstat
"""This script is used for checking that statistics set in the simulation are
correctly parsed through to the python SimStats. This script sets the
statistics using the "StatTester" simobjects and ensures verifies correctness
against the expected JSON output and that produced by the SimStats module.
"""
parser = argparse.ArgumentParser(description="Tests the output of a SimStat.")
subparsers = parser.add_subparsers(
dest="statistic", help="SimStats statistic to test", required=True
)
scalar_parser = subparsers.add_parser(
"scalar", help="Test a scalar statistic."
)
scalar_parser.add_argument(
"value", type=float, help="The value of the scalar statistic."
)
scalar_parser.add_argument(
"--name",
type=str,
default="scalar",
required=False,
help="The name of the scalar statistic.",
)
scalar_parser.add_argument(
"--description",
type=str,
default="",
required=False,
help="The description of the scalar statistic.",
)
args = parser.parse_args()
expected_output = None
stat_tester = None
if args.statistic == "scalar":
stat_tester = ScalarStatTester()
stat_tester.name = args.name
stat_tester.description = args.description
stat_tester.value = args.value
expected_output = {
"type": "Group",
"time_conversion": None,
args.name: {
"value": args.value,
"type": "Scalar",
"unit": "Count",
"description": args.description,
"datatype": "f64",
},
}
assert stat_tester is not None
assert expected_output is not None
root = Root(full_system=False, system=stat_tester)
m5.instantiate()
m5.simulate()
simstats = get_simstat(stat_tester)
output = simstats.to_json()["system"]
if output != expected_output:
print("Output statistics do not match expected:", file=sys.stderr)
print("", file=sys.stderr)
print("Expected:", file=sys.stderr)
print(expected_output, file=sys.stderr)
print("", file=sys.stderr)
print("Actual:", file=sys.stderr)
print(output, file=sys.stderr)
sys.exit(1)

View File

@@ -0,0 +1,115 @@
# Copyright (c) 2024 The Regents of the University of California
# 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.
from testlib import *
gem5_verify_config(
name="simstat-scaler-int-test",
fixtures=(),
verifiers=[],
config=joinpath(
config.base_dir,
"tests",
"gem5",
"stats",
"configs",
"simstat_output_check.py",
),
config_args=[
"scalar",
"42",
"--name",
"scalar_test",
"--description",
"A scalar statistic with a int value",
],
valid_isas=(constants.all_compiled_tag,),
length=constants.quick_tag,
)
gem5_verify_config(
name="simstat-scaler-int-zero-test",
fixtures=(),
verifiers=[],
config=joinpath(
config.base_dir,
"tests",
"gem5",
"stats",
"configs",
"simstat_output_check.py",
),
config_args=[
"scalar",
"0",
],
valid_isas=(constants.all_compiled_tag,),
length=constants.quick_tag,
)
gem5_verify_config(
name="simstat-scaler-int-negative-test",
fixtures=(),
verifiers=[],
config=joinpath(
config.base_dir,
"tests",
"gem5",
"stats",
"configs",
"simstat_output_check.py",
),
config_args=[
"scalar",
"-245",
],
valid_isas=(constants.all_compiled_tag,),
length=constants.quick_tag,
)
gem5_verify_config(
name="simstat-scaler-float-test",
fixtures=(),
verifiers=[],
config=joinpath(
config.base_dir,
"tests",
"gem5",
"stats",
"configs",
"simstat_output_check.py",
),
config_args=[
"scalar",
"42.869",
"--name",
"float_test",
"--description",
"A scalar statistic with a float value",
],
valid_isas=(constants.all_compiled_tag,),
length=constants.quick_tag,
)