simulate.py revision 9342:6fec8f26e56d
112469Sglenn.bergmans@arm.com# Copyright (c) 2012 ARM Limited 212469Sglenn.bergmans@arm.com# All rights reserved. 312469Sglenn.bergmans@arm.com# 412469Sglenn.bergmans@arm.com# The license below extends only to copyright in the software and shall 512469Sglenn.bergmans@arm.com# not be construed as granting a license to any other intellectual 612469Sglenn.bergmans@arm.com# property including but not limited to intellectual property relating 712469Sglenn.bergmans@arm.com# to a hardware implementation of the functionality of the software 812469Sglenn.bergmans@arm.com# licensed hereunder. You may use the software subject to the license 912469Sglenn.bergmans@arm.com# terms below provided that you ensure that this notice is replicated 1012469Sglenn.bergmans@arm.com# unmodified and in its entirety in all distributions of the software, 1112469Sglenn.bergmans@arm.com# modified or unmodified, in source code or in binary form. 1212469Sglenn.bergmans@arm.com# 1312469Sglenn.bergmans@arm.com# Copyright (c) 2005 The Regents of The University of Michigan 1412469Sglenn.bergmans@arm.com# Copyright (c) 2010 Advanced Micro Devices, Inc. 1512469Sglenn.bergmans@arm.com# All rights reserved. 1612469Sglenn.bergmans@arm.com# 1712469Sglenn.bergmans@arm.com# Redistribution and use in source and binary forms, with or without 1812469Sglenn.bergmans@arm.com# modification, are permitted provided that the following conditions are 1912469Sglenn.bergmans@arm.com# met: redistributions of source code must retain the above copyright 2012469Sglenn.bergmans@arm.com# notice, this list of conditions and the following disclaimer; 2112469Sglenn.bergmans@arm.com# redistributions in binary form must reproduce the above copyright 2212469Sglenn.bergmans@arm.com# notice, this list of conditions and the following disclaimer in the 2312469Sglenn.bergmans@arm.com# documentation and/or other materials provided with the distribution; 2412469Sglenn.bergmans@arm.com# neither the name of the copyright holders nor the names of its 2512469Sglenn.bergmans@arm.com# contributors may be used to endorse or promote products derived from 2612469Sglenn.bergmans@arm.com# this software without specific prior written permission. 2712469Sglenn.bergmans@arm.com# 2812469Sglenn.bergmans@arm.com# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2912469Sglenn.bergmans@arm.com# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3012469Sglenn.bergmans@arm.com# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 3112469Sglenn.bergmans@arm.com# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3212469Sglenn.bergmans@arm.com# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 3312469Sglenn.bergmans@arm.com# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 3412469Sglenn.bergmans@arm.com# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3512469Sglenn.bergmans@arm.com# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3612469Sglenn.bergmans@arm.com# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3712469Sglenn.bergmans@arm.com# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3813719Sandreas.sandberg@arm.com# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3913719Sandreas.sandberg@arm.com# 4013719Sandreas.sandberg@arm.com# Authors: Nathan Binkert 4113719Sandreas.sandberg@arm.com# Steve Reinhardt 4212469Sglenn.bergmans@arm.com 4312469Sglenn.bergmans@arm.comimport atexit 4412469Sglenn.bergmans@arm.comimport os 4512469Sglenn.bergmans@arm.comimport sys 4612469Sglenn.bergmans@arm.com 4712469Sglenn.bergmans@arm.com# import the SWIG-wrapped main C++ functions 4812469Sglenn.bergmans@arm.comimport internal 4912469Sglenn.bergmans@arm.comimport core 5012469Sglenn.bergmans@arm.comimport stats 5112469Sglenn.bergmans@arm.comimport SimObject 5212469Sglenn.bergmans@arm.comimport ticks 5312469Sglenn.bergmans@arm.comimport objects 5412469Sglenn.bergmans@arm.comfrom m5.util.dot_writer import do_dot 5512469Sglenn.bergmans@arm.comfrom m5.internal.stats import updateEvents as updateStatEvents 5612469Sglenn.bergmans@arm.com 5712469Sglenn.bergmans@arm.comfrom util import fatal 5812469Sglenn.bergmans@arm.comfrom util import attrdict 5912469Sglenn.bergmans@arm.com 6012469Sglenn.bergmans@arm.com# define a MaxTick parameter 6112469Sglenn.bergmans@arm.comMaxTick = 2**63 - 1 6212469Sglenn.bergmans@arm.com 6312469Sglenn.bergmans@arm.com# The final hook to generate .ini files. Called from the user script 6412469Sglenn.bergmans@arm.com# once the config is built. 6512469Sglenn.bergmans@arm.comdef instantiate(ckpt_dir=None): 6612469Sglenn.bergmans@arm.com from m5 import options 6712469Sglenn.bergmans@arm.com 6812469Sglenn.bergmans@arm.com root = objects.Root.getInstance() 6912469Sglenn.bergmans@arm.com 7012469Sglenn.bergmans@arm.com if not root: 7112469Sglenn.bergmans@arm.com fatal("Need to instantiate Root() before calling instantiate()") 7212469Sglenn.bergmans@arm.com 7312469Sglenn.bergmans@arm.com # we need to fix the global frequency 7412469Sglenn.bergmans@arm.com ticks.fixGlobalFrequency() 7512469Sglenn.bergmans@arm.com 7612469Sglenn.bergmans@arm.com # Make sure SimObject-valued params are in the configuration 7712469Sglenn.bergmans@arm.com # hierarchy so we catch them with future descendants() walks 7812469Sglenn.bergmans@arm.com for obj in root.descendants(): obj.adoptOrphanParams() 7912469Sglenn.bergmans@arm.com 8012469Sglenn.bergmans@arm.com # Unproxy in sorted order for determinism 8112469Sglenn.bergmans@arm.com for obj in root.descendants(): obj.unproxyParams() 8212469Sglenn.bergmans@arm.com 8312469Sglenn.bergmans@arm.com if options.dump_config: 8412469Sglenn.bergmans@arm.com ini_file = file(os.path.join(options.outdir, options.dump_config), 'w') 8512469Sglenn.bergmans@arm.com # Print ini sections in sorted order for easier diffing 8612469Sglenn.bergmans@arm.com for obj in sorted(root.descendants(), key=lambda o: o.path()): 8712469Sglenn.bergmans@arm.com obj.print_ini(ini_file) 8812469Sglenn.bergmans@arm.com ini_file.close() 8912469Sglenn.bergmans@arm.com 9012469Sglenn.bergmans@arm.com if options.json_config: 9112469Sglenn.bergmans@arm.com try: 9212469Sglenn.bergmans@arm.com import json 9312469Sglenn.bergmans@arm.com json_file = file(os.path.join(options.outdir, options.json_config), 'w') 9412469Sglenn.bergmans@arm.com d = root.get_config_as_dict() 9512469Sglenn.bergmans@arm.com json.dump(d, json_file, indent=4) 9612469Sglenn.bergmans@arm.com json_file.close() 9712469Sglenn.bergmans@arm.com except ImportError: 9812469Sglenn.bergmans@arm.com pass 9912469Sglenn.bergmans@arm.com 10012469Sglenn.bergmans@arm.com do_dot(root, options.outdir, options.dot_config) 10112469Sglenn.bergmans@arm.com 10212469Sglenn.bergmans@arm.com # Initialize the global statistics 10312469Sglenn.bergmans@arm.com stats.initSimStats() 10412469Sglenn.bergmans@arm.com 10512469Sglenn.bergmans@arm.com # Create the C++ sim objects and connect ports 10612469Sglenn.bergmans@arm.com for obj in root.descendants(): obj.createCCObject() 10712469Sglenn.bergmans@arm.com for obj in root.descendants(): obj.connectPorts() 10812469Sglenn.bergmans@arm.com 10912469Sglenn.bergmans@arm.com # Do a second pass to finish initializing the sim objects 11012469Sglenn.bergmans@arm.com for obj in root.descendants(): obj.init() 11112469Sglenn.bergmans@arm.com 11212469Sglenn.bergmans@arm.com # Do a third pass to initialize statistics 11312469Sglenn.bergmans@arm.com for obj in root.descendants(): obj.regStats() 11412469Sglenn.bergmans@arm.com 11512469Sglenn.bergmans@arm.com # We're done registering statistics. Enable the stats package now. 11612469Sglenn.bergmans@arm.com stats.enable() 11712469Sglenn.bergmans@arm.com 11812469Sglenn.bergmans@arm.com # Restore checkpoint (if any) 11912469Sglenn.bergmans@arm.com if ckpt_dir: 12012469Sglenn.bergmans@arm.com ckpt = internal.core.getCheckpoint(ckpt_dir) 12112469Sglenn.bergmans@arm.com internal.core.unserializeGlobals(ckpt); 12212469Sglenn.bergmans@arm.com for obj in root.descendants(): obj.loadState(ckpt) 12312469Sglenn.bergmans@arm.com need_resume.append(root) 12412469Sglenn.bergmans@arm.com else: 12512469Sglenn.bergmans@arm.com for obj in root.descendants(): obj.initState() 12612469Sglenn.bergmans@arm.com 12712469Sglenn.bergmans@arm.com # Check to see if any of the stat events are in the past after resuming from 12812469Sglenn.bergmans@arm.com # a checkpoint, If so, this call will shift them to be at a valid time. 12912469Sglenn.bergmans@arm.com updateStatEvents() 13012469Sglenn.bergmans@arm.com 13112469Sglenn.bergmans@arm.com # Reset to put the stats in a consistent state. 13212469Sglenn.bergmans@arm.com stats.reset() 13312469Sglenn.bergmans@arm.com 13412469Sglenn.bergmans@arm.comneed_resume = [] 13512469Sglenn.bergmans@arm.comneed_startup = True 13612469Sglenn.bergmans@arm.comdef simulate(*args, **kwargs): 13712469Sglenn.bergmans@arm.com global need_resume, need_startup 13812469Sglenn.bergmans@arm.com 13912469Sglenn.bergmans@arm.com if need_startup: 14012469Sglenn.bergmans@arm.com root = objects.Root.getInstance() 14112469Sglenn.bergmans@arm.com for obj in root.descendants(): obj.startup() 14212469Sglenn.bergmans@arm.com need_startup = False 14312469Sglenn.bergmans@arm.com 14412469Sglenn.bergmans@arm.com for root in need_resume: 14512469Sglenn.bergmans@arm.com resume(root) 14612469Sglenn.bergmans@arm.com need_resume = [] 14712469Sglenn.bergmans@arm.com 14812469Sglenn.bergmans@arm.com return internal.event.simulate(*args, **kwargs) 14912469Sglenn.bergmans@arm.com 15012469Sglenn.bergmans@arm.com# Export curTick to user script. 15112469Sglenn.bergmans@arm.comdef curTick(): 15212469Sglenn.bergmans@arm.com return internal.core.curTick() 15312469Sglenn.bergmans@arm.com 15412469Sglenn.bergmans@arm.com# Python exit handlers happen in reverse order. We want to dump stats last. 15512469Sglenn.bergmans@arm.comatexit.register(stats.dump) 15612469Sglenn.bergmans@arm.com 15712469Sglenn.bergmans@arm.com# register our C++ exit callback function with Python 15812469Sglenn.bergmans@arm.comatexit.register(internal.core.doExitCleanup) 15912469Sglenn.bergmans@arm.com 16012469Sglenn.bergmans@arm.com# This loops until all objects have been fully drained. 16112469Sglenn.bergmans@arm.comdef doDrain(root): 16212469Sglenn.bergmans@arm.com all_drained = drain(root) 16312469Sglenn.bergmans@arm.com while (not all_drained): 16412469Sglenn.bergmans@arm.com all_drained = drain(root) 16512469Sglenn.bergmans@arm.com 16612469Sglenn.bergmans@arm.com# Tries to drain all objects. Draining might not be completed unless 16712469Sglenn.bergmans@arm.com# all objects return that they are drained on the first call. This is 16812469Sglenn.bergmans@arm.com# because as objects drain they may cause other objects to no longer 16912469Sglenn.bergmans@arm.com# be drained. 17012469Sglenn.bergmans@arm.comdef drain(root): 17112469Sglenn.bergmans@arm.com all_drained = False 17212469Sglenn.bergmans@arm.com dm = internal.drain.createDrainManager() 17312469Sglenn.bergmans@arm.com unready_objs = sum(obj.drain(dm) for obj in root.descendants()) 17412469Sglenn.bergmans@arm.com # If we've got some objects that can't drain immediately, then simulate 17512469Sglenn.bergmans@arm.com if unready_objs > 0: 17612469Sglenn.bergmans@arm.com dm.setCount(unready_objs) 17712469Sglenn.bergmans@arm.com simulate() 17812469Sglenn.bergmans@arm.com else: 17912469Sglenn.bergmans@arm.com all_drained = True 18012469Sglenn.bergmans@arm.com internal.drain.cleanupDrainManager(dm) 18112469Sglenn.bergmans@arm.com return all_drained 18212469Sglenn.bergmans@arm.com 18312469Sglenn.bergmans@arm.comdef resume(root): 18412469Sglenn.bergmans@arm.com for obj in root.descendants(): obj.drainResume() 18512469Sglenn.bergmans@arm.com 18612469Sglenn.bergmans@arm.comdef checkpoint(dir): 18712469Sglenn.bergmans@arm.com root = objects.Root.getInstance() 18812469Sglenn.bergmans@arm.com if not isinstance(root, objects.Root): 18912469Sglenn.bergmans@arm.com raise TypeError, "Checkpoint must be called on a root object." 19012469Sglenn.bergmans@arm.com doDrain(root) 19112469Sglenn.bergmans@arm.com print "Writing checkpoint" 19212469Sglenn.bergmans@arm.com internal.core.serializeAll(dir) 19312469Sglenn.bergmans@arm.com resume(root) 19412469Sglenn.bergmans@arm.com 19512469Sglenn.bergmans@arm.comdef changeToAtomic(system): 19612469Sglenn.bergmans@arm.com if not isinstance(system, (objects.Root, objects.System)): 19712469Sglenn.bergmans@arm.com raise TypeError, "Parameter of type '%s'. Must be type %s or %s." % \ 19812469Sglenn.bergmans@arm.com (type(system), objects.Root, objects.System) 19912469Sglenn.bergmans@arm.com if system.getMemoryMode() != objects.params.atomic: 20012469Sglenn.bergmans@arm.com doDrain(system) 20112469Sglenn.bergmans@arm.com print "Changing memory mode to atomic" 20212469Sglenn.bergmans@arm.com system.setMemoryMode(objects.params.atomic) 20312469Sglenn.bergmans@arm.com 20412469Sglenn.bergmans@arm.comdef changeToTiming(system): 20512469Sglenn.bergmans@arm.com if not isinstance(system, (objects.Root, objects.System)): 20612469Sglenn.bergmans@arm.com raise TypeError, "Parameter of type '%s'. Must be type %s or %s." % \ 20712469Sglenn.bergmans@arm.com (type(system), objects.Root, objects.System) 20812469Sglenn.bergmans@arm.com 20912469Sglenn.bergmans@arm.com if system.getMemoryMode() != objects.params.timing: 21012469Sglenn.bergmans@arm.com doDrain(system) 21112469Sglenn.bergmans@arm.com print "Changing memory mode to timing" 21212469Sglenn.bergmans@arm.com system.setMemoryMode(objects.params.timing) 21312469Sglenn.bergmans@arm.com 21412469Sglenn.bergmans@arm.comdef switchCpus(cpuList): 21512469Sglenn.bergmans@arm.com print "switching cpus" 21612469Sglenn.bergmans@arm.com if not isinstance(cpuList, list): 21712469Sglenn.bergmans@arm.com raise RuntimeError, "Must pass a list to this function" 21812469Sglenn.bergmans@arm.com for item in cpuList: 21912469Sglenn.bergmans@arm.com if not isinstance(item, tuple) or len(item) != 2: 22012469Sglenn.bergmans@arm.com raise RuntimeError, "List must have tuples of (oldCPU,newCPU)" 22112469Sglenn.bergmans@arm.com 22212469Sglenn.bergmans@arm.com for old_cpu, new_cpu in cpuList: 22312469Sglenn.bergmans@arm.com if not isinstance(old_cpu, objects.BaseCPU): 22412469Sglenn.bergmans@arm.com raise TypeError, "%s is not of type BaseCPU" % old_cpu 22512469Sglenn.bergmans@arm.com if not isinstance(new_cpu, objects.BaseCPU): 22612469Sglenn.bergmans@arm.com raise TypeError, "%s is not of type BaseCPU" % new_cpu 22712469Sglenn.bergmans@arm.com 22812469Sglenn.bergmans@arm.com # Now all of the CPUs are ready to be switched out 22912469Sglenn.bergmans@arm.com for old_cpu, new_cpu in cpuList: 23012469Sglenn.bergmans@arm.com old_cpu.switchOut() 23112469Sglenn.bergmans@arm.com 23212469Sglenn.bergmans@arm.com for old_cpu, new_cpu in cpuList: 23312469Sglenn.bergmans@arm.com new_cpu.takeOverFrom(old_cpu) 23412469Sglenn.bergmans@arm.com 23512469Sglenn.bergmans@arm.comfrom internal.core import disableAllListeners 23612469Sglenn.bergmans@arm.com