simulate.py revision 9524
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 559262Ssascha.bischoff@arm.comfrom m5.internal.stats import updateEvents as updateStatEvents 568999Suri.wiener@arm.com 577525Ssteve.reinhardt@amd.comfrom util import fatal 588664SAli.Saidi@ARM.comfrom util import attrdict 594762Snate@binkert.org 606654Snate@binkert.org# define a MaxTick parameter 616654Snate@binkert.orgMaxTick = 2**63 - 1 626654Snate@binkert.org 639521SAndreas.Sandberg@ARM.com_memory_modes = { 649521SAndreas.Sandberg@ARM.com "atomic" : objects.params.atomic, 659521SAndreas.Sandberg@ARM.com "timing" : objects.params.timing, 669524SAndreas.Sandberg@ARM.com "atomic_noncaching" : objects.params.atomic_noncaching, 679521SAndreas.Sandberg@ARM.com } 689521SAndreas.Sandberg@ARM.com 694762Snate@binkert.org# The final hook to generate .ini files. Called from the user script 704762Snate@binkert.org# once the config is built. 717531Ssteve.reinhardt@amd.comdef instantiate(ckpt_dir=None): 728245Snate@binkert.org from m5 import options 738234Snate@binkert.org 747525Ssteve.reinhardt@amd.com root = objects.Root.getInstance() 757525Ssteve.reinhardt@amd.com 767525Ssteve.reinhardt@amd.com if not root: 777525Ssteve.reinhardt@amd.com fatal("Need to instantiate Root() before calling instantiate()") 787525Ssteve.reinhardt@amd.com 794762Snate@binkert.org # we need to fix the global frequency 804762Snate@binkert.org ticks.fixGlobalFrequency() 814762Snate@binkert.org 827528Ssteve.reinhardt@amd.com # Make sure SimObject-valued params are in the configuration 837528Ssteve.reinhardt@amd.com # hierarchy so we catch them with future descendants() walks 847528Ssteve.reinhardt@amd.com for obj in root.descendants(): obj.adoptOrphanParams() 857528Ssteve.reinhardt@amd.com 867527Ssteve.reinhardt@amd.com # Unproxy in sorted order for determinism 877527Ssteve.reinhardt@amd.com for obj in root.descendants(): obj.unproxyParams() 885037Smilesck@eecs.umich.edu 895773Snate@binkert.org if options.dump_config: 905773Snate@binkert.org ini_file = file(os.path.join(options.outdir, options.dump_config), 'w') 917527Ssteve.reinhardt@amd.com # Print ini sections in sorted order for easier diffing 927527Ssteve.reinhardt@amd.com for obj in sorted(root.descendants(), key=lambda o: o.path()): 937527Ssteve.reinhardt@amd.com obj.print_ini(ini_file) 945773Snate@binkert.org ini_file.close() 954762Snate@binkert.org 968664SAli.Saidi@ARM.com if options.json_config: 978675SAli.Saidi@ARM.com try: 988675SAli.Saidi@ARM.com import json 998675SAli.Saidi@ARM.com json_file = file(os.path.join(options.outdir, options.json_config), 'w') 1008675SAli.Saidi@ARM.com d = root.get_config_as_dict() 1018675SAli.Saidi@ARM.com json.dump(d, json_file, indent=4) 1028675SAli.Saidi@ARM.com json_file.close() 1038675SAli.Saidi@ARM.com except ImportError: 1048675SAli.Saidi@ARM.com pass 1058664SAli.Saidi@ARM.com 1068999Suri.wiener@arm.com do_dot(root, options.outdir, options.dot_config) 1078664SAli.Saidi@ARM.com 1084762Snate@binkert.org # Initialize the global statistics 1096001Snate@binkert.org stats.initSimStats() 1104762Snate@binkert.org 1114762Snate@binkert.org # Create the C++ sim objects and connect ports 1127527Ssteve.reinhardt@amd.com for obj in root.descendants(): obj.createCCObject() 1137527Ssteve.reinhardt@amd.com for obj in root.descendants(): obj.connectPorts() 1144762Snate@binkert.org 1154762Snate@binkert.org # Do a second pass to finish initializing the sim objects 1167527Ssteve.reinhardt@amd.com for obj in root.descendants(): obj.init() 1174762Snate@binkert.org 1184762Snate@binkert.org # Do a third pass to initialize statistics 1197527Ssteve.reinhardt@amd.com for obj in root.descendants(): obj.regStats() 1204762Snate@binkert.org 1216001Snate@binkert.org # We're done registering statistics. Enable the stats package now. 1226001Snate@binkert.org stats.enable() 1234762Snate@binkert.org 1247531Ssteve.reinhardt@amd.com # Restore checkpoint (if any) 1257531Ssteve.reinhardt@amd.com if ckpt_dir: 1267532Ssteve.reinhardt@amd.com ckpt = internal.core.getCheckpoint(ckpt_dir) 1277532Ssteve.reinhardt@amd.com internal.core.unserializeGlobals(ckpt); 1287532Ssteve.reinhardt@amd.com for obj in root.descendants(): obj.loadState(ckpt) 1297531Ssteve.reinhardt@amd.com need_resume.append(root) 1307532Ssteve.reinhardt@amd.com else: 1317532Ssteve.reinhardt@amd.com for obj in root.descendants(): obj.initState() 1327531Ssteve.reinhardt@amd.com 1339262Ssascha.bischoff@arm.com # Check to see if any of the stat events are in the past after resuming from 1349262Ssascha.bischoff@arm.com # a checkpoint, If so, this call will shift them to be at a valid time. 1359262Ssascha.bischoff@arm.com updateStatEvents() 1369262Ssascha.bischoff@arm.com 1374762Snate@binkert.org # Reset to put the stats in a consistent state. 1386001Snate@binkert.org stats.reset() 1394762Snate@binkert.org 1404762Snate@binkert.orgneed_resume = [] 1414762Snate@binkert.orgneed_startup = True 1424762Snate@binkert.orgdef simulate(*args, **kwargs): 1434762Snate@binkert.org global need_resume, need_startup 1444762Snate@binkert.org 1454762Snate@binkert.org if need_startup: 1467527Ssteve.reinhardt@amd.com root = objects.Root.getInstance() 1477527Ssteve.reinhardt@amd.com for obj in root.descendants(): obj.startup() 1484762Snate@binkert.org need_startup = False 1494762Snate@binkert.org 1504762Snate@binkert.org for root in need_resume: 1514762Snate@binkert.org resume(root) 1524762Snate@binkert.org need_resume = [] 1534762Snate@binkert.org 1544762Snate@binkert.org return internal.event.simulate(*args, **kwargs) 1554762Snate@binkert.org 1564762Snate@binkert.org# Export curTick to user script. 1574762Snate@binkert.orgdef curTick(): 1587823Ssteve.reinhardt@amd.com return internal.core.curTick() 1594762Snate@binkert.org 1604762Snate@binkert.org# Python exit handlers happen in reverse order. We want to dump stats last. 1618296Snate@binkert.orgatexit.register(stats.dump) 1624762Snate@binkert.org 1634762Snate@binkert.org# register our C++ exit callback function with Python 1644762Snate@binkert.orgatexit.register(internal.core.doExitCleanup) 1654762Snate@binkert.org 1669344SAndreas.Sandberg@arm.com# Drain the system in preparation of a checkpoint or memory mode 1679344SAndreas.Sandberg@arm.com# switch. 1689344SAndreas.Sandberg@arm.comdef drain(root): 1699344SAndreas.Sandberg@arm.com # Try to drain all objects. Draining might not be completed unless 1709344SAndreas.Sandberg@arm.com # all objects return that they are drained on the first call. This 1719344SAndreas.Sandberg@arm.com # is because as objects drain they may cause other objects to no 1729344SAndreas.Sandberg@arm.com # longer be drained. 1739344SAndreas.Sandberg@arm.com def _drain(): 1749344SAndreas.Sandberg@arm.com all_drained = False 1759344SAndreas.Sandberg@arm.com dm = internal.drain.createDrainManager() 1769344SAndreas.Sandberg@arm.com unready_objs = sum(obj.drain(dm) for obj in root.descendants()) 1779344SAndreas.Sandberg@arm.com # If we've got some objects that can't drain immediately, then simulate 1789344SAndreas.Sandberg@arm.com if unready_objs > 0: 1799344SAndreas.Sandberg@arm.com dm.setCount(unready_objs) 1809344SAndreas.Sandberg@arm.com simulate() 1819344SAndreas.Sandberg@arm.com else: 1829344SAndreas.Sandberg@arm.com all_drained = True 1839344SAndreas.Sandberg@arm.com internal.drain.cleanupDrainManager(dm) 1849344SAndreas.Sandberg@arm.com return all_drained 1859344SAndreas.Sandberg@arm.com 1869344SAndreas.Sandberg@arm.com all_drained = _drain() 1874762Snate@binkert.org while (not all_drained): 1889344SAndreas.Sandberg@arm.com all_drained = _drain() 1894762Snate@binkert.org 1909346SAndreas.Sandberg@arm.comdef memWriteback(root): 1919346SAndreas.Sandberg@arm.com for obj in root.descendants(): 1929346SAndreas.Sandberg@arm.com obj.memWriteback() 1939346SAndreas.Sandberg@arm.com 1949346SAndreas.Sandberg@arm.comdef memInvalidate(root): 1959346SAndreas.Sandberg@arm.com for obj in root.descendants(): 1969346SAndreas.Sandberg@arm.com obj.memInvalidate() 1979346SAndreas.Sandberg@arm.com 1984762Snate@binkert.orgdef resume(root): 1999342SAndreas.Sandberg@arm.com for obj in root.descendants(): obj.drainResume() 2004762Snate@binkert.org 2017525Ssteve.reinhardt@amd.comdef checkpoint(dir): 2027525Ssteve.reinhardt@amd.com root = objects.Root.getInstance() 2034762Snate@binkert.org if not isinstance(root, objects.Root): 2044762Snate@binkert.org raise TypeError, "Checkpoint must be called on a root object." 2059344SAndreas.Sandberg@arm.com drain(root) 2069346SAndreas.Sandberg@arm.com memWriteback(root) 2074762Snate@binkert.org print "Writing checkpoint" 2084859Snate@binkert.org internal.core.serializeAll(dir) 2094762Snate@binkert.org resume(root) 2104762Snate@binkert.org 2119521SAndreas.Sandberg@ARM.comdef _changeMemoryMode(system, mode): 2124762Snate@binkert.org if not isinstance(system, (objects.Root, objects.System)): 2134762Snate@binkert.org raise TypeError, "Parameter of type '%s'. Must be type %s or %s." % \ 2144762Snate@binkert.org (type(system), objects.Root, objects.System) 2159343SAndreas.Sandberg@arm.com if system.getMemoryMode() != mode: 2169344SAndreas.Sandberg@arm.com drain(system) 2179343SAndreas.Sandberg@arm.com system.setMemoryMode(mode) 2189343SAndreas.Sandberg@arm.com else: 2199343SAndreas.Sandberg@arm.com print "System already in target mode. Memory mode unchanged." 2204762Snate@binkert.org 2219521SAndreas.Sandberg@ARM.comdef switchCpus(system, cpuList, do_drain=True): 2229521SAndreas.Sandberg@ARM.com """Switch CPUs in a system. 2234762Snate@binkert.org 2249521SAndreas.Sandberg@ARM.com By default, this method drains and resumes the system. This 2259521SAndreas.Sandberg@ARM.com behavior can be disabled by setting the keyword argument 2269521SAndreas.Sandberg@ARM.com 'do_drain' to false, which might be desirable if multiple 2279521SAndreas.Sandberg@ARM.com operations requiring a drained system are going to be performed in 2289521SAndreas.Sandberg@ARM.com sequence. 2294762Snate@binkert.org 2309521SAndreas.Sandberg@ARM.com Note: This method may switch the memory mode of the system if that 2319521SAndreas.Sandberg@ARM.com is required by the CPUs. It may also flush all caches in the 2329521SAndreas.Sandberg@ARM.com system. 2339521SAndreas.Sandberg@ARM.com 2349521SAndreas.Sandberg@ARM.com Arguments: 2359521SAndreas.Sandberg@ARM.com system -- Simulated system. 2369521SAndreas.Sandberg@ARM.com cpuList -- (old_cpu, new_cpu) tuples 2379521SAndreas.Sandberg@ARM.com 2389521SAndreas.Sandberg@ARM.com Keyword Arguments: 2399521SAndreas.Sandberg@ARM.com do_drain -- Perform a drain/resume of the system when switching. 2409521SAndreas.Sandberg@ARM.com """ 2414762Snate@binkert.org print "switching cpus" 2424762Snate@binkert.org if not isinstance(cpuList, list): 2434762Snate@binkert.org raise RuntimeError, "Must pass a list to this function" 2444946Snate@binkert.org for item in cpuList: 2454946Snate@binkert.org if not isinstance(item, tuple) or len(item) != 2: 2464762Snate@binkert.org raise RuntimeError, "List must have tuples of (oldCPU,newCPU)" 2474762Snate@binkert.org 2489521SAndreas.Sandberg@ARM.com old_cpus = [old_cpu for old_cpu, new_cpu in cpuList] 2499521SAndreas.Sandberg@ARM.com new_cpus = [new_cpu for old_cpu, new_cpu in cpuList] 2509521SAndreas.Sandberg@ARM.com old_cpu_set = set(old_cpus) 2519521SAndreas.Sandberg@ARM.com memory_mode_name = new_cpus[0].memory_mode() 2524946Snate@binkert.org for old_cpu, new_cpu in cpuList: 2534946Snate@binkert.org if not isinstance(old_cpu, objects.BaseCPU): 2544946Snate@binkert.org raise TypeError, "%s is not of type BaseCPU" % old_cpu 2554946Snate@binkert.org if not isinstance(new_cpu, objects.BaseCPU): 2564946Snate@binkert.org raise TypeError, "%s is not of type BaseCPU" % new_cpu 2579430SAndreas.Sandberg@ARM.com if new_cpu in old_cpu_set: 2589430SAndreas.Sandberg@ARM.com raise RuntimeError, \ 2599430SAndreas.Sandberg@ARM.com "New CPU (%s) is in the list of old CPUs." % (old_cpu,) 2609430SAndreas.Sandberg@ARM.com if not new_cpu.switchedOut(): 2619430SAndreas.Sandberg@ARM.com raise RuntimeError, \ 2629430SAndreas.Sandberg@ARM.com "New CPU (%s) is already active." % (new_cpu,) 2639521SAndreas.Sandberg@ARM.com if not new_cpu.support_take_over(): 2649521SAndreas.Sandberg@ARM.com raise RuntimeError, \ 2659521SAndreas.Sandberg@ARM.com "New CPU (%s) does not support CPU handover." % (old_cpu,) 2669521SAndreas.Sandberg@ARM.com if new_cpu.memory_mode() != memory_mode_name: 2679521SAndreas.Sandberg@ARM.com raise RuntimeError, \ 2689521SAndreas.Sandberg@ARM.com "%s and %s require different memory modes." % (new_cpu, 2699521SAndreas.Sandberg@ARM.com new_cpus[0]) 2709430SAndreas.Sandberg@ARM.com if old_cpu.switchedOut(): 2719430SAndreas.Sandberg@ARM.com raise RuntimeError, \ 2729430SAndreas.Sandberg@ARM.com "Old CPU (%s) is inactive." % (new_cpu,) 2739521SAndreas.Sandberg@ARM.com if not old_cpu.support_take_over(): 2749521SAndreas.Sandberg@ARM.com raise RuntimeError, \ 2759521SAndreas.Sandberg@ARM.com "Old CPU (%s) does not support CPU handover." % (old_cpu,) 2769521SAndreas.Sandberg@ARM.com 2779521SAndreas.Sandberg@ARM.com try: 2789521SAndreas.Sandberg@ARM.com memory_mode = _memory_modes[memory_mode_name] 2799521SAndreas.Sandberg@ARM.com except KeyError: 2809521SAndreas.Sandberg@ARM.com raise RuntimeError, "Invalid memory mode (%s)" % memory_mode_name 2819521SAndreas.Sandberg@ARM.com 2829521SAndreas.Sandberg@ARM.com if do_drain: 2839521SAndreas.Sandberg@ARM.com drain(system) 2844762Snate@binkert.org 2854946Snate@binkert.org # Now all of the CPUs are ready to be switched out 2864946Snate@binkert.org for old_cpu, new_cpu in cpuList: 2879254SAndreas.Sandberg@arm.com old_cpu.switchOut() 2884762Snate@binkert.org 2899521SAndreas.Sandberg@ARM.com # Change the memory mode if required. We check if this is needed 2909521SAndreas.Sandberg@ARM.com # to avoid printing a warning if no switch was performed. 2919521SAndreas.Sandberg@ARM.com if system.getMemoryMode() != memory_mode: 2929524SAndreas.Sandberg@ARM.com # Flush the memory system if we are switching to a memory mode 2939524SAndreas.Sandberg@ARM.com # that disables caches. This typically happens when switching to a 2949524SAndreas.Sandberg@ARM.com # hardware virtualized CPU. 2959524SAndreas.Sandberg@ARM.com if memory_mode == objects.params.atomic_noncaching: 2969524SAndreas.Sandberg@ARM.com memWriteback(system) 2979524SAndreas.Sandberg@ARM.com memInvalidate(system) 2989524SAndreas.Sandberg@ARM.com 2999521SAndreas.Sandberg@ARM.com _changeMemoryMode(system, memory_mode) 3009521SAndreas.Sandberg@ARM.com 3014946Snate@binkert.org for old_cpu, new_cpu in cpuList: 3024946Snate@binkert.org new_cpu.takeOverFrom(old_cpu) 3035523Snate@binkert.org 3049521SAndreas.Sandberg@ARM.com if do_drain: 3059521SAndreas.Sandberg@ARM.com resume(system) 3069521SAndreas.Sandberg@ARM.com 3075523Snate@binkert.orgfrom internal.core import disableAllListeners 308