diff --git a/src/test_objects/SConscript b/src/test_objects/SConscript new file mode 100644 index 0000000000..6d1d1ec2d1 --- /dev/null +++ b/src/test_objects/SConscript @@ -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') diff --git a/src/test_objects/StatTester.py b/src/test_objects/StatTester.py new file mode 100644 index 0000000000..a413b47764 --- /dev/null +++ b/src/test_objects/StatTester.py @@ -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.") diff --git a/src/test_objects/stat_tester.cc b/src/test_objects/stat_tester.cc new file mode 100644 index 0000000000..bf90993287 --- /dev/null +++ b/src/test_objects/stat_tester.cc @@ -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 ¶ms +) : statistics::Group(parent), + scalar(this, + params.name.c_str(), + statistics::units::Count::get(), + params.description.c_str() + ) +{ +} + +} // namespace gem5 diff --git a/src/test_objects/stat_tester.hh b/src/test_objects/stat_tester.hh new file mode 100644 index 0000000000..d9e3371997 --- /dev/null +++ b/src/test_objects/stat_tester.hh @@ -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 ¶ms + ); + statistics::Scalar scalar; + } stats; +}; + +} // namespace gem5 + +#endif // __STAT_TESTER_HH__ diff --git a/tests/gem5/stats/README.md b/tests/gem5/stats/README.md index c55600bed1..2c721f5a34 100644 --- a/tests/gem5/stats/README.md +++ b/tests/gem5/stats/README.md @@ -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] diff --git a/tests/gem5/stats/configs/simstat_output_check.py b/tests/gem5/stats/configs/simstat_output_check.py new file mode 100644 index 0000000000..4cbe2d0ca7 --- /dev/null +++ b/tests/gem5/stats/configs/simstat_output_check.py @@ -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) diff --git a/tests/gem5/stats/test_simstats_output.py b/tests/gem5/stats/test_simstats_output.py new file mode 100644 index 0000000000..c7393ebf2b --- /dev/null +++ b/tests/gem5/stats/test_simstats_output.py @@ -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, +)