Deleted Added
sdiff udiff text old ( 8724:7b4d80b26e35 ) new ( 8803:f6c5785bc8fd )
full compact
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 setCPUClass(options):
42
43 atomic = False
44 if options.cpu_type == "timing":
45 class TmpClass(TimingSimpleCPU): pass
46 elif options.cpu_type == "detailed" or options.cpu_type == "arm_detailed":
47 if not options.caches and not options.ruby:
48 print "O3 CPU must be used with caches"
49 sys.exit(1)
50 if options.cpu_type == "arm_detailed":
51 class TmpClass(O3_ARM_v7a_3): pass
52 else:
53 class TmpClass(DerivO3CPU): pass
54 elif options.cpu_type == "inorder":
55 if not options.caches:
56 print "InOrder CPU must be used with caches"
57 sys.exit(1)
58 class TmpClass(InOrderCPU): pass
59 else:
60 class TmpClass(AtomicSimpleCPU): pass
61 atomic = True
62
63 CPUClass = None
64 test_mem_mode = 'atomic'
65
66 if not atomic:
67 if options.checkpoint_restore != None:
68 if options.restore_with_cpu != options.cpu_type:
69 CPUClass = TmpClass
70 class TmpClass(AtomicSimpleCPU): pass
71 else:
72 if options.restore_with_cpu != "atomic":
73 test_mem_mode = 'timing'
74
75 elif options.fast_forward:
76 CPUClass = TmpClass
77 class TmpClass(AtomicSimpleCPU): pass
78 else:
79 test_mem_mode = 'timing'
80
81 return (TmpClass, test_mem_mode, CPUClass)
82
83
84def run(options, root, testsys, cpu_class):
85 if options.maxtick:
86 maxtick = options.maxtick
87 elif options.maxtime:
88 simtime = m5.ticks.seconds(simtime)
89 print "simulating for: ", simtime
90 maxtick = simtime
91 else:
92 maxtick = m5.MaxTick
93
94 if options.checkpoint_dir:
95 cptdir = options.checkpoint_dir
96 elif m5.options.outdir:
97 cptdir = m5.options.outdir
98 else:
99 cptdir = getcwd()
100
101 if options.fast_forward and options.checkpoint_restore != None:
102 fatal("Can't specify both --fast-forward and --checkpoint-restore")
103
104 if options.standard_switch and not options.caches:
105 fatal("Must specify --caches when using --standard-switch")
106
107 np = options.num_cpus
108 max_checkpoints = options.max_checkpoints
109 switch_cpus = None
110
111 if options.prog_interval:
112 for i in xrange(np):
113 testsys.cpu[i].progress_interval = options.prog_interval
114
115 if options.maxinsts:
116 for i in xrange(np):
117 testsys.cpu[i].max_insts_any_thread = options.maxinsts
118
119 if cpu_class:
120 switch_cpus = [cpu_class(defer_registration=True, cpu_id=(np+i))
121 for i in xrange(np)]
122
123 for i in xrange(np):
124 if options.fast_forward:
125 testsys.cpu[i].max_insts_any_thread = int(options.fast_forward)
126 switch_cpus[i].system = testsys
127 if not buildEnv['FULL_SYSTEM']:
128 switch_cpus[i].workload = testsys.cpu[i].workload
129 switch_cpus[i].clock = testsys.cpu[0].clock
130 # simulation period
131 if options.maxinsts:
132 switch_cpus[i].max_insts_any_thread = options.maxinsts
133
134 testsys.switch_cpus = switch_cpus
135 switch_cpu_list = [(testsys.cpu[i], switch_cpus[i]) for i in xrange(np)]
136
137 if options.standard_switch:
138 if not options.caches:
139 # O3 CPU must have a cache to work.
140 print "O3 CPU must be used with caches"
141 sys.exit(1)
142
143 switch_cpus = [TimingSimpleCPU(defer_registration=True, cpu_id=(np+i))
144 for i in xrange(np)]
145 switch_cpus_1 = [DerivO3CPU(defer_registration=True, cpu_id=(2*np+i))
146 for i in xrange(np)]
147
148 for i in xrange(np):
149 switch_cpus[i].system = testsys
150 switch_cpus_1[i].system = testsys
151 if not buildEnv['FULL_SYSTEM']:
152 switch_cpus[i].workload = testsys.cpu[i].workload
153 switch_cpus_1[i].workload = testsys.cpu[i].workload
154 switch_cpus[i].clock = testsys.cpu[0].clock
155 switch_cpus_1[i].clock = testsys.cpu[0].clock
156
157 # if restoring, make atomic cpu simulate only a few instructions
158 if options.checkpoint_restore != None:
159 testsys.cpu[i].max_insts_any_thread = 1
160 # Fast forward to specified location if we are not restoring
161 elif options.fast_forward:
162 testsys.cpu[i].max_insts_any_thread = int(options.fast_forward)
163 # Fast forward to a simpoint (warning: time consuming)
164 elif options.simpoint:
165 if testsys.cpu[i].workload[0].simpoint == 0:
166 fatal('simpoint not found')
167 testsys.cpu[i].max_insts_any_thread = \
168 testsys.cpu[i].workload[0].simpoint
169 # No distance specified, just switch
170 else:
171 testsys.cpu[i].max_insts_any_thread = 1
172
173 # warmup period
174 if options.warmup_insts:
175 switch_cpus[i].max_insts_any_thread = options.warmup_insts
176
177 # simulation period
178 if options.maxinsts:
179 switch_cpus_1[i].max_insts_any_thread = options.maxinsts
180
181 testsys.switch_cpus = switch_cpus
182 testsys.switch_cpus_1 = switch_cpus_1
183 switch_cpu_list = [(testsys.cpu[i], switch_cpus[i]) for i in xrange(np)]
184 switch_cpu_list1 = [(switch_cpus[i], switch_cpus_1[i]) for i in xrange(np)]
185
186 # set the checkpoint in the cpu before m5.instantiate is called
187 if options.take_checkpoints != None and \
188 (options.simpoint or options.at_instruction):
189 offset = int(options.take_checkpoints)
190 # Set an instruction break point
191 if options.simpoint:
192 for i in xrange(np):
193 if testsys.cpu[i].workload[0].simpoint == 0:
194 fatal('no simpoint for testsys.cpu[%d].workload[0]', i)
195 checkpoint_inst = int(testsys.cpu[i].workload[0].simpoint) + offset
196 testsys.cpu[i].max_insts_any_thread = checkpoint_inst
197 # used for output below
198 options.take_checkpoints = checkpoint_inst
199 else:
200 options.take_checkpoints = offset
201 # Set all test cpus with the right number of instructions
202 # for the upcoming simulation
203 for i in xrange(np):
204 testsys.cpu[i].max_insts_any_thread = offset
205
206 checkpoint_dir = None
207 if options.checkpoint_restore != None:
208 from os.path import isdir, exists
209 from os import listdir
210 import re
211
212 if not isdir(cptdir):
213 fatal("checkpoint dir %s does not exist!", cptdir)
214
215 if options.at_instruction or options.simpoint:
216 inst = options.checkpoint_restore
217 if options.simpoint:
218 # assume workload 0 has the simpoint
219 if testsys.cpu[0].workload[0].simpoint == 0:
220 fatal('Unable to find simpoint')
221 inst += int(testsys.cpu[0].workload[0].simpoint)
222
223 checkpoint_dir = joinpath(cptdir,
224 "cpt.%s.%s" % (options.bench, inst))
225 if not exists(checkpoint_dir):
226 fatal("Unable to find checkpoint directory %s", checkpoint_dir)
227 else:
228 dirs = listdir(cptdir)
229 expr = re.compile('cpt\.([0-9]*)')
230 cpts = []
231 for dir in dirs:
232 match = expr.match(dir)
233 if match:
234 cpts.append(match.group(1))
235
236 cpts.sort(lambda a,b: cmp(long(a), long(b)))
237
238 cpt_num = options.checkpoint_restore
239
240 if cpt_num > len(cpts):
241 fatal('Checkpoint %d not found', cpt_num)
242
243 ## Adjust max tick based on our starting tick
244 maxtick = maxtick - int(cpts[cpt_num - 1])
245 checkpoint_dir = joinpath(cptdir, "cpt.%s" % cpts[cpt_num - 1])
246
247 m5.instantiate(checkpoint_dir)
248
249 if options.standard_switch or cpu_class:
250 if options.standard_switch:
251 print "Switch at instruction count:%s" % \
252 str(testsys.cpu[0].max_insts_any_thread)
253 exit_event = m5.simulate()
254 elif cpu_class and options.fast_forward:
255 print "Switch at instruction count:%s" % \
256 str(testsys.cpu[0].max_insts_any_thread)
257 exit_event = m5.simulate()
258 else:
259 print "Switch at curTick count:%s" % str(10000)
260 exit_event = m5.simulate(10000)
261 print "Switched CPUS @ tick %s" % (m5.curTick())
262
263 # when you change to Timing (or Atomic), you halt the system
264 # given as argument. When you are finished with the system
265 # changes (including switchCpus), you must resume the system
266 # manually. You DON'T need to resume after just switching
267 # CPUs if you haven't changed anything on the system level.
268
269 m5.changeToTiming(testsys)
270 m5.switchCpus(switch_cpu_list)
271 m5.resume(testsys)
272
273 if options.standard_switch:
274 print "Switch at instruction count:%d" % \
275 (testsys.switch_cpus[0].max_insts_any_thread)
276
277 #warmup instruction count may have already been set
278 if options.warmup_insts:
279 exit_event = m5.simulate()
280 else:
281 exit_event = m5.simulate(options.warmup)
282 print "Switching CPUS @ tick %s" % (m5.curTick())
283 print "Simulation ends instruction count:%d" % \
284 (testsys.switch_cpus_1[0].max_insts_any_thread)
285 m5.drain(testsys)
286 m5.switchCpus(switch_cpu_list1)
287 m5.resume(testsys)
288
289 num_checkpoints = 0
290 exit_cause = ''
291
292 # If we're taking and restoring checkpoints, use checkpoint_dir
293 # option only for finding the checkpoints to restore from. This
294 # lets us test checkpointing by restoring from one set of
295 # checkpoints, generating a second set, and then comparing them.
296 if options.take_checkpoints and options.checkpoint_restore:
297 if m5.options.outdir:
298 cptdir = m5.options.outdir
299 else:
300 cptdir = getcwd()
301
302 # Checkpoints being taken via the command line at <when> and at
303 # subsequent periods of <period>. Checkpoint instructions
304 # received from the benchmark running are ignored and skipped in
305 # favor of command line checkpoint instructions.
306 if options.take_checkpoints != None :
307 if options.at_instruction or options.simpoint:
308 checkpoint_inst = int(options.take_checkpoints)
309
310 # maintain correct offset if we restored from some instruction
311 if options.checkpoint_restore != None:
312 checkpoint_inst += options.checkpoint_restore
313
314 print "Creating checkpoint at inst:%d" % (checkpoint_inst)
315 exit_event = m5.simulate()
316 print "exit cause = %s" % (exit_event.getCause())
317
318 # skip checkpoint instructions should they exist
319 while exit_event.getCause() == "checkpoint":
320 exit_event = m5.simulate()
321
322 if exit_event.getCause() == \
323 "a thread reached the max instruction count":
324 m5.checkpoint(joinpath(cptdir, "cpt.%s.%d" % \
325 (options.bench, checkpoint_inst)))
326 print "Checkpoint written."
327 num_checkpoints += 1
328
329 if exit_event.getCause() == "user interrupt received":
330 exit_cause = exit_event.getCause();
331 else:
332 when, period = options.take_checkpoints.split(",", 1)
333 when = int(when)
334 period = int(period)
335
336 exit_event = m5.simulate(when)
337 while exit_event.getCause() == "checkpoint":
338 exit_event = m5.simulate(when - m5.curTick())
339
340 if exit_event.getCause() == "simulate() limit reached":
341 m5.checkpoint(joinpath(cptdir, "cpt.%d"))
342 num_checkpoints += 1
343
344 sim_ticks = when
345 exit_cause = "maximum %d checkpoints dropped" % max_checkpoints
346 while num_checkpoints < max_checkpoints and \
347 exit_event.getCause() == "simulate() limit reached":
348 if (sim_ticks + period) > maxtick:
349 exit_event = m5.simulate(maxtick - sim_ticks)
350 exit_cause = exit_event.getCause()
351 break
352 else:
353 exit_event = m5.simulate(period)
354 sim_ticks += period
355 while exit_event.getCause() == "checkpoint":
356 exit_event = m5.simulate(sim_ticks - m5.curTick())
357 if exit_event.getCause() == "simulate() limit reached":
358 m5.checkpoint(joinpath(cptdir, "cpt.%d"))
359 num_checkpoints += 1
360
361 if exit_event.getCause() != "simulate() limit reached":
362 exit_cause = exit_event.getCause();
363
364 else: # no checkpoints being taken via this script
365 if options.fast_forward:
366 m5.stats.reset()
367 print "**** REAL SIMULATION ****"
368 exit_event = m5.simulate(maxtick)
369
370 while exit_event.getCause() == "checkpoint":
371 m5.checkpoint(joinpath(cptdir, "cpt.%d"))
372 num_checkpoints += 1
373 if num_checkpoints == max_checkpoints:
374 exit_cause = "maximum %d checkpoints dropped" % max_checkpoints
375 break
376
377 exit_event = m5.simulate(maxtick - m5.curTick())
378 exit_cause = exit_event.getCause()
379
380 if exit_cause == '':
381 exit_cause = exit_event.getCause()
382 print 'Exiting @ tick %i because %s' % (m5.curTick(), exit_cause)
383
384 if options.checkpoint_at_end:
385 m5.checkpoint(joinpath(cptdir, "cpt.%d"))
386