switcheroo.py revision 9521
112863Sgabeblack@google.com# Copyright (c) 2012 ARM Limited
212863Sgabeblack@google.com# All rights reserved.
312863Sgabeblack@google.com#
412863Sgabeblack@google.com# The license below extends only to copyright in the software and shall
512863Sgabeblack@google.com# not be construed as granting a license to any other intellectual
612863Sgabeblack@google.com# property including but not limited to intellectual property relating
712863Sgabeblack@google.com# to a hardware implementation of the functionality of the software
812863Sgabeblack@google.com# licensed hereunder.  You may use the software subject to the license
912863Sgabeblack@google.com# terms below provided that you ensure that this notice is replicated
1012863Sgabeblack@google.com# unmodified and in its entirety in all distributions of the software,
1112863Sgabeblack@google.com# modified or unmodified, in source code or in binary form.
1212863Sgabeblack@google.com#
1312863Sgabeblack@google.com# Redistribution and use in source and binary forms, with or without
1412863Sgabeblack@google.com# modification, are permitted provided that the following conditions are
1512863Sgabeblack@google.com# met: redistributions of source code must retain the above copyright
1612863Sgabeblack@google.com# notice, this list of conditions and the following disclaimer;
1712863Sgabeblack@google.com# redistributions in binary form must reproduce the above copyright
1812863Sgabeblack@google.com# notice, this list of conditions and the following disclaimer in the
1912863Sgabeblack@google.com# documentation and/or other materials provided with the distribution;
2012863Sgabeblack@google.com# neither the name of the copyright holders nor the names of its
2112863Sgabeblack@google.com# contributors may be used to endorse or promote products derived from
2212863Sgabeblack@google.com# this software without specific prior written permission.
2312863Sgabeblack@google.com#
2412863Sgabeblack@google.com# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2512863Sgabeblack@google.com# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2612863Sgabeblack@google.com# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2712863Sgabeblack@google.com# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2812863Sgabeblack@google.com# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2912863Sgabeblack@google.com# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3012863Sgabeblack@google.com# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3112863Sgabeblack@google.com# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3212863Sgabeblack@google.com# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3312950Sgabeblack@google.com# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3413046Sgabeblack@google.com# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3513035Sgabeblack@google.com#
3613035Sgabeblack@google.com# Authors: Andreas Sandberg
3713035Sgabeblack@google.com
3813053Sgabeblack@google.comimport m5
3912950Sgabeblack@google.comfrom m5.objects import *
4012950Sgabeblack@google.comm5.util.addToPath('../configs/common')
4112950Sgabeblack@google.comfrom Caches import *
4212950Sgabeblack@google.com
4313053Sgabeblack@google.comclass Sequential:
4413053Sgabeblack@google.com    """Sequential CPU switcher.
4513053Sgabeblack@google.com
4613053Sgabeblack@google.com    The sequential CPU switches between all CPUs in a system in
4713053Sgabeblack@google.com    order. The CPUs in the system must have been prepared for
4813053Sgabeblack@google.com    switching, which in practice means that only one CPU is switched
4913053Sgabeblack@google.com    in. base_config.BaseFSSwitcheroo can be used to create such a
5012950Sgabeblack@google.com    system.
5112863Sgabeblack@google.com    """
5212863Sgabeblack@google.com    def __init__(self, cpus):
5313035Sgabeblack@google.com        self.first_cpu = None
5413035Sgabeblack@google.com        for (cpuno, cpu) in enumerate(cpus):
5513035Sgabeblack@google.com            if not cpu.switched_out:
5613035Sgabeblack@google.com                if self.first_cpu != None:
5713035Sgabeblack@google.com                    fatal("More than one CPU is switched in");
5813035Sgabeblack@google.com                self.first_cpu = cpuno
5913035Sgabeblack@google.com
6013035Sgabeblack@google.com        if self.first_cpu == None:
6113035Sgabeblack@google.com            fatal("The system contains no switched in CPUs")
6213035Sgabeblack@google.com
6313035Sgabeblack@google.com        self.cur_cpu = self.first_cpu
6413035Sgabeblack@google.com        self.cpus = cpus
6513035Sgabeblack@google.com
6613035Sgabeblack@google.com    def next(self):
6713035Sgabeblack@google.com        self.cur_cpu = (self.cur_cpu + 1) % len(self.cpus)
6813035Sgabeblack@google.com        return self.cpus[self.cur_cpu]
6913035Sgabeblack@google.com
7012863Sgabeblack@google.com    def first(self):
7112863Sgabeblack@google.com        return self.cpus[self.first_cpu]
7212863Sgabeblack@google.com
7312863Sgabeblack@google.comdef run_test(root, switcher=None, freq=1000):
7412950Sgabeblack@google.com    """Test runner for CPU switcheroo tests.
7512950Sgabeblack@google.com
7612863Sgabeblack@google.com    The switcheroo test runner is used to switch CPUs in a system that
7713035Sgabeblack@google.com    has been prepared for CPU switching. Such systems should have
7813035Sgabeblack@google.com    multiple CPUs when they are instantiated, but only one should be
7912863Sgabeblack@google.com    switched in. Such configurations can be created using the
8012863Sgabeblack@google.com    base_config.BaseFSSwitcheroo class.
8112950Sgabeblack@google.com
8212982Sgabeblack@google.com    A CPU switcher object is used to control switching. The default
8312982Sgabeblack@google.com    switcher sequentially switches between all CPUs in a system,
8412950Sgabeblack@google.com    starting with the CPU that is currently switched in.
8512863Sgabeblack@google.com
8612950Sgabeblack@google.com    Unlike most other test runners, this one automatically configures
8712950Sgabeblack@google.com    the memory mode of the system based on the first CPU the switcher
8812950Sgabeblack@google.com    reports.
8912950Sgabeblack@google.com
9012950Sgabeblack@google.com    Keyword Arguments:
9112950Sgabeblack@google.com      switcher -- CPU switcher implementation. See Sequential for
9212950Sgabeblack@google.com                  an example implementation.
9312950Sgabeblack@google.com      period -- Switching frequency in Hz.
9412950Sgabeblack@google.com    """
9512950Sgabeblack@google.com
9612950Sgabeblack@google.com    if switcher == None:
9712950Sgabeblack@google.com        switcher = Sequential(root.system.cpu)
9812950Sgabeblack@google.com
9912950Sgabeblack@google.com    current_cpu = switcher.first()
10012950Sgabeblack@google.com    system = root.system
10112950Sgabeblack@google.com    system.mem_mode = type(current_cpu).memory_mode()
10212950Sgabeblack@google.com
10312950Sgabeblack@google.com    # instantiate configuration
10412950Sgabeblack@google.com    m5.instantiate()
10512950Sgabeblack@google.com
10612950Sgabeblack@google.com    # Determine the switching period, this has to be done after
10712950Sgabeblack@google.com    # instantiating the system since the time base must be fixed.
10812950Sgabeblack@google.com    period = m5.ticks.fromSeconds(1.0 / freq)
10912863Sgabeblack@google.com    while True:
11013035Sgabeblack@google.com        exit_event = m5.simulate(period)
11113035Sgabeblack@google.com        exit_cause = exit_event.getCause()
11213053Sgabeblack@google.com
11313053Sgabeblack@google.com        if exit_cause == "simulate() limit reached":
11412863Sgabeblack@google.com            next_cpu = switcher.next()
11512863Sgabeblack@google.com
11612950Sgabeblack@google.com            print "Switching CPUs..."
11712950Sgabeblack@google.com            print "Next CPU: %s" % type(next_cpu)
11812863Sgabeblack@google.com            m5.drain(system)
11913045Sgabeblack@google.com            if current_cpu != next_cpu:
12013045Sgabeblack@google.com                m5.switchCpus(system, [ (current_cpu, next_cpu) ],
12113045Sgabeblack@google.com                              do_drain=False)
12213046Sgabeblack@google.com            else:
12312982Sgabeblack@google.com                print "Source CPU and destination CPU are the same, skipping..."
12412863Sgabeblack@google.com            m5.resume(system)
12512863Sgabeblack@google.com            current_cpu = next_cpu
12612863Sgabeblack@google.com        elif exit_cause == "target called exit()" or \
127                exit_cause == "m5_exit instruction encountered":
128
129            sys.exit(0)
130        else:
131            print "Test failed: Unknown exit cause: %s" % exit_cause
132            sys.exit(1)
133