113992Stiago.muck@arm.com# Copyright (c) 2012,2019 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 4312563Sgabeblack@google.comfrom __future__ import print_function 4412563Sgabeblack@google.com 454762Snate@binkert.orgimport atexit 464762Snate@binkert.orgimport os 474762Snate@binkert.orgimport sys 484762Snate@binkert.org 4911991Sandreas.sandberg@arm.com# import the wrapped C++ functions 5011802Sandreas.sandberg@arm.comimport _m5.drain 5111802Sandreas.sandberg@arm.comimport _m5.core 5211802Sandreas.sandberg@arm.comfrom _m5.stats import updateEvents as updateStatEvents 5311802Sandreas.sandberg@arm.com 5413714Sandreas.sandberg@arm.comfrom . import stats 5513714Sandreas.sandberg@arm.comfrom . import SimObject 5613714Sandreas.sandberg@arm.comfrom . import ticks 5713714Sandreas.sandberg@arm.comfrom . import objects 5811418Ssascha.bischoff@arm.comfrom m5.util.dot_writer import do_dot, do_dvfs_dot 5913992Stiago.muck@arm.comfrom m5.util.dot_writer_ruby import do_ruby_dot 608999Suri.wiener@arm.com 6113714Sandreas.sandberg@arm.comfrom .util import fatal 6213714Sandreas.sandberg@arm.comfrom .util import attrdict 634762Snate@binkert.org 649811Sandreas.hansson@arm.com# define a MaxTick parameter, unsigned 64 bit 659811Sandreas.hansson@arm.comMaxTick = 2**64 - 1 666654Snate@binkert.org 679521SAndreas.Sandberg@ARM.com_memory_modes = { 689521SAndreas.Sandberg@ARM.com "atomic" : objects.params.atomic, 699521SAndreas.Sandberg@ARM.com "timing" : objects.params.timing, 709524SAndreas.Sandberg@ARM.com "atomic_noncaching" : objects.params.atomic_noncaching, 719521SAndreas.Sandberg@ARM.com } 729521SAndreas.Sandberg@ARM.com 7311802Sandreas.sandberg@arm.com_drain_manager = _m5.drain.DrainManager.instance() 7410912Sandreas.sandberg@arm.com 754762Snate@binkert.org# The final hook to generate .ini files. Called from the user script 764762Snate@binkert.org# once the config is built. 777531Ssteve.reinhardt@amd.comdef instantiate(ckpt_dir=None): 788245Snate@binkert.org from m5 import options 798234Snate@binkert.org 807525Ssteve.reinhardt@amd.com root = objects.Root.getInstance() 817525Ssteve.reinhardt@amd.com 827525Ssteve.reinhardt@amd.com if not root: 837525Ssteve.reinhardt@amd.com fatal("Need to instantiate Root() before calling instantiate()") 847525Ssteve.reinhardt@amd.com 854762Snate@binkert.org # we need to fix the global frequency 864762Snate@binkert.org ticks.fixGlobalFrequency() 874762Snate@binkert.org 887528Ssteve.reinhardt@amd.com # Make sure SimObject-valued params are in the configuration 897528Ssteve.reinhardt@amd.com # hierarchy so we catch them with future descendants() walks 907528Ssteve.reinhardt@amd.com for obj in root.descendants(): obj.adoptOrphanParams() 917528Ssteve.reinhardt@amd.com 927527Ssteve.reinhardt@amd.com # Unproxy in sorted order for determinism 937527Ssteve.reinhardt@amd.com for obj in root.descendants(): obj.unproxyParams() 945037Smilesck@eecs.umich.edu 955773Snate@binkert.org if options.dump_config: 9613670Sandreas.sandberg@arm.com ini_file = open(os.path.join(options.outdir, options.dump_config), 'w') 977527Ssteve.reinhardt@amd.com # Print ini sections in sorted order for easier diffing 987527Ssteve.reinhardt@amd.com for obj in sorted(root.descendants(), key=lambda o: o.path()): 997527Ssteve.reinhardt@amd.com obj.print_ini(ini_file) 1005773Snate@binkert.org ini_file.close() 1014762Snate@binkert.org 1028664SAli.Saidi@ARM.com if options.json_config: 1038675SAli.Saidi@ARM.com try: 1048675SAli.Saidi@ARM.com import json 10513670Sandreas.sandberg@arm.com json_file = open( 10613670Sandreas.sandberg@arm.com os.path.join(options.outdir, options.json_config), 'w') 1078675SAli.Saidi@ARM.com d = root.get_config_as_dict() 1088675SAli.Saidi@ARM.com json.dump(d, json_file, indent=4) 1098675SAli.Saidi@ARM.com json_file.close() 1108675SAli.Saidi@ARM.com except ImportError: 1118675SAli.Saidi@ARM.com pass 1128664SAli.Saidi@ARM.com 1138999Suri.wiener@arm.com do_dot(root, options.outdir, options.dot_config) 11413992Stiago.muck@arm.com do_ruby_dot(root, options.outdir, options.dot_config) 1158664SAli.Saidi@ARM.com 1164762Snate@binkert.org # Initialize the global statistics 1176001Snate@binkert.org stats.initSimStats() 1184762Snate@binkert.org 1194762Snate@binkert.org # Create the C++ sim objects and connect ports 1207527Ssteve.reinhardt@amd.com for obj in root.descendants(): obj.createCCObject() 1217527Ssteve.reinhardt@amd.com for obj in root.descendants(): obj.connectPorts() 1224762Snate@binkert.org 1234762Snate@binkert.org # Do a second pass to finish initializing the sim objects 1247527Ssteve.reinhardt@amd.com for obj in root.descendants(): obj.init() 1254762Snate@binkert.org 1264762Snate@binkert.org # Do a third pass to initialize statistics 12714205Sandreas.sandberg@arm.com stats._bindStatHierarchy(root) 12814205Sandreas.sandberg@arm.com root.regStats() 1294762Snate@binkert.org 13010023Smatt.horsnell@ARM.com # Do a fourth pass to initialize probe points 13110023Smatt.horsnell@ARM.com for obj in root.descendants(): obj.regProbePoints() 13210023Smatt.horsnell@ARM.com 13310023Smatt.horsnell@ARM.com # Do a fifth pass to connect probe listeners 13410023Smatt.horsnell@ARM.com for obj in root.descendants(): obj.regProbeListeners() 13510023Smatt.horsnell@ARM.com 13611418Ssascha.bischoff@arm.com # We want to generate the DVFS diagram for the system. This can only be 13711418Ssascha.bischoff@arm.com # done once all of the CPP objects have been created and initialised so 13811418Ssascha.bischoff@arm.com # that we are able to figure out which object belongs to which domain. 13911431Ssascha.bischoff@arm.com if options.dot_dvfs_config: 14011431Ssascha.bischoff@arm.com do_dvfs_dot(root, options.outdir, options.dot_dvfs_config) 14111418Ssascha.bischoff@arm.com 1426001Snate@binkert.org # We're done registering statistics. Enable the stats package now. 1436001Snate@binkert.org stats.enable() 1444762Snate@binkert.org 1457531Ssteve.reinhardt@amd.com # Restore checkpoint (if any) 1467531Ssteve.reinhardt@amd.com if ckpt_dir: 14710912Sandreas.sandberg@arm.com _drain_manager.preCheckpointRestore() 14811802Sandreas.sandberg@arm.com ckpt = _m5.core.getCheckpoint(ckpt_dir) 14911802Sandreas.sandberg@arm.com _m5.core.unserializeGlobals(ckpt); 1507532Ssteve.reinhardt@amd.com for obj in root.descendants(): obj.loadState(ckpt) 1517532Ssteve.reinhardt@amd.com else: 1527532Ssteve.reinhardt@amd.com for obj in root.descendants(): obj.initState() 1537531Ssteve.reinhardt@amd.com 1549262Ssascha.bischoff@arm.com # Check to see if any of the stat events are in the past after resuming from 1559262Ssascha.bischoff@arm.com # a checkpoint, If so, this call will shift them to be at a valid time. 1569262Ssascha.bischoff@arm.com updateStatEvents() 1579262Ssascha.bischoff@arm.com 1584762Snate@binkert.orgneed_startup = True 1594762Snate@binkert.orgdef simulate(*args, **kwargs): 16010912Sandreas.sandberg@arm.com global need_startup 1614762Snate@binkert.org 1624762Snate@binkert.org if need_startup: 1637527Ssteve.reinhardt@amd.com root = objects.Root.getInstance() 1647527Ssteve.reinhardt@amd.com for obj in root.descendants(): obj.startup() 1654762Snate@binkert.org need_startup = False 1664762Snate@binkert.org 1679983Sstever@gmail.com # Python exit handlers happen in reverse order. 1689983Sstever@gmail.com # We want to dump stats last. 1699983Sstever@gmail.com atexit.register(stats.dump) 1709983Sstever@gmail.com 1719983Sstever@gmail.com # register our C++ exit callback function with Python 17211802Sandreas.sandberg@arm.com atexit.register(_m5.core.doExitCleanup) 1739983Sstever@gmail.com 1749993Snilay@cs.wisc.edu # Reset to put the stats in a consistent state. 1759993Snilay@cs.wisc.edu stats.reset() 1769993Snilay@cs.wisc.edu 17710912Sandreas.sandberg@arm.com if _drain_manager.isDrained(): 17810912Sandreas.sandberg@arm.com _drain_manager.resume() 1794762Snate@binkert.org 18011802Sandreas.sandberg@arm.com return _m5.event.simulate(*args, **kwargs) 1814762Snate@binkert.org 18210912Sandreas.sandberg@arm.comdef drain(): 18310912Sandreas.sandberg@arm.com """Drain the simulator in preparation of a checkpoint or memory mode 18410912Sandreas.sandberg@arm.com switch. 18510912Sandreas.sandberg@arm.com 18610912Sandreas.sandberg@arm.com This operation is a no-op if the simulator is already in the 18710912Sandreas.sandberg@arm.com Drained state. 18810912Sandreas.sandberg@arm.com 18910912Sandreas.sandberg@arm.com """ 19010912Sandreas.sandberg@arm.com 1919344SAndreas.Sandberg@arm.com # Try to drain all objects. Draining might not be completed unless 1929344SAndreas.Sandberg@arm.com # all objects return that they are drained on the first call. This 1939344SAndreas.Sandberg@arm.com # is because as objects drain they may cause other objects to no 1949344SAndreas.Sandberg@arm.com # longer be drained. 1959344SAndreas.Sandberg@arm.com def _drain(): 19610912Sandreas.sandberg@arm.com # Try to drain the system. The drain is successful if all 19710912Sandreas.sandberg@arm.com # objects are done without simulation. We need to simulate 19810912Sandreas.sandberg@arm.com # more if not. 19910912Sandreas.sandberg@arm.com if _drain_manager.tryDrain(): 20010912Sandreas.sandberg@arm.com return True 20110912Sandreas.sandberg@arm.com 20210912Sandreas.sandberg@arm.com # WARNING: if a valid exit event occurs while draining, it 20310912Sandreas.sandberg@arm.com # will not get returned to the user script 20411802Sandreas.sandberg@arm.com exit_event = _m5.event.simulate() 20510912Sandreas.sandberg@arm.com while exit_event.getCause() != 'Finished drain': 20610436Slukefahr@umich.edu exit_event = simulate() 2079344SAndreas.Sandberg@arm.com 20810912Sandreas.sandberg@arm.com return False 20910912Sandreas.sandberg@arm.com 21010912Sandreas.sandberg@arm.com # Don't try to drain a system that is already drained 21110912Sandreas.sandberg@arm.com is_drained = _drain_manager.isDrained() 21210912Sandreas.sandberg@arm.com while not is_drained: 21310912Sandreas.sandberg@arm.com is_drained = _drain() 21410912Sandreas.sandberg@arm.com 21510912Sandreas.sandberg@arm.com assert _drain_manager.isDrained(), "Drain state inconsistent" 2164762Snate@binkert.org 2179346SAndreas.Sandberg@arm.comdef memWriteback(root): 2189346SAndreas.Sandberg@arm.com for obj in root.descendants(): 2199346SAndreas.Sandberg@arm.com obj.memWriteback() 2209346SAndreas.Sandberg@arm.com 2219346SAndreas.Sandberg@arm.comdef memInvalidate(root): 2229346SAndreas.Sandberg@arm.com for obj in root.descendants(): 2239346SAndreas.Sandberg@arm.com obj.memInvalidate() 2249346SAndreas.Sandberg@arm.com 2257525Ssteve.reinhardt@amd.comdef checkpoint(dir): 2267525Ssteve.reinhardt@amd.com root = objects.Root.getInstance() 2274762Snate@binkert.org if not isinstance(root, objects.Root): 22813663Sandreas.sandberg@arm.com raise TypeError("Checkpoint must be called on a root object.") 22910912Sandreas.sandberg@arm.com 23010912Sandreas.sandberg@arm.com drain() 2319346SAndreas.Sandberg@arm.com memWriteback(root) 23212563Sgabeblack@google.com print("Writing checkpoint") 23311802Sandreas.sandberg@arm.com _m5.core.serializeAll(dir) 2344762Snate@binkert.org 2359521SAndreas.Sandberg@ARM.comdef _changeMemoryMode(system, mode): 2364762Snate@binkert.org if not isinstance(system, (objects.Root, objects.System)): 23713663Sandreas.sandberg@arm.com raise TypeError("Parameter of type '%s'. Must be type %s or %s." % \ 23813663Sandreas.sandberg@arm.com (type(system), objects.Root, objects.System)) 2399343SAndreas.Sandberg@arm.com if system.getMemoryMode() != mode: 2409343SAndreas.Sandberg@arm.com system.setMemoryMode(mode) 2419343SAndreas.Sandberg@arm.com else: 24212563Sgabeblack@google.com print("System already in target mode. Memory mode unchanged.") 2434762Snate@binkert.org 24410912Sandreas.sandberg@arm.comdef switchCpus(system, cpuList, verbose=True): 2459521SAndreas.Sandberg@ARM.com """Switch CPUs in a system. 2464762Snate@binkert.org 2479521SAndreas.Sandberg@ARM.com Note: This method may switch the memory mode of the system if that 2489521SAndreas.Sandberg@ARM.com is required by the CPUs. It may also flush all caches in the 2499521SAndreas.Sandberg@ARM.com system. 2509521SAndreas.Sandberg@ARM.com 2519521SAndreas.Sandberg@ARM.com Arguments: 2529521SAndreas.Sandberg@ARM.com system -- Simulated system. 2539521SAndreas.Sandberg@ARM.com cpuList -- (old_cpu, new_cpu) tuples 2549521SAndreas.Sandberg@ARM.com """ 2559980Ssteve.reinhardt@amd.com 2569980Ssteve.reinhardt@amd.com if verbose: 25712563Sgabeblack@google.com print("switching cpus") 2589980Ssteve.reinhardt@amd.com 2594762Snate@binkert.org if not isinstance(cpuList, list): 26013663Sandreas.sandberg@arm.com raise RuntimeError("Must pass a list to this function") 2614946Snate@binkert.org for item in cpuList: 2624946Snate@binkert.org if not isinstance(item, tuple) or len(item) != 2: 26313663Sandreas.sandberg@arm.com raise RuntimeError("List must have tuples of (oldCPU,newCPU)") 2644762Snate@binkert.org 2659521SAndreas.Sandberg@ARM.com old_cpus = [old_cpu for old_cpu, new_cpu in cpuList] 2669521SAndreas.Sandberg@ARM.com new_cpus = [new_cpu for old_cpu, new_cpu in cpuList] 2679521SAndreas.Sandberg@ARM.com old_cpu_set = set(old_cpus) 2689521SAndreas.Sandberg@ARM.com memory_mode_name = new_cpus[0].memory_mode() 2694946Snate@binkert.org for old_cpu, new_cpu in cpuList: 2704946Snate@binkert.org if not isinstance(old_cpu, objects.BaseCPU): 27113663Sandreas.sandberg@arm.com raise TypeError("%s is not of type BaseCPU" % old_cpu) 2724946Snate@binkert.org if not isinstance(new_cpu, objects.BaseCPU): 27313663Sandreas.sandberg@arm.com raise TypeError("%s is not of type BaseCPU" % new_cpu) 2749430SAndreas.Sandberg@ARM.com if new_cpu in old_cpu_set: 27513663Sandreas.sandberg@arm.com raise RuntimeError( 27613663Sandreas.sandberg@arm.com "New CPU (%s) is in the list of old CPUs." % (old_cpu,)) 2779430SAndreas.Sandberg@ARM.com if not new_cpu.switchedOut(): 27813663Sandreas.sandberg@arm.com raise RuntimeError("New CPU (%s) is already active." % (new_cpu,)) 2799521SAndreas.Sandberg@ARM.com if not new_cpu.support_take_over(): 28013663Sandreas.sandberg@arm.com raise RuntimeError( 28113663Sandreas.sandberg@arm.com "New CPU (%s) does not support CPU handover." % (old_cpu,)) 2829521SAndreas.Sandberg@ARM.com if new_cpu.memory_mode() != memory_mode_name: 28313663Sandreas.sandberg@arm.com raise RuntimeError( 2849521SAndreas.Sandberg@ARM.com "%s and %s require different memory modes." % (new_cpu, 28513663Sandreas.sandberg@arm.com new_cpus[0])) 2869430SAndreas.Sandberg@ARM.com if old_cpu.switchedOut(): 28713663Sandreas.sandberg@arm.com raise RuntimeError("Old CPU (%s) is inactive." % (new_cpu,)) 2889521SAndreas.Sandberg@ARM.com if not old_cpu.support_take_over(): 28913663Sandreas.sandberg@arm.com raise RuntimeError( 29013663Sandreas.sandberg@arm.com "Old CPU (%s) does not support CPU handover." % (old_cpu,)) 2919521SAndreas.Sandberg@ARM.com 2929521SAndreas.Sandberg@ARM.com try: 2939521SAndreas.Sandberg@ARM.com memory_mode = _memory_modes[memory_mode_name] 2949521SAndreas.Sandberg@ARM.com except KeyError: 29513663Sandreas.sandberg@arm.com raise RuntimeError("Invalid memory mode (%s)" % memory_mode_name) 2969521SAndreas.Sandberg@ARM.com 29710912Sandreas.sandberg@arm.com drain() 2984762Snate@binkert.org 2994946Snate@binkert.org # Now all of the CPUs are ready to be switched out 3004946Snate@binkert.org for old_cpu, new_cpu in cpuList: 3019254SAndreas.Sandberg@arm.com old_cpu.switchOut() 3024762Snate@binkert.org 3039521SAndreas.Sandberg@ARM.com # Change the memory mode if required. We check if this is needed 3049521SAndreas.Sandberg@ARM.com # to avoid printing a warning if no switch was performed. 3059521SAndreas.Sandberg@ARM.com if system.getMemoryMode() != memory_mode: 3069524SAndreas.Sandberg@ARM.com # Flush the memory system if we are switching to a memory mode 3079524SAndreas.Sandberg@ARM.com # that disables caches. This typically happens when switching to a 3089524SAndreas.Sandberg@ARM.com # hardware virtualized CPU. 3099524SAndreas.Sandberg@ARM.com if memory_mode == objects.params.atomic_noncaching: 3109524SAndreas.Sandberg@ARM.com memWriteback(system) 3119524SAndreas.Sandberg@ARM.com memInvalidate(system) 3129524SAndreas.Sandberg@ARM.com 3139521SAndreas.Sandberg@ARM.com _changeMemoryMode(system, memory_mode) 3149521SAndreas.Sandberg@ARM.com 3154946Snate@binkert.org for old_cpu, new_cpu in cpuList: 3164946Snate@binkert.org new_cpu.takeOverFrom(old_cpu) 3175523Snate@binkert.org 31811360Sandreas@sandberg.pp.sedef notifyFork(root): 31911360Sandreas@sandberg.pp.se for obj in root.descendants(): 32011360Sandreas@sandberg.pp.se obj.notifyFork() 32111360Sandreas@sandberg.pp.se 32211362Sandreas@sandberg.pp.sefork_count = 0 32311362Sandreas@sandberg.pp.sedef fork(simout="%(parent)s.f%(fork_seq)i"): 32411362Sandreas@sandberg.pp.se """Fork the simulator. 32511362Sandreas@sandberg.pp.se 32611362Sandreas@sandberg.pp.se This function forks the simulator. After forking the simulator, 32711362Sandreas@sandberg.pp.se the child process gets its output files redirected to a new output 32811362Sandreas@sandberg.pp.se directory. The default name of the output directory is the same as 32911362Sandreas@sandberg.pp.se the parent with the suffix ".fN" added where N is the fork 33011362Sandreas@sandberg.pp.se sequence number. The name of the output directory can be 33111362Sandreas@sandberg.pp.se overridden using the simout keyword argument. 33211362Sandreas@sandberg.pp.se 33311362Sandreas@sandberg.pp.se Output file formatting dictionary: 33411362Sandreas@sandberg.pp.se parent -- Path to the parent process's output directory. 33511362Sandreas@sandberg.pp.se fork_seq -- Fork sequence number. 33611362Sandreas@sandberg.pp.se pid -- PID of the child process. 33711362Sandreas@sandberg.pp.se 33811362Sandreas@sandberg.pp.se Keyword Arguments: 33911362Sandreas@sandberg.pp.se simout -- New simulation output directory. 34011362Sandreas@sandberg.pp.se 34111362Sandreas@sandberg.pp.se Return Value: 34211362Sandreas@sandberg.pp.se pid of the child process or 0 if running in the child. 34311362Sandreas@sandberg.pp.se """ 34411362Sandreas@sandberg.pp.se from m5 import options 34511362Sandreas@sandberg.pp.se global fork_count 34611362Sandreas@sandberg.pp.se 34711802Sandreas.sandberg@arm.com if not _m5.core.listenersDisabled(): 34813663Sandreas.sandberg@arm.com raise RuntimeError("Can not fork a simulator with listeners enabled") 34911362Sandreas@sandberg.pp.se 35011362Sandreas@sandberg.pp.se drain() 35111362Sandreas@sandberg.pp.se 35211362Sandreas@sandberg.pp.se try: 35311362Sandreas@sandberg.pp.se pid = os.fork() 35413663Sandreas.sandberg@arm.com except OSError as e: 35511362Sandreas@sandberg.pp.se raise e 35611362Sandreas@sandberg.pp.se 35711362Sandreas@sandberg.pp.se if pid == 0: 35811362Sandreas@sandberg.pp.se # In child, notify objects of the fork 35911362Sandreas@sandberg.pp.se root = objects.Root.getInstance() 36011362Sandreas@sandberg.pp.se notifyFork(root) 36111362Sandreas@sandberg.pp.se # Setup a new output directory 36211362Sandreas@sandberg.pp.se parent = options.outdir 36311362Sandreas@sandberg.pp.se options.outdir = simout % { 36411362Sandreas@sandberg.pp.se "parent" : parent, 36511362Sandreas@sandberg.pp.se "fork_seq" : fork_count, 36611362Sandreas@sandberg.pp.se "pid" : os.getpid(), 36711362Sandreas@sandberg.pp.se } 36811802Sandreas.sandberg@arm.com _m5.core.setOutputDir(options.outdir) 36911362Sandreas@sandberg.pp.se else: 37011362Sandreas@sandberg.pp.se fork_count += 1 37111362Sandreas@sandberg.pp.se 37211362Sandreas@sandberg.pp.se return pid 37311362Sandreas@sandberg.pp.se 37411802Sandreas.sandberg@arm.comfrom _m5.core import disableAllListeners, listenersDisabled 37512011Sgabeblack@google.comfrom _m5.core import listenersLoopbackOnly 37611802Sandreas.sandberg@arm.comfrom _m5.core import curTick 377