simulate.py revision 7527:fe90827a663f
1# Copyright (c) 2005 The Regents of The University of Michigan 2# All rights reserved. 3# 4# Redistribution and use in source and binary forms, with or without 5# modification, are permitted provided that the following conditions are 6# met: redistributions of source code must retain the above copyright 7# notice, this list of conditions and the following disclaimer; 8# redistributions in binary form must reproduce the above copyright 9# notice, this list of conditions and the following disclaimer in the 10# documentation and/or other materials provided with the distribution; 11# neither the name of the copyright holders nor the names of its 12# contributors may be used to endorse or promote products derived from 13# this software without specific prior written permission. 14# 15# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26# 27# Authors: Nathan Binkert 28# Steve Reinhardt 29 30import atexit 31import os 32import sys 33 34# import the SWIG-wrapped main C++ functions 35import internal 36import core 37import stats 38from main import options 39import SimObject 40import ticks 41import objects 42from util import fatal 43 44# define a MaxTick parameter 45MaxTick = 2**63 - 1 46 47# The final hook to generate .ini files. Called from the user script 48# once the config is built. 49def instantiate(): 50 root = objects.Root.getInstance() 51 52 if not root: 53 fatal("Need to instantiate Root() before calling instantiate()") 54 55 # we need to fix the global frequency 56 ticks.fixGlobalFrequency() 57 58 # Unproxy in sorted order for determinism 59 for obj in root.descendants(): obj.unproxyParams() 60 61 if options.dump_config: 62 ini_file = file(os.path.join(options.outdir, options.dump_config), 'w') 63 # Print ini sections in sorted order for easier diffing 64 for obj in sorted(root.descendants(), key=lambda o: o.path()): 65 obj.print_ini(ini_file) 66 ini_file.close() 67 68 # Initialize the global statistics 69 stats.initSimStats() 70 71 # Create the C++ sim objects and connect ports 72 for obj in root.descendants(): obj.createCCObject() 73 for obj in root.descendants(): obj.connectPorts() 74 75 # Do a second pass to finish initializing the sim objects 76 for obj in root.descendants(): obj.init() 77 78 # Do a third pass to initialize statistics 79 for obj in root.descendants(): obj.regStats() 80 for obj in root.descendants(): obj.regFormulas() 81 82 # We're done registering statistics. Enable the stats package now. 83 stats.enable() 84 85 # Reset to put the stats in a consistent state. 86 stats.reset() 87 88def doDot(root): 89 dot = pydot.Dot() 90 instance.outputDot(dot) 91 dot.orientation = "portrait" 92 dot.size = "8.5,11" 93 dot.ranksep="equally" 94 dot.rank="samerank" 95 dot.write("config.dot") 96 dot.write_ps("config.ps") 97 98need_resume = [] 99need_startup = True 100def simulate(*args, **kwargs): 101 global need_resume, need_startup 102 103 if need_startup: 104 root = objects.Root.getInstance() 105 for obj in root.descendants(): obj.startup() 106 need_startup = False 107 108 for root in need_resume: 109 resume(root) 110 need_resume = [] 111 112 return internal.event.simulate(*args, **kwargs) 113 114# Export curTick to user script. 115def curTick(): 116 return internal.core.cvar.curTick 117 118# Python exit handlers happen in reverse order. We want to dump stats last. 119atexit.register(internal.stats.dump) 120 121# register our C++ exit callback function with Python 122atexit.register(internal.core.doExitCleanup) 123 124# This loops until all objects have been fully drained. 125def doDrain(root): 126 all_drained = drain(root) 127 while (not all_drained): 128 all_drained = drain(root) 129 130# Tries to drain all objects. Draining might not be completed unless 131# all objects return that they are drained on the first call. This is 132# because as objects drain they may cause other objects to no longer 133# be drained. 134def drain(root): 135 all_drained = False 136 drain_event = internal.event.createCountedDrain() 137 unready_objs = sum(obj.drain(drain_event) for obj in root.descendants()) 138 # If we've got some objects that can't drain immediately, then simulate 139 if unready_objs > 0: 140 drain_event.setCount(unready_objs) 141 simulate() 142 else: 143 all_drained = True 144 internal.event.cleanupCountedDrain(drain_event) 145 return all_drained 146 147def resume(root): 148 for obj in root.descendants(): obj.resume() 149 150def checkpoint(dir): 151 root = objects.Root.getInstance() 152 if not isinstance(root, objects.Root): 153 raise TypeError, "Checkpoint must be called on a root object." 154 doDrain(root) 155 print "Writing checkpoint" 156 internal.core.serializeAll(dir) 157 resume(root) 158 159def restoreCheckpoint(dir): 160 root = objects.Root.getInstance() 161 print "Restoring from checkpoint" 162 internal.core.unserializeAll(dir) 163 need_resume.append(root) 164 stats.reset() 165 166def changeToAtomic(system): 167 if not isinstance(system, (objects.Root, objects.System)): 168 raise TypeError, "Parameter of type '%s'. Must be type %s or %s." % \ 169 (type(system), objects.Root, objects.System) 170 if system.getMemoryMode() != objects.params.atomic: 171 doDrain(system) 172 print "Changing memory mode to atomic" 173 for obj in system.descendants(): 174 obj.changeTiming(objects.params.atomic) 175 176def changeToTiming(system): 177 if not isinstance(system, (objects.Root, objects.System)): 178 raise TypeError, "Parameter of type '%s'. Must be type %s or %s." % \ 179 (type(system), objects.Root, objects.System) 180 181 if system.getMemoryMode() != objects.params.timing: 182 doDrain(system) 183 print "Changing memory mode to timing" 184 for obj in system.descendants(): 185 obj.changeTiming(objects.params.timing) 186 187def switchCpus(cpuList): 188 print "switching cpus" 189 if not isinstance(cpuList, list): 190 raise RuntimeError, "Must pass a list to this function" 191 for item in cpuList: 192 if not isinstance(item, tuple) or len(item) != 2: 193 raise RuntimeError, "List must have tuples of (oldCPU,newCPU)" 194 195 for old_cpu, new_cpu in cpuList: 196 if not isinstance(old_cpu, objects.BaseCPU): 197 raise TypeError, "%s is not of type BaseCPU" % old_cpu 198 if not isinstance(new_cpu, objects.BaseCPU): 199 raise TypeError, "%s is not of type BaseCPU" % new_cpu 200 201 # Now all of the CPUs are ready to be switched out 202 for old_cpu, new_cpu in cpuList: 203 old_cpu._ccObject.switchOut() 204 205 for old_cpu, new_cpu in cpuList: 206 new_cpu.takeOverFrom(old_cpu) 207 208from internal.core import disableAllListeners 209