Simulation.py (9151:a4faa7dde56c) Simulation.py (9156:38dd0780322a)
1# Copyright (c) 2006-2008 The Regents of The University of Michigan
2# Copyright (c) 2010 Advanced Micro Devices, Inc.
3# All rights reserved.
4#
5# Redistribution and use in source and binary forms, with or without
6# modification, are permitted provided that the following conditions are
7# met: redistributions of source code must retain the above copyright
8# notice, this list of conditions and the following disclaimer;
9# redistributions in binary form must reproduce the above copyright
10# notice, this list of conditions and the following disclaimer in the
11# documentation and/or other materials provided with the distribution;
12# neither the name of the copyright holders nor the names of its
13# contributors may be used to endorse or promote products derived from
14# this software without specific prior written permission.
15#
16# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27#
28# Authors: Lisa Hsu
29
30from os import getcwd
31from os.path import join as joinpath
32
33import m5
34from m5.defines import buildEnv
35from m5.objects import *
36from m5.util import *
37from O3_ARM_v7a import *
38
39addToPath('../common')
40
41def getCPUClass(cpu_type):
42 """Returns the required cpu class and the mode of operation.
43 """
44
45 if cpu_type == "timing":
46 return TimingSimpleCPU, 'timing'
47 elif cpu_type == "detailed":
48 return DerivO3CPU, 'timing'
49 elif cpu_type == "arm_detailed":
50 return O3_ARM_v7a_3, 'timing'
51 elif cpu_type == "inorder":
52 return InOrderCPU, 'timing'
53 else:
54 return AtomicSimpleCPU, 'atomic'
55
56def setCPUClass(options):
57 """Returns two cpu classes and the initial mode of operation.
58
59 Restoring from a checkpoint or fast forwarding through a benchmark
60 can be done using one type of cpu, and then the actual
61 simulation can be carried out using another type. This function
62 returns these two types of cpus and the initial mode of operation
63 depending on the options provided.
64 """
65
66 if options.cpu_type == "detailed" or \
67 options.cpu_type == "arm_detailed" or \
68 options.cpu_type == "inorder" :
69 if not options.caches and not options.ruby:
70 fatal("O3/Inorder CPU must be used with caches")
71
72 TmpClass, test_mem_mode = getCPUClass(options.cpu_type)
73 CPUClass = None
74
75 if options.checkpoint_restore != None:
76 if options.restore_with_cpu != options.cpu_type:
77 CPUClass = TmpClass
78 TmpClass, test_mem_mode = getCPUClass(options.restore_with_cpu)
79 elif options.fast_forward:
80 CPUClass = TmpClass
81 TmpClass = AtomicSimpleCPU
82 test_mem_mode = 'atomic'
83
84 return (TmpClass, test_mem_mode, CPUClass)
85
86def setWorkCountOptions(system, options):
87 if options.work_item_id != None:
88 system.work_item_id = options.work_item_id
89 if options.work_begin_cpu_id_exit != None:
90 system.work_begin_cpu_id_exit = options.work_begin_cpu_id_exit
91 if options.work_end_exit_count != None:
92 system.work_end_exit_count = options.work_end_exit_count
93 if options.work_end_checkpoint_count != None:
94 system.work_end_ckpt_count = options.work_end_checkpoint_count
95 if options.work_begin_exit_count != None:
96 system.work_begin_exit_count = options.work_begin_exit_count
97 if options.work_begin_checkpoint_count != None:
98 system.work_begin_ckpt_count = options.work_begin_checkpoint_count
99 if options.work_cpus_checkpoint_count != None:
100 system.work_cpus_ckpt_count = options.work_cpus_checkpoint_count
101
102def findCptDir(options, maxtick, cptdir, testsys):
103 """Figures out the directory from which the checkpointed state is read.
104
105 There are two different ways in which the directories holding checkpoints
106 can be named --
107 1. cpt.<benchmark name>.<instruction count when the checkpoint was taken>
108 2. cpt.<some number, usually the tick value when the checkpoint was taken>
109
110 This function parses through the options to figure out which one of the
111 above should be used for selecting the checkpoint, and then figures out
112 the appropriate directory.
113
114 It also sets the value of the maximum tick value till which the simulation
115 will run.
116 """
117
118 from os.path import isdir, exists
119 from os import listdir
120 import re
121
122 if not isdir(cptdir):
123 fatal("checkpoint dir %s does not exist!", cptdir)
124
125 if options.at_instruction or options.simpoint:
126 inst = options.checkpoint_restore
127 if options.simpoint:
128 # assume workload 0 has the simpoint
129 if testsys.cpu[0].workload[0].simpoint == 0:
130 fatal('Unable to find simpoint')
131 inst += int(testsys.cpu[0].workload[0].simpoint)
132
133 checkpoint_dir = joinpath(cptdir, "cpt.%s.%s" % (options.bench, inst))
134 if not exists(checkpoint_dir):
135 fatal("Unable to find checkpoint directory %s", checkpoint_dir)
136 else:
137 dirs = listdir(cptdir)
138 expr = re.compile('cpt\.([0-9]*)')
139 cpts = []
140 for dir in dirs:
141 match = expr.match(dir)
142 if match:
143 cpts.append(match.group(1))
144
145 cpts.sort(lambda a,b: cmp(long(a), long(b)))
146
147 cpt_num = options.checkpoint_restore
148 if cpt_num > len(cpts):
149 fatal('Checkpoint %d not found', cpt_num)
150
151 maxtick = maxtick - int(cpts[cpt_num - 1])
152 checkpoint_dir = joinpath(cptdir, "cpt.%s" % cpts[cpt_num - 1])
153
154 return maxtick, checkpoint_dir
155
1# Copyright (c) 2006-2008 The Regents of The University of Michigan
2# Copyright (c) 2010 Advanced Micro Devices, Inc.
3# All rights reserved.
4#
5# Redistribution and use in source and binary forms, with or without
6# modification, are permitted provided that the following conditions are
7# met: redistributions of source code must retain the above copyright
8# notice, this list of conditions and the following disclaimer;
9# redistributions in binary form must reproduce the above copyright
10# notice, this list of conditions and the following disclaimer in the
11# documentation and/or other materials provided with the distribution;
12# neither the name of the copyright holders nor the names of its
13# contributors may be used to endorse or promote products derived from
14# this software without specific prior written permission.
15#
16# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27#
28# Authors: Lisa Hsu
29
30from os import getcwd
31from os.path import join as joinpath
32
33import m5
34from m5.defines import buildEnv
35from m5.objects import *
36from m5.util import *
37from O3_ARM_v7a import *
38
39addToPath('../common')
40
41def getCPUClass(cpu_type):
42 """Returns the required cpu class and the mode of operation.
43 """
44
45 if cpu_type == "timing":
46 return TimingSimpleCPU, 'timing'
47 elif cpu_type == "detailed":
48 return DerivO3CPU, 'timing'
49 elif cpu_type == "arm_detailed":
50 return O3_ARM_v7a_3, 'timing'
51 elif cpu_type == "inorder":
52 return InOrderCPU, 'timing'
53 else:
54 return AtomicSimpleCPU, 'atomic'
55
56def setCPUClass(options):
57 """Returns two cpu classes and the initial mode of operation.
58
59 Restoring from a checkpoint or fast forwarding through a benchmark
60 can be done using one type of cpu, and then the actual
61 simulation can be carried out using another type. This function
62 returns these two types of cpus and the initial mode of operation
63 depending on the options provided.
64 """
65
66 if options.cpu_type == "detailed" or \
67 options.cpu_type == "arm_detailed" or \
68 options.cpu_type == "inorder" :
69 if not options.caches and not options.ruby:
70 fatal("O3/Inorder CPU must be used with caches")
71
72 TmpClass, test_mem_mode = getCPUClass(options.cpu_type)
73 CPUClass = None
74
75 if options.checkpoint_restore != None:
76 if options.restore_with_cpu != options.cpu_type:
77 CPUClass = TmpClass
78 TmpClass, test_mem_mode = getCPUClass(options.restore_with_cpu)
79 elif options.fast_forward:
80 CPUClass = TmpClass
81 TmpClass = AtomicSimpleCPU
82 test_mem_mode = 'atomic'
83
84 return (TmpClass, test_mem_mode, CPUClass)
85
86def setWorkCountOptions(system, options):
87 if options.work_item_id != None:
88 system.work_item_id = options.work_item_id
89 if options.work_begin_cpu_id_exit != None:
90 system.work_begin_cpu_id_exit = options.work_begin_cpu_id_exit
91 if options.work_end_exit_count != None:
92 system.work_end_exit_count = options.work_end_exit_count
93 if options.work_end_checkpoint_count != None:
94 system.work_end_ckpt_count = options.work_end_checkpoint_count
95 if options.work_begin_exit_count != None:
96 system.work_begin_exit_count = options.work_begin_exit_count
97 if options.work_begin_checkpoint_count != None:
98 system.work_begin_ckpt_count = options.work_begin_checkpoint_count
99 if options.work_cpus_checkpoint_count != None:
100 system.work_cpus_ckpt_count = options.work_cpus_checkpoint_count
101
102def findCptDir(options, maxtick, cptdir, testsys):
103 """Figures out the directory from which the checkpointed state is read.
104
105 There are two different ways in which the directories holding checkpoints
106 can be named --
107 1. cpt.<benchmark name>.<instruction count when the checkpoint was taken>
108 2. cpt.<some number, usually the tick value when the checkpoint was taken>
109
110 This function parses through the options to figure out which one of the
111 above should be used for selecting the checkpoint, and then figures out
112 the appropriate directory.
113
114 It also sets the value of the maximum tick value till which the simulation
115 will run.
116 """
117
118 from os.path import isdir, exists
119 from os import listdir
120 import re
121
122 if not isdir(cptdir):
123 fatal("checkpoint dir %s does not exist!", cptdir)
124
125 if options.at_instruction or options.simpoint:
126 inst = options.checkpoint_restore
127 if options.simpoint:
128 # assume workload 0 has the simpoint
129 if testsys.cpu[0].workload[0].simpoint == 0:
130 fatal('Unable to find simpoint')
131 inst += int(testsys.cpu[0].workload[0].simpoint)
132
133 checkpoint_dir = joinpath(cptdir, "cpt.%s.%s" % (options.bench, inst))
134 if not exists(checkpoint_dir):
135 fatal("Unable to find checkpoint directory %s", checkpoint_dir)
136 else:
137 dirs = listdir(cptdir)
138 expr = re.compile('cpt\.([0-9]*)')
139 cpts = []
140 for dir in dirs:
141 match = expr.match(dir)
142 if match:
143 cpts.append(match.group(1))
144
145 cpts.sort(lambda a,b: cmp(long(a), long(b)))
146
147 cpt_num = options.checkpoint_restore
148 if cpt_num > len(cpts):
149 fatal('Checkpoint %d not found', cpt_num)
150
151 maxtick = maxtick - int(cpts[cpt_num - 1])
152 checkpoint_dir = joinpath(cptdir, "cpt.%s" % cpts[cpt_num - 1])
153
154 return maxtick, checkpoint_dir
155
156def scriptCheckpoints(options):
156def scriptCheckpoints(options, cptdir):
157 if options.at_instruction or options.simpoint:
158 checkpoint_inst = int(options.take_checkpoints)
159
160 # maintain correct offset if we restored from some instruction
161 if options.checkpoint_restore != None:
162 checkpoint_inst += options.checkpoint_restore
163
164 print "Creating checkpoint at inst:%d" % (checkpoint_inst)
165 exit_event = m5.simulate()
166 exit_cause = exit_event.getCause()
167 print "exit cause = %s" % exit_cause
168
169 # skip checkpoint instructions should they exist
170 while exit_cause == "checkpoint":
171 exit_event = m5.simulate()
172 exit_cause = exit_event.getCause()
173
174 if exit_cause == "a thread reached the max instruction count":
175 m5.checkpoint(joinpath(cptdir, "cpt.%s.%d" % \
176 (options.bench, checkpoint_inst)))
177 print "Checkpoint written."
178
179 else:
180 when, period = options.take_checkpoints.split(",", 1)
181 when = int(when)
182 period = int(period)
157 if options.at_instruction or options.simpoint:
158 checkpoint_inst = int(options.take_checkpoints)
159
160 # maintain correct offset if we restored from some instruction
161 if options.checkpoint_restore != None:
162 checkpoint_inst += options.checkpoint_restore
163
164 print "Creating checkpoint at inst:%d" % (checkpoint_inst)
165 exit_event = m5.simulate()
166 exit_cause = exit_event.getCause()
167 print "exit cause = %s" % exit_cause
168
169 # skip checkpoint instructions should they exist
170 while exit_cause == "checkpoint":
171 exit_event = m5.simulate()
172 exit_cause = exit_event.getCause()
173
174 if exit_cause == "a thread reached the max instruction count":
175 m5.checkpoint(joinpath(cptdir, "cpt.%s.%d" % \
176 (options.bench, checkpoint_inst)))
177 print "Checkpoint written."
178
179 else:
180 when, period = options.take_checkpoints.split(",", 1)
181 when = int(when)
182 period = int(period)
183 num_checkpoints = 0
183
184 exit_event = m5.simulate(when)
185 exit_cause = exit_event.getCause()
186 while exit_cause == "checkpoint":
187 exit_event = m5.simulate(when - m5.curTick())
188 exit_cause = exit_event.getCause()
189
190 if exit_cause == "simulate() limit reached":
191 m5.checkpoint(joinpath(cptdir, "cpt.%d"))
192 num_checkpoints += 1
193
194 sim_ticks = when
184
185 exit_event = m5.simulate(when)
186 exit_cause = exit_event.getCause()
187 while exit_cause == "checkpoint":
188 exit_event = m5.simulate(when - m5.curTick())
189 exit_cause = exit_event.getCause()
190
191 if exit_cause == "simulate() limit reached":
192 m5.checkpoint(joinpath(cptdir, "cpt.%d"))
193 num_checkpoints += 1
194
195 sim_ticks = when
195 num_checkpoints = 0
196 max_checkpoints = options.max_checkpoints
197
198 while num_checkpoints < max_checkpoints and \
199 exit_cause == "simulate() limit reached":
200 if (sim_ticks + period) > maxtick:
201 exit_event = m5.simulate(maxtick - sim_ticks)
202 exit_cause = exit_event.getCause()
203 break
204 else:
205 exit_event = m5.simulate(period)
206 exit_cause = exit_event.getCause()
207 sim_ticks += period
208 while exit_event.getCause() == "checkpoint":
209 exit_event = m5.simulate(sim_ticks - m5.curTick())
210 if exit_event.getCause() == "simulate() limit reached":
211 m5.checkpoint(joinpath(cptdir, "cpt.%d"))
212 num_checkpoints += 1
213
214 return exit_cause
215
216def benchCheckpoints(options, maxtick, cptdir):
217 exit_event = m5.simulate(maxtick)
218 exit_cause = exit_event.getCause()
219
220 num_checkpoints = 0
221 max_checkpoints = options.max_checkpoints
222
223 while exit_cause == "checkpoint":
224 m5.checkpoint(joinpath(cptdir, "cpt.%d"))
225 num_checkpoints += 1
226 if num_checkpoints == max_checkpoints:
227 exit_cause = "maximum %d checkpoints dropped" % max_checkpoints
228 break
229
230 exit_event = m5.simulate(maxtick - m5.curTick())
231 exit_cause = exit_event.getCause()
232
233 return exit_cause
234
235def repeatSwitch(testsys, repeat_switch_cpu_list, maxtick, switch_freq):
236 print "starting switch loop"
237 while True:
238 exit_event = m5.simulate(switch_freq)
239 exit_cause = exit_event.getCause()
240
241 if exit_cause != "simulate() limit reached":
242 return exit_cause
243
244 print "draining the system"
245 m5.doDrain(testsys)
246 m5.switchCpus(repeat_switch_cpu_list)
247 m5.resume(testsys)
248
249 tmp_cpu_list = []
250 for old_cpu, new_cpu in repeat_switch_cpu_list:
251 tmp_cpu_list.append((new_cpu, old_cpu))
252 repeat_switch_cpu_list = tmp_cpu_list
253
254 if (maxtick - m5.curTick()) <= switch_freq:
255 exit_event = m5.simulate(maxtick - m5.curTick())
256 return exit_event.getCause()
257
258def run(options, root, testsys, cpu_class):
259 if options.maxtick:
260 maxtick = options.maxtick
261 elif options.maxtime:
262 simtime = m5.ticks.seconds(simtime)
263 print "simulating for: ", simtime
264 maxtick = simtime
265 else:
266 maxtick = m5.MaxTick
267
268 if options.checkpoint_dir:
269 cptdir = options.checkpoint_dir
270 elif m5.options.outdir:
271 cptdir = m5.options.outdir
272 else:
273 cptdir = getcwd()
274
275 if options.fast_forward and options.checkpoint_restore != None:
276 fatal("Can't specify both --fast-forward and --checkpoint-restore")
277
278 if options.standard_switch and not options.caches:
279 fatal("Must specify --caches when using --standard-switch")
280
281 if options.standard_switch and options.repeat_switch:
282 fatal("Can't specify both --standard-switch and --repeat-switch")
283
284 if options.repeat_switch and options.take_checkpoints:
285 fatal("Can't specify both --repeat-switch and --take-checkpoints")
286
287 np = options.num_cpus
288 switch_cpus = None
289
290 if options.prog_interval:
291 for i in xrange(np):
292 testsys.cpu[i].progress_interval = options.prog_interval
293
294 if options.maxinsts:
295 for i in xrange(np):
296 testsys.cpu[i].max_insts_any_thread = options.maxinsts
297
298 if cpu_class:
299 switch_cpus = [cpu_class(defer_registration=True, cpu_id=(i))
300 for i in xrange(np)]
301
302 for i in xrange(np):
303 if options.fast_forward:
304 testsys.cpu[i].max_insts_any_thread = int(options.fast_forward)
305 switch_cpus[i].system = testsys
306 switch_cpus[i].workload = testsys.cpu[i].workload
307 switch_cpus[i].clock = testsys.cpu[i].clock
308 # simulation period
309 if options.maxinsts:
310 switch_cpus[i].max_insts_any_thread = options.maxinsts
311 # Add checker cpu if selected
312 if options.checker:
313 switch_cpus[i].addCheckerCpu()
314
315 testsys.switch_cpus = switch_cpus
316 switch_cpu_list = [(testsys.cpu[i], switch_cpus[i]) for i in xrange(np)]
317
318 if options.repeat_switch:
319 if options.cpu_type == "arm_detailed":
320 if not options.caches:
321 print "O3 CPU must be used with caches"
322 sys.exit(1)
323
324 repeat_switch_cpus = [O3_ARM_v7a_3(defer_registration=True, \
325 cpu_id=(i)) for i in xrange(np)]
326 elif options.cpu_type == "detailed":
327 if not options.caches:
328 print "O3 CPU must be used with caches"
329 sys.exit(1)
330
331 repeat_switch_cpus = [DerivO3CPU(defer_registration=True, \
332 cpu_id=(i)) for i in xrange(np)]
333 elif options.cpu_type == "inorder":
334 print "inorder CPU switching not supported"
335 sys.exit(1)
336 elif options.cpu_type == "timing":
337 repeat_switch_cpus = [TimingSimpleCPU(defer_registration=True, \
338 cpu_id=(i)) for i in xrange(np)]
339 else:
340 repeat_switch_cpus = [AtomicSimpleCPU(defer_registration=True, \
341 cpu_id=(i)) for i in xrange(np)]
342
343 for i in xrange(np):
344 repeat_switch_cpus[i].system = testsys
345 repeat_switch_cpus[i].workload = testsys.cpu[i].workload
346 repeat_switch_cpus[i].clock = testsys.cpu[i].clock
347
348 if options.maxinsts:
349 repeat_switch_cpus[i].max_insts_any_thread = options.maxinsts
350
351 if options.checker:
352 repeat_switch_cpus[i].addCheckerCpu()
353
354 testsys.repeat_switch_cpus = repeat_switch_cpus
355
356 if cpu_class:
357 repeat_switch_cpu_list = [(switch_cpus[i], repeat_switch_cpus[i])
358 for i in xrange(np)]
359 else:
360 repeat_switch_cpu_list = [(testsys.cpu[i], repeat_switch_cpus[i])
361 for i in xrange(np)]
362
363 if options.standard_switch:
364 switch_cpus = [TimingSimpleCPU(defer_registration=True, cpu_id=(i))
365 for i in xrange(np)]
366 switch_cpus_1 = [DerivO3CPU(defer_registration=True, cpu_id=(i))
367 for i in xrange(np)]
368
369 for i in xrange(np):
370 switch_cpus[i].system = testsys
371 switch_cpus_1[i].system = testsys
372 switch_cpus[i].workload = testsys.cpu[i].workload
373 switch_cpus_1[i].workload = testsys.cpu[i].workload
374 switch_cpus[i].clock = testsys.cpu[i].clock
375 switch_cpus_1[i].clock = testsys.cpu[i].clock
376
377 # if restoring, make atomic cpu simulate only a few instructions
378 if options.checkpoint_restore != None:
379 testsys.cpu[i].max_insts_any_thread = 1
380 # Fast forward to specified location if we are not restoring
381 elif options.fast_forward:
382 testsys.cpu[i].max_insts_any_thread = int(options.fast_forward)
383 # Fast forward to a simpoint (warning: time consuming)
384 elif options.simpoint:
385 if testsys.cpu[i].workload[0].simpoint == 0:
386 fatal('simpoint not found')
387 testsys.cpu[i].max_insts_any_thread = \
388 testsys.cpu[i].workload[0].simpoint
389 # No distance specified, just switch
390 else:
391 testsys.cpu[i].max_insts_any_thread = 1
392
393 # warmup period
394 if options.warmup_insts:
395 switch_cpus[i].max_insts_any_thread = options.warmup_insts
396
397 # simulation period
398 if options.maxinsts:
399 switch_cpus_1[i].max_insts_any_thread = options.maxinsts
400
401 # attach the checker cpu if selected
402 if options.checker:
403 switch_cpus[i].addCheckerCpu()
404 switch_cpus_1[i].addCheckerCpu()
405
406 testsys.switch_cpus = switch_cpus
407 testsys.switch_cpus_1 = switch_cpus_1
408 switch_cpu_list = [(testsys.cpu[i], switch_cpus[i]) for i in xrange(np)]
409 switch_cpu_list1 = [(switch_cpus[i], switch_cpus_1[i]) for i in xrange(np)]
410
411 # set the checkpoint in the cpu before m5.instantiate is called
412 if options.take_checkpoints != None and \
413 (options.simpoint or options.at_instruction):
414 offset = int(options.take_checkpoints)
415 # Set an instruction break point
416 if options.simpoint:
417 for i in xrange(np):
418 if testsys.cpu[i].workload[0].simpoint == 0:
419 fatal('no simpoint for testsys.cpu[%d].workload[0]', i)
420 checkpoint_inst = int(testsys.cpu[i].workload[0].simpoint) + offset
421 testsys.cpu[i].max_insts_any_thread = checkpoint_inst
422 # used for output below
423 options.take_checkpoints = checkpoint_inst
424 else:
425 options.take_checkpoints = offset
426 # Set all test cpus with the right number of instructions
427 # for the upcoming simulation
428 for i in xrange(np):
429 testsys.cpu[i].max_insts_any_thread = offset
430
431 checkpoint_dir = None
432 if options.checkpoint_restore != None:
433 maxtick, checkpoint_dir = findCptDir(options, maxtick, cptdir, testsys)
434 m5.instantiate(checkpoint_dir)
435
436 if options.standard_switch or cpu_class:
437 if options.standard_switch:
438 print "Switch at instruction count:%s" % \
439 str(testsys.cpu[0].max_insts_any_thread)
440 exit_event = m5.simulate()
441 elif cpu_class and options.fast_forward:
442 print "Switch at instruction count:%s" % \
443 str(testsys.cpu[0].max_insts_any_thread)
444 exit_event = m5.simulate()
445 else:
446 print "Switch at curTick count:%s" % str(10000)
447 exit_event = m5.simulate(10000)
448 print "Switched CPUS @ tick %s" % (m5.curTick())
449
450 # when you change to Timing (or Atomic), you halt the system
451 # given as argument. When you are finished with the system
452 # changes (including switchCpus), you must resume the system
453 # manually. You DON'T need to resume after just switching
454 # CPUs if you haven't changed anything on the system level.
455
456 m5.changeToTiming(testsys)
457 m5.switchCpus(switch_cpu_list)
458 m5.resume(testsys)
459
460 if options.standard_switch:
461 print "Switch at instruction count:%d" % \
462 (testsys.switch_cpus[0].max_insts_any_thread)
463
464 #warmup instruction count may have already been set
465 if options.warmup_insts:
466 exit_event = m5.simulate()
467 else:
468 exit_event = m5.simulate(options.standard_switch)
469 print "Switching CPUS @ tick %s" % (m5.curTick())
470 print "Simulation ends instruction count:%d" % \
471 (testsys.switch_cpus_1[0].max_insts_any_thread)
472 m5.drain(testsys)
473 m5.switchCpus(switch_cpu_list1)
474 m5.resume(testsys)
475
476 # If we're taking and restoring checkpoints, use checkpoint_dir
477 # option only for finding the checkpoints to restore from. This
478 # lets us test checkpointing by restoring from one set of
479 # checkpoints, generating a second set, and then comparing them.
480 if options.take_checkpoints and options.checkpoint_restore:
481 if m5.options.outdir:
482 cptdir = m5.options.outdir
483 else:
484 cptdir = getcwd()
485
486 if options.take_checkpoints != None :
487 # Checkpoints being taken via the command line at <when> and at
488 # subsequent periods of <period>. Checkpoint instructions
489 # received from the benchmark running are ignored and skipped in
490 # favor of command line checkpoint instructions.
196 max_checkpoints = options.max_checkpoints
197
198 while num_checkpoints < max_checkpoints and \
199 exit_cause == "simulate() limit reached":
200 if (sim_ticks + period) > maxtick:
201 exit_event = m5.simulate(maxtick - sim_ticks)
202 exit_cause = exit_event.getCause()
203 break
204 else:
205 exit_event = m5.simulate(period)
206 exit_cause = exit_event.getCause()
207 sim_ticks += period
208 while exit_event.getCause() == "checkpoint":
209 exit_event = m5.simulate(sim_ticks - m5.curTick())
210 if exit_event.getCause() == "simulate() limit reached":
211 m5.checkpoint(joinpath(cptdir, "cpt.%d"))
212 num_checkpoints += 1
213
214 return exit_cause
215
216def benchCheckpoints(options, maxtick, cptdir):
217 exit_event = m5.simulate(maxtick)
218 exit_cause = exit_event.getCause()
219
220 num_checkpoints = 0
221 max_checkpoints = options.max_checkpoints
222
223 while exit_cause == "checkpoint":
224 m5.checkpoint(joinpath(cptdir, "cpt.%d"))
225 num_checkpoints += 1
226 if num_checkpoints == max_checkpoints:
227 exit_cause = "maximum %d checkpoints dropped" % max_checkpoints
228 break
229
230 exit_event = m5.simulate(maxtick - m5.curTick())
231 exit_cause = exit_event.getCause()
232
233 return exit_cause
234
235def repeatSwitch(testsys, repeat_switch_cpu_list, maxtick, switch_freq):
236 print "starting switch loop"
237 while True:
238 exit_event = m5.simulate(switch_freq)
239 exit_cause = exit_event.getCause()
240
241 if exit_cause != "simulate() limit reached":
242 return exit_cause
243
244 print "draining the system"
245 m5.doDrain(testsys)
246 m5.switchCpus(repeat_switch_cpu_list)
247 m5.resume(testsys)
248
249 tmp_cpu_list = []
250 for old_cpu, new_cpu in repeat_switch_cpu_list:
251 tmp_cpu_list.append((new_cpu, old_cpu))
252 repeat_switch_cpu_list = tmp_cpu_list
253
254 if (maxtick - m5.curTick()) <= switch_freq:
255 exit_event = m5.simulate(maxtick - m5.curTick())
256 return exit_event.getCause()
257
258def run(options, root, testsys, cpu_class):
259 if options.maxtick:
260 maxtick = options.maxtick
261 elif options.maxtime:
262 simtime = m5.ticks.seconds(simtime)
263 print "simulating for: ", simtime
264 maxtick = simtime
265 else:
266 maxtick = m5.MaxTick
267
268 if options.checkpoint_dir:
269 cptdir = options.checkpoint_dir
270 elif m5.options.outdir:
271 cptdir = m5.options.outdir
272 else:
273 cptdir = getcwd()
274
275 if options.fast_forward and options.checkpoint_restore != None:
276 fatal("Can't specify both --fast-forward and --checkpoint-restore")
277
278 if options.standard_switch and not options.caches:
279 fatal("Must specify --caches when using --standard-switch")
280
281 if options.standard_switch and options.repeat_switch:
282 fatal("Can't specify both --standard-switch and --repeat-switch")
283
284 if options.repeat_switch and options.take_checkpoints:
285 fatal("Can't specify both --repeat-switch and --take-checkpoints")
286
287 np = options.num_cpus
288 switch_cpus = None
289
290 if options.prog_interval:
291 for i in xrange(np):
292 testsys.cpu[i].progress_interval = options.prog_interval
293
294 if options.maxinsts:
295 for i in xrange(np):
296 testsys.cpu[i].max_insts_any_thread = options.maxinsts
297
298 if cpu_class:
299 switch_cpus = [cpu_class(defer_registration=True, cpu_id=(i))
300 for i in xrange(np)]
301
302 for i in xrange(np):
303 if options.fast_forward:
304 testsys.cpu[i].max_insts_any_thread = int(options.fast_forward)
305 switch_cpus[i].system = testsys
306 switch_cpus[i].workload = testsys.cpu[i].workload
307 switch_cpus[i].clock = testsys.cpu[i].clock
308 # simulation period
309 if options.maxinsts:
310 switch_cpus[i].max_insts_any_thread = options.maxinsts
311 # Add checker cpu if selected
312 if options.checker:
313 switch_cpus[i].addCheckerCpu()
314
315 testsys.switch_cpus = switch_cpus
316 switch_cpu_list = [(testsys.cpu[i], switch_cpus[i]) for i in xrange(np)]
317
318 if options.repeat_switch:
319 if options.cpu_type == "arm_detailed":
320 if not options.caches:
321 print "O3 CPU must be used with caches"
322 sys.exit(1)
323
324 repeat_switch_cpus = [O3_ARM_v7a_3(defer_registration=True, \
325 cpu_id=(i)) for i in xrange(np)]
326 elif options.cpu_type == "detailed":
327 if not options.caches:
328 print "O3 CPU must be used with caches"
329 sys.exit(1)
330
331 repeat_switch_cpus = [DerivO3CPU(defer_registration=True, \
332 cpu_id=(i)) for i in xrange(np)]
333 elif options.cpu_type == "inorder":
334 print "inorder CPU switching not supported"
335 sys.exit(1)
336 elif options.cpu_type == "timing":
337 repeat_switch_cpus = [TimingSimpleCPU(defer_registration=True, \
338 cpu_id=(i)) for i in xrange(np)]
339 else:
340 repeat_switch_cpus = [AtomicSimpleCPU(defer_registration=True, \
341 cpu_id=(i)) for i in xrange(np)]
342
343 for i in xrange(np):
344 repeat_switch_cpus[i].system = testsys
345 repeat_switch_cpus[i].workload = testsys.cpu[i].workload
346 repeat_switch_cpus[i].clock = testsys.cpu[i].clock
347
348 if options.maxinsts:
349 repeat_switch_cpus[i].max_insts_any_thread = options.maxinsts
350
351 if options.checker:
352 repeat_switch_cpus[i].addCheckerCpu()
353
354 testsys.repeat_switch_cpus = repeat_switch_cpus
355
356 if cpu_class:
357 repeat_switch_cpu_list = [(switch_cpus[i], repeat_switch_cpus[i])
358 for i in xrange(np)]
359 else:
360 repeat_switch_cpu_list = [(testsys.cpu[i], repeat_switch_cpus[i])
361 for i in xrange(np)]
362
363 if options.standard_switch:
364 switch_cpus = [TimingSimpleCPU(defer_registration=True, cpu_id=(i))
365 for i in xrange(np)]
366 switch_cpus_1 = [DerivO3CPU(defer_registration=True, cpu_id=(i))
367 for i in xrange(np)]
368
369 for i in xrange(np):
370 switch_cpus[i].system = testsys
371 switch_cpus_1[i].system = testsys
372 switch_cpus[i].workload = testsys.cpu[i].workload
373 switch_cpus_1[i].workload = testsys.cpu[i].workload
374 switch_cpus[i].clock = testsys.cpu[i].clock
375 switch_cpus_1[i].clock = testsys.cpu[i].clock
376
377 # if restoring, make atomic cpu simulate only a few instructions
378 if options.checkpoint_restore != None:
379 testsys.cpu[i].max_insts_any_thread = 1
380 # Fast forward to specified location if we are not restoring
381 elif options.fast_forward:
382 testsys.cpu[i].max_insts_any_thread = int(options.fast_forward)
383 # Fast forward to a simpoint (warning: time consuming)
384 elif options.simpoint:
385 if testsys.cpu[i].workload[0].simpoint == 0:
386 fatal('simpoint not found')
387 testsys.cpu[i].max_insts_any_thread = \
388 testsys.cpu[i].workload[0].simpoint
389 # No distance specified, just switch
390 else:
391 testsys.cpu[i].max_insts_any_thread = 1
392
393 # warmup period
394 if options.warmup_insts:
395 switch_cpus[i].max_insts_any_thread = options.warmup_insts
396
397 # simulation period
398 if options.maxinsts:
399 switch_cpus_1[i].max_insts_any_thread = options.maxinsts
400
401 # attach the checker cpu if selected
402 if options.checker:
403 switch_cpus[i].addCheckerCpu()
404 switch_cpus_1[i].addCheckerCpu()
405
406 testsys.switch_cpus = switch_cpus
407 testsys.switch_cpus_1 = switch_cpus_1
408 switch_cpu_list = [(testsys.cpu[i], switch_cpus[i]) for i in xrange(np)]
409 switch_cpu_list1 = [(switch_cpus[i], switch_cpus_1[i]) for i in xrange(np)]
410
411 # set the checkpoint in the cpu before m5.instantiate is called
412 if options.take_checkpoints != None and \
413 (options.simpoint or options.at_instruction):
414 offset = int(options.take_checkpoints)
415 # Set an instruction break point
416 if options.simpoint:
417 for i in xrange(np):
418 if testsys.cpu[i].workload[0].simpoint == 0:
419 fatal('no simpoint for testsys.cpu[%d].workload[0]', i)
420 checkpoint_inst = int(testsys.cpu[i].workload[0].simpoint) + offset
421 testsys.cpu[i].max_insts_any_thread = checkpoint_inst
422 # used for output below
423 options.take_checkpoints = checkpoint_inst
424 else:
425 options.take_checkpoints = offset
426 # Set all test cpus with the right number of instructions
427 # for the upcoming simulation
428 for i in xrange(np):
429 testsys.cpu[i].max_insts_any_thread = offset
430
431 checkpoint_dir = None
432 if options.checkpoint_restore != None:
433 maxtick, checkpoint_dir = findCptDir(options, maxtick, cptdir, testsys)
434 m5.instantiate(checkpoint_dir)
435
436 if options.standard_switch or cpu_class:
437 if options.standard_switch:
438 print "Switch at instruction count:%s" % \
439 str(testsys.cpu[0].max_insts_any_thread)
440 exit_event = m5.simulate()
441 elif cpu_class and options.fast_forward:
442 print "Switch at instruction count:%s" % \
443 str(testsys.cpu[0].max_insts_any_thread)
444 exit_event = m5.simulate()
445 else:
446 print "Switch at curTick count:%s" % str(10000)
447 exit_event = m5.simulate(10000)
448 print "Switched CPUS @ tick %s" % (m5.curTick())
449
450 # when you change to Timing (or Atomic), you halt the system
451 # given as argument. When you are finished with the system
452 # changes (including switchCpus), you must resume the system
453 # manually. You DON'T need to resume after just switching
454 # CPUs if you haven't changed anything on the system level.
455
456 m5.changeToTiming(testsys)
457 m5.switchCpus(switch_cpu_list)
458 m5.resume(testsys)
459
460 if options.standard_switch:
461 print "Switch at instruction count:%d" % \
462 (testsys.switch_cpus[0].max_insts_any_thread)
463
464 #warmup instruction count may have already been set
465 if options.warmup_insts:
466 exit_event = m5.simulate()
467 else:
468 exit_event = m5.simulate(options.standard_switch)
469 print "Switching CPUS @ tick %s" % (m5.curTick())
470 print "Simulation ends instruction count:%d" % \
471 (testsys.switch_cpus_1[0].max_insts_any_thread)
472 m5.drain(testsys)
473 m5.switchCpus(switch_cpu_list1)
474 m5.resume(testsys)
475
476 # If we're taking and restoring checkpoints, use checkpoint_dir
477 # option only for finding the checkpoints to restore from. This
478 # lets us test checkpointing by restoring from one set of
479 # checkpoints, generating a second set, and then comparing them.
480 if options.take_checkpoints and options.checkpoint_restore:
481 if m5.options.outdir:
482 cptdir = m5.options.outdir
483 else:
484 cptdir = getcwd()
485
486 if options.take_checkpoints != None :
487 # Checkpoints being taken via the command line at <when> and at
488 # subsequent periods of <period>. Checkpoint instructions
489 # received from the benchmark running are ignored and skipped in
490 # favor of command line checkpoint instructions.
491 exit_cause = scriptCheckpoints(options)
491 exit_cause = scriptCheckpoints(options, cptdir)
492 else:
493 if options.fast_forward:
494 m5.stats.reset()
495 print "**** REAL SIMULATION ****"
496
497 # If checkpoints are being taken, then the checkpoint instruction
498 # will occur in the benchmark code it self.
499 if options.repeat_switch and maxtick > options.repeat_switch:
500 exit_cause = repeatSwitch(testsys, repeat_switch_cpu_list,
501 maxtick, options.repeat_switch)
502 else:
503 exit_cause = benchCheckpoints(options, maxtick, cptdir)
504
505 print 'Exiting @ tick %i because %s' % (m5.curTick(), exit_cause)
506 if options.checkpoint_at_end:
507 m5.checkpoint(joinpath(cptdir, "cpt.%d"))
492 else:
493 if options.fast_forward:
494 m5.stats.reset()
495 print "**** REAL SIMULATION ****"
496
497 # If checkpoints are being taken, then the checkpoint instruction
498 # will occur in the benchmark code it self.
499 if options.repeat_switch and maxtick > options.repeat_switch:
500 exit_cause = repeatSwitch(testsys, repeat_switch_cpu_list,
501 maxtick, options.repeat_switch)
502 else:
503 exit_cause = benchCheckpoints(options, maxtick, cptdir)
504
505 print 'Exiting @ tick %i because %s' % (m5.curTick(), exit_cause)
506 if options.checkpoint_at_end:
507 m5.checkpoint(joinpath(cptdir, "cpt.%d"))