simulate.py revision 9254
18999Suri.wiener@arm.com# Copyright (c) 2012 ARM Limited 28999Suri.wiener@arm.com# All rights reserved. 38999Suri.wiener@arm.com# 48999Suri.wiener@arm.com# The license below extends only to copyright in the software and shall 58999Suri.wiener@arm.com# not be construed as granting a license to any other intellectual 68999Suri.wiener@arm.com# property including but not limited to intellectual property relating 78999Suri.wiener@arm.com# to a hardware implementation of the functionality of the software 88999Suri.wiener@arm.com# licensed hereunder. You may use the software subject to the license 98999Suri.wiener@arm.com# terms below provided that you ensure that this notice is replicated 108999Suri.wiener@arm.com# unmodified and in its entirety in all distributions of the software, 118999Suri.wiener@arm.com# modified or unmodified, in source code or in binary form. 128999Suri.wiener@arm.com# 134762Snate@binkert.org# Copyright (c) 2005 The Regents of The University of Michigan 147534Ssteve.reinhardt@amd.com# Copyright (c) 2010 Advanced Micro Devices, Inc. 154762Snate@binkert.org# All rights reserved. 164762Snate@binkert.org# 174762Snate@binkert.org# Redistribution and use in source and binary forms, with or without 184762Snate@binkert.org# modification, are permitted provided that the following conditions are 194762Snate@binkert.org# met: redistributions of source code must retain the above copyright 204762Snate@binkert.org# notice, this list of conditions and the following disclaimer; 214762Snate@binkert.org# redistributions in binary form must reproduce the above copyright 224762Snate@binkert.org# notice, this list of conditions and the following disclaimer in the 234762Snate@binkert.org# documentation and/or other materials provided with the distribution; 244762Snate@binkert.org# neither the name of the copyright holders nor the names of its 254762Snate@binkert.org# contributors may be used to endorse or promote products derived from 264762Snate@binkert.org# this software without specific prior written permission. 274762Snate@binkert.org# 284762Snate@binkert.org# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 294762Snate@binkert.org# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 304762Snate@binkert.org# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 314762Snate@binkert.org# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 324762Snate@binkert.org# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 334762Snate@binkert.org# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 344762Snate@binkert.org# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 354762Snate@binkert.org# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 364762Snate@binkert.org# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 374762Snate@binkert.org# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 384762Snate@binkert.org# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 394762Snate@binkert.org# 404762Snate@binkert.org# Authors: Nathan Binkert 414762Snate@binkert.org# Steve Reinhardt 424762Snate@binkert.org 434762Snate@binkert.orgimport atexit 444762Snate@binkert.orgimport os 454762Snate@binkert.orgimport sys 464762Snate@binkert.org 474762Snate@binkert.org# import the SWIG-wrapped main C++ functions 484762Snate@binkert.orgimport internal 496001Snate@binkert.orgimport core 506001Snate@binkert.orgimport stats 514762Snate@binkert.orgimport SimObject 524762Snate@binkert.orgimport ticks 534851Snate@binkert.orgimport objects 548999Suri.wiener@arm.comfrom m5.util.dot_writer import do_dot 558999Suri.wiener@arm.com 567525Ssteve.reinhardt@amd.comfrom util import fatal 578664SAli.Saidi@ARM.comfrom util import attrdict 584762Snate@binkert.org 596654Snate@binkert.org# define a MaxTick parameter 606654Snate@binkert.orgMaxTick = 2**63 - 1 616654Snate@binkert.org 624762Snate@binkert.org# The final hook to generate .ini files. Called from the user script 634762Snate@binkert.org# once the config is built. 647531Ssteve.reinhardt@amd.comdef instantiate(ckpt_dir=None): 658245Snate@binkert.org from m5 import options 668234Snate@binkert.org 677525Ssteve.reinhardt@amd.com root = objects.Root.getInstance() 687525Ssteve.reinhardt@amd.com 697525Ssteve.reinhardt@amd.com if not root: 707525Ssteve.reinhardt@amd.com fatal("Need to instantiate Root() before calling instantiate()") 717525Ssteve.reinhardt@amd.com 724762Snate@binkert.org # we need to fix the global frequency 734762Snate@binkert.org ticks.fixGlobalFrequency() 744762Snate@binkert.org 757528Ssteve.reinhardt@amd.com # Make sure SimObject-valued params are in the configuration 767528Ssteve.reinhardt@amd.com # hierarchy so we catch them with future descendants() walks 777528Ssteve.reinhardt@amd.com for obj in root.descendants(): obj.adoptOrphanParams() 787528Ssteve.reinhardt@amd.com 797527Ssteve.reinhardt@amd.com # Unproxy in sorted order for determinism 807527Ssteve.reinhardt@amd.com for obj in root.descendants(): obj.unproxyParams() 815037Smilesck@eecs.umich.edu 825773Snate@binkert.org if options.dump_config: 835773Snate@binkert.org ini_file = file(os.path.join(options.outdir, options.dump_config), 'w') 847527Ssteve.reinhardt@amd.com # Print ini sections in sorted order for easier diffing 857527Ssteve.reinhardt@amd.com for obj in sorted(root.descendants(), key=lambda o: o.path()): 867527Ssteve.reinhardt@amd.com obj.print_ini(ini_file) 875773Snate@binkert.org ini_file.close() 884762Snate@binkert.org 898664SAli.Saidi@ARM.com if options.json_config: 908675SAli.Saidi@ARM.com try: 918675SAli.Saidi@ARM.com import json 928675SAli.Saidi@ARM.com json_file = file(os.path.join(options.outdir, options.json_config), 'w') 938675SAli.Saidi@ARM.com d = root.get_config_as_dict() 948675SAli.Saidi@ARM.com json.dump(d, json_file, indent=4) 958675SAli.Saidi@ARM.com json_file.close() 968675SAli.Saidi@ARM.com except ImportError: 978675SAli.Saidi@ARM.com pass 988664SAli.Saidi@ARM.com 998999Suri.wiener@arm.com do_dot(root, options.outdir, options.dot_config) 1008664SAli.Saidi@ARM.com 1014762Snate@binkert.org # Initialize the global statistics 1026001Snate@binkert.org stats.initSimStats() 1034762Snate@binkert.org 1044762Snate@binkert.org # Create the C++ sim objects and connect ports 1057527Ssteve.reinhardt@amd.com for obj in root.descendants(): obj.createCCObject() 1067527Ssteve.reinhardt@amd.com for obj in root.descendants(): obj.connectPorts() 1074762Snate@binkert.org 1084762Snate@binkert.org # Do a second pass to finish initializing the sim objects 1097527Ssteve.reinhardt@amd.com for obj in root.descendants(): obj.init() 1104762Snate@binkert.org 1114762Snate@binkert.org # Do a third pass to initialize statistics 1127527Ssteve.reinhardt@amd.com for obj in root.descendants(): obj.regStats() 1134762Snate@binkert.org 1146001Snate@binkert.org # We're done registering statistics. Enable the stats package now. 1156001Snate@binkert.org stats.enable() 1164762Snate@binkert.org 1177531Ssteve.reinhardt@amd.com # Restore checkpoint (if any) 1187531Ssteve.reinhardt@amd.com if ckpt_dir: 1197532Ssteve.reinhardt@amd.com ckpt = internal.core.getCheckpoint(ckpt_dir) 1207532Ssteve.reinhardt@amd.com internal.core.unserializeGlobals(ckpt); 1217532Ssteve.reinhardt@amd.com for obj in root.descendants(): obj.loadState(ckpt) 1227531Ssteve.reinhardt@amd.com need_resume.append(root) 1237532Ssteve.reinhardt@amd.com else: 1247532Ssteve.reinhardt@amd.com for obj in root.descendants(): obj.initState() 1257531Ssteve.reinhardt@amd.com 1264762Snate@binkert.org # Reset to put the stats in a consistent state. 1276001Snate@binkert.org stats.reset() 1284762Snate@binkert.org 1294762Snate@binkert.orgneed_resume = [] 1304762Snate@binkert.orgneed_startup = True 1314762Snate@binkert.orgdef simulate(*args, **kwargs): 1324762Snate@binkert.org global need_resume, need_startup 1334762Snate@binkert.org 1344762Snate@binkert.org if need_startup: 1357527Ssteve.reinhardt@amd.com root = objects.Root.getInstance() 1367527Ssteve.reinhardt@amd.com for obj in root.descendants(): obj.startup() 1374762Snate@binkert.org need_startup = False 1384762Snate@binkert.org 1394762Snate@binkert.org for root in need_resume: 1404762Snate@binkert.org resume(root) 1414762Snate@binkert.org need_resume = [] 1424762Snate@binkert.org 1434762Snate@binkert.org return internal.event.simulate(*args, **kwargs) 1444762Snate@binkert.org 1454762Snate@binkert.org# Export curTick to user script. 1464762Snate@binkert.orgdef curTick(): 1477823Ssteve.reinhardt@amd.com return internal.core.curTick() 1484762Snate@binkert.org 1494762Snate@binkert.org# Python exit handlers happen in reverse order. We want to dump stats last. 1508296Snate@binkert.orgatexit.register(stats.dump) 1514762Snate@binkert.org 1524762Snate@binkert.org# register our C++ exit callback function with Python 1534762Snate@binkert.orgatexit.register(internal.core.doExitCleanup) 1544762Snate@binkert.org 1554762Snate@binkert.org# This loops until all objects have been fully drained. 1564762Snate@binkert.orgdef doDrain(root): 1574762Snate@binkert.org all_drained = drain(root) 1584762Snate@binkert.org while (not all_drained): 1594762Snate@binkert.org all_drained = drain(root) 1604762Snate@binkert.org 1614762Snate@binkert.org# Tries to drain all objects. Draining might not be completed unless 1624762Snate@binkert.org# all objects return that they are drained on the first call. This is 1634762Snate@binkert.org# because as objects drain they may cause other objects to no longer 1644762Snate@binkert.org# be drained. 1654762Snate@binkert.orgdef drain(root): 1664762Snate@binkert.org all_drained = False 1674762Snate@binkert.org drain_event = internal.event.createCountedDrain() 1687527Ssteve.reinhardt@amd.com unready_objs = sum(obj.drain(drain_event) for obj in root.descendants()) 1694762Snate@binkert.org # If we've got some objects that can't drain immediately, then simulate 1707527Ssteve.reinhardt@amd.com if unready_objs > 0: 1717527Ssteve.reinhardt@amd.com drain_event.setCount(unready_objs) 1724762Snate@binkert.org simulate() 1734762Snate@binkert.org else: 1744762Snate@binkert.org all_drained = True 1754762Snate@binkert.org internal.event.cleanupCountedDrain(drain_event) 1764762Snate@binkert.org return all_drained 1774762Snate@binkert.org 1784762Snate@binkert.orgdef resume(root): 1797527Ssteve.reinhardt@amd.com for obj in root.descendants(): obj.resume() 1804762Snate@binkert.org 1817525Ssteve.reinhardt@amd.comdef checkpoint(dir): 1827525Ssteve.reinhardt@amd.com root = objects.Root.getInstance() 1834762Snate@binkert.org if not isinstance(root, objects.Root): 1844762Snate@binkert.org raise TypeError, "Checkpoint must be called on a root object." 1854762Snate@binkert.org doDrain(root) 1864762Snate@binkert.org print "Writing checkpoint" 1874859Snate@binkert.org internal.core.serializeAll(dir) 1884762Snate@binkert.org resume(root) 1894762Snate@binkert.org 1904762Snate@binkert.orgdef changeToAtomic(system): 1914762Snate@binkert.org if not isinstance(system, (objects.Root, objects.System)): 1924762Snate@binkert.org raise TypeError, "Parameter of type '%s'. Must be type %s or %s." % \ 1934762Snate@binkert.org (type(system), objects.Root, objects.System) 1944945Snate@binkert.org if system.getMemoryMode() != objects.params.atomic: 1954762Snate@binkert.org doDrain(system) 1964762Snate@binkert.org print "Changing memory mode to atomic" 1979253SAndreas.Sandberg@arm.com system.setMemoryMode(objects.params.atomic) 1984762Snate@binkert.org 1994762Snate@binkert.orgdef changeToTiming(system): 2004762Snate@binkert.org if not isinstance(system, (objects.Root, objects.System)): 2014762Snate@binkert.org raise TypeError, "Parameter of type '%s'. Must be type %s or %s." % \ 2024762Snate@binkert.org (type(system), objects.Root, objects.System) 2034762Snate@binkert.org 2044945Snate@binkert.org if system.getMemoryMode() != objects.params.timing: 2054762Snate@binkert.org print "Changing memory mode to timing" 2069253SAndreas.Sandberg@arm.com system.setMemoryMode(objects.params.timing) 2074762Snate@binkert.org 2084762Snate@binkert.orgdef switchCpus(cpuList): 2094762Snate@binkert.org print "switching cpus" 2104762Snate@binkert.org if not isinstance(cpuList, list): 2114762Snate@binkert.org raise RuntimeError, "Must pass a list to this function" 2124946Snate@binkert.org for item in cpuList: 2134946Snate@binkert.org if not isinstance(item, tuple) or len(item) != 2: 2144762Snate@binkert.org raise RuntimeError, "List must have tuples of (oldCPU,newCPU)" 2154762Snate@binkert.org 2164946Snate@binkert.org for old_cpu, new_cpu in cpuList: 2174946Snate@binkert.org if not isinstance(old_cpu, objects.BaseCPU): 2184946Snate@binkert.org raise TypeError, "%s is not of type BaseCPU" % old_cpu 2194946Snate@binkert.org if not isinstance(new_cpu, objects.BaseCPU): 2204946Snate@binkert.org raise TypeError, "%s is not of type BaseCPU" % new_cpu 2214762Snate@binkert.org 2224946Snate@binkert.org # Now all of the CPUs are ready to be switched out 2234946Snate@binkert.org for old_cpu, new_cpu in cpuList: 2249254SAndreas.Sandberg@arm.com old_cpu.switchOut() 2254762Snate@binkert.org 2264946Snate@binkert.org for old_cpu, new_cpu in cpuList: 2274946Snate@binkert.org new_cpu.takeOverFrom(old_cpu) 2285523Snate@binkert.org 2295523Snate@binkert.orgfrom internal.core import disableAllListeners 230