switcheroo.py revision 12575
110201SAndrew.Bardsley@arm.com# Copyright (c) 2012 ARM Limited
210201SAndrew.Bardsley@arm.com# All rights reserved.
310201SAndrew.Bardsley@arm.com#
410201SAndrew.Bardsley@arm.com# The license below extends only to copyright in the software and shall
510201SAndrew.Bardsley@arm.com# not be construed as granting a license to any other intellectual
610201SAndrew.Bardsley@arm.com# property including but not limited to intellectual property relating
710201SAndrew.Bardsley@arm.com# to a hardware implementation of the functionality of the software
810201SAndrew.Bardsley@arm.com# licensed hereunder.  You may use the software subject to the license
910201SAndrew.Bardsley@arm.com# terms below provided that you ensure that this notice is replicated
1010201SAndrew.Bardsley@arm.com# unmodified and in its entirety in all distributions of the software,
1110201SAndrew.Bardsley@arm.com# modified or unmodified, in source code or in binary form.
1210201SAndrew.Bardsley@arm.com#
1310201SAndrew.Bardsley@arm.com# Redistribution and use in source and binary forms, with or without
1410201SAndrew.Bardsley@arm.com# modification, are permitted provided that the following conditions are
1510201SAndrew.Bardsley@arm.com# met: redistributions of source code must retain the above copyright
1610201SAndrew.Bardsley@arm.com# notice, this list of conditions and the following disclaimer;
1710201SAndrew.Bardsley@arm.com# redistributions in binary form must reproduce the above copyright
1810201SAndrew.Bardsley@arm.com# notice, this list of conditions and the following disclaimer in the
1910201SAndrew.Bardsley@arm.com# documentation and/or other materials provided with the distribution;
2010201SAndrew.Bardsley@arm.com# neither the name of the copyright holders nor the names of its
2110201SAndrew.Bardsley@arm.com# contributors may be used to endorse or promote products derived from
2210201SAndrew.Bardsley@arm.com# this software without specific prior written permission.
2310201SAndrew.Bardsley@arm.com#
2410201SAndrew.Bardsley@arm.com# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2510201SAndrew.Bardsley@arm.com# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2610201SAndrew.Bardsley@arm.com# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2710201SAndrew.Bardsley@arm.com# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2810201SAndrew.Bardsley@arm.com# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2910201SAndrew.Bardsley@arm.com# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3010201SAndrew.Bardsley@arm.com# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3110201SAndrew.Bardsley@arm.com# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3210201SAndrew.Bardsley@arm.com# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3310201SAndrew.Bardsley@arm.com# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3410201SAndrew.Bardsley@arm.com# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3510201SAndrew.Bardsley@arm.com#
3610201SAndrew.Bardsley@arm.com# Authors: Andreas Sandberg
3710201SAndrew.Bardsley@arm.com
3810201SAndrew.Bardsley@arm.comfrom __future__ import print_function
3910201SAndrew.Bardsley@arm.com
4010201SAndrew.Bardsley@arm.comimport m5
4110201SAndrew.Bardsley@arm.comimport _m5
4210201SAndrew.Bardsley@arm.comfrom m5.objects import *
4310201SAndrew.Bardsley@arm.comm5.util.addToPath('../configs/')
4410201SAndrew.Bardsley@arm.comfrom common.Caches import *
4510201SAndrew.Bardsley@arm.com
4610201SAndrew.Bardsley@arm.comclass Sequential:
4710201SAndrew.Bardsley@arm.com    """Sequential CPU switcher.
4810201SAndrew.Bardsley@arm.com
4910201SAndrew.Bardsley@arm.com    The sequential CPU switches between all CPUs in a system in
5010201SAndrew.Bardsley@arm.com    order. The CPUs in the system must have been prepared for
5110201SAndrew.Bardsley@arm.com    switching, which in practice means that only one CPU is switched
5210201SAndrew.Bardsley@arm.com    in. base_config.BaseFSSwitcheroo can be used to create such a
5310201SAndrew.Bardsley@arm.com    system.
5410201SAndrew.Bardsley@arm.com    """
5510201SAndrew.Bardsley@arm.com    def __init__(self, cpus):
5610201SAndrew.Bardsley@arm.com        self.first_cpu = None
5710201SAndrew.Bardsley@arm.com        for (cpuno, cpu) in enumerate(cpus):
5810201SAndrew.Bardsley@arm.com            if not cpu.switched_out:
5910201SAndrew.Bardsley@arm.com                if self.first_cpu != None:
6010201SAndrew.Bardsley@arm.com                    fatal("More than one CPU is switched in");
6110201SAndrew.Bardsley@arm.com                self.first_cpu = cpuno
6210201SAndrew.Bardsley@arm.com
6310201SAndrew.Bardsley@arm.com        if self.first_cpu == None:
6410201SAndrew.Bardsley@arm.com            fatal("The system contains no switched in CPUs")
6510201SAndrew.Bardsley@arm.com
6610201SAndrew.Bardsley@arm.com        self.cur_cpu = self.first_cpu
6710201SAndrew.Bardsley@arm.com        self.cpus = cpus
6810201SAndrew.Bardsley@arm.com
6910201SAndrew.Bardsley@arm.com    def next(self):
7010201SAndrew.Bardsley@arm.com        self.cur_cpu = (self.cur_cpu + 1) % len(self.cpus)
7110201SAndrew.Bardsley@arm.com        return self.cpus[self.cur_cpu]
7210201SAndrew.Bardsley@arm.com
7310201SAndrew.Bardsley@arm.com    def first(self):
7410201SAndrew.Bardsley@arm.com        return self.cpus[self.first_cpu]
7510201SAndrew.Bardsley@arm.com
7610201SAndrew.Bardsley@arm.comdef run_test(root, switcher=None, freq=1000, verbose=False):
7710201SAndrew.Bardsley@arm.com    """Test runner for CPU switcheroo tests.
7810201SAndrew.Bardsley@arm.com
7910201SAndrew.Bardsley@arm.com    The switcheroo test runner is used to switch CPUs in a system that
8010201SAndrew.Bardsley@arm.com    has been prepared for CPU switching. Such systems should have
8110201SAndrew.Bardsley@arm.com    multiple CPUs when they are instantiated, but only one should be
8210201SAndrew.Bardsley@arm.com    switched in. Such configurations can be created using the
8310201SAndrew.Bardsley@arm.com    base_config.BaseFSSwitcheroo class.
8410201SAndrew.Bardsley@arm.com
8510201SAndrew.Bardsley@arm.com    A CPU switcher object is used to control switching. The default
8610201SAndrew.Bardsley@arm.com    switcher sequentially switches between all CPUs in a system,
8710201SAndrew.Bardsley@arm.com    starting with the CPU that is currently switched in.
8810201SAndrew.Bardsley@arm.com
8910201SAndrew.Bardsley@arm.com    Unlike most other test runners, this one automatically configures
9010201SAndrew.Bardsley@arm.com    the memory mode of the system based on the first CPU the switcher
9110201SAndrew.Bardsley@arm.com    reports.
9210201SAndrew.Bardsley@arm.com
9310201SAndrew.Bardsley@arm.com    Keyword Arguments:
9410201SAndrew.Bardsley@arm.com      switcher -- CPU switcher implementation. See Sequential for
9510201SAndrew.Bardsley@arm.com                  an example implementation.
9610201SAndrew.Bardsley@arm.com      period -- Switching frequency in Hz.
9710201SAndrew.Bardsley@arm.com      verbose -- Enable output at each switch (suppressed by default).
9810201SAndrew.Bardsley@arm.com    """
9910201SAndrew.Bardsley@arm.com
10010201SAndrew.Bardsley@arm.com    if switcher == None:
10110201SAndrew.Bardsley@arm.com        switcher = Sequential(root.system.cpu)
10210201SAndrew.Bardsley@arm.com
10310201SAndrew.Bardsley@arm.com    current_cpu = switcher.first()
10410201SAndrew.Bardsley@arm.com    system = root.system
10510201SAndrew.Bardsley@arm.com    system.mem_mode = type(current_cpu).memory_mode()
10610201SAndrew.Bardsley@arm.com
10710201SAndrew.Bardsley@arm.com    # Suppress "Entering event queue" messages since we get tons of them.
10810201SAndrew.Bardsley@arm.com    # Worse yet, they include the timestamp, which makes them highly
10910201SAndrew.Bardsley@arm.com    # variable and unsuitable for comparing as test outputs.
11010201SAndrew.Bardsley@arm.com    if not verbose:
11110201SAndrew.Bardsley@arm.com        _m5.core.setLogLevel(_m5.core.LogLevel.WARN)
11210201SAndrew.Bardsley@arm.com
113    # instantiate configuration
114    m5.instantiate()
115
116    # Determine the switching period, this has to be done after
117    # instantiating the system since the time base must be fixed.
118    period = m5.ticks.fromSeconds(1.0 / freq)
119    while True:
120        exit_event = m5.simulate(period)
121        exit_cause = exit_event.getCause()
122
123        if exit_cause == "simulate() limit reached":
124            next_cpu = switcher.next()
125
126            if verbose:
127                print("Switching CPUs...")
128                print("Next CPU: %s" % type(next_cpu))
129            m5.drain()
130            if current_cpu != next_cpu:
131                m5.switchCpus(system, [ (current_cpu, next_cpu) ],
132                              verbose=verbose)
133            else:
134                print("Source CPU and destination CPU are the same,"
135                    " skipping...")
136            current_cpu = next_cpu
137        elif exit_cause == "target called exit()" or \
138                exit_cause == "m5_exit instruction encountered":
139
140            sys.exit(0)
141        else:
142            print("Test failed: Unknown exit cause: %s" % exit_cause)
143            sys.exit(1)
144