110751SAndreas.Sandberg@ARM.com# Copyright (c) 2015 ARM Limited
210751SAndreas.Sandberg@ARM.com# All rights reserved.
310751SAndreas.Sandberg@ARM.com#
410751SAndreas.Sandberg@ARM.com# The license below extends only to copyright in the software and shall
510751SAndreas.Sandberg@ARM.com# not be construed as granting a license to any other intellectual
610751SAndreas.Sandberg@ARM.com# property including but not limited to intellectual property relating
710751SAndreas.Sandberg@ARM.com# to a hardware implementation of the functionality of the software
810751SAndreas.Sandberg@ARM.com# licensed hereunder.  You may use the software subject to the license
910751SAndreas.Sandberg@ARM.com# terms below provided that you ensure that this notice is replicated
1010751SAndreas.Sandberg@ARM.com# unmodified and in its entirety in all distributions of the software,
1110751SAndreas.Sandberg@ARM.com# modified or unmodified, in source code or in binary form.
1210751SAndreas.Sandberg@ARM.com#
1310751SAndreas.Sandberg@ARM.com# Redistribution and use in source and binary forms, with or without
1410751SAndreas.Sandberg@ARM.com# modification, are permitted provided that the following conditions are
1510751SAndreas.Sandberg@ARM.com# met: redistributions of source code must retain the above copyright
1610751SAndreas.Sandberg@ARM.com# notice, this list of conditions and the following disclaimer;
1710751SAndreas.Sandberg@ARM.com# redistributions in binary form must reproduce the above copyright
1810751SAndreas.Sandberg@ARM.com# notice, this list of conditions and the following disclaimer in the
1910751SAndreas.Sandberg@ARM.com# documentation and/or other materials provided with the distribution;
2010751SAndreas.Sandberg@ARM.com# neither the name of the copyright holders nor the names of its
2110751SAndreas.Sandberg@ARM.com# contributors may be used to endorse or promote products derived from
2210751SAndreas.Sandberg@ARM.com# this software without specific prior written permission.
2310751SAndreas.Sandberg@ARM.com#
2410751SAndreas.Sandberg@ARM.com# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2510751SAndreas.Sandberg@ARM.com# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2610751SAndreas.Sandberg@ARM.com# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2710751SAndreas.Sandberg@ARM.com# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2810751SAndreas.Sandberg@ARM.com# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2910751SAndreas.Sandberg@ARM.com# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3010751SAndreas.Sandberg@ARM.com# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3110751SAndreas.Sandberg@ARM.com# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3210751SAndreas.Sandberg@ARM.com# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3310751SAndreas.Sandberg@ARM.com# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3410751SAndreas.Sandberg@ARM.com# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3510751SAndreas.Sandberg@ARM.com#
3610751SAndreas.Sandberg@ARM.com# Authors: Andreas Sandberg
3710751SAndreas.Sandberg@ARM.com
3812575Sgiacomo.travaglini@arm.comfrom __future__ import print_function
3912575Sgiacomo.travaglini@arm.com
4010751SAndreas.Sandberg@ARM.comfrom multiprocessing import Process
4110751SAndreas.Sandberg@ARM.comimport sys
4210751SAndreas.Sandberg@ARM.comimport os
4310751SAndreas.Sandberg@ARM.com
4410751SAndreas.Sandberg@ARM.comimport m5
4510751SAndreas.Sandberg@ARM.com
4610751SAndreas.Sandberg@ARM.com_exit_normal = (
4710751SAndreas.Sandberg@ARM.com    "target called exit()",
4810751SAndreas.Sandberg@ARM.com    "m5_exit instruction encountered",
4910751SAndreas.Sandberg@ARM.com    )
5010751SAndreas.Sandberg@ARM.com
5110751SAndreas.Sandberg@ARM.com_exit_limit = (
5210751SAndreas.Sandberg@ARM.com    "simulate() limit reached",
5310751SAndreas.Sandberg@ARM.com    )
5410751SAndreas.Sandberg@ARM.com
5510751SAndreas.Sandberg@ARM.com_exitcode_done = 0
5610751SAndreas.Sandberg@ARM.com_exitcode_fail = 1
5710751SAndreas.Sandberg@ARM.com_exitcode_checkpoint = 42
5810751SAndreas.Sandberg@ARM.com
5910751SAndreas.Sandberg@ARM.com
6010751SAndreas.Sandberg@ARM.comdef _run_step(name, restore=None, interval=0.5):
6110751SAndreas.Sandberg@ARM.com    """
6210751SAndreas.Sandberg@ARM.com    Instantiate (optionally from a checkpoint if restore is set to the
6310751SAndreas.Sandberg@ARM.com    checkpoitn name) the system and run for interval seconds of
6410751SAndreas.Sandberg@ARM.com    simulated time. At the end of the simulation interval, create a
6510751SAndreas.Sandberg@ARM.com    checkpoint and exit.
6610751SAndreas.Sandberg@ARM.com
6710751SAndreas.Sandberg@ARM.com    As this function is intended to run in its own process using the
6810751SAndreas.Sandberg@ARM.com    multiprocessing framework, the exit is a true call to exit which
6910751SAndreas.Sandberg@ARM.com    terminates the process. Exit codes are used to pass information to
7010751SAndreas.Sandberg@ARM.com    the parent.
7110751SAndreas.Sandberg@ARM.com    """
7210751SAndreas.Sandberg@ARM.com    if restore is not None:
7310751SAndreas.Sandberg@ARM.com        m5.instantiate(restore)
7410751SAndreas.Sandberg@ARM.com    else:
7510751SAndreas.Sandberg@ARM.com        m5.instantiate()
7610751SAndreas.Sandberg@ARM.com
7710751SAndreas.Sandberg@ARM.com    e = m5.simulate(m5.ticks.fromSeconds(interval))
7810751SAndreas.Sandberg@ARM.com    cause = e.getCause()
7910751SAndreas.Sandberg@ARM.com    if cause in _exit_limit:
8010751SAndreas.Sandberg@ARM.com        m5.checkpoint(name)
8110751SAndreas.Sandberg@ARM.com        sys.exit(_exitcode_checkpoint)
8210751SAndreas.Sandberg@ARM.com    elif cause in _exit_normal:
8310751SAndreas.Sandberg@ARM.com        sys.exit(_exitcode_done)
8410751SAndreas.Sandberg@ARM.com    else:
8512575Sgiacomo.travaglini@arm.com        print("Test failed: Unknown exit cause: %s" % cause)
8610751SAndreas.Sandberg@ARM.com        sys.exit(_exitcode_fail)
8710751SAndreas.Sandberg@ARM.com
8810751SAndreas.Sandberg@ARM.comdef run_test(root, interval=0.5, max_checkpoints=5):
8910751SAndreas.Sandberg@ARM.com    """
9010751SAndreas.Sandberg@ARM.com    Run the simulated system for a fixed amount of time and take a
9110751SAndreas.Sandberg@ARM.com    checkpoint, then restore from the same checkpoint and run until
9210751SAndreas.Sandberg@ARM.com    the system calls m5 exit.
9310751SAndreas.Sandberg@ARM.com    """
9410751SAndreas.Sandberg@ARM.com
9510751SAndreas.Sandberg@ARM.com    cpt_name = os.path.join(m5.options.outdir, "test.cpt")
9610751SAndreas.Sandberg@ARM.com    restore = None
9710751SAndreas.Sandberg@ARM.com
9810751SAndreas.Sandberg@ARM.com    for cpt_no in range(max_checkpoints):
9910751SAndreas.Sandberg@ARM.com        # Create a checkpoint from a separate child process. This enables
10010751SAndreas.Sandberg@ARM.com        # us to get back to a (mostly) pristine state and restart
10110751SAndreas.Sandberg@ARM.com        # simulation from the checkpoint.
10210751SAndreas.Sandberg@ARM.com        p = Process(target=_run_step,
10310751SAndreas.Sandberg@ARM.com                    args=(cpt_name, ),
10410751SAndreas.Sandberg@ARM.com                    kwargs={
10510751SAndreas.Sandberg@ARM.com                "restore" : restore,
10610751SAndreas.Sandberg@ARM.com                "interval" : interval,
10710751SAndreas.Sandberg@ARM.com                })
10810751SAndreas.Sandberg@ARM.com        p.start()
10910751SAndreas.Sandberg@ARM.com
11010751SAndreas.Sandberg@ARM.com        # Wait for the child to return
11110751SAndreas.Sandberg@ARM.com        p.join()
11210751SAndreas.Sandberg@ARM.com
11310751SAndreas.Sandberg@ARM.com        # Restore from the checkpoint next iteration
11410751SAndreas.Sandberg@ARM.com        restore = cpt_name
11510751SAndreas.Sandberg@ARM.com
11610751SAndreas.Sandberg@ARM.com        if p.exitcode == _exitcode_done:
11712575Sgiacomo.travaglini@arm.com            print("Test done.", file=sys.stderr)
11810751SAndreas.Sandberg@ARM.com            sys.exit(0)
11910751SAndreas.Sandberg@ARM.com        elif p.exitcode == _exitcode_checkpoint:
12010751SAndreas.Sandberg@ARM.com            pass
12110751SAndreas.Sandberg@ARM.com        else:
12212575Sgiacomo.travaglini@arm.com            print("Test failed.", file=sys.stderr)
12310751SAndreas.Sandberg@ARM.com            sys.exit(1)
12410751SAndreas.Sandberg@ARM.com
12510751SAndreas.Sandberg@ARM.com    # Maximum number of checkpoints reached. Just run full-speed from
12610751SAndreas.Sandberg@ARM.com    # now on.
12710751SAndreas.Sandberg@ARM.com    m5.instantiate()
12810751SAndreas.Sandberg@ARM.com    e = m5.simulate()
12910751SAndreas.Sandberg@ARM.com    cause = e.getCause()
13010751SAndreas.Sandberg@ARM.com    if cause in _exit_normal:
13110751SAndreas.Sandberg@ARM.com        sys.exit(0)
13210751SAndreas.Sandberg@ARM.com    else:
13312575Sgiacomo.travaglini@arm.com        print("Test failed: Unknown exit cause: %s" % cause)
13410751SAndreas.Sandberg@ARM.com        sys.exit(1)
135