Simulation.py revision 8919
15081Sgblack@eecs.umich.edu# Copyright (c) 2006-2008 The Regents of The University of Michigan 25081Sgblack@eecs.umich.edu# Copyright (c) 2010 Advanced Micro Devices, Inc. 35081Sgblack@eecs.umich.edu# All rights reserved. 45081Sgblack@eecs.umich.edu# 55081Sgblack@eecs.umich.edu# Redistribution and use in source and binary forms, with or without 65081Sgblack@eecs.umich.edu# modification, are permitted provided that the following conditions are 75081Sgblack@eecs.umich.edu# met: redistributions of source code must retain the above copyright 85081Sgblack@eecs.umich.edu# notice, this list of conditions and the following disclaimer; 95081Sgblack@eecs.umich.edu# redistributions in binary form must reproduce the above copyright 105081Sgblack@eecs.umich.edu# notice, this list of conditions and the following disclaimer in the 115081Sgblack@eecs.umich.edu# documentation and/or other materials provided with the distribution; 125081Sgblack@eecs.umich.edu# neither the name of the copyright holders nor the names of its 135081Sgblack@eecs.umich.edu# contributors may be used to endorse or promote products derived from 145081Sgblack@eecs.umich.edu# this software without specific prior written permission. 155081Sgblack@eecs.umich.edu# 165081Sgblack@eecs.umich.edu# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 175081Sgblack@eecs.umich.edu# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 185081Sgblack@eecs.umich.edu# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 195081Sgblack@eecs.umich.edu# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 205081Sgblack@eecs.umich.edu# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 215081Sgblack@eecs.umich.edu# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 225081Sgblack@eecs.umich.edu# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 235081Sgblack@eecs.umich.edu# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 245081Sgblack@eecs.umich.edu# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 255081Sgblack@eecs.umich.edu# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 265081Sgblack@eecs.umich.edu# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 275081Sgblack@eecs.umich.edu# 285081Sgblack@eecs.umich.edu# Authors: Lisa Hsu 295081Sgblack@eecs.umich.edu 305081Sgblack@eecs.umich.edufrom os import getcwd 315081Sgblack@eecs.umich.edufrom os.path import join as joinpath 325081Sgblack@eecs.umich.edu 335081Sgblack@eecs.umich.eduimport m5 345081Sgblack@eecs.umich.edufrom m5.defines import buildEnv 355081Sgblack@eecs.umich.edufrom m5.objects import * 365081Sgblack@eecs.umich.edufrom m5.util import * 375081Sgblack@eecs.umich.edufrom O3_ARM_v7a import * 385081Sgblack@eecs.umich.edu 395081Sgblack@eecs.umich.eduaddToPath('../common') 405081Sgblack@eecs.umich.edu 415081Sgblack@eecs.umich.edudef setCPUClass(options): 425081Sgblack@eecs.umich.edu 435081Sgblack@eecs.umich.edu atomic = False 445081Sgblack@eecs.umich.edu if options.cpu_type == "timing": 455081Sgblack@eecs.umich.edu class TmpClass(TimingSimpleCPU): pass 465081Sgblack@eecs.umich.edu elif options.cpu_type == "detailed" or options.cpu_type == "arm_detailed": 475081Sgblack@eecs.umich.edu if not options.caches and not options.ruby: 485081Sgblack@eecs.umich.edu print "O3 CPU must be used with caches" 495081Sgblack@eecs.umich.edu sys.exit(1) 505081Sgblack@eecs.umich.edu if options.cpu_type == "arm_detailed": 515081Sgblack@eecs.umich.edu class TmpClass(O3_ARM_v7a_3): pass 525081Sgblack@eecs.umich.edu else: 535081Sgblack@eecs.umich.edu class TmpClass(DerivO3CPU): pass 545081Sgblack@eecs.umich.edu elif options.cpu_type == "inorder": 555081Sgblack@eecs.umich.edu if not options.caches: 565081Sgblack@eecs.umich.edu print "InOrder CPU must be used with caches" 575081Sgblack@eecs.umich.edu sys.exit(1) 585081Sgblack@eecs.umich.edu class TmpClass(InOrderCPU): pass 595081Sgblack@eecs.umich.edu else: 605081Sgblack@eecs.umich.edu class TmpClass(AtomicSimpleCPU): pass 615081Sgblack@eecs.umich.edu atomic = True 625081Sgblack@eecs.umich.edu 635081Sgblack@eecs.umich.edu CPUClass = None 645081Sgblack@eecs.umich.edu test_mem_mode = 'atomic' 655081Sgblack@eecs.umich.edu 665081Sgblack@eecs.umich.edu if not atomic: 675081Sgblack@eecs.umich.edu if options.checkpoint_restore != None: 685081Sgblack@eecs.umich.edu if options.restore_with_cpu != options.cpu_type: 695081Sgblack@eecs.umich.edu CPUClass = TmpClass 705081Sgblack@eecs.umich.edu class TmpClass(AtomicSimpleCPU): pass 715081Sgblack@eecs.umich.edu else: 725081Sgblack@eecs.umich.edu if options.restore_with_cpu != "atomic": 735081Sgblack@eecs.umich.edu test_mem_mode = 'timing' 745081Sgblack@eecs.umich.edu 755081Sgblack@eecs.umich.edu elif options.fast_forward: 765081Sgblack@eecs.umich.edu CPUClass = TmpClass 775081Sgblack@eecs.umich.edu class TmpClass(AtomicSimpleCPU): pass 785081Sgblack@eecs.umich.edu else: 795081Sgblack@eecs.umich.edu test_mem_mode = 'timing' 805081Sgblack@eecs.umich.edu 815081Sgblack@eecs.umich.edu return (TmpClass, test_mem_mode, CPUClass) 825081Sgblack@eecs.umich.edu 835081Sgblack@eecs.umich.edudef setWorkCountOptions(system, options): 845081Sgblack@eecs.umich.edu if options.work_item_id != None: 855081Sgblack@eecs.umich.edu system.work_item_id = options.work_item_id 865081Sgblack@eecs.umich.edu if options.work_begin_cpu_id_exit != None: 875081Sgblack@eecs.umich.edu system.work_begin_cpu_id_exit = options.work_begin_cpu_id_exit 885081Sgblack@eecs.umich.edu if options.work_end_exit_count != None: 895081Sgblack@eecs.umich.edu system.work_end_exit_count = options.work_end_exit_count 905081Sgblack@eecs.umich.edu if options.work_end_checkpoint_count != None: 915081Sgblack@eecs.umich.edu system.work_end_ckpt_count = options.work_end_checkpoint_count 925081Sgblack@eecs.umich.edu if options.work_begin_exit_count != None: 935081Sgblack@eecs.umich.edu system.work_begin_exit_count = options.work_begin_exit_count 945081Sgblack@eecs.umich.edu if options.work_begin_checkpoint_count != None: 955081Sgblack@eecs.umich.edu system.work_begin_ckpt_count = options.work_begin_checkpoint_count 965081Sgblack@eecs.umich.edu if options.work_cpus_checkpoint_count != None: 975081Sgblack@eecs.umich.edu system.work_cpus_ckpt_count = options.work_cpus_checkpoint_count 985081Sgblack@eecs.umich.edu 995081Sgblack@eecs.umich.edudef run(options, root, testsys, cpu_class): 1005081Sgblack@eecs.umich.edu if options.maxtick: 1015081Sgblack@eecs.umich.edu maxtick = options.maxtick 1025081Sgblack@eecs.umich.edu elif options.maxtime: 1035081Sgblack@eecs.umich.edu simtime = m5.ticks.seconds(simtime) 1045081Sgblack@eecs.umich.edu print "simulating for: ", simtime 1055081Sgblack@eecs.umich.edu maxtick = simtime 1065081Sgblack@eecs.umich.edu else: 1075081Sgblack@eecs.umich.edu maxtick = m5.MaxTick 1085081Sgblack@eecs.umich.edu 1095081Sgblack@eecs.umich.edu if options.checkpoint_dir: 1105081Sgblack@eecs.umich.edu cptdir = options.checkpoint_dir 1115081Sgblack@eecs.umich.edu elif m5.options.outdir: 1125081Sgblack@eecs.umich.edu cptdir = m5.options.outdir 1135081Sgblack@eecs.umich.edu else: 1145081Sgblack@eecs.umich.edu cptdir = getcwd() 1155081Sgblack@eecs.umich.edu 1165081Sgblack@eecs.umich.edu if options.fast_forward and options.checkpoint_restore != None: 1175081Sgblack@eecs.umich.edu fatal("Can't specify both --fast-forward and --checkpoint-restore") 1185081Sgblack@eecs.umich.edu 1195081Sgblack@eecs.umich.edu if options.standard_switch and not options.caches: 1205081Sgblack@eecs.umich.edu fatal("Must specify --caches when using --standard-switch") 1215081Sgblack@eecs.umich.edu 1225081Sgblack@eecs.umich.edu np = options.num_cpus 1235081Sgblack@eecs.umich.edu max_checkpoints = options.max_checkpoints 1245081Sgblack@eecs.umich.edu switch_cpus = None 1255081Sgblack@eecs.umich.edu 1265081Sgblack@eecs.umich.edu if options.prog_interval: 1275081Sgblack@eecs.umich.edu for i in xrange(np): 1285081Sgblack@eecs.umich.edu testsys.cpu[i].progress_interval = options.prog_interval 1295081Sgblack@eecs.umich.edu 1305081Sgblack@eecs.umich.edu if options.maxinsts: 1315081Sgblack@eecs.umich.edu for i in xrange(np): 1325081Sgblack@eecs.umich.edu testsys.cpu[i].max_insts_any_thread = options.maxinsts 1335081Sgblack@eecs.umich.edu 1345081Sgblack@eecs.umich.edu if cpu_class: 1355081Sgblack@eecs.umich.edu switch_cpus = [cpu_class(defer_registration=True, cpu_id=(np+i)) 1365081Sgblack@eecs.umich.edu for i in xrange(np)] 1375081Sgblack@eecs.umich.edu 1385081Sgblack@eecs.umich.edu for i in xrange(np): 1395081Sgblack@eecs.umich.edu if options.fast_forward: 1405081Sgblack@eecs.umich.edu testsys.cpu[i].max_insts_any_thread = int(options.fast_forward) 1415081Sgblack@eecs.umich.edu switch_cpus[i].system = testsys 1425081Sgblack@eecs.umich.edu switch_cpus[i].workload = testsys.cpu[i].workload 1435081Sgblack@eecs.umich.edu switch_cpus[i].clock = testsys.cpu[0].clock 1445081Sgblack@eecs.umich.edu # simulation period 1455081Sgblack@eecs.umich.edu if options.maxinsts: 1465081Sgblack@eecs.umich.edu switch_cpus[i].max_insts_any_thread = options.maxinsts 1475081Sgblack@eecs.umich.edu # Add checker cpu if selected 1485081Sgblack@eecs.umich.edu if options.checker: 1495081Sgblack@eecs.umich.edu switch_cpus[i].addCheckerCpu() 1505081Sgblack@eecs.umich.edu 1515081Sgblack@eecs.umich.edu testsys.switch_cpus = switch_cpus 1525081Sgblack@eecs.umich.edu switch_cpu_list = [(testsys.cpu[i], switch_cpus[i]) for i in xrange(np)] 1535081Sgblack@eecs.umich.edu 1545081Sgblack@eecs.umich.edu if options.standard_switch: 1555081Sgblack@eecs.umich.edu if not options.caches: 1565081Sgblack@eecs.umich.edu # O3 CPU must have a cache to work. 1575081Sgblack@eecs.umich.edu print "O3 CPU must be used with caches" 1585081Sgblack@eecs.umich.edu sys.exit(1) 1595081Sgblack@eecs.umich.edu 1605081Sgblack@eecs.umich.edu switch_cpus = [TimingSimpleCPU(defer_registration=True, cpu_id=(np+i)) 1615081Sgblack@eecs.umich.edu for i in xrange(np)] 1625081Sgblack@eecs.umich.edu switch_cpus_1 = [DerivO3CPU(defer_registration=True, cpu_id=(2*np+i)) 1635081Sgblack@eecs.umich.edu for i in xrange(np)] 1645081Sgblack@eecs.umich.edu 1655081Sgblack@eecs.umich.edu for i in xrange(np): 1665081Sgblack@eecs.umich.edu switch_cpus[i].system = testsys 1675081Sgblack@eecs.umich.edu switch_cpus_1[i].system = testsys 1685081Sgblack@eecs.umich.edu switch_cpus[i].workload = testsys.cpu[i].workload 1695081Sgblack@eecs.umich.edu switch_cpus_1[i].workload = testsys.cpu[i].workload 1705081Sgblack@eecs.umich.edu switch_cpus[i].clock = testsys.cpu[0].clock 1715081Sgblack@eecs.umich.edu switch_cpus_1[i].clock = testsys.cpu[0].clock 1725081Sgblack@eecs.umich.edu 1735081Sgblack@eecs.umich.edu # if restoring, make atomic cpu simulate only a few instructions 1745081Sgblack@eecs.umich.edu if options.checkpoint_restore != None: 1755081Sgblack@eecs.umich.edu testsys.cpu[i].max_insts_any_thread = 1 1765081Sgblack@eecs.umich.edu # Fast forward to specified location if we are not restoring 1775081Sgblack@eecs.umich.edu elif options.fast_forward: 1785081Sgblack@eecs.umich.edu testsys.cpu[i].max_insts_any_thread = int(options.fast_forward) 1795081Sgblack@eecs.umich.edu # Fast forward to a simpoint (warning: time consuming) 1805081Sgblack@eecs.umich.edu elif options.simpoint: 1815081Sgblack@eecs.umich.edu if testsys.cpu[i].workload[0].simpoint == 0: 1825081Sgblack@eecs.umich.edu fatal('simpoint not found') 1835081Sgblack@eecs.umich.edu testsys.cpu[i].max_insts_any_thread = \ 1845081Sgblack@eecs.umich.edu testsys.cpu[i].workload[0].simpoint 1855081Sgblack@eecs.umich.edu # No distance specified, just switch 1865081Sgblack@eecs.umich.edu else: 1875081Sgblack@eecs.umich.edu testsys.cpu[i].max_insts_any_thread = 1 1885081Sgblack@eecs.umich.edu 1895081Sgblack@eecs.umich.edu # warmup period 1905081Sgblack@eecs.umich.edu if options.warmup_insts: 1915081Sgblack@eecs.umich.edu switch_cpus[i].max_insts_any_thread = options.warmup_insts 1925081Sgblack@eecs.umich.edu 1935081Sgblack@eecs.umich.edu # simulation period 1945081Sgblack@eecs.umich.edu if options.maxinsts: 1955081Sgblack@eecs.umich.edu switch_cpus_1[i].max_insts_any_thread = options.maxinsts 1965081Sgblack@eecs.umich.edu 1975081Sgblack@eecs.umich.edu # attach the checker cpu if selected 1985081Sgblack@eecs.umich.edu if options.checker: 1995081Sgblack@eecs.umich.edu switch_cpus[i].addCheckerCpu() 2005081Sgblack@eecs.umich.edu switch_cpus_1[i].addCheckerCpu() 2015081Sgblack@eecs.umich.edu 2025081Sgblack@eecs.umich.edu testsys.switch_cpus = switch_cpus 2035081Sgblack@eecs.umich.edu testsys.switch_cpus_1 = switch_cpus_1 2045081Sgblack@eecs.umich.edu switch_cpu_list = [(testsys.cpu[i], switch_cpus[i]) for i in xrange(np)] 2055081Sgblack@eecs.umich.edu switch_cpu_list1 = [(switch_cpus[i], switch_cpus_1[i]) for i in xrange(np)] 2065081Sgblack@eecs.umich.edu 2075081Sgblack@eecs.umich.edu # set the checkpoint in the cpu before m5.instantiate is called 2085081Sgblack@eecs.umich.edu if options.take_checkpoints != None and \ 2095081Sgblack@eecs.umich.edu (options.simpoint or options.at_instruction): 2105081Sgblack@eecs.umich.edu offset = int(options.take_checkpoints) 2115081Sgblack@eecs.umich.edu # Set an instruction break point 2125081Sgblack@eecs.umich.edu if options.simpoint: 2135081Sgblack@eecs.umich.edu for i in xrange(np): 2145081Sgblack@eecs.umich.edu if testsys.cpu[i].workload[0].simpoint == 0: 2155081Sgblack@eecs.umich.edu fatal('no simpoint for testsys.cpu[%d].workload[0]', i) 2165081Sgblack@eecs.umich.edu checkpoint_inst = int(testsys.cpu[i].workload[0].simpoint) + offset 2175081Sgblack@eecs.umich.edu testsys.cpu[i].max_insts_any_thread = checkpoint_inst 2185081Sgblack@eecs.umich.edu # used for output below 2195081Sgblack@eecs.umich.edu options.take_checkpoints = checkpoint_inst 2205081Sgblack@eecs.umich.edu else: 2215081Sgblack@eecs.umich.edu options.take_checkpoints = offset 2225081Sgblack@eecs.umich.edu # Set all test cpus with the right number of instructions 2235081Sgblack@eecs.umich.edu # for the upcoming simulation 2245081Sgblack@eecs.umich.edu for i in xrange(np): 2255081Sgblack@eecs.umich.edu testsys.cpu[i].max_insts_any_thread = offset 2265081Sgblack@eecs.umich.edu 2275081Sgblack@eecs.umich.edu checkpoint_dir = None 2285081Sgblack@eecs.umich.edu if options.checkpoint_restore != None: 2295081Sgblack@eecs.umich.edu from os.path import isdir, exists 2305081Sgblack@eecs.umich.edu from os import listdir 2315081Sgblack@eecs.umich.edu import re 2325081Sgblack@eecs.umich.edu 2335081Sgblack@eecs.umich.edu if not isdir(cptdir): 2345081Sgblack@eecs.umich.edu fatal("checkpoint dir %s does not exist!", cptdir) 2355081Sgblack@eecs.umich.edu 2365081Sgblack@eecs.umich.edu if options.at_instruction or options.simpoint: 2375081Sgblack@eecs.umich.edu inst = options.checkpoint_restore 2385081Sgblack@eecs.umich.edu if options.simpoint: 2395081Sgblack@eecs.umich.edu # assume workload 0 has the simpoint 2405081Sgblack@eecs.umich.edu if testsys.cpu[0].workload[0].simpoint == 0: 2415081Sgblack@eecs.umich.edu fatal('Unable to find simpoint') 2425081Sgblack@eecs.umich.edu inst += int(testsys.cpu[0].workload[0].simpoint) 2435081Sgblack@eecs.umich.edu 2445081Sgblack@eecs.umich.edu checkpoint_dir = joinpath(cptdir, 2455081Sgblack@eecs.umich.edu "cpt.%s.%s" % (options.bench, inst)) 2465081Sgblack@eecs.umich.edu if not exists(checkpoint_dir): 2475081Sgblack@eecs.umich.edu fatal("Unable to find checkpoint directory %s", checkpoint_dir) 248 else: 249 dirs = listdir(cptdir) 250 expr = re.compile('cpt\.([0-9]*)') 251 cpts = [] 252 for dir in dirs: 253 match = expr.match(dir) 254 if match: 255 cpts.append(match.group(1)) 256 257 cpts.sort(lambda a,b: cmp(long(a), long(b))) 258 259 cpt_num = options.checkpoint_restore 260 261 if cpt_num > len(cpts): 262 fatal('Checkpoint %d not found', cpt_num) 263 264 ## Adjust max tick based on our starting tick 265 maxtick = maxtick - int(cpts[cpt_num - 1]) 266 checkpoint_dir = joinpath(cptdir, "cpt.%s" % cpts[cpt_num - 1]) 267 268 m5.instantiate(checkpoint_dir) 269 270 if options.standard_switch or cpu_class: 271 if options.standard_switch: 272 print "Switch at instruction count:%s" % \ 273 str(testsys.cpu[0].max_insts_any_thread) 274 exit_event = m5.simulate() 275 elif cpu_class and options.fast_forward: 276 print "Switch at instruction count:%s" % \ 277 str(testsys.cpu[0].max_insts_any_thread) 278 exit_event = m5.simulate() 279 else: 280 print "Switch at curTick count:%s" % str(10000) 281 exit_event = m5.simulate(10000) 282 print "Switched CPUS @ tick %s" % (m5.curTick()) 283 284 # when you change to Timing (or Atomic), you halt the system 285 # given as argument. When you are finished with the system 286 # changes (including switchCpus), you must resume the system 287 # manually. You DON'T need to resume after just switching 288 # CPUs if you haven't changed anything on the system level. 289 290 m5.changeToTiming(testsys) 291 m5.switchCpus(switch_cpu_list) 292 m5.resume(testsys) 293 294 if options.standard_switch: 295 print "Switch at instruction count:%d" % \ 296 (testsys.switch_cpus[0].max_insts_any_thread) 297 298 #warmup instruction count may have already been set 299 if options.warmup_insts: 300 exit_event = m5.simulate() 301 else: 302 exit_event = m5.simulate(options.warmup) 303 print "Switching CPUS @ tick %s" % (m5.curTick()) 304 print "Simulation ends instruction count:%d" % \ 305 (testsys.switch_cpus_1[0].max_insts_any_thread) 306 m5.drain(testsys) 307 m5.switchCpus(switch_cpu_list1) 308 m5.resume(testsys) 309 310 num_checkpoints = 0 311 exit_cause = '' 312 313 # If we're taking and restoring checkpoints, use checkpoint_dir 314 # option only for finding the checkpoints to restore from. This 315 # lets us test checkpointing by restoring from one set of 316 # checkpoints, generating a second set, and then comparing them. 317 if options.take_checkpoints and options.checkpoint_restore: 318 if m5.options.outdir: 319 cptdir = m5.options.outdir 320 else: 321 cptdir = getcwd() 322 323 # Checkpoints being taken via the command line at <when> and at 324 # subsequent periods of <period>. Checkpoint instructions 325 # received from the benchmark running are ignored and skipped in 326 # favor of command line checkpoint instructions. 327 if options.take_checkpoints != None : 328 if options.at_instruction or options.simpoint: 329 checkpoint_inst = int(options.take_checkpoints) 330 331 # maintain correct offset if we restored from some instruction 332 if options.checkpoint_restore != None: 333 checkpoint_inst += options.checkpoint_restore 334 335 print "Creating checkpoint at inst:%d" % (checkpoint_inst) 336 exit_event = m5.simulate() 337 print "exit cause = %s" % (exit_event.getCause()) 338 339 # skip checkpoint instructions should they exist 340 while exit_event.getCause() == "checkpoint": 341 exit_event = m5.simulate() 342 343 if exit_event.getCause() == \ 344 "a thread reached the max instruction count": 345 m5.checkpoint(joinpath(cptdir, "cpt.%s.%d" % \ 346 (options.bench, checkpoint_inst))) 347 print "Checkpoint written." 348 num_checkpoints += 1 349 350 if exit_event.getCause() == "user interrupt received": 351 exit_cause = exit_event.getCause(); 352 else: 353 when, period = options.take_checkpoints.split(",", 1) 354 when = int(when) 355 period = int(period) 356 357 exit_event = m5.simulate(when) 358 while exit_event.getCause() == "checkpoint": 359 exit_event = m5.simulate(when - m5.curTick()) 360 361 if exit_event.getCause() == "simulate() limit reached": 362 m5.checkpoint(joinpath(cptdir, "cpt.%d")) 363 num_checkpoints += 1 364 365 sim_ticks = when 366 exit_cause = "maximum %d checkpoints dropped" % max_checkpoints 367 while num_checkpoints < max_checkpoints and \ 368 exit_event.getCause() == "simulate() limit reached": 369 if (sim_ticks + period) > maxtick: 370 exit_event = m5.simulate(maxtick - sim_ticks) 371 exit_cause = exit_event.getCause() 372 break 373 else: 374 exit_event = m5.simulate(period) 375 sim_ticks += period 376 while exit_event.getCause() == "checkpoint": 377 exit_event = m5.simulate(sim_ticks - m5.curTick()) 378 if exit_event.getCause() == "simulate() limit reached": 379 m5.checkpoint(joinpath(cptdir, "cpt.%d")) 380 num_checkpoints += 1 381 382 if exit_event.getCause() != "simulate() limit reached": 383 exit_cause = exit_event.getCause(); 384 385 else: # no checkpoints being taken via this script 386 if options.fast_forward: 387 m5.stats.reset() 388 print "**** REAL SIMULATION ****" 389 exit_event = m5.simulate(maxtick) 390 391 while exit_event.getCause() == "checkpoint": 392 m5.checkpoint(joinpath(cptdir, "cpt.%d")) 393 num_checkpoints += 1 394 if num_checkpoints == max_checkpoints: 395 exit_cause = "maximum %d checkpoints dropped" % max_checkpoints 396 break 397 398 exit_event = m5.simulate(maxtick - m5.curTick()) 399 exit_cause = exit_event.getCause() 400 401 if exit_cause == '': 402 exit_cause = exit_event.getCause() 403 print 'Exiting @ tick %i because %s' % (m5.curTick(), exit_cause) 404 405 if options.checkpoint_at_end: 406 m5.checkpoint(joinpath(cptdir, "cpt.%d")) 407 408