sim: make Python Root object a singleton
Enforce that the Python Root SimObject is instantiated only once. The C++ Root object already panics if more than one is created. This change avoids the need to track what the root object is, since it's available from Root.getInstance() (if it exists). It's now redundant to have the user pass the root object to functions like instantiate(), checkpoint(), and restoreCheckpoint(), so that arg is gone. Users who use configs/common/Simulate.py should not notice.
This commit is contained in:
parent
0f8b5afd7a
commit
1fbe466345
10 changed files with 53 additions and 20 deletions
|
@ -190,7 +190,7 @@ def run(options, root, testsys, cpu_class):
|
|||
for i in xrange(np):
|
||||
testsys.cpu[i].max_insts_any_thread = offset
|
||||
|
||||
m5.instantiate(root)
|
||||
m5.instantiate()
|
||||
|
||||
if options.checkpoint_restore != None:
|
||||
from os.path import isdir, exists
|
||||
|
@ -207,7 +207,7 @@ def run(options, root, testsys, cpu_class):
|
|||
fatal("Unable to find checkpoint directory %s", checkpoint_dir)
|
||||
|
||||
print "Restoring checkpoint ..."
|
||||
m5.restoreCheckpoint(root, checkpoint_dir)
|
||||
m5.restoreCheckpoint(checkpoint_dir)
|
||||
print "Done."
|
||||
elif options.simpoint:
|
||||
# assume workload 0 has the simpoint
|
||||
|
@ -224,7 +224,7 @@ def run(options, root, testsys, cpu_class):
|
|||
options.bench, options.checkpoint_restore)
|
||||
|
||||
print "Restoring checkpoint ..."
|
||||
m5.restoreCheckpoint(root,checkpoint_dir)
|
||||
m5.restoreCheckpoint(checkpoint_dir)
|
||||
print "Done."
|
||||
else:
|
||||
dirs = listdir(cptdir)
|
||||
|
@ -246,8 +246,8 @@ def run(options, root, testsys, cpu_class):
|
|||
maxtick = maxtick - int(cpts[cpt_num - 1])
|
||||
|
||||
## Restore the checkpoint
|
||||
m5.restoreCheckpoint(root,
|
||||
joinpath(cptdir, "cpt.%s" % cpts[cpt_num - 1]))
|
||||
m5.restoreCheckpoint(joinpath(cptdir,
|
||||
"cpt.%s" % cpts[cpt_num - 1]))
|
||||
|
||||
if options.standard_switch or cpu_class:
|
||||
if options.standard_switch:
|
||||
|
@ -324,7 +324,7 @@ def run(options, root, testsys, cpu_class):
|
|||
|
||||
if exit_event.getCause() == \
|
||||
"a thread reached the max instruction count":
|
||||
m5.checkpoint(root, joinpath(cptdir, "cpt.%s.%d" % \
|
||||
m5.checkpoint(joinpath(cptdir, "cpt.%s.%d" % \
|
||||
(options.bench, checkpoint_inst)))
|
||||
print "Checkpoint written."
|
||||
num_checkpoints += 1
|
||||
|
@ -341,7 +341,7 @@ def run(options, root, testsys, cpu_class):
|
|||
exit_event = m5.simulate(when - m5.curTick())
|
||||
|
||||
if exit_event.getCause() == "simulate() limit reached":
|
||||
m5.checkpoint(root, joinpath(cptdir, "cpt.%d"))
|
||||
m5.checkpoint(joinpath(cptdir, "cpt.%d"))
|
||||
num_checkpoints += 1
|
||||
|
||||
sim_ticks = when
|
||||
|
@ -358,7 +358,7 @@ def run(options, root, testsys, cpu_class):
|
|||
while exit_event.getCause() == "checkpoint":
|
||||
exit_event = m5.simulate(sim_ticks - m5.curTick())
|
||||
if exit_event.getCause() == "simulate() limit reached":
|
||||
m5.checkpoint(root, joinpath(cptdir, "cpt.%d"))
|
||||
m5.checkpoint(joinpath(cptdir, "cpt.%d"))
|
||||
num_checkpoints += 1
|
||||
|
||||
if exit_event.getCause() != "simulate() limit reached":
|
||||
|
@ -371,7 +371,7 @@ def run(options, root, testsys, cpu_class):
|
|||
exit_event = m5.simulate(maxtick)
|
||||
|
||||
while exit_event.getCause() == "checkpoint":
|
||||
m5.checkpoint(root, joinpath(cptdir, "cpt.%d"))
|
||||
m5.checkpoint(joinpath(cptdir, "cpt.%d"))
|
||||
num_checkpoints += 1
|
||||
if num_checkpoints == max_checkpoints:
|
||||
exit_cause = "maximum %d checkpoints dropped" % max_checkpoints
|
||||
|
@ -385,5 +385,5 @@ def run(options, root, testsys, cpu_class):
|
|||
print 'Exiting @ cycle %i because %s' % (m5.curTick(), exit_cause)
|
||||
|
||||
if options.checkpoint_at_end:
|
||||
m5.checkpoint(root, joinpath(cptdir, "cpt.%d"))
|
||||
m5.checkpoint(joinpath(cptdir, "cpt.%d"))
|
||||
|
||||
|
|
|
@ -129,7 +129,7 @@ else:
|
|||
m5.ticks.setGlobalFrequency('1ns')
|
||||
|
||||
# instantiate configuration
|
||||
m5.instantiate(root)
|
||||
m5.instantiate()
|
||||
|
||||
# simulate until program terminates
|
||||
exit_event = m5.simulate(options.maxtick)
|
||||
|
|
|
@ -181,7 +181,7 @@ else:
|
|||
m5.ticks.setGlobalFrequency('1ns')
|
||||
|
||||
# instantiate configuration
|
||||
m5.instantiate(root)
|
||||
m5.instantiate()
|
||||
|
||||
# simulate until program terminates
|
||||
exit_event = m5.simulate(options.maxtick)
|
||||
|
|
|
@ -118,7 +118,7 @@ root.system.mem_mode = 'timing'
|
|||
m5.ticks.setGlobalFrequency('1ns')
|
||||
|
||||
# instantiate configuration
|
||||
m5.instantiate(root)
|
||||
m5.instantiate()
|
||||
|
||||
# simulate until program terminates
|
||||
exit_event = m5.simulate(options.maxtick)
|
||||
|
|
|
@ -292,7 +292,7 @@ if options.timing or options.detailed:
|
|||
root.system.mem_mode = 'timing'
|
||||
|
||||
# instantiate configuration
|
||||
m5.instantiate(root)
|
||||
m5.instantiate()
|
||||
|
||||
# simulate until program terminates
|
||||
if options.maxtick:
|
||||
|
|
|
@ -276,7 +276,7 @@ if options.timing or options.detailed:
|
|||
root.system.mem_mode = 'timing'
|
||||
|
||||
# instantiate configuration
|
||||
m5.instantiate(root)
|
||||
m5.instantiate()
|
||||
|
||||
# simulate until program terminates
|
||||
if options.maxtick:
|
||||
|
|
|
@ -623,7 +623,7 @@ class SimObject(object):
|
|||
|
||||
def path(self):
|
||||
if not self._parent:
|
||||
return 'root'
|
||||
return '(orphan)'
|
||||
ppath = self._parent.path()
|
||||
if ppath == 'root':
|
||||
return self._name
|
||||
|
|
|
@ -39,13 +39,19 @@ from main import options
|
|||
import SimObject
|
||||
import ticks
|
||||
import objects
|
||||
from util import fatal
|
||||
|
||||
# define a MaxTick parameter
|
||||
MaxTick = 2**63 - 1
|
||||
|
||||
# The final hook to generate .ini files. Called from the user script
|
||||
# once the config is built.
|
||||
def instantiate(root):
|
||||
def instantiate():
|
||||
root = objects.Root.getInstance()
|
||||
|
||||
if not root:
|
||||
fatal("Need to instantiate Root() before calling instantiate()")
|
||||
|
||||
# we need to fix the global frequency
|
||||
ticks.fixGlobalFrequency()
|
||||
|
||||
|
@ -136,7 +142,8 @@ def drain(root):
|
|||
def resume(root):
|
||||
root.resume()
|
||||
|
||||
def checkpoint(root, dir):
|
||||
def checkpoint(dir):
|
||||
root = objects.Root.getInstance()
|
||||
if not isinstance(root, objects.Root):
|
||||
raise TypeError, "Checkpoint must be called on a root object."
|
||||
doDrain(root)
|
||||
|
@ -144,7 +151,8 @@ def checkpoint(root, dir):
|
|||
internal.core.serializeAll(dir)
|
||||
resume(root)
|
||||
|
||||
def restoreCheckpoint(root, dir):
|
||||
def restoreCheckpoint(dir):
|
||||
root = objects.Root.getInstance()
|
||||
print "Restoring from checkpoint"
|
||||
internal.core.unserializeAll(dir)
|
||||
need_resume.append(root)
|
||||
|
|
|
@ -28,7 +28,32 @@
|
|||
|
||||
from m5.SimObject import SimObject
|
||||
from m5.params import *
|
||||
from m5.util import fatal
|
||||
|
||||
class Root(SimObject):
|
||||
|
||||
_the_instance = None
|
||||
|
||||
def __new__(cls, **kwargs):
|
||||
if Root._the_instance:
|
||||
fatal("Attempt to allocate multiple instances of Root.")
|
||||
return None
|
||||
|
||||
# first call: allocate the unique instance
|
||||
#
|
||||
# If SimObject ever implements __new__, we may want to pass
|
||||
# kwargs here, but for now this goes straight to
|
||||
# object.__new__ which prints an ugly warning if you pass it
|
||||
# args. Seems like a bad design but that's the way it is.
|
||||
Root._the_instance = SimObject.__new__(cls)
|
||||
return Root._the_instance
|
||||
|
||||
@classmethod
|
||||
def getInstance(cls):
|
||||
return Root._the_instance
|
||||
|
||||
def path(self):
|
||||
return 'root'
|
||||
|
||||
type = 'Root'
|
||||
dummy = Param.Int(0, "We don't support objects without params")
|
||||
|
|
|
@ -78,7 +78,7 @@ sys.path.append(joinpath(tests_root, category, name))
|
|||
execfile(joinpath(tests_root, category, name, 'test.py'))
|
||||
|
||||
# instantiate configuration
|
||||
m5.instantiate(root)
|
||||
m5.instantiate()
|
||||
|
||||
# simulate until program terminates
|
||||
exit_event = m5.simulate(maxtick)
|
||||
|
|
Loading…
Reference in a new issue