Simulation.py revision 12880
12579SN/A# Copyright (c) 2012-2013 ARM Limited
22579SN/A# All rights reserved
32579SN/A#
42579SN/A# The license below extends only to copyright in the software and shall
52579SN/A# not be construed as granting a license to any other intellectual
62579SN/A# property including but not limited to intellectual property relating
72579SN/A# to a hardware implementation of the functionality of the software
82579SN/A# licensed hereunder.  You may use the software subject to the license
92579SN/A# terms below provided that you ensure that this notice is replicated
102579SN/A# unmodified and in its entirety in all distributions of the software,
112579SN/A# modified or unmodified, in source code or in binary form.
122579SN/A#
132579SN/A# Copyright (c) 2006-2008 The Regents of The University of Michigan
142579SN/A# Copyright (c) 2010 Advanced Micro Devices, Inc.
152579SN/A# All rights reserved.
162579SN/A#
172579SN/A# Redistribution and use in source and binary forms, with or without
182579SN/A# modification, are permitted provided that the following conditions are
192579SN/A# met: redistributions of source code must retain the above copyright
202579SN/A# notice, this list of conditions and the following disclaimer;
212579SN/A# redistributions in binary form must reproduce the above copyright
222579SN/A# notice, this list of conditions and the following disclaimer in the
232579SN/A# documentation and/or other materials provided with the distribution;
242579SN/A# neither the name of the copyright holders nor the names of its
252579SN/A# contributors may be used to endorse or promote products derived from
262579SN/A# this software without specific prior written permission.
272665Ssaidi@eecs.umich.edu#
282665Ssaidi@eecs.umich.edu# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
292579SN/A# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
302579SN/A# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
312599SN/A# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
322599SN/A# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
332579SN/A# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
342579SN/A# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
352579SN/A# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
362579SN/A# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
372579SN/A# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
382579SN/A# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
392579SN/A#
403113Sgblack@eecs.umich.edu# Authors: Lisa Hsu
413113Sgblack@eecs.umich.edu
423113Sgblack@eecs.umich.edufrom __future__ import print_function
433113Sgblack@eecs.umich.edu
443113Sgblack@eecs.umich.eduimport sys
453113Sgblack@eecs.umich.edufrom os import getcwd
463113Sgblack@eecs.umich.edufrom os.path import join as joinpath
473113Sgblack@eecs.umich.edu
483113Sgblack@eecs.umich.edufrom common import CpuConfig
493113Sgblack@eecs.umich.edufrom common import MemConfig
503113Sgblack@eecs.umich.edu
513113Sgblack@eecs.umich.eduimport m5
523113Sgblack@eecs.umich.edufrom m5.defines import buildEnv
533113Sgblack@eecs.umich.edufrom m5.objects import *
543113Sgblack@eecs.umich.edufrom m5.util import *
553113Sgblack@eecs.umich.edu
563113Sgblack@eecs.umich.eduaddToPath('../common')
573113Sgblack@eecs.umich.edu
583113Sgblack@eecs.umich.edudef getCPUClass(cpu_type):
592579SN/A    """Returns the required cpu class and the mode of operation."""
602579SN/A    cls = CpuConfig.get(cpu_type)
615543Ssaidi@eecs.umich.edu    return cls, cls.memory_mode()
625543Ssaidi@eecs.umich.edu
635543Ssaidi@eecs.umich.edudef setCPUClass(options):
645543Ssaidi@eecs.umich.edu    """Returns two cpu classes and the initial mode of operation.
655543Ssaidi@eecs.umich.edu
665543Ssaidi@eecs.umich.edu       Restoring from a checkpoint or fast forwarding through a benchmark
675543Ssaidi@eecs.umich.edu       can be done using one type of cpu, and then the actual
685543Ssaidi@eecs.umich.edu       simulation can be carried out using another type. This function
695543Ssaidi@eecs.umich.edu       returns these two types of cpus and the initial mode of operation
705543Ssaidi@eecs.umich.edu       depending on the options provided.
715543Ssaidi@eecs.umich.edu    """
725543Ssaidi@eecs.umich.edu
735543Ssaidi@eecs.umich.edu    TmpClass, test_mem_mode = getCPUClass(options.cpu_type)
745543Ssaidi@eecs.umich.edu    CPUClass = None
755543Ssaidi@eecs.umich.edu    if TmpClass.require_caches() and \
762579SN/A            not options.caches and not options.ruby:
772579SN/A        fatal("%s must be used with caches" % options.cpu_type)
782579SN/A
792579SN/A    if options.checkpoint_restore != None:
808600Ssteve.reinhardt@amd.com        if options.restore_with_cpu != options.cpu_type:
816640Svince@csl.cornell.edu            CPUClass = TmpClass
826640Svince@csl.cornell.edu            TmpClass, test_mem_mode = getCPUClass(options.restore_with_cpu)
836640Svince@csl.cornell.edu    elif options.fast_forward:
846640Svince@csl.cornell.edu        CPUClass = TmpClass
856640Svince@csl.cornell.edu        TmpClass = AtomicSimpleCPU
866640Svince@csl.cornell.edu        test_mem_mode = 'atomic'
876640Svince@csl.cornell.edu
886640Svince@csl.cornell.edu    # Ruby only supports atomic accesses in noncaching mode
896640Svince@csl.cornell.edu    if test_mem_mode == 'atomic' and options.ruby:
906640Svince@csl.cornell.edu        warn("Memory mode will be changed to atomic_noncaching")
916640Svince@csl.cornell.edu        test_mem_mode = 'atomic_noncaching'
926640Svince@csl.cornell.edu
936640Svince@csl.cornell.edu    return (TmpClass, test_mem_mode, CPUClass)
946640Svince@csl.cornell.edu
956640Svince@csl.cornell.edudef setMemClass(options):
966640Svince@csl.cornell.edu    """Returns a memory controller class."""
972579SN/A
982579SN/A    return MemConfig.get(options.mem_type)
994188Sgblack@eecs.umich.edu
1004188Sgblack@eecs.umich.edudef setWorkCountOptions(system, options):
1014188Sgblack@eecs.umich.edu    if options.work_item_id != None:
1024188Sgblack@eecs.umich.edu        system.work_item_id = options.work_item_id
1034188Sgblack@eecs.umich.edu    if options.num_work_ids != None:
1044188Sgblack@eecs.umich.edu        system.num_work_ids = options.num_work_ids
1054188Sgblack@eecs.umich.edu    if options.work_begin_cpu_id_exit != None:
1064188Sgblack@eecs.umich.edu        system.work_begin_cpu_id_exit = options.work_begin_cpu_id_exit
1074188Sgblack@eecs.umich.edu    if options.work_end_exit_count != None:
1084188Sgblack@eecs.umich.edu        system.work_end_exit_count = options.work_end_exit_count
1094188Sgblack@eecs.umich.edu    if options.work_end_checkpoint_count != None:
1104188Sgblack@eecs.umich.edu        system.work_end_ckpt_count = options.work_end_checkpoint_count
1114188Sgblack@eecs.umich.edu    if options.work_begin_exit_count != None:
1124188Sgblack@eecs.umich.edu        system.work_begin_exit_count = options.work_begin_exit_count
1134188Sgblack@eecs.umich.edu    if options.work_begin_checkpoint_count != None:
1144188Sgblack@eecs.umich.edu        system.work_begin_ckpt_count = options.work_begin_checkpoint_count
1154188Sgblack@eecs.umich.edu    if options.work_cpus_checkpoint_count != None:
1164188Sgblack@eecs.umich.edu        system.work_cpus_ckpt_count = options.work_cpus_checkpoint_count
1174188Sgblack@eecs.umich.edu
1184188Sgblack@eecs.umich.edudef findCptDir(options, cptdir, testsys):
1194188Sgblack@eecs.umich.edu    """Figures out the directory from which the checkpointed state is read.
1204188Sgblack@eecs.umich.edu
1214188Sgblack@eecs.umich.edu    There are two different ways in which the directories holding checkpoints
1224188Sgblack@eecs.umich.edu    can be named --
1234188Sgblack@eecs.umich.edu    1. cpt.<benchmark name>.<instruction count when the checkpoint was taken>
1244188Sgblack@eecs.umich.edu    2. cpt.<some number, usually the tick value when the checkpoint was taken>
1256640Svince@csl.cornell.edu
1266640Svince@csl.cornell.edu    This function parses through the options to figure out which one of the
1276640Svince@csl.cornell.edu    above should be used for selecting the checkpoint, and then figures out
1286640Svince@csl.cornell.edu    the appropriate directory.
1296640Svince@csl.cornell.edu    """
1306640Svince@csl.cornell.edu
1316640Svince@csl.cornell.edu    from os.path import isdir, exists
1326640Svince@csl.cornell.edu    from os import listdir
1336640Svince@csl.cornell.edu    import re
1346640Svince@csl.cornell.edu
1356640Svince@csl.cornell.edu    if not isdir(cptdir):
1366640Svince@csl.cornell.edu        fatal("checkpoint dir %s does not exist!", cptdir)
1376640Svince@csl.cornell.edu
1386640Svince@csl.cornell.edu    cpt_starttick = 0
1396640Svince@csl.cornell.edu    if options.at_instruction or options.simpoint:
1406640Svince@csl.cornell.edu        inst = options.checkpoint_restore
1414188Sgblack@eecs.umich.edu        if options.simpoint:
1424188Sgblack@eecs.umich.edu            # assume workload 0 has the simpoint
1432579SN/A            if testsys.cpu[0].workload[0].simpoint == 0:
144                fatal('Unable to find simpoint')
145            inst += int(testsys.cpu[0].workload[0].simpoint)
146
147        checkpoint_dir = joinpath(cptdir, "cpt.%s.%s" % (options.bench, inst))
148        if not exists(checkpoint_dir):
149            fatal("Unable to find checkpoint directory %s", checkpoint_dir)
150
151    elif options.restore_simpoint_checkpoint:
152        # Restore from SimPoint checkpoints
153        # Assumes that the checkpoint dir names are formatted as follows:
154        dirs = listdir(cptdir)
155        expr = re.compile('cpt\.simpoint_(\d+)_inst_(\d+)' +
156                    '_weight_([\d\.e\-]+)_interval_(\d+)_warmup_(\d+)')
157        cpts = []
158        for dir in dirs:
159            match = expr.match(dir)
160            if match:
161                cpts.append(dir)
162        cpts.sort()
163
164        cpt_num = options.checkpoint_restore
165        if cpt_num > len(cpts):
166            fatal('Checkpoint %d not found', cpt_num)
167        checkpoint_dir = joinpath(cptdir, cpts[cpt_num - 1])
168        match = expr.match(cpts[cpt_num - 1])
169        if match:
170            index = int(match.group(1))
171            start_inst = int(match.group(2))
172            weight_inst = float(match.group(3))
173            interval_length = int(match.group(4))
174            warmup_length = int(match.group(5))
175        print("Resuming from", checkpoint_dir)
176        simpoint_start_insts = []
177        simpoint_start_insts.append(warmup_length)
178        simpoint_start_insts.append(warmup_length + interval_length)
179        testsys.cpu[0].simpoint_start_insts = simpoint_start_insts
180        if testsys.switch_cpus != None:
181            testsys.switch_cpus[0].simpoint_start_insts = simpoint_start_insts
182
183        print("Resuming from SimPoint", end=' ')
184        print("#%d, start_inst:%d, weight:%f, interval:%d, warmup:%d" %
185            (index, start_inst, weight_inst, interval_length, warmup_length))
186
187    else:
188        dirs = listdir(cptdir)
189        expr = re.compile('cpt\.([0-9]+)')
190        cpts = []
191        for dir in dirs:
192            match = expr.match(dir)
193            if match:
194                cpts.append(match.group(1))
195
196        cpts.sort(lambda a,b: cmp(long(a), long(b)))
197
198        cpt_num = options.checkpoint_restore
199        if cpt_num > len(cpts):
200            fatal('Checkpoint %d not found', cpt_num)
201
202        cpt_starttick = int(cpts[cpt_num - 1])
203        checkpoint_dir = joinpath(cptdir, "cpt.%s" % cpts[cpt_num - 1])
204
205    return cpt_starttick, checkpoint_dir
206
207def scriptCheckpoints(options, maxtick, cptdir):
208    if options.at_instruction or options.simpoint:
209        checkpoint_inst = int(options.take_checkpoints)
210
211        # maintain correct offset if we restored from some instruction
212        if options.checkpoint_restore != None:
213            checkpoint_inst += options.checkpoint_restore
214
215        print("Creating checkpoint at inst:%d" % (checkpoint_inst))
216        exit_event = m5.simulate()
217        exit_cause = exit_event.getCause()
218        print("exit cause = %s" % exit_cause)
219
220        # skip checkpoint instructions should they exist
221        while exit_cause == "checkpoint":
222            exit_event = m5.simulate()
223            exit_cause = exit_event.getCause()
224
225        if exit_cause == "a thread reached the max instruction count":
226            m5.checkpoint(joinpath(cptdir, "cpt.%s.%d" % \
227                    (options.bench, checkpoint_inst)))
228            print("Checkpoint written.")
229
230    else:
231        when, period = options.take_checkpoints.split(",", 1)
232        when = int(when)
233        period = int(period)
234        num_checkpoints = 0
235
236        exit_event = m5.simulate(when - m5.curTick())
237        exit_cause = exit_event.getCause()
238        while exit_cause == "checkpoint":
239            exit_event = m5.simulate(when - m5.curTick())
240            exit_cause = exit_event.getCause()
241
242        if exit_cause == "simulate() limit reached":
243            m5.checkpoint(joinpath(cptdir, "cpt.%d"))
244            num_checkpoints += 1
245
246        sim_ticks = when
247        max_checkpoints = options.max_checkpoints
248
249        while num_checkpoints < max_checkpoints and \
250                exit_cause == "simulate() limit reached":
251            if (sim_ticks + period) > maxtick:
252                exit_event = m5.simulate(maxtick - sim_ticks)
253                exit_cause = exit_event.getCause()
254                break
255            else:
256                exit_event = m5.simulate(period)
257                exit_cause = exit_event.getCause()
258                sim_ticks += period
259                while exit_event.getCause() == "checkpoint":
260                    exit_event = m5.simulate(sim_ticks - m5.curTick())
261                if exit_event.getCause() == "simulate() limit reached":
262                    m5.checkpoint(joinpath(cptdir, "cpt.%d"))
263                    num_checkpoints += 1
264
265    return exit_event
266
267def benchCheckpoints(options, maxtick, cptdir):
268    exit_event = m5.simulate(maxtick - m5.curTick())
269    exit_cause = exit_event.getCause()
270
271    num_checkpoints = 0
272    max_checkpoints = options.max_checkpoints
273
274    while exit_cause == "checkpoint":
275        m5.checkpoint(joinpath(cptdir, "cpt.%d"))
276        num_checkpoints += 1
277        if num_checkpoints == max_checkpoints:
278            exit_cause = "maximum %d checkpoints dropped" % max_checkpoints
279            break
280
281        exit_event = m5.simulate(maxtick - m5.curTick())
282        exit_cause = exit_event.getCause()
283
284    return exit_event
285
286# Set up environment for taking SimPoint checkpoints
287# Expecting SimPoint files generated by SimPoint 3.2
288def parseSimpointAnalysisFile(options, testsys):
289    import re
290
291    simpoint_filename, weight_filename, interval_length, warmup_length = \
292        options.take_simpoint_checkpoints.split(",", 3)
293    print("simpoint analysis file:", simpoint_filename)
294    print("simpoint weight file:", weight_filename)
295    print("interval length:", interval_length)
296    print("warmup length:", warmup_length)
297
298    interval_length = int(interval_length)
299    warmup_length = int(warmup_length)
300
301    # Simpoint analysis output starts interval counts with 0.
302    simpoints = []
303    simpoint_start_insts = []
304
305    # Read in SimPoint analysis files
306    simpoint_file = open(simpoint_filename)
307    weight_file = open(weight_filename)
308    while True:
309        line = simpoint_file.readline()
310        if not line:
311            break
312        m = re.match("(\d+)\s+(\d+)", line)
313        if m:
314            interval = int(m.group(1))
315        else:
316            fatal('unrecognized line in simpoint file!')
317
318        line = weight_file.readline()
319        if not line:
320            fatal('not enough lines in simpoint weight file!')
321        m = re.match("([0-9\.e\-]+)\s+(\d+)", line)
322        if m:
323            weight = float(m.group(1))
324        else:
325            fatal('unrecognized line in simpoint weight file!')
326
327        if (interval * interval_length - warmup_length > 0):
328            starting_inst_count = \
329                interval * interval_length - warmup_length
330            actual_warmup_length = warmup_length
331        else:
332            # Not enough room for proper warmup
333            # Just starting from the beginning
334            starting_inst_count = 0
335            actual_warmup_length = interval * interval_length
336
337        simpoints.append((interval, weight, starting_inst_count,
338            actual_warmup_length))
339
340    # Sort SimPoints by starting inst count
341    simpoints.sort(key=lambda obj: obj[2])
342    for s in simpoints:
343        interval, weight, starting_inst_count, actual_warmup_length = s
344        print(str(interval), str(weight), starting_inst_count,
345            actual_warmup_length)
346        simpoint_start_insts.append(starting_inst_count)
347
348    print("Total # of simpoints:", len(simpoints))
349    testsys.cpu[0].simpoint_start_insts = simpoint_start_insts
350
351    return (simpoints, interval_length)
352
353def takeSimpointCheckpoints(simpoints, interval_length, cptdir):
354    num_checkpoints = 0
355    index = 0
356    last_chkpnt_inst_count = -1
357    for simpoint in simpoints:
358        interval, weight, starting_inst_count, actual_warmup_length = simpoint
359        if starting_inst_count == last_chkpnt_inst_count:
360            # checkpoint starting point same as last time
361            # (when warmup period longer than starting point)
362            exit_cause = "simpoint starting point found"
363            code = 0
364        else:
365            exit_event = m5.simulate()
366
367            # skip checkpoint instructions should they exist
368            while exit_event.getCause() == "checkpoint":
369                print("Found 'checkpoint' exit event...ignoring...")
370                exit_event = m5.simulate()
371
372            exit_cause = exit_event.getCause()
373            code = exit_event.getCode()
374
375        if exit_cause == "simpoint starting point found":
376            m5.checkpoint(joinpath(cptdir,
377                "cpt.simpoint_%02d_inst_%d_weight_%f_interval_%d_warmup_%d"
378                % (index, starting_inst_count, weight, interval_length,
379                actual_warmup_length)))
380            print("Checkpoint #%d written. start inst:%d weight:%f" %
381                (num_checkpoints, starting_inst_count, weight))
382            num_checkpoints += 1
383            last_chkpnt_inst_count = starting_inst_count
384        else:
385            break
386        index += 1
387
388    print('Exiting @ tick %i because %s' % (m5.curTick(), exit_cause))
389    print("%d checkpoints taken" % num_checkpoints)
390    sys.exit(code)
391
392def restoreSimpointCheckpoint():
393    exit_event = m5.simulate()
394    exit_cause = exit_event.getCause()
395
396    if exit_cause == "simpoint starting point found":
397        print("Warmed up! Dumping and resetting stats!")
398        m5.stats.dump()
399        m5.stats.reset()
400
401        exit_event = m5.simulate()
402        exit_cause = exit_event.getCause()
403
404        if exit_cause == "simpoint starting point found":
405            print("Done running SimPoint!")
406            sys.exit(exit_event.getCode())
407
408    print('Exiting @ tick %i because %s' % (m5.curTick(), exit_cause))
409    sys.exit(exit_event.getCode())
410
411def repeatSwitch(testsys, repeat_switch_cpu_list, maxtick, switch_freq):
412    print("starting switch loop")
413    while True:
414        exit_event = m5.simulate(switch_freq)
415        exit_cause = exit_event.getCause()
416
417        if exit_cause != "simulate() limit reached":
418            return exit_event
419
420        m5.switchCpus(testsys, repeat_switch_cpu_list)
421
422        tmp_cpu_list = []
423        for old_cpu, new_cpu in repeat_switch_cpu_list:
424            tmp_cpu_list.append((new_cpu, old_cpu))
425        repeat_switch_cpu_list = tmp_cpu_list
426
427        if (maxtick - m5.curTick()) <= switch_freq:
428            exit_event = m5.simulate(maxtick - m5.curTick())
429            return exit_event
430
431def run(options, root, testsys, cpu_class):
432    if options.checkpoint_dir:
433        cptdir = options.checkpoint_dir
434    elif m5.options.outdir:
435        cptdir = m5.options.outdir
436    else:
437        cptdir = getcwd()
438
439    if options.fast_forward and options.checkpoint_restore != None:
440        fatal("Can't specify both --fast-forward and --checkpoint-restore")
441
442    if options.standard_switch and not options.caches:
443        fatal("Must specify --caches when using --standard-switch")
444
445    if options.standard_switch and options.repeat_switch:
446        fatal("Can't specify both --standard-switch and --repeat-switch")
447
448    if options.repeat_switch and options.take_checkpoints:
449        fatal("Can't specify both --repeat-switch and --take-checkpoints")
450
451    np = options.num_cpus
452    switch_cpus = None
453
454    if options.prog_interval:
455        for i in xrange(np):
456            testsys.cpu[i].progress_interval = options.prog_interval
457
458    if options.maxinsts:
459        for i in xrange(np):
460            testsys.cpu[i].max_insts_any_thread = options.maxinsts
461
462    if cpu_class:
463        switch_cpus = [cpu_class(switched_out=True, cpu_id=(i))
464                       for i in xrange(np)]
465
466        for i in xrange(np):
467            if options.fast_forward:
468                testsys.cpu[i].max_insts_any_thread = int(options.fast_forward)
469            switch_cpus[i].system = testsys
470            switch_cpus[i].workload = testsys.cpu[i].workload
471            switch_cpus[i].clk_domain = testsys.cpu[i].clk_domain
472            switch_cpus[i].progress_interval = \
473                testsys.cpu[i].progress_interval
474            switch_cpus[i].isa = testsys.cpu[i].isa
475            # simulation period
476            if options.maxinsts:
477                switch_cpus[i].max_insts_any_thread = options.maxinsts
478            # Add checker cpu if selected
479            if options.checker:
480                switch_cpus[i].addCheckerCpu()
481
482        # If elastic tracing is enabled attach the elastic trace probe
483        # to the switch CPUs
484        if options.elastic_trace_en:
485            CpuConfig.config_etrace(cpu_class, switch_cpus, options)
486
487        testsys.switch_cpus = switch_cpus
488        switch_cpu_list = [(testsys.cpu[i], switch_cpus[i]) for i in xrange(np)]
489
490    if options.repeat_switch:
491        switch_class = getCPUClass(options.cpu_type)[0]
492        if switch_class.require_caches() and \
493                not options.caches:
494            print("%s: Must be used with caches" % str(switch_class))
495            sys.exit(1)
496        if not switch_class.support_take_over():
497            print("%s: CPU switching not supported" % str(switch_class))
498            sys.exit(1)
499
500        repeat_switch_cpus = [switch_class(switched_out=True, \
501                                               cpu_id=(i)) for i in xrange(np)]
502
503        for i in xrange(np):
504            repeat_switch_cpus[i].system = testsys
505            repeat_switch_cpus[i].workload = testsys.cpu[i].workload
506            repeat_switch_cpus[i].clk_domain = testsys.cpu[i].clk_domain
507            repeat_switch_cpus[i].isa = testsys.cpu[i].isa
508
509            if options.maxinsts:
510                repeat_switch_cpus[i].max_insts_any_thread = options.maxinsts
511
512            if options.checker:
513                repeat_switch_cpus[i].addCheckerCpu()
514
515        testsys.repeat_switch_cpus = repeat_switch_cpus
516
517        if cpu_class:
518            repeat_switch_cpu_list = [(switch_cpus[i], repeat_switch_cpus[i])
519                                      for i in xrange(np)]
520        else:
521            repeat_switch_cpu_list = [(testsys.cpu[i], repeat_switch_cpus[i])
522                                      for i in xrange(np)]
523
524    if options.standard_switch:
525        switch_cpus = [TimingSimpleCPU(switched_out=True, cpu_id=(i))
526                       for i in xrange(np)]
527        switch_cpus_1 = [DerivO3CPU(switched_out=True, cpu_id=(i))
528                        for i in xrange(np)]
529
530        for i in xrange(np):
531            switch_cpus[i].system =  testsys
532            switch_cpus_1[i].system =  testsys
533            switch_cpus[i].workload = testsys.cpu[i].workload
534            switch_cpus_1[i].workload = testsys.cpu[i].workload
535            switch_cpus[i].clk_domain = testsys.cpu[i].clk_domain
536            switch_cpus_1[i].clk_domain = testsys.cpu[i].clk_domain
537            switch_cpus[i].isa = testsys.cpu[i].isa
538            switch_cpus_1[i].isa = testsys.cpu[i].isa
539
540            # if restoring, make atomic cpu simulate only a few instructions
541            if options.checkpoint_restore != None:
542                testsys.cpu[i].max_insts_any_thread = 1
543            # Fast forward to specified location if we are not restoring
544            elif options.fast_forward:
545                testsys.cpu[i].max_insts_any_thread = int(options.fast_forward)
546            # Fast forward to a simpoint (warning: time consuming)
547            elif options.simpoint:
548                if testsys.cpu[i].workload[0].simpoint == 0:
549                    fatal('simpoint not found')
550                testsys.cpu[i].max_insts_any_thread = \
551                    testsys.cpu[i].workload[0].simpoint
552            # No distance specified, just switch
553            else:
554                testsys.cpu[i].max_insts_any_thread = 1
555
556            # warmup period
557            if options.warmup_insts:
558                switch_cpus[i].max_insts_any_thread =  options.warmup_insts
559
560            # simulation period
561            if options.maxinsts:
562                switch_cpus_1[i].max_insts_any_thread = options.maxinsts
563
564            # attach the checker cpu if selected
565            if options.checker:
566                switch_cpus[i].addCheckerCpu()
567                switch_cpus_1[i].addCheckerCpu()
568
569        testsys.switch_cpus = switch_cpus
570        testsys.switch_cpus_1 = switch_cpus_1
571        switch_cpu_list = [(testsys.cpu[i], switch_cpus[i]) for i in xrange(np)]
572        switch_cpu_list1 = [(switch_cpus[i], switch_cpus_1[i]) for i in xrange(np)]
573
574    # set the checkpoint in the cpu before m5.instantiate is called
575    if options.take_checkpoints != None and \
576           (options.simpoint or options.at_instruction):
577        offset = int(options.take_checkpoints)
578        # Set an instruction break point
579        if options.simpoint:
580            for i in xrange(np):
581                if testsys.cpu[i].workload[0].simpoint == 0:
582                    fatal('no simpoint for testsys.cpu[%d].workload[0]', i)
583                checkpoint_inst = int(testsys.cpu[i].workload[0].simpoint) + offset
584                testsys.cpu[i].max_insts_any_thread = checkpoint_inst
585                # used for output below
586                options.take_checkpoints = checkpoint_inst
587        else:
588            options.take_checkpoints = offset
589            # Set all test cpus with the right number of instructions
590            # for the upcoming simulation
591            for i in xrange(np):
592                testsys.cpu[i].max_insts_any_thread = offset
593
594    if options.take_simpoint_checkpoints != None:
595        simpoints, interval_length = parseSimpointAnalysisFile(options, testsys)
596
597    checkpoint_dir = None
598    if options.checkpoint_restore:
599        cpt_starttick, checkpoint_dir = findCptDir(options, cptdir, testsys)
600    m5.instantiate(checkpoint_dir)
601
602    # Initialization is complete.  If we're not in control of simulation
603    # (that is, if we're a slave simulator acting as a component in another
604    #  'master' simulator) then we're done here.  The other simulator will
605    # call simulate() directly. --initialize-only is used to indicate this.
606    if options.initialize_only:
607        return
608
609    # Handle the max tick settings now that tick frequency was resolved
610    # during system instantiation
611    # NOTE: the maxtick variable here is in absolute ticks, so it must
612    # include any simulated ticks before a checkpoint
613    explicit_maxticks = 0
614    maxtick_from_abs = m5.MaxTick
615    maxtick_from_rel = m5.MaxTick
616    maxtick_from_maxtime = m5.MaxTick
617    if options.abs_max_tick:
618        maxtick_from_abs = options.abs_max_tick
619        explicit_maxticks += 1
620    if options.rel_max_tick:
621        maxtick_from_rel = options.rel_max_tick
622        if options.checkpoint_restore:
623            # NOTE: this may need to be updated if checkpoints ever store
624            # the ticks per simulated second
625            maxtick_from_rel += cpt_starttick
626            if options.at_instruction or options.simpoint:
627                warn("Relative max tick specified with --at-instruction or" \
628                     " --simpoint\n      These options don't specify the " \
629                     "checkpoint start tick, so assuming\n      you mean " \
630                     "absolute max tick")
631        explicit_maxticks += 1
632    if options.maxtime:
633        maxtick_from_maxtime = m5.ticks.fromSeconds(options.maxtime)
634        explicit_maxticks += 1
635    if explicit_maxticks > 1:
636        warn("Specified multiple of --abs-max-tick, --rel-max-tick, --maxtime."\
637             " Using least")
638    maxtick = min([maxtick_from_abs, maxtick_from_rel, maxtick_from_maxtime])
639
640    if options.checkpoint_restore != None and maxtick < cpt_starttick:
641        fatal("Bad maxtick (%d) specified: " \
642              "Checkpoint starts starts from tick: %d", maxtick, cpt_starttick)
643
644    if options.standard_switch or cpu_class:
645        if options.standard_switch:
646            print("Switch at instruction count:%s" %
647                    str(testsys.cpu[0].max_insts_any_thread))
648            exit_event = m5.simulate()
649        elif cpu_class and options.fast_forward:
650            print("Switch at instruction count:%s" %
651                    str(testsys.cpu[0].max_insts_any_thread))
652            exit_event = m5.simulate()
653        else:
654            print("Switch at curTick count:%s" % str(10000))
655            exit_event = m5.simulate(10000)
656        print("Switched CPUS @ tick %s" % (m5.curTick()))
657
658        m5.switchCpus(testsys, switch_cpu_list)
659
660        if options.standard_switch:
661            print("Switch at instruction count:%d" %
662                    (testsys.switch_cpus[0].max_insts_any_thread))
663
664            #warmup instruction count may have already been set
665            if options.warmup_insts:
666                exit_event = m5.simulate()
667            else:
668                exit_event = m5.simulate(options.standard_switch)
669            print("Switching CPUS @ tick %s" % (m5.curTick()))
670            print("Simulation ends instruction count:%d" %
671                    (testsys.switch_cpus_1[0].max_insts_any_thread))
672            m5.switchCpus(testsys, switch_cpu_list1)
673
674    # If we're taking and restoring checkpoints, use checkpoint_dir
675    # option only for finding the checkpoints to restore from.  This
676    # lets us test checkpointing by restoring from one set of
677    # checkpoints, generating a second set, and then comparing them.
678    if (options.take_checkpoints or options.take_simpoint_checkpoints) \
679        and options.checkpoint_restore:
680
681        if m5.options.outdir:
682            cptdir = m5.options.outdir
683        else:
684            cptdir = getcwd()
685
686    if options.take_checkpoints != None :
687        # Checkpoints being taken via the command line at <when> and at
688        # subsequent periods of <period>.  Checkpoint instructions
689        # received from the benchmark running are ignored and skipped in
690        # favor of command line checkpoint instructions.
691        exit_event = scriptCheckpoints(options, maxtick, cptdir)
692
693    # Take SimPoint checkpoints
694    elif options.take_simpoint_checkpoints != None:
695        takeSimpointCheckpoints(simpoints, interval_length, cptdir)
696
697    # Restore from SimPoint checkpoints
698    elif options.restore_simpoint_checkpoint != None:
699        restoreSimpointCheckpoint()
700
701    else:
702        if options.fast_forward:
703            m5.stats.reset()
704        print("**** REAL SIMULATION ****")
705
706        # If checkpoints are being taken, then the checkpoint instruction
707        # will occur in the benchmark code it self.
708        if options.repeat_switch and maxtick > options.repeat_switch:
709            exit_event = repeatSwitch(testsys, repeat_switch_cpu_list,
710                                      maxtick, options.repeat_switch)
711        else:
712            exit_event = benchCheckpoints(options, maxtick, cptdir)
713
714    print('Exiting @ tick %i because %s' %
715          (m5.curTick(), exit_event.getCause()))
716    if options.checkpoint_at_end:
717        m5.checkpoint(joinpath(cptdir, "cpt.%d"))
718
719    if exit_event.getCode() != 0:
720        print("Simulated exit code not 0! Exit code is", exit_event.getCode())
721