PageRenderTime 68ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 1ms

/configs/common/Simulation.py

https://bitbucket.org/musleh123/ece565
Python | 508 lines | 344 code | 79 blank | 85 comment | 138 complexity | 007effd2f69eacd02b0d3a119c4e9283 MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-2.1, WTFPL
  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. from os import getcwd
  30. from os.path import join as joinpath
  31. import m5
  32. from m5.defines import buildEnv
  33. from m5.objects import *
  34. from m5.util import *
  35. from O3_ARM_v7a import *
  36. addToPath('../common')
  37. def getCPUClass(cpu_type):
  38. """Returns the required cpu class and the mode of operation.
  39. """
  40. if cpu_type == "timing":
  41. return TimingSimpleCPU, 'timing'
  42. elif cpu_type == "detailed":
  43. return DerivO3CPU, 'timing'
  44. elif cpu_type == "arm_detailed":
  45. return O3_ARM_v7a_3, 'timing'
  46. elif cpu_type == "inorder":
  47. return InOrderCPU, 'timing'
  48. else:
  49. return AtomicSimpleCPU, 'atomic'
  50. def setCPUClass(options):
  51. """Returns two cpu classes and the initial mode of operation.
  52. Restoring from a checkpoint or fast forwarding through a benchmark
  53. can be done using one type of cpu, and then the actual
  54. simulation can be carried out using another type. This function
  55. returns these two types of cpus and the initial mode of operation
  56. depending on the options provided.
  57. """
  58. if options.cpu_type == "detailed" or \
  59. options.cpu_type == "arm_detailed" or \
  60. options.cpu_type == "inorder" :
  61. if not options.caches and not options.ruby:
  62. fatal("O3/Inorder CPU must be used with caches")
  63. TmpClass, test_mem_mode = getCPUClass(options.cpu_type)
  64. CPUClass = None
  65. if options.checkpoint_restore != None:
  66. if options.restore_with_cpu != options.cpu_type:
  67. CPUClass = TmpClass
  68. TmpClass, test_mem_mode = getCPUClass(options.restore_with_cpu)
  69. elif options.fast_forward:
  70. CPUClass = TmpClass
  71. TmpClass = AtomicSimpleCPU
  72. test_mem_mode = 'atomic'
  73. return (TmpClass, test_mem_mode, CPUClass)
  74. def setWorkCountOptions(system, options):
  75. if options.work_item_id != None:
  76. system.work_item_id = options.work_item_id
  77. if options.work_begin_cpu_id_exit != None:
  78. system.work_begin_cpu_id_exit = options.work_begin_cpu_id_exit
  79. if options.work_end_exit_count != None:
  80. system.work_end_exit_count = options.work_end_exit_count
  81. if options.work_end_checkpoint_count != None:
  82. system.work_end_ckpt_count = options.work_end_checkpoint_count
  83. if options.work_begin_exit_count != None:
  84. system.work_begin_exit_count = options.work_begin_exit_count
  85. if options.work_begin_checkpoint_count != None:
  86. system.work_begin_ckpt_count = options.work_begin_checkpoint_count
  87. if options.work_cpus_checkpoint_count != None:
  88. system.work_cpus_ckpt_count = options.work_cpus_checkpoint_count
  89. def findCptDir(options, maxtick, cptdir, testsys):
  90. """Figures out the directory from which the checkpointed state is read.
  91. There are two different ways in which the directories holding checkpoints
  92. can be named --
  93. 1. cpt.<benchmark name>.<instruction count when the checkpoint was taken>
  94. 2. cpt.<some number, usually the tick value when the checkpoint was taken>
  95. This function parses through the options to figure out which one of the
  96. above should be used for selecting the checkpoint, and then figures out
  97. the appropriate directory.
  98. It also sets the value of the maximum tick value till which the simulation
  99. will run.
  100. """
  101. from os.path import isdir, exists
  102. from os import listdir
  103. import re
  104. if not isdir(cptdir):
  105. fatal("checkpoint dir %s does not exist!", cptdir)
  106. if options.at_instruction or options.simpoint:
  107. inst = options.checkpoint_restore
  108. if options.simpoint:
  109. # assume workload 0 has the simpoint
  110. if testsys.cpu[0].workload[0].simpoint == 0:
  111. fatal('Unable to find simpoint')
  112. inst += int(testsys.cpu[0].workload[0].simpoint)
  113. checkpoint_dir = joinpath(cptdir, "cpt.%s.%s" % (options.bench, inst))
  114. if not exists(checkpoint_dir):
  115. fatal("Unable to find checkpoint directory %s", checkpoint_dir)
  116. else:
  117. dirs = listdir(cptdir)
  118. expr = re.compile('cpt\.([0-9]*)')
  119. cpts = []
  120. for dir in dirs:
  121. match = expr.match(dir)
  122. if match:
  123. cpts.append(match.group(1))
  124. cpts.sort(lambda a,b: cmp(long(a), long(b)))
  125. cpt_num = options.checkpoint_restore
  126. if cpt_num > len(cpts):
  127. fatal('Checkpoint %d not found', cpt_num)
  128. maxtick = maxtick - int(cpts[cpt_num - 1])
  129. checkpoint_dir = joinpath(cptdir, "cpt.%s" % cpts[cpt_num - 1])
  130. return maxtick, checkpoint_dir
  131. def scriptCheckpoints(options, maxtick, cptdir):
  132. if options.at_instruction or options.simpoint:
  133. checkpoint_inst = int(options.take_checkpoints)
  134. # maintain correct offset if we restored from some instruction
  135. if options.checkpoint_restore != None:
  136. checkpoint_inst += options.checkpoint_restore
  137. print "Creating checkpoint at inst:%d" % (checkpoint_inst)
  138. exit_event = m5.simulate()
  139. exit_cause = exit_event.getCause()
  140. print "exit cause = %s" % exit_cause
  141. # skip checkpoint instructions should they exist
  142. while exit_cause == "checkpoint":
  143. exit_event = m5.simulate()
  144. exit_cause = exit_event.getCause()
  145. if exit_cause == "a thread reached the max instruction count":
  146. m5.checkpoint(joinpath(cptdir, "cpt.%s.%d" % \
  147. (options.bench, checkpoint_inst)))
  148. print "Checkpoint written."
  149. else:
  150. when, period = options.take_checkpoints.split(",", 1)
  151. when = int(when)
  152. period = int(period)
  153. num_checkpoints = 0
  154. exit_event = m5.simulate(when)
  155. exit_cause = exit_event.getCause()
  156. while exit_cause == "checkpoint":
  157. exit_event = m5.simulate(when - m5.curTick())
  158. exit_cause = exit_event.getCause()
  159. if exit_cause == "simulate() limit reached":
  160. m5.checkpoint(joinpath(cptdir, "cpt.%d"))
  161. num_checkpoints += 1
  162. sim_ticks = when
  163. max_checkpoints = options.max_checkpoints
  164. while num_checkpoints < max_checkpoints and \
  165. exit_cause == "simulate() limit reached":
  166. if (sim_ticks + period) > maxtick:
  167. exit_event = m5.simulate(maxtick - sim_ticks)
  168. exit_cause = exit_event.getCause()
  169. break
  170. else:
  171. exit_event = m5.simulate(period)
  172. exit_cause = exit_event.getCause()
  173. sim_ticks += period
  174. while exit_event.getCause() == "checkpoint":
  175. exit_event = m5.simulate(sim_ticks - m5.curTick())
  176. if exit_event.getCause() == "simulate() limit reached":
  177. m5.checkpoint(joinpath(cptdir, "cpt.%d"))
  178. num_checkpoints += 1
  179. return exit_cause
  180. def benchCheckpoints(options, maxtick, cptdir):
  181. exit_event = m5.simulate(maxtick)
  182. exit_cause = exit_event.getCause()
  183. num_checkpoints = 0
  184. max_checkpoints = options.max_checkpoints
  185. while exit_cause == "checkpoint":
  186. m5.checkpoint(joinpath(cptdir, "cpt.%d"))
  187. num_checkpoints += 1
  188. if num_checkpoints == max_checkpoints:
  189. exit_cause = "maximum %d checkpoints dropped" % max_checkpoints
  190. break
  191. exit_event = m5.simulate(maxtick - m5.curTick())
  192. exit_cause = exit_event.getCause()
  193. return exit_cause
  194. def repeatSwitch(testsys, repeat_switch_cpu_list, maxtick, switch_freq):
  195. print "starting switch loop"
  196. while True:
  197. exit_event = m5.simulate(switch_freq)
  198. exit_cause = exit_event.getCause()
  199. if exit_cause != "simulate() limit reached":
  200. return exit_cause
  201. print "draining the system"
  202. m5.doDrain(testsys)
  203. m5.switchCpus(repeat_switch_cpu_list)
  204. m5.resume(testsys)
  205. tmp_cpu_list = []
  206. for old_cpu, new_cpu in repeat_switch_cpu_list:
  207. tmp_cpu_list.append((new_cpu, old_cpu))
  208. repeat_switch_cpu_list = tmp_cpu_list
  209. if (maxtick - m5.curTick()) <= switch_freq:
  210. exit_event = m5.simulate(maxtick - m5.curTick())
  211. return exit_event.getCause()
  212. def run(options, root, testsys, cpu_class):
  213. if options.maxtick:
  214. maxtick = options.maxtick
  215. elif options.maxtime:
  216. simtime = m5.ticks.seconds(simtime)
  217. print "simulating for: ", simtime
  218. maxtick = simtime
  219. else:
  220. maxtick = m5.MaxTick
  221. if options.checkpoint_dir:
  222. cptdir = options.checkpoint_dir
  223. elif m5.options.outdir:
  224. cptdir = m5.options.outdir
  225. else:
  226. cptdir = getcwd()
  227. if options.fast_forward and options.checkpoint_restore != None:
  228. fatal("Can't specify both --fast-forward and --checkpoint-restore")
  229. if options.standard_switch and not options.caches:
  230. fatal("Must specify --caches when using --standard-switch")
  231. if options.standard_switch and options.repeat_switch:
  232. fatal("Can't specify both --standard-switch and --repeat-switch")
  233. if options.repeat_switch and options.take_checkpoints:
  234. fatal("Can't specify both --repeat-switch and --take-checkpoints")
  235. np = options.num_cpus
  236. switch_cpus = None
  237. if options.prog_interval:
  238. for i in xrange(np):
  239. testsys.cpu[i].progress_interval = options.prog_interval
  240. if options.maxinsts:
  241. for i in xrange(np):
  242. testsys.cpu[i].max_insts_any_thread = options.maxinsts
  243. if cpu_class:
  244. switch_cpus = [cpu_class(defer_registration=True, cpu_id=(i))
  245. for i in xrange(np)]
  246. for i in xrange(np):
  247. if options.fast_forward:
  248. testsys.cpu[i].max_insts_any_thread = int(options.fast_forward)
  249. switch_cpus[i].system = testsys
  250. switch_cpus[i].workload = testsys.cpu[i].workload
  251. switch_cpus[i].clock = testsys.cpu[i].clock
  252. # simulation period
  253. if options.maxinsts:
  254. switch_cpus[i].max_insts_any_thread = options.maxinsts
  255. # Add checker cpu if selected
  256. if options.checker:
  257. switch_cpus[i].addCheckerCpu()
  258. testsys.switch_cpus = switch_cpus
  259. switch_cpu_list = [(testsys.cpu[i], switch_cpus[i]) for i in xrange(np)]
  260. if options.repeat_switch:
  261. if options.cpu_type == "arm_detailed":
  262. if not options.caches:
  263. print "O3 CPU must be used with caches"
  264. sys.exit(1)
  265. repeat_switch_cpus = [O3_ARM_v7a_3(defer_registration=True, \
  266. cpu_id=(i)) for i in xrange(np)]
  267. elif options.cpu_type == "detailed":
  268. if not options.caches:
  269. print "O3 CPU must be used with caches"
  270. sys.exit(1)
  271. repeat_switch_cpus = [DerivO3CPU(defer_registration=True, \
  272. cpu_id=(i)) for i in xrange(np)]
  273. elif options.cpu_type == "inorder":
  274. print "inorder CPU switching not supported"
  275. sys.exit(1)
  276. elif options.cpu_type == "timing":
  277. repeat_switch_cpus = [TimingSimpleCPU(defer_registration=True, \
  278. cpu_id=(i)) for i in xrange(np)]
  279. else:
  280. repeat_switch_cpus = [AtomicSimpleCPU(defer_registration=True, \
  281. cpu_id=(i)) for i in xrange(np)]
  282. for i in xrange(np):
  283. repeat_switch_cpus[i].system = testsys
  284. repeat_switch_cpus[i].workload = testsys.cpu[i].workload
  285. repeat_switch_cpus[i].clock = testsys.cpu[i].clock
  286. if options.maxinsts:
  287. repeat_switch_cpus[i].max_insts_any_thread = options.maxinsts
  288. if options.checker:
  289. repeat_switch_cpus[i].addCheckerCpu()
  290. testsys.repeat_switch_cpus = repeat_switch_cpus
  291. if cpu_class:
  292. repeat_switch_cpu_list = [(switch_cpus[i], repeat_switch_cpus[i])
  293. for i in xrange(np)]
  294. else:
  295. repeat_switch_cpu_list = [(testsys.cpu[i], repeat_switch_cpus[i])
  296. for i in xrange(np)]
  297. if options.standard_switch:
  298. switch_cpus = [TimingSimpleCPU(defer_registration=True, cpu_id=(i))
  299. for i in xrange(np)]
  300. switch_cpus_1 = [DerivO3CPU(defer_registration=True, cpu_id=(i))
  301. for i in xrange(np)]
  302. for i in xrange(np):
  303. switch_cpus[i].system = testsys
  304. switch_cpus_1[i].system = testsys
  305. switch_cpus[i].workload = testsys.cpu[i].workload
  306. switch_cpus_1[i].workload = testsys.cpu[i].workload
  307. switch_cpus[i].clock = testsys.cpu[i].clock
  308. switch_cpus_1[i].clock = testsys.cpu[i].clock
  309. # if restoring, make atomic cpu simulate only a few instructions
  310. if options.checkpoint_restore != None:
  311. testsys.cpu[i].max_insts_any_thread = 1
  312. # Fast forward to specified location if we are not restoring
  313. elif options.fast_forward:
  314. testsys.cpu[i].max_insts_any_thread = int(options.fast_forward)
  315. # Fast forward to a simpoint (warning: time consuming)
  316. elif options.simpoint:
  317. if testsys.cpu[i].workload[0].simpoint == 0:
  318. fatal('simpoint not found')
  319. testsys.cpu[i].max_insts_any_thread = \
  320. testsys.cpu[i].workload[0].simpoint
  321. # No distance specified, just switch
  322. else:
  323. testsys.cpu[i].max_insts_any_thread = 1
  324. # warmup period
  325. if options.warmup_insts:
  326. switch_cpus[i].max_insts_any_thread = options.warmup_insts
  327. # simulation period
  328. if options.maxinsts:
  329. switch_cpus_1[i].max_insts_any_thread = options.maxinsts
  330. # attach the checker cpu if selected
  331. if options.checker:
  332. switch_cpus[i].addCheckerCpu()
  333. switch_cpus_1[i].addCheckerCpu()
  334. testsys.switch_cpus = switch_cpus
  335. testsys.switch_cpus_1 = switch_cpus_1
  336. switch_cpu_list = [(testsys.cpu[i], switch_cpus[i]) for i in xrange(np)]
  337. switch_cpu_list1 = [(switch_cpus[i], switch_cpus_1[i]) for i in xrange(np)]
  338. # set the checkpoint in the cpu before m5.instantiate is called
  339. if options.take_checkpoints != None and \
  340. (options.simpoint or options.at_instruction):
  341. offset = int(options.take_checkpoints)
  342. # Set an instruction break point
  343. if options.simpoint:
  344. for i in xrange(np):
  345. if testsys.cpu[i].workload[0].simpoint == 0:
  346. fatal('no simpoint for testsys.cpu[%d].workload[0]', i)
  347. checkpoint_inst = int(testsys.cpu[i].workload[0].simpoint) + offset
  348. testsys.cpu[i].max_insts_any_thread = checkpoint_inst
  349. # used for output below
  350. options.take_checkpoints = checkpoint_inst
  351. else:
  352. options.take_checkpoints = offset
  353. # Set all test cpus with the right number of instructions
  354. # for the upcoming simulation
  355. for i in xrange(np):
  356. testsys.cpu[i].max_insts_any_thread = offset
  357. checkpoint_dir = None
  358. if options.checkpoint_restore != None:
  359. maxtick, checkpoint_dir = findCptDir(options, maxtick, cptdir, testsys)
  360. m5.instantiate(checkpoint_dir)
  361. if options.standard_switch or cpu_class:
  362. if options.standard_switch:
  363. print "Switch at instruction count:%s" % \
  364. str(testsys.cpu[0].max_insts_any_thread)
  365. exit_event = m5.simulate()
  366. elif cpu_class and options.fast_forward:
  367. print "Switch at instruction count:%s" % \
  368. str(testsys.cpu[0].max_insts_any_thread)
  369. exit_event = m5.simulate()
  370. else:
  371. print "Switch at curTick count:%s" % str(10000)
  372. exit_event = m5.simulate(10000)
  373. print "Switched CPUS @ tick %s" % (m5.curTick())
  374. # when you change to Timing (or Atomic), you halt the system
  375. # given as argument. When you are finished with the system
  376. # changes (including switchCpus), you must resume the system
  377. # manually. You DON'T need to resume after just switching
  378. # CPUs if you haven't changed anything on the system level.
  379. m5.doDrain(testsys)
  380. m5.changeToTiming(testsys)
  381. m5.switchCpus(switch_cpu_list)
  382. m5.resume(testsys)
  383. if options.standard_switch:
  384. print "Switch at instruction count:%d" % \
  385. (testsys.switch_cpus[0].max_insts_any_thread)
  386. #warmup instruction count may have already been set
  387. if options.warmup_insts:
  388. exit_event = m5.simulate()
  389. else:
  390. exit_event = m5.simulate(options.standard_switch)
  391. print "Switching CPUS @ tick %s" % (m5.curTick())
  392. print "Simulation ends instruction count:%d" % \
  393. (testsys.switch_cpus_1[0].max_insts_any_thread)
  394. m5.doDrain(testsys)
  395. m5.switchCpus(switch_cpu_list1)
  396. m5.resume(testsys)
  397. # If we're taking and restoring checkpoints, use checkpoint_dir
  398. # option only for finding the checkpoints to restore from. This
  399. # lets us test checkpointing by restoring from one set of
  400. # checkpoints, generating a second set, and then comparing them.
  401. if options.take_checkpoints and options.checkpoint_restore:
  402. if m5.options.outdir:
  403. cptdir = m5.options.outdir
  404. else:
  405. cptdir = getcwd()
  406. if options.take_checkpoints != None :
  407. # Checkpoints being taken via the command line at <when> and at
  408. # subsequent periods of <period>. Checkpoint instructions
  409. # received from the benchmark running are ignored and skipped in
  410. # favor of command line checkpoint instructions.
  411. exit_cause = scriptCheckpoints(options, maxtick, cptdir)
  412. else:
  413. if options.fast_forward:
  414. m5.stats.reset()
  415. print "**** REAL SIMULATION ****"
  416. # If checkpoints are being taken, then the checkpoint instruction
  417. # will occur in the benchmark code it self.
  418. if options.repeat_switch and maxtick > options.repeat_switch:
  419. exit_cause = repeatSwitch(testsys, repeat_switch_cpu_list,
  420. maxtick, options.repeat_switch)
  421. else:
  422. exit_cause = benchCheckpoints(options, maxtick, cptdir)
  423. print 'Exiting @ tick %i because %s' % (m5.curTick(), exit_cause)
  424. if options.checkpoint_at_end:
  425. m5.checkpoint(joinpath(cptdir, "cpt.%d"))